diff --git a/AUTHORS b/AUTHORS
index 8aede9c..8336c63 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1098,8 +1098,7 @@
 Simon La Macchia <smacchia@amazon.com>
 Siva Kumar Gunturi <siva.gunturi@samsung.com>
 Slava Aseev <nullptrnine@gmail.com>
-Sohan Jyoti Ghosh <sohan.jyoti@huawei.com>
-Sohan Jyoti Ghosh <sohan.jyoti@samsung.com>
+Sohan Jyoti Ghosh <sohanjg@chromium.org>
 Sohom Datta <sohom.datta@learner.manipal.edu>
 Sohom Datta <dattasohom1@gmail.com>
 Song Fangzhen <songfangzhen@bytedance.com>
diff --git a/DEPS b/DEPS
index 4b3f592..124194e 100644
--- a/DEPS
+++ b/DEPS
@@ -275,11 +275,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '162dfca3403b21575212f2b75e6627fa88ae6160',
+  'skia_revision': '20a2f7b4d443f1a38a14e484617c5356d5fcd047',
   # 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': '9941bdcba032566bdf440513cba4a1d5066bdbeb',
+  'v8_revision': '54939cdc830d2fff9fd8588c27723212bfa500ef',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
@@ -291,7 +291,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'bf9eee17581fa62ce40fd6f3911c0dd88e196d1c',
+  'pdfium_revision': 'c85f8943e9cccbfbd7ee0661c112ee9b5ba94d1b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -302,7 +302,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
-  'fuchsia_version': 'version:8.20220527.2.1',
+  'fuchsia_version': 'version:8.20220528.1.1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -354,7 +354,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': '50a0b94bcb16130284a3a954757646cc8b7f950f',
+  'devtools_frontend_revision': '8a28dfec425e431c831ee0497eec7e6b6c560500',
   # 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.
@@ -390,7 +390,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': '2cefd07454df24d6dc71f9e986d86b64228913ee',
+  'dawn_revision': 'b8ac93390909e0a87a838b71f431f01c66191292',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -747,7 +747,7 @@
     Var('chromium_git') + '/external/github.com/toji/webvr.info.git' + '@' + 'c58ae99b9ff9e2aa4c524633519570bf33536248',
 
   'src/docs/website': {
-    'url': Var('chromium_git') + '/website.git' + '@' + 'b9ea7d6b756e7e7d3a8bb7accece4a7f150687c6',
+    'url': Var('chromium_git') + '/website.git' + '@' + '0df96724d5586995354039ff746b43b5bfe9cdcd',
   },
 
   'src/ios/third_party/earl_grey2/src': {
@@ -863,7 +863,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/windows-amd64',
-          'version': 'gzTf5qwKwwtjRp7sR_EpyMufpNT8ib8bFMiVBHvidZ8C',
+          'version': 'oHo3sxxUvWy9nko65nfOGtF639JCF8dFu-O6cpkmjLUC',
         },
       ],
       'dep_type': 'cipd',
@@ -920,7 +920,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'fG_1zE_32JdLLyVDr2e60nsfHYDu7bylpMV_MZtZxvMC',
+          'version': '_3gaSYtb8HQIr0ti1OnRCzzfyUDoYIHd9U7cGQk9Q5EC',
       },
     ],
     'condition': 'checkout_android',
@@ -1533,7 +1533,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '26f1ca3b42a13a5dc179334f972ad8847aded023',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '6214d0c954d720a3c87cf7673903d679d2ae7413',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1669,7 +1669,7 @@
       'condition': 'checkout_android',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@2f94e7e4c5bbf83e526fbab8af36bd43c4dba896',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@59aa5963cf6476846f7537136b7dac4fdeec98ff',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907',
@@ -1708,7 +1708,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '70091fdb8d3d037b8f2919eb63e5a2bf6444deb7',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'a93260b2f418f00cc93b10ae8470a7ff08b31f3d',
+    Var('webrtc_git') + '/src.git' + '@' + 'e0ad779aaa97bda74c4edd3c84c4fc872b9b8b10',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1781,7 +1781,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@ab8cc2ad9ed1c2e6573970ea6e00893c6885622d',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b6c8bb85d2b0bc2710f5715e19ebe3c29936609b',
     'condition': 'checkout_src_internal',
   },
 
@@ -1833,7 +1833,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': 'wia4LIvBXYtmD32chYy-LGLF9GHp0DqDa3DDXm_b7EsC',
+        'version': 'GYuCX6QFNlK9d1YCFyf2SMAKXA874T5KYJDiixmka7sC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
index ec550f91..86a0bb6 100644
--- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
+++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -337,6 +337,9 @@
             Flag.baseFeature(BlinkFeatures.EVENT_PATH, "Enables the deprecated Event.path API."),
             Flag.baseFeature(BlinkFeatures.PREFETCH_FONT_LOOKUP_TABLES,
                     "If enabled, font lookup tables will be prefetched on renderer startup."),
+            Flag.baseFeature(BlinkFeatures.PRECOMPILE_INLINE_SCRIPTS,
+                    "If enabled, inline scripts will be stream compiled using a background HTML"
+                            + " scanner."),
             // Add new commandline switches and features above. The final entry should have a
             // trailing comma for cleaner diffs.
     };
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index 97e09b88..958abc1 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -4772,7 +4772,7 @@
         Opened yesterday
       </message>
       <message name="IDS_APP_LIST_OPEN_TAB_HINT" desc="Shown alongside launcher search results which will take the user to an open tab when clicked.">
-        Go to this tab
+        <ph name="delimiter">$1<ex> - </ex></ph> Go to this tab
       </message>
       <message name="IDS_APP_LIST_SEARCH_GAME_PLATFORMS_PREFIX" desc="Shown next to a video game search result, begins a list of cloud gaming platforms the game is playable on.">
         on
diff --git a/ash/ash_strings_grd/IDS_APP_LIST_OPEN_TAB_HINT.png.sha1 b/ash/ash_strings_grd/IDS_APP_LIST_OPEN_TAB_HINT.png.sha1
index f05f7e0..ad86098 100644
--- a/ash/ash_strings_grd/IDS_APP_LIST_OPEN_TAB_HINT.png.sha1
+++ b/ash/ash_strings_grd/IDS_APP_LIST_OPEN_TAB_HINT.png.sha1
@@ -1 +1 @@
-01c6ebfd07de5c34e9ff559823396ef011e8b777
\ No newline at end of file
+35b10699f3dfd788c8669c4596d5c2f43207d02d
\ No newline at end of file
diff --git a/ash/components/arc/BUILD.gn b/ash/components/arc/BUILD.gn
index 6b43151f..238cc18 100644
--- a/ash/components/arc/BUILD.gn
+++ b/ash/components/arc/BUILD.gn
@@ -129,6 +129,7 @@
     "//chromeos/ash/components/dbus/concierge:concierge_proto",
     "//chromeos/ash/components/dbus/patchpanel",
     "//chromeos/ash/components/dbus/patchpanel:patchpanel_proto",
+    "//chromeos/ash/components/dbus/spaced:spaced",
     "//chromeos/components/disks:prefs",
     "//chromeos/components/sensors:sensors",
     "//chromeos/dbus",
diff --git a/ash/components/arc/disk_quota/arc_disk_quota_bridge.cc b/ash/components/arc/disk_quota/arc_disk_quota_bridge.cc
index 65191897..59e755f 100644
--- a/ash/components/arc/disk_quota/arc_disk_quota_bridge.cc
+++ b/ash/components/arc/disk_quota/arc_disk_quota_bridge.cc
@@ -11,8 +11,8 @@
 #include "ash/components/cryptohome/cryptohome_parameters.h"
 #include "base/bind.h"
 #include "base/memory/singleton.h"
+#include "chromeos/ash/components/dbus/spaced/spaced_client.h"
 #include "chromeos/dbus/userdataauth/arc_quota_client.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace arc {
 
@@ -234,4 +234,23 @@
           std::move(callback), project_id, parent_path, child_path.value()));
 }
 
+void ArcDiskQuotaBridge::GetFreeDiskSpace(GetFreeDiskSpaceCallback callback) {
+  ash::SpacedClient::Get()->GetFreeDiskSpace(
+      "/home", base::BindOnce(&ArcDiskQuotaBridge::OnGetFreeDiskSpace,
+                              weak_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void ArcDiskQuotaBridge::OnGetFreeDiskSpace(GetFreeDiskSpaceCallback callback,
+                                            absl::optional<int64_t> reply) {
+  if (!reply.has_value()) {
+    LOG(ERROR) << "spaced::GetFreeDiskSpace failed";
+    std::move(callback).Run(nullptr);
+    return;
+  }
+
+  mojom::DiskSpacePtr disk_space = mojom::DiskSpace::New();
+  disk_space->space_in_bytes = reply.value();
+  std::move(callback).Run(std::move(disk_space));
+}
+
 }  // namespace arc
diff --git a/ash/components/arc/disk_quota/arc_disk_quota_bridge.h b/ash/components/arc/disk_quota/arc_disk_quota_bridge.h
index cff9060..4e658f7 100644
--- a/ash/components/arc/disk_quota/arc_disk_quota_bridge.h
+++ b/ash/components/arc/disk_quota/arc_disk_quota_bridge.h
@@ -7,9 +7,11 @@
 
 #include "ash/components/arc/mojom/disk_quota.mojom.h"
 #include "base/files/file_path.h"
+#include "base/memory/weak_ptr.h"
 #include "chromeos/dbus/cryptohome/UserDataAuth.pb.h"
 #include "components/account_id/account_id.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/cros_system_api/dbus/cryptohome/dbus-constants.h"
 
 namespace content {
@@ -64,10 +66,18 @@
                     const std::string& android_path,
                     SetProjectIdCallback callback) override;
 
+  void GetFreeDiskSpace(GetFreeDiskSpaceCallback) override;
+
  private:
+  void OnGetFreeDiskSpace(GetFreeDiskSpaceCallback callback,
+                          absl::optional<int64_t> reply);
+
   ArcBridgeService* const arc_bridge_service_;  // Owned by ArcServiceManager.
 
   AccountId account_id_;
+
+  // WeakPtrFactory to use for callbacks.
+  base::WeakPtrFactory<ArcDiskQuotaBridge> weak_factory_{this};
 };
 
 }  // namespace arc
diff --git a/ash/components/arc/mojom/disk_quota.mojom b/ash/components/arc/mojom/disk_quota.mojom
index 4f73906..4d0c67c0 100644
--- a/ash/components/arc/mojom/disk_quota.mojom
+++ b/ash/components/arc/mojom/disk_quota.mojom
@@ -2,11 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Next MinVersion: 2
+// Next MinVersion: 3
 
 module arc.mojom;
 
-// Next Method ID: 3
+struct DiskSpace {
+  uint64 space_in_bytes;
+};
+
+// Next Method ID: 6
 interface DiskQuotaHost {
   // Whether cryptohome supports quota-based stats.
   IsQuotaSupported@0() => (bool supported);
@@ -26,10 +30,13 @@
   // corresponding path in Chrome OS file system.
   [MinVersion=1] SetProjectId@4(uint32 project_id, string android_file_path) =>
       (bool success);
+
+  // Get free disk space in the stateful partition.
+  [MinVersion=2] GetFreeDiskSpace@5() => (DiskSpace? free_space);
 };
 
 // Next Method ID: 1
 interface DiskQuotaInstance {
   // Establishes full-duplex communication with the host.
   Init@0(pending_remote<DiskQuotaHost> host_remote) => ();
-};
\ No newline at end of file
+};
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 30d5e7cf..c5bb0aa 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -1136,7 +1136,7 @@
 // Provides a UI for users to customize their wallpapers, screensaver and
 // avatars.
 const base::Feature kPersonalizationHub{"PersonalizationHub",
-                                        base::FEATURE_DISABLED_BY_DEFAULT};
+                                        base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Provides a UI for users to view information about their Android phone
 // and perform phone-side actions within ChromeOS.
diff --git a/ash/strings/ash_strings_am.xtb b/ash/strings/ash_strings_am.xtb
index 96f6e702..6c536f9 100644
--- a/ash/strings/ash_strings_am.xtb
+++ b/ash/strings/ash_strings_am.xtb
@@ -1057,6 +1057,7 @@
 <translation id="7348093485538360975">የታይታ የቁልፍ ሰሌዳ</translation>
 <translation id="735745346212279324">የቪ ፒ ኤን ግንኙነት ተቋርጧል</translation>
 <translation id="7360036564632145207">ለተቀጥላ ክፍሎች ቅንብሮች የውሂብ መዳረሻ ጥበቃን መለወጥ አፈጻጸሙን ሊያተባ ይችላል</translation>
+<translation id="736045644501761622">ልጣፍ እና ቅጥ አቀናብር</translation>
 <translation id="7371404428569700291">መስኮትን ቅዳ</translation>
 <translation id="7377169924702866686">Caps Lock በርቷል።</translation>
 <translation id="7377481913241237033">ከኮድ ጋር ተገናኝ</translation>
@@ -1291,6 +1292,7 @@
 <translation id="8721053961083920564">ድምፅን ቀያይር። <ph name="STATE_TEXT" /></translation>
 <translation id="8724318433625452070">ሙሉ የማያ ገጽ ቀረጻ</translation>
 <translation id="8734991477317290293">የእርስዎን የቁልፍ ጭረቶች ለመስረቅ እየሞከረ ሊሆን ይችላል</translation>
+<translation id="8735678380411481005">የቁልፍ ሰሌዳ የጀርባ ብርሃን ቀለም</translation>
 <translation id="8735953464173050365">የቁልፍ ሰሌዳ ቅንብሮችን አሳይ። <ph name="KEYBOARD_NAME" /> ተመርጧል</translation>
 <translation id="8755498163081687682">የእርስዎን ማንነት ያረጋግጡ፦ <ph name="ORIGIN_NAME" /> እርስዎ መሆንዎን ማረጋገጥ ይፈልጋል</translation>
 <translation id="875593634123171288">የቪፒኤን ቅንብሮችን አሳይ</translation>
diff --git a/ash/strings/ash_strings_bn.xtb b/ash/strings/ash_strings_bn.xtb
index 7e1d5181..ca5f0aad 100644
--- a/ash/strings/ash_strings_bn.xtb
+++ b/ash/strings/ash_strings_bn.xtb
@@ -252,6 +252,7 @@
 <translation id="243878895369688216">গতকাল খোলা হয়েছে</translation>
 <translation id="2441427462554639370">ডিস্কে স্টোরেজের জায়গা খুবই কম থাকায় রেকর্ডিং বন্ধ হয়ে গেছে</translation>
 <translation id="24452542372838207">বিজ্ঞপ্তি প্রসারিত করুন</translation>
+<translation id="2449089818483227734">ব্যাটারিতে চার্জ কম আছে</translation>
 <translation id="2450205753526923158">স্ক্রিনশট মোড</translation>
 <translation id="2456008742792828469">ক্যালেন্ডার, <ph name="CURRENT_MONTH_YEAR" /></translation>
 <translation id="2473177541599297363">রেজোলিউশন কনফার্ম করুন</translation>
@@ -412,11 +413,13 @@
 <translation id="3441920967307853524"><ph name="RECEIVED_BYTES" />/<ph name="TOTAL_BYTES" /></translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> মিনিট</translation>
 <translation id="3445925074670675829">USB-C ডিভাইস</translation>
+<translation id="3455468639467374593">টেমপ্লেট, <ph name="TEMPLATE_NAME" /></translation>
 <translation id="3465223694362104965">আপনি শেষবার সাইন-ইন করার পরে আরেকটি কীবোর্ড এই ডিভাইসে কানেক্ট করা হয়েছে। এটি ব্যবহার করার আগে কীবোর্ডটিকে আপনি নিরাপদ বলে মনে করেন কিনা তা দেখে নিন।</translation>
 <translation id="3465356146291925647">আপনার অ্যাডমিনিস্ট্রেটর ম্যানেজ করে</translation>
 <translation id="3477079411857374384">Control-Shift-Space</translation>
 <translation id="3485319357743610354"><ph name="SECURITY_STATUS" />, <ph name="CONNECTION_STATUS" />, সিগন্যাল: <ph name="SIGNAL_STRENGTH" /></translation>
 <translation id="348799646910989694">শেল্ফ অটোমেটিক লুকানো হবে</translation>
+<translation id="3505066820268455558">ব্যাটারি চার্জ হচ্ছে</translation>
 <translation id="3509391053705095206">আপনার ফোন খুঁজে পাওয়া যায়নি। আপনার ফোনের ব্লুটুথ চালু আছে কিনা তা ভালভাবে দেখে নিন।</translation>
 <translation id="3510164367642747937">মাউস কার্সার হাইলাইট করুন</translation>
 <translation id="3513798432020909783">অ্যাকাউন্টটি <ph name="MANAGER_EMAIL" /> ম্যানেজ করছেন</translation>
@@ -457,6 +460,8 @@
 <translation id="3633097874324966332">আপনার ডিভাইস পেয়ার করতে ব্লুটুথ সেটিংস খুলুন</translation>
 <translation id="3638400994746983214">গোপনীয়তা স্ক্রিন টগল করুন। <ph name="STATE_TEXT" />।</translation>
 <translation id="3649505501900178324">আপডেট করতে ডিভাইস রিস্টার্ট করুন</translation>
+<translation id="3659814201068740063">আর <ph name="TIME_LEFT" /> চলবে (<ph name="PERCENTAGE" />%)।
+ডিভাইসটি চার্জে বসান।</translation>
 <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> ম্যানেজ করা ব্যবহারকারী</translation>
 <translation id="36813544980941320">ফোন ও <ph name="DEVICE_NAME" />-এর মধ্যে ওয়াই-ফাই নেটওয়ার্ক শেয়ার করা হবে।</translation>
 <translation id="3694122362646626770">ওয়েবসাইটগুলি</translation>
@@ -511,6 +516,7 @@
 <translation id="3962859241508114581">আগের ট্র্যাক চালান</translation>
 <translation id="3969043077941541451">বন্ধ আছে</translation>
 <translation id="397105322502079400">গণনা করা হচ্ছে...</translation>
+<translation id="397726367135689299">ব্যাটারি চার্জ করার জায়গাটি নির্ভরযোগ্য নাও হতে পারে।</translation>
 <translation id="3977512764614765090">ব্যাটারি <ph name="PERCENTAGE" /> শতাংশ চার্জ করা হয়েছে এবং এখনও চার্জ করা চলছে।</translation>
 <translation id="3986082989454912832">উত্তর</translation>
 <translation id="3995138139523574647">USB-C ডিভাইস (ডান দিকের পিছনের পোর্ট)</translation>
@@ -698,6 +704,7 @@
 <translation id="5071064518267176975">অ্যাপ মাইক্রোফোন ব্যবহার করতে চায়</translation>
 <translation id="5078796286268621944">ভুল পিন</translation>
 <translation id="5083553833479578423">অ্যাসিস্ট্যান্ট-এর আরও বৈশিষ্ট্য আনলক করুন।</translation>
+<translation id="509790653408515442">আপনি ফোনের অ্যাপ স্ট্রিম করলে, সেগুলি এখানে দেখা যাবে</translation>
 <translation id="5107522548814527560">ওয়েব</translation>
 <translation id="5117590920725113268">পরবর্তী মাস দেখান</translation>
 <translation id="5136175204352732067">বিভিন্ন কীবোর্ড কানেক্ট করা হয়েছে</translation>
@@ -720,6 +727,7 @@
 <translation id="523505283826916779">অ্যাক্সেসিবিলিটি সেটিংস</translation>
 <translation id="5245201184978705914">ট্রান্সক্রিপ্ট তৈরি করা যাচ্ছে না</translation>
 <translation id="5253783950165989294"><ph name="DEVICE_NAME" /> নামের ডিভাইসে কানেক্ট করা হয়েছে, ব্যাটারি চার্জ <ph name="BATTERY_PERCENTAGE" />%</translation>
+<translation id="5258528442992323769">সেভ করা কোনও ডেস্ক নেই</translation>
 <translation id="5260676007519551770">ডেস্ক ৪</translation>
 <translation id="5283099933536931082"><ph name="APP_ITEM_TITLE" /> আপনার মনোযোগ আকর্ষণ করতে চাইছে।</translation>
 <translation id="5283198616748585639">১ মিনিট যোগ করুন</translation>
@@ -1036,6 +1044,7 @@
 <translation id="7130207228079676353">সবথেকে বেশি সম্ভাবনা</translation>
 <translation id="7131634465328662194">আপনি নিজে থেকেই সাইন-আউট হয়ে যাবেন।</translation>
 <translation id="7143207342074048698">সংযুক্ত হচ্ছে</translation>
+<translation id="7144942256906679589">ব্যাটারির স্ট্যাটাস</translation>
 <translation id="7165278925115064263">Alt+Shift+K</translation>
 <translation id="7168224885072002358"><ph name="TIMEOUT_SECONDS" /> -এ পুরনো রেজোলিউশানে ফেরানো হচ্ছে</translation>
 <translation id="7180611975245234373">রিফ্রেশ করুন</translation>
@@ -1102,6 +1111,7 @@
 <translation id="7593891976182323525">Search অথবা Shift</translation>
 <translation id="7600875258240007829">সব বিজ্ঞপ্তি দেখুন</translation>
 <translation id="7607002721634913082">বিরত রয়েছে</translation>
+<translation id="7609951632080598826">ক্যালেন্ডার ভিউ, <ph name="DATE" />, <ph name="TIME" /></translation>
 <translation id="7611213136657090146">ক্যামেরা আবার কানেক্ট করা হয়েছে।</translation>
 <translation id="7624117708979618027"><ph name="TEMPERATURE_F" />° ফারেনহাইট</translation>
 <translation id="7633755430369750696">'নিয়ারবাই শেয়ার' সেটিংস দেখুন।</translation>
@@ -1227,6 +1237,7 @@
 <translation id="8345019317483336363"><ph name="WINDOW_TITLE" />টি উইন্ডো বেছে নেওয়া হয়েছে</translation>
 <translation id="8351131234907093545">নোট তৈরি করুন</translation>
 <translation id="8364673525741149932">শেল্ফ পার্টি টগল করুন। <ph name="STATE_TEXT" /></translation>
+<translation id="8369166482916924789">সেভ করা ডেস্ক, <ph name="SAVE_AND_RECALL_DESK_NAME" /></translation>
 <translation id="8371779926711439835">অক্ষর অনুযায়ী এগিয়ে যান</translation>
 <translation id="8371991222807690464">কেবলমাত্র 'গেস্ট' মোডেই পেরিফেরাল পারফর্ম্যান্স সীমাবদ্ধ থাকতে পারে</translation>
 <translation id="8374601332003098278">আংশিক স্ক্রিন রেকর্ড করার জন্য Enter প্রেস করুন</translation>
@@ -1260,6 +1271,7 @@
 <translation id="851458219935658693">বর্তমান ডেস্ক থেকে উইন্ডো দেখুন, রেডিও বোতাম বেছে নেওয়া হয়েছে</translation>
 <translation id="8517041960877371778">আপনার <ph name="DEVICE_TYPE" /> চালু থাকা অবস্থায় চার্জ নাও হতে পারে।</translation>
 <translation id="8535393432370007982">রঙ অনুযায়ী বেছে নেওয়ার সেটিং থেকে বেরিয়ে আগের অবস্থায় ফেরানো হয়েছে</translation>
+<translation id="8542053257095774575">সেভ করা কোনও ডেস্ক বা টেমপ্লেট নেই</translation>
 <translation id="8546059259582788728">বেছে নেওয়ার সেটিং থেকে বেরিয়ে আগের অবস্থায় ফেরানো হয়েছে</translation>
 <translation id="8551588720239073785">তারিখ ও সময়ের সেটিংস</translation>
 <translation id="8553395910833293175">সব ডেস্কে আগেই অ্যাসাইন করা হয়েছে।</translation>
@@ -1338,6 +1350,7 @@
 <translation id="9000771174482730261">স্টোরেজ ম্যানেজ করুন</translation>
 <translation id="9017320285115481645">Family Link-এর অভিভাবকীয় অ্যাক্সেস কোডটি লিখুন।</translation>
 <translation id="9024331582947483881">পূর্ণ স্ক্রিন</translation>
+<translation id="9029736946581028033">শীঘ্রই ডিভাইসের চার্জ শেষ হয়ে যাবে</translation>
 <translation id="9030319654231318877">সূর্যাস্ত পর্যন্ত বন্ধ আছে</translation>
 <translation id="9034924485347205037">Linux ফাইল</translation>
 <translation id="9047624247355796468"><ph name="NETWORK_NAME" /> নেটওয়ার্কের জন্য সেটিংস খুলুন</translation>
@@ -1367,6 +1380,7 @@
 <translation id="9168436347345867845">এটি পরে করুন</translation>
 <translation id="9178475906033259337"><ph name="QUERY" />-এর জন্য ১টি ফলাফল দেখানো হচ্ছে</translation>
 <translation id="9179259655489829027">এই বৈশিষ্ট্যের মাধ্যমে আপনি কোনও পাসওয়ার্ড ছাড়াই সাইন-ইন করা যেকোনও ব্যবহারকারীকে দ্রুত অ্যাক্সেস করতে পারেন। এটি শুধুমাত্র বিশ্বস্ত অ্যাকাউন্টেই ব্যবহার করুন।</translation>
+<translation id="9180906851711123156">বন্ধ করতে Ctrl ও W কী একসাথে প্রেস করুন</translation>
 <translation id="9183456764293710005">ফুল-স্ক্রিন ম্যাগনিফায়ার</translation>
 <translation id="9193626018745640770">অজানা ডিভাইসে কাস্ট করা হচ্ছে</translation>
 <translation id="9194617393863864469">অন্য ব্যবহারকারীকে সাইন-ইন করান...</translation>
diff --git a/ash/strings/ash_strings_bs.xtb b/ash/strings/ash_strings_bs.xtb
index b0004ac2..fcab363 100644
--- a/ash/strings/ash_strings_bs.xtb
+++ b/ash/strings/ash_strings_bs.xtb
@@ -252,7 +252,7 @@
 <translation id="243878895369688216">Otvoreno jučer</translation>
 <translation id="2441427462554639370">Snimanje je prekinuto zbog jako malo slobodnog prostora za pohranu</translation>
 <translation id="24452542372838207">Proširi obavještenje</translation>
-<translation id="2449089818483227734">Slaba baterija</translation>
+<translation id="2449089818483227734">Baterija je slaba</translation>
 <translation id="2450205753526923158">Način rada za snimak ekrana</translation>
 <translation id="2456008742792828469">Kalendar, <ph name="CURRENT_MONTH_YEAR" /></translation>
 <translation id="2473177541599297363">Potvrdite rezoluciju</translation>
@@ -413,7 +413,7 @@
 <translation id="3441920967307853524"><ph name="RECEIVED_BYTES" />/<ph name="TOTAL_BYTES" /></translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> min</translation>
 <translation id="3445925074670675829">USB-C uređaj</translation>
-<translation id="3455468639467374593">Predložak, <ph name="TEMPLATE_NAME" /></translation>
+<translation id="3455468639467374593">Šablon, <ph name="TEMPLATE_NAME" /></translation>
 <translation id="3465223694362104965">Od vaše posljednje prijave na ovaj uređaj je povezana još jedna tastatura. Prije nego što upotrijebite tu tastaturu, provjerite je li pouzdana.</translation>
 <translation id="3465356146291925647">Upravlja vaš administrator</translation>
 <translation id="3477079411857374384">Ctrl + Shift + razmak</translation>
@@ -460,8 +460,8 @@
 <translation id="3633097874324966332">Otvorite postavke Bluetootha da uparite uređaj</translation>
 <translation id="3638400994746983214">Uključite/isključite ekran za privatnost. <ph name="STATE_TEXT" />.</translation>
 <translation id="3649505501900178324">Rok za ažuriranje je prekoračen</translation>
-<translation id="3659814201068740063">Još oko <ph name="TIME_LEFT" /> (<ph name="PERCENTAGE" />%).
-Priključite uređaj na napajanje.</translation>
+<translation id="3659814201068740063">Preostalo je oko <ph name="TIME_LEFT" /> (<ph name="PERCENTAGE" />%).
+Povežite uređaj na napajanje.</translation>
 <translation id="366222428570480733">Korisnik kojim upravlja <ph name="USER_EMAIL_ADDRESS" /></translation>
 <translation id="36813544980941320">WiFi mreže će se dijeliti između vašeg telefona i uređaja <ph name="DEVICE_NAME" /></translation>
 <translation id="3694122362646626770">Web-lokacije</translation>
@@ -516,7 +516,7 @@
 <translation id="3962859241508114581">Prethodna numera</translation>
 <translation id="3969043077941541451">Isključeno</translation>
 <translation id="397105322502079400">Računanje…</translation>
-<translation id="397726367135689299">Punjenje baterije možda nije pouzdano.</translation>
+<translation id="397726367135689299">Punjenje baterije može biti nepouzdano.</translation>
 <translation id="3977512764614765090">Baterija je na <ph name="PERCENTAGE" />% i puni se.</translation>
 <translation id="3986082989454912832">Odgovori</translation>
 <translation id="3995138139523574647">USB-C uređaj (stražnji desni priključak)</translation>
@@ -1237,7 +1237,7 @@
 <translation id="8345019317483336363">Odabran je prozor <ph name="WINDOW_TITLE" /></translation>
 <translation id="8351131234907093545">Napravite bilješku</translation>
 <translation id="8364673525741149932">Uključite Shelf Party. <ph name="STATE_TEXT" /></translation>
-<translation id="8369166482916924789">Spremljena radna površina, <ph name="SAVE_AND_RECALL_DESK_NAME" /></translation>
+<translation id="8369166482916924789">Sačuvana radna površina, <ph name="SAVE_AND_RECALL_DESK_NAME" /></translation>
 <translation id="8371779926711439835">Slovo unaprijed</translation>
 <translation id="8371991222807690464">Performanse perifernog uređaja mogu biti ograničene u Načinu rada za gosta</translation>
 <translation id="8374601332003098278">Pritisnite Enter da snimite dio ekrana</translation>
@@ -1380,7 +1380,7 @@
 <translation id="9168436347345867845">Uradit ću to kasnije</translation>
 <translation id="9178475906033259337">Prikaz 1 rezultata za upit <ph name="QUERY" /></translation>
 <translation id="9179259655489829027">Ova funkcija vam omogućava da brzo pristupite prijavljenim korisnicima bez lozinke. Ovu funkciju koristite samo s računima kojima vjerujete.</translation>
-<translation id="9180906851711123156">Pritisnite Ctrl + W da biste zatvorili</translation>
+<translation id="9180906851711123156">Pritisnite Ctrl + W da zatvorite</translation>
 <translation id="9183456764293710005">Povećalo za cijeli ekran</translation>
 <translation id="9193626018745640770">Emitiranje na nepoznatom prijemniku</translation>
 <translation id="9194617393863864469">Prijavite još jednog korisnika...</translation>
diff --git a/ash/strings/ash_strings_ca.xtb b/ash/strings/ash_strings_ca.xtb
index 6a20f2e..0dfdff0 100644
--- a/ash/strings/ash_strings_ca.xtb
+++ b/ash/strings/ash_strings_ca.xtb
@@ -698,6 +698,7 @@
 <translation id="5071064518267176975">Una aplicació vol utilitzar el micròfon</translation>
 <translation id="5078796286268621944">PIN incorrecte</translation>
 <translation id="5083553833479578423">Desbloqueja més funcions de l'Assistent.</translation>
+<translation id="509790653408515442">Quan reprodueixis en continu aplicacions del telèfon, apareixeran aquí</translation>
 <translation id="5107522548814527560">Web</translation>
 <translation id="5117590920725113268">Mostra el mes següent</translation>
 <translation id="5136175204352732067">S'ha connectat un altre teclat</translation>
@@ -720,6 +721,7 @@
 <translation id="523505283826916779">Configuració d'accessibilitat</translation>
 <translation id="5245201184978705914">No es pot generar una transcripció</translation>
 <translation id="5253783950165989294">Connectat a un dispositiu anomenat <ph name="DEVICE_NAME" />, <ph name="BATTERY_PERCENTAGE" />% de bateria</translation>
+<translation id="5258528442992323769">No s'ha desat cap escriptori</translation>
 <translation id="5260676007519551770">Escriptori 4</translation>
 <translation id="5283099933536931082"><ph name="APP_ITEM_TITLE" /> sol·licita la teva atenció.</translation>
 <translation id="5283198616748585639">Afegeix 1 minut</translation>
@@ -1259,6 +1261,7 @@
 <translation id="851458219935658693">Mostra les finestres de l'escriptori actual amb el botó d'opció seleccionat</translation>
 <translation id="8517041960877371778">És possible que el dispositiu <ph name="DEVICE_TYPE" /> no es carregui mentre està encès.</translation>
 <translation id="8535393432370007982">Desfés l'ordenació per color</translation>
+<translation id="8542053257095774575">No s'ha desat cap escriptori ni cap plantilla</translation>
 <translation id="8546059259582788728">L'ordenació s'ha desfet correctament</translation>
 <translation id="8551588720239073785">Configuració de data i hora</translation>
 <translation id="8553395910833293175">Ja està assignada a tots els escriptoris.</translation>
diff --git a/ash/strings/ash_strings_da.xtb b/ash/strings/ash_strings_da.xtb
index 7675d217..ba8c41f 100644
--- a/ash/strings/ash_strings_da.xtb
+++ b/ash/strings/ash_strings_da.xtb
@@ -698,6 +698,7 @@
 <translation id="5071064518267176975">En app anmoder om at anvende mikrofonen</translation>
 <translation id="5078796286268621944">Forkert pinkode</translation>
 <translation id="5083553833479578423">Få adgang til endnu flere Assistent-funktioner.</translation>
+<translation id="509790653408515442">Når du streamer din telefons apps, vises de her</translation>
 <translation id="5107522548814527560">Internet</translation>
 <translation id="5117590920725113268">Vis næste måned</translation>
 <translation id="5136175204352732067">Du har tilsluttet et andet tastatur</translation>
@@ -720,6 +721,7 @@
 <translation id="523505283826916779">Indstillinger for hjælpefunktioner</translation>
 <translation id="5245201184978705914">Det er ikke muligt at generere en transskription</translation>
 <translation id="5253783950165989294">Forbundet til en enhed ved navn <ph name="DEVICE_NAME" />, <ph name="BATTERY_PERCENTAGE" /> % batteri</translation>
+<translation id="5258528442992323769">Der er ingen gemte skriveborde</translation>
 <translation id="5260676007519551770">Skrivebord 4</translation>
 <translation id="5283099933536931082"><ph name="APP_ITEM_TITLE" /> kræver din opmærksomhed.</translation>
 <translation id="5283198616748585639">Tilføj 1 minut</translation>
@@ -1259,6 +1261,7 @@
 <translation id="851458219935658693">Vis vinduer fra det aktuelle skrivebord. Alternativknappen er valgt.</translation>
 <translation id="8517041960877371778">Din <ph name="DEVICE_TYPE" /> kan muligvis ikke oplades, mens den er tændt.</translation>
 <translation id="8535393432370007982">Fortryd sortering efter farve</translation>
+<translation id="8542053257095774575">Der er ingen gemte skriveborde eller skabeloner</translation>
 <translation id="8546059259582788728">Sorteringen blev fortrudt</translation>
 <translation id="8551588720239073785">Indstillinger for dato og tid</translation>
 <translation id="8553395910833293175">Allerede tildelt til alle skriveborde.</translation>
diff --git a/ash/strings/ash_strings_el.xtb b/ash/strings/ash_strings_el.xtb
index de40b2e3..97859c57 100644
--- a/ash/strings/ash_strings_el.xtb
+++ b/ash/strings/ash_strings_el.xtb
@@ -252,6 +252,7 @@
 <translation id="243878895369688216">Ανοίχτηκαν χθες</translation>
 <translation id="2441427462554639370">Η εγγραφή ολοκληρώθηκε λόγω του εξαιρετικά περιορισμένου αποθηκευτικού χώρου.</translation>
 <translation id="24452542372838207">Ανάπτυξη ειδοποίησης</translation>
+<translation id="2449089818483227734">Χαμηλή ισχύς μπαταρίας</translation>
 <translation id="2450205753526923158">Λειτουργία στιγμιότυπου οθόνης</translation>
 <translation id="2456008742792828469">Ημερολόγιο, <ph name="CURRENT_MONTH_YEAR" /></translation>
 <translation id="2473177541599297363">Επιβεβαίωση ανάλυσης</translation>
@@ -412,11 +413,13 @@
 <translation id="3441920967307853524"><ph name="RECEIVED_BYTES" />/<ph name="TOTAL_BYTES" /></translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> λεπτά</translation>
 <translation id="3445925074670675829">Συσκευή USB-C</translation>
+<translation id="3455468639467374593">Πρότυπο, <ph name="TEMPLATE_NAME" /></translation>
 <translation id="3465223694362104965">Ένα άλλο πληκτρολόγιο έχει συνδεθεί με αυτήν τη συσκευή από την τελευταία σύνδεσή σας. Βεβαιωθείτε ότι εμπιστεύεστε αυτό το πληκτρολόγιο πριν το χρησιμοποιήσετε.</translation>
 <translation id="3465356146291925647">Διαχειριζόμενο από τον διαχειριστή σας</translation>
 <translation id="3477079411857374384">Control-Shift-Space</translation>
 <translation id="3485319357743610354"><ph name="SECURITY_STATUS" />, <ph name="CONNECTION_STATUS" />, Ισχύς σήματος <ph name="SIGNAL_STRENGTH" /></translation>
 <translation id="348799646910989694">Αυτόματη απόκρυψη ραφιού</translation>
+<translation id="3505066820268455558">Φόρτιση μπαταρίας</translation>
 <translation id="3509391053705095206">Δεν βρέθηκε το τηλέφωνό σας. Βεβαιωθείτε ότι το Bluetooth του τηλεφώνου είναι ενεργό.</translation>
 <translation id="3510164367642747937">Επισήμανση δείκτη ποντικιού</translation>
 <translation id="3513798432020909783">Ο λογαριασμός είναι διαχειριζόμενος από τον χρήστη <ph name="MANAGER_EMAIL" /></translation>
@@ -457,6 +460,8 @@
 <translation id="3633097874324966332">Ανοίξτε τις ρυθμίσεις Bluetooth για σύζευξη της συσκευής σας</translation>
 <translation id="3638400994746983214">Εναλλαγή οθόνης απορρήτου. <ph name="STATE_TEXT" />.</translation>
 <translation id="3649505501900178324">Εκπρόθεσμη ενημέρωση</translation>
+<translation id="3659814201068740063">Απομένουν περίπου <ph name="TIME_LEFT" /> (<ph name="PERCENTAGE" />%).
+Συνδέστε τη συσκευή σας στο ρεύμα.</translation>
 <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> Διαχειριζόμενος χρήστης</translation>
 <translation id="36813544980941320">Θα γίνει κοινοποίηση των δικτύων Wi-Fi μεταξύ του τηλεφώνου σας και της συσκευής <ph name="DEVICE_NAME" /></translation>
 <translation id="3694122362646626770">Ιστότοποι</translation>
@@ -511,6 +516,7 @@
 <translation id="3962859241508114581">Προηγούμενο κομμάτι</translation>
 <translation id="3969043077941541451">Ανενεργό</translation>
 <translation id="397105322502079400">Υπολογισμός…</translation>
+<translation id="397726367135689299">Η φόρτιση της μπαταρίας ενδέχεται να μην είναι αξιόπιστη.</translation>
 <translation id="3977512764614765090">Η μπαταρία είναι στο <ph name="PERCENTAGE" />% και φορτίζει.</translation>
 <translation id="3986082989454912832">Απάντηση</translation>
 <translation id="3995138139523574647">Συσκευή USB-C (πίσω δεξιά θύρα)</translation>
@@ -1038,6 +1044,7 @@
 <translation id="7130207228079676353">ΔΗΜΟΦΙΛΕΣΤΕΡΕΣ</translation>
 <translation id="7131634465328662194">Θα αποσυνδεθείτε αυτόματα.</translation>
 <translation id="7143207342074048698">Σύνδεση</translation>
+<translation id="7144942256906679589">Κατάσταση μπαταρίας</translation>
 <translation id="7165278925115064263">Alt+Shift+K</translation>
 <translation id="7168224885072002358">Επαναφορά στην προηγούμενη ανάλυση σε <ph name="TIMEOUT_SECONDS" /></translation>
 <translation id="7180611975245234373">Ανανέωση</translation>
@@ -1103,6 +1110,7 @@
 <translation id="7593891976182323525">Search ή Shift</translation>
 <translation id="7600875258240007829">Δείτε όλες τις ειδοποιήσεις</translation>
 <translation id="7607002721634913082">Έγινε παύση</translation>
+<translation id="7609951632080598826">Προβολή ημερολογίου, <ph name="DATE" />, <ph name="TIME" /></translation>
 <translation id="7611213136657090146">Επανασύνδεση κάμερας.</translation>
 <translation id="7624117708979618027"><ph name="TEMPERATURE_F" />° F</translation>
 <translation id="7633755430369750696">Εμφάνιση ρυθμίσεων της λειτουργίας Κοινοποίηση κοντά.</translation>
@@ -1228,6 +1236,7 @@
 <translation id="8345019317483336363">Επιλέχτηκε το παράθυρο <ph name="WINDOW_TITLE" />.</translation>
 <translation id="8351131234907093545">Δημιουργία σημείωσης</translation>
 <translation id="8364673525741149932">Εναλλαγή Shelf Party. <ph name="STATE_TEXT" /></translation>
+<translation id="8369166482916924789">Αποθηκευμένο γραφείο, <ph name="SAVE_AND_RECALL_DESK_NAME" /></translation>
 <translation id="8371779926711439835">Προώθηση ανά γράμμα</translation>
 <translation id="8371991222807690464">Η απόδοση των περιφερειακών ενδέχεται να περιορίζεται στη Λειτουργία επισκέπτη</translation>
 <translation id="8374601332003098278">Πατήστε Enter για εγγραφή μέρους της οθόνης</translation>
@@ -1339,6 +1348,7 @@
 <translation id="9000771174482730261">ΔΙΑΧΕΙΡΙΣΗ ΑΠΟΘΗΚΕΥΤΙΚΟΥ ΧΩΡΟΥ</translation>
 <translation id="9017320285115481645">Εισαγάγετε τον κωδικό πρόσβασης γονέα του Family Link.</translation>
 <translation id="9024331582947483881">πλήρης οθόνη</translation>
+<translation id="9029736946581028033">Η συσκευή θα απενεργοποιηθεί σύντομα</translation>
 <translation id="9030319654231318877">Ανενεργό μέχρι το ηλιοβασίλεμα</translation>
 <translation id="9034924485347205037">Αρχεία Linux</translation>
 <translation id="9047624247355796468">Άνοιγμα ρυθμίσεων για το δίκτυο <ph name="NETWORK_NAME" /></translation>
@@ -1368,6 +1378,7 @@
 <translation id="9168436347345867845">Αργότερα</translation>
 <translation id="9178475906033259337">Προβολή 1 αποτελέσματος για την αναζήτηση <ph name="QUERY" /></translation>
 <translation id="9179259655489829027">Αυτή η λειτουργία σάς επιτρέπει να έχετε γρήγορη πρόσβαση σε οποιονδήποτε συνδεδεμένο χρήστη, χωρίς να απαιτείται κωδικός πρόσβασης. Χρησιμοποιήστε αυτήν τη λειτουργία μόνο με λογαριασμούς που εμπιστεύεστε.</translation>
+<translation id="9180906851711123156">Πατήστε Ctrl+W για κλείσιμο</translation>
 <translation id="9183456764293710005">Μεγέθυνση πλήρους οθόνης</translation>
 <translation id="9193626018745640770">Μετάδοση σε άγνωστο δέκτη</translation>
 <translation id="9194617393863864469">Σύνδεση με άλλον χρήστη...</translation>
diff --git a/ash/strings/ash_strings_es.xtb b/ash/strings/ash_strings_es.xtb
index 4b384e4..2960110 100644
--- a/ash/strings/ash_strings_es.xtb
+++ b/ash/strings/ash_strings_es.xtb
@@ -699,6 +699,7 @@
 <translation id="5071064518267176975">Una aplicación quiere usar el micrófono</translation>
 <translation id="5078796286268621944">PIN incorrecto</translation>
 <translation id="5083553833479578423">Descubre más funciones del Asistente.</translation>
+<translation id="509790653408515442">Cuando emitas las aplicaciones de tu teléfono, aparecerán aquí</translation>
 <translation id="5107522548814527560">Web</translation>
 <translation id="5117590920725113268">Mostrar mes siguiente</translation>
 <translation id="5136175204352732067">Se ha conectado otro teclado</translation>
@@ -721,6 +722,7 @@
 <translation id="523505283826916779">Ajustes de accesibilidad</translation>
 <translation id="5245201184978705914">No se puede generar la transcripción</translation>
 <translation id="5253783950165989294">Conectado a un dispositivo llamado <ph name="DEVICE_NAME" />, <ph name="BATTERY_PERCENTAGE" /> % de batería</translation>
+<translation id="5258528442992323769">No hay escritorios guardados</translation>
 <translation id="5260676007519551770">Escritorio 4</translation>
 <translation id="5283099933536931082"><ph name="APP_ITEM_TITLE" /> solicita tu atención.</translation>
 <translation id="5283198616748585639">Añadir 1 minuto</translation>
@@ -1260,6 +1262,7 @@
 <translation id="851458219935658693">Mostrar ventanas del escritorio actual, botón seleccionado</translation>
 <translation id="8517041960877371778">Es posible que tu <ph name="DEVICE_TYPE" /> no se cargue mientras esté encendido.</translation>
 <translation id="8535393432370007982">Deshacer orden por color</translation>
+<translation id="8542053257095774575">No hay escritorios ni plantillas guardados</translation>
 <translation id="8546059259582788728">Orden deshecho correctamente</translation>
 <translation id="8551588720239073785">Configuración de fecha y hora</translation>
 <translation id="8553395910833293175">Ya está asignado a todos los escritorios.</translation>
diff --git a/ash/strings/ash_strings_fi.xtb b/ash/strings/ash_strings_fi.xtb
index 4e1967d..8220d4c 100644
--- a/ash/strings/ash_strings_fi.xtb
+++ b/ash/strings/ash_strings_fi.xtb
@@ -697,6 +697,7 @@
 <translation id="5071064518267176975">Sovellus haluaa käyttää mikrofonia</translation>
 <translation id="5078796286268621944">Väärä PIN-koodi</translation>
 <translation id="5083553833479578423">Käytä lisää Assistantin ominaisuuksia.</translation>
+<translation id="509790653408515442">Kun striimaat puhelimen sovelluksia, ne näkyvät täällä</translation>
 <translation id="5107522548814527560">Verkko</translation>
 <translation id="5117590920725113268">Näytä seuraava kuukausi</translation>
 <translation id="5136175204352732067">Eri näppäimistö kytketty</translation>
@@ -719,6 +720,7 @@
 <translation id="523505283826916779">Esteettömyysasetukset</translation>
 <translation id="5245201184978705914">Transkriptiota ei voi luoda</translation>
 <translation id="5253783950165989294">Yhdistetty laitteeseen nimeltä <ph name="DEVICE_NAME" />, <ph name="BATTERY_PERCENTAGE" /> % virtaa</translation>
+<translation id="5258528442992323769">Ei tallennettuja virtuaalityöpöytiä</translation>
 <translation id="5260676007519551770">Pöytä 4</translation>
 <translation id="5283099933536931082"><ph name="APP_ITEM_TITLE" /> pyytää huomiotasi.</translation>
 <translation id="5283198616748585639">Lisää 1 min</translation>
@@ -1258,6 +1260,7 @@
 <translation id="851458219935658693">Näytä ikkunat nykyiseltä työpöydältä, valintanappi valittu</translation>
 <translation id="8517041960877371778"><ph name="DEVICE_TYPE" /> ei välttämättä lataudu, kun se on käynnissä.</translation>
 <translation id="8535393432370007982">Kumoa värin mukaan lajittelu</translation>
+<translation id="8542053257095774575">Ei tallennettuja virtuaalityöpöytiä tai malleja</translation>
 <translation id="8546059259582788728">Lajittelun kumoaminen ei onnistunut</translation>
 <translation id="8551588720239073785">Aika- ja päivämääräasetukset</translation>
 <translation id="8553395910833293175">Lisätty jo kaikille työpöydille.</translation>
diff --git a/ash/strings/ash_strings_fil.xtb b/ash/strings/ash_strings_fil.xtb
index c6bd3368..2f38163b 100644
--- a/ash/strings/ash_strings_fil.xtb
+++ b/ash/strings/ash_strings_fil.xtb
@@ -698,6 +698,7 @@
 <translation id="5071064518267176975">Gustong gamitin ng isang app ang mikropono</translation>
 <translation id="5078796286268621944">Maling PIN</translation>
 <translation id="5083553833479578423">Mag-unlock ng higit pang feature ng Assistant.</translation>
+<translation id="509790653408515442">Kapag na-stream mo ang mga app sa iyong telepono, lalabas ang mga ito dito</translation>
 <translation id="5107522548814527560">Web</translation>
 <translation id="5117590920725113268">Ipakita ang susunod na buwan</translation>
 <translation id="5136175204352732067">Ibang keyboard ang nakakonekta</translation>
@@ -720,6 +721,7 @@
 <translation id="523505283826916779">Mga setting ng accessibility</translation>
 <translation id="5245201184978705914">Hindi makabuo ng transcript</translation>
 <translation id="5253783950165989294">Nakakonekta sa isang device na may pangalang <ph name="DEVICE_NAME" />, <ph name="BATTERY_PERCENTAGE" />% baterya</translation>
+<translation id="5258528442992323769">Walang naka-save na desk</translation>
 <translation id="5260676007519551770">Desk 4</translation>
 <translation id="5283099933536931082">Hinihiling ng <ph name="APP_ITEM_TITLE" /> ang iyong atensyon.</translation>
 <translation id="5283198616748585639">Magdagdag ng 1 minuto</translation>
@@ -1260,6 +1262,7 @@
 <translation id="851458219935658693">Ipakita ang mga window mula sa kasalukuyang desk at piniling radio button</translation>
 <translation id="8517041960877371778">Maaaring hindi mag-charge ang iyong <ph name="DEVICE_TYPE" /> habang naka-on ito.</translation>
 <translation id="8535393432370007982">I-undo ang ayos ng pagkakasunod-sunod ayon sa kulay</translation>
+<translation id="8542053257095774575">Walang naka-save na desk o template</translation>
 <translation id="8546059259582788728">Na-undo ang pagbubukod-bukod</translation>
 <translation id="8551588720239073785">Mga setting ng petsa at oras</translation>
 <translation id="8553395910833293175">Naitalaga na sa lahat ng desk.</translation>
diff --git a/ash/strings/ash_strings_fr-CA.xtb b/ash/strings/ash_strings_fr-CA.xtb
index 8515a587..1eacba27 100644
--- a/ash/strings/ash_strings_fr-CA.xtb
+++ b/ash/strings/ash_strings_fr-CA.xtb
@@ -698,6 +698,7 @@
 <translation id="5071064518267176975">Une application demande l'autorisation d'utiliser le microphone</translation>
 <translation id="5078796286268621944">NIP incorrect</translation>
 <translation id="5083553833479578423">Déverrouillez davantage de fonctionnalités de l'Assistant Google.</translation>
+<translation id="509790653408515442">Lorsque vous diffusez les applications de votre téléphone, elles apparaissent ici</translation>
 <translation id="5107522548814527560">Web</translation>
 <translation id="5117590920725113268">Afficher le mois suivant</translation>
 <translation id="5136175204352732067">Autre clavier branché</translation>
@@ -720,6 +721,7 @@
 <translation id="523505283826916779">Paramètres d'accessibilité</translation>
 <translation id="5245201184978705914">Impossible de générer la transcription</translation>
 <translation id="5253783950165989294">Connecté à un appareil nommé <ph name="DEVICE_NAME" />, dont le niveau de pile est à<ph name="BATTERY_PERCENTAGE" /> %</translation>
+<translation id="5258528442992323769">Aucun bureau enregistré</translation>
 <translation id="5260676007519551770">Bureau 4</translation>
 <translation id="5283099933536931082"><ph name="APP_ITEM_TITLE" /> demande votre attention.</translation>
 <translation id="5283198616748585639">Ajouter 1 minute</translation>
@@ -1259,6 +1261,7 @@
 <translation id="851458219935658693">Afficher les fenêtres du bureau actuel, bouton radio sélectionné</translation>
 <translation id="8517041960877371778">Il est possible que votre <ph name="DEVICE_TYPE" /> ne se charge pas lorsqu’il est allumé.</translation>
 <translation id="8535393432370007982">Annuler l'ordre de tri par couleur</translation>
+<translation id="8542053257095774575">Aucun bureau ni modèle enregistré</translation>
 <translation id="8546059259582788728">Le tri a bien été annulé</translation>
 <translation id="8551588720239073785">Paramètres de date et d'heure</translation>
 <translation id="8553395910833293175">Association déjà faite sur tous les bureaux.</translation>
diff --git a/ash/strings/ash_strings_fr.xtb b/ash/strings/ash_strings_fr.xtb
index d53f2f7..97be1f47 100644
--- a/ash/strings/ash_strings_fr.xtb
+++ b/ash/strings/ash_strings_fr.xtb
@@ -698,6 +698,7 @@
 <translation id="5071064518267176975">Une appli souhaite utiliser le micro</translation>
 <translation id="5078796286268621944">Code PIN incorrect</translation>
 <translation id="5083553833479578423">Déverrouiller plus de fonctionnalités de l'Assistant.</translation>
+<translation id="509790653408515442">Lorsque vous diffusez les applis de votre téléphone en streaming, elles s'affichent ici</translation>
 <translation id="5107522548814527560">Web</translation>
 <translation id="5117590920725113268">Afficher le mois suivant</translation>
 <translation id="5136175204352732067">Clavier différent branché</translation>
@@ -720,6 +721,7 @@
 <translation id="523505283826916779">Paramètres d'accessibilité</translation>
 <translation id="5245201184978705914">Impossible de générer la transcription</translation>
 <translation id="5253783950165989294">Connecté à un appareil nommé "<ph name="DEVICE_NAME" />", batterie à <ph name="BATTERY_PERCENTAGE" /> %</translation>
+<translation id="5258528442992323769">Aucun bureau enregistré</translation>
 <translation id="5260676007519551770">Bureau 4</translation>
 <translation id="5283099933536931082"><ph name="APP_ITEM_TITLE" /> requiert votre attention.</translation>
 <translation id="5283198616748585639">Ajouter une minute</translation>
@@ -1259,6 +1261,7 @@
 <translation id="851458219935658693">Afficher les fenêtres du bureau actuel, case d'option cochée</translation>
 <translation id="8517041960877371778">Il est possible que votre appareil <ph name="DEVICE_TYPE" /> ne se recharge pas lorsqu'il est allumé.</translation>
 <translation id="8535393432370007982">Annuler le tri par couleur</translation>
+<translation id="8542053257095774575">Aucun bureau ni modèle enregistré</translation>
 <translation id="8546059259582788728">Le tri a bien été annulé</translation>
 <translation id="8551588720239073785">Paramètres de date et d'heure</translation>
 <translation id="8553395910833293175">Association déjà faite sur tous les bureaux.</translation>
diff --git a/ash/strings/ash_strings_gl.xtb b/ash/strings/ash_strings_gl.xtb
index 57c5602..04b40af1 100644
--- a/ash/strings/ash_strings_gl.xtb
+++ b/ash/strings/ash_strings_gl.xtb
@@ -699,6 +699,7 @@
 <translation id="5071064518267176975">Unha aplicación quere usar o micrófono</translation>
 <translation id="5078796286268621944">PIN incorrecto</translation>
 <translation id="5083553833479578423">Desbloquea máis funcións do Asistente.</translation>
+<translation id="509790653408515442">Cando emitas as aplicacións do teu teléfono, aparecerán aquí</translation>
 <translation id="5107522548814527560">Web</translation>
 <translation id="5117590920725113268">Mostrar mes seguinte</translation>
 <translation id="5136175204352732067">Conectouse un teclado diferente</translation>
@@ -721,6 +722,7 @@
 <translation id="523505283826916779">Configuración de accesibilidade</translation>
 <translation id="5245201184978705914">Non se puido xerar a transcrición</translation>
 <translation id="5253783950165989294">Conexión establecida cun dispositivo chamado "<ph name="DEVICE_NAME" />"; <ph name="BATTERY_PERCENTAGE" /> % de batería</translation>
+<translation id="5258528442992323769">Non hai escritorios gardados</translation>
 <translation id="5260676007519551770">Escritorio 4</translation>
 <translation id="5283099933536931082"><ph name="APP_ITEM_TITLE" /> require a túa atención.</translation>
 <translation id="5283198616748585639">Engadir 1 min</translation>
@@ -1260,6 +1262,7 @@
 <translation id="851458219935658693">Seleccionouse o botón de opción para mostrar as ventás do escritorio actual</translation>
 <translation id="8517041960877371778">É posible que o teu <ph name="DEVICE_TYPE" /> non cargue mentres estea acendido.</translation>
 <translation id="8535393432370007982">Desfacer orde de clasificación por cor</translation>
+<translation id="8542053257095774575">Non hai modelos nin escritorios gardados</translation>
 <translation id="8546059259582788728">A orde desfíxose correctamente</translation>
 <translation id="8551588720239073785">Configuración de data e hora</translation>
 <translation id="8553395910833293175">Xa se asignou a todos os escritorios.</translation>
diff --git a/ash/strings/ash_strings_is.xtb b/ash/strings/ash_strings_is.xtb
index 1ddce7b8..dfda3870 100644
--- a/ash/strings/ash_strings_is.xtb
+++ b/ash/strings/ash_strings_is.xtb
@@ -698,6 +698,7 @@
 <translation id="5071064518267176975">Forrit vill nota hljóðnemann</translation>
 <translation id="5078796286268621944">Rangt PIN-númer</translation>
 <translation id="5083553833479578423">Opnaðu fyrir fleiri eiginleika hjálparans.</translation>
+<translation id="509790653408515442">Um leið og þú streymir forrit símans birtast forritin hér</translation>
 <translation id="5107522548814527560">Vefur</translation>
 <translation id="5117590920725113268">Sýna næsta mánuð</translation>
 <translation id="5136175204352732067">Annað lyklaborð tengt</translation>
@@ -720,6 +721,7 @@
 <translation id="523505283826916779">Aðgengisstillingar</translation>
 <translation id="5245201184978705914">Ekki tókst að búa til textauppskrift</translation>
 <translation id="5253783950165989294">Tengdist tækinu <ph name="DEVICE_NAME" />, <ph name="BATTERY_PERCENTAGE" />% rafhleðsla</translation>
+<translation id="5258528442992323769">Engin vistuð skrifborð</translation>
 <translation id="5260676007519551770">Skrifborð 4</translation>
 <translation id="5283099933536931082"><ph name="APP_ITEM_TITLE" /> vill ná athygli þinni.</translation>
 <translation id="5283198616748585639">Bæta 1 mín. við</translation>
@@ -1259,6 +1261,7 @@
 <translation id="851458219935658693">Sýna glugga á núverandi skrifborði, hringhnappur valinn</translation>
 <translation id="8517041960877371778">Ekki er víst að <ph name="DEVICE_TYPE" /> hlaðist á meðan kveikt er á tölvunni.</translation>
 <translation id="8535393432370007982">Afturkalla röðun eftir lit</translation>
+<translation id="8542053257095774575">Engin vistuð skrifborð eða sniðmát</translation>
 <translation id="8546059259582788728">Röðun var afturkölluð</translation>
 <translation id="8551588720239073785">Dagsetningar- og tímastillingar</translation>
 <translation id="8553395910833293175">Þegar úthlutað til allra skrifborða</translation>
diff --git a/ash/strings/ash_strings_kk.xtb b/ash/strings/ash_strings_kk.xtb
index a56f73d..50f4b83 100644
--- a/ash/strings/ash_strings_kk.xtb
+++ b/ash/strings/ash_strings_kk.xtb
@@ -698,6 +698,7 @@
 <translation id="5071064518267176975">Қолданба микрофонды пайдалануға рұқсат сұрайды</translation>
 <translation id="5078796286268621944">PIN коды дұрыс емес</translation>
 <translation id="5083553833479578423">Басқа да Assistant мүмкіндіктерін ашыңыз.</translation>
+<translation id="509790653408515442">Телефондағы қолданбаларды трансляциялау кезінде олар осы жерде шығады.</translation>
 <translation id="5107522548814527560">Интернет</translation>
 <translation id="5117590920725113268">Келесі айды көрсету</translation>
 <translation id="5136175204352732067">Басқа пернетақта жалғанды</translation>
@@ -720,6 +721,7 @@
 <translation id="523505283826916779">Арнайы мүмкіндіктер параметрлері</translation>
 <translation id="5245201184978705914">Транскриптіні құру мүмкін емес</translation>
 <translation id="5253783950165989294">"<ph name="DEVICE_NAME" />" деп аталатын, батарея заряды <ph name="BATTERY_PERCENTAGE" />% құрылғыға қосылды.</translation>
+<translation id="5258528442992323769">Сақталған жұмыс үстелі жоқ.</translation>
 <translation id="5260676007519551770">4-ші жұмыс үстелі</translation>
 <translation id="5283099933536931082"><ph name="APP_ITEM_TITLE" /> қолданбасы назар аударуыңызды сұрайды.</translation>
 <translation id="5283198616748585639">1 мин қосу</translation>
@@ -1259,6 +1261,7 @@
 <translation id="851458219935658693">Терезелерді қазіргі жұмыс үстелінен көрсету, ауыстырып қосқыш таңдалды.</translation>
 <translation id="8517041960877371778"><ph name="DEVICE_TYPE" /> іске қосылғанда зарядталмауы мүмкін.</translation>
 <translation id="8535393432370007982">Түс бойынша сұрыптау ретін қайтару</translation>
+<translation id="8542053257095774575">Сақталған жұмыс үстелі немесе үлгі жоқ.</translation>
 <translation id="8546059259582788728">Сұрыптау реті қайтарылды.</translation>
 <translation id="8551588720239073785">Күн және уақыт параметрлері</translation>
 <translation id="8553395910833293175">Барлық жұмыс үстеліне әлдеқашан тағайындалған.</translation>
diff --git a/ash/strings/ash_strings_lv.xtb b/ash/strings/ash_strings_lv.xtb
index 251a1c59..435ebfa 100644
--- a/ash/strings/ash_strings_lv.xtb
+++ b/ash/strings/ash_strings_lv.xtb
@@ -698,6 +698,7 @@
 <translation id="5071064518267176975">Lietotne pieprasa atļauju izmantot mikrofonu</translation>
 <translation id="5078796286268621944">Nepareizs PIN</translation>
 <translation id="5083553833479578423">Piekļūstiet citām Asistenta funkcijām</translation>
+<translation id="509790653408515442">Šeit būs redzamas jūsu tālruņa lietotnes, kad tās straumēsiet.</translation>
 <translation id="5107522548814527560">Tīmeklis</translation>
 <translation id="5117590920725113268">Rādīt nākamo mēnesi</translation>
 <translation id="5136175204352732067">Ir pievienota cita tastatūra</translation>
@@ -720,6 +721,7 @@
 <translation id="523505283826916779">Pieejamības iestatījumi</translation>
 <translation id="5245201184978705914">Nevar ģenerēt transkripciju.</translation>
 <translation id="5253783950165989294">Izveidots savienojums ar ierīci “<ph name="DEVICE_NAME" />”, akumulatora uzlādes līmenis: <ph name="BATTERY_PERCENTAGE" />%</translation>
+<translation id="5258528442992323769">Nav saglabātu darbvietu</translation>
 <translation id="5260676007519551770">4. galds</translation>
 <translation id="5283099933536931082">Lietotne <ph name="APP_ITEM_TITLE" /> aicina pievērst tai uzmanību.</translation>
 <translation id="5283198616748585639">Pievienot 1 min</translation>
@@ -1259,6 +1261,7 @@
 <translation id="851458219935658693">Atlasīta poga “Rādīt pašreizējās darbvietas logus”</translation>
 <translation id="8517041960877371778"><ph name="DEVICE_TYPE" /> ierīce, iespējams, netiks uzlādēta, kamēr tā būs ieslēgta.</translation>
 <translation id="8535393432370007982">Atsaukt kārtošanu pēc krāsas</translation>
+<translation id="8542053257095774575">Nav saglabātu darbvietu vai veidņu</translation>
 <translation id="8546059259582788728">Kārtošana sekmīgi atsaukta</translation>
 <translation id="8551588720239073785">Datuma un laika iestatījumi</translation>
 <translation id="8553395910833293175">Jau ir redzams visās darbvietās.</translation>
diff --git a/ash/strings/ash_strings_mn.xtb b/ash/strings/ash_strings_mn.xtb
index faa07ef4..6b177ef 100644
--- a/ash/strings/ash_strings_mn.xtb
+++ b/ash/strings/ash_strings_mn.xtb
@@ -252,6 +252,7 @@
 <translation id="243878895369688216">Өчигдөр нээсэн</translation>
 <translation id="2441427462554639370">Хадгалах сангийн зай хэт бага байгаа тул бичлэгийг дуусгасан</translation>
 <translation id="24452542372838207">Мэдэгдлийг дэлгэх</translation>
+<translation id="2449089818483227734">Батарей бага байна</translation>
 <translation id="2450205753526923158">Дэлгэцийн агшны горим</translation>
 <translation id="2456008742792828469">Календарь, <ph name="CURRENT_MONTH_YEAR" /></translation>
 <translation id="2473177541599297363">Нягтралыг баталгаажуулах</translation>
@@ -412,11 +413,13 @@
 <translation id="3441920967307853524"><ph name="RECEIVED_BYTES" />/<ph name="TOTAL_BYTES" /></translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> мин</translation>
 <translation id="3445925074670675829">USB-C төхөөрөмж</translation>
+<translation id="3455468639467374593">Загвар, <ph name="TEMPLATE_NAME" /></translation>
 <translation id="3465223694362104965">Таныг сүүлд нэвтэрснээс хойш энэ төхөөрөмжид өөр гар холбогдсон байна. Энэ гарыг ашиглахаасаа өмнө та итгэж болох эсэхээ шалгана уу.</translation>
 <translation id="3465356146291925647">Таны администратор удирддаг</translation>
 <translation id="3477079411857374384">Control-Shift-Space</translation>
 <translation id="3485319357743610354"><ph name="SECURITY_STATUS" />, <ph name="CONNECTION_STATUS" />, дохионы хүч <ph name="SIGNAL_STRENGTH" /></translation>
 <translation id="348799646910989694">Shelf-г автоматаар нууна</translation>
+<translation id="3505066820268455558">Батарейг цэнэглэж байна</translation>
 <translation id="3509391053705095206">Таны утсыг олох боломжгүй. Утасны тань Bluetooth асаалттай эсэхийг шалгана уу.</translation>
 <translation id="3510164367642747937">Хулганы курсорыг тодруулах</translation>
 <translation id="3513798432020909783"><ph name="MANAGER_EMAIL" />-н удирддаг бүртгэл</translation>
@@ -457,6 +460,8 @@
 <translation id="3633097874324966332">Төхөөрөмжөө хослуулахын тулд Bluetooth-н тохиргоог нээнэ үү</translation>
 <translation id="3638400994746983214">Нууцлалын дэлгэцийг асаах/унтраах. <ph name="STATE_TEXT" />.</translation>
 <translation id="3649505501900178324">Шинэчлэлтийн хугацаа хэтэрсэн</translation>
+<translation id="3659814201068740063">Ойролцоогоор <ph name="TIME_LEFT" /> үлдлээ (<ph name="PERCENTAGE" />%).
+Төхөөрөмжөө тэжээлд залгана уу.</translation>
 <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> Хяналттай хэрэглэгч</translation>
 <translation id="36813544980941320">Wi-Fi сүлжээг таны утас болон <ph name="DEVICE_NAME" />-н хооронд хуваалцана</translation>
 <translation id="3694122362646626770">Вебсайт</translation>
@@ -512,6 +517,7 @@
 <translation id="3962859241508114581">Өмнөх бичлэг</translation>
 <translation id="3969043077941541451">Унтраах</translation>
 <translation id="397105322502079400">Тооцоолж байна ...</translation>
+<translation id="397726367135689299">Батарейн цэнэглэлт найдваргүй байж болзошгүй.</translation>
 <translation id="3977512764614765090">Батарей <ph name="PERCENTAGE" />%-тай байгаа бөгөөд цэнэглэж байна.</translation>
 <translation id="3986082989454912832">Хариулах</translation>
 <translation id="3995138139523574647">USB-C төхөөрөмж (ард талын портын баруун тал)</translation>
@@ -1039,6 +1045,7 @@
 <translation id="7130207228079676353">ДАРАГДАХ МАГАДЛАЛТАЙ</translation>
 <translation id="7131634465328662194">Таныг автоматаар гаргана.</translation>
 <translation id="7143207342074048698">Холбож байна</translation>
+<translation id="7144942256906679589">Батарейн төлөв</translation>
 <translation id="7165278925115064263">Alt+Shift+K</translation>
 <translation id="7168224885072002358"><ph name="TIMEOUT_SECONDS" />-д хуучин хэмэжээнд нь буцааж оруулах</translation>
 <translation id="7180611975245234373">Дахин сэргээх</translation>
@@ -1105,6 +1112,7 @@
 <translation id="7593891976182323525">Search эсвэл Shift</translation>
 <translation id="7600875258240007829">Бүх мэдэгдлийг харах</translation>
 <translation id="7607002721634913082">зогссон</translation>
+<translation id="7609951632080598826">Календарийн харагдах байдал, <ph name="DATE" />, <ph name="TIME" /></translation>
 <translation id="7611213136657090146">Камер дахин холбогдсон.</translation>
 <translation id="7624117708979618027"><ph name="TEMPERATURE_F" />° F</translation>
 <translation id="7633755430369750696">Ойролцоо хуваалцах тохиргоог харуулна.</translation>
@@ -1230,6 +1238,7 @@
 <translation id="8345019317483336363"><ph name="WINDOW_TITLE" /> цонх сонгосон</translation>
 <translation id="8351131234907093545">Тэмдэглэл үүсгэх</translation>
 <translation id="8364673525741149932">Shelf Party-г асаана уу/унтраана уу. <ph name="STATE_TEXT" /></translation>
+<translation id="8369166482916924789">Хадгалсан дэлгэц, <ph name="SAVE_AND_RECALL_DESK_NAME" /></translation>
 <translation id="8371779926711439835">Нэг үсгээр урагшлуулах</translation>
 <translation id="8371991222807690464">Зочны горимд дагалдах төхөөрөмжийн гүйцэтгэлийг хязгаарласан байж магадгүй</translation>
 <translation id="8374601332003098278">Хэсэгчилсэн дэлгэц бичихийн тулд enter дээр дарна уу</translation>
@@ -1343,6 +1352,7 @@
 <translation id="9000771174482730261">ХАДГАЛАХ САНГ УДИРДАХ</translation>
 <translation id="9017320285115481645">Family Link-н эцэг эхийн нэвтрэх кодоо оруулна уу.</translation>
 <translation id="9024331582947483881">бүтэн дэлгэц</translation>
+<translation id="9029736946581028033">Төхөөрөмж удахгүй унтарна</translation>
 <translation id="9030319654231318877">Нар жаргах хүртэл унтраалттай</translation>
 <translation id="9034924485347205037">Linux-н файл</translation>
 <translation id="9047624247355796468"><ph name="NETWORK_NAME" />-н тохиргоог нээх</translation>
@@ -1372,6 +1382,7 @@
 <translation id="9168436347345867845">Үүнийг дараа хийх</translation>
 <translation id="9178475906033259337"><ph name="QUERY" />-н 1 илэрцийг үзүүлж байна</translation>
 <translation id="9179259655489829027">Тус онцлог нь танаас нууц үг шаардахгүйгээр таныг түргэн хугацаанд хэрэглэгчид хандах боломжийг олгоно. Энэ онцлогийг зөвхөн итгэдэг бүртгэлд ашиглана уу.</translation>
+<translation id="9180906851711123156">Хаахын тулд Ctrl+W дээр дарна уу</translation>
 <translation id="9183456764293710005">Бүтэн дэлгэц томруулагч</translation>
 <translation id="9193626018745640770">Үл мэдэгдэх хүлээн авагчид дамжуулж байна</translation>
 <translation id="9194617393863864469">Өөр дансаар нэвтрэх...</translation>
diff --git a/ash/strings/ash_strings_mr.xtb b/ash/strings/ash_strings_mr.xtb
index 9bd13716..2a0498e 100644
--- a/ash/strings/ash_strings_mr.xtb
+++ b/ash/strings/ash_strings_mr.xtb
@@ -252,6 +252,7 @@
 <translation id="243878895369688216">काल उघडलेली</translation>
 <translation id="2441427462554639370">स्टोरेज जागा अतिशय कमी असल्यामुळे रेकॉर्डिंग संपले</translation>
 <translation id="24452542372838207">सूचना विस्तार करा</translation>
+<translation id="2449089818483227734">बॅटरी कमी आहे</translation>
 <translation id="2450205753526923158">स्क्रीनशॉट मोड</translation>
 <translation id="2456008742792828469">कॅलेंडर, <ph name="CURRENT_MONTH_YEAR" /></translation>
 <translation id="2473177541599297363">रेझोल्यूशनची खात्री करा</translation>
@@ -412,11 +413,13 @@
 <translation id="3441920967307853524"><ph name="RECEIVED_BYTES" />/<ph name="TOTAL_BYTES" /></translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> मिनिटे</translation>
 <translation id="3445925074670675829">USB-C डिव्‍हाइस</translation>
+<translation id="3455468639467374593">टेंप्लेट, <ph name="TEMPLATE_NAME" /></translation>
 <translation id="3465223694362104965">तुम्ही शेवटचे साइन इन केल्यापासून या डिव्हाइसवर दुसरा कीबोर्ड कनेक्ट करण्यात आला आहे. तो वापरण्यापूर्वी तुमचा या कीबोर्डवर विश्वास असल्याची खात्री करा.</translation>
 <translation id="3465356146291925647">तुमच्या अ‍ॅडमिनिस्ट्रेटरने व्यवस्थापित केलेले</translation>
 <translation id="3477079411857374384">Control-Shift-Space</translation>
 <translation id="3485319357743610354"><ph name="SECURITY_STATUS" />, <ph name="CONNECTION_STATUS" />, सिग्नल क्षमता <ph name="SIGNAL_STRENGTH" /></translation>
 <translation id="348799646910989694">शेल्फ आपोआप लपवले</translation>
+<translation id="3505066820268455558">बॅटरी चार्ज होत आहे</translation>
 <translation id="3509391053705095206">तुमचा फोन शोधू शकत नाही. तुमच्या फोनचे ब्लूटूथ सुरू असल्याची खात्री करा.</translation>
 <translation id="3510164367642747937">माउसचा कर्सर हायलाइट करा</translation>
 <translation id="3513798432020909783">खाते <ph name="MANAGER_EMAIL" /> ने व्‍यवस्‍थापित केले आहे</translation>
@@ -457,6 +460,8 @@
 <translation id="3633097874324966332">तुमचे डिव्हाइस पेअर करण्यासाठी ब्लूटूथ सेटिंग्ज उघडा</translation>
 <translation id="3638400994746983214">गोपनीयता स्क्रीन टॉगल करा. <ph name="STATE_TEXT" />.</translation>
 <translation id="3649505501900178324">अपडेटची मुदत संपली आहे</translation>
+<translation id="3659814201068740063">सुमारे <ph name="TIME_LEFT" /> शिल्लक (<ph name="PERCENTAGE" />%).
+तुमचे डिव्हाइस पॉवरशी कनेक्ट करा.</translation>
 <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> व्यवस्थापित वापरकर्ता</translation>
 <translation id="36813544980941320">तुमचा फोन आणि <ph name="DEVICE_NAME" /> यांच्या दरम्यान वाय-फाय नेटवर्क शेअर केली जातील</translation>
 <translation id="3694122362646626770">वेबसाइट</translation>
@@ -511,6 +516,7 @@
 <translation id="3962859241508114581">मागील ट्रॅक</translation>
 <translation id="3969043077941541451">बंद आहे</translation>
 <translation id="397105322502079400">गणना करत आहे...</translation>
+<translation id="397726367135689299">बॅटरी चार्जिंग बेभरवशाचे असू शकते.</translation>
 <translation id="3977512764614765090">बॅटरी <ph name="PERCENTAGE" />% वर आहे आणि चार्ज होत आहे.</translation>
 <translation id="3986082989454912832">उत्तर</translation>
 <translation id="3995138139523574647">USB-C डिव्‍हाइस (उजव्या बाजूचे मागील पोर्ट)</translation>
@@ -1038,6 +1044,7 @@
 <translation id="7130207228079676353">सर्वाधिक शक्यता</translation>
 <translation id="7131634465328662194">तुम्हाला आपोआप साइन आउट केले जाईल.</translation>
 <translation id="7143207342074048698">कनेक्ट करत आहे</translation>
+<translation id="7144942256906679589">बॅटरीची स्थिती</translation>
 <translation id="7165278925115064263">Alt+Shift+K</translation>
 <translation id="7168224885072002358"><ph name="TIMEOUT_SECONDS" /> मध्ये जुन्या रिझोल्युशनवर परत करत आहे</translation>
 <translation id="7180611975245234373">रिफ्रेश करा</translation>
@@ -1104,6 +1111,7 @@
 <translation id="7593891976182323525">Search किंवा Shift</translation>
 <translation id="7600875258240007829">सर्व सूचना पहा</translation>
 <translation id="7607002721634913082">विराम द्या</translation>
+<translation id="7609951632080598826">कॅलेंडर दृश्य, <ph name="DATE" />, <ph name="TIME" /></translation>
 <translation id="7611213136657090146">कॅमेरा पुन्हा कनेक्ट केला.</translation>
 <translation id="7624117708979618027"><ph name="TEMPERATURE_F" />° फॅ</translation>
 <translation id="7633755430369750696">Nearby सह शेअरिंग सेटिंग्ज दाखवा.</translation>
@@ -1229,6 +1237,7 @@
 <translation id="8345019317483336363"><ph name="WINDOW_TITLE" /> विंडो निवडली</translation>
 <translation id="8351131234907093545">टीप तयार करा</translation>
 <translation id="8364673525741149932">शेल्फ पार्टी टॉगल करा. <ph name="STATE_TEXT" /></translation>
+<translation id="8369166482916924789">सेव्ह केलेला डेस्‍क, <ph name="SAVE_AND_RECALL_DESK_NAME" /></translation>
 <translation id="8371779926711439835">एक अक्षर पुढे जा</translation>
 <translation id="8371991222807690464">अतिथी मोडमध्ये पेरिफेरल परफॉर्मन्स मर्यादित असू शकतो</translation>
 <translation id="8374601332003098278">आंशिक स्क्रीन रेकॉर्ड करण्यासाठी एंटर दाबा</translation>
@@ -1341,6 +1350,7 @@
 <translation id="9000771174482730261">स्टोरेज व्यवस्थापित करा</translation>
 <translation id="9017320285115481645">Family Link पालक ॲक्सेस कोड एंटर करा.</translation>
 <translation id="9024331582947483881">फुल स्क्रीन</translation>
+<translation id="9029736946581028033">डिव्हाइसची पॉवर लवकरच संपेल</translation>
 <translation id="9030319654231318877">सूर्यास्तापर्यंत बंद</translation>
 <translation id="9034924485347205037">Linux फाइल</translation>
 <translation id="9047624247355796468"><ph name="NETWORK_NAME" /> साठी सेटिंग्ज उघडा</translation>
@@ -1371,6 +1381,7 @@
 <translation id="9168436347345867845">ते नंतर करा</translation>
 <translation id="9178475906033259337"><ph name="QUERY" /> साठी एक परिणाम दाखवत आहे</translation>
 <translation id="9179259655489829027">हे वैशिष्ट्य तुम्हाला पासवर्ड शिवाय कोणत्याही साइन-इन केलेल्या वापरकर्त्यास जलदपणे ॲक्सेस करण्याची परवानगी  देते. तुमचा विश्वास असलेल्या खात्यांसाठीच फक्त या वैशिष्ट्याचा वापर करा.</translation>
+<translation id="9180906851711123156">बंद करण्यासाठी Ctrl+W दाबा</translation>
 <translation id="9183456764293710005">फुल-स्क्रीन मॅग्निफायर</translation>
 <translation id="9193626018745640770">एका अज्ञात मिळवणाऱ्यावर कास्ट करत आहे</translation>
 <translation id="9194617393863864469">दुसरा वापरकर्ता साइन इन करा...</translation>
diff --git a/ash/strings/ash_strings_no.xtb b/ash/strings/ash_strings_no.xtb
index da698b7..6c408e1 100644
--- a/ash/strings/ash_strings_no.xtb
+++ b/ash/strings/ash_strings_no.xtb
@@ -1060,6 +1060,7 @@
 <translation id="7348093485538360975">Skjermtastatur</translation>
 <translation id="735745346212279324">VPN frakoblet</translation>
 <translation id="7360036564632145207">Hvis du endrer innstillingen for datatilgangsbeskyttelse for eksterne enheter, kan det optimalisere ytelsen</translation>
+<translation id="736045644501761622">Angi bakgrunn og stil</translation>
 <translation id="7371404428569700291">Ta opp vinduet</translation>
 <translation id="7377169924702866686">Caps Lock er på.</translation>
 <translation id="7377481913241237033">Tilknytt med en kode</translation>
@@ -1294,6 +1295,7 @@
 <translation id="8721053961083920564">Slå lyden av/på. <ph name="STATE_TEXT" /></translation>
 <translation id="8724318433625452070">Skjermdump av hele skjermen</translation>
 <translation id="8734991477317290293">Det brukes kanskje til å stjele tastetrykkene dine.</translation>
+<translation id="8735678380411481005">Farge på tastaturets bakgrunnsbelysning</translation>
 <translation id="8735953464173050365">Vis tastaturinnstillinger. <ph name="KEYBOARD_NAME" /> er valgt</translation>
 <translation id="8755498163081687682">Verifiser identiteten din: <ph name="ORIGIN_NAME" /> vil bekrefte at det er deg</translation>
 <translation id="875593634123171288">Vis innstillinger for VPN</translation>
diff --git a/ash/strings/ash_strings_or.xtb b/ash/strings/ash_strings_or.xtb
index 7176e6d..4d2f7a9 100644
--- a/ash/strings/ash_strings_or.xtb
+++ b/ash/strings/ash_strings_or.xtb
@@ -1059,6 +1059,7 @@
 <translation id="7348093485538360975">ଅନ୍-ସ୍କ୍ରିନ୍ କୀ'ବୋର୍ଡ</translation>
 <translation id="735745346212279324">VPN ବିଚ୍ଛିନ୍ନ ହୋଇଛି</translation>
 <translation id="7360036564632145207">ପେରିଫେରାଲଗୁଡ଼ିକ ପାଇଁ ଆପଣଙ୍କ ଡାଟା ଆକ୍ସେସ୍ ସୁରକ୍ଷା ସେଟିଂରେ ପରିବର୍ତ୍ତନ କରି ପରଫରମାନ୍ସକୁ ଅପ୍ଟିମାଇଜ୍ କରାଯାଇପାରିବ</translation>
+<translation id="736045644501761622">ୱାଲପେପର ଏବଂ ଷ୍ଟାଇଲ ସେଟ କରନ୍ତୁ</translation>
 <translation id="7371404428569700291">ୱିଣ୍ଡୋ ରେକର୍ଡ କରନ୍ତୁ</translation>
 <translation id="7377169924702866686">କ୍ୟାପ୍ସ ଲକ୍ ଅନ୍ ଅଛି।</translation>
 <translation id="7377481913241237033">ଏକ କୋଡ ମାଧ୍ୟମରେ ସଂଯୋଗ କରନ୍ତୁ</translation>
@@ -1293,6 +1294,7 @@
 <translation id="8721053961083920564">ଭଲ୍ୟୁମ୍ ଟୋଗଲ୍ କରନ୍ତୁ। <ph name="STATE_TEXT" /></translation>
 <translation id="8724318433625452070">ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ୍ କ୍ୟାପଚର୍</translation>
 <translation id="8734991477317290293">ଆପଣଙ୍କ କୀ'ଷ୍ଟ୍ରୋକ୍‌କୁ ଚୋରି କରିବାକୁ ଏହା ଏକ ପ୍ରୟାସ ହୋଇପାରେ</translation>
+<translation id="8735678380411481005">କୀବୋର୍ଡ ବ୍ୟାକଲାଇଟ ରଙ୍ଗ</translation>
 <translation id="8735953464173050365">କୀ'ବୋର୍ଡ ସେଟିଂ‌ସ୍ ଦେଖାନ୍ତୁ। <ph name="KEYBOARD_NAME" />କୁ ଚୟନ କରାଯାଇଛି</translation>
 <translation id="8755498163081687682">ଆପଣଙ୍କ ପରିଚୟ ଯାଞ୍ଚ କରନ୍ତୁ: ଏହା ଆପଣ ଅଟନ୍ତି ବୋଲି <ph name="ORIGIN_NAME" /> ସୁନିଶ୍ଚିତ କରିବାକୁ ଚାହୁଁଛି</translation>
 <translation id="875593634123171288">VPN ସେଟିଂସ୍‌ ଦେଖାନ୍ତୁ</translation>
diff --git a/ash/strings/ash_strings_pa.xtb b/ash/strings/ash_strings_pa.xtb
index 7a6fef5..1d093e8 100644
--- a/ash/strings/ash_strings_pa.xtb
+++ b/ash/strings/ash_strings_pa.xtb
@@ -1061,6 +1061,7 @@
 <translation id="7348093485538360975">ਔਨ-ਸਕ੍ਰੀਨ ਕੀ-ਬੋਰਡ</translation>
 <translation id="735745346212279324">VPN ਡਿਸਕਨੈਕਟ ਹੋ ਗਿਆ</translation>
 <translation id="7360036564632145207">ਪੈਰੀਫੈਰਲ ਸੈਟਿੰਗਾਂ ਲਈ ਆਪਣੀ ਡਾਟਾ ਪਹੁੰਚ ਸੁਰੱਖਿਆ ਨੂੰ ਬਦਲਣ ਨਾਲ ਕਾਰਗੁਜ਼ਾਰੀ ਨੂੰ ਸੁਯੋਗ ਬਣਾਇਆ ਜਾ ਸਕਦਾ ਹੈ</translation>
+<translation id="736045644501761622">ਵਾਲਪੇਪਰ ਅਤੇ ਸਟਾਈਲ ਸੈੱਟ ਕਰੋ</translation>
 <translation id="7371404428569700291">ਰਿਕਾਰਡ ਵਿੰਡੋ</translation>
 <translation id="7377169924702866686">Caps Lock ਚਾਲੂ ਹੈ।</translation>
 <translation id="7377481913241237033">ਕੋਡ ਨਾਲ ਕਨੈਕਟ ਕਰੋ</translation>
@@ -1295,6 +1296,7 @@
 <translation id="8721053961083920564">ਅਵਾਜ਼ ਨੂੰ ਟੌਗਲ ਕਰੋ। <ph name="STATE_TEXT" /></translation>
 <translation id="8724318433625452070">ਪੂਰੀ-ਸਕ੍ਰੀਨ ਕੈਪਚਰ</translation>
 <translation id="8734991477317290293">ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਇਹ ਤੁਹਾਡੇ ਕੀਸਟ੍ਰੋਕ ਚੋਰੀ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰ ਰਿਹਾ ਹੋਵੇ</translation>
+<translation id="8735678380411481005">ਕੀ-ਬੋਰਡ ਦੀ ਬੈਕਲਾਈਟ ਦਾ ਰੰਗ</translation>
 <translation id="8735953464173050365">ਕੀ-ਬੋਰਡ ਸੈਟਿੰਗਾਂ ਦਿਖਾਓ। <ph name="KEYBOARD_NAME" /> ਚੁਣਿਆ ਹੋਇਆ ਹੈ</translation>
 <translation id="8755498163081687682">ਆਪਣੀ ਪਛਾਣ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ: <ph name="ORIGIN_NAME" /> ਤੁਹਾਡੀ ਪਛਾਣ ਦੀ ਪੁਸ਼ਟੀ ਕਰਨਾ ਚਾਹੁੰਦੀ ਹੈ</translation>
 <translation id="875593634123171288">VPN ਸੈਟਿੰਗਾਂ ਦਿਖਾਓ</translation>
diff --git a/ash/strings/ash_strings_pl.xtb b/ash/strings/ash_strings_pl.xtb
index b37a640..94353623 100644
--- a/ash/strings/ash_strings_pl.xtb
+++ b/ash/strings/ash_strings_pl.xtb
@@ -252,6 +252,7 @@
 <translation id="243878895369688216">Otwierane wczoraj</translation>
 <translation id="2441427462554639370">Nagrywanie zostało zakończone z powodu krytycznie małej ilości dostępnego miejsca</translation>
 <translation id="24452542372838207">Rozwiń powiadomienie</translation>
+<translation id="2449089818483227734">Słaba bateria</translation>
 <translation id="2450205753526923158">Tryb zrzutu ekranu</translation>
 <translation id="2456008742792828469">Kalendarz, <ph name="CURRENT_MONTH_YEAR" /></translation>
 <translation id="2473177541599297363">Potwierdź rozdzielczość</translation>
@@ -412,11 +413,13 @@
 <translation id="3441920967307853524"><ph name="RECEIVED_BYTES" />/<ph name="TOTAL_BYTES" /></translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> min</translation>
 <translation id="3445925074670675829">Urządzenie USB-C</translation>
+<translation id="3455468639467374593">Szablon, <ph name="TEMPLATE_NAME" /></translation>
 <translation id="3465223694362104965">Od czasu Twojego ostatniego logowania do tego urządzenia podłączono inną klawiaturę. Zanim jej użyjesz, upewnij się, że masz do niej zaufanie.</translation>
 <translation id="3465356146291925647">Zarządzana przez administratora</translation>
 <translation id="3477079411857374384">Control+Shift+spacja</translation>
 <translation id="3485319357743610354"><ph name="SECURITY_STATUS" />, <ph name="CONNECTION_STATUS" />, siła sygnału: <ph name="SIGNAL_STRENGTH" /></translation>
 <translation id="348799646910989694">Półka ukryta automatycznie</translation>
+<translation id="3505066820268455558">Bateria się ładuje</translation>
 <translation id="3509391053705095206">Nie udało się znaleźć telefonu. Sprawdź, czy jest na nim włączony Bluetooth.</translation>
 <translation id="3510164367642747937">Podświetlaj wskaźnik myszy</translation>
 <translation id="3513798432020909783">Kontem zarządza <ph name="MANAGER_EMAIL" /></translation>
@@ -457,6 +460,8 @@
 <translation id="3633097874324966332">Otwórz ustawienia Bluetooth, aby sparować urządzenie</translation>
 <translation id="3638400994746983214">Przełącz ekran chroniący prywatność. <ph name="STATE_TEXT" />.</translation>
 <translation id="3649505501900178324">Zaległa aktualizacja</translation>
+<translation id="3659814201068740063">Pozostało około <ph name="TIME_LEFT" /> (<ph name="PERCENTAGE" />%).
+Podłącz urządzenie do zasilania.</translation>
 <translation id="366222428570480733">Użytkownik zarządzany <ph name="USER_EMAIL_ADDRESS" /></translation>
 <translation id="36813544980941320">Twój telefon i <ph name="DEVICE_NAME" /> będą wspólnie korzystać z sieci Wi-Fi</translation>
 <translation id="3694122362646626770">Witryny</translation>
@@ -511,6 +516,7 @@
 <translation id="3962859241508114581">Poprzedni utwór</translation>
 <translation id="3969043077941541451">Wyłączone</translation>
 <translation id="397105322502079400">Obliczanie...</translation>
+<translation id="397726367135689299">Ładowanie baterii może przebiegać nieprawidłowo.</translation>
 <translation id="3977512764614765090">Naładowanie baterii: <ph name="PERCENTAGE" />%. Trwa ładowanie.</translation>
 <translation id="3986082989454912832">Odpowiedz</translation>
 <translation id="3995138139523574647">Urządzenie USB-C (tylny port na prawym boku)</translation>
@@ -1037,6 +1043,7 @@
 <translation id="7130207228079676353">NAJBARDZIEJ PRAWDOPODOBNE</translation>
 <translation id="7131634465328662194">Nastąpi automatyczne wylogowanie.</translation>
 <translation id="7143207342074048698">Łączenie</translation>
+<translation id="7144942256906679589">Stan baterii</translation>
 <translation id="7165278925115064263">Alt + Shift + K</translation>
 <translation id="7168224885072002358">Powrót do wcześniejszej rozdzielczości za <ph name="TIMEOUT_SECONDS" /></translation>
 <translation id="7180611975245234373">Odśwież</translation>
@@ -1103,6 +1110,7 @@
 <translation id="7593891976182323525">Szukaj lub Shift</translation>
 <translation id="7600875258240007829">Zobacz wszystkie powiadomienia</translation>
 <translation id="7607002721634913082">Wstrzymano</translation>
+<translation id="7609951632080598826">Widok kalendarza, <ph name="DATE" />, <ph name="TIME" /></translation>
 <translation id="7611213136657090146">Kamera została ponownie połączona.</translation>
 <translation id="7624117708979618027"><ph name="TEMPERATURE_F" />° F</translation>
 <translation id="7633755430369750696">Pokaż ustawienia Udostępniania w pobliżu.</translation>
@@ -1228,6 +1236,7 @@
 <translation id="8345019317483336363">Wybrano okno <ph name="WINDOW_TITLE" /></translation>
 <translation id="8351131234907093545">Utwórz notatkę</translation>
 <translation id="8364673525741149932">Przełączanie trybu Shelf Party. <ph name="STATE_TEXT" /></translation>
+<translation id="8369166482916924789">Zapisane biurko, <ph name="SAVE_AND_RECALL_DESK_NAME" /></translation>
 <translation id="8371779926711439835">Do przodu o jedną literę</translation>
 <translation id="8371991222807690464">W trybie gościa urządzenia peryferyjne mogą działać mniej wydajnie.</translation>
 <translation id="8374601332003098278">Aby nagrać fragment ekranu, naciśnij Enter</translation>
@@ -1340,6 +1349,7 @@
 <translation id="9000771174482730261">ZARZĄDZAJ MIEJSCEM NA DANE</translation>
 <translation id="9017320285115481645">Wpisz kod dostępu rodzica w Family Link.</translation>
 <translation id="9024331582947483881">pełny ekran</translation>
+<translation id="9029736946581028033">Urządzenie wkrótce straci zasilanie</translation>
 <translation id="9030319654231318877">Wyłączony do zachodu słońca</translation>
 <translation id="9034924485347205037">Pliki Linuksa</translation>
 <translation id="9047624247355796468">Otwórz ustawienia sieci <ph name="NETWORK_NAME" /></translation>
@@ -1369,6 +1379,7 @@
 <translation id="9168436347345867845">Później</translation>
 <translation id="9178475906033259337">Wyświetlam 1 wynik dla zapytania <ph name="QUERY" /></translation>
 <translation id="9179259655489829027">Ta funkcja umożliwia szybki dostęp do każdego konta zalogowanego użytkownika bez konieczności podawania hasła. Używaj jej tylko w przypadku kont, którym ufasz.</translation>
+<translation id="9180906851711123156">Aby zamknąć, naciśnij Ctrl+W</translation>
 <translation id="9183456764293710005">Lupa pełnego ekranu</translation>
 <translation id="9193626018745640770">Przesyłam do nieznanego odbiornika</translation>
 <translation id="9194617393863864469">Zaloguj innego użytkownika...</translation>
diff --git a/ash/strings/ash_strings_pt-BR.xtb b/ash/strings/ash_strings_pt-BR.xtb
index f454420..4e3cd373 100644
--- a/ash/strings/ash_strings_pt-BR.xtb
+++ b/ash/strings/ash_strings_pt-BR.xtb
@@ -252,6 +252,7 @@
 <translation id="243878895369688216">Aberto ontem</translation>
 <translation id="2441427462554639370">A gravação foi encerrada porque há pouco espaço de armazenamento</translation>
 <translation id="24452542372838207">Expandir notificação</translation>
+<translation id="2449089818483227734">Pouca bateria</translation>
 <translation id="2450205753526923158">Modo de captura de tela</translation>
 <translation id="2456008742792828469">Agenda, <ph name="CURRENT_MONTH_YEAR" /></translation>
 <translation id="2473177541599297363">Confirmar resolução</translation>
@@ -412,11 +413,13 @@
 <translation id="3441920967307853524"><ph name="RECEIVED_BYTES" />/<ph name="TOTAL_BYTES" /></translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> minutos</translation>
 <translation id="3445925074670675829">Dispositivo USB-C</translation>
+<translation id="3455468639467374593">Modelo: <ph name="TEMPLATE_NAME" /></translation>
 <translation id="3465223694362104965">Outro teclado foi conectado a este dispositivo desde seu último acesso. Verifique se esse teclado é confiável antes de usá-lo.</translation>
 <translation id="3465356146291925647">Gerenciado pelo seu administrador</translation>
 <translation id="3477079411857374384">Control-Shift-Espaço</translation>
 <translation id="3485319357743610354"><ph name="SECURITY_STATUS" />, <ph name="CONNECTION_STATUS" />, intensidade do sinal em <ph name="SIGNAL_STRENGTH" /></translation>
 <translation id="348799646910989694">Estante automaticamente oculta</translation>
+<translation id="3505066820268455558">Carregando bateria</translation>
 <translation id="3509391053705095206">Não foi possível encontrar o smartphone. Confira se o Bluetooth está ativado.</translation>
 <translation id="3510164367642747937">Destacar cursor do mouse</translation>
 <translation id="3513798432020909783">Conta gerenciada por <ph name="MANAGER_EMAIL" /></translation>
@@ -457,6 +460,8 @@
 <translation id="3633097874324966332">Abra as configurações do Bluetooth se quiser parear o dispositivo</translation>
 <translation id="3638400994746983214">Alternar tela de privacidade. <ph name="STATE_TEXT" /></translation>
 <translation id="3649505501900178324">Atualização atrasada</translation>
+<translation id="3659814201068740063">Tempo restante: cerca de <ph name="TIME_LEFT" /> (<ph name="PERCENTAGE" />%).
+Conecte o dispositivo a uma fonte de energia.</translation>
 <translation id="366222428570480733">Usuário gerenciado <ph name="USER_EMAIL_ADDRESS" /></translation>
 <translation id="36813544980941320">Redes Wi-Fi serão compartilhadas entre seu smartphone e o <ph name="DEVICE_NAME" /></translation>
 <translation id="3694122362646626770">Websites</translation>
@@ -511,6 +516,7 @@
 <translation id="3962859241508114581">Faixa anterior</translation>
 <translation id="3969043077941541451">Desativado</translation>
 <translation id="397105322502079400">Calculando...</translation>
+<translation id="397726367135689299">O carregamento da bateria pode não ser confiável.</translation>
 <translation id="3977512764614765090">Bateria em <ph name="PERCENTAGE" />% e carregando.</translation>
 <translation id="3986082989454912832">Atender</translation>
 <translation id="3995138139523574647">Dispositivo USB-C (porta traseira da direita)</translation>
@@ -1038,6 +1044,7 @@
 <translation id="7130207228079676353">MUITO PROVAVELMENTE</translation>
 <translation id="7131634465328662194">Você será automaticamente desconectado.</translation>
 <translation id="7143207342074048698">Conectando</translation>
+<translation id="7144942256906679589">Status da bateria</translation>
 <translation id="7165278925115064263">Alt+Shift+K</translation>
 <translation id="7168224885072002358">Revertendo para resolução anterior em <ph name="TIMEOUT_SECONDS" /></translation>
 <translation id="7180611975245234373">Atualizar</translation>
@@ -1060,6 +1067,7 @@
 <translation id="7348093485538360975">Teclado virtual</translation>
 <translation id="735745346212279324">VPN desconectada</translation>
 <translation id="7360036564632145207">Mudar sua configuração de proteção de acesso a dados para periféricos pode otimizar o desempenho</translation>
+<translation id="736045644501761622">Definir Estilo e fundo de tela</translation>
 <translation id="7371404428569700291">Gravar janela</translation>
 <translation id="7377169924702866686">O Caps Lock está ativado.</translation>
 <translation id="7377481913241237033">Conectar com um código</translation>
@@ -1103,6 +1111,7 @@
 <translation id="7593891976182323525">Pesquisar ou Shift</translation>
 <translation id="7600875258240007829">Ver todas as notificações</translation>
 <translation id="7607002721634913082">Pausado</translation>
+<translation id="7609951632080598826">Visualização da agenda (<ph name="DATE" />, <ph name="TIME" />)</translation>
 <translation id="7611213136657090146">Câmera reconectada.</translation>
 <translation id="7624117708979618027"><ph name="TEMPERATURE_F" /> °F</translation>
 <translation id="7633755430369750696">Mostrar configurações de Compartilhar por proximidade.</translation>
@@ -1228,6 +1237,7 @@
 <translation id="8345019317483336363">Janela <ph name="WINDOW_TITLE" /> selecionada</translation>
 <translation id="8351131234907093545">Criar nota</translation>
 <translation id="8364673525741149932">Alterne o modo Grupo de estantes. <ph name="STATE_TEXT" /></translation>
+<translation id="8369166482916924789">Espaço de trabalho salvo: <ph name="SAVE_AND_RECALL_DESK_NAME" /></translation>
 <translation id="8371779926711439835">Avançar por letra</translation>
 <translation id="8371991222807690464">O desempenho dos periféricos pode ser limitado no modo visitante</translation>
 <translation id="8374601332003098278">Pressione "Enter" para gravar a tela parcialmente</translation>
@@ -1294,6 +1304,7 @@
 <translation id="8721053961083920564">Altere o volume. <ph name="STATE_TEXT" /></translation>
 <translation id="8724318433625452070">Captura de tela cheia</translation>
 <translation id="8734991477317290293">Ele pode estar tentando capturar sua digitação</translation>
+<translation id="8735678380411481005">Cor da luz de fundo do teclado</translation>
 <translation id="8735953464173050365">Mostrar configurações do teclado. <ph name="KEYBOARD_NAME" /> está selecionado</translation>
 <translation id="8755498163081687682">Verifique sua identidade: <ph name="ORIGIN_NAME" /> quer confirmar que é você</translation>
 <translation id="875593634123171288">Mostrar configurações de VPN</translation>
@@ -1339,6 +1350,7 @@
 <translation id="9000771174482730261">GERENCIE O ARMAZENAMENTO</translation>
 <translation id="9017320285115481645">Insira o código de acesso do familiar responsável do Family Link.</translation>
 <translation id="9024331582947483881">tela cheia</translation>
+<translation id="9029736946581028033">O dispositivo vai desligar em breve</translation>
 <translation id="9030319654231318877">Desativado até o pôr do sol</translation>
 <translation id="9034924485347205037">Arquivos do Linux</translation>
 <translation id="9047624247355796468">Abrir configurações de <ph name="NETWORK_NAME" /></translation>
@@ -1368,6 +1380,7 @@
 <translation id="9168436347345867845">Mais tarde</translation>
 <translation id="9178475906033259337">Exibindo 1 resultado para <ph name="QUERY" /></translation>
 <translation id="9179259655489829027">Este recurso permite acessar rapidamente qualquer usuário conectado sem a necessidade de uma senha. Use esse recurso somente com contas em que você confia.</translation>
+<translation id="9180906851711123156">Pressione Ctrl+W para fechar</translation>
 <translation id="9183456764293710005">Lupa de tela cheia</translation>
 <translation id="9193626018745640770">Transmitindo para um destinatário desconhecido</translation>
 <translation id="9194617393863864469">Fazer login com outro usuário...</translation>
diff --git a/ash/strings/ash_strings_pt-PT.xtb b/ash/strings/ash_strings_pt-PT.xtb
index f97adef3..2a76e82a 100644
--- a/ash/strings/ash_strings_pt-PT.xtb
+++ b/ash/strings/ash_strings_pt-PT.xtb
@@ -252,6 +252,7 @@
 <translation id="243878895369688216">Aberto ontem</translation>
 <translation id="2441427462554639370">A gravação terminou porque o espaço de armazenamento está criticamente baixo</translation>
 <translation id="24452542372838207">Expandir notificação</translation>
+<translation id="2449089818483227734">Bateria fraca</translation>
 <translation id="2450205753526923158">Modo de captura de ecrã</translation>
 <translation id="2456008742792828469">Calendário, <ph name="CURRENT_MONTH_YEAR" /></translation>
 <translation id="2473177541599297363">Confirme a resolução</translation>
@@ -412,11 +413,13 @@
 <translation id="3441920967307853524"><ph name="RECEIVED_BYTES" />/<ph name="TOTAL_BYTES" /></translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> min</translation>
 <translation id="3445925074670675829">Dispositivo USB-C</translation>
+<translation id="3455468639467374593">Modelo, <ph name="TEMPLATE_NAME" /></translation>
 <translation id="3465223694362104965">Foi ligado outro teclado a este dispositivo desde o seu último acesso. Certifique-se de que confia neste teclado antes de o utilizar.</translation>
 <translation id="3465356146291925647">Gerida pelo administrador</translation>
 <translation id="3477079411857374384">Control-Shift-Espaço</translation>
 <translation id="3485319357743610354"><ph name="SECURITY_STATUS" />, <ph name="CONNECTION_STATUS" />, intensidade do sinal: <ph name="SIGNAL_STRENGTH" /></translation>
 <translation id="348799646910989694">Ocultação automática da prateleira</translation>
+<translation id="3505066820268455558">A carregar a bateria</translation>
 <translation id="3509391053705095206">Não é possível encontrar o telemóvel. Certifique-se de que o Bluetooth do telemóvel está ativado.</translation>
 <translation id="3510164367642747937">Realçar cursor do rato</translation>
 <translation id="3513798432020909783">Conta gerida por <ph name="MANAGER_EMAIL" />.</translation>
@@ -457,6 +460,8 @@
 <translation id="3633097874324966332">Abra as definições do Bluetooth para sincronizar o seu dispositivo</translation>
 <translation id="3638400994746983214">Ative/desative o ecrã de privacidade. <ph name="STATE_TEXT" />.</translation>
 <translation id="3649505501900178324">Atualização vencida</translation>
+<translation id="3659814201068740063">Resta(m) cerca de <ph name="TIME_LEFT" /> (<ph name="PERCENTAGE" />%).
+Ligue o dispositivo à corrente.</translation>
 <translation id="366222428570480733">Utilizador gerido por <ph name="USER_EMAIL_ADDRESS" /></translation>
 <translation id="36813544980941320">As redes Wi-Fi serão partilhadas entre o seu telemóvel e o dispositivo <ph name="DEVICE_NAME" />.</translation>
 <translation id="3694122362646626770">Sites</translation>
@@ -511,6 +516,7 @@
 <translation id="3962859241508114581">Faixa anterior</translation>
 <translation id="3969043077941541451">Desativado</translation>
 <translation id="397105322502079400">A calcular...</translation>
+<translation id="397726367135689299">O carregamento da bateria pode ser instável.</translation>
 <translation id="3977512764614765090">A bateria está <ph name="PERCENTAGE" />% cheia e a carregar.</translation>
 <translation id="3986082989454912832">Atender</translation>
 <translation id="3995138139523574647">Dispositivo USB-C (porta traseira do lado direito)</translation>
@@ -1038,6 +1044,7 @@
 <translation id="7130207228079676353">MUITO PROVAVELMENTE</translation>
 <translation id="7131634465328662194">A sessão será terminada automaticamente.</translation>
 <translation id="7143207342074048698">A ligar</translation>
+<translation id="7144942256906679589">Estado da bateria</translation>
 <translation id="7165278925115064263">Alt+Shift+K</translation>
 <translation id="7168224885072002358">A reverter para a resolução antiga dentro de <ph name="TIMEOUT_SECONDS" /></translation>
 <translation id="7180611975245234373">Atualizar</translation>
@@ -1103,6 +1110,7 @@
 <translation id="7593891976182323525">Pesquisar ou Shift</translation>
 <translation id="7600875258240007829">Ver todas as notificações</translation>
 <translation id="7607002721634913082">Em pausa</translation>
+<translation id="7609951632080598826">Vista de calendário, <ph name="DATE" />, <ph name="TIME" /></translation>
 <translation id="7611213136657090146">A câmara restabeleceu a ligação.</translation>
 <translation id="7624117708979618027"><ph name="TEMPERATURE_F" /> °F</translation>
 <translation id="7633755430369750696">Mostre as definições da funcionalidade Partilhar na proximidade.</translation>
@@ -1228,6 +1236,7 @@
 <translation id="8345019317483336363">Janela <ph name="WINDOW_TITLE" /> selecionada</translation>
 <translation id="8351131234907093545">Criar nota</translation>
 <translation id="8364673525741149932">Ative/desative o Shelf Party. <ph name="STATE_TEXT" /></translation>
+<translation id="8369166482916924789">Espaço de trabalho guardado, <ph name="SAVE_AND_RECALL_DESK_NAME" /></translation>
 <translation id="8371779926711439835">Avançar por letra</translation>
 <translation id="8371991222807690464">O desempenho periférico pode estar limitado no Modo convidado.</translation>
 <translation id="8374601332003098278">Prima Enter para gravar o ecrã parcial</translation>
@@ -1339,6 +1348,7 @@
 <translation id="9000771174482730261">GERIR ARMAZENAMENTO</translation>
 <translation id="9017320285115481645">Introduza o código de acesso parental do Family Link.</translation>
 <translation id="9024331582947483881">ecrã inteiro</translation>
+<translation id="9029736946581028033">O dispositivo vai desligar-se em breve</translation>
 <translation id="9030319654231318877">Desativado até ao nascer do sol</translation>
 <translation id="9034924485347205037">Ficheiros Linux</translation>
 <translation id="9047624247355796468">Abrir as definições de <ph name="NETWORK_NAME" /></translation>
@@ -1368,6 +1378,7 @@
 <translation id="9168436347345867845">Fazer isto mais tarde</translation>
 <translation id="9178475906033259337">A apresentar 1 resultado para <ph name="QUERY" /></translation>
 <translation id="9179259655489829027">Esta funcionalidade permite-lhe aceder rapidamente a qualquer utilizador com a sessão iniciada sem ser necessária uma palavra-passe. Utilize esta funcionalidade apenas com contas fidedignas.</translation>
+<translation id="9180906851711123156">Prima Ctrl + W para fechar</translation>
 <translation id="9183456764293710005">Lupa de ecrã inteiro</translation>
 <translation id="9193626018745640770">A transmitir para um recetor desconhecido…</translation>
 <translation id="9194617393863864469">Iniciar sessão com outro utilizador...</translation>
diff --git a/ash/strings/ash_strings_si.xtb b/ash/strings/ash_strings_si.xtb
index 807a4b6..0fb8d4c 100644
--- a/ash/strings/ash_strings_si.xtb
+++ b/ash/strings/ash_strings_si.xtb
@@ -698,6 +698,7 @@
 <translation id="5071064518267176975">යෙදුමකට මයික්‍රෆෝනය භාවිත කිරීමට අවශ්‍යය</translation>
 <translation id="5078796286268621944">වැරදි PIN</translation>
 <translation id="5083553833479578423">තව සහායක අංග අගුලු හරින්න</translation>
+<translation id="509790653408515442">ඔබ ඔබගේ දුරකථනයේ යෙදුම් ප්‍රවාහ කරන විට, ඒවා මෙහි දිස් වනු ඇත</translation>
 <translation id="5107522548814527560">වෙබය</translation>
 <translation id="5117590920725113268">ඊළඟ මාසය පෙන්වන්න</translation>
 <translation id="5136175204352732067">වෙනස් යතුරු පුවරුවක් සම්බන්ධ කර ඇත</translation>
@@ -720,6 +721,7 @@
 <translation id="523505283826916779">ප්‍රවේශ්‍යතා පසුතල</translation>
 <translation id="5245201184978705914">අනුපත ජනනය කළ නොහැකිය</translation>
 <translation id="5253783950165989294"><ph name="DEVICE_NAME" /> නම් වූ උපාංගයකට සම්බන්ධ විය, බැටරිය <ph name="BATTERY_PERCENTAGE" />%</translation>
+<translation id="5258528442992323769">සුරැකි මේස නැත</translation>
 <translation id="5260676007519551770">4 වෙනි මේසය</translation>
 <translation id="5283099933536931082"><ph name="APP_ITEM_TITLE" /> ඔබගේ අවධානය ඉල්ලයි.</translation>
 <translation id="5283198616748585639">1 විනාඩියක් එක් කරන්න</translation>
@@ -1259,6 +1261,7 @@
 <translation id="851458219935658693">වත්මන් මේසයෙන් කවුළු පෙන්වයි, රේඩියෝ බොත්තම තෝරා ගන්නා ලදී</translation>
 <translation id="8517041960877371778">ඔබගේ <ph name="DEVICE_TYPE" /> සක්‍රියව පවතින විට එය ආරෝපණය නොවනු ඇත.</translation>
 <translation id="8535393432370007982">වර්ණය අනුව අනුපිළිවෙලට සැකසීමේ පිළිවෙළ පසුගමනය කරන්න</translation>
+<translation id="8542053257095774575">සුරැකි මේස හෝ අච්චු නැත</translation>
 <translation id="8546059259582788728">අනුපිළිවෙළට සැකසීම පසුගමනය සාර්ථකයි</translation>
 <translation id="8551588720239073785">දිනය සහ වේලාව සැකසීම්</translation>
 <translation id="8553395910833293175">සියලු මේස වෙත දැනටමත් පවරා ඇත.</translation>
diff --git a/ash/strings/ash_strings_sk.xtb b/ash/strings/ash_strings_sk.xtb
index da241f4..7c718b20 100644
--- a/ash/strings/ash_strings_sk.xtb
+++ b/ash/strings/ash_strings_sk.xtb
@@ -252,6 +252,7 @@
 <translation id="243878895369688216">Otvorené včera</translation>
 <translation id="2441427462554639370">Nahrávanie bolo ukončené, pretože sa takmer úplne minul voľný priestor</translation>
 <translation id="24452542372838207">Rozbaliť upozornenie</translation>
+<translation id="2449089818483227734">Nízky stav batérie</translation>
 <translation id="2450205753526923158">Režim snímky obrazovky</translation>
 <translation id="2456008742792828469">Kalendár, <ph name="CURRENT_MONTH_YEAR" /></translation>
 <translation id="2473177541599297363">Potvrďte rozlíšenie</translation>
@@ -412,11 +413,13 @@
 <translation id="3441920967307853524"><ph name="RECEIVED_BYTES" />/<ph name="TOTAL_BYTES" /></translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> min</translation>
 <translation id="3445925074670675829">Zariadenie USB-C</translation>
+<translation id="3455468639467374593">Šablóna, <ph name="TEMPLATE_NAME" /></translation>
 <translation id="3465223694362104965">Od vášho posledného prihlásenia bola k tomuto zariadeniu pripojená ďalšia klávesnica. Skôr ako ju použijete, uistite sa, že je dôveryhodná.</translation>
 <translation id="3465356146291925647">Ovládané správcom</translation>
 <translation id="3477079411857374384">Ctrl-Shift-medzerník</translation>
 <translation id="3485319357743610354"><ph name="SECURITY_STATUS" />, <ph name="CONNECTION_STATUS" />, sila signálu <ph name="SIGNAL_STRENGTH" /></translation>
 <translation id="348799646910989694">Polička sa bude automaticky skrývať</translation>
+<translation id="3505066820268455558">Batéria sa nabíja</translation>
 <translation id="3509391053705095206">Váš telefón sa nedá nájsť. Skontrolujte, či v ňom máte zapnuté rozhranie Bluetooth.</translation>
 <translation id="3510164367642747937">Zvýrazniť ukazovateľ myši</translation>
 <translation id="3513798432020909783">Správca účtu: <ph name="MANAGER_EMAIL" /></translation>
@@ -457,6 +460,8 @@
 <translation id="3633097874324966332">Ak chcete zariadenie spárovať, otvorte nastavenia rozhrania Bluetooth</translation>
 <translation id="3638400994746983214">Prepnúť obrazovku ochrany súkromia. <ph name="STATE_TEXT" />.</translation>
 <translation id="3649505501900178324">Termín aktualizácie ubehol</translation>
+<translation id="3659814201068740063">Približný zostávajúci čas: <ph name="TIME_LEFT" /> (<ph name="PERCENTAGE" /> %).
+Pripojte svoje zariadenie k napájaniu.</translation>
 <translation id="366222428570480733">Spravovaný používateľ <ph name="USER_EMAIL_ADDRESS" /></translation>
 <translation id="36813544980941320">Siete Wi‑Fi sa budú zdieľať medzi vaším telefónom a zariadením <ph name="DEVICE_NAME" /></translation>
 <translation id="3694122362646626770">Webové stránky</translation>
@@ -511,6 +516,7 @@
 <translation id="3962859241508114581">Predchádzajúca stopa</translation>
 <translation id="3969043077941541451">Vypnuté</translation>
 <translation id="397105322502079400">Prebieha výpočet...</translation>
+<translation id="397726367135689299">Nabíjanie batérie môže byť nespoľahlivé.</translation>
 <translation id="3977512764614765090">Batéria je nabitá na <ph name="PERCENTAGE" /> % a nabíja sa.</translation>
 <translation id="3986082989454912832">Prijať</translation>
 <translation id="3995138139523574647">zariadenia USB-C (port vpravo vzadu)</translation>
@@ -1038,6 +1044,7 @@
 <translation id="7130207228079676353">S NAJVÄČŠOU PRAVDEPODOBNOSŤOU</translation>
 <translation id="7131634465328662194">Odhlásenie prebehne automaticky.</translation>
 <translation id="7143207342074048698">Pripája sa</translation>
+<translation id="7144942256906679589">Stav batérie</translation>
 <translation id="7165278925115064263">Alt+Shift+K</translation>
 <translation id="7168224885072002358">Vrátenie starého rozlíšenia prebehne o <ph name="TIMEOUT_SECONDS" /></translation>
 <translation id="7180611975245234373">Obnoviť</translation>
@@ -1104,6 +1111,7 @@
 <translation id="7593891976182323525">Hľadať alebo Shift</translation>
 <translation id="7600875258240007829">Zobraziť všetky upozornenia</translation>
 <translation id="7607002721634913082">Pozastavené</translation>
+<translation id="7609951632080598826">Zobrazenie kalendára, <ph name="DATE" />, <ph name="TIME" /></translation>
 <translation id="7611213136657090146">Kamera bola odpojená</translation>
 <translation id="7624117708979618027"><ph name="TEMPERATURE_F" />° F</translation>
 <translation id="7633755430369750696">Zobraziť nastavenia Zdieľania nablízku</translation>
@@ -1229,6 +1237,7 @@
 <translation id="8345019317483336363">Bolo vybrané okno <ph name="WINDOW_TITLE" /></translation>
 <translation id="8351131234907093545">Vytvoriť poznámku</translation>
 <translation id="8364673525741149932">Prepnúť na režim Shelf Party. <ph name="STATE_TEXT" /></translation>
+<translation id="8369166482916924789">Uložená plocha, <ph name="SAVE_AND_RECALL_DESK_NAME" /></translation>
 <translation id="8371779926711439835">Dopredu o písmeno</translation>
 <translation id="8371991222807690464">V režime pre hostí môže byť výkonnosť periférie obmedzená</translation>
 <translation id="8374601332003098278">Čiastočnú obrazovku nahráte stlačením klávesa Enter</translation>
@@ -1341,6 +1350,7 @@
 <translation id="9000771174482730261">SPRAVOVAŤ PRIESTOR</translation>
 <translation id="9017320285115481645">Zadajte prístupový kód rodiča Family Link.</translation>
 <translation id="9024331582947483881">celá obrazovka</translation>
+<translation id="9029736946581028033">Zariadenie sa čoskoro vypne</translation>
 <translation id="9030319654231318877">Vypnutý do západu slnka</translation>
 <translation id="9034924485347205037">Súbory systému Linux</translation>
 <translation id="9047624247355796468">Otvoriť nastavenia siete <ph name="NETWORK_NAME" /></translation>
@@ -1370,6 +1380,7 @@
 <translation id="9168436347345867845">Neskôr</translation>
 <translation id="9178475906033259337">Zobrazuje sa jeden výsledok pre <ph name="QUERY" /></translation>
 <translation id="9179259655489829027">Táto funkcia vám umožní rýchly prístup k ľubovoľnému prihlásenému používateľovi bez hesla. Používajte ju iba s dôveryhodnými účtami.</translation>
+<translation id="9180906851711123156">Zavrite stlačením klávesov Ctrl + W</translation>
 <translation id="9183456764293710005">Lupa na celú obrazovku</translation>
 <translation id="9193626018745640770">Prebieha prenášanie do neznámeho prijímača</translation>
 <translation id="9194617393863864469">Prihlásiť ďalšieho používateľa...</translation>
diff --git a/ash/strings/ash_strings_sl.xtb b/ash/strings/ash_strings_sl.xtb
index 24070f4e..8d9a7abc 100644
--- a/ash/strings/ash_strings_sl.xtb
+++ b/ash/strings/ash_strings_sl.xtb
@@ -698,6 +698,7 @@
 <translation id="5071064518267176975">Aplikacija želi uporabljati mikrofon</translation>
 <translation id="5078796286268621944">Napačen PIN</translation>
 <translation id="5083553833479578423">Odklenite več funkcij Pomočnika.</translation>
+<translation id="509790653408515442">Ko pretočno predvajate aplikacije v telefonu, so prikazane tukaj</translation>
 <translation id="5107522548814527560">Splet</translation>
 <translation id="5117590920725113268">Prikaz naslednjega meseca</translation>
 <translation id="5136175204352732067">Priklopljena je druga tipkovnica</translation>
@@ -720,6 +721,7 @@
 <translation id="523505283826916779">Nastavitve funkcij za ljudi s posebnimi potrebami</translation>
 <translation id="5245201184978705914">Prepisa ni mogoče ustvariti</translation>
 <translation id="5253783950165989294">Vzpostavljena je povezava z napravo <ph name="DEVICE_NAME" />, napolnjenost baterije: <ph name="BATTERY_PERCENTAGE" /> %</translation>
+<translation id="5258528442992323769">Ni shranjenih namizij</translation>
 <translation id="5260676007519551770">Namizje 4</translation>
 <translation id="5283099933536931082"><ph name="APP_ITEM_TITLE" /> potrebuje vašo pozornost.</translation>
 <translation id="5283198616748585639">Dodaj 1 min</translation>
@@ -1259,6 +1261,7 @@
 <translation id="851458219935658693">Prikaz oken na trenutnem namizju, izbran je izbirni gumb</translation>
 <translation id="8517041960877371778">Akumulator naprave <ph name="DEVICE_TYPE" /> se morda ne bo polnil, medtem ko je naprava vklopljena.</translation>
 <translation id="8535393432370007982">Razveljavi način razvrščanja po barvi</translation>
+<translation id="8542053257095774575">Ni shranjenih namizij ali predlogov</translation>
 <translation id="8546059259582788728">Razveljavitev razvrščanja je uspela</translation>
 <translation id="8551588720239073785">Nastavitve datuma in ure</translation>
 <translation id="8553395910833293175">Že dodeljeno vsem namizjem.</translation>
diff --git a/ash/strings/ash_strings_sr-Latn.xtb b/ash/strings/ash_strings_sr-Latn.xtb
index 0028cb25..6439bd71 100644
--- a/ash/strings/ash_strings_sr-Latn.xtb
+++ b/ash/strings/ash_strings_sr-Latn.xtb
@@ -1067,6 +1067,7 @@
 <translation id="7348093485538360975">Tastatura na ekranu</translation>
 <translation id="735745346212279324">Veza sa VPN-om je prekinuta</translation>
 <translation id="7360036564632145207">Ako promenite podešavanje zaštite pristupa podacima za periferne uređaje, možete da optimizujete učinak</translation>
+<translation id="736045644501761622">Podesi pozadinu i stil</translation>
 <translation id="7371404428569700291">Snimi prozor</translation>
 <translation id="7377169924702866686">Caps Lock je uključen.</translation>
 <translation id="7377481913241237033">Povežite se pomoću koda</translation>
@@ -1303,6 +1304,7 @@
 <translation id="8721053961083920564">Uključite/isključite zvuk. <ph name="STATE_TEXT" /></translation>
 <translation id="8724318433625452070">Snimanje celog ekrana</translation>
 <translation id="8734991477317290293">Možda pokušava da ukrade vašu kombinaciju tastera</translation>
+<translation id="8735678380411481005">Boja pozadinskog osvetljenja tastature</translation>
 <translation id="8735953464173050365">Pregledajte podešavanja tastature. Izabrana je <ph name="KEYBOARD_NAME" /></translation>
 <translation id="8755498163081687682">Verifikujte identitet: <ph name="ORIGIN_NAME" /> želi da potvrdi da ste to vi</translation>
 <translation id="875593634123171288">Pregledajte podešavanja VPN-a</translation>
diff --git a/ash/strings/ash_strings_sr.xtb b/ash/strings/ash_strings_sr.xtb
index 6951a76..ed0b9fe 100644
--- a/ash/strings/ash_strings_sr.xtb
+++ b/ash/strings/ash_strings_sr.xtb
@@ -1067,6 +1067,7 @@
 <translation id="7348093485538360975">Тастатура на екрану</translation>
 <translation id="735745346212279324">Веза са VPN-ом је прекинута</translation>
 <translation id="7360036564632145207">Ако промените подешавање заштите приступа подацима за периферне уређаје, можете да оптимизујете учинак</translation>
+<translation id="736045644501761622">Подеси позадину и стил</translation>
 <translation id="7371404428569700291">Сними прозор</translation>
 <translation id="7377169924702866686">Caps Lock је укључен.</translation>
 <translation id="7377481913241237033">Повежите се помоћу кода</translation>
@@ -1303,6 +1304,7 @@
 <translation id="8721053961083920564">Укључите/искључите звук. <ph name="STATE_TEXT" /></translation>
 <translation id="8724318433625452070">Снимање целог екрана</translation>
 <translation id="8734991477317290293">Можда покушава да украде вашу комбинацију тастера</translation>
+<translation id="8735678380411481005">Боја позадинског осветљења тастатуре</translation>
 <translation id="8735953464173050365">Прегледајте подешавања тастатуре. Изабрана је <ph name="KEYBOARD_NAME" /></translation>
 <translation id="8755498163081687682">Верификујте идентитет: <ph name="ORIGIN_NAME" /> жели да потврди да сте то ви</translation>
 <translation id="875593634123171288">Прегледајте подешавања VPN-а</translation>
diff --git a/ash/strings/ash_strings_sv.xtb b/ash/strings/ash_strings_sv.xtb
index 8b56d86..1f39e66d 100644
--- a/ash/strings/ash_strings_sv.xtb
+++ b/ash/strings/ash_strings_sv.xtb
@@ -698,6 +698,7 @@
 <translation id="5071064518267176975">En app vill använda mikrofonen</translation>
 <translation id="5078796286268621944">Fel pinkod</translation>
 <translation id="5083553833479578423">Lås upp fler funktioner för Assistent</translation>
+<translation id="509790653408515442">När du streamar telefonens appar visas de här</translation>
 <translation id="5107522548814527560">Webb</translation>
 <translation id="5117590920725113268">Visa nästa månad</translation>
 <translation id="5136175204352732067">Ett annat tangentbord har anslutits</translation>
@@ -720,6 +721,7 @@
 <translation id="523505283826916779">Inställningar för tillgänglighet</translation>
 <translation id="5245201184978705914">Det gick inte att generera transkription</translation>
 <translation id="5253783950165989294">Ansluten till enheten <ph name="DEVICE_NAME" />, <ph name="BATTERY_PERCENTAGE" /> % batteri</translation>
+<translation id="5258528442992323769">Det finns inga sparade skrivbord</translation>
 <translation id="5260676007519551770">Skrivbord 4</translation>
 <translation id="5283099933536931082"><ph name="APP_ITEM_TITLE" /> begär din uppmärksamhet.</translation>
 <translation id="5283198616748585639">Lägg till en min</translation>
@@ -1259,6 +1261,7 @@
 <translation id="851458219935658693">Visa fönster från det aktuella skrivbordet, alternativknapp har markerats</translation>
 <translation id="8517041960877371778">Din <ph name="DEVICE_TYPE" /> laddas eventuellt inte så länge den är på.</translation>
 <translation id="8535393432370007982">Ångra sortering efter färg</translation>
+<translation id="8542053257095774575">Det finns inga sparade skrivbord eller mallar</translation>
 <translation id="8546059259582788728">Sorteringen har ångrats.</translation>
 <translation id="8551588720239073785">Inställningar för datum och tid</translation>
 <translation id="8553395910833293175">Detta har redan tilldelats alla skrivbord.</translation>
diff --git a/ash/strings/ash_strings_sw.xtb b/ash/strings/ash_strings_sw.xtb
index 4209f57..17fb41a 100644
--- a/ash/strings/ash_strings_sw.xtb
+++ b/ash/strings/ash_strings_sw.xtb
@@ -698,6 +698,7 @@
 <translation id="5071064518267176975">Kuna programu inayotaka kutumia maikrofoni</translation>
 <translation id="5078796286268621944">PIN isiyo sahihi</translation>
 <translation id="5083553833479578423">Fungua vipengele zaidi vya programu yako ya Mratibu.</translation>
+<translation id="509790653408515442">Unapotiririsha programu za simu yako, zitaonekana hapa</translation>
 <translation id="5107522548814527560">Wavuti</translation>
 <translation id="5117590920725113268">Onyesha mwezi unaofuata</translation>
 <translation id="5136175204352732067">Kibodi tofauti imeunganishwa</translation>
@@ -720,6 +721,7 @@
 <translation id="523505283826916779">Mipangilio ya ufikiaji</translation>
 <translation id="5245201184978705914">Imeshindwa kuzalisha manukuu</translation>
 <translation id="5253783950165989294">Imeunganishwa kwenye kifaa kiitwacho <ph name="DEVICE_NAME" />, chaji ya betri ni <ph name="BATTERY_PERCENTAGE" />%</translation>
+<translation id="5258528442992323769">Hakuna maeneokazi yaliyohifadhiwa</translation>
 <translation id="5260676007519551770">Eneokazi la 4</translation>
 <translation id="5283099933536931082"><ph name="APP_ITEM_TITLE" /> inakuomba ushughulikie jambo fulani.</translation>
 <translation id="5283198616748585639">Ongeza dakika 1</translation>
@@ -1260,6 +1262,7 @@
 <translation id="851458219935658693">Onyesha madirisha yaliyo kwenye eneokazi la sasa, umechagua kitufe cha mviringo</translation>
 <translation id="8517041960877371778">Huenda kifaa chako cha <ph name="DEVICE_TYPE" /> kisichaji kikiwa kimewashwa.</translation>
 <translation id="8535393432370007982">Tendua utaratibu wa kupanga kulingana na rangi</translation>
+<translation id="8542053257095774575">Hakuna maeneokazi au violezo vilivyohifadhiwa</translation>
 <translation id="8546059259582788728">Imefanikiwa kutendua upangaji</translation>
 <translation id="8551588720239073785">Mipangilio ya saa na tarehe</translation>
 <translation id="8553395910833293175">Tayari limewekwa kwenye maeneokazi yote.</translation>
diff --git a/ash/strings/ash_strings_te.xtb b/ash/strings/ash_strings_te.xtb
index 0411bb00..8c413c0 100644
--- a/ash/strings/ash_strings_te.xtb
+++ b/ash/strings/ash_strings_te.xtb
@@ -252,6 +252,7 @@
 <translation id="243878895369688216">నిన్న తెరిచారు</translation>
 <translation id="2441427462554639370">చాలా తక్కువ స్టోరేజ్ స్పేస్ కారణంగా రికార్డ్ చేయడం ముగించబడింది</translation>
 <translation id="24452542372838207">నోటిఫికేషన్‌ను విస్తరించు</translation>
+<translation id="2449089818483227734">బ్యాటరీ తక్కువ ఉంది</translation>
 <translation id="2450205753526923158">స్క్రీన్‌షాట్ మోడ్</translation>
 <translation id="2456008742792828469">క్యాలెండర్, <ph name="CURRENT_MONTH_YEAR" /></translation>
 <translation id="2473177541599297363">రిజల్యూషన్‌ను ధృవీకరించండి</translation>
@@ -412,11 +413,13 @@
 <translation id="3441920967307853524"><ph name="RECEIVED_BYTES" />/<ph name="TOTAL_BYTES" /></translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> నిమి</translation>
 <translation id="3445925074670675829">USB-C పరికరం</translation>
+<translation id="3455468639467374593">టెంప్లేట్, <ph name="TEMPLATE_NAME" /></translation>
 <translation id="3465223694362104965">మీరు చివరిగా సైన్ ఇన్ చేసిన తర్వాత ఈ పరికరానికి మరొక కీబోర్డ్ కనెక్ట్ చేయబడింది. మీరు ఈ కీబోర్డ్‌ను ఉపయోగించే ముందు దీనిని మీరు విశ్వసిస్తున్నట్లు నిర్ధారించుకోండి.</translation>
 <translation id="3465356146291925647">మీ అడ్మినిస్ట్రేటర్ ద్వారా నిర్వహించబడుతోంది</translation>
 <translation id="3477079411857374384">Control-Shift-Space</translation>
 <translation id="3485319357743610354"><ph name="SECURITY_STATUS" />, <ph name="CONNECTION_STATUS" />, సిగ్నల్ సామర్థ్యం <ph name="SIGNAL_STRENGTH" /></translation>
 <translation id="348799646910989694">అర ఆటోమేటిక్‌గా దాచి పెట్టబడుతుంది</translation>
+<translation id="3505066820268455558">బ్యాటరీ ఛార్జ్ అవుతోంది</translation>
 <translation id="3509391053705095206">మీ ఫోన్‌ను కనుగొనడం సాధ్యపడలేదు. మీ ఫోన్‌లో బ్లూటూత్ ఆన్‌లో ఉందని నిర్ధారించుకోండి.</translation>
 <translation id="3510164367642747937">మౌస్ కర్సర్‌ను హైలైట్ చేయి</translation>
 <translation id="3513798432020909783"><ph name="MANAGER_EMAIL" /> ద్వారా ఖాతా నిర్వహించబడుతోంది</translation>
@@ -457,6 +460,8 @@
 <translation id="3633097874324966332">మీ పరికరాన్ని పెయిర్ చేయడానికి బ్లూటూత్ సెట్టింగ్‌లను తెరవండి</translation>
 <translation id="3638400994746983214">గోప్యతా స్క్రీన్‌ను టోగుల్ చేస్తుంది. <ph name="STATE_TEXT" />.</translation>
 <translation id="3649505501900178324">అప్‌డేట్ పెండింగ్‌లో ఉంది</translation>
+<translation id="3659814201068740063">సుమారు <ph name="TIME_LEFT" /> మిగిలింది (<ph name="PERCENTAGE" />%).
+మీ పరికరాన్ని పవర్‌కి కనెక్ట్ చేయండి.</translation>
 <translation id="366222428570480733"><ph name="USER_EMAIL_ADDRESS" /> మేనేజ్ చేయబడిన యూజర్</translation>
 <translation id="36813544980941320">Wi-Fi నెట్‌వర్క్‌లు మీ ఫోన్, <ph name="DEVICE_NAME" /> మధ్య షేర్ చేయబడతాయి</translation>
 <translation id="3694122362646626770">వెబ్‌సైట్‌లు</translation>
@@ -512,6 +517,7 @@
 <translation id="3962859241508114581">మునుపటి ట్రాక్</translation>
 <translation id="3969043077941541451">ఆఫ్</translation>
 <translation id="397105322502079400">గణిస్తోంది...</translation>
+<translation id="397726367135689299">బ్యాటరీ ఛార్జింగ్ అస్థిరంగా ఉండవచ్చు.</translation>
 <translation id="3977512764614765090">బ్యాటరీ <ph name="PERCENTAGE" />% ఉంది. ఛార్జ్ అవుతోంది.</translation>
 <translation id="3986082989454912832">సమాధానం ఇవ్వండి</translation>
 <translation id="3995138139523574647">USB-C పరికరం (కుడివైపు వెనుక పోర్ట్)</translation>
@@ -1039,6 +1045,7 @@
 <translation id="7130207228079676353">అత్యంత ఇష్టపడేవి</translation>
 <translation id="7131634465328662194">మీరు ఆటోమేటిక్‌గా సైన్ అవుట్ చేయబడతారు.</translation>
 <translation id="7143207342074048698">కనెక్ట్ అవుతో.</translation>
+<translation id="7144942256906679589">బ్యాటరీ స్టేటస్</translation>
 <translation id="7165278925115064263">Alt+Shift+K</translation>
 <translation id="7168224885072002358"><ph name="TIMEOUT_SECONDS" />లో తిరిగి పాత రిజల్యూషన్‌కి మార్చబడుతుంది</translation>
 <translation id="7180611975245234373">రిఫ్రెష్ చేయి</translation>
@@ -1104,6 +1111,7 @@
 <translation id="7593891976182323525">Search లేదా Shift</translation>
 <translation id="7600875258240007829">అన్ని నోటిఫికేషన్‌లను చూడండి</translation>
 <translation id="7607002721634913082">పాజ్ చెయ్యబడింది</translation>
+<translation id="7609951632080598826">క్యాలెండర్ వీక్షణ, <ph name="DATE" />, <ph name="TIME" /></translation>
 <translation id="7611213136657090146">కెమెరా తిరిగి కనెక్ట్ చేయబడింది.</translation>
 <translation id="7624117708979618027"><ph name="TEMPERATURE_F" />° F</translation>
 <translation id="7633755430369750696">సమీప షేరింగ్ సెట్టింగ్‌లను చూపించు.</translation>
@@ -1229,6 +1237,7 @@
 <translation id="8345019317483336363"><ph name="WINDOW_TITLE" /> విండో ఎంచుకోబడింది</translation>
 <translation id="8351131234907093545">గమనికను క్రియేట్ చేయండి</translation>
 <translation id="8364673525741149932">షెల్ఫ్ పార్టీ టోగుల్. <ph name="STATE_TEXT" /></translation>
+<translation id="8369166482916924789">సేవ్ చేసిన డెస్క్, <ph name="SAVE_AND_RECALL_DESK_NAME" /></translation>
 <translation id="8371779926711439835">ఒక అక్షరం ముందుకు</translation>
 <translation id="8371991222807690464">గెస్ట్ మోడ్‌లో పెరిఫెరల్ పనితీరు పరిమితంగా ఉండవచ్చు</translation>
 <translation id="8374601332003098278">పాక్షిక స్క్రీన్‌షాట్‌ను రికార్డ్ చేయడానికి enterను నొక్కండి</translation>
@@ -1340,6 +1349,7 @@
 <translation id="9000771174482730261">స్టోరేజ్‌ను మేనేజ్ చేయండి</translation>
 <translation id="9017320285115481645">Family Link తల్లిదండ్రుల యాక్సెస్ కోడ్‌ను నమోదు చేయండి.</translation>
 <translation id="9024331582947483881">ఫుల్-స్క్రీన్‌</translation>
+<translation id="9029736946581028033">పరికరం త్వరలో ఆఫ్ చేయబడుతుంది</translation>
 <translation id="9030319654231318877">సూర్యాస్తమయం వరకు ఆఫ్‌లో ఉంటుంది</translation>
 <translation id="9034924485347205037">Linux ఫైళ్లు</translation>
 <translation id="9047624247355796468"><ph name="NETWORK_NAME" /> సెట్టింగ్‌లను తెరవండి</translation>
@@ -1369,6 +1379,7 @@
 <translation id="9168436347345867845">దీనిని తర్వాత చేయి</translation>
 <translation id="9178475906033259337"><ph name="QUERY" /> కోసం 1 ఫలితాన్ని ప్రదర్శిస్తోంది</translation>
 <translation id="9179259655489829027">ఈ ఫీచర్ ద్వారా పాస్‌వర్డ్ అవసరం లేకుండానే మీరు సైన్ ఇన్ చేసిన ఏ వినియోగదారునైనా త్వరగా యాక్సెస్ చేయగలుగుతారు. ఈ ఫీచర్‌ను మీరు విశ్వసించే ఖాతాలతో మాత్రమే ఉపయోగించండి.</translation>
+<translation id="9180906851711123156">మూసివేయడానికి Ctrl + W నొక్కండి</translation>
 <translation id="9183456764293710005">పూర్తి-స్క్రీన్‌ మ్యాగ్నిఫైయర్</translation>
 <translation id="9193626018745640770">తెలియని రిసీవర్‌లో ప్రసారం చేస్తోంది</translation>
 <translation id="9194617393863864469">మరొక వినియోగదారుగా సైన్ ఇన్ చేయండి...</translation>
diff --git a/ash/strings/ash_strings_tr.xtb b/ash/strings/ash_strings_tr.xtb
index 39041589..89b7c10 100644
--- a/ash/strings/ash_strings_tr.xtb
+++ b/ash/strings/ash_strings_tr.xtb
@@ -698,6 +698,7 @@
 <translation id="5071064518267176975">Bir uygulama, mikrofonu kullanmak istiyor</translation>
 <translation id="5078796286268621944">Yanlış PIN</translation>
 <translation id="5083553833479578423">Diğer Asistan özelliklerinin kilidini açın.</translation>
+<translation id="509790653408515442">Telefonunuzdan yayınladığınız uygulamalar burada görünür</translation>
 <translation id="5107522548814527560">Web</translation>
 <translation id="5117590920725113268">Sonraki ayı göster</translation>
 <translation id="5136175204352732067">Farklı klavye bağlandı</translation>
@@ -720,6 +721,7 @@
 <translation id="523505283826916779">Erişilebilirlik ayarları</translation>
 <translation id="5245201184978705914">Transkript oluşturulamıyor</translation>
 <translation id="5253783950165989294"><ph name="DEVICE_NAME" /> adlı cihaza bağlanıldı, pil %<ph name="BATTERY_PERCENTAGE" /></translation>
+<translation id="5258528442992323769">Kayıtlı masa yok</translation>
 <translation id="5260676007519551770">Çalışma Masası 4</translation>
 <translation id="5283099933536931082"><ph name="APP_ITEM_TITLE" />, ilgilenmenizi gerektiriyor.</translation>
 <translation id="5283198616748585639">1 dk ekle</translation>
@@ -1259,6 +1261,7 @@
 <translation id="851458219935658693">Geçerli masadaki pencereleri göster, radyo düğmesi seçildi</translation>
 <translation id="8517041960877371778"><ph name="DEVICE_TYPE" /> cihazınız açıkken şarj olmayabilir.</translation>
 <translation id="8535393432370007982">Renge göre sıralama ölçütünü geri al</translation>
+<translation id="8542053257095774575">Kayıtlı masa veya şablon yok</translation>
 <translation id="8546059259582788728">Sıralama işlemi başarıyla geri alındı</translation>
 <translation id="8551588720239073785">Tarih ve zaman ayarları</translation>
 <translation id="8553395910833293175">Zaten tüm masalara atandı.</translation>
diff --git a/ash/strings/ash_strings_uk.xtb b/ash/strings/ash_strings_uk.xtb
index b96970a3..6f6ece3 100644
--- a/ash/strings/ash_strings_uk.xtb
+++ b/ash/strings/ash_strings_uk.xtb
@@ -698,6 +698,7 @@
 <translation id="5071064518267176975">Додаток хоче використовувати мікрофон</translation>
 <translation id="5078796286268621944">Неправильний PIN-код</translation>
 <translation id="5083553833479578423">Розблокуйте інші функції Асистента.</translation>
+<translation id="509790653408515442">Тут з’являтимуться додатки, які ви транслюєте з телефона</translation>
 <translation id="5107522548814527560">Інтернет</translation>
 <translation id="5117590920725113268">Показати наступний місяць</translation>
 <translation id="5136175204352732067">Під’єднано іншу клавіатуру</translation>
@@ -720,6 +721,7 @@
 <translation id="523505283826916779">Налаштування доступності</translation>
 <translation id="5245201184978705914">Не вдалося створити текстову версію</translation>
 <translation id="5253783950165989294">Підключено до пристрою "<ph name="DEVICE_NAME" />", заряд акумулятора – <ph name="BATTERY_PERCENTAGE" />%</translation>
+<translation id="5258528442992323769">Немає збережених робочих столів</translation>
 <translation id="5260676007519551770">Робочий стіл 4</translation>
 <translation id="5283099933536931082"><ph name="APP_ITEM_TITLE" />: потрібно переглянути.</translation>
 <translation id="5283198616748585639">Додати 1 хв</translation>
@@ -1259,6 +1261,7 @@
 <translation id="851458219935658693">Показувати вікна з поточного робочого столу, перемикач вибрано</translation>
 <translation id="8517041960877371778">Пристрій <ph name="DEVICE_TYPE" /> може не заряджатися, коли він увімкнений.</translation>
 <translation id="8535393432370007982">Скасувати сортування за кольором</translation>
+<translation id="8542053257095774575">Немає збережених робочих столів або шаблонів</translation>
 <translation id="8546059259582788728">Сортування скасовано</translation>
 <translation id="8551588720239073785">Налаштування дати й часу</translation>
 <translation id="8553395910833293175">Уже призначено для всіх робочих столів.</translation>
diff --git a/ash/strings/ash_strings_ur.xtb b/ash/strings/ash_strings_ur.xtb
index d2b846d..3e57493 100644
--- a/ash/strings/ash_strings_ur.xtb
+++ b/ash/strings/ash_strings_ur.xtb
@@ -1059,6 +1059,7 @@
 <translation id="7348093485538360975">آن اسکرین کی بورڈ</translation>
 <translation id="735745346212279324">‏VPN منقطع ہو گیا</translation>
 <translation id="7360036564632145207">پیریفیرلزکی ترتیب کیلئے آپ کے ڈیٹا تک رسائی کے تحفظ کی تبدیلی کارکردگی کو بہتر بنا سکتی ہے</translation>
+<translation id="736045644501761622">وال پیپر اور اسٹائل سیٹ کریں</translation>
 <translation id="7371404428569700291">ونڈو ریکارڈ کریں</translation>
 <translation id="7377169924702866686">‏Caps Lock آن ہے۔</translation>
 <translation id="7377481913241237033">کوڈ کے ساتھ منسلک کریں</translation>
@@ -1293,6 +1294,7 @@
 <translation id="8721053961083920564">والیوم ٹوگل کریں۔ <ph name="STATE_TEXT" /></translation>
 <translation id="8724318433625452070">فُل اسکرین کیپچر</translation>
 <translation id="8734991477317290293">ممکن ہے یہ آپ کی کلید کے اسٹروکس کو چوری کرنے کی کوشش کر رہا ہو</translation>
+<translation id="8735678380411481005">کی بورڈ بیک لائٹ کا رنگ</translation>
 <translation id="8735953464173050365">کی بورڈ کی ترتیبات دکھائیں۔ <ph name="KEYBOARD_NAME" /> منتخب ہے</translation>
 <translation id="8755498163081687682">اپنی شناخت کی توثیق کریں: <ph name="ORIGIN_NAME" /> اس بات کی تصدیق کرنا چاہتی ہے کہ یہ آپ ہی ہیں</translation>
 <translation id="875593634123171288">‏VPN کی ترتیبات دکھائیں</translation>
diff --git a/ash/strings/ash_strings_vi.xtb b/ash/strings/ash_strings_vi.xtb
index 0e5ddd4..adfd3b4 100644
--- a/ash/strings/ash_strings_vi.xtb
+++ b/ash/strings/ash_strings_vi.xtb
@@ -698,6 +698,7 @@
 <translation id="5071064518267176975">Một ứng dụng muốn dùng micrô</translation>
 <translation id="5078796286268621944">Mã PIN không chính xác</translation>
 <translation id="5083553833479578423">Mở khóa các tính năng khác của Trợ lý.</translation>
+<translation id="509790653408515442">Khi bạn phát trực tuyến các ứng dụng trên điện thoại, những ứng dụng đó sẽ xuất hiện ở đây</translation>
 <translation id="5107522548814527560">Web</translation>
 <translation id="5117590920725113268">Hiển thị tháng tiếp theo</translation>
 <translation id="5136175204352732067">Đã kết nối bàn phím khác</translation>
@@ -720,6 +721,7 @@
 <translation id="523505283826916779">Hỗ trợ tiếp cận</translation>
 <translation id="5245201184978705914">Không tạo được bản chép lời</translation>
 <translation id="5253783950165989294">Đã kết nối với thiết bị có tên <ph name="DEVICE_NAME" />, <ph name="BATTERY_PERCENTAGE" />% pin</translation>
+<translation id="5258528442992323769">Bạn chưa lưu không gian làm việc nào</translation>
 <translation id="5260676007519551770">Không gian làm việc 4</translation>
 <translation id="5283099933536931082">Có thông báo từ <ph name="APP_ITEM_TITLE" />.</translation>
 <translation id="5283198616748585639">Thêm 1 phút</translation>
@@ -1259,6 +1261,7 @@
 <translation id="851458219935658693">Hiển thị cửa sổ từ không gian làm việc hiện tại, đã chọn nút chọn</translation>
 <translation id="8517041960877371778"><ph name="DEVICE_TYPE" /> của bạn có thể không sạc khi được bật.</translation>
 <translation id="8535393432370007982">Huỷ thứ tự sắp xếp theo màu</translation>
+<translation id="8542053257095774575">Bạn chưa lưu không gian làm việc hoặc mẫu nào</translation>
 <translation id="8546059259582788728">Đã huỷ thao tác sắp xếp</translation>
 <translation id="8551588720239073785">Cài đặt ngày và giờ</translation>
 <translation id="8553395910833293175">Đã được gán cho tất cả không gian làm việc.</translation>
diff --git a/ash/strings/ash_strings_zh-TW.xtb b/ash/strings/ash_strings_zh-TW.xtb
index 9fb5727..3c2677a 100644
--- a/ash/strings/ash_strings_zh-TW.xtb
+++ b/ash/strings/ash_strings_zh-TW.xtb
@@ -695,6 +695,7 @@
 <translation id="5071064518267176975">某個應用程式要求使用麥克風</translation>
 <translation id="5078796286268621944">PIN 不正確</translation>
 <translation id="5083553833479578423">啟用更多 Google 助理功能。</translation>
+<translation id="509790653408515442">串流播放手機的應用程式時,這些應用程式會顯示在這裡</translation>
 <translation id="5107522548814527560">網頁</translation>
 <translation id="5117590920725113268">顯示下一個月</translation>
 <translation id="5136175204352732067">已連接其他鍵盤</translation>
@@ -717,6 +718,7 @@
 <translation id="523505283826916779">無障礙設定</translation>
 <translation id="5245201184978705914">無法產生轉錄稿</translation>
 <translation id="5253783950165989294">已連線至名為「<ph name="DEVICE_NAME" />」的裝置,電池電力:<ph name="BATTERY_PERCENTAGE" />%</translation>
+<translation id="5258528442992323769">沒有已儲存的桌面</translation>
 <translation id="5260676007519551770">桌面 4</translation>
 <translation id="5283099933536931082">「<ph name="APP_ITEM_TITLE" />」有通知需要查看。</translation>
 <translation id="5283198616748585639">增加 1 分鐘</translation>
@@ -1254,6 +1256,7 @@
 <translation id="851458219935658693">顯示目前桌面的視窗,已點選圓形按鈕</translation>
 <translation id="8517041960877371778"><ph name="DEVICE_TYPE" /> 在開啟時可能無法充電。</translation>
 <translation id="8535393432370007982">復原依顏色排列順序</translation>
+<translation id="8542053257095774575">沒有已儲存的桌面或範本</translation>
 <translation id="8546059259582788728">已成功復原排列順序</translation>
 <translation id="8551588720239073785">日期和時間設定</translation>
 <translation id="8553395910833293175">已指派給所有桌面。</translation>
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index 7fa1c4da..d9598f0 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-8.20220527.3.1
+8.20220528.1.1
diff --git a/chrome/VERSION b/chrome/VERSION
index 40c76534..821d82f 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=104
 MINOR=0
-BUILD=5088
+BUILD=5090
 PATCH=0
diff --git a/chrome/app/resources/chromium_strings_am.xtb b/chrome/app/resources/chromium_strings_am.xtb
index 2178ea4..e3f9841e 100644
--- a/chrome/app/resources/chromium_strings_am.xtb
+++ b/chrome/app/resources/chromium_strings_am.xtb
@@ -61,6 +61,7 @@
 <translation id="2583187216237139145">ይህን መገለጫ በሚጠቀሙበት ጊዜ የመነጨ ማንኛውም የChromium ውሂብ (እንደ የዕልባቶች፣ ታሪክ፣ የይለፍ ቃላት እና ሌሎች ቅንብሮች መፈጠር ያለ) በስራ መገለጫ አስተዳዳሪው ሊወገድ ይችላል። <ph name="LEARN_MORE" /></translation>
 <translation id="2648074677641340862">በጭነት ጊዜ የስርዓተ ክወና ስህተት ተፈጥሯል። እባክዎ Chromiumን እንደገና ያውርዱት።</translation>
 <translation id="2661879430930417727">መሣሪያ የሚያጋሩ ከሆኑ ጓደኛዎች እና ቤተሰብ ተለይተው ሊያስሱ እና Chromiumን በሚፈልጉበት መንገድ ማዋቀር ይችላሉ</translation>
+<translation id="268602741124540128">እንኳን ወደ Chromium በደህና መጡ <ph name="ACCOUNT_FIRST_NAME" /></translation>
 <translation id="2711502716910134313">የChromium ትር</translation>
 <translation id="2718390899429598676">ለተጨማሪ ደህንነት ሲባል Chromium ውሂብዎን ያመሰጥረዋል።</translation>
 <translation id="2770231113462710648">ነባሪ አሳሽን ወደዚህ ቀይር፦</translation>
@@ -119,9 +120,11 @@
 <translation id="3830894615770080216">የChromiumOS ስርዓት</translation>
 <translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
 <translation id="386822487697155367">ChromiumOS ላይ እገዛ ያግኙ</translation>
+<translation id="3871664619793219264">የChromium አሳሽ ነገሮችዎን ከ<ph name="ACCOUNT_EMAIL" /> ያግኙ</translation>
 <translation id="388648406173476553">Chromiumን ያብጁ እና ይቆጣጠሩ። የሆነ ነገር ትኩረትዎ ያስፈልገዋል - ለዝርዝሮች ጠቅ ያድርጉ።</translation>
 <translation id="3889543394854987837">Chromiumን ለመክፈት እና ማሰስ ለመጀመር ስምዎን ጠቅ ያድርጉት።</translation>
 <translation id="390528597099634151"><ph name="EXISTING_USER" /> አስቀድመው ወደዚህ የChromium መገለጫ ገብተዋል። አሰሳዎን የተለየ እንደሆነ ለማቆየት Chromium የራስዎን መገለጫ ለእርስዎ መፍጠር ይችላል።</translation>
+<translation id="391789666908693569">የእርስዎ መለያ የሚተዳደረው በ<ph name="MANAGER_NAME" /> ነው። የእርስዎ አስተዳዳሪ ይህንን የChrome አሳሽ መገለጫ እና እንደ እልባቶች፣ ታሪክ እና የይለፍ ቃላት ያሉ ውሂቡን መመልከት እና ማርትዕ ይችላሉ።</translation>
 <translation id="3945058413678539331">Chromium የይለፍ ቃላትን ለመቅዳት እየሞከረ ነው። ይህንን ለመፍቀድ የWindows የይለፍ ቃልዎን ይተይቡ።</translation>
 <translation id="3962623956404948996">Chromium ይህ ፋይል አደገኛ ሊሆን ስለሚችል እንዲቃኙት ይመክራል</translation>
 <translation id="3997429360543082038">ስለChromiumOS</translation>
diff --git a/chrome/app/resources/chromium_strings_no.xtb b/chrome/app/resources/chromium_strings_no.xtb
index cc0804a..908377a5 100644
--- a/chrome/app/resources/chromium_strings_no.xtb
+++ b/chrome/app/resources/chromium_strings_no.xtb
@@ -59,6 +59,7 @@
 <translation id="2583187216237139145">Alle Chromium-data som genereres mens denne profilen brukes (f.eks. oppretting av bokmerker, logg, passord og andre innstillinger), kan fjernes av administratoren for jobbprofilen. <ph name="LEARN_MORE" /></translation>
 <translation id="2648074677641340862">Det oppsto en systemfeil under installering. Last ned Chromium på nytt.</translation>
 <translation id="2661879430930417727">Hvis du deler en enhet med andre, kan venner og familie surfe hver for seg og konfigurere Chromium akkurat slik de vil</translation>
+<translation id="268602741124540128">Velkommen til Chromium, <ph name="ACCOUNT_FIRST_NAME" /></translation>
 <translation id="2711502716910134313">Chromium-fane</translation>
 <translation id="2718390899429598676">Chromium krypterer dataene dine for å øke sikkerheten.</translation>
 <translation id="2770231113462710648">Endre standardnettleser til:</translation>
@@ -117,9 +118,11 @@
 <translation id="3830894615770080216">ChromiumOS-systemet</translation>
 <translation id="3848258323044014972"><ph name="PAGE_TITLE" /> – Chromium</translation>
 <translation id="386822487697155367">Få hjelp med ChromiumOS</translation>
+<translation id="3871664619793219264">Få Chromium-nettlesertingene dine fra <ph name="ACCOUNT_EMAIL" /></translation>
 <translation id="388648406173476553">Tilpass og kontrollér Chromium. Det er noe du må se på – klikk for mer informasjon.</translation>
 <translation id="3889543394854987837">Klikk på navnet ditt for å åpne Chromium og starte surfingen.</translation>
 <translation id="390528597099634151"><ph name="EXISTING_USER" /> er allerede logget på denne Chromium-profilen. For å holde surfingen din atskilt kan Chromium opprette en egen profil til deg.</translation>
+<translation id="391789666908693569">Kontoen din administreres av <ph name="MANAGER_NAME" />. Administratoren kan se og redigere denne Chromium-nettleserprofilen og tilhørende data, som bokmerker, logg og passord.</translation>
 <translation id="3945058413678539331">Chromium prøver å kopiere passord. Skriv inn Windows-passordet ditt for å tillate dette.</translation>
 <translation id="3962623956404948996">Chromium anbefaler å skanne denne filen ettersom den kan være farlig</translation>
 <translation id="3997429360543082038">Om ChromiumOS</translation>
diff --git a/chrome/app/resources/chromium_strings_or.xtb b/chrome/app/resources/chromium_strings_or.xtb
index be5bac4..35f1f72 100644
--- a/chrome/app/resources/chromium_strings_or.xtb
+++ b/chrome/app/resources/chromium_strings_or.xtb
@@ -61,6 +61,7 @@
 <translation id="2583187216237139145">ଏହି ପ୍ରୋଫାଇଲର ବ୍ୟବହାର ସମୟରେ ସୃଷ୍ଟି ହୋଇଥିବା ଯେ କୌଣସି Chromium ଡାଟା (ଯେପରି ବୁକମାର୍କ୍, ଇତିହାସ, ପାସୱାର୍ଡ ଏବଂ ଅନ୍ୟ ସେଟିଂସର କ୍ରିଏସନ୍) ୱାର୍କ ପ୍ରୋଫାଇଲ୍ ଆଡମିନିଷ୍ଟ୍ରେଟରଙ୍କ ଦ୍ୱାରା କାଢ଼ି ଦିଆଯାଇପାରିବ। <ph name="LEARN_MORE" /></translation>
 <translation id="2648074677641340862">ଇନ୍‍ଷ୍ଟଲେସନ୍ ସମୟରେ ଏକ ଅପରେଟିଂ ସିଷ୍ଟମ୍ ତ୍ରୁଟି ଦେଖାଦେଲା। ଦୟାକରି Chromium ପୁଣି ଡାଉନ୍‌ଲୋଡ୍ କରନ୍ତୁ।</translation>
 <translation id="2661879430930417727">ଯଦି ଆପଣ ଏକ ଡିଭାଇସକୁ ସେୟାର୍ କରନ୍ତି, ତେବେ ସାଙ୍ଗ ଏବଂ ପରିବାରର ଲୋକମାନେ ଅଲଗା ଭାବରେ ବ୍ରାଉଜ୍ କରିପାରିବେ ଓ ସେମାନଙ୍କ ପସନ୍ଦ ଅନୁସାରେ Chromiumକୁ ସେଟ୍ ଅପ୍ କରିପାରିବେ</translation>
+<translation id="268602741124540128">Chromiumକୁ ସ୍ଵାଗତ, <ph name="ACCOUNT_FIRST_NAME" /></translation>
 <translation id="2711502716910134313">Chromium ଟାବ୍</translation>
 <translation id="2718390899429598676">ଅତିରିକ୍ତ ସୁରକ୍ଷା ପାଇଁ, Chromium ଆପଣଙ୍କର ଡାଟା ଏନ୍‍କ୍ରିପ୍ଟ କରିବ।</translation>
 <translation id="2770231113462710648">ଏଠାକୁ ଡିଫଲ୍ଟ ବ୍ରାଉଜର୍‌କୁ ପରିବର୍ତ୍ତନ କରନ୍ତୁ:</translation>
@@ -119,9 +120,11 @@
 <translation id="3830894615770080216">ChromiumOS ସିଷ୍ଟମ</translation>
 <translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
 <translation id="386822487697155367">ChromiumOS ମାଧ୍ୟମରେ ସାହାଯ୍ୟ ପାଆନ୍ତୁ</translation>
+<translation id="3871664619793219264"><ph name="ACCOUNT_EMAIL" />ରୁ ଆପଣଙ୍କ Chromium ବ୍ରାଉଜର ଷ୍ଟଫ ପାଆନ୍ତୁ</translation>
 <translation id="388648406173476553">Chromium କଷ୍ଟମାଇଜ୍ ଓ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ କିଛି ଆପଣଙ୍କର ଧ୍ୟାନ ଦେବା ଆବଶ୍ୟକ କରୁଛି - ବିବରଣୀ ପାଇଁ କ୍ଲିକ୍ କରନ୍ତୁ।</translation>
 <translation id="3889543394854987837">Chromium ଖୋଲିବା ପାଇଁ ଆପଣଙ୍କର ନାମ ଉପରେ କ୍ଲିକ୍ କରନ୍ତୁ ଏବଂ ବ୍ରାଉଜ୍ କରିବା ଆରମ୍ଭ କରନ୍ତୁ।</translation>
 <translation id="390528597099634151"><ph name="EXISTING_USER" /> ଏହି Chromium ପ୍ରୋଫାଇଲରେ ପୂର୍ବରୁ ସାଇନ୍ ଇନ୍ କରିସାରିଛନ୍ତି। ଆପଣଙ୍କ ବ୍ରାଉଜିଂକୁ ଅଲଗା ରଖିବା ପାଇଁ, Chromium ଆପଣଙ୍କ ପାଇଁ ଆପଣଙ୍କର ନିଜର ପ୍ରୋଫାଇଲ୍ ତିଆରି କରିପାରିବ।</translation>
+<translation id="391789666908693569">ଆପଣଙ୍କ ଆକାଉଣ୍ଟ <ph name="MANAGER_NAME" />ଙ୍କ ଦ୍ୱାରା ପରିଚାଳନା କରାଯାଉଛି। ଆପଣଙ୍କ ଆଡମିନିଷ୍ଟ୍ରେଟର ଏହି Chromium ବ୍ରାଉଜର ପ୍ରୋଫାଇଲ ଏବଂ ଏହାର ବୁକମାର୍କ, ଇତିହାସ ଏବଂ ପାସୱାର୍ଡଗୁଡ଼ିକ ପରି ଡାଟାକୁ ଦେଖିପାରିବେ ଓ ଏଡିଟ କରିପାରିବେ।</translation>
 <translation id="3945058413678539331">Chromium ପାସୱାର୍ଡଗୁଡ଼ିକ କପି କରିବାକୁ ଚେଷ୍ଟା କରୁଛି। ଏହାକୁ ଅନୁମତି ଦେବା ପାଇଁ ଆପଣଙ୍କର Windows ପାସୱାର୍ଡ ଟାଇପ୍ କରନ୍ତୁ।</translation>
 <translation id="3962623956404948996">ଏହି ଫାଇଲଟି ବିପଦଜନକ ହୋଇଥାଇପାରେ ବୋଲି Chromium ଏହାକୁ ସ୍କାନ କରିବାକୁ ସୁପାରିଶ କରୁଛି</translation>
 <translation id="3997429360543082038">ChromiumOS ବିଷୟରେ</translation>
diff --git a/chrome/app/resources/chromium_strings_pa.xtb b/chrome/app/resources/chromium_strings_pa.xtb
index 9d3a2d7..3ae7869 100644
--- a/chrome/app/resources/chromium_strings_pa.xtb
+++ b/chrome/app/resources/chromium_strings_pa.xtb
@@ -61,6 +61,7 @@
 <translation id="2583187216237139145">ਇਸ ਪ੍ਰੋਫਾਈਲ ਦੀ ਵਰਤੋਂ ਦੇ ਦੌਰਾਨ ਤਿਆਰ ਕੀਤਾ ਕੋਈ ਵੀ Chromium ਡਾਟਾ (ਜਿਵੇਂ ਕਿ ਬੁੱਕਮਾਰਕ, ਇਤਿਹਾਸ, ਪਾਸਵਰਡ ਅਤੇ ਹੋਰ ਸੈਟਿੰਗਾਂ ਦੀ ਰਚਨਾ) ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਹਟਾਇਆ ਜਾ ਸਕਦਾ ਹੈ। <ph name="LEARN_MORE" /></translation>
 <translation id="2648074677641340862">ਸਥਾਪਤ ਕਰਨ ਦੌਰਾਨ ਇੱਕ ਓਪਰੇਟਿੰਗ ਸਿਸਟਮ ਵਿੱਚ ਗੜਬੜ ਹੋਈ। ਕਿਰਪਾ ਕਰਕੇ Chromium ਨੂੰ ਦੁਬਾਰਾ ਡਾਊਨਲੋਡ ਕਰੋ।</translation>
 <translation id="2661879430930417727">ਜੇ ਤੁਸੀਂ ਕੋਈ ਡੀਵਾਈਸ ਸਾਂਝਾ ਕਰਦੇ ਹੋ, ਤਾਂ ਦੋਸਤ ਅਤੇ ਪਰਿਵਾਰ ਵੱਖਰੇ ਤੌਰ 'ਤੇ ਬ੍ਰਾਊਜ਼ ਕਰ ਸਕਦੇ ਹਨ ਅਤੇ ਆਪਣੇ ਤਰੀਕੇ ਨਾਲ Chromium ਦਾ ਸੈੱਟਅੱਪ ਕਰ ਸਕਦੇ ਹਨ</translation>
+<translation id="268602741124540128">Chromium ਵਿੱਚ ਜੀ ਆਇਆਂ ਨੂੰ, <ph name="ACCOUNT_FIRST_NAME" /></translation>
 <translation id="2711502716910134313">Chromium ਟੈਬ</translation>
 <translation id="2718390899429598676">ਵਾਧੂ ਸੁਰੱਖਿਆ ਲਈ, Chromium ਤੁਹਾਡਾ ਡਾਟਾ ਐਨਕ੍ਰਿਪਟ ਕਰੇਗਾ।</translation>
 <translation id="2770231113462710648">ਪੂਰਵ-ਨਿਰਧਾਰਤ ਬ੍ਰਾਊਜ਼ਰ ਨੂੰ ਇਸ ਵਿੱਚ ਬਦਲੋ:</translation>
@@ -119,9 +120,11 @@
 <translation id="3830894615770080216">ChromiumOS ਸਿਸਟਮ</translation>
 <translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
 <translation id="386822487697155367">ChromiumOS ਬਾਰੇ ਮਦਦ ਪ੍ਰਾਪਤ ਕਰੋ</translation>
+<translation id="3871664619793219264"><ph name="ACCOUNT_EMAIL" /> ਤੋਂ ਆਪਣੀ Chromium ਬ੍ਰਾਊਜ਼ਰ ਸਮੱਗਰੀ ਪ੍ਰਾਪਤ ਕਰੋ</translation>
 <translation id="388648406173476553">Chromium ਨੂੰ ਵਿਉਂਤਬੱਧ ਕਰਕੇ ਕੰਟਰੋਲ ਕਰੋ। ਕਿਸੇ ਚੀਜ਼ ਨੂੰ ਤੁਹਾਡੇ ਧਿਆਨ ਦੇਣ ਦੀ ਲੋੜ ਹੈ - ਵੇਰਵਿਆਂ ਲਈ ਕਲਿੱਕ ਕਰੋ।</translation>
 <translation id="3889543394854987837">Chromium ਨੂੰ ਖੋਲ੍ਹਣ ਲਈ ਆਪਣੇ ਨਾਮ 'ਤੇ ਕਲਿੱਕ ਕਰੋ ਅਤੇ ਬ੍ਰਾਊਜ਼ ਕਰਨਾ ਸ਼ੁਰੂ ਕਰੋ।</translation>
 <translation id="390528597099634151"><ph name="EXISTING_USER" /> ਪਹਿਲਾਂ ਤੋਂ ਹੀ ਇਸ Chromium ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਸਾਈਨ-ਇਨ ਹੈ। ਤੁਹਾਡੀ ਬ੍ਰਾਊਜ਼ਿੰਗ ਨੂੰ ਵੱਖਰਾ ਰੱਖਣ ਲਈ, Chromium ਤੁਹਾਡੇ ਲਈ ਤੁਹਾਡਾ ਖੁਦ ਦਾ ਪ੍ਰੋਫਾਈਲ ਬਣਾ ਸਕਦਾ ਹੈ।</translation>
+<translation id="391789666908693569">ਤੁਹਾਡਾ ਖਾਤਾ <ph name="MANAGER_NAME" /> ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਤੁਹਾਡਾ ਪ੍ਰਸ਼ਾਸਕ ਇਸ Chromium ਬ੍ਰਾਊਜ਼ਰ ਪ੍ਰੋਫਾਈਲ ਅਤੇ ਇਸਦੇ ਡਾਟੇ ਨੂੰ ਦੇਖ ਸਕਦਾ ਹੈ ਅਤੇ ਇਸਦਾ ਸੰਪਾਦਨ ਕਰ ਸਕਦਾ ਹੈ, ਜਿਵੇਂ ਕਿ ਬੁੱਕਮਾਰਕ, ਇਤਿਹਾਸ ਅਤੇ ਪਾਸਵਰਡ।</translation>
 <translation id="3945058413678539331">Chromium ਪਾਸਵਰਡਾਂ ਨੂੰ ਕਾਪੀ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰ ਰਿਹਾ ਹੈ। ਇਹ ਕਰਨ ਦੇਣ ਲਈ ਆਪਣਾ ਵਿੰਡੋ ਪਾਸਵਰਡ ਟਾਈਪ ਕਰੋ।</translation>
 <translation id="3962623956404948996">Chromium ਵੱਲੋਂ ਇਸ ਫ਼ਾਈਲ ਨੂੰ ਸਕੈਨ ਕਰਨ ਦੀ ਸਿਫ਼ਾਰਸ਼ ਕੀਤੀ ਜਾਂਦੀ ਹੈ ਕਿਉਂਕਿ ਇਹ ਹਾਨੀਕਾਰਕ ਹੋ ਸਕਦੀ ਹੈ</translation>
 <translation id="3997429360543082038">ChromiumOS ਬਾਰੇ</translation>
diff --git a/chrome/app/resources/chromium_strings_pt-BR.xtb b/chrome/app/resources/chromium_strings_pt-BR.xtb
index 399ee13..18f3b9e39 100644
--- a/chrome/app/resources/chromium_strings_pt-BR.xtb
+++ b/chrome/app/resources/chromium_strings_pt-BR.xtb
@@ -59,6 +59,7 @@
 <translation id="2583187216237139145">Quaisquer dados do Chromium gerados quando este perfil estiver sendo usado (como a criação de favoritos, histórico, senhas e outras configurações) podem ser removidos pelo administrador do perfil de trabalho. <ph name="LEARN_MORE" /></translation>
 <translation id="2648074677641340862">Ocorreu um erro no sistema operacional durante a instalação. Faça o download do Chromium novamente.</translation>
 <translation id="2661879430930417727">Se você compartilha um dispositivo, seus amigos e familiares podem navegar separadamente e configurar o Chromium da maneira que quiserem</translation>
+<translation id="268602741124540128">Bem-vindo ao Chromium, <ph name="ACCOUNT_FIRST_NAME" /></translation>
 <translation id="2711502716910134313">Guia do Chromium</translation>
 <translation id="2718390899429598676">Para maior segurança, o Chromium criptografará seus dados.</translation>
 <translation id="2770231113462710648">Alterar navegador padrão para:</translation>
@@ -115,9 +116,11 @@
 <translation id="3830894615770080216">Sistema ChromiumOS</translation>
 <translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
 <translation id="386822487697155367">Receber ajuda com o ChromiumOS</translation>
+<translation id="3871664619793219264">Acesse os dados do navegador Chromium pela conta <ph name="ACCOUNT_EMAIL" /></translation>
 <translation id="388648406173476553">Personalize e controle o Chromium. Algo precisa da sua atenção. Clique para ver mais detalhes.</translation>
 <translation id="3889543394854987837">Clique no seu nome para abrir o Chromium e começar a navegar.</translation>
 <translation id="390528597099634151">A conta de <ph name="EXISTING_USER" /> já está conectada a este perfil do Chromium. Para manter sua navegação separada, o Chromium pode criar um perfil só para você.</translation>
+<translation id="391789666908693569">Sua conta é gerenciada por <ph name="MANAGER_NAME" />. Seu administrador pode ver e editar este perfil do navegador Chromium e os dados dele, como favoritos, histórico e senhas.</translation>
 <translation id="3945058413678539331">O Chromium está tentando copiar senhas. Digite a senha do Windows para permitir essa ação.</translation>
 <translation id="3962623956404948996">O Chromium recomenda verificar esse arquivo porque ele pode ser perigoso</translation>
 <translation id="3997429360543082038">Sobre o ChromiumOS</translation>
diff --git a/chrome/app/resources/chromium_strings_sr-Latn.xtb b/chrome/app/resources/chromium_strings_sr-Latn.xtb
index eea84c49..a82d497a 100644
--- a/chrome/app/resources/chromium_strings_sr-Latn.xtb
+++ b/chrome/app/resources/chromium_strings_sr-Latn.xtb
@@ -61,6 +61,7 @@
 <translation id="2583187216237139145">Administrator poslovnog profila može da ukloni sve podatke Chromium-a koji se generišu tokom korišćenja ovog profila (poput pravljenja obeleživača, istorije, lozinki i drugih podešavanja). <ph name="LEARN_MORE" /></translation>
 <translation id="2648074677641340862">Tokom instalacije je došlo do greške u operativnom sistemu. Preuzmite Chromium ponovo.</translation>
 <translation id="2661879430930417727">Ako delite uređaj, prijatelji i porodica mogu zasebno da pregledaju i da podese Chromium baš onako kako žele</translation>
+<translation id="268602741124540128">Dobro došli u Chromium, <ph name="ACCOUNT_FIRST_NAME" /></translation>
 <translation id="2711502716910134313">Kartica Chromium</translation>
 <translation id="2718390899429598676">Chromium će šifrovati podatke radi dodatne sigurnosti.</translation>
 <translation id="2770231113462710648">Promeni podrazumevani pregledač u:</translation>
@@ -119,9 +120,11 @@
 <translation id="3830894615770080216">Sistem Chromium OS</translation>
 <translation id="3848258323044014972"><ph name="PAGE_TITLE" /> – Chromium</translation>
 <translation id="386822487697155367">Pronađite pomoć za Chromium OS</translation>
+<translation id="3871664619793219264">Preuzmite sadržaj iz Chromium pregledača sa: <ph name="ACCOUNT_EMAIL" /></translation>
 <translation id="388648406173476553">Prilagodite i kontrolišite Chromium. Treba da obratite pažnju na nešto – kliknite za više detalja.</translation>
 <translation id="3889543394854987837">Kliknite na ime da biste otvorili Chromium i počnite da pregledate.</translation>
 <translation id="390528597099634151">Korisnik <ph name="EXISTING_USER" /> je već prijavljen na ovaj Chromium profil. Da bi vam pregledanje bilo razdvojeno, Chromium može da napravi zaseban profil za vas.</translation>
+<translation id="391789666908693569">Vašim nalogom upravlja <ph name="MANAGER_NAME" />. Administrator može da vidi i menja ovaj profil u Chromium pregledaču i njegove podatke, poput obeleživača, istorije i lozinki.</translation>
 <translation id="3945058413678539331">Chromium pokušava da kopira lozinke. Unesite lozinku za Windows da biste to omogućili.</translation>
 <translation id="3962623956404948996">Chromium preporučuje skeniranje ovog fajla jer može da bude opasan</translation>
 <translation id="3997429360543082038">O Chromium OS-u</translation>
diff --git a/chrome/app/resources/chromium_strings_sr.xtb b/chrome/app/resources/chromium_strings_sr.xtb
index ed77fc5..9411779 100644
--- a/chrome/app/resources/chromium_strings_sr.xtb
+++ b/chrome/app/resources/chromium_strings_sr.xtb
@@ -61,6 +61,7 @@
 <translation id="2583187216237139145">Администратор пословног профила може да уклони све податке Chromium-а који се генеришу током коришћења овог профила (попут прављења обележивача, историје, лозинки и других подешавања). <ph name="LEARN_MORE" /></translation>
 <translation id="2648074677641340862">Током инсталације је дошло до грешке у оперативном систему. Преузмите Chromium поново.</translation>
 <translation id="2661879430930417727">Ако делите уређај, пријатељи и породица могу засебно да прегледају и да подесе Chromium баш онако како желе</translation>
+<translation id="268602741124540128">Добро дошли у Chromium, <ph name="ACCOUNT_FIRST_NAME" /></translation>
 <translation id="2711502716910134313">Картица Chromium</translation>
 <translation id="2718390899429598676">Chromium ће шифровати податке ради додатне сигурности.</translation>
 <translation id="2770231113462710648">Промени подразумевани прегледач у:</translation>
@@ -119,9 +120,11 @@
 <translation id="3830894615770080216">Систем Chromium ОС</translation>
 <translation id="3848258323044014972"><ph name="PAGE_TITLE" /> – Chromium</translation>
 <translation id="386822487697155367">Пронађите помоћ за Chromium OS</translation>
+<translation id="3871664619793219264">Преузмите садржај из Chromium прегледача са: <ph name="ACCOUNT_EMAIL" /></translation>
 <translation id="388648406173476553">Прилагодите и контролишите Chromium. Треба да обратите пажњу на нешто – кликните за више детаља.</translation>
 <translation id="3889543394854987837">Кликните на име да бисте отворили Chromium и почните да прегледате.</translation>
 <translation id="390528597099634151">Корисник <ph name="EXISTING_USER" /> је већ пријављен на овај Chromium профил. Да би вам прегледање било раздвојено, Chromium може да направи засебан профил за вас.</translation>
+<translation id="391789666908693569">Вашим налогом управља <ph name="MANAGER_NAME" />. Администратор може да види и мења овај профил у Chromium прегледачу и његове податке, попут обележивача, историје и лозинки.</translation>
 <translation id="3945058413678539331">Chromium покушава да копира лозинке. Унесите лозинку за Windows да бисте то омогућили.</translation>
 <translation id="3962623956404948996">Chromium препоручује скенирање овог фајла јер може да буде опасан</translation>
 <translation id="3997429360543082038">О Chromium ОС-у</translation>
diff --git a/chrome/app/resources/chromium_strings_ur.xtb b/chrome/app/resources/chromium_strings_ur.xtb
index 14c6bda..0af9a151 100644
--- a/chrome/app/resources/chromium_strings_ur.xtb
+++ b/chrome/app/resources/chromium_strings_ur.xtb
@@ -61,6 +61,7 @@
 <translation id="2583187216237139145">‏دفتری پروفائل کا منتظم اس پروفائل کے استعمال کے دوران جنریٹ ہونے والے کسی بھی Chromium ڈیٹا (جیسے، بُک مارکس کی تخلیق، سرگزشت، پاس ورڈز اور دیگر ترتیبات) کو ہٹا سکتا ہے۔ <ph name="LEARN_MORE" /></translation>
 <translation id="2648074677641340862">‏انسٹالیشن کے دوران آپریٹنگ سسٹم کی ایک خرابی پیش آ گئی۔ براہ کرم Chromium دوبارہ ڈاؤن لوڈ کریں۔</translation>
 <translation id="2661879430930417727">‏اگر آپ کسی آلے کا اشتراک کرتے ہیں تو دوست اور اہل خانہ الگ الگ براؤز کر سکتے ہیں اور Chromium کو اپنی مرضی کے مطابق سیٹ اپ کر سکتے ہیں</translation>
+<translation id="268602741124540128">‏Chromium میں خوش آمدید، <ph name="ACCOUNT_FIRST_NAME" /></translation>
 <translation id="2711502716910134313">‏Chromium ٹیب</translation>
 <translation id="2718390899429598676">‏اضافی سیکیورٹی کیلئے، Chromium آپ کا ڈیٹا مرموز کر دے گا۔</translation>
 <translation id="2770231113462710648">ڈیفالٹ براؤزر کو اس میں تبدیل کریں:</translation>
@@ -119,9 +120,11 @@
 <translation id="3830894615770080216">‏ChromiumOS سسٹم</translation>
 <translation id="3848258323044014972">‎<ph name="PAGE_TITLE" /> - Chromium</translation>
 <translation id="386822487697155367">‏ChromiumOS کے بارے میں مدد حاصل کریں</translation>
+<translation id="3871664619793219264">‏<ph name="ACCOUNT_EMAIL" /> سے اپنے Chromium براؤزر کا مواد حاصل کریں</translation>
 <translation id="388648406173476553">‏Chromium کو حسب ضرورت بنائیں اور کنٹرول کریں۔ کچھ چیزوں کو آپ کی توجہ درکار ہے۔ تفصیلات کیلئے کلک کریں۔</translation>
 <translation id="3889543394854987837">‏Chromium کو کھولنے اور براؤزنگ شروع کرنے کیلئے اپنے نام پر کلک کریں۔</translation>
 <translation id="390528597099634151">‏<ph name="EXISTING_USER" /> اس Chromium پروفائل میں پہلے سے سائن ان ہے۔ اپنی براؤزنگ کو الگ رکھنے کیلئے، Chromium آپ کیلئے آپ کی ذاتی پروفائل تخلیق کر سکتا ہے۔</translation>
+<translation id="391789666908693569">‏<ph name="MANAGER_NAME" /> آپ کے اکاؤنٹ کا نظم کرتا ہے۔ آپ کا منتظم اس Chromium براؤزر کی پروفائل اور اس کا ڈیٹا جیسے بُک مارکس، سرگزشت اور پاس ورڈز دیکھ اور ان میں ترمیم کر سکتا ہے۔</translation>
 <translation id="3945058413678539331">‏Chromium پاس ورڈز کاپی کرنے کی کوشش کر رہا ہے۔ اس کی اجازت دینے کے لیے اپنا Windows پاس ورڈ ٹائپ کریں۔</translation>
 <translation id="3962623956404948996">‏Chromium اس فائل کو اسکین کرنے کی تجویز کرتا ہے کیونکہ یہ خطرناک ہو سکتی ہے</translation>
 <translation id="3997429360543082038">‏ChromiumOS کے بارے میں</translation>
diff --git a/chrome/app/resources/generated_resources_am.xtb b/chrome/app/resources/generated_resources_am.xtb
index 774995b..25141b3 100644
--- a/chrome/app/resources/generated_resources_am.xtb
+++ b/chrome/app/resources/generated_resources_am.xtb
@@ -1014,6 +1014,7 @@
 <translation id="1944921356641260203">ዝማኔ ተገኝቷል</translation>
 <translation id="1947136734041527201">በማንነት አገልግሎት ያለዎትን መለያ ተጠቅመው ወደ ድር ጣቢያዎች እንዲገቡ ያስችልዎታል</translation>
 <translation id="1949584741547056205">ፈጣን መልሶች</translation>
+<translation id="1949849604471335579">ልጣፍ፣ የማያ ገጽ ማቆያ፣ የቀለማት ቅልሞች እና ሌሎችንም ያብጁ</translation>
 <translation id="1951012854035635156">ረዳት</translation>
 <translation id="1954597385941141174">ጣቢያዎች ከዩኤስቢ መሣሪያዎች ጋር ለመገናኘት መጠየቅ ይችላሉ</translation>
 <translation id="1954813140452229842">ማጋራትን ማፈናጠጥ ላይ ስህተት። እባክዎ ምስክርነቶችዎን ይፈትሹና እንደገና ይሞክሩ።</translation>
@@ -1045,6 +1046,7 @@
 <translation id="1981434377190976112">ሁሉንም መረጃዎችዎን በሁሉም ድር ጣቢያዎች ላይ ያንብቡ</translation>
 <translation id="1984417487208496350">ምንም ጥበቃ የለም (አይመከርም)</translation>
 <translation id="1987317783729300807">መለያዎች</translation>
+<translation id="1987574314042117472">የታወቁ መተግበሪያዎችን ምረጥ እና ጫን</translation>
 <translation id="1988259784461813694">መስፈርት</translation>
 <translation id="1989112275319619282">አስስ</translation>
 <translation id="1989903373608997757">ሁልጊዜ ይጠቀሙ</translation>
@@ -1110,6 +1112,7 @@
 <translation id="2048554637254265991">የመያዣ አስተዳዳሪውን ማስጀመር ላይ ስሕተት። እባክዎ እንደገና ይሞክሩ።</translation>
 <translation id="2048653237708779538">እርምጃ አይገኝም</translation>
 <translation id="2050339315714019657">በቁመት</translation>
+<translation id="2052572566310583903">በሌሎች መሣሪያዎችዎ ላይ ተጭነዋል</translation>
 <translation id="2053312383184521053">የስራ-ፈት ሁኔታ ውሂብ</translation>
 <translation id="2054240652864153171">በ<ph name="PARTITION_SITE_NAME" /> ላይ የተከፋፈለው የ<ph name="SITE_NAME" /> የጣቢያ ውሂብ ይጽዳ?</translation>
 <translation id="2055585478631012616">ክፍት ትሮችን ጨምሮ ከእነዚህ ጣቢያዎች ዘግተው እንዲወጡ ይደረጋሉ</translation>
@@ -1272,6 +1275,7 @@
 <translation id="2191754378957563929">አብራ</translation>
 <translation id="2192505247865591433">ከ፦</translation>
 <translation id="2193365732679659387">የእምነት ቅንብሮች</translation>
+<translation id="2194554416429452547">በሙከራዎች ጊዜ ላይ Chrome አይፈለጌ መልዕክትን፣ ማጭበርበርን እና በጣቢያዎች መካከል መጋራትን የሚገድብበትን መንገዶች እያሰሰ ነው። Chrome እንዲሁም ጣቢያዎች ማስታወቂያዎችን ለእርስዎ ለማሳየት ሊጠቀሙባቸው የሚችሏቸውን <ph name="ESTIMATE_INTERESTS_LINK" />። የእርስዎን ዝንባሌዎች በቅንብሮች ውስጥ ማቀናበር ይችላሉ።</translation>
 <translation id="2194856509914051091">ከግምት ውስጥ መግባት ያለባቸው ነገሮች</translation>
 <translation id="2195331105963583686">ከዚያ ጊዜ በኋላ አሁንም ይህን <ph name="DEVICE_TYPE" /> መጠቀም ይችላሉ፣ ነገር ግን ከእንግዲህ ራስ-ሰር የሶፍትዌር እና የደህንነት ዝማኔዎችን አያገኝም</translation>
 <translation id="2195729137168608510">የኢሜይል መከላከያ</translation>
@@ -1877,6 +1881,7 @@
 <translation id="2749836841884031656">ሲም</translation>
 <translation id="2749881179542288782">ሰዋሰው እና ሆሄ አርም</translation>
 <translation id="2753677631968972007">የጣቢያ ፈቃዶችን ራስዎ ይቆጣጠሩ።</translation>
+<translation id="2754825024506485820">በGoogle Play መደብር ላይ ከምርታማነት እስከ መዝናኛ ያሉ የሚያስፈልጉዎትን መተግበሪያዎች ያግኙ። መተግበሪያዎችን በማንኛውም ጊዜ መጫን ይችላሉ።</translation>
 <translation id="2755349111255270002">ይህን <ph name="DEVICE_TYPE" /> ዳግም አቀናብር</translation>
 <translation id="2755367719610958252">የተደራሽነት ባህሪያትን ያቀናብሩ</translation>
 <translation id="275662540872599901">ማያ ገጽ ጠፍቷል</translation>
@@ -1953,6 +1958,7 @@
 <translation id="2815693974042551705">የዕልባት አቃፊ</translation>
 <translation id="2816319641769218778">የይለፍ ቃላትን ውወደ Google መለያዎ ለማስቀመት ስምረትን ያብሩ።</translation>
 <translation id="2816628817680324566">ይህ ጣቢያ የደህንነት ቁልፍዎ እንዲለይ ይፈቀድለት?</translation>
+<translation id="2817435998497102771">የእርስዎን ልጣፍ እና ቅጥ ያቀናብሩ</translation>
 <translation id="2818476747334107629">የአታሚ ዝርዝሮች</translation>
 <translation id="2819167288942847344">መተግበሪያው አጉል ባህሪ እንዳያሳይ ለመከላከል ለስልክ፣ ለጡባዊ ወይም መጠናቸው ለሚቀየር መስኮቶች የሆኑ ቅድመ-ቅምጦችን ይጠቀሙ</translation>
 <translation id="2820957248982571256">በመቃኘት ላይ...</translation>
@@ -2846,6 +2852,7 @@
 <translation id="3727144509609414201">የሚገኙ የWiFi አውታረ መረቦች</translation>
 <translation id="3727187387656390258">ብቅባይ መርምር</translation>
 <translation id="372722114124766626">አንድ ጊዜ ብቻ</translation>
+<translation id="3727332897090187514">ምንም ማስታወሻ አልታከለም</translation>
 <translation id="3727473233247516571">የጀርባ/ፊት መሸጎጫ ንዑስ ክፈፍ፦ <ph name="BACK_FORWARD_CACHE_PAGE_URL" /></translation>
 <translation id="3728188878314831180">ከእርስዎ ስልክ ማሳወቂያዎችን ያንጸባርቁ</translation>
 <translation id="3728681439294129328">የአውታረ መረብ አድራሻን ያዋቅሩ</translation>
@@ -3181,6 +3188,7 @@
 <translation id="4031527940632463547">ዳሳሾች ታግደዋል</translation>
 <translation id="4033415645631238123">ከእንግዲህ በSmart Lock መግባት አይገኝም። አሁንም በSmart Lock መክፈት ይችላሉ።</translation>
 <translation id="4033471457476425443">አዲስ አቃፊ ያክሉ</translation>
+<translation id="4033711848170683365">ይህ የአሰሳ ውሂብን እስከ መጨረሻው ከዚህ መሣሪያ ይሰርዘዋል። በዚህ መገለጫ ውስጥ ያሉት የGoogle መለያዎች በእርስዎ <ph name="DEVICE_TYPE" /> ላይ ባሉ ሌሎች መተግበሪያዎች ስራ ላይ ሊውሉ ይችላሉ። እነዚህን መለያዎች በ<ph name="BEGIN_LINK" /><ph name="SETTING_SECTION" /> &gt; <ph name="ACCOUNTS_SECTION" /><ph name="END_LINK" /> ውስጥ ማስወገድ ይችላሉ።</translation>
 <translation id="4033963223187371752">ደህንነታቸው የተጠበቀ ጣቢያዎች እንደ ምስሎች ወይም የድር ክፈፎች ያለ ደህንነታቸው ያልተጠበቀ ይዘትን ሊያካትቱ ይችሉ ይሆናል</translation>
 <translation id="4034824040120875894">አታሚ</translation>
 <translation id="4035758313003622889">&amp;ተግባር አስተዳዳሪ</translation>
@@ -3457,6 +3465,7 @@
 <translation id="4314815835985389558">ስምረትን ያቀናብሩ</translation>
 <translation id="4315933848520197627">የመለያ ግንኙነትን ያቋርጡ</translation>
 <translation id="4316850752623536204">የገንቢ ድር ጣቢያ</translation>
+<translation id="4317733381297736564">የውስጥ-መተግበሪያ ግዢዎች</translation>
 <translation id="4317820549299924617">ማረጋገጫ አልተሳካም</translation>
 <translation id="4320177379694898372">ምንም የበይነመረብ ግንኙነት የለም</translation>
 <translation id="4322394346347055525">ሌሎች ትሮችን ዝጋ</translation>
@@ -4039,6 +4048,7 @@
 <translation id="4893522937062257019">በማያ ገጽ ቁልፉ ላይ</translation>
 <translation id="4897496410259333978">ለተጨማሪ መረጃ አስተዳዳሪዎን ያነጋግሩ።</translation>
 <translation id="4898011734382862273">የ«<ph name="CERTIFICATE_NAME" />» እውቅና ማረጋገጫ አንድ የእውቅና ማረጋገጫ ባለሥልጣንን ይወክላል</translation>
+<translation id="4899696330053002588">ማስታወቂያዎችን ይዟል</translation>
 <translation id="489985760463306091">ጎጂ ሶፍትዌርን ማስወገዱን ለመጨረስ ኮምፒውተርዎን ዳግም ያስነሱት</translation>
 <translation id="4900392736118574277">የእርስዎ ጅምር ገጽ ወደ <ph name="URL" /> ተቀይሯል።</translation>
 <translation id="490051679772058907"><ph name="REFRESH_RATE" /> ኸዝ - የተጠላለፈ</translation>
@@ -4412,6 +4422,7 @@
 <translation id="52912272896845572">የግል ቁልፍ ፋይል ልክ አይደለም።</translation>
 <translation id="5291739252352359682">በChrome አሳሽ ውስጥ ለሚዲያ የመግለጫ ጽሑፎችን በራስ-ሰር ይፈጥራል (በአሁኑ ጊዜ በእንግሊዝኛ የሚገኝ) ኦዲዮ እና መግለጫ ጽሑፎች በአካባቢ ውስጥ የሚስተናገዱ ሲሆኑ መሣሪያውን በጭራሽ አይተዉት።</translation>
 <translation id="529175790091471945">ይህን መሣሪያ ቅርጸት ይስሩለት</translation>
+<translation id="5292862864186939732">«<ph name="EXTENSION_NAME" />» ሁልጊዜ በ<ph name="ORIGIN" /> ላይ እንዲያሄድ ይፈቀድለት?</translation>
 <translation id="529296195492126134">የበጣም አጭር ጊዜ ሁነታ አይደገፍም እባክዎ አስተዳዳሪዎን ያነጋግሩ</translation>
 <translation id="5293170712604732402">ቅንብሮች ወደ የመጀመሪያቸው ነባሪዎች መልሳቸው</translation>
 <translation id="5294097441441645251">በንዑስ ሆሄ ቁምፊ ወይም የስር መስመር መጀመር አለበት</translation>
@@ -5169,6 +5180,7 @@
 <translation id="6054961935262556546">ታይነትን ቀይር</translation>
 <translation id="6055171183283175969">ያስገቡት የይለፍ ቃል ትክክል ያልሆነ ነው።</translation>
 <translation id="6055392876709372977">PKCS #1 SHA-256 ከRSA ምስጠራ ጋር</translation>
+<translation id="6055544610007596637">ለእርስዎ <ph name="DEVICE_TYPE" /> መተግበሪያዎችን ከGoogle Play መደብር ይጫኑ</translation>
 <translation id="6056710589053485679">መደበኛ ዳግም መጫን</translation>
 <translation id="6057312498756061228">ይህ ፋይል ለደህንነት ፍተሻ በጣም ትልቅ ነው። እስከ 50 ሜባ የሚያህሉ ፋይሎችን መክፈት ይችላሉ።</translation>
 <translation id="6057381398996433816">ይህ ጣቢያ የእንቅስቃሴ እና የብርሃን ዳሳሾችን እንዳይጠቀም ታግዷል።</translation>
@@ -6143,6 +6155,7 @@
 <translation id="7002055706763150362">Smart Lock ለChromebook ለማዘጋጀት Google እርስዎ መሆንዎን እርግጠኛ መሆን ይፈልጋል—ለመጀመር የይለፍ ቃልዎን ይተይቡ።</translation>
 <translation id="7003339318920871147">የድር ውሂብ ጎታዎች</translation>
 <translation id="7003454175711353260">{COUNT,plural, =1{{COUNT} ፋይል}one{{COUNT} ፋይሎች}other{{COUNT} ፋይሎች}}</translation>
+<translation id="7003705861991657723">አልፋ</translation>
 <translation id="7003723821785740825">መሣሪያዎን በበለጠ ፍጥነት የሚከፍቱበት መንገድ ያዋቅሩ</translation>
 <translation id="7003844668372540529">ያልታወቀ ምርት <ph name="PRODUCT_ID" /> ከ<ph name="VENDOR_NAME" /></translation>
 <translation id="7004402701596653846">ጣቢያ midiን መጠቀም ይችላል</translation>
@@ -6159,6 +6172,7 @@
 <translation id="7008815993384338777">በአሁኑ ጊዜ በማዛወር ላይ አይደለም</translation>
 <translation id="7009709314043432820"><ph name="APP_NAME" /> የእርስዎን ካሜራ እየተጠቀመ ነው</translation>
 <translation id="701080569351381435">ሶርስ አሳይ</translation>
+<translation id="7011797924920577670">የእርስዎን ዝንባሌዎች ይገምታል</translation>
 <translation id="7014174261166285193">መጫን አልተሳካም።</translation>
 <translation id="7014480873681694324">ማድመቂያውን አስወግድ</translation>
 <translation id="7017004637493394352">እንደገና «Ok Google» ይበሉ</translation>
@@ -6226,6 +6240,7 @@
 <translation id="7082568314107259011"><ph name="NETWORK_NAME" /> የሚተዳደረው በእርስዎ አስተዳዳሪ ነው</translation>
 <translation id="7085389578340536476">Chrome ኦዲዮን እንዲቀርጽ ይፈቀድለት?</translation>
 <translation id="708550780726587276">(አልተዋቀረም)</translation>
+<translation id="7086531709814430567">እነዚህ ቅጥያዎች ሁልጊዜ በ<ph name="ORIGIN" /> ላይ እንዲያሄዱ ይፈቀድላቸው?</translation>
 <translation id="7086672505018440886">የChrome ምዝግብ ማስታወሻ ፋይሎችን በማህደሩ ውስጥ ያክትቱ።</translation>
 <translation id="7088434364990739311">የዝማኔ ፍተሻ መጀመር አልተሳካም (የስህተት ኮድ <ph name="ERROR" />)።</translation>
 <translation id="7088674813905715446">ይህ መሳሪያ በአስተዳዳሪው ወዳልተከፋፈለ ሁኔታ ተቀምጧል። ለምዝገባ ለማንቃት፣ እባክዎ አስተዳዳሪዎ እየተካሄደ ወዳለ ሁኔታ እንዲለውጠው ያድርጉ።</translation>
@@ -8365,6 +8380,7 @@
 <translation id="9215742531438648683">Google Play መደብርን ያራግፉ</translation>
 <translation id="9218430445555521422">እንደወረደ አዘጋጀው</translation>
 <translation id="9218842937876577955"><ph name="APP_NAME" /> (የማይደገፍ መተግበሪያ)</translation>
+<translation id="9219582468404818260">የተሻለ ድር እንድንገነባ ያግዙን</translation>
 <translation id="9220525904950070496">መለያ ያስወግዱ</translation>
 <translation id="9220820413868316583">ያንሱ እና ከዚያ እንደገና ይሞክሩ።</translation>
 <translation id="923467487918828349">ሁሉንም አሳይ</translation>
diff --git a/chrome/app/resources/generated_resources_bn.xtb b/chrome/app/resources/generated_resources_bn.xtb
index a17c326d..f70d2912 100644
--- a/chrome/app/resources/generated_resources_bn.xtb
+++ b/chrome/app/resources/generated_resources_bn.xtb
@@ -850,6 +850,7 @@
 <translation id="1794051631868188691"><ph name="MERCHANT" /> কখনও দেখতে চাই না</translation>
 <translation id="1794791083288629568">এই সমস্যা সমাধানে আমাদের সাহায্য করতে প্রতিবার্তা পাঠান।</translation>
 <translation id="1795214765651529549">ক্লাসিক ব্যবহার করুন</translation>
+<translation id="1796105431091975902">যোগ করার জন্য কোনও একটি Ansible প্লেবুক বেছে নিন</translation>
 <translation id="1796588414813960292">যেসব ফিচার ব্যবহার করার জন্য সাউন্ড প্রয়োজন সেগুলি কাজ করবে না</translation>
 <translation id="1800502858278951817">কোনও এক্সটেনশন পড়ার এবং <ph name="SITE_NAME" />-এ পরিবর্তন করার অনুরোধ করা হয়নি</translation>
 <translation id="1802624026913571222">ডিভাইসের কভার বন্ধ করলে স্লিপ মোডে চলে যাবে</translation>
@@ -3054,6 +3055,7 @@
 <translation id="389901847090970821">কীবোর্ড বেছে নিন</translation>
 <translation id="3900966090527141178">পাসওয়ার্ড এক্সপোর্ট করুন</translation>
 <translation id="3903187154317825986">আগে থেকেই তৈরি করা কীবোর্ড</translation>
+<translation id="3903191712482985591">প্লেবুক যোগ করুন</translation>
 <translation id="3904326018476041253">লোকেশন ভিত্তিক পরিষেবা</translation>
 <translation id="3904849010307028014">একটি সাইটের সাথে আপনার ইন্টার‌্যাকশনের উপর ভিত্তি করে, যেমন একটি অ্যাকাউন্টে নিয়মিত সাইন-ইন করা ইত্যাদি, সেই সাইটটি আপনার ব্রাউজারে একটি ট্রাস্ট টোকেন ইস্যু করতে পারে। পরবর্তীকালে আপনার ভিজিট করা অন্য়ান্য সাইট কোনও ট্রাস্ট টোকেন খুঁজে পেলে, তারা আপনাকে মানুষই ভাববে, কোনও বট নয়।</translation>
 <translation id="3905761538810670789">অ্যাপ্লিকেশান মেরামত করুন</translation>
@@ -3665,6 +3667,7 @@
 <translation id="4510479820467554003">অভিভাবকীয় অ্যাকাউন্টের তালিকা</translation>
 <translation id="451102079304155829">কার্ট</translation>
 <translation id="4513872120116766993">লেখার সাজেশন</translation>
+<translation id="4513909579793564731">প্লেবুক প্রয়োগ করুন</translation>
 <translation id="4513946894732546136">প্রতিক্রিয়া</translation>
 <translation id="451407183922382411"><ph name="COMPANY_NAME" /> এর দ্বারা চালিত</translation>
 <translation id="4514610446763173167">ভিডিও চালাতে বা থামানোর জন্য টগল করুন</translation>
@@ -5501,6 +5504,7 @@
 <translation id="635609604405270300">ডিভাইসটি চালু রাখুন</translation>
 <translation id="63566973648609420">শুধুমাত্র আপনার পাসফ্রেজসহ কোনো ব্যক্তি আপনার এনক্রিপ্ট করা ডেটা পড়তে পারবেন৷ পাসফ্রেজটি Google-এ পাঠানো হয় না বা এর দ্বারা সংরক্ষণ করা হয় না৷ যদি আপনি আপনার পাসফ্রেজ ভুলে যান বা এই সেটিং পরিবর্তন করতে চান, তাহলে আপনাকে <ph name="BEGIN_LINK" />সিঙ্ক রিসেট<ph name="END_LINK" /> করতে হবে।</translation>
 <translation id="6357305427698525450">কিছু সহায়তা প্রদান করার লিঙ্ক <ph name="APP_NAME" /> বা  <ph name="APP_NAME_2" />-এ এখনও খুলবে।</translation>
+<translation id="6357794994761110294"><ph name="SITE_NAME" />-কে পড়ার ও পরিবর্তন করার অনুমতি কোনও এক্সটেনশনের নেই</translation>
 <translation id="6358884629796491903">ড্রাগন</translation>
 <translation id="6361850914223837199">ত্রুটির বিশদ বিবরণ:</translation>
 <translation id="6362853299801475928">&amp;কোনও সমস্যা অভিযোগ করুন...</translation>
diff --git a/chrome/app/resources/generated_resources_bs.xtb b/chrome/app/resources/generated_resources_bs.xtb
index ea1216c..6b9779b 100644
--- a/chrome/app/resources/generated_resources_bs.xtb
+++ b/chrome/app/resources/generated_resources_bs.xtb
@@ -848,7 +848,7 @@
 <translation id="1794051631868188691">Nikad ne prikazuj <ph name="MERCHANT" /></translation>
 <translation id="1794791083288629568">Šaljite nam povratne informacije kako bismo riješili ovaj problem.</translation>
 <translation id="1795214765651529549">Koristi klasičnu</translation>
-<translation id="1796105431091975902">Odaberite Ansible Playbook za dodavanje</translation>
+<translation id="1796105431091975902">Odaberite vodič Ansible da dodate</translation>
 <translation id="1796588414813960292">Funkcije za koje je potreban zvuk neće funkcionirati</translation>
 <translation id="1800502858278951817">Nijedna ekstenzija nije zatražila da čita i mijenja <ph name="SITE_NAME" /></translation>
 <translation id="1802624026913571222">Uključi stanje mirovanje kada se zatvori poklopac</translation>
@@ -3053,7 +3053,7 @@
 <translation id="389901847090970821">Odaberite tastaturu</translation>
 <translation id="3900966090527141178">Izvezite lozinke</translation>
 <translation id="3903187154317825986">Ugrađena tastatura</translation>
-<translation id="3903191712482985591">Dodajte playbook</translation>
+<translation id="3903191712482985591">Dodajte vodič</translation>
 <translation id="3904326018476041253">Usluge lokacije</translation>
 <translation id="3904849010307028014">Na osnovu vaše interakcije s web lokacijom, kao što je redovna prijava na račun, ta web lokacija može izdati token povjerenja vašem pregledniku. Kasnije, ako druga web lokacija koju ste posjetili provjeri i pronađe važeći token povjerenja, veća je vjerovatnoća da će vas tretirati kao stvarnu osobu, a ne kao bota.</translation>
 <translation id="3905761538810670789">Popravi aplikaciju</translation>
@@ -3665,7 +3665,7 @@
 <translation id="4510479820467554003">Lista roditeljskih računa</translation>
 <translation id="451102079304155829">kolica</translation>
 <translation id="4513872120116766993">Predvidljivo pisanje</translation>
-<translation id="4513909579793564731">Primijeni playbook</translation>
+<translation id="4513909579793564731">Primijeni vodič</translation>
 <translation id="4513946894732546136">Povratne informacije</translation>
 <translation id="451407183922382411">Omogućuje <ph name="COMPANY_NAME" /></translation>
 <translation id="4514610446763173167">Reproduciraj ili pauziraj videozapis</translation>
@@ -5499,7 +5499,7 @@
 <translation id="635609604405270300">Ne isključujte uređaj</translation>
 <translation id="63566973648609420">Vaše šifrirane podatke može čitati isključivo osoba koja ima vašu šifru za pristup. Šifra za pristup se ne šalje Googleu niti je Google pohranjuje. Ukoliko zaboravite šifru za pristup ili želite promijeniti ovu postavku, morat ćete <ph name="BEGIN_LINK" />poništiti sinhronizaciju<ph name="END_LINK" />.</translation>
 <translation id="6357305427698525450">Neki podržani linkovi će se i dalje otvarati u aplikaciji <ph name="APP_NAME" /> ili <ph name="APP_NAME_2" />.</translation>
-<translation id="6357794994761110294">Nijedno proširenje nema dopuštenje za čitanje i promjenu web-lokacije <ph name="SITE_NAME" /></translation>
+<translation id="6357794994761110294">Nijedna ekstenzija nije dozvoljena da očitava i izmjenjuje web lokaciju <ph name="SITE_NAME" /></translation>
 <translation id="6358884629796491903">Zmaj</translation>
 <translation id="6361850914223837199">Detalji o grešci</translation>
 <translation id="6362853299801475928">&amp;Prijavi problem...</translation>
diff --git a/chrome/app/resources/generated_resources_el.xtb b/chrome/app/resources/generated_resources_el.xtb
index a7e1713..c584c5fa 100644
--- a/chrome/app/resources/generated_resources_el.xtb
+++ b/chrome/app/resources/generated_resources_el.xtb
@@ -849,6 +849,7 @@
 <translation id="1794051631868188691">Να μην εμφανίζεται ποτέ περιεχόμενο σχετικά με <ph name="MERCHANT" />.</translation>
 <translation id="1794791083288629568">Στείλτε τα σχόλιά σας για να μας βοηθήσετε να επιλύσουμε αυτό το πρόβλημα.</translation>
 <translation id="1795214765651529549">Χρήση κλασικού</translation>
+<translation id="1796105431091975902">Επιλέξτε ένα Ansible Playbook για προσθήκη</translation>
 <translation id="1796588414813960292">Οι λειτουργίες που απαιτούν ήχο δεν θα είναι διαθέσιμες</translation>
 <translation id="1800502858278951817">Καμία επέκταση δεν ζήτησε να γίνει ανάγνωση και αλλαγή του ιστοτόπου <ph name="SITE_NAME" /></translation>
 <translation id="1802624026913571222">Σε κατάσταση αδράνειας όταν το κάλυμμα είναι κλειστό</translation>
@@ -3047,6 +3048,7 @@
 <translation id="389901847090970821">Επιλογή πληκτρολογίου</translation>
 <translation id="3900966090527141178">Εξαγωγή κωδικών πρόσβασης</translation>
 <translation id="3903187154317825986">Ενσωματωμένο πληκτρολόγιο</translation>
+<translation id="3903191712482985591">Προσθήκη playbook</translation>
 <translation id="3904326018476041253">Υπηρεσίες τοποθεσίας</translation>
 <translation id="3904849010307028014">Με βάση την αλληλεπίδρασή σας με έναν ιστότοπο, όπως η τακτική σύνδεση σε έναν λογαριασμό, αυτός ο ιστότοπος μπορεί να εκδώσει ένα διακριτικό αξιοπιστίας στο πρόγραμμα περιήγησής σας. Αργότερα, εάν άλλοι ιστότοποι που επισκέπτεστε ελέγξουν και βρουν ένα έγκυρο διακριτικό αξιοπιστίας, είναι πιο πιθανό να σας συμπεριφέρονται όπως σε έναν πραγματικό χρήστη και όχι όπως σε ένα bot.</translation>
 <translation id="3905761538810670789">Επισκευή εφαρμογής</translation>
@@ -3656,6 +3658,7 @@
 <translation id="4510479820467554003">Λίστα λογαριασμών γονέα</translation>
 <translation id="451102079304155829">καλάθια</translation>
 <translation id="4513872120116766993">Πρόβλεψη γραφής</translation>
+<translation id="4513909579793564731">Εφαρμογή playbook</translation>
 <translation id="4513946894732546136">Σχόλια</translation>
 <translation id="451407183922382411">Με την υποστήριξη της <ph name="COMPANY_NAME" /></translation>
 <translation id="4514610446763173167">Εναλλαγή αναπαραγωγής ή παύσης βίντεο</translation>
@@ -5487,6 +5490,7 @@
 <translation id="635609604405270300">Κρατήστε τη συσκευή ενεργοποιημένη</translation>
 <translation id="63566973648609420">Μόνο κάποιος που γνωρίζει τη φράση πρόσβασης μπορεί να διαβάσει τα κρυπτογραφημένα δεδομένα σας. Η φράση πρόσβασης δεν αποστέλλεται ούτε αποθηκεύεται στην Google. Εάν ξεχάσετε τη φράση πρόσβασης ή θέλετε να αλλάξετε αυτήν τη ρύθμιση, θα πρέπει να <ph name="BEGIN_LINK" />επαναφέρετε τον συγχρονισμό<ph name="END_LINK" />.</translation>
 <translation id="6357305427698525450">Ορισμένοι υποστηριζόμενοι σύνδεσμοι θα εξακολουθούν να ανοίγουν στην εφαρμογή <ph name="APP_NAME" /> ή την εφαρμογή  <ph name="APP_NAME_2" />.</translation>
+<translation id="6357794994761110294">Δεν επιτρέπονται επεκτάσεις για ανάγνωση και αλλαγή του ιστοτόπου <ph name="SITE_NAME" /></translation>
 <translation id="6358884629796491903">Δράκος</translation>
 <translation id="6361850914223837199">Λεπτομέρειες σφάλματος:</translation>
 <translation id="6362853299801475928">&amp;Αναφορά προβλήματος...</translation>
diff --git a/chrome/app/resources/generated_resources_ka.xtb b/chrome/app/resources/generated_resources_ka.xtb
index 30aebaac..98d158d 100644
--- a/chrome/app/resources/generated_resources_ka.xtb
+++ b/chrome/app/resources/generated_resources_ka.xtb
@@ -2465,6 +2465,7 @@
 <translation id="3348038390189153836">აღმოჩენილია ამოშლადი მოწყობილობა</translation>
 <translation id="3348131053948466246">შემოთავაზებულია emoji. ნავიგაციისთვის დააჭირეთ კლავიშებს ზემოთ ან ქვემოთ მიმართული ისრით, შეყვანისთვის დააჭირეთ enter-ს.</translation>
 <translation id="3349933790966648062">მეხსიერების მოხმარება</translation>
+<translation id="3353786022389205125">ჩართეთ „ჩაკეტილი ეკრანის ჩვენება გამოღვიძებისას“ და ცადეთ ხელახლა</translation>
 <translation id="3354972872297836698">მოწყობილობასთან <ph name="DEVICE_NAME" /> დაწყვილება ვერ მოხერხდა; ხელახლა საცდელად არჩიეთ მოწყობილოა</translation>
 <translation id="3355936511340229503">კავშირის შეცდომა</translation>
 <translation id="3356469410714175391">(ვირტუალური ბარათი ჩართულია)</translation>
@@ -4942,6 +4943,7 @@
 <translation id="5827733057563115968">შემდეგი სიტყვის ამოცნობა</translation>
 <translation id="5828545842856466741">პროფილის დამატება…</translation>
 <translation id="5828633471261496623">ბეჭდვა…</translation>
+<translation id="5830205393314753525"><ph name="APP_NAME" /> არ იხსნება</translation>
 <translation id="5830720307094128296">&amp;შეინახეთ გვერდი როგორც…</translation>
 <translation id="5832813618714645810">პროფილები</translation>
 <translation id="583281660410589416">უცნობი</translation>
diff --git a/chrome/app/resources/generated_resources_mn.xtb b/chrome/app/resources/generated_resources_mn.xtb
index 5482a23..36e9b1a 100644
--- a/chrome/app/resources/generated_resources_mn.xtb
+++ b/chrome/app/resources/generated_resources_mn.xtb
@@ -845,6 +845,7 @@
 <translation id="1794051631868188691"><ph name="MERCHANT" />-г хэзээ ч бүү харуул</translation>
 <translation id="1794791083288629568">Энэ алдааг засахад бидэнд туслан, санал хүсэлтээ илгээнэ үү.</translation>
 <translation id="1795214765651529549">Сонгодог загварыг ашиглах</translation>
+<translation id="1796105431091975902">Нэмэх Ansible гарын авлагыг сонгоно уу</translation>
 <translation id="1796588414813960292">Дуу чимээ шаардлагатай онцлогууд ажиллахгүй</translation>
 <translation id="1800502858278951817">Ямар ч өргөтгөл <ph name="SITE_NAME" />-г унших болон өөрчлөх хүсэлт тавиагүй</translation>
 <translation id="1802624026913571222">Хавтас хаалттай үед идэвхгүй болгох</translation>
@@ -3050,6 +3051,7 @@
 <translation id="389901847090970821">Гар сонгох</translation>
 <translation id="3900966090527141178">Нууц үгийг экспортлох</translation>
 <translation id="3903187154317825986">Суурилагдсан гар</translation>
+<translation id="3903191712482985591">Гарын авлага нэмэх</translation>
 <translation id="3904326018476041253">Байршлын үйлчилгээ</translation>
 <translation id="3904849010307028014">Бүртгэлд тогтмол нэвтрэх зэрэг таны сайттай хийсэн харилцан үйлдэл тулгуурлан тухайн сайт таны хөтчид итгэмжлэгдсэн токен олгох боломжтой. Дараа нь хэрэв таны зочилсон бусад сайт хүчинтэй итгэмжлэгдсэн токен шалгасан, мөн олсон бол тэдгээр сайт тантай бот бус харин хүн шиг хандах магадлал өндөр болно.</translation>
 <translation id="3905761538810670789">Апп засах</translation>
@@ -3660,6 +3662,7 @@
 <translation id="4510479820467554003">Эцэг эхийн бүртгэлийн жагсаалт</translation>
 <translation id="451102079304155829">сагс</translation>
 <translation id="4513872120116766993">Бичих үгсийг урьдчилан санал болгох</translation>
+<translation id="4513909579793564731">Гарын авлагыг ашиглах</translation>
 <translation id="4513946894732546136">Санал дүгнэлт</translation>
 <translation id="451407183922382411"><ph name="COMPANY_NAME" />-р хүргэсэн</translation>
 <translation id="4514610446763173167">Видеог тоглуулах эсвэл түр зогсоохын тулд асаах/унтраах</translation>
@@ -5493,6 +5496,7 @@
 <translation id="635609604405270300">Төхөөрөмжийг асаалттай хэвээр байлгаарай</translation>
 <translation id="63566973648609420">Зөвхөн таны нэвтрэх үгийг мэддэг хүн л таны шифрлэсэн өгөгдлийг унших боломжтой. Нэвтрэх үгийг Google-д илгээх болон хадгалахгүй. Хэрэв та нэвтрэх үгээ мартсан, эсвэл тохиргоог өөрчлөх бол <ph name="BEGIN_LINK" />синкийг дахин тохируулах<ph name="END_LINK" /> шаардлагатай.</translation>
 <translation id="6357305427698525450">Зарим дэмжигдсэн холбоосыг <ph name="APP_NAME" /> эсвэл  <ph name="APP_NAME_2" />-д нээх боломжтой хэвээр байна.</translation>
+<translation id="6357794994761110294">Ямар ч өргөтгөлд <ph name="SITE_NAME" />-г унших болон өөрчлөхийг зөвшөөрдөггүй</translation>
 <translation id="6358884629796491903">Луу</translation>
 <translation id="6361850914223837199">Алдааны талаарх дэлгэрэнгүй мэдээлэл:</translation>
 <translation id="6362853299801475928">&amp; Асуудлыг мэдэгдэх ...</translation>
diff --git a/chrome/app/resources/generated_resources_mr.xtb b/chrome/app/resources/generated_resources_mr.xtb
index 69b8a74c..e0d548cf 100644
--- a/chrome/app/resources/generated_resources_mr.xtb
+++ b/chrome/app/resources/generated_resources_mr.xtb
@@ -848,6 +848,7 @@
 <translation id="1794051631868188691"><ph name="MERCHANT" /> कधीही दाखवू नका</translation>
 <translation id="1794791083288629568">या समस्येचे निराकरण करण्यात आम्हाला मदत करण्यासाठी अभिप्राय पाठवा.</translation>
 <translation id="1795214765651529549">क्लासिक वापरा</translation>
+<translation id="1796105431091975902">जोडण्यासाठी Ansible प्लेबुक निवडा</translation>
 <translation id="1796588414813960292">साउंडची आवश्यकता असलेली वैशिष्ट्ये काम करणार नाहीत</translation>
 <translation id="1800502858278951817">कोणत्याही एक्स्टेंशनने <ph name="SITE_NAME" /> ला वाचण्यासाठी आणि बदलण्यासाठी विनंती केलेली नाही</translation>
 <translation id="1802624026913571222">कव्हर बंद केल्यावर स्लीप मोड ऑन करा</translation>
@@ -1307,7 +1308,7 @@
 <translation id="222447520299472966">किमान एक आर्ट गॅलरी अल्बम निवडणे आवश्यक आहे</translation>
 <translation id="2224551243087462610">फोल्डर नाव संपादित करा</translation>
 <translation id="2225864335125757863">तुमचे खाते सुरक्षित ठेवण्यासाठी हे पासवर्ड तात्काळ बदला:</translation>
-<translation id="2226449515541314767">MIDI डिव्हाइसचे पूर्ण नियंत्रण असण्यापासून ही साइट अवरोधित केली गेली आहे.</translation>
+<translation id="2226449515541314767">MIDI डिव्हाइसचे पूर्ण नियंत्रण असण्यापासून ही साइट ब्लॉक केली आहे.</translation>
 <translation id="2226826835915474236">इनॲक्टिव्ह शॉर्टकट</translation>
 <translation id="2226907662744526012">पिन एंटर केल्यानंतर आपोआप अनलॉक करा</translation>
 <translation id="2227179592712503583">सूचना काढून टाका</translation>
@@ -3053,6 +3054,7 @@
 <translation id="389901847090970821">कीबोर्ड निवडा</translation>
 <translation id="3900966090527141178">पासवर्ड एक्सपोर्ट करा</translation>
 <translation id="3903187154317825986">बिल्ट-इन कीबोर्ड</translation>
+<translation id="3903191712482985591">प्लेबुक जोडा</translation>
 <translation id="3904326018476041253">स्‍थान सेवा</translation>
 <translation id="3904849010307028014">नियमितपणे खात्यामध्ये साइन इन करणे यासारख्या एखाद्या साइटसोबतच्या तुमच्या संवादाच्या आधारे, ती साइट तुमच्या ब्राउझरला ट्रस्ट टोकन जारी करू शकते. त्यानंतर, तुम्ही इतर साइटना भेट दिल्यास आणि त्या साइटना वैध ट्रस्ट टोकन सापडल्यास, त्या तुम्हाला बॉट नव्हे तर एखादी व्यक्ती समजण्याची जास्त शक्यता आहे.</translation>
 <translation id="3905761538810670789">अ‍ॅप दुरुस्त करा</translation>
@@ -3662,6 +3664,7 @@
 <translation id="4510479820467554003">पालक खाते सूची</translation>
 <translation id="451102079304155829">कार्ट</translation>
 <translation id="4513872120116766993">अंदाजानुसार लिखाण</translation>
+<translation id="4513909579793564731">प्लेबुक लागू करा</translation>
 <translation id="4513946894732546136">फीडबॅक</translation>
 <translation id="451407183922382411"><ph name="COMPANY_NAME" />ने समर्थित करा</translation>
 <translation id="4514610446763173167">प्ले करण्यासाठी किंवा थांबवण्यासाठी व्हिडिओ टॉगल करा</translation>
@@ -5496,6 +5499,7 @@
 <translation id="635609604405270300">डिव्हाइस सुरू ठेवा</translation>
 <translation id="63566973648609420">फक्त तुमचा सांकेतिक पासफ्रेझ असलेली एखादी व्यक्ती तुमचा एंक्रिप्ट केलेला डेटा वाचू शकते. सांकेतिक पासफ्रेझ Google कडे पाठविला किंवा त्याद्वारे स्टोअर केला जात नाही.  तुमचा सांकेतिक पासफ्रेझ विसरल्यास किंवा हे सेटिंग बदलू इच्छित असल्यास, तुम्हाला <ph name="BEGIN_LINK" />सिंक रीसेट करण्याची आवश्यकता असेल<ph name="END_LINK" />.</translation>
 <translation id="6357305427698525450">सपोर्ट असलेल्या काही लिंक तरीही <ph name="APP_NAME" /> किंवा  <ph name="APP_NAME_2" /> मध्ये उघडतील.</translation>
+<translation id="6357794994761110294">कोणत्याही एक्स्टेंशनना <ph name="SITE_NAME" /> ला वाचण्याची आणि बदलण्याची अनुमती नाही</translation>
 <translation id="6358884629796491903">ड्रॅगन</translation>
 <translation id="6361850914223837199">एरर तपशील:</translation>
 <translation id="6362853299801475928">&amp;समस्या नोंदवणे...</translation>
@@ -7388,7 +7392,7 @@
 <translation id="8213449224684199188">फोटो मोड टाकला</translation>
 <translation id="8214489666383623925">फाइल उघडा...</translation>
 <translation id="8215129063232901118">तुमच्या <ph name="DEVICE_TYPE" /> वरून तुमच्या फोनच्या क्षमता अ‍ॅक्सेस करा</translation>
-<translation id="8217399928341212914">एकाधिक फायलींचे स्वयंचलित डाउनलोड अवरोधित करणे सुरू ठेवा</translation>
+<translation id="8217399928341212914">एकाधिक फाइलचे ऑटोमॅटिक डाउनलोड ब्लॉक करणे सुरू ठेवा</translation>
 <translation id="822050276545350872">इथून पुढे, प्रतीक्षा करण्याची आवश्यकता नाही</translation>
 <translation id="8221491193165283816">तुम्ही सहसा सूचना ब्लॉक करता. या साइटला तुम्हाला सूचित करू देण्यासाठी, येथे क्लिक करा.</translation>
 <translation id="822347941086490485">HID डिव्हाइस शोधत आहे…</translation>
@@ -7816,7 +7820,7 @@
 <translation id="8662811608048051533">तुम्हाला बहुतांश साइटवरून साइन आउट करते.</translation>
 <translation id="8662911384982557515">तुमचे होम पेज यावर बदला: <ph name="HOME_PAGE" /></translation>
 <translation id="8662978096466608964">Chrome वॉलपेपर सेट करू शकत नाही.</translation>
-<translation id="8663099077749055505"><ph name="HOST" /> वरील एकाधिक स्वयंचलित डाउनलोड नेहमी अवरोधित करा</translation>
+<translation id="8663099077749055505"><ph name="HOST" /> वरील एकाधिक ऑटोमॅटिक डाउनलोड नेहमी ब्लॉक करा</translation>
 <translation id="8664389313780386848">पृष्ठ स्रोत &amp;पहा</translation>
 <translation id="8665110742939124773">तुम्ही चुकीचा अ‍ॅक्सेस कोड एंटर केला आहे. पुन्हा प्रयत्न करा.</translation>
 <translation id="8665180165765946056">बॅकअप पूर्ण झाला</translation>
diff --git a/chrome/app/resources/generated_resources_my.xtb b/chrome/app/resources/generated_resources_my.xtb
index 1b7c83f..e4242ec 100644
--- a/chrome/app/resources/generated_resources_my.xtb
+++ b/chrome/app/resources/generated_resources_my.xtb
@@ -2473,6 +2473,7 @@
 <translation id="3348038390189153836">ဖြုတ်ရနိုင်သည့် ကိရိယာကို ရှာတွေ့ခဲ့</translation>
 <translation id="3348131053948466246">အကြံပြုထားသော အီမိုဂျီ။ ရွှေ့ရန် အပေါ် သို့မဟုတ် အောက်ခလုတ်၊ ထည့်သွင်းရန် enter နှိပ်ပါ။</translation>
 <translation id="3349933790966648062">ဖြစ်စဉ်တွင် မှတ်ဉာဏ်အသုံးပြုမှု</translation>
+<translation id="3353786022389205125">“နားချိန်မှ ပြန်ဖွင့်လိုက်သောအခါ လော့ခ်မျက်နှာပြင်ကို ပြရန်” ကိုဖွင့်ပြီး ထပ်စမ်းကြည့်ပါ</translation>
 <translation id="3354972872297836698">စက် <ph name="DEVICE_NAME" /> ကိုတွဲချိတ်၍ မရပါ။ ထပ်စမ်းကြည့်ရန် စက်ပစ္စည်းကိုရွေးပါ</translation>
 <translation id="3355936511340229503">ချိတ်ဆက်မှု မှားယွင်းခြင်း</translation>
 <translation id="3356469410714175391">(ပကတိအသွင်ကတ် သုံးထားသည်)</translation>
@@ -4948,6 +4949,7 @@
 <translation id="5827733057563115968">လာမည့်စကားလုံး ခန့်မှန်းချက်</translation>
 <translation id="5828545842856466741">ပရိုဖိုင် ထည့်ရန်...</translation>
 <translation id="5828633471261496623">ပရင့် ထုတ်နေသည်...</translation>
+<translation id="5830205393314753525"><ph name="APP_NAME" /> ကို ဖွင့်၍မရပါ</translation>
 <translation id="5830720307094128296">စာမျက်နှာကို...အဖြစ် သိမ်းရန်</translation>
 <translation id="5832813618714645810">ပရိုဖိုင်များ</translation>
 <translation id="583281660410589416">မသိရ</translation>
diff --git a/chrome/app/resources/generated_resources_no.xtb b/chrome/app/resources/generated_resources_no.xtb
index 886bc886..5102157 100644
--- a/chrome/app/resources/generated_resources_no.xtb
+++ b/chrome/app/resources/generated_resources_no.xtb
@@ -1012,6 +1012,7 @@
 <translation id="1944921356641260203">En oppdatering ble funnet</translation>
 <translation id="1947136734041527201">Lar deg logge på nettsteder med kontoer du har hos identitetstjenester</translation>
 <translation id="1949584741547056205">Hurtigsvar</translation>
+<translation id="1949849604471335579">Gi personlig preg til bakgrunnen, skjermspareren, markeringsfargene med mer</translation>
 <translation id="1951012854035635156">Assistent</translation>
 <translation id="1954597385941141174">Nettsteder kan be om å få koble til USB-enheter</translation>
 <translation id="1954813140452229842">Feil ved innsetting av deling. Sjekk legitimasjonen og prøv igjen.</translation>
@@ -1043,6 +1044,7 @@
 <translation id="1981434377190976112">lese alle dataene dine på alle nettsteder</translation>
 <translation id="1984417487208496350">Ingen beskyttelse (anbefales ikke)</translation>
 <translation id="1987317783729300807">Kontoer</translation>
+<translation id="1987574314042117472">Velg og installer populære apper</translation>
 <translation id="1988259784461813694">Krav</translation>
 <translation id="1989112275319619282">Bla gjennom</translation>
 <translation id="1989903373608997757">Bruk alltid</translation>
@@ -1108,6 +1110,7 @@
 <translation id="2048554637254265991">Feil ved oppstart av beholderbehandling. Prøv på nytt.</translation>
 <translation id="2048653237708779538">Handlingen er ikke tilgjengelig</translation>
 <translation id="2050339315714019657">Stående</translation>
+<translation id="2052572566310583903">Installert på de andre enhetene dine</translation>
 <translation id="2053312383184521053">Data om hviletilstand</translation>
 <translation id="2054240652864153171">Vil du slette nettstedsdata for <ph name="SITE_NAME" /> som er partisjonert på <ph name="PARTITION_SITE_NAME" />?</translation>
 <translation id="2055585478631012616">Du blir logget av disse nettstedene – inkludert i åpne faner</translation>
@@ -1270,6 +1273,7 @@
 <translation id="2191754378957563929">På</translation>
 <translation id="2192505247865591433">Fra:</translation>
 <translation id="2193365732679659387">Klareringsinnstillinger</translation>
+<translation id="2194554416429452547">Mens prøveprosjekter pågår, utforsker Chrome måter å begrense nettsøppel, svindel og deling mellom nettsteder på. Chrome <ph name="ESTIMATE_INTERESTS_LINK" />, som nettsteder kan bruke til å vise deg annonser. Du kan administrere interessene dine i innstillingene.</translation>
 <translation id="2194856509914051091">Ting å tenke på</translation>
 <translation id="2195331105963583686">Du kan fortsette å bruke <ph name="DEVICE_TYPE" />-enheten etter dette tidspunktet, men den kommer ikke til å få automatiske programvare- og sikkerhetsoppdateringer lenger</translation>
 <translation id="2195729137168608510">Beskyttelse av e-post </translation>
@@ -1877,6 +1881,7 @@
 <translation id="2749836841884031656">SIM-kort</translation>
 <translation id="2749881179542288782">Kontroller·grammatikk·og·staving</translation>
 <translation id="2753677631968972007">Styr nettstedstillatelser manuelt.</translation>
+<translation id="2754825024506485820">Finn appene du trenger – fra produktivitet til underholdning – i Google Play-butikken. Du kan installere apper når som helst.</translation>
 <translation id="2755349111255270002">Tilbakestill <ph name="DEVICE_TYPE" /></translation>
 <translation id="2755367719610958252">Administrer tilgjengelighetsfunksjoner</translation>
 <translation id="275662540872599901">skjerm av</translation>
@@ -1953,6 +1958,7 @@
 <translation id="2815693974042551705">Bokmerke-mappen</translation>
 <translation id="2816319641769218778">For å lagre passord i Google-kontoen, slå på synkronisering.</translation>
 <translation id="2816628817680324566">Vil du la dette nettstedet identifisere sikkerhetsnøkkelen din?</translation>
+<translation id="2817435998497102771">Angi bakgrunn og stil</translation>
 <translation id="2818476747334107629">Skriverdetaljer</translation>
 <translation id="2819167288942847344">Bruk forhåndsinnstillinger for vinduer på telefon, vinduer på nettbrett eller vinduer du kan endre størrelse på, for å unngå at appen lastes inn eller vises på feil måte</translation>
 <translation id="2820957248982571256">Skanner …</translation>
@@ -2846,6 +2852,7 @@
 <translation id="3727144509609414201">Tilgjengelige Wi-Fi-nettverk</translation>
 <translation id="3727187387656390258">Undersøk hurtigvindu</translation>
 <translation id="372722114124766626">Bare én gang</translation>
+<translation id="3727332897090187514">Det er ikke lagt til noe notat</translation>
 <translation id="3727473233247516571">Underramme i frem-og-tilbake-bufferen: <ph name="BACK_FORWARD_CACHE_PAGE_URL" /></translation>
 <translation id="3728188878314831180">Speil varsler fra telefonen din</translation>
 <translation id="3728681439294129328">Konfigurer nettverksadressen</translation>
@@ -3179,6 +3186,7 @@
 <translation id="4031527940632463547">Sensorene er blokkerte</translation>
 <translation id="4033415645631238123">Pålogging med Smart Lock er ikke tilgjengelig lenger. Du kan fremdeles låse opp med Smart Lock.</translation>
 <translation id="4033471457476425443">Legg til ny mappe</translation>
+<translation id="4033711848170683365">Dette medfører at nettlesingsdata blir slettet permanent fra denne enheten. Det kan hende at Google-kontoene i denne profilen brukes av andre apper på <ph name="DEVICE_TYPE" />. Du kan fjerne disse kontoene i <ph name="BEGIN_LINK" /><ph name="SETTING_SECTION" /> &gt; <ph name="ACCOUNTS_SECTION" /><ph name="END_LINK" />.</translation>
 <translation id="4033963223187371752">Sikre nettsteder kan bygge inn innhold som bilder eller nettrammer som ikke er sikre</translation>
 <translation id="4034824040120875894">Skriver</translation>
 <translation id="4035758313003622889">&amp;Oppgavebehandling</translation>
@@ -3457,6 +3465,7 @@
 <translation id="4314815835985389558">Administrer synkronisering</translation>
 <translation id="4315933848520197627">Fjern tilknytningen til kontoen</translation>
 <translation id="4316850752623536204">Utviklernettsted</translation>
+<translation id="4317733381297736564">Kjøp i app</translation>
 <translation id="4317820549299924617">Verifiseringen var ikke vellykket</translation>
 <translation id="4320177379694898372">Ingen internettilkobling</translation>
 <translation id="4322394346347055525">Lukk andre faner</translation>
@@ -4039,6 +4048,7 @@
 <translation id="4893522937062257019">På låseskjermen</translation>
 <translation id="4897496410259333978">Kontakt administratoren din for å få mer informasjon.</translation>
 <translation id="4898011734382862273">Sertifikatet «<ph name="CERTIFICATE_NAME" />» representerer en sertifiseringsinstans</translation>
+<translation id="4899696330053002588">Inneholder annonser</translation>
 <translation id="489985760463306091">For å fullføre fjerningen av den skadelige programvaren, start datamaskinen på nytt</translation>
 <translation id="4900392736118574277">Oppstartssiden er endret til <ph name="URL" />.</translation>
 <translation id="490051679772058907"><ph name="REFRESH_RATE" /> Hz – linjefletting</translation>
@@ -4412,6 +4422,7 @@
 <translation id="52912272896845572">Den private nøkkelfilen er ugyldig.</translation>
 <translation id="5291739252352359682">Lager teksting for medier i Chrome automatisk (for tiden tilgjengelig på engelsk). Lyd og teksting behandles lokalt og forlater aldri enheten.</translation>
 <translation id="529175790091471945">Formatér denne enheten</translation>
+<translation id="5292862864186939732">Vil du alltid la «<ph name="EXTENSION_NAME" />» kjøre på <ph name="ORIGIN" />?</translation>
 <translation id="529296195492126134">Engangsmodus støttes ikke. Kontakt administratoren din</translation>
 <translation id="5293170712604732402">Tilbakestill innstillingene til standardverdiene</translation>
 <translation id="5294097441441645251">Må begynne med liten bokstav eller understrek</translation>
@@ -5168,6 +5179,7 @@
 <translation id="6054961935262556546">Endre tilgang</translation>
 <translation id="6055171183283175969">Passordet du skrev inn, er feil.</translation>
 <translation id="6055392876709372977">PKCS #1 SHA-256 med RSA-kryptering</translation>
+<translation id="6055544610007596637">Installer apper på <ph name="DEVICE_TYPE" /> fra Google Play-butikken</translation>
 <translation id="6056710589053485679">Normal innlasting på nytt</translation>
 <translation id="6057312498756061228">Denne filen er for stor til at en sikkerhetssjekk kan utføres. Du kan åpne filer på opptil 50 MB.</translation>
 <translation id="6057381398996433816">Dette nettstedet er blokkert fra å bruke bevegelses- og lyssensorer.</translation>
@@ -6140,6 +6152,7 @@
 <translation id="7002055706763150362">For å konfigurere Smart Lock for Chromebook, må Google være sikker på at det er deg. Skriv inn passordet for å begynne.</translation>
 <translation id="7003339318920871147">Nettdatabaser</translation>
 <translation id="7003454175711353260">{COUNT,plural, =1{{COUNT} fil}other{{COUNT} filer}}</translation>
+<translation id="7003705861991657723">Alfa</translation>
 <translation id="7003723821785740825">Konfigurer en raskere måte å låse opp enheten din på</translation>
 <translation id="7003844668372540529">Ukjent produkt, <ph name="PRODUCT_ID" />, fra <ph name="VENDOR_NAME" /></translation>
 <translation id="7004402701596653846">Nettstedet kan bruke MIDI</translation>
@@ -6156,6 +6169,7 @@
 <translation id="7008815993384338777">Roamer ikke for øyeblikket</translation>
 <translation id="7009709314043432820"><ph name="APP_NAME" /> bruker kameraet ditt</translation>
 <translation id="701080569351381435">Se kilde</translation>
+<translation id="7011797924920577670">beregner også interessene dine</translation>
 <translation id="7014174261166285193">Installeringen mislyktes.</translation>
 <translation id="7014480873681694324">Fjern markering</translation>
 <translation id="7017004637493394352">Si «Ok Google» igjen</translation>
@@ -6223,6 +6237,7 @@
 <translation id="7082568314107259011"><ph name="NETWORK_NAME" /> administreres av administratoren din</translation>
 <translation id="7085389578340536476">Vil du gi Chrome tillatelse til å spille inn lyd?</translation>
 <translation id="708550780726587276">(ikke konfigurert)</translation>
+<translation id="7086531709814430567">Vil du alltid la disse utvidelsene kjøre på <ph name="ORIGIN" />?</translation>
 <translation id="7086672505018440886">Inkluder Chrome-loggfiler i arkivet.</translation>
 <translation id="7088434364990739311">Kunne ikke starte søk etter oppdateringer (feilkode <ph name="ERROR" />).</translation>
 <translation id="7088674813905715446">Administratoren har gitt denne enheten status som «ikke klargjort». For å aktivere den for registrering, må du be administratoren gi enheten status som «ventende».</translation>
@@ -8355,6 +8370,7 @@
 <translation id="9215742531438648683">Avinstaller Google Play-butikken</translation>
 <translation id="9218430445555521422">Bruk som standard</translation>
 <translation id="9218842937876577955"><ph name="APP_NAME" /> (appen støttes ikke)</translation>
+<translation id="9219582468404818260">Hjelp oss med å bygge et bedre internett</translation>
 <translation id="9220525904950070496">Fjern konto</translation>
 <translation id="9220820413868316583">Løft fingeren, og prøv deretter på nytt.</translation>
 <translation id="923467487918828349">Vis alle</translation>
diff --git a/chrome/app/resources/generated_resources_or.xtb b/chrome/app/resources/generated_resources_or.xtb
index 952ea77..26aad092 100644
--- a/chrome/app/resources/generated_resources_or.xtb
+++ b/chrome/app/resources/generated_resources_or.xtb
@@ -1003,6 +1003,7 @@
 <translation id="1944921356641260203">ଅପ୍‌ଡେଟ୍‍ ମିଳିଲା</translation>
 <translation id="1947136734041527201">ଏକ ପରିଚୟ ପ୍ରଦାନ କରୁଥିବା ସେବା ସହିତ ଆପଣଙ୍କର ଆକାଉଣ୍ଟ ବ୍ୟବହାର କରି ଆପଣଙ୍କୁ ୱେବସାଇଟରେ ସାଇନ ଇନ କରିବାକୁ ଦିଏ</translation>
 <translation id="1949584741547056205">ଦ୍ରୁତ ଉତ୍ତରଗୁଡ଼ିକ</translation>
+<translation id="1949849604471335579">ୱାଲପେପର, ସ୍କ୍ରିନ ସେଭର, ଆକ୍ସେଣ୍ଟ ରଙ୍ଗ ଏବଂ ଆହୁରି ଅନେକ କିଛିକୁ ପର୍ସନାଲାଇଜ କରନ୍ତୁ</translation>
 <translation id="1951012854035635156">Assistant</translation>
 <translation id="1954597385941141174">USB ଡିଭାଇସଗୁଡ଼ିକ ସହିତ ସଂଯୋଗ କରିବାକୁ ସାଇଟଗୁଡ଼ିକ ପଚାରିପାରିବ</translation>
 <translation id="1954813140452229842">ସେୟାର୍ ଖଞ୍ଜିବାରେ ତ୍ରୁଟି। ଦୟାକରି ଆପଣଙ୍କର କ୍ରେଡେନ୍ସିଆଲ୍ ଯାଞ୍ଚ କରନ୍ତୁ ଏବଂ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।</translation>
@@ -1034,6 +1035,7 @@
 <translation id="1981434377190976112">ସମସ୍ତ ୱେବସାଇଟରେ ଆପଣଙ୍କ ସବୁ ଡାଟା ପଢ଼ନ୍ତୁ</translation>
 <translation id="1984417487208496350">କୌଣସି ସୁରକ୍ଷା ନାହିଁ (ସୁପାରିଶ କରାଯାଇ ନାହିଁ)</translation>
 <translation id="1987317783729300807">ଆକାଉଣ୍ଟ</translation>
+<translation id="1987574314042117472">ଲୋକପ୍ରିୟ ଆପ୍ସ ଚୟନ କରି ଇନଷ୍ଟଲ କରନ୍ତୁ</translation>
 <translation id="1988259784461813694">ଆବଶ୍ୟକତା</translation>
 <translation id="1989112275319619282">ବ୍ରାଉଜ୍ କରନ୍ତୁ</translation>
 <translation id="1989903373608997757">ସର୍ବଦା ବ୍ୟବହାର କରନ୍ତୁ</translation>
@@ -1099,6 +1101,7 @@
 <translation id="2048554637254265991">କଣ୍ଟେନର୍ ମ୍ୟାନେଜର୍ ଆରମ୍ଭ କରିବାରେ ତ୍ରୁଟି। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।</translation>
 <translation id="2048653237708779538">କାର୍ଯ୍ୟ ଉପଲବ୍ଧ ନାହିଁ</translation>
 <translation id="2050339315714019657">ପୋଟ୍ରେଟ୍‌</translation>
+<translation id="2052572566310583903">ଆପଣଙ୍କ ଅନ୍ୟ ଡିଭାଇସଗୁଡ଼ିକରେ ଇନଷ୍ଟଲ କରାଯାଇଛି</translation>
 <translation id="2053312383184521053">ନିଷ୍କ୍ରିୟ ସ୍ଥିତିରେ ଥିବା ଡାଟା</translation>
 <translation id="2054240652864153171"><ph name="PARTITION_SITE_NAME" />ରେ ପାର୍ଟିସନ କରାଯାଇଥିବା <ph name="SITE_NAME" /> ପାଇଁ ସାଇଟ ଡାଟା ଖାଲି କରିବେ କି?</translation>
 <translation id="2055585478631012616">ଖୋଲାଥିବା ଟାବ୍‌ଗୁଡ଼ିକ ସମେତ ଆପଣ ଏହି ସାଇଟ୍‌ଗୁଡ଼ିକରୁ ସାଇନ୍ ଆଉଟ୍ ହୋଇଯିବେ।</translation>
@@ -1261,6 +1264,7 @@
 <translation id="2191754378957563929">ଚାଲୁ ଅଛି</translation>
 <translation id="2192505247865591433">ଠାରୁ:</translation>
 <translation id="2193365732679659387">ବିଶ୍ୱସ୍ତ ସେଟିଂସ୍</translation>
+<translation id="2194554416429452547">ଟ୍ରାଏଲ ସମୟରେ, Chrome ସ୍ପାମ, ଠକାମୀ ଏବଂ ସାଇଟଗୁଡ଼ିକ ମଧ୍ୟରେ ସେୟାରିଂକୁ ସୀମିତ କରିବାର ଉପାୟଗୁଡ଼ିକୁ ଏକ୍ସପ୍ଲୋର କରୁଛି। Chrome <ph name="ESTIMATE_INTERESTS_LINK" /> ମଧ୍ୟ କରେ ଯାହାକୁ ସାଇଟଗୁଡ଼ିକ ଆପଣଙ୍କୁ ବିଜ୍ଞାପନ ଦେଖାଇବା ପାଇଁ ବ୍ୟବହାର କରିପାରିବ। ଆପଣ ସେଟିଂସରେ ଆପଣଙ୍କ ରୁଚିଗୁଡ଼ିକୁ ପରିଚାଳନା କରିପାରିବେ।</translation>
 <translation id="2194856509914051091">ବିଚାରଯୋଗ୍ୟ ବିଷୟଗୁଡ଼ିକ</translation>
 <translation id="2195331105963583686">ଆପଣ ସେହି ସମୟ ପରେ ମଧ୍ୟ <ph name="DEVICE_TYPE" /> ବ୍ୟବହାର କରିପାରିବେ, କିନ୍ତୁ ଏହା ଆଉ ସ୍ୱଚାଳିତ ସଫ୍ଟୱେୟାର ଏବଂ ସୁରକ୍ଷା ଅପ୍‌ଡେଟ୍‍ଗୁଡ଼ିକ ପାଇବ ନାହିଁ।</translation>
 <translation id="2195729137168608510">ଇମେଲ୍ ସୁରକ୍ଷା</translation>
@@ -1866,6 +1870,7 @@
 <translation id="2749836841884031656">SIM</translation>
 <translation id="2749881179542288782">ବନାନ ସହିତ ବ୍ୟାକରଣର ଯାଞ୍ଚ କରନ୍ତୁ</translation>
 <translation id="2753677631968972007">ସାଇଟ୍ ଅନୁମତିଗୁଡ଼ିକୁ ମାନୁଆଲୀ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ।</translation>
+<translation id="2754825024506485820">ଉତ୍ପାଦନକ୍ଷମତାରୁ ମନୋରଞ୍ଜନ ପର୍ଯ୍ୟନ୍ତ ଆପଣ ଆବଶ୍ୟକ କରୁଥିବା ଆପ୍ସକୁ Google Play Storeରେ ପାଆନ୍ତୁ। ଆପଣ ଯେ କୌଣସି ସମୟରେ ଆପ୍ସ ଇନଷ୍ଟଲ କରିପାରିବେ।</translation>
 <translation id="2755349111255270002">ଏହି <ph name="DEVICE_TYPE" />କୁ ରିସେଟ୍ କରନ୍ତୁ</translation>
 <translation id="2755367719610958252">ଆକ୍ସେସିବିଲିଟୀ ବୈଶିଷ୍ଟ୍ୟଗୁଡ଼ିକୁ ପରିଚାଳନା କରନ୍ତୁ</translation>
 <translation id="275662540872599901">ସ୍କ୍ରିନ୍‍ ବନ୍ଦ ଅଛି</translation>
@@ -1942,6 +1947,7 @@
 <translation id="2815693974042551705">ବୁକ୍‌ମାର୍କ ଫୋଲ୍ଡର୍</translation>
 <translation id="2816319641769218778">ଆପଣଙ୍କର Google ଆକାଉଣ୍ଟରେ ପାସ୍‌ୱାର୍ଡଗୁଡ଼ିକୁ ସେଭ୍ କରିବାକୁ ସିଙ୍କ୍ ଚାଲୁ କରନ୍ତୁ।</translation>
 <translation id="2816628817680324566">ଆପଣଙ୍କ ସୁରକ୍ଷା କୀ'କୁ ଚିହ୍ନଟ କରିବା ପାଇଁ ଏହି ସାଇଟକୁ ଅନୁମତି ଦେବେ କି?</translation>
+<translation id="2817435998497102771">ଆପଣଙ୍କ ୱାଲପେପର ଏବଂ ଷ୍ଟାଇଲ ସେଟ କରନ୍ତୁ</translation>
 <translation id="2818476747334107629">ପ୍ରିଣ୍ଟର୍‌ର ବିବରଣୀ</translation>
 <translation id="2819167288942847344">ଆପକୁ ଅସ୍ୱାଭାବିକ ଆଚରଣ କରିବାରୁ ପ୍ରତିରୋଧ କରିବା ପାଇଁ ଫୋନ୍, ଟାବଲେଟ୍ କିମ୍ବା ରିସାଇଜ୍ କରାଯାଇପାରୁଥିବା ୱିଣ୍ଡୋ ନିମନ୍ତେ ପ୍ରିସେଟଗୁଡ଼ିକୁ ବ୍ୟବହାର କରନ୍ତୁ</translation>
 <translation id="2820957248982571256">ସ୍କାନ୍‌ କରୁଛି...</translation>
@@ -2835,6 +2841,7 @@
 <translation id="3727144509609414201">ଉପଲବ୍ଧ ଥିବା ୱାଇଫାଇ ନେଟୱାର୍କଗୁଡ଼ିକ</translation>
 <translation id="3727187387656390258">ପପ୍‍ଅପ୍‍ର ନିରୀକ୍ଷଣ କରନ୍ତୁ</translation>
 <translation id="372722114124766626">ଥରେ ମାତ୍ର</translation>
+<translation id="3727332897090187514">କୌଣସି ନୋଟ ଯୋଗ କରାଯାଇନାହିଁ</translation>
 <translation id="3727473233247516571">ବ୍ୟାକ୍/ଫରୱାର୍ଡ୍ କ୍ୟାଶ୍ ସବଫ୍ରେମ୍: <ph name="BACK_FORWARD_CACHE_PAGE_URL" /></translation>
 <translation id="3728188878314831180">ଆପଣଙ୍କ ଫୋନର ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ Chromebookରେ ମିଳିବ</translation>
 <translation id="3728681439294129328">ନେଟୱାର୍କ ଠିକଣା କନଫିଗର୍ କରନ୍ତୁ</translation>
@@ -3169,6 +3176,7 @@
 <translation id="4031527940632463547">ସେନ୍ସର୍‍ ଅବରୋଧ କରାଯାଇଛି</translation>
 <translation id="4033415645631238123">Smart Lock ମାଧ୍ୟମରେ ସାଇନ ଇନ କରିବା ଆଉ ଉପଲବ୍ଧ ନାହିଁ। ଆପଣ ଏବେ ବି Smart Lock ସହ ଅନଲକ କରିପାରିବେ।</translation>
 <translation id="4033471457476425443">ନୂଆ ଫୋଡ୍ଲର୍ ଯୋଗ କରନ୍ତୁ</translation>
+<translation id="4033711848170683365">ଏହି ଡିଭାଇସରୁ ବ୍ରାଉଜିଂ ଡାଟାକୁ ଏହା ସ୍ଥାୟୀରୂପେ ଡିଲିଟ କରିଦେବ। ଏହି ପ୍ରୋଫାଇଲରେ ଥିବା Google ଆକାଉଣ୍ଟଗୁଡ଼ିକ ଆପଣଙ୍କ <ph name="DEVICE_TYPE" />ରେ ଥିବା ଅନ୍ୟ ଆପ୍ସ ଦ୍ୱାରା ବ୍ୟବହୃତ ହୋଇପାରେ। ଆପଣ <ph name="BEGIN_LINK" /><ph name="SETTING_SECTION" /> &gt; <ph name="ACCOUNTS_SECTION" /><ph name="END_LINK" />ରେ ଏହି ଆକାଉଣ୍ଟଗୁଡ଼ିକୁ କାଢ଼ିପାରିବେ।</translation>
 <translation id="4033963223187371752">ସୁରକ୍ଷିତ ନଥିବା ଛବି କିମ୍ବା ୱେବ୍ ଫ୍ରେମଗୁଡ଼ିକ ପରି ବିଷୟବସ୍ତୁକୁ ସୁରକ୍ଷିତ ସାଇଟଗୁଡ଼ିକ ଏମ୍ବେଡ୍ କରିପାରେ</translation>
 <translation id="4034824040120875894">ପ୍ରିଣ୍ଟର୍‌</translation>
 <translation id="4035758313003622889">&amp;ଟାସ୍କ ପରିଚାଳକ</translation>
@@ -3447,6 +3455,7 @@
 <translation id="4314815835985389558">ସିଙ୍କ ପରିଚାଳନା କରନ୍ତୁ</translation>
 <translation id="4315933848520197627">ଆକାଉଣ୍ଟ ଅନଲିଙ୍କ୍ କରନ୍ତୁ</translation>
 <translation id="4316850752623536204">ଡେଭେଲପର୍‌ ୱେବ୍‍ସାଇଟ୍</translation>
+<translation id="4317733381297736564">ଇନ-ଆପ କ୍ରୟଗୁଡ଼ିକ</translation>
 <translation id="4317820549299924617">ଯାଞ୍ଚକରଣ ସଫଳ ହୋଇନାହିଁ</translation>
 <translation id="4320177379694898372">କୌଣସି ଇଣ୍ଟର୍ନେଟ୍‍ ସଂଯୋଗ ନାହିଁ</translation>
 <translation id="4322394346347055525">ଅନ୍ୟ ଟାବ୍‌ଗୁଡ଼ିକୁ ବନ୍ଦ କରନ୍ତୁ</translation>
@@ -4030,6 +4039,7 @@
 <translation id="4893522937062257019">ଲକ୍ ସ୍କ୍ରିନ୍ ଉପରେ</translation>
 <translation id="4897496410259333978">ଅଧିକ ସୂଚନା ପାଇଁ, ଆପଣଙ୍କ ଆଡମିନିଷ୍ଟ୍ରେଟରଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।</translation>
 <translation id="4898011734382862273">ସାର୍ଟିଫିକେଟ୍‍ "<ph name="CERTIFICATE_NAME" />" ଏକ ସାର୍ଟିଫିକେସନ୍ ଅଧିକାରୀଙ୍କର ପ୍ରରତିନିଧିତ୍ୱ କରେ</translation>
+<translation id="4899696330053002588">ଏଥିରେ ବିଜ୍ଞାପନଗୁଡ଼ିକ ଅଛି</translation>
 <translation id="489985760463306091">କ୍ଷତିକାରକ ସଫ୍ଟୱେର୍ କାଢ଼ିବାର ପ୍ରକ୍ରିୟାକୁ ସମ୍ପୂର୍ଣ୍ଣ କରିବା ପାଇଁ, ଆପଣଙ୍କ କମ୍ପ୍ୟୁଟର୍‍କୁ ରିଷ୍ଟାର୍ଟ କରନ୍ତୁ</translation>
 <translation id="4900392736118574277">ଆପଣଙ୍କର ଆରମ୍ଭ ପୃଷ୍ଠା <ph name="URL" />କୁ ପରିବର୍ତ୍ତନ ହୋଇଥିଲା।</translation>
 <translation id="490051679772058907"><ph name="REFRESH_RATE" /> Hz - ଇଣ୍ଟରଲେସ୍ ହୋଇଛି</translation>
@@ -4403,6 +4413,7 @@
 <translation id="52912272896845572">ବ୍ୟକ୍ତିଗତ କୀ' ଫାଇଲ୍ ଅବୈଧ ଅଟେ।</translation>
 <translation id="5291739252352359682">Chrome ବ୍ରାଉଜରରେ ମିଡିଆ ପାଇଁ ସ୍ୱଚାଳିତ ଭାବେ କ୍ୟାପ୍ସନଗୁଡ଼ିକ ତିଆରି କରେ (ବର୍ତ୍ତମାନ ଇଂରାଜୀରେ ଉପଲବ୍ଧ ଅଛି)। ଅଡିଓ ଏବଂ କ୍ୟାପ୍ସନଗୁଡ଼ିକୁ ଡିଭାଇସରେ ହିଁ ପ୍ରକ୍ରିୟାନ୍ୱିତ କରାଯାଏ ଏବଂ ସେଗୁଡ଼ିକୁ କେବେ ବି ଡିଭାଇସରୁ କାଢ଼ି ଦିଆଯାଏ ନାହିଁ।</translation>
 <translation id="529175790091471945">ଏହି ଡିଭାଇସ୍‌କୁ ଫର୍ମାଟ୍ କରନ୍ତୁ</translation>
+<translation id="5292862864186939732">"<ph name="EXTENSION_NAME" />"କୁ <ph name="ORIGIN" />ରେ ଚାଲିବା ପାଇଁ ସର୍ବଦା ଅନୁମତି ଦେବେ?</translation>
 <translation id="529296195492126134">ଏଫିମେରାଲ୍ ମୋଡ୍ ସମର୍ଥିତ ନୁହେଁ। ଦୟାକରି ଆପଣଙ୍କ ଆଡମିନିଷ୍ଟ୍ରେଟରଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ</translation>
 <translation id="5293170712604732402">ସେଟିଂସ୍‌କୁ ସେମାନଙ୍କର ମୂଳ ଡିଫଲ୍ଟରେ ରିଷ୍ଟୋର୍ କରନ୍ତୁ</translation>
 <translation id="5294097441441645251">ଏକ ସାନ ଅକ୍ଷର କିମ୍ବା ଅଣ୍ଡରସ୍କୋର୍ ସହିତ ଆରମ୍ଭ ହେବା ଉଚିତ</translation>
@@ -5157,6 +5168,7 @@
 <translation id="6054961935262556546">ଭିଜିବିଲିଟୀ ପରିବର୍ତ୍ତନ କରନ୍ତୁ</translation>
 <translation id="6055171183283175969">ଆପଣ ଲେଖିଥିବା ପାସ୍‍ୱର୍ଡ ଭୁଲ୍ ଅଛି।</translation>
 <translation id="6055392876709372977">RSA ଏନକ୍ରିପ୍ସନ୍ ସହିତ PKCS #1 SHA-256</translation>
+<translation id="6055544610007596637">ଆପଣଙ୍କ <ph name="DEVICE_TYPE" /> ପାଇଁ Google Play Storeରୁ ଆପ୍ସ ଇନଷ୍ଟଲ କରନ୍ତୁ</translation>
 <translation id="6056710589053485679">ସାଧାରଣ ପୁଣି ଲୋଡ୍ ହେଉଛି</translation>
 <translation id="6057312498756061228">ସୁରକ୍ଷା ଯାଞ୍ଚ ପାଇଁ ଏହି ଫାଇଲଟି ବହୁତ ବଡ଼ ଅଟେ। ଆପଣ 50 MB ପର୍ଯ୍ୟନ୍ତ ଫାଇଲଗୁଡ଼ିକୁ ଖୋଲି ପାରିବେ।</translation>
 <translation id="6057381398996433816">ମୋସନ୍ ଏବଂ ଲାଇଟ୍ ସେନ୍ସର୍ ବ୍ୟବହାର କରିବା ପାଇଁ ଏହି ସାଇଟ୍‍କୁ ବ୍ଲକ୍ କରାଯାଇଛି।</translation>
@@ -6131,6 +6143,7 @@
 <translation id="7002055706763150362">Chromebook ପାଇଁ ସ୍ମାର୍ଟ ଲକ୍ ସେଟ୍ ଅପ୍ କରିବାକୁ, Google, ଏହା ଆପଣ ଅଟନ୍ତି ବୋଲି ସୁନିଶ୍ଚିତ କରିବା ଦରକାର—ଆରମ୍ଭ କରିବା ପାଇଁ ଆପଣଙ୍କର ପାସୱାର୍ଡ୍ ଟାଇପ୍ କରନ୍ତୁ।</translation>
 <translation id="7003339318920871147">ୱେବ୍ ଡାଟାବେସ୍</translation>
 <translation id="7003454175711353260">{COUNT,plural, =1{{COUNT}ଟି ଫାଇଲ୍}other{{COUNT}ଟି ଫାଇଲ୍}}</translation>
+<translation id="7003705861991657723">ଆଲଫା</translation>
 <translation id="7003723821785740825">ଆପଣଙ୍କର ଡିଭାଇସ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବା ପାଇଁ ଏକ ଦ୍ରୁତତର ଉପାୟ ସେଟ୍ କରନ୍ତୁ</translation>
 <translation id="7003844668372540529"><ph name="VENDOR_NAME" />ରୁ <ph name="PRODUCT_ID" /> ଅଜଣା ଉତ୍ପାଦ</translation>
 <translation id="7004402701596653846">ସାଇଟ୍ MIDI ବ୍ୟବହାର କରିପାରିବ</translation>
@@ -6147,6 +6160,7 @@
 <translation id="7008815993384338777">ବର୍ତ୍ତମାନ ରୋମିଂରେ ନାହିଁ</translation>
 <translation id="7009709314043432820"><ph name="APP_NAME" /> ଆପଣଙ୍କ କ୍ୟାମେରା ବ୍ୟବହାର କରୁଛି</translation>
 <translation id="701080569351381435">ଉତ୍ସ ଦେଖନ୍ତୁ</translation>
+<translation id="7011797924920577670">ଆପଣଙ୍କ ରୁଚିଗୁଡ଼ିକୁ ଆକଳନ କରେ</translation>
 <translation id="7014174261166285193">ଇନ୍‍ଷ୍ଟଲ୍ କରିହେଲା ନାହିଁ</translation>
 <translation id="7014480873681694324">ହାଇଲାଇଟ୍ କାଢ଼ି ଦିଅନ୍ତୁ</translation>
 <translation id="7017004637493394352">ପୁଣି "Ok Google" କୁହନ୍ତୁ</translation>
@@ -6214,6 +6228,7 @@
 <translation id="7082568314107259011"><ph name="NETWORK_NAME" /> ଆପଣଙ୍କ ଆଡମିନିଷ୍ଟ୍ରେଟରଙ୍କ ଦ୍ୱାରା ପରିଚାଳିତ ହେଉଛି</translation>
 <translation id="7085389578340536476">ଅଡିଓ ରେକର୍ଡ କରିବାକୁ Chromeକୁ ଅନୁମତି ଦେବେ କି?</translation>
 <translation id="708550780726587276">(କନଫିଗର କରାଯାଇନାହିଁ)</translation>
+<translation id="7086531709814430567">ଏହି ଏକ୍ସଟେନସନଗୁଡ଼ିକୁ <ph name="ORIGIN" />ରେ ଚାଲିବା ପାଇଁ ସର୍ବଦା ଅନୁମତି ଦେବେ?</translation>
 <translation id="7086672505018440886">ଆର୍କାଇଭରେ Chrome ଲଗ୍ ଫାଇଲଗୁଡ଼ିକ ସାମିଲ କରନ୍ତୁ।</translation>
 <translation id="7088434364990739311">ଅପ୍‍ଡେଟ୍‍ର ଯାଞ୍ଚ ପ୍ରକ୍ରିୟା ଆରମ୍ଭ କରିବାରେ ବିଫଳ ହେଲା (ତ୍ରୁଟି କୋଡ୍ <ph name="ERROR" />)।</translation>
 <translation id="7088674813905715446">ବ୍ୟବସ୍ଥାପକଙ୍କ ଦ୍ୱାରା ଏହି ଡିଭାଇସ୍‌ ଏକ ଅବ୍ୟବସ୍ଥିତ ସ୍ଥିତିରେ ରଖାଯାଇଛି। ଏହାକୁ ନାମାଙ୍କନ ପାଇଁ ସକ୍ଷମ କରିବାକୁ, ଦୟାକରି ଆପଣଙ୍କର ବ୍ୟବସ୍ଥାପକଙ୍କ ଦ୍ୱାରା ଡିଭାଇସ୍‌କୁ ଏକ ବିଳମ୍ବିତ ସ୍ଥିତିରେ ରହିବାକୁ ଦିଅନ୍ତୁ।</translation>
@@ -8344,6 +8359,7 @@
 <translation id="9215742531438648683">Google Play Store ଅନଇନଷ୍ଟଲ୍ କରନ୍ତୁ</translation>
 <translation id="9218430445555521422">ଡିଫଲ୍ଟ ଭାବେ ସେଟ୍ କରନ୍ତୁ</translation>
 <translation id="9218842937876577955"><ph name="APP_NAME" /> (ଅସମର୍ଥିତ ଆପ୍)</translation>
+<translation id="9219582468404818260">ଏକ ଉନ୍ନତ ୱେବ ତିଆରି କରିବାରେ ଆମକୁ ସାହାଯ୍ୟ କରନ୍ତୁ</translation>
 <translation id="9220525904950070496">ଆକାଉଣ୍ଟ କାଢ଼ିଦିଅନ୍ତୁ</translation>
 <translation id="9220820413868316583">ଆଙ୍ଗୁଠି ଉଠାନ୍ତୁ ଏହାପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।</translation>
 <translation id="923467487918828349">ସବୁ ଦେଖାନ୍ତୁ</translation>
diff --git a/chrome/app/resources/generated_resources_pa.xtb b/chrome/app/resources/generated_resources_pa.xtb
index 1e8eec00..e774195 100644
--- a/chrome/app/resources/generated_resources_pa.xtb
+++ b/chrome/app/resources/generated_resources_pa.xtb
@@ -1019,6 +1019,7 @@
 <translation id="1944921356641260203">ਅੱਪਡੇਟ ਮਿਲਿਆ</translation>
 <translation id="1947136734041527201">ਤੁਹਾਨੂੰ ਉਸ ਖਾਤੇ ਨਾਲ ਵੈੱਬਸਾਈਟਾਂ ਵਿੱਚ ਸਾਈਨ-ਇਨ ਕਰਨ ਦਿੰਦਾ ਹੈ ਜਿਸਦੀ ਵਰਤੋਂ ਤੁਸੀਂ ਪਛਾਣ ਸੰਬੰਧੀ ਸੇਵਾ ਨਾਲ ਕਰਦੇ ਹੋ</translation>
 <translation id="1949584741547056205">ਤਤਕਾਲ ਜਵਾਬ</translation>
+<translation id="1949849604471335579">ਵਾਲਪੇਪਰ, ਸਕ੍ਰੀਨ-ਸੇਵਰ, ਐਕਸੈਂਟ ਰੰਗ ਅਤੇ ਹੋਰ ਬਹੁਤ ਕੁਝ ਨੂੰ ਵਿਅਕਤੀਗਤ ਬਣਾਓ</translation>
 <translation id="1951012854035635156">Assistant</translation>
 <translation id="1954597385941141174">ਸਾਈਟਾਂ USB ਡੀਵਾਈਸਾਂ ਨਾਲ ਕਨੈਕਟ ਕਰਨ ਲਈ ਪੁੱਛ ਸਕਦੀਆਂ ਹਨ</translation>
 <translation id="1954813140452229842">ਸਾਂਝਾਕਰਨ ਮਾਊਂਟ ਕਰਨ ਵਿੱਚ ਗੜਬੜ ਹੋਈ। ਕਿਰਪਾ ਕਰਕੇ ਆਪਣੇ ਕ੍ਰੀਡੈਂਸ਼ੀਅਲ ਦੀ ਜਾਂਚ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</translation>
@@ -1050,6 +1051,7 @@
 <translation id="1981434377190976112">ਸਾਰੀਆਂ ਵੈੱਬਸਾਈਟਾਂ 'ਤੇ ਆਪਣਾ ਸਾਰਾ ਡਾਟਾ ਪੜ੍ਹੋ</translation>
 <translation id="1984417487208496350">ਕੋਈ ਸੁਰੱਖਿਆ ਨਹੀਂ (ਇਸਦੀ ਸਿਫ਼ਾਰਸ਼ ਨਹੀਂ ਕੀਤੀ ਜਾਂਦੀ)</translation>
 <translation id="1987317783729300807">ਖਾਤੇ</translation>
+<translation id="1987574314042117472">ਪ੍ਰਸਿੱਧ ਐਪਾਂ ਨੂੰ ਚੁਣੋ ਅਤੇ ਸਥਾਪਤ ਕਰੋ</translation>
 <translation id="1988259784461813694">ਲੋੜ</translation>
 <translation id="1989112275319619282">ਬ੍ਰਾਊਜ਼ ਕਰੋ</translation>
 <translation id="1989903373608997757">ਹਮੇਸ਼ਾਂ ਵਰਤੋ</translation>
@@ -1115,6 +1117,7 @@
 <translation id="2048554637254265991">ਕੰਟੇਨਰ ਪ੍ਰਬੰਧਕ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਵੇਲੇ ਗੜਬੜ ਹੋਈ। ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</translation>
 <translation id="2048653237708779538">ਕਾਰਵਾਈ ਉਪਲਬਧ ਨਹੀਂ ਹੈ</translation>
 <translation id="2050339315714019657">ਪੋਰਟਰੇਟ</translation>
+<translation id="2052572566310583903">ਤੁਹਾਡੇ ਦੂਜੇ ਡੀਵਾਈਸਾਂ 'ਤੇ ਸਥਾਪਤ ਕੀਤੀਆਂ ਗਈਆਂ</translation>
 <translation id="2053312383184521053">ਨਿਸ਼ਕਿਰਿਆ ਸਥਿਤੀ ਡਾਟਾ</translation>
 <translation id="2054240652864153171">ਕੀ <ph name="PARTITION_SITE_NAME" /> 'ਤੇ ਵੰਡੀ ਗਈ <ph name="SITE_NAME" /> ਲਈ ਸਾਈਟ ਡਾਟਾ ਕਲੀਅਰ ਕਰਨਾ ਹੈ?</translation>
 <translation id="2055585478631012616">ਖੁੱਲ੍ਹੀਆਂ ਟੈਬਾਂ ਸਮੇਤ, ਤੁਹਾਨੂੰ ਇਹਨਾਂ ਸਾਈਟਾਂ ਤੋਂ ਸਾਈਨ-ਆਊਟ ਕਰ ਦਿੱਤਾ ਜਾਵੇਗਾ</translation>
@@ -1277,6 +1280,7 @@
 <translation id="2191754378957563929">ਚਾਲੂ</translation>
 <translation id="2192505247865591433">ਤੋਂ:</translation>
 <translation id="2193365732679659387">ਭਰੋਸਾ ਸੈਟਿੰਗਾਂ</translation>
+<translation id="2194554416429452547">ਪਰਖ ਦੌਰਾਨ, Chrome ਸਪੈਮ, ਧੋਖਾਧੜੀ, ਅਤੇ ਸਾਈਟਾਂ ਵਿਚਕਾਰ ਸਾਂਝਾਕਰਨ ਨੂੰ ਸੀਮਤ ਕਰਨ ਦੇ ਤਰੀਕਿਆਂ ਦੀ ਪੜਚੋਲ ਕਰ ਰਿਹਾ ਹੈ। Chrome <ph name="ESTIMATE_INTERESTS_LINK" /> ਵੀ ਦਿਖਾਉਂਦਾ ਹੈ, ਜਿਸ ਨੂੰ ਸਾਈਟਾਂ ਤੁਹਾਨੂੰ ਵਿਗਿਆਪਨ ਦਿਖਾਉਣ ਲਈ ਵਰਤ ਸਕਦੀਆਂ ਹਨ। ਤੁਸੀਂ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਜਾ ਕੇ ਆਪਣੀਆਂ ਦਿਲਚਸਪੀਆਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰ ਸਕਦੇ ਹੋ।</translation>
 <translation id="2194856509914051091">ਵਿਚਾਰੇ ਜਾਣ ਵਾਲੀਆਂ ਚੀਜ਼ਾਂ</translation>
 <translation id="2195331105963583686">ਤੁਸੀਂ ਹਾਲੇ ਵੀ ਉਸ ਸਮੇਂ ਤੋਂ ਬਾਅਦ ਇਸ <ph name="DEVICE_TYPE" /> ਨੂੰ ਵਰਤ ਸਕੋਗੇ, ਪਰ ਇਸਨੂੰ ਸਵੈਚਲਿਤ ਸਾਫ਼ਟਵੇਅਰ ਅਤੇ ਸੁਰੱਖਿਆ ਅੱਪਡੇਟ ਨਹੀਂ ਮਿਲਣਗੇ</translation>
 <translation id="2195729137168608510">ਈਮੇਲ ਸੁਰੱਖਿਆ</translation>
@@ -1884,6 +1888,7 @@
 <translation id="2749836841884031656">ਸਿਮ</translation>
 <translation id="2749881179542288782">ਸਪੈਲਿੰਗ ਨਾਲ ਵਿਆਕਰਣ ਦੀ ਜਾਂਚ ਕਰੋ</translation>
 <translation id="2753677631968972007">ਸਾਈਟ ਦੀਆਂ ਇਜਾਜ਼ਤਾਂ ਹੱਥੀਂ ਕੰਟਰੋਲ ਕਰੋ।</translation>
+<translation id="2754825024506485820">Google Play Store 'ਤੇ ਉਤਪਾਦਕਤਾ ਤੋਂ ਲੈ ਕੇ ਮਨੋਰੰਜਨ ਤੱਕ, ਆਪਣੀਆਂ ਲੋੜੀਂਦੀਆਂ ਐਪਾਂ ਲੱਭੋ। ਤੁਸੀਂ ਕਿਸੇ ਵੀ ਵੇਲੇ ਐਪਾਂ ਨੂੰ ਸਥਾਪਤ ਕਰ ਸਕਦੇ ਹੋ।</translation>
 <translation id="2755349111255270002">ਇਸ <ph name="DEVICE_TYPE" /> ਨੂੰ ਰੀਸੈੱਟ ਕਰੋ</translation>
 <translation id="2755367719610958252">ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ</translation>
 <translation id="275662540872599901">ਸਕ੍ਰੀਨ ਬੰਦ</translation>
@@ -1960,6 +1965,7 @@
 <translation id="2815693974042551705">ਬੁੱਕਮਾਰਕ ਫੋਲਡਰ</translation>
 <translation id="2816319641769218778">ਪਾਸਵਰਡਾਂ ਨੂੰ ਆਪਣੇ 'Google ਖਾਤੇ' ਵਿੱਚ ਰੱਖਿਅਤ ਕਰਨ ਲਈ, ਸਿੰਕ ਚਾਲੂ ਕਰੋ।</translation>
 <translation id="2816628817680324566">ਕੀ ਇਸ ਸਾਈਟ ਨੂੰ ਤੁਹਾਡੀ ਸੁਰੱਖਿਆ ਕੁੰਜੀ ਦੀ ਪਛਾਣ ਕਰਨ ਦੇਣੀ ਹੈ?</translation>
+<translation id="2817435998497102771">ਆਪਣੇ ਵਾਲਪੇਪਰ ਅਤੇ ਸਟਾਈਲ ਸੈੱਟ ਕਰੋ</translation>
 <translation id="2818476747334107629">ਪ੍ਰਿੰਟਰ ਵੇਰਵੇ</translation>
 <translation id="2819167288942847344">ਸਕ੍ਰੀਨ 'ਤੇ ਐਪਾਂ ਦੇ ਅਜੀਬ ਢੰਗ ਨਾਲ ਦਿਖਾਈ ਦੇਣ ਤੋਂ ਬਚਣ ਲਈ ਫ਼ੋਨ ਅਤੇ ਟੈਬਲੈੱਟ ਵਾਸਤੇ ਪ੍ਰੀਸੈੱਟਾਂ ਜਾਂ ਆਕਾਰ ਬਦਲਣਯੋਗ ਵਿੰਡੋਆਂ ਨੂੰ ਵਰਤੋ</translation>
 <translation id="2820957248982571256">ਸਕੈਨ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ...</translation>
@@ -2852,6 +2858,7 @@
 <translation id="3727144509609414201">ਉਪਲਬਧ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ</translation>
 <translation id="3727187387656390258">ਪੌਪਅਪ ਦੀ ਜਾਂਚ ਕਰੋ</translation>
 <translation id="372722114124766626">ਬੱਸ ਇੱਕ ਵਾਰ</translation>
+<translation id="3727332897090187514">ਕੋਈ ਨੋਟ-ਕਥਨ ਸ਼ਾਮਲ ਨਹੀਂ ਕੀਤਾ ਗਿਆ</translation>
 <translation id="3727473233247516571">ਪੂਰੇ ਪੰਨੇ ਦੇ ਕੈਸ਼ੇ ਵਿੱਚ ਸਟੋਰ ਕੀਤਾ ਸਬਫ੍ਰੇਮ: <ph name="BACK_FORWARD_CACHE_PAGE_URL" /></translation>
 <translation id="3728188878314831180">ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਮਿਰਰ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ</translation>
 <translation id="3728681439294129328">ਨੈੱਟਵਰਕ ਪਤੇ ਦਾ ਸੰਰੂਪਣ ਕਰੋ</translation>
@@ -3187,6 +3194,7 @@
 <translation id="4031527940632463547">ਸੈਂਸਰ ਬਲਾਕ ਕੀਤੇ ਗਏ</translation>
 <translation id="4033415645631238123">Smart Lock ਨਾਲ ਸਾਈਨ-ਇਨ ਕਰਨ ਦੀ ਸੁਵਿਧਾ ਹੁਣ ਉਪਲਬਧ ਨਹੀਂ ਹੈ। ਤੁਸੀਂ ਹਾਲੇ ਵੀ Smart Lock ਨਾਲ ਅਣਲਾਕ ਕਰ ਸਕਦੇ ਹੋ।</translation>
 <translation id="4033471457476425443">ਨਵਾਂ ਫੋਲਡਰ ਸ਼ਾਮਲ ਕਰੋ</translation>
+<translation id="4033711848170683365">ਇਸ ਨਾਲ ਇਸ ਡੀਵਾਈਸ ਤੋਂ ਬ੍ਰਾਊਜ਼ਿੰਗ ਡਾਟਾ ਪੱਕੇ ਤੌਰ 'ਤੇ ਮਿਟ ਜਾਵੇਗਾ। ਇਸ ਪ੍ਰੋਫਾਈਲ ਵਿਚਲੇ Google ਖਾਤਿਆਂ ਨੂੰ ਤੁਹਾਡੇ <ph name="DEVICE_TYPE" /> ਦੀਆਂ ਹੋਰ ਐਪਾਂ ਵੱਲੋਂ ਵਰਤਿਆ ਜਾ ਸਕਦਾ ਹੈ। <ph name="BEGIN_LINK" /><ph name="SETTING_SECTION" /> &gt; <ph name="ACCOUNTS_SECTION" /><ph name="END_LINK" /> ਵਿੱਚ ਜਾ ਕੇ ਤੁਸੀਂ ਇਨ੍ਹਾਂ ਖਾਤਿਆਂ ਨੂੰ ਹਟਾ ਸਕਦੇ ਹੋ।</translation>
 <translation id="4033963223187371752">ਸੁਰੱਖਿਅਤ ਸਾਈਟਾਂ ਚਿੱਤਰਾਂ ਜਾਂ ਵੈੱਬ ਫ੍ਰੇਮਾਂ ਵਰਗੀ ਅਸੁਰੱਖਿਅਤ ਸਮੱਗਰੀ ਨਾਲ ਪਰੋਈਆਂ ਹੋ ਸਕਦੀਆਂ ਹਨ</translation>
 <translation id="4034824040120875894">ਪ੍ਰਿੰਟਰ</translation>
 <translation id="4035758313003622889">&amp;ਕੰਮ ਪ੍ਰਬੰਧਕ</translation>
@@ -3465,6 +3473,7 @@
 <translation id="4314815835985389558">ਸਿੰਕ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ</translation>
 <translation id="4315933848520197627">ਖਾਤਾ ਅਣਲਿੰਕ ਕਰੋ</translation>
 <translation id="4316850752623536204">ਵਿਕਾਸਕਾਰ ਵੈੱਬਸਾਈਟ</translation>
+<translation id="4317733381297736564">ਐਪ-ਅੰਦਰ ਖਰੀਦਾਂ</translation>
 <translation id="4317820549299924617">ਪੁਸ਼ਟੀਕਰਨ ਅਸਫਲ ਰਿਹਾ</translation>
 <translation id="4320177379694898372">ਕੋਈ ਇੰਟਰਨੈਟ ਕਨੈਕਸ਼ਨ ਨਹੀਂ</translation>
 <translation id="4322394346347055525">ਹੋਰ ਟੈਬਸ ਬੰਦ ਕਰੋ</translation>
@@ -4048,6 +4057,7 @@
 <translation id="4893522937062257019">ਲਾਕ ਸਕ੍ਰੀਨ 'ਤੇ</translation>
 <translation id="4897496410259333978">ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।</translation>
 <translation id="4898011734382862273">ਪ੍ਰਮਾਣ-ਪੱਤਰ "<ph name="CERTIFICATE_NAME" />" ਅਥਾਰਿਟੀ ਨੂੰ ਪ੍ਰਸਤੁਤ ਕਰਦਾ ਹੈ</translation>
+<translation id="4899696330053002588">ਇਸ ਵਿੱਚ ਵਿਗਿਆਪਨ ਸ਼ਾਮਲ ਹਨ</translation>
 <translation id="489985760463306091">ਹਾਨੀਕਾਰਕ ਸਾਫਟਵੇਅਰ ਹਟਾਉਣ ਦੀ ਪ੍ਰਕਿਰਿਆ ਪੂਰੀ ਕਰਨ ਲਈ, ਆਪਣੇ ਕੰਪਿਊਟਰ ਨੂੰ ਮੁੜ-ਚਾਲੂ ਕਰੋ</translation>
 <translation id="4900392736118574277">ਤੁਹਾਡਾ ਸ਼ੁਰੂਆਤੀ ਪੰਨਾ <ph name="URL" /> 'ਤੇ ਬਦਲ ਦਿੱਤਾ ਗਿਆ ਸੀ।</translation>
 <translation id="490051679772058907"><ph name="REFRESH_RATE" /> Hz - ਇੰਟਰਲੇਸਡ</translation>
@@ -4421,6 +4431,7 @@
 <translation id="52912272896845572">ਨਿੱਜੀ ਕੁੰਜੀ ਫ਼ਾਈਲ ਅਵੈਧ ਹੈ।</translation>
 <translation id="5291739252352359682">Chrome ਬ੍ਰਾਊਜ਼ਰ ਵਿੱਚ ਸਵੈਚਲਿਤ ਤੌਰ 'ਤੇ ਮੀਡੀਆ ਲਈ ਸੁਰਖੀਆਂ ਬਣਾਉਂਦੀ ਹੈ (ਫ਼ਿਲਹਾਲ ਅੰਗਰੇਜ਼ੀ ਵਿੱਚ ਉਪਲਬਧ ਹੈ)। ਆਡੀਓ ਅਤੇ ਸੁਰਖੀਆਂ 'ਤੇ ਸਥਾਨਕ ਤੌਰ 'ਤੇ ਪ੍ਰਕਿਰਿਆ ਕੀਤੀ ਜਾਂਦੀ ਹੈ ਅਤੇ ਇਹਨਾਂ ਨੂੰ ਕਦੇ ਵੀ ਡੀਵਾਈਸ ਤੋਂ ਬਾਹਰ ਨਹੀਂ ਲਿਜਾਇਆ ਜਾਂਦਾ ਹੈ।</translation>
 <translation id="529175790091471945">ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਫੌਰਮੈਟ ਕਰੋ</translation>
+<translation id="5292862864186939732">ਕੀ <ph name="ORIGIN" /> 'ਤੇ "<ph name="EXTENSION_NAME" />" ਨੂੰ ਹਮੇਸ਼ਾਂ ਚਲਾਉਣ ਦੀ ਇਜਾਜ਼ਤ ਦੇਣੀ ਹੈ?</translation>
 <translation id="529296195492126134">ਅਲਪਜੀਵੀ ਮੋਡ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ</translation>
 <translation id="5293170712604732402">ਸੈਟਿੰਗਾਂ ਨੂੰ ਉਹਨਾਂ ਦੇ ਮੂਲ ਪੂਰਵ-ਨਿਰਧਾਰਤਾਂ 'ਤੇ ਮੁੜ-ਬਹਾਲ ਕਰੋ</translation>
 <translation id="5294097441441645251">ਛੋਟੇ ਅੱਖਰ ਜਾਂ ਅੰਡਰਸਕੋਰ ਨਾਲ ਸ਼ੁਰੂ ਹੋਣਾ ਲਾਜ਼ਮੀ ਹੈ</translation>
@@ -5178,6 +5189,7 @@
 <translation id="6054961935262556546">ਦਿਖਣਯੋਗਤਾ ਬਦਲੋ</translation>
 <translation id="6055171183283175969">ਤੁਹਾਡੇ ਵੱਲੋਂ ਦਾਖਲ ਕੀਤਾ ਗਿਆ ਪਾਸਵਰਡ ਗਲਤ ਹੈ।</translation>
 <translation id="6055392876709372977">RSA ਐਨਕ੍ਰਿਪਸ਼ਨ ਨਾਲ PKCS #1 SHA-256</translation>
+<translation id="6055544610007596637">Google Play Store ਤੋਂ ਆਪਣੇ <ph name="DEVICE_TYPE" /> ਲਈ ਐਪਾਂ ਸਥਾਪਤ ਕਰੋ</translation>
 <translation id="6056710589053485679">ਸਧਾਰਨ ਰੀਲੋਡ</translation>
 <translation id="6057312498756061228">ਇਹ ਫ਼ਾਈਲ ਸੁਰੱਖਿਆ ਜਾਂਚ ਲਈ ਬਹੁਤ ਵੱਡੀ ਹੈ। ਤੁਸੀਂ 50 MB ਤੱਕ ਦੀਆਂ ਫ਼ਾਈਲਾਂ ਖੋਲ੍ਹ ਸਕਦੇ ਹੋ।</translation>
 <translation id="6057381398996433816">ਇਸ ਸਾਈਟ ਨੂੰ ਮੋਸ਼ਨ ਅਤੇ ਲਾਈਟ ਸੈਂਸਰਾਂ ਦੀ ਵਰਤੋਂ ਕਰਨ ਤੋਂ ਬਲਾਕ ਕੀਤਾ ਗਿਆ ਹੈ।</translation>
@@ -6153,6 +6165,7 @@
 <translation id="7002055706763150362">Chromebook ਲਈ 'ਸਮਾਰਟ ਲਾਕ' ਸੈੱਟ-ਅਪ ਕਰਨ ਵਾਸਤੇ, Google ਨੂੰ ਇਹ ਪੱਕਾ ਕਰਨ ਦੀ ਲੋੜ ਹੈ ਕਿ ਇਹ ਤੁਸੀਂ ਹੋ—ਸ਼ੁਰੂਆਤ ਕਰਨ ਲਈ ਆਪਣਾ ਪਾਸਵਰਡ ਟਾਈਪ ਕਰੋ।</translation>
 <translation id="7003339318920871147">ਵੈੱਬ ਡਾਟਾਬੇਸ</translation>
 <translation id="7003454175711353260">{COUNT,plural, =1{{COUNT} ਫ਼ਾਈਲ}one{{COUNT} ਫ਼ਾਈਲ}other{{COUNT} ਫ਼ਾਈਲਾਂ}}</translation>
+<translation id="7003705861991657723">ਅਲਫ਼ਾ</translation>
 <translation id="7003723821785740825">ਆਪਣੀ ਡੀਵਾਈਸ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਲਈ ਇੱਕ ਵਧੇਰੇ ਤੇਜ਼ ਤਰੀਕਾ ਸਥਾਪਤ ਕਰੋ</translation>
 <translation id="7003844668372540529"><ph name="VENDOR_NAME" /> ਤੋਂ ਅਗਿਆਤ ਉਤਪਾਦ <ph name="PRODUCT_ID" /></translation>
 <translation id="7004402701596653846">ਸਾਈਟ MIDI ਨੂੰ ਵਰਤ ਸਕਦੀ ਹੈ</translation>
@@ -6169,6 +6182,7 @@
 <translation id="7008815993384338777">ਫ਼ਿਲਹਾਲ ਰੋਮਿੰਗ 'ਤੇ ਨਹੀਂ ਹੈ</translation>
 <translation id="7009709314043432820"><ph name="APP_NAME" /> ਤੁਹਾਡੇ ਕੈਮਰੇ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀ ਹੈ</translation>
 <translation id="701080569351381435">ਸਰੋਤ ਦੇਖੋ</translation>
+<translation id="7011797924920577670">ਤੁਹਾਡੀਆਂ ਦਿਲਚਸਪੀਆਂ ਦਾ ਅੰਦਾਜ਼ਾ ਲਗਾਉਂਦਾ ਹੈ</translation>
 <translation id="7014174261166285193">ਇੰਸਟੌਲੇਸ਼ਨ ਅਸਫਲ।</translation>
 <translation id="7014480873681694324">ਹਾਈਲਾਈਟ ਹਟਾਓ</translation>
 <translation id="7017004637493394352">ਦੁਬਾਰਾ "Ok Google" ਕਹੋ</translation>
@@ -6236,6 +6250,7 @@
 <translation id="7082568314107259011"><ph name="NETWORK_NAME" /> ਦਾ ਪ੍ਰਬੰਧਨ ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਦੁਆਰਾ ਕੀਤਾ ਜਾਂਦਾ ਹੈ</translation>
 <translation id="7085389578340536476">ਕੀ Chrome ਨੂੰ ਆਡੀਓ ਰਿਕਾਰਡ ਕਰਨ ਦੇਣਾ ਹੈ?</translation>
 <translation id="708550780726587276">(ਸੰਰੂਪਣ ਨਹੀਂ ਕੀਤਾ ਗਿਆ)</translation>
+<translation id="7086531709814430567">ਕੀ ਇਨ੍ਹਾਂ ਐਕਸਟੈਂਸ਼ਨਾਂ ਨੂੰ ਹਮੇਸ਼ਾਂ <ph name="ORIGIN" /> 'ਤੇ ਚੱਲਣ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?</translation>
 <translation id="7086672505018440886">Chrome ਲੌਗ ਫ਼ਾਈਲਾਂ ਨੂੰ ਪੁਰਾਲੇਖ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ।</translation>
 <translation id="7088434364990739311">ਅੱਪਡੇਟ ਜਾਂਚ ਸ਼ੁਰੂ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ (ਗੜਬੜ ਕੋਡ <ph name="ERROR" />)।</translation>
 <translation id="7088674813905715446">ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਪ੍ਰਬੰਧਕ ਵੱਲੋਂ ਵਾਂਝਾਕਰਨ ਸਥਿਤੀ ਵਿੱਚ ਰੱਖਿਆ ਗਿਆ ਹੈ। ਇਸਨੂੰ ਦਰਜਾਬੰਦੀ ਲਈ ਚਾਲੂ ਕਰਨ ਲਈ, ਕਿਰਪਾ ਕਰਕੇ ਇੱਕ ਵਿਚਾਰ ਅਧੀਨ ਸਥਿਤੀ ਵਿੱਚ ਆਪਣੀ ਪ੍ਰਬੰਧਕ ਥਾਂ ਪ੍ਰਾਪਤ ਕਰੋ।</translation>
@@ -8368,6 +8383,7 @@
 <translation id="9215742531438648683">Google Play Store ਨੂੰ ਅਣਸਥਾਪਤ ਕਰੋ</translation>
 <translation id="9218430445555521422">ਪੂਰਵ-ਨਿਰਧਾਰਤ ਦੇ ਤੌਰ 'ਤੇ ਸੈੱਟ ਕਰੋ</translation>
 <translation id="9218842937876577955"><ph name="APP_NAME" /> (ਅਸਮਰਥਿਤ ਐਪ)</translation>
+<translation id="9219582468404818260">ਬਿਹਤਰ ਵੈੱਬ ਬਣਾਉਣ ਵਿੱਚ ਸਾਡੀ ਮਦਦ ਕਰੋ</translation>
 <translation id="9220525904950070496">ਖਾਤਾ ਹਟਾਓ</translation>
 <translation id="9220820413868316583">ਚੁੱਕੋ ਫਿਰ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</translation>
 <translation id="923467487918828349">ਸਾਰੇ ਦਿਖਾਓ</translation>
diff --git a/chrome/app/resources/generated_resources_pl.xtb b/chrome/app/resources/generated_resources_pl.xtb
index e31440cd..602b869 100644
--- a/chrome/app/resources/generated_resources_pl.xtb
+++ b/chrome/app/resources/generated_resources_pl.xtb
@@ -840,6 +840,7 @@
 <translation id="1794051631868188691">Nigdy tego nie pokazuj (<ph name="MERCHANT" />)</translation>
 <translation id="1794791083288629568">Wyślij opinię, by pomóc nam rozwiązać ten problem.</translation>
 <translation id="1795214765651529549">Użyj motywu klasycznego</translation>
+<translation id="1796105431091975902">Wybierz playbook Ansible, który chcesz dodać</translation>
 <translation id="1796588414813960292">Funkcje, które wymagają dźwięku, nie będą działać</translation>
 <translation id="1800502858278951817">Żadne rozszerzenia nie prosiły o uprawnienie do odczytywania i modyfikowania witryny <ph name="SITE_NAME" /></translation>
 <translation id="1802624026913571222">Uśpij po zamknięciu pokrywy</translation>
@@ -3025,6 +3026,7 @@
 <translation id="389901847090970821">Wybierz klawiaturę</translation>
 <translation id="3900966090527141178">Eksportuj hasła</translation>
 <translation id="3903187154317825986">Klawiatura wbudowana</translation>
+<translation id="3903191712482985591">Dodaj playbook</translation>
 <translation id="3904326018476041253">Usługi lokalizacyjne</translation>
 <translation id="3904849010307028014">Na podstawie Twoich interakcji z witryną, na przykład regularnego logowania się na konto, może ona wystawić token zaufania do Twojej przeglądarki. Jeśli później inne odwiedzane przez Ciebie witryny znajdą ważny token zaufania, z większym prawdopodobieństwem uznają Cię za człowieka, a nie bota.</translation>
 <translation id="3905761538810670789">Napraw aplikację</translation>
@@ -3635,6 +3637,7 @@
 <translation id="4510479820467554003">Lista kont rodzica</translation>
 <translation id="451102079304155829">koszyki</translation>
 <translation id="4513872120116766993">Przewidywanie tekstu podczas pisania</translation>
+<translation id="4513909579793564731">Zastosuj playbook</translation>
 <translation id="4513946894732546136">Twoja opinia</translation>
 <translation id="451407183922382411">Technologia <ph name="COMPANY_NAME" /></translation>
 <translation id="4514610446763173167">Przełącz, by odtworzyć lub wstrzymać wideo</translation>
@@ -5467,6 +5470,7 @@
 <translation id="635609604405270300">Nie wyłączaj urządzenia</translation>
 <translation id="63566973648609420">Twoje zaszyfrowane dane może odczytać tylko ktoś znający hasło. Google nie otrzyma Twojego hasła ani nie będzie go przechowywać. Jeśli je zapomnisz lub zechcesz zmienić to ustawienie, musisz <ph name="BEGIN_LINK" />zresetować synchronizację<ph name="END_LINK" />.</translation>
 <translation id="6357305427698525450">Niektóre obsługiwane linki nadal będą się otwierać w aplikacjach <ph name="APP_NAME" /> lub <ph name="APP_NAME_2" />.</translation>
+<translation id="6357794994761110294">Żadne rozszerzenia nie mają uprawnień do odczytywania i modyfikowania witryny <ph name="SITE_NAME" /></translation>
 <translation id="6358884629796491903">Smok</translation>
 <translation id="6361850914223837199">Szczegóły błędu:</translation>
 <translation id="6362853299801475928">&amp;Zgłoś problem</translation>
diff --git a/chrome/app/resources/generated_resources_pt-BR.xtb b/chrome/app/resources/generated_resources_pt-BR.xtb
index c9fd2fd..0ab8958 100644
--- a/chrome/app/resources/generated_resources_pt-BR.xtb
+++ b/chrome/app/resources/generated_resources_pt-BR.xtb
@@ -850,6 +850,7 @@
 <translation id="1794051631868188691">Nunca mostrar <ph name="MERCHANT" /></translation>
 <translation id="1794791083288629568">Envie um feedback para nos ajudar a corrigir esse problema.</translation>
 <translation id="1795214765651529549">Usar "Clássico"</translation>
+<translation id="1796105431091975902">Selecionar playbook Ansible para adicionar</translation>
 <translation id="1796588414813960292">Os recursos que precisam de som não funcionarão</translation>
 <translation id="1800502858278951817">Nenhuma extensão solicitou a leitura ou mudança de <ph name="SITE_NAME" /></translation>
 <translation id="1802624026913571222">Suspender quando a capa for fechada</translation>
@@ -1019,6 +1020,7 @@
 <translation id="1944921356641260203">Atualização encontrada</translation>
 <translation id="1947136734041527201">Permite fazer login em sites usando a conta que você tem com um serviço de identidade</translation>
 <translation id="1949584741547056205">Respostas rápidas</translation>
+<translation id="1949849604471335579">Personalizar papel de parede, protetor de tela, cores de destaque e muito mais</translation>
 <translation id="1951012854035635156">Assistente</translation>
 <translation id="1954597385941141174">Os sites podem pedir permissão para se conectar a dispositivos USB</translation>
 <translation id="1954813140452229842">Erro ao ativar o compartilhamento. Verifique suas credenciais e tente novamente.</translation>
@@ -1050,6 +1052,7 @@
 <translation id="1981434377190976112">Ler seus dados em qualquer site</translation>
 <translation id="1984417487208496350">Sem proteção (não recomendado)</translation>
 <translation id="1987317783729300807">Contas</translation>
+<translation id="1987574314042117472">Selecionar e instalar apps populares</translation>
 <translation id="1988259784461813694">Requisito</translation>
 <translation id="1989112275319619282">Procurar</translation>
 <translation id="1989903373608997757">Usar sempre</translation>
@@ -1115,6 +1118,7 @@
 <translation id="2048554637254265991">Erro ao iniciar o administrador de contêiner. Tente novamente.</translation>
 <translation id="2048653237708779538">Ação indisponível</translation>
 <translation id="2050339315714019657">Retrato</translation>
+<translation id="2052572566310583903">Instalado nos seus outros dispositivos</translation>
 <translation id="2053312383184521053">Dados em estado de inatividade</translation>
 <translation id="2054240652864153171">Limpar os dados do site <ph name="SITE_NAME" /> particionados em <ph name="PARTITION_SITE_NAME" />?</translation>
 <translation id="2055585478631012616">Sua conta será desconectada desses sites, inclusive nas guias abertas.</translation>
@@ -1277,6 +1281,7 @@
 <translation id="2191754378957563929">Ativado</translation>
 <translation id="2192505247865591433">De:</translation>
 <translation id="2193365732679659387">Configurações de confiança</translation>
+<translation id="2194554416429452547">Durante os testes, o Chrome explora maneiras de limitar spam, fraude e compartilhamento entre sites. O Chrome também <ph name="ESTIMATE_INTERESTS_LINK" /> para que os sites possam os usar para mostrar anúncios. Você pode gerenciar seus interesses nas configurações.</translation>
 <translation id="2194856509914051091">Considerações</translation>
 <translation id="2195331105963583686">Você ainda poderá usar este <ph name="DEVICE_TYPE" /> após esse período, mas ele não receberá mais atualizações automáticas de software e segurança</translation>
 <translation id="2195729137168608510">Proteção de e-mail</translation>
@@ -1884,6 +1889,7 @@
 <translation id="2749836841884031656">Chip</translation>
 <translation id="2749881179542288782">Verificar a gramática com a ortografia</translation>
 <translation id="2753677631968972007">Controlar as permissões de sites manualmente.</translation>
+<translation id="2754825024506485820">Encontre os apps de que você precisa, de produtividade a entretenimento, na Google Play Store. É possível instalar apps a qualquer momento.</translation>
 <translation id="2755349111255270002">Redefinir este <ph name="DEVICE_TYPE" /></translation>
 <translation id="2755367719610958252">Gerenciar recursos de acessibilidade</translation>
 <translation id="275662540872599901">tela desativada</translation>
@@ -1960,6 +1966,7 @@
 <translation id="2815693974042551705">Pasta de favoritos</translation>
 <translation id="2816319641769218778">Para salvar senhas na Conta do Google, ative a sincronização.</translation>
 <translation id="2816628817680324566">Permitir que este site identifique sua chave de segurança?</translation>
+<translation id="2817435998497102771">Definir Estilo e fundo de tela</translation>
 <translation id="2818476747334107629">Detalhes da impressora</translation>
 <translation id="2819167288942847344">Usar os tamanhos predefinidos para evitar problemas em smartphones, tablets ou janelas redimensionáveis</translation>
 <translation id="2820957248982571256">Verificando...</translation>
@@ -2854,6 +2861,7 @@
 <translation id="3727144509609414201">Redes W-Fi disponíveis</translation>
 <translation id="3727187387656390258">Inspecionar pop-up</translation>
 <translation id="372722114124766626">Apenas uma vez</translation>
+<translation id="3727332897090187514">Nenhuma observação foi adicionada</translation>
 <translation id="3727473233247516571">Subframe salvo em cache de avanço e retorno: <ph name="BACK_FORWARD_CACHE_PAGE_URL" /></translation>
 <translation id="3728188878314831180">espelhar notificações do smartphone;</translation>
 <translation id="3728681439294129328">Configurar endereço de rede</translation>
@@ -3049,6 +3057,7 @@
 <translation id="389901847090970821">Selecionar teclado</translation>
 <translation id="3900966090527141178">Exportar senhas</translation>
 <translation id="3903187154317825986">Teclado integrado</translation>
+<translation id="3903191712482985591">Adicionar playbook</translation>
 <translation id="3904326018476041253">Serviços de localização</translation>
 <translation id="3904849010307028014">Baseado na sua interação com um site, como fazer login em uma conta com frequência, o site pode emitir um token de confiança para o navegador. Se outros sites que você visitar verificarem e encontrarem um token de confiança válido, é mais provável que eles tratem você como uma pessoa e não como um robô.</translation>
 <translation id="3905761538810670789">Reparar app</translation>
@@ -3189,6 +3198,7 @@
 <translation id="4031527940632463547">Sensores bloqueados</translation>
 <translation id="4033415645631238123">O login com o Smart Lock não está mais disponível. Ainda é possível desbloquear com o Smart Lock.</translation>
 <translation id="4033471457476425443">Adicionar nova pasta</translation>
+<translation id="4033711848170683365">Esta ação vai excluir permanentemente os dados de navegação deste dispositivo. As Contas do Google relacionadas a este perfil ainda podem ser usadas por outros apps no <ph name="DEVICE_TYPE" />. Acesse <ph name="BEGIN_LINK" /><ph name="SETTING_SECTION" /> &gt; <ph name="ACCOUNTS_SECTION" /><ph name="END_LINK" /> para remover essas contas.</translation>
 <translation id="4033963223187371752">Sites seguros podem incorporar conteúdo não seguro, como imagens ou frames da Web</translation>
 <translation id="4034824040120875894">Impressora</translation>
 <translation id="4035758313003622889">&amp;Gerenciador de tarefas</translation>
@@ -3467,6 +3477,7 @@
 <translation id="4314815835985389558">Gerenciar sincronização</translation>
 <translation id="4315933848520197627">Desvincular conta</translation>
 <translation id="4316850752623536204">Website do desenvolvedor</translation>
+<translation id="4317733381297736564">Compras no app</translation>
 <translation id="4317820549299924617">A verificação não foi concluída</translation>
 <translation id="4320177379694898372">Sem conexão com a Internet</translation>
 <translation id="4322394346347055525">Fechar outras guias</translation>
@@ -3658,6 +3669,7 @@
 <translation id="4510479820467554003">Lista das contas de pai/mãe</translation>
 <translation id="451102079304155829">carrinhos</translation>
 <translation id="4513872120116766993">Escrita preditiva</translation>
+<translation id="4513909579793564731">Aplicar playbook</translation>
 <translation id="4513946894732546136">Comentários</translation>
 <translation id="451407183922382411">Tecnologia da <ph name="COMPANY_NAME" /></translation>
 <translation id="4514610446763173167">Alternar vídeo entre reproduzir e pausar</translation>
@@ -4050,6 +4062,7 @@
 <translation id="4893522937062257019">Na tela de bloqueio</translation>
 <translation id="4897496410259333978">Para ver mais informações, entre em contato com seu administrador.</translation>
 <translation id="4898011734382862273">O certificado "<ph name="CERTIFICATE_NAME" />" representa uma Autoridade de certificação</translation>
+<translation id="4899696330053002588">Contém anúncios</translation>
 <translation id="489985760463306091">Para terminar de remover o software nocivo, reinicie o computador</translation>
 <translation id="4900392736118574277">Sua página de inicialização foi alterada para <ph name="URL" />.</translation>
 <translation id="490051679772058907"><ph name="REFRESH_RATE" /> Hz (entrelaçado)</translation>
@@ -4423,6 +4436,7 @@
 <translation id="52912272896845572">O arquivo de chave privada é inválido.</translation>
 <translation id="5291739252352359682">Cria legendas automaticamente para conteúdo de mídia no navegador Chrome (disponível em inglês). Os áudios e as legendas são processados localmente e nunca deixam o dispositivo.</translation>
 <translation id="529175790091471945">Formatar este dispositivo</translation>
+<translation id="5292862864186939732">Sempre permitir que a extensão "<ph name="EXTENSION_NAME" />" seja executada em <ph name="ORIGIN" />?</translation>
 <translation id="529296195492126134">O modo temporário não é compatível. Entre em contato com seu administrador</translation>
 <translation id="5293170712604732402">Restaurar configurações para os padrões originais</translation>
 <translation id="5294097441441645251">Comece com um caractere minúsculo ou um sublinhado</translation>
@@ -5181,6 +5195,7 @@
 <translation id="6054961935262556546">Mudar visibilidade</translation>
 <translation id="6055171183283175969">A senha inserida está incorreta.</translation>
 <translation id="6055392876709372977">PKCS #1 SHA-256 com criptografia RSA</translation>
+<translation id="6055544610007596637">Instale apps para o dispositivo <ph name="DEVICE_TYPE" /> na Google Play Store</translation>
 <translation id="6056710589053485679">Recarregamento normal</translation>
 <translation id="6057312498756061228">Esse arquivo é grande demais para uma verificação de segurança. É possível abrir arquivos de até 50 MB.</translation>
 <translation id="6057381398996433816">Este site foi impedido de usar sensores de luz e movimento.</translation>
@@ -5489,6 +5504,7 @@
 <translation id="635609604405270300">Mantenha o dispositivo ligado</translation>
 <translation id="63566973648609420">Somente uma pessoa que tenha sua senha longa pode ler seus dados criptografados. A senha longa não é enviada para o Google ou armazenada por ele. Se você esquecer sua senha longa ou quiser alterar essa configuração, será necessário <ph name="BEGIN_LINK" />redefinir a sincronização<ph name="END_LINK" />.</translation>
 <translation id="6357305427698525450">Alguns links com suporte ainda serão abertos no app <ph name="APP_NAME" /> ou <ph name="APP_NAME_2" />.</translation>
+<translation id="6357794994761110294">Nenhuma extensão pode ler ou editar o site <ph name="SITE_NAME" /></translation>
 <translation id="6358884629796491903">Dragão</translation>
 <translation id="6361850914223837199">Detalhes do erro:</translation>
 <translation id="6362853299801475928">&amp;Informar um problema...</translation>
@@ -6155,6 +6171,7 @@
 <translation id="7002055706763150362">Para configurar o Smart Lock para Chromebook, o Google precisa confirmar que é você: digite sua senha para começar.</translation>
 <translation id="7003339318920871147">Bancos de dados da web</translation>
 <translation id="7003454175711353260">{COUNT,plural, =1{{COUNT} arquivo}one{{COUNT} arquivo}other{{COUNT} arquivos}}</translation>
+<translation id="7003705861991657723">Alfa</translation>
 <translation id="7003723821785740825">Configure uma forma mais rápida de desbloquear seu dispositivo</translation>
 <translation id="7003844668372540529">Produto <ph name="PRODUCT_ID" /> desconhecido de <ph name="VENDOR_NAME" /></translation>
 <translation id="7004402701596653846">O site pode usar um dispositivo MIDI</translation>
@@ -6171,6 +6188,7 @@
 <translation id="7008815993384338777">Não está em roaming no momento</translation>
 <translation id="7009709314043432820"><ph name="APP_NAME" /> está usando a câmera</translation>
 <translation id="701080569351381435">Exibir o código fonte</translation>
+<translation id="7011797924920577670">tenta prever seus interesses</translation>
 <translation id="7014174261166285193">Falha na instalação.</translation>
 <translation id="7014480873681694324">Remover destaque</translation>
 <translation id="7017004637493394352">Diga "Ok Google" novamente</translation>
@@ -6238,6 +6256,7 @@
 <translation id="7082568314107259011">A rede <ph name="NETWORK_NAME" /> é gerenciada pelo seu administrador</translation>
 <translation id="7085389578340536476">Permitir que o Chrome grave áudio?</translation>
 <translation id="708550780726587276">(não configurado)</translation>
+<translation id="7086531709814430567">Sempre permitir que essas extensões sejam executadas em <ph name="ORIGIN" />?</translation>
 <translation id="7086672505018440886">Incluir arquivos de registros do Chrome no arquivo.</translation>
 <translation id="7088434364990739311">A atualização da verificação falhou ao iniciar (código do erro <ph name="ERROR" />).</translation>
 <translation id="7088674813905715446">O administrador pôs este dispositivo no estado de provisionamento cancelado. Para ativar a inscrição do dispositivo, solicite que o administrador o coloque no estado "Pendente".</translation>
@@ -8372,6 +8391,7 @@
 <translation id="9215742531438648683">Desinstalar a Google Play Store</translation>
 <translation id="9218430445555521422">Definir como padrão</translation>
 <translation id="9218842937876577955"><ph name="APP_NAME" /> (app sem suporte)</translation>
+<translation id="9219582468404818260">Ajude a tornar a Web um lugar melhor</translation>
 <translation id="9220525904950070496">Remover conta</translation>
 <translation id="9220820413868316583">Levante o dedo e tente novamente.</translation>
 <translation id="923467487918828349">Mostrar tudo</translation>
diff --git a/chrome/app/resources/generated_resources_pt-PT.xtb b/chrome/app/resources/generated_resources_pt-PT.xtb
index 37f97d29..1e1bd53 100644
--- a/chrome/app/resources/generated_resources_pt-PT.xtb
+++ b/chrome/app/resources/generated_resources_pt-PT.xtb
@@ -838,6 +838,7 @@
 <translation id="1794051631868188691">Nunca mostrar <ph name="MERCHANT" /></translation>
 <translation id="1794791083288629568">Envie-nos comentários para nos ajudar a corrigir este problema.</translation>
 <translation id="1795214765651529549">Utilizar tema clássico</translation>
+<translation id="1796105431091975902">Selecione um guia interativo do Ansible para adicionar</translation>
 <translation id="1796588414813960292">As funcionalidades que necessitam de som não funcionarão</translation>
 <translation id="1800502858278951817">Nenhuma extensão pediu para ler e alterar <ph name="SITE_NAME" /></translation>
 <translation id="1802624026913571222">Suspender quando a tampa for fechada</translation>
@@ -2460,6 +2461,7 @@
 <translation id="3348038390189153836">Detetado dispositivo removível</translation>
 <translation id="3348131053948466246">Emoji sugerido. Prima a seta para cima ou para baixo para navegar e Enter para inserir.</translation>
 <translation id="3349933790966648062">Utilização da memória</translation>
+<translation id="3353786022389205125">Ative a opção "Mostrar o ecrã de bloqueio quando for ativado após a suspensão" e tente novamente</translation>
 <translation id="3354972872297836698">Não foi possível sincronizar com o dispositivo <ph name="DEVICE_NAME" />; selecione o dispositivo para tentar novamente</translation>
 <translation id="3355936511340229503">Erro de ligação</translation>
 <translation id="3356469410714175391">(Cartão virtual ativado)</translation>
@@ -3033,6 +3035,7 @@
 <translation id="389901847090970821">Selecionar teclado</translation>
 <translation id="3900966090527141178">Exportar palavras-passe</translation>
 <translation id="3903187154317825986">Teclado incorporado</translation>
+<translation id="3903191712482985591">Adicione um guia interativo</translation>
 <translation id="3904326018476041253">Serviços de localização</translation>
 <translation id="3904849010307028014">Com base na sua interação com um site, como iniciar sessão regularmente numa conta, esse site pode emitir um símbolo fidedigno para o seu navegador. Posteriormente, se outros sites que visitar verificarem e encontrarem um símbolo fidedigno válido, é mais provável que tratem o utilizador como uma pessoa e não como um bot.</translation>
 <translation id="3905761538810670789">Reparar aplicação</translation>
@@ -3641,6 +3644,7 @@
 <translation id="4510479820467554003">Lista de contas parentais</translation>
 <translation id="451102079304155829">carrinhos</translation>
 <translation id="4513872120116766993">Escrita preditiva</translation>
+<translation id="4513909579793564731">Aplicar guia interativo</translation>
 <translation id="4513946894732546136">Comentários</translation>
 <translation id="451407183922382411">Com tecnologia da <ph name="COMPANY_NAME" /></translation>
 <translation id="4514610446763173167">Ativar/desativar vídeo para reprodução ou pausa.</translation>
@@ -4933,6 +4937,7 @@
 <translation id="5827733057563115968">Previsão da palavra seguinte</translation>
 <translation id="5828545842856466741">Adicionar perfil…</translation>
 <translation id="5828633471261496623">A imprimir...</translation>
+<translation id="5830205393314753525">Não é possível abrir a app <ph name="APP_NAME" /></translation>
 <translation id="5830720307094128296">Guard&amp;ar Página Como...</translation>
 <translation id="5832813618714645810">Perfis</translation>
 <translation id="583281660410589416">Desconhecido</translation>
@@ -5472,6 +5477,7 @@
 <translation id="635609604405270300">Manter o dispositivo ativado</translation>
 <translation id="63566973648609420">Apenas alguém que conheça a sua frase de acesso pode ler os seus dados encriptados. A frase de acesso não é enviada para a Google nem armazenada pela mesma. Se se esquecer da frase de acesso ou pretender alterar esta definição, tem de <ph name="BEGIN_LINK" />repor a sincronização<ph name="END_LINK" />.</translation>
 <translation id="6357305427698525450">Alguns links suportados continuarão a ser abertos na app <ph name="APP_NAME" /> ou <ph name="APP_NAME_2" />.</translation>
+<translation id="6357794994761110294">Nenhuma extensão tem autorização para ler e alterar <ph name="SITE_NAME" /></translation>
 <translation id="6358884629796491903">Dragão</translation>
 <translation id="6361850914223837199">Detalhes do erro:</translation>
 <translation id="6362853299801475928">&amp;Comunicar um problema...</translation>
diff --git a/chrome/app/resources/generated_resources_sk.xtb b/chrome/app/resources/generated_resources_sk.xtb
index 9debb5d2..83485f8 100644
--- a/chrome/app/resources/generated_resources_sk.xtb
+++ b/chrome/app/resources/generated_resources_sk.xtb
@@ -840,6 +840,7 @@
 <translation id="1794051631868188691">Nikdy nezobrazovať predajcu <ph name="MERCHANT" /></translation>
 <translation id="1794791083288629568">Odoslať spätnú väzbu, ktorá nám pomôže pri riešení tohto problému</translation>
 <translation id="1795214765651529549">Použiť klasický</translation>
+<translation id="1796105431091975902">Výber príručky Ansible na pridanie</translation>
 <translation id="1796588414813960292">Funkcie vyžadujúce zvuk nebudú podporované</translation>
 <translation id="1800502858278951817">O čítanie a zmenu webu <ph name="SITE_NAME" /> nepožiadali žiadne rozšírenia</translation>
 <translation id="1802624026913571222">Po zavretí krytu prejsť do režimu spánku</translation>
@@ -3041,6 +3042,7 @@
 <translation id="389901847090970821">Výber klávesnice</translation>
 <translation id="3900966090527141178">Exportovanie hesiel</translation>
 <translation id="3903187154317825986">Vstavaná klávesnica</translation>
+<translation id="3903191712482985591">Pridanie príručky</translation>
 <translation id="3904326018476041253">Služby určovania polohy</translation>
 <translation id="3904849010307028014">Na základe vašej interakcie s určitým webom, ako je pravidelné prihlasovanie sa do účtu, môže daný web vydať vášmu prehliadaču token dôveryhodnosti. Ak neskôr ďalšie weby, ktoré navštívite, skontrolujú a nájdu platný token dôveryhodnosti, budú vás s vyššou pravdepodobnosťou považovať za osobu a nie robota.</translation>
 <translation id="3905761538810670789">Opraviť aplikáciu</translation>
@@ -3651,6 +3653,7 @@
 <translation id="4510479820467554003">Zoznam účtov rodičov</translation>
 <translation id="451102079304155829">košíky</translation>
 <translation id="4513872120116766993">Predvídanie písania</translation>
+<translation id="4513909579793564731">Použiť príručku</translation>
 <translation id="4513946894732546136">Spätná väzba</translation>
 <translation id="451407183922382411">Používa technológiu <ph name="COMPANY_NAME" /></translation>
 <translation id="4514610446763173167">Prepnutím prehráte alebo pozastavíte video</translation>
@@ -5484,6 +5487,7 @@
 <translation id="635609604405270300">Ponechajte zariadenie zapnuté</translation>
 <translation id="63566973648609420">Šifrované údaje môže čítať iba používateľ s prístupovou frázou. Prístupová fráza sa do Googlu neodosiela a Google ju ani neukladá. Ak zabudnete prístupovú frázu alebo budete chcieť zmeniť toto nastavenie zmeniť, musíte <ph name="BEGIN_LINK" />resetovať synchronizáciu<ph name="END_LINK" />.</translation>
 <translation id="6357305427698525450">Niektoré podporované odkazy sa budú stále otvárať v aplikácii <ph name="APP_NAME" /> alebo <ph name="APP_NAME_2" />.</translation>
+<translation id="6357794994761110294">Web <ph name="SITE_NAME" /> nemajú povolené čítať ani meniť žiadne rozšírenia</translation>
 <translation id="6358884629796491903">Drak</translation>
 <translation id="6361850914223837199">Podrobnosti chyby:</translation>
 <translation id="6362853299801475928">Nahlásenie p&amp;roblému...</translation>
diff --git a/chrome/app/resources/generated_resources_sr-Latn.xtb b/chrome/app/resources/generated_resources_sr-Latn.xtb
index cd58a4f..a2f318d 100644
--- a/chrome/app/resources/generated_resources_sr-Latn.xtb
+++ b/chrome/app/resources/generated_resources_sr-Latn.xtb
@@ -1006,6 +1006,7 @@
 <translation id="1944921356641260203">Ažuriranje je pronađeno</translation>
 <translation id="1947136734041527201">Omogućava vam da se prijavljujete na veb-sajtove pomoću naloga koji imate u usluzi za identitet</translation>
 <translation id="1949584741547056205">Brzi odgovori</translation>
+<translation id="1949849604471335579">Personalizujte pozadinu, čuvar ekrana, boje za naglašavanje i drugo</translation>
 <translation id="1951012854035635156">Pomoćnik</translation>
 <translation id="1954597385941141174">Sajtovi mogu da traže da se povezuju sa USB uređajima</translation>
 <translation id="1954813140452229842">Greška pri učitavanju deljene datoteke. Proverite akreditive i probajte ponovo.</translation>
@@ -1037,6 +1038,7 @@
 <translation id="1981434377190976112">da čita sve vaše podatke na svim veb-sajtovima</translation>
 <translation id="1984417487208496350">Bez zaštite (ne preporučuje se)</translation>
 <translation id="1987317783729300807">Nalozi</translation>
+<translation id="1987574314042117472">Izaberi i instaliraj popularne aplikacije</translation>
 <translation id="1988259784461813694">Uslov</translation>
 <translation id="1989112275319619282">Pregledaj</translation>
 <translation id="1989903373608997757">Uvek koristi</translation>
@@ -1102,6 +1104,7 @@
 <translation id="2048554637254265991">Greška pri pokretanju menadžera kontejnera. Probajte ponovo.</translation>
 <translation id="2048653237708779538">Radnja nije dostupna</translation>
 <translation id="2050339315714019657">Vertikalno</translation>
+<translation id="2052572566310583903">Instalirano na drugim uređajima</translation>
 <translation id="2053312383184521053">Podaci o stanju mirovanja</translation>
 <translation id="2054240652864153171">Želite da obrišete podatke o sajtovima za <ph name="SITE_NAME" /> izdeljene na <ph name="PARTITION_SITE_NAME" />?</translation>
 <translation id="2055585478631012616">Odjavićete se sa ovih sajtova, uključujući i one na otvorenim karticama</translation>
@@ -1264,6 +1267,7 @@
 <translation id="2191754378957563929">Uključeno</translation>
 <translation id="2192505247865591433">Od:</translation>
 <translation id="2193365732679659387">Podešavanja pouzdanosti</translation>
+<translation id="2194554416429452547">Tokom probnih perioda, Chrome istražuje načine da ograniči nepoželjan sadržaj, prevaru i deljenje između sajtova. Chrome takođe <ph name="ESTIMATE_INTERESTS_LINK" /> koja sajtovi mogu da koriste da bi vam prikazivali oglase. Možete da upravljate interesovanjima u podešavanjima.</translation>
 <translation id="2194856509914051091">Šta treba imati u vidu</translation>
 <translation id="2195331105963583686">Posle tog perioda i dalje ćete moći da koristite <ph name="DEVICE_TYPE" />, ali uređaj neće više dobijati automatska ažuriranja softvera i bezbednosna ažuriranja</translation>
 <translation id="2195729137168608510">Zaštita e-pošte</translation>
@@ -1868,6 +1872,7 @@
 <translation id="2749836841884031656">SIM</translation>
 <translation id="2749881179542288782">Proveri gramatiku i pravopis</translation>
 <translation id="2753677631968972007">Ručno kontrolišite dozvole za sajtove.</translation>
+<translation id="2754825024506485820">Pronađite potrebne aplikacije, od aplikacija za produktivnost do aplikacija za zabavu, u Google Play prodavnici. Aplikacije možete da instalirate bilo kada.</translation>
 <translation id="2755349111255270002">Resetujte ovaj <ph name="DEVICE_TYPE" /></translation>
 <translation id="2755367719610958252">Upravljaj funkcijama pristupačnosti</translation>
 <translation id="275662540872599901">ekran je isključen</translation>
@@ -1944,6 +1949,7 @@
 <translation id="2815693974042551705">Folder za obeleživače</translation>
 <translation id="2816319641769218778">Da biste sačuvali lozinke na Google nalogu, uključite sinhronizaciju.</translation>
 <translation id="2816628817680324566">Želite da dozvolite ovom sajtu da identifikuje bezbednosni ključ?</translation>
+<translation id="2817435998497102771">Podesi pozadinu i stil</translation>
 <translation id="2818476747334107629">Detalji o štampaču</translation>
 <translation id="2819167288942847344">Koristite unapred određena podešavanja za telefon, tablet ili prozore za koje može da se menja veličina da biste sprečili da aplikacija ne radi pravilno</translation>
 <translation id="2820957248982571256">Skenira se...</translation>
@@ -2837,6 +2843,7 @@
 <translation id="3727144509609414201">Dostupne WiFi mreže</translation>
 <translation id="3727187387656390258">Ispitaj iskačući prozor</translation>
 <translation id="372722114124766626">Samo jednom</translation>
+<translation id="3727332897090187514">Nijedna napomena nije dodata</translation>
 <translation id="3727473233247516571">Ceo keširani podokvir: <ph name="BACK_FORWARD_CACHE_PAGE_URL" /></translation>
 <translation id="3728188878314831180">da preslika obaveštenja sa vašeg telefona</translation>
 <translation id="3728681439294129328">Konfiguriši mrežnu adresu</translation>
@@ -3173,6 +3180,7 @@
 <translation id="4031527940632463547">Pristup senzorima je blokiran</translation>
 <translation id="4033415645631238123">Prijavljivanje pomoću Smart Lock-a više nije dostupno. I dalje možete da otključavate pomoću Smart Lock-a.</translation>
 <translation id="4033471457476425443">Dodaj novi direktorijum</translation>
+<translation id="4033711848170683365">To će trajno izbrisati podatke pregledanja sa ovog uređaja. Google naloge na ovom profilu možda koriste druge aplikacije na uređaju <ph name="DEVICE_TYPE" />. Možete da uklonite te naloge u odeljku <ph name="BEGIN_LINK" /><ph name="SETTING_SECTION" /> &gt; <ph name="ACCOUNTS_SECTION" /><ph name="END_LINK" />.</translation>
 <translation id="4033963223187371752">Bezbedni sajtovi mogu da ugrade sadržaj, poput slika ili veb-okvira koji nisu bezbedni</translation>
 <translation id="4034824040120875894">Štampač</translation>
 <translation id="4035758313003622889">&amp;Menadžer zadataka</translation>
@@ -3451,6 +3459,7 @@
 <translation id="4314815835985389558">Upravljajte sinhronizacijom</translation>
 <translation id="4315933848520197627">Opozovi vezu sa nalogom</translation>
 <translation id="4316850752623536204">Veb-sajt programera</translation>
+<translation id="4317733381297736564">Kupovine u aplikaciji</translation>
 <translation id="4317820549299924617">Verifikacija nije uspela</translation>
 <translation id="4320177379694898372">Nema internet veze</translation>
 <translation id="4322394346347055525">Zatvori druge kartice</translation>
@@ -4034,6 +4043,7 @@
 <translation id="4893522937062257019">Na zaključanom ekranu</translation>
 <translation id="4897496410259333978">Dodatne informacije potražite od administratora.</translation>
 <translation id="4898011734382862273">Sertifikat „<ph name="CERTIFICATE_NAME" />“ predstavlja autoritet za izdavanje sertifikata</translation>
+<translation id="4899696330053002588">Sadrži oglase</translation>
 <translation id="489985760463306091">Da biste dovršili uklanjanje štetnog softvera, ponovo pokrenite računar</translation>
 <translation id="4900392736118574277">Polazna stranica je promenjena u <ph name="URL" />.</translation>
 <translation id="490051679772058907"><ph name="REFRESH_RATE" /> Hz – prepleteno</translation>
@@ -4407,6 +4417,7 @@
 <translation id="52912272896845572">Datoteka privatnog ključa je nevažeća.</translation>
 <translation id="5291739252352359682">Automatski pravi titl za medije u Chrome pregledaču (trenutno je dostupno na engleskom). Sve audio datoteke i titlovi se obrađuju lokalno i ostaju samo na uređaju.</translation>
 <translation id="529175790091471945">Formatiraj ovaj uređaj</translation>
+<translation id="5292862864186939732">Uvek ćete dozvoljavati da se dodatak<ph name="EXTENSION_NAME" /> pokreće na <ph name="ORIGIN" />?</translation>
 <translation id="529296195492126134">Jednokratni režim nije podržan. Obratite se administratoru</translation>
 <translation id="5293170712604732402">Vratite podešavanja na prvobitne podrazumevane vrednosti</translation>
 <translation id="5294097441441645251">Mora da počinje malim slovom ili donjom crtom</translation>
@@ -5164,6 +5175,7 @@
 <translation id="6054961935262556546">Promeni vidljivost</translation>
 <translation id="6055171183283175969">Lozinka koju ste uneli je netačna.</translation>
 <translation id="6055392876709372977">PKCS #1 SHA-256 sa RSA šifrovanjem</translation>
+<translation id="6055544610007596637">Instalirajte aplikacije za <ph name="DEVICE_TYPE" /> iz Google Play prodavnice</translation>
 <translation id="6056710589053485679">Ponovo učitaj normalno</translation>
 <translation id="6057312498756061228">Ova datoteka je prevelika za bezbednosnu proveru. Možete da otvorite datoteke veličine do 50 MB.</translation>
 <translation id="6057381398996433816">Ovom sajtu je zabranjeno da koristi senzore za pokret i svetlo.</translation>
@@ -6141,6 +6153,7 @@
 <translation id="7002055706763150362">Da biste podesili Smart Lock za Chromebook, Google mora da proveri da li ste to vi – unesite lozinku da biste počeli.</translation>
 <translation id="7003339318920871147">Veb baze podataka</translation>
 <translation id="7003454175711353260">{COUNT,plural, =1{{COUNT} fajl}one{{COUNT} fajl}few{{COUNT} fajla}other{{COUNT} fajlova}}</translation>
+<translation id="7003705861991657723">Alfa</translation>
 <translation id="7003723821785740825">Podesite brži način otključavanja uređaja</translation>
 <translation id="7003844668372540529">Nepoznati proizvod <ph name="PRODUCT_ID" /> prodavca <ph name="VENDOR_NAME" /></translation>
 <translation id="7004402701596653846">Sajt može da koristi MIDI</translation>
@@ -6157,6 +6170,7 @@
 <translation id="7008815993384338777">Trenutno nije u romingu</translation>
 <translation id="7009709314043432820"><ph name="APP_NAME" /> koristi kameru</translation>
 <translation id="701080569351381435">Prikaži izvor</translation>
+<translation id="7011797924920577670">procenjuje vaša interesovanja</translation>
 <translation id="7014174261166285193">Instalacija nije uspela.</translation>
 <translation id="7014480873681694324">Ukloni isticanje</translation>
 <translation id="7017004637493394352">Kažite ponovo „Ok Google“</translation>
@@ -6224,6 +6238,7 @@
 <translation id="7082568314107259011">Administrator upravlja mrežom <ph name="NETWORK_NAME" /></translation>
 <translation id="7085389578340536476">Želite li da dozvolite Chrome-u da snima zvuk?</translation>
 <translation id="708550780726587276">(nije konfigurisano)</translation>
+<translation id="7086531709814430567">Uvek ćete dozvoljavati ovim podacima da se pokreću na <ph name="ORIGIN" />?</translation>
 <translation id="7086672505018440886">Uvrsti Chrome datoteke evidencije u arhivu.</translation>
 <translation id="7088434364990739311">Pokretanje provere ažuriranja nije uspelo (kôd greške <ph name="ERROR" />).</translation>
 <translation id="7088674813905715446">Administrator je uklonio ovaj uređaj. Da biste ga omogućili za registraciju, zatražite od administratora da promeni njegov status u „Na čekanju“.</translation>
@@ -8358,6 +8373,7 @@
 <translation id="9215742531438648683">Deinstalirajte Google Play prodavnicu</translation>
 <translation id="9218430445555521422">Podesi kao podrazumevan</translation>
 <translation id="9218842937876577955"><ph name="APP_NAME" /> (aplikacija nije podržana)</translation>
+<translation id="9219582468404818260">Pomozite nam da napravimo bolji veb</translation>
 <translation id="9220525904950070496">Uklanjanje naloga</translation>
 <translation id="9220820413868316583">Podignite, pa probajte ponovo.</translation>
 <translation id="923467487918828349">Prikaži sve</translation>
diff --git a/chrome/app/resources/generated_resources_sr.xtb b/chrome/app/resources/generated_resources_sr.xtb
index 87f61f7..2d37f36 100644
--- a/chrome/app/resources/generated_resources_sr.xtb
+++ b/chrome/app/resources/generated_resources_sr.xtb
@@ -1006,6 +1006,7 @@
 <translation id="1944921356641260203">Ажурирање је пронађено</translation>
 <translation id="1947136734041527201">Омогућава вам да се пријављујете на веб-сајтове помоћу налога који имате у услузи за идентитет</translation>
 <translation id="1949584741547056205">Брзи одговори</translation>
+<translation id="1949849604471335579">Персонализујте позадину, чувар екрана, боје за наглашавање и друго</translation>
 <translation id="1951012854035635156">Помоћник</translation>
 <translation id="1954597385941141174">Сајтови могу да траже да се повезују са USB уређајима</translation>
 <translation id="1954813140452229842">Грешка при учитавању дељене датотеке. Проверите акредитиве и пробајте поново.</translation>
@@ -1037,6 +1038,7 @@
 <translation id="1981434377190976112">да чита све ваше податке на свим веб-сајтовима</translation>
 <translation id="1984417487208496350">Без заштите (не препоручује се)</translation>
 <translation id="1987317783729300807">Налози</translation>
+<translation id="1987574314042117472">Изабери и инсталирај популарне апликације</translation>
 <translation id="1988259784461813694">Услов</translation>
 <translation id="1989112275319619282">Прегледај</translation>
 <translation id="1989903373608997757">Увек користи</translation>
@@ -1102,6 +1104,7 @@
 <translation id="2048554637254265991">Грешка при покретању менаџера контејнера. Пробајте поново.</translation>
 <translation id="2048653237708779538">Радња није доступна</translation>
 <translation id="2050339315714019657">Вертикално</translation>
+<translation id="2052572566310583903">Инсталирано на другим уређајима</translation>
 <translation id="2053312383184521053">Подаци о стању мировања</translation>
 <translation id="2054240652864153171">Желите да обришете податке о сајтовима за <ph name="SITE_NAME" /> издељене на <ph name="PARTITION_SITE_NAME" />?</translation>
 <translation id="2055585478631012616">Одјавићете се са ових сајтова, укључујући и оне на отвореним картицама</translation>
@@ -1264,6 +1267,7 @@
 <translation id="2191754378957563929">Укључено</translation>
 <translation id="2192505247865591433">Од:</translation>
 <translation id="2193365732679659387">Подешавања поузданости</translation>
+<translation id="2194554416429452547">Током пробних периода, Chrome истражује начине да ограничи непожељан садржај, превару и дељење између сајтова. Chrome такође <ph name="ESTIMATE_INTERESTS_LINK" /> која сајтови могу да користе да би вам приказивали огласе. Можете да управљате интересовањима у подешавањима.</translation>
 <translation id="2194856509914051091">Шта треба имати у виду</translation>
 <translation id="2195331105963583686">После тог периода и даље ћете моћи да користите <ph name="DEVICE_TYPE" />, али уређај неће више добијати аутоматска ажурирања софтвера и безбедносна ажурирања</translation>
 <translation id="2195729137168608510">Заштита е-поште</translation>
@@ -1868,6 +1872,7 @@
 <translation id="2749836841884031656">SIM</translation>
 <translation id="2749881179542288782">Провери граматику и правопис</translation>
 <translation id="2753677631968972007">Ручно контролишите дозволе за сајтове.</translation>
+<translation id="2754825024506485820">Пронађите потребне апликације, од апликација за продуктивност до апликација за забаву, у Google Play продавници. Апликације можете да инсталирате било када.</translation>
 <translation id="2755349111255270002">Ресетујте овај <ph name="DEVICE_TYPE" /></translation>
 <translation id="2755367719610958252">Управљај функцијама приступачности</translation>
 <translation id="275662540872599901">екран је искључен</translation>
@@ -1944,6 +1949,7 @@
 <translation id="2815693974042551705">Фолдер за обележиваче</translation>
 <translation id="2816319641769218778">Да бисте сачували лозинке на Google налогу, укључите синхронизацију.</translation>
 <translation id="2816628817680324566">Желите да дозволите овом сајту да идентификује безбедносни кључ?</translation>
+<translation id="2817435998497102771">Подеси позадину и стил</translation>
 <translation id="2818476747334107629">Детаљи о штампачу</translation>
 <translation id="2819167288942847344">Користите унапред одређена подешавања за телефон, таблет или прозоре за које може да се мења величина да бисте спречили да апликација не ради правилно</translation>
 <translation id="2820957248982571256">Скенира се...</translation>
@@ -2837,6 +2843,7 @@
 <translation id="3727144509609414201">Доступне WiFi мреже</translation>
 <translation id="3727187387656390258">Испитај искачући прозор</translation>
 <translation id="372722114124766626">Само једном</translation>
+<translation id="3727332897090187514">Ниједна напомена није додата</translation>
 <translation id="3727473233247516571">Цео кеширани подоквир: <ph name="BACK_FORWARD_CACHE_PAGE_URL" /></translation>
 <translation id="3728188878314831180">да преслика обавештења са вашег телефона</translation>
 <translation id="3728681439294129328">Конфигуриши мрежну адресу</translation>
@@ -3173,6 +3180,7 @@
 <translation id="4031527940632463547">Приступ сензорима је блокиран</translation>
 <translation id="4033415645631238123">Пријављивање помоћу Smart Lock-а више није доступно. И даље можете да откључавате помоћу Smart Lock-а.</translation>
 <translation id="4033471457476425443">Додај нови директоријум</translation>
+<translation id="4033711848170683365">То ће трајно избрисати податке прегледања са овог уређаја. Google налоге на овом профилу можда користе друге апликације на уређају <ph name="DEVICE_TYPE" />. Можете да уклоните те налоге у одељку <ph name="BEGIN_LINK" /><ph name="SETTING_SECTION" /> &gt; <ph name="ACCOUNTS_SECTION" /><ph name="END_LINK" />.</translation>
 <translation id="4033963223187371752">Безбедни сајтови могу да уграде садржај, попут слика или веб-оквира који нису безбедни</translation>
 <translation id="4034824040120875894">Штампач</translation>
 <translation id="4035758313003622889">&amp;Менаџер задатака</translation>
@@ -3451,6 +3459,7 @@
 <translation id="4314815835985389558">Управљајте синхронизацијом</translation>
 <translation id="4315933848520197627">Опозови везу са налогом</translation>
 <translation id="4316850752623536204">Веб-сајт програмера</translation>
+<translation id="4317733381297736564">Куповине у апликацији</translation>
 <translation id="4317820549299924617">Верификација није успела</translation>
 <translation id="4320177379694898372">Нема интернет везе</translation>
 <translation id="4322394346347055525">Затвори друге картице</translation>
@@ -4034,6 +4043,7 @@
 <translation id="4893522937062257019">На закључаном екрану</translation>
 <translation id="4897496410259333978">Додатне информације потражите од администратора.</translation>
 <translation id="4898011734382862273">Сертификат „<ph name="CERTIFICATE_NAME" />“ представља ауторитет за издавање сертификата</translation>
+<translation id="4899696330053002588">Садржи огласе</translation>
 <translation id="489985760463306091">Да бисте довршили уклањање штетног софтвера, поново покрените рачунар</translation>
 <translation id="4900392736118574277">Полазна страница је промењена у <ph name="URL" />.</translation>
 <translation id="490051679772058907"><ph name="REFRESH_RATE" /> Hz – преплетено</translation>
@@ -4407,6 +4417,7 @@
 <translation id="52912272896845572">Датотека приватног кључа је неважећа.</translation>
 <translation id="5291739252352359682">Аутоматски прави титл за медије у Chrome прегледачу (тренутно је доступно на енглеском). Све аудио датотеке и титлови се обрађују локално и остају само на уређају.</translation>
 <translation id="529175790091471945">Форматирај овај уређај</translation>
+<translation id="5292862864186939732">Увек ћете дозвољавати да се додатак<ph name="EXTENSION_NAME" /> покреће на <ph name="ORIGIN" />?</translation>
 <translation id="529296195492126134">Једнократни режим није подржан. Обратите се администратору</translation>
 <translation id="5293170712604732402">Вратите подешавања на првобитне подразумеване вредности</translation>
 <translation id="5294097441441645251">Мора да почиње малим словом или доњом цртом</translation>
@@ -5164,6 +5175,7 @@
 <translation id="6054961935262556546">Промени видљивост</translation>
 <translation id="6055171183283175969">Лозинка коју сте унели је нетачна.</translation>
 <translation id="6055392876709372977">PKCS #1 SHA-256 са RSA шифровањем</translation>
+<translation id="6055544610007596637">Инсталирајте апликације за <ph name="DEVICE_TYPE" /> из Google Play продавнице</translation>
 <translation id="6056710589053485679">Поново учитај нормално</translation>
 <translation id="6057312498756061228">Ова датотека је превелика за безбедносну проверу. Можете да отворите датотеке величине до 50 MB.</translation>
 <translation id="6057381398996433816">Овом сајту је забрањено да користи сензоре за покрет и светло.</translation>
@@ -6141,6 +6153,7 @@
 <translation id="7002055706763150362">Да бисте подесили Smart Lock за Chromebook, Google мора да провери да ли сте то ви – унесите лозинку да бисте почели.</translation>
 <translation id="7003339318920871147">Веб базе података</translation>
 <translation id="7003454175711353260">{COUNT,plural, =1{{COUNT} фајл}one{{COUNT} фајл}few{{COUNT} фајла}other{{COUNT} фајлова}}</translation>
+<translation id="7003705861991657723">Алфа</translation>
 <translation id="7003723821785740825">Подесите бржи начин откључавања уређаја</translation>
 <translation id="7003844668372540529">Непознати производ <ph name="PRODUCT_ID" /> продавца <ph name="VENDOR_NAME" /></translation>
 <translation id="7004402701596653846">Сајт може да користи MIDI</translation>
@@ -6157,6 +6170,7 @@
 <translation id="7008815993384338777">Тренутно није у ромингу</translation>
 <translation id="7009709314043432820"><ph name="APP_NAME" /> користи камеру</translation>
 <translation id="701080569351381435">Прикажи извор</translation>
+<translation id="7011797924920577670">процењује ваша интересовања</translation>
 <translation id="7014174261166285193">Инсталација није успела.</translation>
 <translation id="7014480873681694324">Уклони истицање</translation>
 <translation id="7017004637493394352">Кажите поново „Ок Google“</translation>
@@ -6224,6 +6238,7 @@
 <translation id="7082568314107259011">Администратор управља мрежом <ph name="NETWORK_NAME" /></translation>
 <translation id="7085389578340536476">Желите ли да дозволите Chrome-у да снима звук?</translation>
 <translation id="708550780726587276">(није конфигурисано)</translation>
+<translation id="7086531709814430567">Увек ћете дозвољавати овим подацима да се покрећу на <ph name="ORIGIN" />?</translation>
 <translation id="7086672505018440886">Уврсти Chrome датотеке евиденције у архиву.</translation>
 <translation id="7088434364990739311">Покретање провере ажурирања није успело (кôд грешке <ph name="ERROR" />).</translation>
 <translation id="7088674813905715446">Администратор је уклонио овај уређај. Да бисте га омогућили за регистрацију, затражите од администратора да промени његов статус у „На чекању“.</translation>
@@ -8358,6 +8373,7 @@
 <translation id="9215742531438648683">Деинсталирајте Google Play продавницу</translation>
 <translation id="9218430445555521422">Подеси као подразумеван</translation>
 <translation id="9218842937876577955"><ph name="APP_NAME" /> (апликација није подржана)</translation>
+<translation id="9219582468404818260">Помозите нам да направимо бољи веб</translation>
 <translation id="9220525904950070496">Уклањање налога</translation>
 <translation id="9220820413868316583">Подигните, па пробајте поново.</translation>
 <translation id="923467487918828349">Прикажи све</translation>
diff --git a/chrome/app/resources/generated_resources_te.xtb b/chrome/app/resources/generated_resources_te.xtb
index 16e2b78..8b0d07d 100644
--- a/chrome/app/resources/generated_resources_te.xtb
+++ b/chrome/app/resources/generated_resources_te.xtb
@@ -848,6 +848,7 @@
 <translation id="1794051631868188691"><ph name="MERCHANT" />ను ఎప్పుడూ చూపవద్దు</translation>
 <translation id="1794791083288629568">ఈ సమస్యను పరిష్కరించడంలో మాకు సహాయం చేయడానికి అభిప్రాయాన్ని పంపుతుంది.</translation>
 <translation id="1795214765651529549">క్లాసిక్‌ను ఉపయోగించు</translation>
+<translation id="1796105431091975902">జోడించడానికి Ansible గైడ్‌లైన్ కిట్‌ని ఎంచుకోండి</translation>
 <translation id="1796588414813960292">సౌండ్ అవసరం అయ్యే ఫీచర్‌లు పని చేయవు</translation>
 <translation id="1800502858278951817"><ph name="SITE_NAME" />ను చదవడానికి, మార్చడానికి ఎక్స్‌టెన్షన్‌లు ఏవీ రిక్వెస్ట్ చేయలేదు</translation>
 <translation id="1802624026913571222">కవర్ మూసి ఉన్నప్పుడు స్లీప్ స్థితికి వెళ్లు</translation>
@@ -3046,6 +3047,7 @@
 <translation id="389901847090970821">కీబోర్డ్‌ను ఎంచుకోండి</translation>
 <translation id="3900966090527141178">పాస్‌వర్డ్‌లను ఎగుమతి చేయండి</translation>
 <translation id="3903187154317825986">బిల్ట్-ఇన్ కీబోర్డ్</translation>
+<translation id="3903191712482985591">గైడ్‌లైన్ కిట్‌ను జోడించండి</translation>
 <translation id="3904326018476041253">లొకేషన్ సర్వీస్‌లు</translation>
 <translation id="3904849010307028014">తరచుగా మీరు ఖాతాకు సైన్ ఇన్ చేయడం వంటి సైట్‌తో మీ ఇంటరాక్షన్ ఆధారంగా, ఆ సైట్ మీ బ్రౌజర్‌కు విశ్వసనీయ టోకెన్‌ను జారీ చేయవచ్చు. తర్వాత, మీరు సందర్శించే ఇతర సైట్‌లు చెక్ చేసి, చెల్లుబాటయ్యే విశ్వసనీయ టోకెన్‌ను కనుగొంటే, వారు మిమ్మల్ని బాట్‌గా కాకుండా ఒక వ్యక్తిగా పరిగణించే అవకాశం ఎక్కువగా ఉంటుంది.</translation>
 <translation id="3905761538810670789">యాప్‌ను సరి చేయి</translation>
@@ -3655,6 +3657,7 @@
 <translation id="4510479820467554003">తల్లి/తండ్రి ఖాతా లిస్ట్‌</translation>
 <translation id="451102079304155829">కార్ట్‌లు</translation>
 <translation id="4513872120116766993">సూచనాత్మక వ్రాత</translation>
+<translation id="4513909579793564731">గైడ్‌లైన్ కిట్‌ని వర్తింపజేయండి</translation>
 <translation id="4513946894732546136">ఫీడ్‌బ్యాక్</translation>
 <translation id="451407183922382411"><ph name="COMPANY_NAME" /> అందిస్తోంది</translation>
 <translation id="4514610446763173167">ప్లే లేదా పాజ్ చేయడానికి వీడియోని టోగుల్ చేయండి</translation>
@@ -5485,6 +5488,7 @@
 <translation id="635609604405270300">పరికరాన్ని ఆన్ చేసి ఉంచండి</translation>
 <translation id="63566973648609420">మీ రహస్య పదబంధాన్ని కలిగి ఉన్న వారు మాత్రమే మీ ఎన్‌క్రిప్ట్ చేసిన‌ డేటాను చదవగలరు. రహస్య పదబంధం ఎవరికీ పంపబడదు లేదా Googleలో నిల్వ చేయబడదు. మీరు మీ రహస్య పదబంధాన్ని మర్చిపోతే లేదా ఈ సెట్టింగ్‌ను మార్చాలనుకుంటే, సింక్‌ను రీసెట్ చేయాల్సి ఉంటుంది. <ph name="BEGIN_LINK" />సింక్‌ను రీసెట్ చేయండి<ph name="END_LINK" />.</translation>
 <translation id="6357305427698525450">కొన్ని సపోర్ట్ లింక్‌లు ఇప్పటికీ <ph name="APP_NAME" /> లేదా  <ph name="APP_NAME_2" />లో తెరవబడతాయి.</translation>
+<translation id="6357794994761110294"><ph name="SITE_NAME" />ను చదవడానికి, మార్చడానికి ఎక్స్‌టెన్షన్‌లు ఏవీ అనుమతించబడవు</translation>
 <translation id="6358884629796491903">డ్రాగన్</translation>
 <translation id="6361850914223837199">ఎర్రర్ వివరాలు:</translation>
 <translation id="6362853299801475928">&amp;ఒక సమస్యను రిపోర్ట్ చేయండి...</translation>
diff --git a/chrome/app/resources/generated_resources_ur.xtb b/chrome/app/resources/generated_resources_ur.xtb
index 6d2817f..8df33bcd 100644
--- a/chrome/app/resources/generated_resources_ur.xtb
+++ b/chrome/app/resources/generated_resources_ur.xtb
@@ -1006,6 +1006,7 @@
 <translation id="1944921356641260203">اپ ڈیٹ ملا</translation>
 <translation id="1947136734041527201">آپ کو اس اکاؤنٹ کا استعمال کرتے ہوئے ویب سائٹس میں سائن ان کرنے دیتا ہے جن کی شناختی سروس آپ کے پاس ہے</translation>
 <translation id="1949584741547056205">فوری جوابات</translation>
+<translation id="1949849604471335579">وال پیپر، اسکرین سیور، ایکسینٹ کے رنگ اور مزید کو ذاتی نوعیت کا بنائیں</translation>
 <translation id="1951012854035635156">اسسٹنٹ</translation>
 <translation id="1954597385941141174">‏سائٹس USB آلات سے منسلک ہونے کے لیے پوچھ سکتی ہیں</translation>
 <translation id="1954813140452229842">اشتراک کو ماؤنٹ کرنے میں خرابی آگئی ۔ براہ کرم اپنے اسنادات چیک کریں اور دوبارہ کوشش کریں۔</translation>
@@ -1037,6 +1038,7 @@
 <translation id="1981434377190976112">سبھی ویب سائٹس پر اپنا سبھی ڈیٹا پڑھیں</translation>
 <translation id="1984417487208496350">کوئی تحفظ نہیں (تجویز نہیں کی جاتی ہے)</translation>
 <translation id="1987317783729300807">اکاؤنٹس</translation>
+<translation id="1987574314042117472">مقبول ایپس منتخب کریں اور انسٹال کریں</translation>
 <translation id="1988259784461813694">درکار</translation>
 <translation id="1989112275319619282">براؤز کریں</translation>
 <translation id="1989903373608997757">ہمیشہ استعمال کریں</translation>
@@ -1102,6 +1104,7 @@
 <translation id="2048554637254265991">کنٹینر مینیجر کو شروع کرنے میں خرابی۔ دوبارہ کوشش کریں۔</translation>
 <translation id="2048653237708779538">کارروائی دستیاب نہیں ہے</translation>
 <translation id="2050339315714019657">پورٹریٹ</translation>
+<translation id="2052572566310583903">آپ کے دیگر آلات پر انسٹال کردہ</translation>
 <translation id="2053312383184521053">معطل صورتحال کا ڈیٹا</translation>
 <translation id="2054240652864153171"><ph name="PARTITION_SITE_NAME" /> پر تقسیم کردہ <ph name="SITE_NAME" /> کے لیے سائٹ ڈیٹا کو صاف کریں؟</translation>
 <translation id="2055585478631012616">اوپن ٹیبز سمیت، آپ ان سائٹس سے سائن آؤٹ ہو جائیں گے</translation>
@@ -1265,6 +1268,7 @@
 <translation id="2191754378957563929">آن</translation>
 <translation id="2192505247865591433">منجانب:</translation>
 <translation id="2193365732679659387">ٹرسٹ کی ترتیبات</translation>
+<translation id="2194554416429452547">‏ٹرائلز کے دوران، Chrome سپام، دھوکہ اور سائٹس کے درمیان اشتراک کو محدود کرنے کے طریقے دریافت کر رہا ہے۔ Chrome <ph name="ESTIMATE_INTERESTS_LINK" /> کرتا ہے جو سائٹس آپ کو اشتہارات دکھانے کے لیے استعمال کر سکتی ہیں۔ آپ ترتیبات میں اپنی دلچسپیوں کا نظم کر سکتے ہیں۔</translation>
 <translation id="2194856509914051091">قابل غور چیزیں</translation>
 <translation id="2195331105963583686">اس وقت کے بعد، آپ اب بھی اس <ph name="DEVICE_TYPE" /> کا استعمال کر سکیں گے، لیکن اب اسے خودکار سافٹ ویئر اور سیکیورٹی اپ ڈیٹس حاصل نہیں ہوں گی</translation>
 <translation id="2195729137168608510">ای میل کا تحفظ</translation>
@@ -1869,6 +1873,7 @@
 <translation id="2749836841884031656">SIM</translation>
 <translation id="2749881179542288782">ہجے کے ساتھ گرامر چیک کریں</translation>
 <translation id="2753677631968972007">دستی طور پر سائٹ کی اجازتوں کو کنٹرول کریں۔</translation>
+<translation id="2754825024506485820">‏Google Play اسٹور پر پروڈکٹیوٹی سے لے کر تفریح تک اپنی ضرورت کی ایپس تلاش کریں۔ آپ کسی بھی وقت ایپس انسٹال کر سکتے ہیں۔</translation>
 <translation id="2755349111255270002">اس <ph name="DEVICE_TYPE" /> کو ری سیٹ کریں</translation>
 <translation id="2755367719610958252">ایکسیسبیلٹی کی خصوصیات کا نظم کریں</translation>
 <translation id="275662540872599901">اسکرین آف ہے</translation>
@@ -1945,6 +1950,7 @@
 <translation id="2815693974042551705">بُک مارک فولڈر</translation>
 <translation id="2816319641769218778">‏اپنے Google اکاؤنٹ میں پاس ورڈز محفوظ کرنے کیلئے، مطابقت پذیری آن کریں۔</translation>
 <translation id="2816628817680324566">اس سائٹ کو آپ کی سیکیورٹی کلید شناخت کرنے کی اجازت دیں؟</translation>
+<translation id="2817435998497102771">اپنا وال پیپر اور اسٹائل سیٹ کریں</translation>
 <translation id="2818476747334107629">پرنٹر کی تفصیلات</translation>
 <translation id="2819167288942847344">ایپ کو غلط طریقے سے کام کرنے سے روکنے کیلئے فون، ٹیبلیٹ یا سائز تبدیل کرنے والی ونڈوز کیلئے پہلے سے ترتیب شدہ سائز استعمال کریں</translation>
 <translation id="2820957248982571256">اسکین ہو رہا ہے…</translation>
@@ -2838,6 +2844,7 @@
 <translation id="3727144509609414201">‏دستیاب WiFi نیٹ ورکس</translation>
 <translation id="3727187387656390258">پاپ اپ کا معائنہ کریں</translation>
 <translation id="372722114124766626">بس ایک بار</translation>
+<translation id="3727332897090187514">کوئی نوٹ شامل نہیں کیا گیا</translation>
 <translation id="3727473233247516571">بیک/فارورڈ کیش کردہ کا سب فریم: <ph name="BACK_FORWARD_CACHE_PAGE_URL" /></translation>
 <translation id="3728188878314831180">آپ کے فون سے مرر کی اطلاعات</translation>
 <translation id="3728681439294129328">نیٹ ورک پتہ کنفیگر کریں</translation>
@@ -3173,6 +3180,7 @@
 <translation id="4031527940632463547">سینسرز مسدود ہیں</translation>
 <translation id="4033415645631238123">‏Smart Lock سے سائن ان کرنا اب دستیاب نہیں ہے۔ آپ اب بھی Smart Lock سے غیر مقفل کر سکتے ہیں۔</translation>
 <translation id="4033471457476425443">نیا فولڈر شامل کریں</translation>
+<translation id="4033711848170683365">‏یہ اس آلے سے براؤزنگ ڈیٹا کو مستقل طور پر حذف کر دے گا۔ اس پروفائل میں موجود Google اکاؤنٹس کا استعمال آپ کے <ph name="DEVICE_TYPE" /> پر دیگر ایپس کے ذریعے کیا جا سکتا ہے۔ آپ <ph name="BEGIN_LINK" /><ph name="SETTING_SECTION" /> &gt; <ph name="ACCOUNTS_SECTION" /><ph name="END_LINK" /> میں ان اکاؤنٹس کو ہٹا سکتے ہیں۔</translation>
 <translation id="4033963223187371752">محفوظ سائٹس غیر محفوظ تصاویر یا ویب فریمز جیسے مواد سرایت کر سکتی ہیں</translation>
 <translation id="4034824040120875894">پرنٹر</translation>
 <translation id="4035758313003622889">&amp;ٹاسک مینیجر</translation>
@@ -3451,6 +3459,7 @@
 <translation id="4314815835985389558">مطابقت پذیری کا نظم کريں</translation>
 <translation id="4315933848520197627">اکاؤنٹ کا لنک ختم کریں</translation>
 <translation id="4316850752623536204">ڈویلپر کی ویب سائٹ</translation>
+<translation id="4317733381297736564">درون ایپ خریداریاں</translation>
 <translation id="4317820549299924617">توثیق کامیاب نہیں ہوئی</translation>
 <translation id="4320177379694898372">کوئی انٹرنیٹ کنکشن نہیں ہے</translation>
 <translation id="4322394346347055525">دیگر ٹیبز بند کریں</translation>
@@ -4033,6 +4042,7 @@
 <translation id="4893522937062257019">مقفل اسکرین پر</translation>
 <translation id="4897496410259333978">مزید معلومات کیلئے اپنے منتظم سے رابطہ کریں۔</translation>
 <translation id="4898011734382862273">سرٹیفیکیٹ "<ph name="CERTIFICATE_NAME" />" ایک سرٹیفیکیشن ادارہ کی نمائندگی کرتی ہے</translation>
+<translation id="4899696330053002588">اشتہارات پر مشتمل ہے</translation>
 <translation id="489985760463306091">نقصان دہ سافٹ ویئر کو ہٹانا ختم کرنے کیلئے، اپنے کمپیوٹر کو ری سٹارٹ کریں</translation>
 <translation id="4900392736118574277">آپ کا ابتدائی صفحہ <ph name="URL" /> پر تبدیل کر دیا گیا۔</translation>
 <translation id="490051679772058907">‏<ph name="REFRESH_RATE" /> Hz - انٹرلیسڈ</translation>
@@ -4406,6 +4416,7 @@
 <translation id="52912272896845572">نجی کلید کی فائل غلط ہے۔</translation>
 <translation id="5291739252352359682">‏یہ خصوصیت Chrome براؤزر میں میڈیا کیلئے خودکار طور پر کیپشنز تخلیق کرتی ہے (فی الحال انگریزی میں دستیاب ہے)۔ آڈیو اور کیپشنز پر مقامی طور پر کارروائی کی جاتی ہے اور یہ ہمیشہ آلے پر ہی رہتے ہیں۔</translation>
 <translation id="529175790091471945">اس آلہ کو فارمیٹ کریں</translation>
+<translation id="5292862864186939732">"<ph name="EXTENSION_NAME" />" کو ہمیشہ <ph name="ORIGIN" /> پر چلنے کی اجازت دیں؟</translation>
 <translation id="529296195492126134">عارضی موڈ سیٹ نہیں ہے۔ براہ کرم اپنے منتظم سے رابطہ کریں</translation>
 <translation id="5293170712604732402">ترتیبات کو ان کی اصل ڈیفالٹس میں بحال کریں</translation>
 <translation id="5294097441441645251">چھوٹے حرف یا انڈر سکور کے ساتھ شروع کرنا ضروری ہے</translation>
@@ -5162,6 +5173,7 @@
 <translation id="6054961935262556546">نظر آنے کو تبدیل کریں</translation>
 <translation id="6055171183283175969">آپ کا درج کردہ پاس ورڈ غلط ہے۔</translation>
 <translation id="6055392876709372977">‏PKCS #1 SHA-256 مع RSA مرموز کاری</translation>
+<translation id="6055544610007596637">‏Google Play اسٹور سے اپنے <ph name="DEVICE_TYPE" /> کے لیے ایپس انسٹال کریں</translation>
 <translation id="6056710589053485679">عام ری لوڈ</translation>
 <translation id="6057312498756061228">‏یہ فائل سیکیورٹی چیک کے لئے بہت بڑی ہے۔ آپ ‎50 MB تک کی فائلز کھول سکتے ہیں۔</translation>
 <translation id="6057381398996433816">اس سائٹ کو موشن اور لائٹ سینسرز استعمال کرنے سے مسدود کر دیا گيا ہے۔</translation>
@@ -6134,6 +6146,7 @@
 <translation id="7002055706763150362">‏Chromebook کیلئے Smart Lock ترتیب دینے کیلئے، Google اس بات کو یقینی بنانا چاہتا ہے کہ یہ آپ ہی ہیں—شروع کرنے کیلئے اپنا پاس ورڈ ٹائپ کریں۔</translation>
 <translation id="7003339318920871147">ویب ڈیٹا بیسز</translation>
 <translation id="7003454175711353260">{COUNT,plural, =1{{COUNT} فائل}other{{COUNT} فائلز}}</translation>
+<translation id="7003705861991657723">الفا</translation>
 <translation id="7003723821785740825">اپنا آلہ غیر مقفل کرنے کا ایک تیز تر طریقہ ترتیب دیں</translation>
 <translation id="7003844668372540529"><ph name="VENDOR_NAME" /> کی جانب سے نامعلوم پروڈکٹ <ph name="PRODUCT_ID" /></translation>
 <translation id="7004402701596653846">‏سائٹ MIDI استعمال کر سکتی ہے</translation>
@@ -6150,6 +6163,7 @@
 <translation id="7008815993384338777">فی الحال رومنگ میں نہیں ہے</translation>
 <translation id="7009709314043432820"><ph name="APP_NAME" /> ایپ آپ کا کیمرا استعمال کر رہی ہے</translation>
 <translation id="701080569351381435">ماخذ دیکھیں</translation>
+<translation id="7011797924920577670">آپ کی دلچسپیوں کا اندازہ لگاتا ہے</translation>
 <translation id="7014174261166285193">انسٹالیشن ناکام ہو گیا۔</translation>
 <translation id="7014480873681694324">ہائی لائٹ کو ہٹائیں</translation>
 <translation id="7017004637493394352">‏"Ok Google" دوبارہ بولیں</translation>
@@ -6217,6 +6231,7 @@
 <translation id="7082568314107259011"><ph name="NETWORK_NAME" /> آپ کے منتظم کے زیر انتظام ہے</translation>
 <translation id="7085389578340536476">‏Chrome کو آڈیو ریکارڈ کرنے کی اجازت دیں؟</translation>
 <translation id="708550780726587276">(کنفیگر نہیں ہے)</translation>
+<translation id="7086531709814430567">ان ایکسٹینشنز کو ہمیشہ <ph name="ORIGIN" /> پر چلنے کی اجازت دیں؟</translation>
 <translation id="7086672505018440886">‏آرکائیو میں Chrome کی لاگ فائلز کو شامل کریں۔</translation>
 <translation id="7088434364990739311">اپ ڈیٹ چیک شروع ہونے میں ناکام ہوگیا (خرابی کا کوڈ <ph name="ERROR" />)۔</translation>
 <translation id="7088674813905715446">منتظم نے اس آلہ کو ایک مسترد کردہ حالت میں رکھ دیا ہے۔ اندراج کیلئے اسے فعال کرنے کیلئے، براہ کرم اپنے منتظم کو آلہ کو ایک زیر التوا حالت میں رکھنے دیں۔</translation>
@@ -8348,6 +8363,7 @@
 <translation id="9215742531438648683">‏Google Play اسٹور اَن انسٹال کریں</translation>
 <translation id="9218430445555521422">ڈیفالٹ کے بطور سیٹ کریں</translation>
 <translation id="9218842937876577955"><ph name="APP_NAME" /> (غیر تعاون یافتہ ایپ)</translation>
+<translation id="9219582468404818260">بہتر ویب بنانے میں ہماری مدد کریں</translation>
 <translation id="9220525904950070496">اکاؤنٹ ہٹائیں</translation>
 <translation id="9220820413868316583">اٹھائیں پھر دوبارہ کوشش کریں۔</translation>
 <translation id="923467487918828349">سبھی کو دکھائیں</translation>
diff --git a/chrome/app/resources/generated_resources_zh-HK.xtb b/chrome/app/resources/generated_resources_zh-HK.xtb
index 9f700fa0d..5215724 100644
--- a/chrome/app/resources/generated_resources_zh-HK.xtb
+++ b/chrome/app/resources/generated_resources_zh-HK.xtb
@@ -2475,6 +2475,7 @@
 <translation id="3348038390189153836">偵測到卸除式裝置</translation>
 <translation id="3348131053948466246">提供咗 Emoji 建議。㩒向上鍵或者向下鍵就可以導覽,㩒 Enter 鍵就可以插入 Emoji。</translation>
 <translation id="3349933790966648062">記憶體使用量</translation>
+<translation id="3353786022389205125">請開啟「從休眠狀態喚醒時顯示上鎖畫面」,然後再試一次</translation>
 <translation id="3354972872297836698">同裝置 <ph name="DEVICE_NAME" /> 配對唔到;請揀裝置之後再試一次</translation>
 <translation id="3355936511340229503">連線錯誤</translation>
 <translation id="3356469410714175391">(已啟用虛擬卡)</translation>
@@ -4948,6 +4949,7 @@
 <translation id="5827733057563115968">下一字預測</translation>
 <translation id="5828545842856466741">新增設定檔…</translation>
 <translation id="5828633471261496623">列印中…</translation>
+<translation id="5830205393314753525">無法開啟「<ph name="APP_NAME" />」</translation>
 <translation id="5830720307094128296">另存網頁(&amp;A)…</translation>
 <translation id="5832813618714645810">設定檔</translation>
 <translation id="583281660410589416">不明</translation>
diff --git a/chrome/browser/ash/crosapi/BUILD.gn b/chrome/browser/ash/crosapi/BUILD.gn
index dee3998..9f99764 100644
--- a/chrome/browser/ash/crosapi/BUILD.gn
+++ b/chrome/browser/ash/crosapi/BUILD.gn
@@ -189,6 +189,8 @@
     "video_frame_handler_ash.h",
     "vpn_extension_observer_ash.cc",
     "vpn_extension_observer_ash.h",
+    "vpn_service_ash.cc",
+    "vpn_service_ash.h",
     "web_app_service_ash.cc",
     "web_app_service_ash.h",
     "web_page_info_ash.cc",
diff --git a/chrome/browser/ash/crosapi/browser_util.cc b/chrome/browser/ash/crosapi/browser_util.cc
index dc37c064..bff557fd 100644
--- a/chrome/browser/ash/crosapi/browser_util.cc
+++ b/chrome/browser/ash/crosapi/browser_util.cc
@@ -231,9 +231,8 @@
 }
 
 static_assert(
-    crosapi::mojom::Crosapi::Version_ == 78,
+    crosapi::mojom::Crosapi::Version_ == 79,
     "if you add a new crosapi, please add it to kInterfaceVersionEntries");
-
 }  // namespace
 
 // NOTE: If you change the lacros component names, you must also update
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.cc b/chrome/browser/ash/crosapi/crosapi_ash.cc
index 1e9074c9..2b976006 100644
--- a/chrome/browser/ash/crosapi/crosapi_ash.cc
+++ b/chrome/browser/ash/crosapi/crosapi_ash.cc
@@ -78,6 +78,7 @@
 #include "chrome/browser/ash/crosapi/url_handler_ash.h"
 #include "chrome/browser/ash/crosapi/video_capture_device_factory_ash.h"
 #include "chrome/browser/ash/crosapi/vpn_extension_observer_ash.h"
+#include "chrome/browser/ash/crosapi/vpn_service_ash.h"
 #include "chrome/browser/ash/crosapi/web_app_service_ash.h"
 #include "chrome/browser/ash/crosapi/web_page_info_ash.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
@@ -210,15 +211,16 @@
       structured_metrics_service_ash_(
           std::make_unique<StructuredMetricsServiceAsh>()),
       system_display_ash_(std::make_unique<SystemDisplayAsh>()),
-      web_app_service_ash_(std::make_unique<WebAppServiceAsh>()),
-      web_page_info_factory_ash_(std::make_unique<WebPageInfoFactoryAsh>()),
       task_manager_ash_(std::make_unique<TaskManagerAsh>()),
       time_zone_service_ash_(std::make_unique<TimeZoneServiceAsh>()),
       tts_ash_(std::make_unique<TtsAsh>(g_browser_process->profile_manager())),
       url_handler_ash_(std::make_unique<UrlHandlerAsh>()),
       video_capture_device_factory_ash_(
           std::make_unique<VideoCaptureDeviceFactoryAsh>()),
-      vpn_extension_observer_ash_(std::make_unique<VpnExtensionObserverAsh>()) {
+      vpn_extension_observer_ash_(std::make_unique<VpnExtensionObserverAsh>()),
+      vpn_service_ash_(std::make_unique<VpnServiceAsh>()),
+      web_app_service_ash_(std::make_unique<WebAppServiceAsh>()),
+      web_page_info_factory_ash_(std::make_unique<WebPageInfoFactoryAsh>()) {
   receiver_set_.set_disconnect_handler(base::BindRepeating(
       &CrosapiAsh::OnDisconnected, weak_factory_.GetWeakPtr()));
 }
@@ -658,6 +660,11 @@
   vpn_extension_observer_ash_->BindReceiver(std::move(receiver));
 }
 
+void CrosapiAsh::BindVpnService(
+    mojo::PendingReceiver<mojom::VpnService> receiver) {
+  vpn_service_ash_->BindReceiver(std::move(receiver));
+}
+
 void CrosapiAsh::BindWebAppPublisher(
     mojo::PendingReceiver<mojom::AppPublisher> receiver) {
   Profile* profile = ProfileManager::GetPrimaryUserProfile();
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.h b/chrome/browser/ash/crosapi/crosapi_ash.h
index ffaf8d6..1f69d50 100644
--- a/chrome/browser/ash/crosapi/crosapi_ash.h
+++ b/chrome/browser/ash/crosapi/crosapi_ash.h
@@ -84,6 +84,7 @@
 class TaskManagerAsh;
 class TimeZoneServiceAsh;
 class TtsAsh;
+class VpnServiceAsh;
 class WebAppServiceAsh;
 class WebPageInfoFactoryAsh;
 class UrlHandlerAsh;
@@ -244,6 +245,8 @@
       mojo::PendingReceiver<mojom::SyncService> receiver) override;
   void BindSystemDisplay(
       mojo::PendingReceiver<mojom::SystemDisplay> receiver) override;
+  void BindVpnService(
+      mojo::PendingReceiver<mojom::VpnService> receiver) override;
   void BindWebAppService(
       mojo::PendingReceiver<mojom::WebAppService> receiver) override;
   void BindWebPageInfoFactory(
@@ -359,6 +362,7 @@
   VpnExtensionObserverAsh* vpn_extension_observer_ash() {
     return vpn_extension_observer_ash_.get();
   }
+  VpnServiceAsh* vpn_service_ash() { return vpn_service_ash_.get(); }
 
   // Caller is responsible for ensuring that the pointer stays valid.
   void SetTestControllerForTesting(TestControllerReceiver* test_controller);
@@ -424,8 +428,6 @@
 #endif  // BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)
   std::unique_ptr<StructuredMetricsServiceAsh> structured_metrics_service_ash_;
   std::unique_ptr<SystemDisplayAsh> system_display_ash_;
-  std::unique_ptr<WebAppServiceAsh> web_app_service_ash_;
-  std::unique_ptr<WebPageInfoFactoryAsh> web_page_info_factory_ash_;
   std::unique_ptr<TaskManagerAsh> task_manager_ash_;
   std::unique_ptr<TimeZoneServiceAsh> time_zone_service_ash_;
   std::unique_ptr<TtsAsh> tts_ash_;
@@ -433,6 +435,9 @@
   std::unique_ptr<VideoCaptureDeviceFactoryAsh>
       video_capture_device_factory_ash_;
   std::unique_ptr<VpnExtensionObserverAsh> vpn_extension_observer_ash_;
+  std::unique_ptr<VpnServiceAsh> vpn_service_ash_;
+  std::unique_ptr<WebAppServiceAsh> web_app_service_ash_;
+  std::unique_ptr<WebPageInfoFactoryAsh> web_page_info_factory_ash_;
 
   // Only set in the test ash chrome binary. In production ash this is always
   // nullptr.
diff --git a/chrome/browser/ash/crosapi/crosapi_util.cc b/chrome/browser/ash/crosapi/crosapi_util.cc
index fb3fbebf..e066deb8 100644
--- a/chrome/browser/ash/crosapi/crosapi_util.cc
+++ b/chrome/browser/ash/crosapi/crosapi_util.cc
@@ -90,6 +90,7 @@
 #include "chromeos/crosapi/mojom/url_handler.mojom.h"
 #include "chromeos/crosapi/mojom/video_capture.mojom.h"
 #include "chromeos/crosapi/mojom/vpn_extension_observer.mojom.h"
+#include "chromeos/crosapi/mojom/vpn_service.mojom.h"
 #include "chromeos/crosapi/mojom/web_app_service.mojom.h"
 #include "chromeos/crosapi/mojom/web_page_info.mojom.h"
 #include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h"
@@ -257,9 +258,10 @@
     MakeInterfaceVersionEntry<crosapi::mojom::Tts>(),
     MakeInterfaceVersionEntry<crosapi::mojom::UrlHandler>(),
     MakeInterfaceVersionEntry<crosapi::mojom::VideoCaptureDeviceFactory>(),
+    MakeInterfaceVersionEntry<crosapi::mojom::VpnExtensionObserver>(),
+    MakeInterfaceVersionEntry<crosapi::mojom::VpnService>(),
     MakeInterfaceVersionEntry<crosapi::mojom::WebAppService>(),
     MakeInterfaceVersionEntry<crosapi::mojom::WebPageInfoFactory>(),
-    MakeInterfaceVersionEntry<crosapi::mojom::VpnExtensionObserver>(),
     MakeInterfaceVersionEntry<device::mojom::HidConnection>(),
     MakeInterfaceVersionEntry<device::mojom::HidManager>(),
     MakeInterfaceVersionEntry<
diff --git a/chrome/browser/ash/crosapi/local_printer_ash.cc b/chrome/browser/ash/crosapi/local_printer_ash.cc
index 6c8e58e..f98d5ea 100644
--- a/chrome/browser/ash/crosapi/local_printer_ash.cc
+++ b/chrome/browser/ash/crosapi/local_printer_ash.cc
@@ -486,9 +486,8 @@
     return;
   }
 
-  deny_list.reserve(deny_list_from_prefs->GetListDeprecated().size());
-  for (const base::Value& deny_list_value :
-       deny_list_from_prefs->GetListDeprecated()) {
+  deny_list.reserve(deny_list_from_prefs->GetList().size());
+  for (const base::Value& deny_list_value : deny_list_from_prefs->GetList()) {
     const std::string& deny_list_str = deny_list_value.GetString();
     printing::mojom::PrinterType printer_type;
     if (deny_list_str == "extension")
diff --git a/chrome/browser/ash/crosapi/search_provider_ash.h b/chrome/browser/ash/crosapi/search_provider_ash.h
index 37b3af46..6f5b4d6 100644
--- a/chrome/browser/ash/crosapi/search_provider_ash.h
+++ b/chrome/browser/ash/crosapi/search_provider_ash.h
@@ -17,10 +17,28 @@
 
 namespace crosapi {
 
-// Implements the crosapi interface for launcher search. Lives ash-chrome on UI
-// thread.
 // IMPORTANT: This search API should only be used by the launcher, because
 // in-flight queries will be cancelled whenever a new query is issued.
+//
+// This class is the crosapi entry-point for launcher omnibox search. It lives
+// in ash-chrome on the UI thread. Omnibox results are obtained as follows:
+//
+//   1) On creation, each lacros instance requests a `SearchControllerRegistry`
+//      (all of which are implemented by the same instance of this class), and
+//      sends across a handle to its search controller.
+//
+//      TODO(1329709): Currently, a search controller is accepted exactly if a
+//      new lacros instance is created after the previous instance is dead.
+//      Correct this.
+//
+//   2) Once the search controller handle has been received, clients (i.e. code
+//      in ash-chrome) can use the `Search` method to fetch omnibox results,
+//      which delegates to the search controller over Mojo.
+//
+//      Internally, this class implements one `SearchResultsPublisher` per
+//      search request (even though the search controller can only execute one
+//      search at a time) in order to notify old clients if their search is
+//      preempted. It's likely that this can be simplified in the future.
 class SearchProviderAsh : public mojom::SearchResultsPublisher,
                           public mojom::SearchControllerRegistry {
  public:
diff --git a/chrome/browser/ash/crosapi/vpn_service_ash.cc b/chrome/browser/ash/crosapi/vpn_service_ash.cc
new file mode 100644
index 0000000..8ceb728e
--- /dev/null
+++ b/chrome/browser/ash/crosapi/vpn_service_ash.cc
@@ -0,0 +1,666 @@
+// 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.
+
+#include "chrome/browser/ash/crosapi/vpn_service_ash.h"
+
+#include <utility>
+
+#include "ash/public/cpp/network_config_service.h"
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/guid.h"
+#include "base/memory/raw_ptr.h"
+#include "base/notreached.h"
+#include "base/run_loop.h"
+#include "base/values.h"
+#include "chrome/browser/ash/crosapi/crosapi_ash.h"
+#include "chrome/browser/ash/profiles/profile_helper.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_third_party_vpn_driver_client.h"
+#include "chromeos/dbus/shill/shill_third_party_vpn_observer.h"
+#include "chromeos/network/network_configuration_handler.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_profile_handler.h"
+#include "chromeos/network/network_state_handler.h"
+#include "chromeos/network/network_type_pattern.h"
+#include "crypto/sha2.h"
+#include "extensions/browser/extension_event_histogram_value.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
+
+namespace {
+
+using SuccessOrFailureCallback =
+    base::OnceCallback<void(crosapi::mojom::VpnErrorResponsePtr)>;
+
+void RunSuccessCallback(SuccessOrFailureCallback callback) {
+  std::move(callback).Run(nullptr);
+}
+
+void RunWarningCallback(
+    crosapi::VpnServiceForExtensionAsh::SuccessCallback callback,
+    const std::string& /*warning*/) {
+  std::move(callback).Run();
+}
+
+void RunFailureCallback(SuccessOrFailureCallback callback,
+                        const std::string& error_name,
+                        const std::string& error_message) {
+  std::move(callback).Run(
+      crosapi::mojom::VpnErrorResponse::New(error_name, error_message));
+}
+
+// crosapi::mojom::VpnService expects a single callback, whereas the API is
+// designed to pass in two (one for success, one for failure). This function
+// unpacks (splits) the single callback into the success and failure ones
+// respectively. For the reverse transformation see
+// chrome/browser/chromeos/extensions/vpn_provider/vpn_service.cc
+std::pair<crosapi::VpnServiceForExtensionAsh::SuccessCallback,
+          crosapi::VpnServiceForExtensionAsh::FailureCallback>
+AdaptCallback(SuccessOrFailureCallback callback) {
+  auto [success, failure] = base::SplitOnceCallback(std::move(callback));
+
+  return {base::BindOnce(&RunSuccessCallback, std::move(success)),
+          base::BindOnce(&RunFailureCallback, std::move(failure))};
+}
+
+}  // namespace
+
+namespace crosapi {
+
+VpnProvidersObserver::VpnProvidersObserver(
+    VpnProvidersObserver::Delegate* delegate)
+    : delegate_(delegate) {
+  ash::GetNetworkConfigService(
+      cros_network_config_.BindNewPipeAndPassReceiver());
+  cros_network_config_->AddObserver(
+      cros_network_config_observer_.BindNewPipeAndPassRemote());
+}
+
+VpnProvidersObserver::~VpnProvidersObserver() = default;
+
+void VpnProvidersObserver::OnVpnProvidersChanged() {
+  cros_network_config_->GetVpnProviders(base::BindOnce(
+      &VpnProvidersObserver::OnGetVpnProviders, weak_factory_.GetWeakPtr()));
+}
+
+void VpnProvidersObserver::OnGetVpnProviders(
+    std::vector<chromeos::network_config::mojom::VpnProviderPtr>
+        vpn_providers) {
+  if (!delegate_) {
+    return;
+  }
+  base::flat_set<std::string> vpn_extensions;
+  for (const auto& vpn_provider : vpn_providers) {
+    if (vpn_provider->type ==
+        chromeos::network_config::mojom::VpnType::kExtension) {
+      vpn_extensions.insert(vpn_provider->app_id);
+    }
+  }
+  delegate_->OnVpnExtensionsChanged(std::move(vpn_extensions));
+}
+
+class VpnConfigurationImpl
+    : public VpnServiceForExtensionAsh::VpnConfiguration {
+ public:
+  VpnConfigurationImpl(const std::string& configuration_name,
+                       const std::string& key,
+                       VpnServiceForExtensionAsh* vpn_service)
+      : configuration_name_(configuration_name),
+        key_(key),
+        object_path_(shill::kObjectPathBase + key),
+        vpn_service_(std::move(vpn_service)) {}
+
+  // VpnServiceAsh::VpnConfiguration:
+  const std::string& configuration_name() const override {
+    return configuration_name_;
+  }
+  const std::string& key() const override { return key_; }
+  const std::string& object_path() const override { return object_path_; }
+  const absl::optional<std::string>& service_path() const override {
+    return service_path_;
+  }
+  void set_service_path(std::string service_path) override {
+    service_path_ = std::move(service_path);
+  }
+
+  void BindPepperVpnProxyObserver(
+      mojo::PendingRemote<crosapi::mojom::PepperVpnProxyObserver>
+          pepper_vpn_proxy_observer) override {
+    pepper_vpn_proxy_observer_.Bind(std::move(pepper_vpn_proxy_observer));
+  }
+
+  // chromeos::ShillThirdPartyVpnObserver:
+  void OnPacketReceived(const std::vector<char>& data) override;
+  void OnPlatformMessage(uint32_t platform_message) override;
+
+ private:
+  const std::string configuration_name_;
+  const std::string key_;
+  const std::string object_path_;
+  absl::optional<std::string> service_path_;
+
+  mojo::Remote<crosapi::mojom::PepperVpnProxyObserver>
+      pepper_vpn_proxy_observer_;
+
+  // |this| is owned by VpnServiceForExtensionAsh.
+  raw_ptr<VpnServiceForExtensionAsh> vpn_service_ = nullptr;
+};
+
+void VpnConfigurationImpl::OnPacketReceived(const std::vector<char>& data) {
+  DCHECK(vpn_service_);
+  // If Pepper observer is bound, route the packet through the Pepper API.
+  if (pepper_vpn_proxy_observer_) {
+    pepper_vpn_proxy_observer_->OnPacketReceived(
+        std::vector<uint8_t>(data.begin(), data.end()));
+  } else {
+    vpn_service_->DispatchOnPacketReceivedEvent(data);
+  }
+}
+
+void VpnConfigurationImpl::OnPlatformMessage(uint32_t platform_message) {
+  DCHECK(vpn_service_);
+  DCHECK_GE(api_vpn::PLATFORM_MESSAGE_LAST, platform_message);
+
+  if (platform_message == api_vpn::PLATFORM_MESSAGE_CONNECTED) {
+    vpn_service_->SetActiveConfiguration(this);
+  } else if (platform_message == api_vpn::PLATFORM_MESSAGE_DISCONNECTED ||
+             platform_message == api_vpn::PLATFORM_MESSAGE_ERROR) {
+    vpn_service_->SetActiveConfiguration(nullptr);
+    if (pepper_vpn_proxy_observer_) {
+      pepper_vpn_proxy_observer_->OnUnbind();
+      pepper_vpn_proxy_observer_.reset();
+    }
+  }
+
+  vpn_service_->DispatchOnPlatformMessageEvent(configuration_name(),
+                                               platform_message);
+}
+
+VpnServiceForExtensionAsh::VpnServiceForExtensionAsh(
+    const std::string& extension_id)
+    : extension_id_(extension_id) {
+  network_configuration_observer_.Observe(
+      chromeos::NetworkHandler::Get()->network_configuration_handler());
+}
+
+VpnServiceForExtensionAsh::~VpnServiceForExtensionAsh() = default;
+
+void VpnServiceForExtensionAsh::BindReceiverAndObserver(
+    mojo::PendingReceiver<crosapi::mojom::VpnServiceForExtension> receiver,
+    mojo::PendingRemote<crosapi::mojom::EventObserverForExtension> observer) {
+  receivers_.Add(this, std::move(receiver));
+  observers_.Add(std::move(observer));
+}
+
+void VpnServiceForExtensionAsh::CreateConfiguration(
+    const std::string& configuration_name,
+    CreateConfigurationCallback callback) {
+  if (configuration_name.empty()) {
+    RunFailureCallback(std::move(callback), /*error_name=*/{},
+                       "Empty name not supported.");
+    return;
+  }
+
+  const std::string key = GetKey(extension_id(), configuration_name);
+  if (base::Contains(key_to_configuration_map_, key)) {
+    RunFailureCallback(std::move(callback), /*error_name=*/{},
+                       "Name not unique.");
+    return;
+  }
+
+  // Since the API is only designed to be used with the primary profile, it's
+  // safe to get the hash of the primary profile here.
+  const chromeos::NetworkProfile* profile =
+      chromeos::NetworkHandler::Get()
+          ->network_profile_handler()
+          ->GetProfileForUserhash(ash::ProfileHelper::GetUserIdHashFromProfile(
+              ProfileManager::GetPrimaryUserProfile()));
+  if (!profile) {
+    RunFailureCallback(std::move(callback), /*error_name=*/{},
+                       "No user profile for unshared network configuration.");
+    return;
+  }
+
+  VpnConfiguration* configuration =
+      CreateConfigurationInternal(configuration_name);
+
+  base::Value::Dict properties;
+  properties.Set(shill::kTypeProperty, shill::kTypeVPN);
+  properties.Set(shill::kNameProperty, configuration_name);
+  properties.Set(shill::kProviderHostProperty, extension_id());
+  properties.Set(shill::kObjectPathSuffixProperty, key);
+  properties.Set(shill::kProviderTypeProperty, shill::kProviderThirdPartyVpn);
+  properties.Set(shill::kProfileProperty, profile->path);
+  properties.Set(shill::kGuidProperty, base::GenerateGUID());
+
+  auto [success, failure] = AdaptCallback(std::move(callback));
+  chromeos::NetworkHandler::Get()
+      ->network_configuration_handler()
+      ->CreateShillConfiguration(
+          base::Value(std::move(properties)),
+          base::BindOnce(
+              &VpnServiceForExtensionAsh::OnCreateConfigurationSuccess,
+              weak_factory_.GetWeakPtr(), std::move(success), configuration),
+          base::BindOnce(
+              &VpnServiceForExtensionAsh::OnCreateConfigurationFailure,
+              weak_factory_.GetWeakPtr(), std::move(failure), configuration));
+}
+
+void VpnServiceForExtensionAsh::DestroyConfiguration(
+    const std::string& configuration_name,
+    DestroyConfigurationCallback callback) {
+  const std::string key = GetKey(extension_id(), configuration_name);
+  auto it = key_to_configuration_map_.find(key);
+  if (it == key_to_configuration_map_.end()) {
+    RunFailureCallback(std::move(callback), /*error_name=*/{},
+                       "Unauthorized access.");
+    return;
+  }
+  VpnConfiguration* configuration = it->second.get();
+
+  // Avoid const ref here since configuration gets removed before service_path
+  // is used.
+  const absl::optional<std::string> service_path =
+      configuration->service_path();
+
+  if (!service_path) {
+    RunFailureCallback(std::move(callback), /*error_name=*/{},
+                       "Pending create.");
+    return;
+  }
+
+  if (active_configuration_ == configuration) {
+    configuration->OnPlatformMessage(api_vpn::PLATFORM_MESSAGE_DISCONNECTED);
+  }
+
+  DestroyConfigurationInternal(configuration);
+
+  auto [success, failure] = AdaptCallback(std::move(callback));
+  chromeos::NetworkHandler::Get()
+      ->network_configuration_handler()
+      ->RemoveConfiguration(
+          *service_path,
+          /*remove_confirmer=*/{},
+          base::BindOnce(
+              &VpnServiceForExtensionAsh::OnRemoveConfigurationSuccess,
+              weak_factory_.GetWeakPtr(), std::move(success)),
+          base::BindOnce(
+              &VpnServiceForExtensionAsh::OnRemoveConfigurationFailure,
+              weak_factory_.GetWeakPtr(), std::move(failure)));
+}
+
+void VpnServiceForExtensionAsh::SetParameters(base::Value::Dict parameters,
+                                              SetParametersCallback callback) {
+  if (!OwnsActiveConfiguration()) {
+    RunFailureCallback(std::move(callback), /*error_name=*/{},
+                       "Unauthorized access.");
+    return;
+  }
+
+  auto [success, failure] = AdaptCallback(std::move(callback));
+  chromeos::ShillThirdPartyVpnDriverClient::Get()->SetParameters(
+      active_configuration_->object_path(), base::Value(std::move(parameters)),
+      base::BindOnce(&RunWarningCallback, std::move(success)),
+      std::move(failure));
+}
+
+void VpnServiceForExtensionAsh::SendPacket(const std::vector<uint8_t>& data,
+                                           SendPacketCallback callback) {
+  if (!OwnsActiveConfiguration()) {
+    RunFailureCallback(std::move(callback), /*error_name=*/{},
+                       "Unauthorized access.");
+    return;
+  }
+
+  if (data.empty()) {
+    RunFailureCallback(std::move(callback), /*error_name=*/{},
+                       "Can't send an empty packet.");
+    return;
+  }
+
+  auto [success, failure] = AdaptCallback(std::move(callback));
+  chromeos::ShillThirdPartyVpnDriverClient::Get()->SendPacket(
+      active_configuration_->object_path(),
+      std::vector<char>(data.begin(), data.end()), std::move(success),
+      std::move(failure));
+}
+
+void VpnServiceForExtensionAsh::NotifyConnectionStateChanged(
+    bool connection_success,
+    NotifyConnectionStateChangedCallback callback) {
+  if (!OwnsActiveConfiguration()) {
+    RunFailureCallback(std::move(callback), /*error_name=*/{},
+                       "Unauthorized access.");
+    return;
+  }
+
+  auto [success, failure] = AdaptCallback(std::move(callback));
+  chromeos::ShillThirdPartyVpnDriverClient::Get()->UpdateConnectionState(
+      active_configuration_->object_path(),
+      connection_success
+          ? api_vpn::VpnConnectionState::VPN_CONNECTION_STATE_CONNECTED
+          : api_vpn::VpnConnectionState::VPN_CONNECTION_STATE_FAILURE,
+      std::move(success), std::move(failure));
+}
+
+void VpnServiceForExtensionAsh::BindPepperVpnProxyObserver(
+    const std::string& configuration_name,
+    mojo::PendingRemote<crosapi::mojom::PepperVpnProxyObserver>
+        pepper_vpn_proxy_observer,
+    BindPepperVpnProxyObserverCallback callback) {
+  const std::string key = GetKey(extension_id(), configuration_name);
+  auto it = key_to_configuration_map_.find(key);
+  if (it == key_to_configuration_map_.end()) {
+    RunFailureCallback(
+        std::move(callback), /*error_name=*/{},
+        "Unauthorized access. The configuration does not exist.");
+    return;
+  }
+
+  VpnConfiguration* configuration = it->second.get();
+  if (active_configuration_ != configuration) {
+    RunFailureCallback(std::move(callback), /*error_name=*/{},
+                       "Unauthorized access. The configuration is not active.");
+    return;
+  }
+
+  if (configuration->configuration_name() != configuration_name) {
+    RunFailureCallback(
+        std::move(callback), /*error_name=*/{},
+        "Unauthorized access. Configuration name or extension ID mismatch.");
+    return;
+  }
+
+  if (!configuration->service_path()) {
+    RunFailureCallback(std::move(callback), /*error_name=*/{},
+                       "Pending create.");
+    return;
+  }
+
+  // Connection authorized. All packets will be routed through the Pepper API.
+  configuration->BindPepperVpnProxyObserver(
+      std::move(pepper_vpn_proxy_observer));
+
+  RunSuccessCallback(std::move(callback));
+}
+
+void VpnServiceForExtensionAsh::DispatchAddDialogEvent() {
+  for (auto& observer : observers_) {
+    observer->OnAddDialog();
+  }
+}
+
+void VpnServiceForExtensionAsh::DispatchConfigureDialogEvent(
+    const std::string& configuration_name) {
+  for (auto& observer : observers_) {
+    observer->OnConfigureDialog(configuration_name);
+  }
+}
+
+void VpnServiceForExtensionAsh::OnConfigurationRemoved(
+    const std::string& service_path,
+    const std::string& guid) {
+  auto it = service_path_to_configuration_map_.find(service_path);
+  if (it == service_path_to_configuration_map_.end()) {
+    // Ignore removal of a configuration unknown to VPN service, which means
+    // the configuration was created internally by the platform or already
+    // removed by the extension.
+    return;
+  }
+
+  VpnConfiguration* configuration = it->second;
+
+  DispatchConfigRemovedEvent(configuration->configuration_name());
+  DestroyConfigurationInternal(configuration);
+}
+
+bool VpnServiceForExtensionAsh::OwnsActiveConfiguration() const {
+  return !!active_configuration_;
+}
+
+bool VpnServiceForExtensionAsh::HasConfigurationForServicePath(
+    const std::string& service_path) const {
+  return base::Contains(service_path_to_configuration_map_, service_path);
+}
+
+void VpnServiceForExtensionAsh::DestroyAllConfigurations() {
+  std::vector<std::string> to_be_destroyed;
+  for (const auto& [key, configuration] : key_to_configuration_map_) {
+    to_be_destroyed.push_back(configuration->configuration_name());
+  }
+  for (const auto& configuration_name : to_be_destroyed) {
+    DestroyConfiguration(configuration_name, base::DoNothing());
+  }
+}
+
+void VpnServiceForExtensionAsh::CreateConfigurationWithServicePath(
+    const std::string& configuration_name,
+    const std::string& service_path) {
+  DCHECK(!HasConfigurationForServicePath(service_path));
+  VpnConfiguration* configuration =
+      CreateConfigurationInternal(configuration_name);
+  configuration->set_service_path(service_path);
+  service_path_to_configuration_map_[service_path] = configuration;
+  chromeos::ShillThirdPartyVpnDriverClient::Get()
+      ->AddShillThirdPartyVpnObserver(configuration->object_path(),
+                                      configuration);
+}
+
+void VpnServiceForExtensionAsh::DispatchConfigRemovedEvent(
+    const std::string& configuration_name) {
+  for (auto& observer : observers_) {
+    observer->OnConfigRemoved(configuration_name);
+  }
+}
+
+void VpnServiceForExtensionAsh::DispatchOnPacketReceivedEvent(
+    const std::vector<char>& data) {
+  std::vector<uint8_t> data_(data.begin(), data.end());
+  for (auto& observer : observers_) {
+    observer->OnPacketReceived(data_);
+  }
+}
+
+void VpnServiceForExtensionAsh::DispatchOnPlatformMessageEvent(
+    const std::string& configuration_name,
+    int32_t platform_message,
+    const absl::optional<std::string>& error) {
+  for (auto& observer : observers_) {
+    observer->OnPlatformMessage(configuration_name, platform_message, error);
+  }
+}
+
+// static
+std::string VpnServiceForExtensionAsh::GetKey(
+    const std::string& extension_id,
+    const std::string& configuration_name) {
+  const std::string key =
+      crypto::SHA256HashString(extension_id + configuration_name);
+  return base::HexEncode(key.data(), key.size());
+}
+
+VpnServiceForExtensionAsh::VpnConfiguration*
+VpnServiceForExtensionAsh::CreateConfigurationInternal(
+    const std::string& configuration_name) {
+  const std::string key = GetKey(extension_id(), configuration_name);
+  auto configuration =
+      std::make_unique<VpnConfigurationImpl>(configuration_name, key, this);
+  auto* ptr = configuration.get();
+  key_to_configuration_map_.emplace(key, std::move(configuration));
+  return ptr;
+}
+
+void VpnServiceForExtensionAsh::DestroyConfigurationInternal(
+    VpnConfiguration* configuration) {
+  // |owned_configuration| ensures that |configuration| stays valid until the
+  // end of the scope.
+  auto owned_configuration =
+      std::move(key_to_configuration_map_[configuration->key()]);
+  key_to_configuration_map_.erase(configuration->key());
+  if (active_configuration_ == configuration) {
+    SetActiveConfiguration(nullptr);
+  }
+
+  if (const absl::optional<std::string>& service_path =
+          configuration->service_path()) {
+    chromeos::ShillThirdPartyVpnDriverClient::Get()
+        ->RemoveShillThirdPartyVpnObserver(configuration->object_path());
+    service_path_to_configuration_map_.erase(*service_path);
+  }
+}
+
+void VpnServiceForExtensionAsh::OnCreateConfigurationSuccess(
+    SuccessCallback callback,
+    VpnConfiguration* configuration,
+    const std::string& service_path,
+    const std::string& guid) {
+  configuration->set_service_path(service_path);
+  service_path_to_configuration_map_[service_path] = configuration;
+  chromeos::ShillThirdPartyVpnDriverClient::Get()
+      ->AddShillThirdPartyVpnObserver(configuration->object_path(),
+                                      configuration);
+  std::move(callback).Run();
+}
+
+void VpnServiceForExtensionAsh::OnCreateConfigurationFailure(
+    FailureCallback callback,
+    VpnConfiguration* configuration,
+    const std::string& error_name) {
+  DestroyConfigurationInternal(configuration);
+  std::move(callback).Run(error_name, /*error_message=*/{});
+}
+
+void VpnServiceForExtensionAsh::OnRemoveConfigurationSuccess(
+    SuccessCallback callback) {
+  std::move(callback).Run();
+}
+
+void VpnServiceForExtensionAsh::OnRemoveConfigurationFailure(
+    FailureCallback callback,
+    const std::string& error_name) {
+  std::move(callback).Run(error_name, /*error_message=*/{});
+}
+
+void VpnServiceForExtensionAsh::SetActiveConfiguration(
+    VpnConfiguration* configuration) {
+  active_configuration_ = configuration;
+}
+
+VpnServiceAsh::VpnServiceAsh() {
+  // Can be false in unit tests.
+  if (!chromeos::NetworkHandler::IsInitialized()) {
+    return;
+  }
+
+  network_state_handler_observer_.Observe(
+      chromeos::NetworkHandler::Get()->network_state_handler());
+
+  vpn_providers_observer_ = std::make_unique<VpnProvidersObserver>(this);
+}
+
+VpnServiceAsh::~VpnServiceAsh() = default;
+
+void VpnServiceAsh::BindReceiver(
+    mojo::PendingReceiver<crosapi::mojom::VpnService> receiver) {
+  receivers_.Add(this, std::move(receiver));
+}
+
+void VpnServiceAsh::RegisterVpnServiceForExtension(
+    const std::string& extension_id,
+    mojo::PendingReceiver<crosapi::mojom::VpnServiceForExtension> receiver,
+    mojo::PendingRemote<crosapi::mojom::EventObserverForExtension> observer) {
+  auto it = extension_id_to_service_.find(extension_id);
+  if (it == extension_id_to_service_.end()) {
+    it = extension_id_to_service_.insert(
+        it, {extension_id,
+             std::make_unique<VpnServiceForExtensionAsh>(extension_id)});
+  }
+  const auto& service = it->second;
+  service->BindReceiverAndObserver(std::move(receiver), std::move(observer));
+}
+
+void VpnServiceAsh::MaybeFailActiveConnectionAndDestroyConfigurations(
+    const std::string& extension_id,
+    bool destroy_configurations) {
+  auto it = extension_id_to_service_.find(extension_id);
+  if (it == extension_id_to_service_.end()) {
+    return;
+  }
+  auto& service = it->second;
+
+  service->NotifyConnectionStateChanged(
+      /*connection_success=*/false, base::DoNothing());
+
+  if (destroy_configurations) {
+    service->DestroyAllConfigurations();
+  }
+}
+
+void VpnServiceAsh::NetworkListChanged() {
+  chromeos::NetworkStateHandler::NetworkStateList network_list;
+
+  auto* network_handler = chromeos::NetworkHandler::Get();
+  network_handler->network_state_handler()->GetVisibleNetworkListByType(
+      chromeos::NetworkTypePattern::VPN(), &network_list);
+
+  for (auto* network_state : network_list) {
+    network_handler->network_configuration_handler()->GetShillProperties(
+        network_state->path(),
+        base::BindOnce(&VpnServiceAsh::OnGetShillProperties,
+                       weak_factory_.GetWeakPtr()));
+  }
+}
+
+void VpnServiceAsh::OnVpnExtensionsChanged(
+    base::flat_set<std::string> vpn_extensions) {
+  // No changes to the existing set?
+  if (vpn_extensions_ == vpn_extensions) {
+    return;
+  }
+  vpn_extensions_ = std::move(vpn_extensions);
+  NetworkListChanged();
+}
+
+void VpnServiceAsh::OnGetShillProperties(
+    const std::string& service_path,
+    absl::optional<base::Value> configuration_properties) {
+  if (!configuration_properties) {
+    return;
+  }
+  const std::string* vpn_type =
+      configuration_properties->FindStringPath(shill::kProviderTypeProperty);
+  const std::string* extension_id =
+      configuration_properties->FindStringPath(shill::kProviderHostProperty);
+  const std::string* type =
+      configuration_properties->FindStringPath(shill::kTypeProperty);
+  const std::string* configuration_name =
+      configuration_properties->FindStringPath(shill::kNameProperty);
+  if (!vpn_type || !extension_id || !type || !configuration_name ||
+      *vpn_type != shill::kProviderThirdPartyVpn || *type != shill::kTypeVPN) {
+    return;
+  }
+
+  if (!base::Contains(vpn_extensions_, *extension_id)) {
+    return;
+  }
+
+  auto it = extension_id_to_service_.find(*extension_id);
+  if (it == extension_id_to_service_.end()) {
+    it = extension_id_to_service_.insert(
+        it, {*extension_id,
+             std::make_unique<VpnServiceForExtensionAsh>(*extension_id)});
+  }
+  auto& service = it->second;
+  if (service->HasConfigurationForServicePath(service_path)) {
+    return;
+  }
+  service->CreateConfigurationWithServicePath(*configuration_name,
+                                              service_path);
+}
+
+}  // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/vpn_service_ash.h b/chrome/browser/ash/crosapi/vpn_service_ash.h
new file mode 100644
index 0000000..01aa9e74
--- /dev/null
+++ b/chrome/browser/ash/crosapi/vpn_service_ash.h
@@ -0,0 +1,315 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_CROSAPI_VPN_SERVICE_ASH_H_
+#define CHROME_BROWSER_ASH_CROSAPI_VPN_SERVICE_ASH_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/callback_helpers.h"
+#include "base/containers/flat_set.h"
+#include "base/memory/raw_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/scoped_observation.h"
+#include "chrome/common/extensions/api/vpn_provider.h"
+#include "chromeos/crosapi/mojom/vpn_service.mojom.h"
+#include "chromeos/dbus/shill/shill_third_party_vpn_driver_client.h"
+#include "chromeos/dbus/shill/shill_third_party_vpn_observer.h"
+#include "chromeos/network/network_configuration_handler.h"
+#include "chromeos/network/network_configuration_observer.h"
+#include "chromeos/network/network_profile_handler.h"
+#include "chromeos/network/network_state_handler.h"
+#include "chromeos/network/network_state_handler_observer.h"
+#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/remote_set.h"
+
+namespace base {
+
+class Value;
+
+}  // namespace base
+
+namespace chromeos {
+
+// Fwd for friend declaration in VpnServiceAsh.
+class VpnProviderApiTest;
+
+}  // namespace chromeos
+
+namespace crosapi {
+
+namespace api_vpn = extensions::api::vpn_provider;
+
+class SimpleCrosNetworkObserver
+    : public chromeos::network_config::mojom::CrosNetworkConfigObserver {
+ public:
+  // chromeos::network_config::mojom::CrosNetworkConfigObserver:
+  void OnVpnProvidersChanged() override {}
+
+  // We're not interested in these functions, but we still have to override them
+  // since they're purely virtual.
+  void OnActiveNetworksChanged(
+      std::vector<chromeos::network_config::mojom::NetworkStatePropertiesPtr>)
+      final {}
+  void OnNetworkStateChanged(
+      chromeos::network_config::mojom::NetworkStatePropertiesPtr) final {}
+  void OnNetworkStateListChanged() final {}
+  void OnDeviceStateListChanged() final {}
+  void OnNetworkCertificatesChanged() final {}
+  void OnPoliciesApplied(const std::string&) final {}
+};
+
+// Listens to |OnVpnProvidersChanged| event and informs the delegate of the
+// current set of vpn extension.
+class VpnProvidersObserver : public SimpleCrosNetworkObserver {
+ public:
+  class Delegate {
+   public:
+    virtual ~Delegate() {}
+
+    virtual void OnVpnExtensionsChanged(
+        base::flat_set<std::string> vpn_extensions) = 0;
+  };
+
+  explicit VpnProvidersObserver(Delegate*);
+  ~VpnProvidersObserver() override;
+
+  // chromeos::network_config::mojom::CrosNetworkConfigObserver:
+  void OnVpnProvidersChanged() override;
+
+ private:
+  // Callback for CrosNetworkConfig::GetVpnProviders().
+  // Extracts vpn extension ids and calls Delegate::OnVpnExtensionsChanged().
+  void OnGetVpnProviders(
+      std::vector<chromeos::network_config::mojom::VpnProviderPtr>
+          vpn_providers);
+
+  raw_ptr<Delegate> delegate_ = nullptr;
+
+  mojo::Remote<chromeos::network_config::mojom::CrosNetworkConfig>
+      cros_network_config_;
+  mojo::Receiver<chromeos::network_config::mojom::CrosNetworkConfigObserver>
+      cros_network_config_observer_{this};
+
+  base::WeakPtrFactory<VpnProvidersObserver> weak_factory_{this};
+};
+
+class VpnServiceAsh;
+
+// This class manages configurations for a particular extension.
+class VpnServiceForExtensionAsh
+    : public crosapi::mojom::VpnServiceForExtension,
+      public chromeos::NetworkConfigurationObserver {
+ public:
+  // Callback definitions.
+  using SuccessCallback = base::OnceClosure;
+  using FailureCallback =
+      base::OnceCallback<void(const std::string& error_name,
+                              const std::string& error_message)>;
+
+  // Class forward declarations.
+  class VpnConfiguration;
+
+ public:
+  explicit VpnServiceForExtensionAsh(const std::string& extension_id);
+  ~VpnServiceForExtensionAsh() override;
+
+  VpnServiceForExtensionAsh(const VpnServiceForExtensionAsh&) = delete;
+  VpnServiceForExtensionAsh& operator=(const VpnServiceForExtensionAsh&) =
+      delete;
+
+  void BindReceiverAndObserver(
+      mojo::PendingReceiver<crosapi::mojom::VpnServiceForExtension> receiver,
+      mojo::PendingRemote<crosapi::mojom::EventObserverForExtension> observer);
+
+  // crosapi::mojom::VpnServiceForExtension:
+  void CreateConfiguration(const std::string& configuration_name,
+                           CreateConfigurationCallback) override;
+  void DestroyConfiguration(const std::string& configuration_name,
+                            DestroyConfigurationCallback) override;
+  void SetParameters(base::Value::Dict parameters,
+                     SetParametersCallback) override;
+  void SendPacket(const std::vector<uint8_t>& data,
+                  SendPacketCallback) override;
+  void NotifyConnectionStateChanged(
+      bool connection_success,
+      NotifyConnectionStateChangedCallback) override;
+  void BindPepperVpnProxyObserver(
+      const std::string& configuration_name,
+      mojo::PendingRemote<crosapi::mojom::PepperVpnProxyObserver>
+          pepper_vpn_proxy_observer,
+      BindPepperVpnProxyObserverCallback) override;
+  void DispatchAddDialogEvent() override;
+  void DispatchConfigureDialogEvent(
+      const std::string& configuration_name) override;
+
+  // chromeos::NetworkConfigurationObserver:
+  void OnConfigurationRemoved(const std::string& service_path,
+                              const std::string& guid) override;
+
+  bool OwnsActiveConfiguration() const;
+  bool HasConfigurationForServicePath(const std::string& service_path) const;
+
+  void DestroyAllConfigurations();
+
+  void CreateConfigurationWithServicePath(const std::string& configuration_name,
+                                          const std::string& service_path);
+
+  void DispatchConfigRemovedEvent(const std::string& configuration_name);
+  void DispatchOnPacketReceivedEvent(const std::vector<char>& data);
+  void DispatchOnPlatformMessageEvent(
+      const std::string& configuration_name,
+      int32_t platform_message,
+      const absl::optional<std::string>& error = {});
+
+ private:
+  friend class VpnConfigurationImpl;
+  friend class chromeos::VpnProviderApiTest;
+
+  using StringToOwnedConfigurationMap =
+      std::map<std::string, std::unique_ptr<VpnConfiguration>>;
+  using StringToConfigurationMap = std::map<std::string, VpnConfiguration*>;
+
+  const std::string& extension_id() const { return extension_id_; }
+
+  // Creates a key for |key_to_configuration_map_| as a hash of |extension_id|
+  // and |configuration_name|.
+  static std::string GetKey(const std::string& extension_id,
+                            const std::string& configuration_name);
+
+  // Creates and adds the configuration to the internal store.
+  VpnConfiguration* CreateConfigurationInternal(
+      const std::string& configuration_name);
+
+  // Removes configuration from the internal store and destroys it.
+  void DestroyConfigurationInternal(VpnConfiguration*);
+
+  // Callback used to indicate that configuration was successfully created.
+  void OnCreateConfigurationSuccess(SuccessCallback,
+                                    VpnConfiguration*,
+                                    const std::string& service_path,
+                                    const std::string& guid);
+
+  // Callback used to indicate that configuration creation failed.
+  void OnCreateConfigurationFailure(FailureCallback,
+                                    VpnConfiguration*,
+                                    const std::string& error_name);
+
+  // Callback used to indicate that removing a configuration succeeded.
+  void OnRemoveConfigurationSuccess(SuccessCallback);
+
+  // Callback used to indicate that removing a configuration failed.
+  void OnRemoveConfigurationFailure(FailureCallback,
+                                    const std::string& error_name);
+
+  void SetActiveConfiguration(VpnConfiguration*);
+
+  const std::string extension_id_;
+
+  // Owns all configurations. Key is a hash of |extension_id| and
+  // |configuration_name|.
+  StringToOwnedConfigurationMap key_to_configuration_map_;
+  // Maps shill service path to unowned configuration.
+  StringToConfigurationMap service_path_to_configuration_map_;
+
+  // Configuration that is currently in use.
+  raw_ptr<VpnConfiguration> active_configuration_ = nullptr;
+
+  base::ScopedObservation<chromeos::NetworkConfigurationHandler,
+                          chromeos::NetworkConfigurationObserver>
+      network_configuration_observer_{this};
+
+  mojo::ReceiverSet<crosapi::mojom::VpnServiceForExtension> receivers_;
+  mojo::RemoteSet<crosapi::mojom::EventObserverForExtension> observers_;
+
+  base::WeakPtrFactory<VpnServiceForExtensionAsh> weak_factory_{this};
+};
+
+class VpnServiceAsh : public crosapi::mojom::VpnService,
+                      public chromeos::NetworkStateHandlerObserver,
+                      public VpnProvidersObserver::Delegate {
+ public:
+  VpnServiceAsh();
+  ~VpnServiceAsh() override;
+
+  VpnServiceAsh(const VpnServiceAsh&) = delete;
+  VpnServiceAsh& operator=(const VpnServiceAsh&) = delete;
+
+  // Binds |receiver| to this instance of VpnServiceAsh.
+  void BindReceiver(mojo::PendingReceiver<crosapi::mojom::VpnService> receiver);
+
+  // crosapi::mojom::VpnService:
+  void RegisterVpnServiceForExtension(
+      const std::string& extension_id,
+      mojo::PendingReceiver<crosapi::mojom::VpnServiceForExtension> receiver,
+      mojo::PendingRemote<crosapi::mojom::EventObserverForExtension> observer)
+      override;
+  void MaybeFailActiveConnectionAndDestroyConfigurations(
+      const std::string& extension_id,
+      bool destroy_configurations) override;
+
+  // chromeos::NetworkStateHandlerObserver:
+  void NetworkListChanged() override;
+
+  // VpnProvidersObserver::Delegate:
+  void OnVpnExtensionsChanged(
+      base::flat_set<std::string> vpn_extensions) override;
+
+ private:
+  friend class chromeos::VpnProviderApiTest;
+  friend class VpnServiceForExtensionAsh;
+
+  // Callback for
+  // chromeos::NetworkConfigurationHandler::GetShillProperties(...); parses
+  // the |configuration_properties| dictionary and tries to add a new
+  // configuration provided that it belongs to some enabled extension.
+  void OnGetShillProperties(
+      const std::string& service_path,
+      absl::optional<base::Value> configuration_properties);
+
+  // Ids of enabled vpn extensions.
+  base::flat_set<std::string> vpn_extensions_;
+
+  base::ScopedObservation<chromeos::NetworkStateHandler,
+                          chromeos::NetworkStateHandlerObserver>
+      network_state_handler_observer_{this};
+
+  // Supports any number of receivers.
+  mojo::ReceiverSet<crosapi::mojom::VpnService> receivers_;
+
+  // Maps |extension_id| to a dedicated service for that extension.
+  // We do not remove entries from this map due to various ash/lacros corner
+  // cases.
+  base::flat_map<std::string, std::unique_ptr<VpnServiceForExtensionAsh>>
+      extension_id_to_service_;
+
+  std::unique_ptr<VpnProvidersObserver> vpn_providers_observer_;
+
+  base::WeakPtrFactory<VpnServiceAsh> weak_factory_{this};
+};
+
+class VpnServiceForExtensionAsh::VpnConfiguration
+    : public chromeos::ShillThirdPartyVpnObserver {
+ public:
+  virtual const std::string& configuration_name() const = 0;
+  virtual const std::string& key() const = 0;
+  virtual const std::string& object_path() const = 0;
+
+  virtual const absl::optional<std::string>& service_path() const = 0;
+  virtual void set_service_path(std::string) = 0;
+
+  virtual void BindPepperVpnProxyObserver(
+      mojo::PendingRemote<crosapi::mojom::PepperVpnProxyObserver>) = 0;
+};
+
+}  // namespace crosapi
+
+#endif  // CHROME_BROWSER_ASH_CROSAPI_VPN_SERVICE_ASH_H_
diff --git a/chrome/browser/ash/printing/bulk_printers_calculator.cc b/chrome/browser/ash/printing/bulk_printers_calculator.cc
index 702883b..7a85e54 100644
--- a/chrome/browser/ash/printing/bulk_printers_calculator.cc
+++ b/chrome/browser/ash/printing/bulk_printers_calculator.cc
@@ -69,7 +69,7 @@
     return nullptr;
   }
 
-  base::Value::ConstListView printer_list = json_blob.GetListDeprecated();
+  const base::Value::List& printer_list = json_blob.GetList();
   if (printer_list.size() > kMaxRecords) {
     LOG(WARNING) << "Too many records in printers policy: "
                  << printer_list.size();
diff --git a/chrome/browser/ash/printing/calculators_policies_binder.cc b/chrome/browser/ash/printing/calculators_policies_binder.cc
index 24eee9c..d52d515 100644
--- a/chrome/browser/ash/printing/calculators_policies_binder.cc
+++ b/chrome/browser/ash/printing/calculators_policies_binder.cc
@@ -41,7 +41,7 @@
     return string_list;
   }
 
-  for (const base::Value& value : list->GetListDeprecated()) {
+  for (const base::Value& value : list->GetList()) {
     if (value.is_string()) {
       string_list.push_back(value.GetString());
     }
@@ -107,11 +107,7 @@
   }
 
   std::vector<std::string> GetStringList(const char* name) const override {
-    const base::ListValue* list;
-    if (!settings_->GetList(name, &list)) {
-      list = nullptr;
-    }
-    return ConvertToVector(list);
+    return ConvertToVector(settings_->GetPref(name));
   }
 
  private:
diff --git a/chrome/browser/ash/printing/enterprise_printers_provider.cc b/chrome/browser/ash/printing/enterprise_printers_provider.cc
index 63db3f7..ca0484f 100644
--- a/chrome/browser/ash/printing/enterprise_printers_provider.cc
+++ b/chrome/browser/ash/printing/enterprise_printers_provider.cc
@@ -32,7 +32,7 @@
 std::vector<std::string> ConvertToVector(const base::Value* list) {
   std::vector<std::string> string_list;
   if (list && list->is_list()) {
-    for (const base::Value& value : list->GetListDeprecated()) {
+    for (const base::Value& value : list->GetList()) {
       if (value.is_string()) {
         string_list.push_back(value.GetString());
       }
diff --git a/chrome/browser/ash/printing/enterprise_printers_provider_unittest.cc b/chrome/browser/ash/printing/enterprise_printers_provider_unittest.cc
index 76575cf96..11b014a3 100644
--- a/chrome/browser/ash/printing/enterprise_printers_provider_unittest.cc
+++ b/chrome/browser/ash/printing/enterprise_printers_provider_unittest.cc
@@ -89,16 +89,16 @@
     base::RunLoop().RunUntilIdle();
   }
 
-  void SetPolicyPrinters(const std::vector<std::string>& printer_json_blobs) {
-    auto value = std::make_unique<base::ListValue>();
-    for (const std::string& blob : printer_json_blobs) {
-      value->Append(blob);
-    }
+  void SetPolicyPrinters(std::vector<std::string> printer_json_blobs) {
+    base::Value::List value;
+    for (std::string& blob : printer_json_blobs)
+      value.Append(std::move(blob));
 
     sync_preferences::TestingPrefServiceSyncable* prefs =
         profile_.GetTestingPrefService();
     // TestingPrefSyncableService assumes ownership of |value|.
-    prefs->SetManagedPref(prefs::kRecommendedPrinters, std::move(value));
+    prefs->SetManagedPref(prefs::kRecommendedPrinters,
+                          base::Value(std::move(value)));
   }
 
   // Must outlive |profile_|.
diff --git a/chrome/browser/ash/printing/oauth2/authorization_server_data_unittest.cc b/chrome/browser/ash/printing/oauth2/authorization_server_data_unittest.cc
index 458ac166..ea4d1ea 100644
--- a/chrome/browser/ash/printing/oauth2/authorization_server_data_unittest.cc
+++ b/chrome/browser/ash/printing/oauth2/authorization_server_data_unittest.cc
@@ -29,11 +29,11 @@
     const std::string& value) {
   auto it = value_dict.find(name);
   ASSERT_NE(it, value_dict.end());
-  ASSERT_EQ(it->second.type(), base::Value::Type::LIST);
-  auto nodeAsList = base::Value::AsListValue(it->second).GetListDeprecated();
-  ASSERT_EQ(nodeAsList.size(), 1);
-  ASSERT_TRUE(nodeAsList.front().is_string());
-  EXPECT_EQ(nodeAsList.front().GetString(), value);
+  ASSERT_TRUE(it->second.is_list());
+  const base::Value::List& list = it->second.GetList();
+  ASSERT_EQ(list.size(), 1);
+  ASSERT_TRUE(list.front().is_string());
+  EXPECT_EQ(list.front().GetString(), value);
 }
 
 TEST(PrintingOAuth2AuthorizationServerDataTest, InitialState) {
diff --git a/chrome/browser/ash/printing/oauth2/http_exchange.cc b/chrome/browser/ash/printing/oauth2/http_exchange.cc
index a210c923..640757c 100644
--- a/chrome/browser/ash/printing/oauth2/http_exchange.cc
+++ b/chrome/browser/ash/printing/oauth2/http_exchange.cc
@@ -267,15 +267,15 @@
                                             bool required,
                                             const std::string& value) {
   base::Value* node = FindNode(name, required);
-  if (node == nullptr) {
+  if (!node) {
     return !required;
   }
   if (!node->is_list()) {
     error_msg_ = "Field " + name + " must be an array.";
     return false;
   }
-  auto nodeAsList = base::Value::AsListValue(*node).GetListDeprecated();
-  for (auto& element : nodeAsList) {
+  const auto& node_as_list = node->GetList();
+  for (auto& element : node_as_list) {
     if (element.is_string() && element.GetString() == value) {
       // Success!
       return true;
@@ -290,19 +290,19 @@
     bool required,
     const std::vector<std::string>& value) {
   base::Value* node = FindNode(name, required);
-  if (node == nullptr) {
+  if (!node) {
     return !required;
   }
   if (!node->is_list()) {
     error_msg_ = "Field " + name + " must be an array";
     return false;
   }
-  auto nodeAsList = base::Value::AsListValue(*node).GetListDeprecated();
-  if (nodeAsList.size() == value.size()) {
+  const base::Value::List& node_as_list = node->GetList();
+  if (node_as_list.size() == value.size()) {
     // Compares the vectors, element by element.
     bool are_equal = true;
     for (size_t i = 0; i < value.size() && are_equal; ++i) {
-      const auto& element = nodeAsList[i];
+      const auto& element = node_as_list[i];
       if (!element.is_string() || element.GetString() != value[i]) {
         are_equal = false;
       }
@@ -329,14 +329,14 @@
                                   bool required,
                                   std::string* value) {
   base::Value* node = FindNode(name, required);
-  if (node == nullptr) {
+  if (!node) {
     return !required;
   }
   if (!node->is_string()) {
     error_msg_ = "Field " + name + " must be a string";
     return false;
   }
-  if (value != nullptr) {
+  if (value) {
     *value = node->GetString();
   }
   return true;
@@ -346,7 +346,7 @@
                                      bool required,
                                      const std::string& value) {
   base::Value* node = FindNode(name, required);
-  if (node == nullptr) {
+  if (!node) {
     return !required;
   }
   if (!node->is_string()) {
@@ -364,7 +364,7 @@
                                bool required,
                                GURL* value) {
   base::Value* node = FindNode(name, required);
-  if (node == nullptr) {
+  if (!node) {
     return !required;
   }
   if (!node->is_string()) {
@@ -374,7 +374,7 @@
   GURL gurl(node->GetString());
   if (gurl.is_valid() && gurl.IsStandard() && gurl.scheme() == "https") {
     // Success!
-    if (value != nullptr) {
+    if (value) {
       *value = gurl;
     }
     return true;
@@ -387,7 +387,7 @@
                                   bool required,
                                   const GURL& value) {
   base::Value* node = FindNode(name, required);
-  if (node == nullptr) {
+  if (!node) {
     return !required;
   }
   if (!node->is_string()) {
@@ -407,7 +407,7 @@
 
 base::Value* HttpExchange::FindNode(const std::string& name, bool required) {
   base::Value* value = content_.FindKey(name);
-  if (required && value == nullptr) {
+  if (required && !value) {
     error_msg_ = "Field " + name + " is missing";
   }
   return value;
diff --git a/chrome/browser/ash/printing/print_servers_provider.cc b/chrome/browser/ash/printing/print_servers_provider.cc
index f54599ab..7ffe2e7 100644
--- a/chrome/browser/ash/printing/print_servers_provider.cc
+++ b/chrome/browser/ash/printing/print_servers_provider.cc
@@ -69,8 +69,8 @@
 
   std::set<std::string> print_server_ids;
   std::set<GURL> print_server_urls;
-  task_data.servers.reserve(json_blob.GetListDeprecated().size());
-  for (const base::Value& val : json_blob.GetListDeprecated()) {
+  task_data.servers.reserve(json_blob.GetList().size());
+  for (const base::Value& val : json_blob.GetList()) {
     if (!val.is_dict()) {
       LOG(WARNING) << "Entry in print servers policy skipped. "
                    << "Not a dictionary.";
@@ -79,7 +79,7 @@
     const std::string* id = val.FindStringKey("id");
     const std::string* url = val.FindStringKey("url");
     const std::string* name = val.FindStringKey("display_name");
-    if (id == nullptr || url == nullptr || name == nullptr) {
+    if (!id || !url || !name) {
       LOG(WARNING) << "Entry in print servers policy skipped. The following "
                    << "fields are required: id, url, display_name.";
       continue;
@@ -237,9 +237,7 @@
     if (last_processed_task_ != last_received_task_)
       return false;
     // The case when prefs are not set.
-    if (prefs_ == nullptr)
-      return false;
-    return true;
+    return !!prefs_;
   }
 
   // Called when a new allowlist is available.
@@ -248,9 +246,9 @@
     // Fetch and parse the allowlist.
     const PrefService::Preference* pref =
         prefs_->FindPreference(allowlist_pref_);
-    if (pref != nullptr && !pref->IsDefaultValue()) {
+    if (pref && !pref->IsDefaultValue()) {
       allowlist_ = std::set<std::string>();
-      for (const base::Value& value : pref->GetValue()->GetListDeprecated()) {
+      for (const base::Value& value : pref->GetValue()->GetList()) {
         if (value.is_string()) {
           allowlist_.value().insert(value.GetString());
         }
@@ -267,11 +265,11 @@
   // Recalculate the value of |result_servers_| field. Returns true if the new
   // list is different than the previous one.
   bool CalculateResultantList() {
-    std::vector<PrintServer> new_servers;
-    if (prefs_ == nullptr) {
+    if (!prefs_) {
       // |result_servers_| remains empty when prefs is not set.
       return false;
     }
+    std::vector<PrintServer> new_servers;
     if (!allowlist_.has_value()) {
       new_servers = servers_;
     } else {
diff --git a/chrome/browser/ash/printing/print_servers_provider_unittest.cc b/chrome/browser/ash/printing/print_servers_provider_unittest.cc
index 0aae3a6..088193a 100644
--- a/chrome/browser/ash/printing/print_servers_provider_unittest.cc
+++ b/chrome/browser/ash/printing/print_servers_provider_unittest.cc
@@ -301,17 +301,18 @@
       std::make_unique<std::string>(kPrintServersPolicyJson1));
   // Apply an empty allowlist on the top.
   pref_service_.SetManagedPref(kAllowlistPrefName,
-                               std::make_unique<base::ListValue>());
+                               base::Value(base::Value::Type::LIST));
   // Check the resultant list - is is supposed to be empty.
   task_environment_.RunUntilIdle();
   ASSERT_FALSE(obs.GetCalls().empty());
   EXPECT_TRUE(obs.GetCalls().back().complete);
   EXPECT_TRUE(obs.GetCalls().back().servers.empty());
   // Apply allowlist.
-  auto value = std::make_unique<base::ListValue>();
-  for (const std::string& id : {"id3", "idX", "id1"})
-    value->Append(base::Value(id));
-  pref_service_.SetManagedPref(kAllowlistPrefName, std::move(value));
+  base::Value::List value;
+  for (std::string id : {"id3", "idX", "id1"})
+    value.Append(std::move(id));
+  pref_service_.SetManagedPref(kAllowlistPrefName,
+                               base::Value(std::move(value)));
   // Check the resultant list.
   task_environment_.RunUntilIdle();
   EXPECT_TRUE(obs.GetCalls().back().complete);
diff --git a/chrome/browser/chromeos/extensions/printing_metrics/print_job_finished_event_dispatcher_unittest.cc b/chrome/browser/chromeos/extensions/printing_metrics/print_job_finished_event_dispatcher_unittest.cc
index 9461d69..7b25c01 100644
--- a/chrome/browser/chromeos/extensions/printing_metrics/print_job_finished_event_dispatcher_unittest.cc
+++ b/chrome/browser/chromeos/extensions/printing_metrics/print_job_finished_event_dispatcher_unittest.cc
@@ -36,13 +36,13 @@
 
   const extensions::Event& event = *iter->second;
   if (!event.event_args || !event.event_args->is_list() ||
-      event.event_args->GetListDeprecated().size() != 1u) {
+      event.event_args->GetList().size() != 1u) {
     ADD_FAILURE() << "Invalid event args";
     return nullptr;
   }
 
   return extensions::api::printing_metrics::PrintJobInfo::FromValue(
-      event.event_args->GetListDeprecated()[0]);
+      event.event_args->GetList()[0]);
 }
 
 // Creates a new MockPrintJobHistoryService for the given |context|.
diff --git a/chrome/browser/chromeos/extensions/printing_metrics/printing_metrics_api_unittest.cc b/chrome/browser/chromeos/extensions/printing_metrics/printing_metrics_api_unittest.cc
index f58742f..4e26457 100644
--- a/chrome/browser/chromeos/extensions/printing_metrics/printing_metrics_api_unittest.cc
+++ b/chrome/browser/chromeos/extensions/printing_metrics/printing_metrics_api_unittest.cc
@@ -108,7 +108,7 @@
 
   ASSERT_TRUE(result);
   ASSERT_TRUE(result->is_list());
-  EXPECT_TRUE(result->GetListDeprecated().empty());
+  EXPECT_TRUE(result->GetList().empty());
 }
 
 // Test that calling |printingMetrics.getPrintJobs()| returns the mock print
@@ -122,10 +122,9 @@
 
   ASSERT_TRUE(result);
   ASSERT_TRUE(result->is_list());
-  ASSERT_EQ(1u, result->GetListDeprecated().size());
+  ASSERT_EQ(1u, result->GetList().size());
   std::unique_ptr<api::printing_metrics::PrintJobInfo> print_job_info =
-      api::printing_metrics::PrintJobInfo::FromValue(
-          result->GetListDeprecated()[0]);
+      api::printing_metrics::PrintJobInfo::FromValue(result->GetList()[0]);
   EXPECT_TRUE(print_job_info);
   EXPECT_EQ(kTitle1, print_job_info->title);
   EXPECT_EQ(api::printing_metrics::PRINT_JOB_STATUS_FAILED,
@@ -144,15 +143,13 @@
 
   ASSERT_TRUE(result);
   ASSERT_TRUE(result->is_list());
-  ASSERT_EQ(2u, result->GetListDeprecated().size());
+  ASSERT_EQ(2u, result->GetList().size());
   std::unique_ptr<api::printing_metrics::PrintJobInfo> print_job_info1 =
-      api::printing_metrics::PrintJobInfo::FromValue(
-          result->GetListDeprecated()[0]);
+      api::printing_metrics::PrintJobInfo::FromValue(result->GetList()[0]);
   EXPECT_TRUE(print_job_info1);
   EXPECT_EQ(kTitle1, print_job_info1->title);
   std::unique_ptr<api::printing_metrics::PrintJobInfo> print_job_info2 =
-      api::printing_metrics::PrintJobInfo::FromValue(
-          result->GetListDeprecated()[1]);
+      api::printing_metrics::PrintJobInfo::FromValue(result->GetList()[1]);
   EXPECT_TRUE(print_job_info2);
   EXPECT_EQ(kTitle2, print_job_info2->title);
 }
diff --git a/chrome/browser/chromeos/extensions/vpn_provider/BUILD.gn b/chrome/browser/chromeos/extensions/vpn_provider/BUILD.gn
index 79675a7..b1c1456 100644
--- a/chrome/browser/chromeos/extensions/vpn_provider/BUILD.gn
+++ b/chrome/browser/chromeos/extensions/vpn_provider/BUILD.gn
@@ -23,10 +23,10 @@
 
   deps = [
     "//base",
+    "//chrome/browser/ash/crosapi",
     "//chrome/common/extensions/api",
-    "//chromeos/dbus",
+    "//chromeos/crosapi/mojom",
     "//chromeos/login/login_state",
-    "//chromeos/network",
     "//components/keyed_service/content",
     "//content/public/browser",
     "//extensions/browser",
diff --git a/chrome/browser/chromeos/extensions/vpn_provider/vpn_provider_api.cc b/chrome/browser/chromeos/extensions/vpn_provider/vpn_provider_api.cc
index 18fadc66e3..20106e546 100644
--- a/chrome/browser/chromeos/extensions/vpn_provider/vpn_provider_api.cc
+++ b/chrome/browser/chromeos/extensions/vpn_provider/vpn_provider_api.cc
@@ -305,8 +305,13 @@
     return RespondNow(Error("Invalid profile."));
   }
 
+  // Cannot be VPN_CONNECTION_STATE_NONE at this point -- see !params guard
+  // above.
+  bool connection_success =
+      params->state ==
+      api_vpn::VpnConnectionState::VPN_CONNECTION_STATE_CONNECTED;
   service->NotifyConnectionStateChanged(
-      extension_id(), params->state,
+      extension_id(), connection_success,
       base::BindOnce(&VpnProviderNotifyConnectionStateChangedFunction::
                          SignalCallCompletionSuccess,
                      this),
diff --git a/chrome/browser/chromeos/extensions/vpn_provider/vpn_service.cc b/chrome/browser/chromeos/extensions/vpn_provider/vpn_service.cc
index 80cea51..e9b7956 100644
--- a/chrome/browser/chromeos/extensions/vpn_provider/vpn_service.cc
+++ b/chrome/browser/chromeos/extensions/vpn_provider/vpn_service.cc
@@ -4,38 +4,24 @@
 
 #include "chrome/browser/chromeos/extensions/vpn_provider/vpn_service.h"
 
-#include <stdint.h>
 #include <utility>
-#include <vector>
 
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/containers/contains.h"
-#include "base/guid.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/task/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "chrome/browser/chromeos/extensions/vpn_provider/vpn_service_interface.h"
-#include "chromeos/dbus/shill/shill_third_party_vpn_driver_client.h"
-#include "chromeos/dbus/shill/shill_third_party_vpn_observer.h"
-#include "chromeos/network/network_configuration_handler.h"
-#include "chromeos/network/network_profile.h"
-#include "chromeos/network/network_profile_handler.h"
-#include "chromeos/network/network_state.h"
-#include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_type_pattern.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/pepper_vpn_provider_resource_host_proxy.h"
 #include "content/public/browser/vpn_service_proxy.h"
-#include "crypto/sha2.h"
 #include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_event_histogram_value.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/unloaded_extension_reason.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/cros_system_api/dbus/service_constants.h"
+
+#include "chrome/browser/ash/crosapi/crosapi_ash.h"
+#include "chrome/browser/ash/crosapi/crosapi_manager.h"
+#include "chrome/browser/ash/crosapi/vpn_service_ash.h"
 
 namespace chromeos {
 
@@ -43,125 +29,42 @@
 
 namespace api_vpn = extensions::api::vpn_provider;
 
-void DoNothingFailureCallback(const std::string& error_name,
-                              const std::string& error_message) {
-  LOG(ERROR) << error_name << ": " << error_message;
+void RunSuccessCallback(chromeos::VpnService::SuccessCallback success) {
+  std::move(success).Run();
 }
 
-void RunWarningCallback(
-    extensions::api::VpnServiceInterface::SuccessCallback callback,
-    const std::string& /*warning*/) {
-  std::move(callback).Run();
+void RunFailureCallback(chromeos::VpnService::FailureCallback failure,
+                        const absl::optional<std::string>& error_name,
+                        const absl::optional<std::string>& error_message) {
+  std::move(failure).Run(error_name.value_or(std::string{}),
+                         error_message.value_or(std::string{}));
+}
+
+using SuccessOrFailureCallback =
+    base::OnceCallback<void(crosapi::mojom::VpnErrorResponsePtr)>;
+
+// crosapi::mojom::VpnService expects a single callback, whereas the API is
+// designed to pass in two (one for success, one for failure). This function
+// glues the two callbacks in one; for the reverse transformation see
+// chrome/browser/ash/crosapi/vpn_service_ash.cc
+SuccessOrFailureCallback AdaptCallback(
+    chromeos::VpnService::SuccessCallback success,
+    chromeos::VpnService::FailureCallback failure) {
+  return base::BindOnce(
+      [](chromeos::VpnService::SuccessCallback success,
+         chromeos::VpnService::FailureCallback failure,
+         crosapi::mojom::VpnErrorResponsePtr error) {
+        if (error) {
+          RunFailureCallback(std::move(failure), error->name, error->message);
+        } else {
+          RunSuccessCallback(std::move(success));
+        }
+      },
+      std::move(success), std::move(failure));
 }
 
 }  // namespace
 
-class VpnService::VpnConfiguration : public ShillThirdPartyVpnObserver {
- public:
-  VpnConfiguration(const std::string& extension_id,
-                   const std::string& configuration_name,
-                   const std::string& key,
-                   base::WeakPtr<VpnService> vpn_service);
-
-  VpnConfiguration(const VpnConfiguration&) = delete;
-  VpnConfiguration& operator=(const VpnConfiguration&) = delete;
-
-  ~VpnConfiguration() override;
-
-  const std::string& extension_id() const { return extension_id_; }
-  const std::string& configuration_name() const { return configuration_name_; }
-  const std::string& key() const { return key_; }
-  const std::string& service_path() const { return service_path_; }
-  void set_service_path(const std::string& service_path) {
-    service_path_ = service_path;
-  }
-  const std::string& object_path() const { return object_path_; }
-  void set_pepper_proxy(
-      std::unique_ptr<content::PepperVpnProviderResourceHostProxy>
-          pepper_vpn_provider_proxy) {
-    pepper_vpn_provider_proxy_ = std::move(pepper_vpn_provider_proxy);
-  }
-
-  // ShillThirdPartyVpnObserver:
-  void OnPacketReceived(const std::vector<char>& data) override;
-  void OnPlatformMessage(uint32_t message) override;
-
- private:
-  const std::string extension_id_;
-  const std::string configuration_name_;
-  const std::string key_;
-  const std::string object_path_;
-
-  std::unique_ptr<content::PepperVpnProviderResourceHostProxy>
-      pepper_vpn_provider_proxy_;
-
-  std::string service_path_;
-
-  base::WeakPtr<VpnService> vpn_service_;
-};
-
-VpnService::VpnConfiguration::VpnConfiguration(
-    const std::string& extension_id,
-    const std::string& configuration_name,
-    const std::string& key,
-    base::WeakPtr<VpnService> vpn_service)
-    : extension_id_(extension_id),
-      configuration_name_(configuration_name),
-      key_(key),
-      object_path_(shill::kObjectPathBase + key_),
-      vpn_service_(vpn_service) {}
-
-VpnService::VpnConfiguration::~VpnConfiguration() {}
-
-void VpnService::VpnConfiguration::OnPacketReceived(
-    const std::vector<char>& data) {
-  if (!vpn_service_) {
-    return;
-  }
-  // Pass packet to the Pepper API if the connection is bound to it.
-  if (pepper_vpn_provider_proxy_) {
-    pepper_vpn_provider_proxy_->SendOnPacketReceived(data);
-  } else {
-    auto event_args = api_vpn::OnPacketReceived::Create(
-        std::vector<uint8_t>(data.begin(), data.end()));
-    vpn_service_->SendSignalToExtension(
-        extension_id_, extensions::events::VPN_PROVIDER_ON_PACKET_RECEIVED,
-        api_vpn::OnPacketReceived::kEventName, std::move(event_args));
-  }
-}
-
-void VpnService::VpnConfiguration::OnPlatformMessage(uint32_t message) {
-  if (!vpn_service_) {
-    return;
-  }
-  DCHECK_GE(api_vpn::PLATFORM_MESSAGE_LAST, message);
-
-  api_vpn::PlatformMessage platform_message =
-      static_cast<api_vpn::PlatformMessage>(message);
-
-  if (platform_message == api_vpn::PLATFORM_MESSAGE_CONNECTED) {
-    vpn_service_->SetActiveConfiguration(this);
-  } else if (platform_message == api_vpn::PLATFORM_MESSAGE_DISCONNECTED ||
-             platform_message == api_vpn::PLATFORM_MESSAGE_ERROR) {
-    vpn_service_->SetActiveConfiguration(nullptr);
-
-    // Disconnect Pepper-bound configuration.
-    if (pepper_vpn_provider_proxy_) {
-      pepper_vpn_provider_proxy_->SendOnUnbind();
-      pepper_vpn_provider_proxy_.reset();
-    }
-  }
-
-  // TODO(kaliamoorthi): Update the lower layers to get the error message and
-  // pass in the error instead of std::string().
-  auto event_args = api_vpn::OnPlatformMessage::Create(
-      configuration_name_, platform_message, std::string());
-
-  vpn_service_->SendSignalToExtension(
-      extension_id_, extensions::events::VPN_PROVIDER_ON_PLATFORM_MESSAGE,
-      api_vpn::OnPlatformMessage::kEventName, std::move(event_args));
-}
-
 class VpnService::VpnServiceProxyImpl : public content::VpnServiceProxy {
  public:
   explicit VpnServiceProxyImpl(base::WeakPtr<VpnService> vpn_service);
@@ -192,20 +95,19 @@
 
 void VpnService::VpnServiceProxyImpl::Bind(
     const std::string& extension_id,
-    const std::string& configuration_id,
+    const std::string& /*configuration_id*/,
     const std::string& configuration_name,
     SuccessCallback success,
     FailureCallback failure,
     std::unique_ptr<content::PepperVpnProviderResourceHostProxy>
         pepper_vpn_provider_proxy) {
   if (!vpn_service_) {
-    NOTREACHED();
     return;
   }
 
-  vpn_service_->Bind(extension_id, configuration_id, configuration_name,
-                     std::move(success), std::move(failure),
-                     std::move(pepper_vpn_provider_proxy));
+  vpn_service_->BindPepperVpnProxy(extension_id, configuration_name,
+                                   std::move(success), std::move(failure),
+                                   std::move(pepper_vpn_provider_proxy));
 }
 
 void VpnService::VpnServiceProxyImpl::SendPacket(
@@ -214,7 +116,6 @@
     SuccessCallback success,
     FailureCallback failure) {
   if (!vpn_service_) {
-    NOTREACHED();
     return;
   }
 
@@ -222,463 +123,247 @@
                            std::move(failure));
 }
 
-VpnService::VpnService(
-    content::BrowserContext* browser_context,
-    const std::string& userid_hash,
-    extensions::ExtensionRegistry* extension_registry,
-    extensions::EventRouter* event_router,
-    ShillThirdPartyVpnDriverClient* shill_client,
-    NetworkConfigurationHandler* network_configuration_handler,
-    NetworkProfileHandler* network_profile_handler,
-    NetworkStateHandler* network_state_handler)
-    : browser_context_(browser_context),
-      userid_hash_(userid_hash),
-      extension_registry_(extension_registry),
-      event_router_(event_router),
-      shill_client_(shill_client),
-      network_configuration_handler_(network_configuration_handler),
-      network_profile_handler_(network_profile_handler),
-      network_state_handler_(network_state_handler),
-      active_configuration_(nullptr) {
-  extension_registry_->AddObserver(this);
-  network_state_handler_->AddObserver(this, FROM_HERE);
-  network_configuration_handler_->AddObserver(this);
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(&VpnService::NetworkListChanged,
-                                weak_factory_.GetWeakPtr()));
+VpnServiceForExtension::VpnServiceForExtension(
+    const std::string& extension_id,
+    content::BrowserContext* browser_context)
+    : extension_id_(extension_id), browser_context_(browser_context) {
+  VpnService::GetVpnService()->RegisterVpnServiceForExtension(
+      extension_id, vpn_service_.BindNewPipeAndPassReceiver(),
+      receiver_.BindNewPipeAndPassRemote());
 }
 
-VpnService::~VpnService() {
-  network_configuration_handler_->RemoveObserver(this);
-  network_state_handler_->RemoveObserver(this, FROM_HERE);
-  extension_registry_->RemoveObserver(this);
+VpnServiceForExtension::~VpnServiceForExtension() = default;
+
+void VpnServiceForExtension::OnAddDialog() {
+  DispatchEvent(std::make_unique<extensions::Event>(
+      extensions::events::HistogramValue::VPN_PROVIDER_ON_UI_EVENT,
+      api_vpn::OnUIEvent::kEventName,
+      api_vpn::OnUIEvent::Create(api_vpn::UI_EVENT_SHOWADDDIALOG,
+                                 std::string()),
+      browser_context_));
 }
 
+void VpnServiceForExtension::OnConfigureDialog(
+    const std::string& configuration_name) {
+  DispatchEvent(std::make_unique<extensions::Event>(
+      extensions::events::HistogramValue::VPN_PROVIDER_ON_UI_EVENT,
+      api_vpn::OnUIEvent::kEventName,
+      api_vpn::OnUIEvent::Create(api_vpn::UI_EVENT_SHOWCONFIGUREDIALOG,
+                                 configuration_name),
+      browser_context_));
+}
+
+void VpnServiceForExtension::OnConfigRemoved(
+    const std::string& configuration_name) {
+  DispatchEvent(std::make_unique<extensions::Event>(
+      extensions::events::HistogramValue::VPN_PROVIDER_ON_CONFIG_REMOVED,
+      api_vpn::OnConfigRemoved::kEventName,
+      api_vpn::OnConfigRemoved::Create(configuration_name), browser_context_));
+}
+
+void VpnServiceForExtension::OnPlatformMessage(
+    const std::string& configuration_name,
+    int32_t platform_message,
+    const absl::optional<std::string>& error) {
+  DispatchEvent(std::make_unique<extensions::Event>(
+      extensions::events::VPN_PROVIDER_ON_PLATFORM_MESSAGE,
+      api_vpn::OnPlatformMessage::kEventName,
+      api_vpn::OnPlatformMessage::Create(
+          configuration_name,
+          static_cast<api_vpn::PlatformMessage>(platform_message),
+          error.value_or(std::string{})),
+      browser_context_));
+}
+
+void VpnServiceForExtension::OnPacketReceived(
+    const std::vector<uint8_t>& data) {
+  DispatchEvent(std::make_unique<extensions::Event>(
+      extensions::events::VPN_PROVIDER_ON_PACKET_RECEIVED,
+      api_vpn::OnPacketReceived::kEventName,
+      api_vpn::OnPacketReceived::Create(
+          std::vector<uint8_t>(data.begin(), data.end())),
+      browser_context_));
+}
+
+void VpnServiceForExtension::DispatchEvent(
+    std::unique_ptr<extensions::Event> event) const {
+  extensions::EventRouter::Get(browser_context_)
+      ->DispatchEventToExtension(extension_id_, std::move(event));
+}
+
+VpnService::VpnService(content::BrowserContext* browser_context)
+    : browser_context_(browser_context) {
+  extension_registry_observer_.Observe(
+      extensions::ExtensionRegistry::Get(browser_context));
+}
+
+VpnService::~VpnService() = default;
+
 void VpnService::SendShowAddDialogToExtension(const std::string& extension_id) {
-  SendSignalToExtension(extension_id,
-                        extensions::events::VPN_PROVIDER_ON_UI_EVENT,
-                        api_vpn::OnUIEvent::kEventName,
-                        api_vpn::OnUIEvent::Create(
-                            api_vpn::UI_EVENT_SHOWADDDIALOG, std::string()));
+  GetVpnServiceForExtension(extension_id)->DispatchAddDialogEvent();
 }
 
 void VpnService::SendShowConfigureDialogToExtension(
     const std::string& extension_id,
     const std::string& configuration_name) {
-  SendSignalToExtension(
-      extension_id, extensions::events::VPN_PROVIDER_ON_UI_EVENT,
-      api_vpn::OnUIEvent::kEventName,
-      api_vpn::OnUIEvent::Create(api_vpn::UI_EVENT_SHOWCONFIGUREDIALOG,
-                                 configuration_name));
-}
-
-void VpnService::SendPlatformError(const std::string& extension_id,
-                                   const std::string& configuration_name,
-                                   const std::string& error_message) {
-  SendSignalToExtension(
-      extension_id, extensions::events::VPN_PROVIDER_ON_PLATFORM_MESSAGE,
-      api_vpn::OnPlatformMessage::kEventName,
-      api_vpn::OnPlatformMessage::Create(
-          configuration_name, api_vpn::PLATFORM_MESSAGE_ERROR, error_message));
-}
-
-std::string VpnService::GetKey(const std::string& extension_id,
-                               const std::string& name) {
-  const std::string key = crypto::SHA256HashString(extension_id + name);
-  return base::HexEncode(key.data(), key.size());
-}
-
-void VpnService::OnConfigurationRemoved(const std::string& service_path,
-                                        const std::string& guid) {
-  if (service_path_to_configuration_map_.find(service_path) ==
-      service_path_to_configuration_map_.end()) {
-    // Ignore removal of a configuration unknown to VPN service, which means the
-    // configuration was created internally by the platform or already removed
-    // by the extension.
-    return;
-  }
-
-  VpnConfiguration* configuration =
-      service_path_to_configuration_map_[service_path];
-  auto event_args =
-      api_vpn::OnConfigRemoved::Create(configuration->configuration_name());
-  SendSignalToExtension(configuration->extension_id(),
-                        extensions::events::VPN_PROVIDER_ON_CONFIG_REMOVED,
-                        api_vpn::OnConfigRemoved::kEventName,
-                        std::move(event_args));
-
-  DestroyConfigurationInternal(configuration);
-}
-
-void VpnService::OnGetShillProperties(const std::string& service_path,
-                                      absl::optional<base::Value> dictionary) {
-  if (!dictionary || service_path_to_configuration_map_.find(service_path) !=
-                         service_path_to_configuration_map_.end()) {
-    return;
-  }
-  const std::string* vpn_type =
-      dictionary->FindStringPath(shill::kProviderTypeProperty);
-  const std::string* extension_id =
-      dictionary->FindStringPath(shill::kProviderHostProperty);
-  const std::string* type = dictionary->FindStringPath(shill::kTypeProperty);
-  const std::string* configuration_name =
-      dictionary->FindStringPath(shill::kNameProperty);
-  if (!vpn_type || !extension_id || !type || !configuration_name ||
-      *vpn_type != shill::kProviderThirdPartyVpn || *type != shill::kTypeVPN) {
-    return;
-  }
-
-  if (!extension_registry_->GetExtensionById(
-          *extension_id, extensions::ExtensionRegistry::ENABLED)) {
-    // Does not belong to this instance of VpnService.
-    return;
-  }
-
-  const std::string key = GetKey(*extension_id, *configuration_name);
-  VpnConfiguration* configuration =
-      CreateConfigurationInternal(*extension_id, *configuration_name, key);
-  configuration->set_service_path(service_path);
-  service_path_to_configuration_map_[service_path] = configuration;
-  shill_client_->AddShillThirdPartyVpnObserver(configuration->object_path(),
-                                               configuration);
-}
-
-void VpnService::NetworkListChanged() {
-  NetworkStateHandler::NetworkStateList network_list;
-  network_state_handler_->GetVisibleNetworkListByType(NetworkTypePattern::VPN(),
-                                                      &network_list);
-  for (auto* iter : network_list) {
-    if (service_path_to_configuration_map_.find(iter->path()) !=
-        service_path_to_configuration_map_.end()) {
-      continue;
-    }
-
-    network_configuration_handler_->GetShillProperties(
-        iter->path(), base::BindOnce(&VpnService::OnGetShillProperties,
-                                     weak_factory_.GetWeakPtr()));
-  }
+  GetVpnServiceForExtension(extension_id)
+      ->DispatchConfigureDialogEvent(configuration_name);
 }
 
 void VpnService::CreateConfiguration(const std::string& extension_id,
                                      const std::string& configuration_name,
                                      SuccessCallback success,
                                      FailureCallback failure) {
-  if (configuration_name.empty()) {
-    std::move(failure).Run(std::string(),
-                           std::string("Empty name not supported."));
-    return;
-  }
-
-  const std::string key = GetKey(extension_id, configuration_name);
-  if (base::Contains(key_to_configuration_map_, key)) {
-    std::move(failure).Run(std::string(), std::string("Name not unique."));
-    return;
-  }
-
-  const NetworkProfile* profile =
-      network_profile_handler_->GetProfileForUserhash(userid_hash_);
-  if (!profile) {
-    std::move(failure).Run(
-        std::string(),
-        std::string("No user profile for unshared network configuration."));
-    return;
-  }
-
-  VpnConfiguration* configuration =
-      CreateConfigurationInternal(extension_id, configuration_name, key);
-
-  base::Value::Dict properties;
-  properties.Set(shill::kTypeProperty, shill::kTypeVPN);
-  properties.Set(shill::kNameProperty, configuration_name);
-  properties.Set(shill::kProviderHostProperty, extension_id);
-  properties.Set(shill::kObjectPathSuffixProperty, configuration->key());
-  properties.Set(shill::kProviderTypeProperty, shill::kProviderThirdPartyVpn);
-  properties.Set(shill::kProfileProperty, profile->path);
-  properties.Set(shill::kGuidProperty, base::GenerateGUID());
-
-  network_configuration_handler_->CreateShillConfiguration(
-      base::Value(std::move(properties)),
-      base::BindOnce(&VpnService::OnCreateConfigurationSuccess,
-                     weak_factory_.GetWeakPtr(), std::move(success),
-                     configuration),
-      base::BindOnce(&VpnService::OnCreateConfigurationFailure,
-                     weak_factory_.GetWeakPtr(), std::move(failure),
-                     configuration));
+  GetVpnServiceForExtension(extension_id)
+      ->CreateConfiguration(
+          configuration_name,
+          AdaptCallback(std::move(success), std::move(failure)));
 }
 
 void VpnService::DestroyConfiguration(const std::string& extension_id,
                                       const std::string& configuration_name,
                                       SuccessCallback success,
                                       FailureCallback failure) {
-  // The ID is the configuration name for now. This may change in the future.
-  const std::string key = GetKey(extension_id, configuration_name);
-  if (!base::Contains(key_to_configuration_map_, key)) {
-    std::move(failure).Run(std::string(), std::string("Unauthorized access."));
-    return;
-  }
-
-  VpnConfiguration* configuration = key_to_configuration_map_[key].get();
-  const std::string service_path = configuration->service_path();
-  if (service_path.empty()) {
-    std::move(failure).Run(std::string(), std::string("Pending create."));
-    return;
-  }
-  if (active_configuration_ == configuration) {
-    configuration->OnPlatformMessage(api_vpn::PLATFORM_MESSAGE_DISCONNECTED);
-  }
-  DestroyConfigurationInternal(configuration);
-
-  network_configuration_handler_->RemoveConfiguration(
-      service_path,
-      /*remove_confirmer=*/absl::nullopt,
-      base::BindOnce(&VpnService::OnRemoveConfigurationSuccess,
-                     weak_factory_.GetWeakPtr(), std::move(success)),
-      base::BindOnce(&VpnService::OnRemoveConfigurationFailure,
-                     weak_factory_.GetWeakPtr(), std::move(failure)));
+  GetVpnServiceForExtension(extension_id)
+      ->DestroyConfiguration(
+          configuration_name,
+          AdaptCallback(std::move(success), std::move(failure)));
 }
 
 void VpnService::SetParameters(const std::string& extension_id,
                                base::Value::Dict parameters,
                                SuccessCallback success,
                                FailureCallback failure) {
-  if (!DoesActiveConfigurationExistAndIsAccessAuthorized(extension_id)) {
-    std::move(failure).Run(std::string(), std::string("Unauthorized access."));
-    return;
-  }
-
-  shill_client_->SetParameters(
-      active_configuration_->object_path(), base::Value(std::move(parameters)),
-      base::BindOnce(&RunWarningCallback, std::move(success)),
-      std::move(failure));
+  GetVpnServiceForExtension(extension_id)
+      ->SetParameters(std::move(parameters),
+                      AdaptCallback(std::move(success), std::move(failure)));
 }
 
 void VpnService::SendPacket(const std::string& extension_id,
                             const std::vector<char>& data,
                             SuccessCallback success,
                             FailureCallback failure) {
-  if (!DoesActiveConfigurationExistAndIsAccessAuthorized(extension_id)) {
-    std::move(failure).Run(std::string(), std::string("Unauthorized access."));
-    return;
-  }
-
-  if (data.empty()) {
-    std::move(failure).Run(std::string(),
-                           std::string("Can't send an empty packet."));
-    return;
-  }
-
-  shill_client_->SendPacket(active_configuration_->object_path(), data,
-                            std::move(success), std::move(failure));
+  GetVpnServiceForExtension(extension_id)
+      ->SendPacket(std::vector<uint8_t>(data.begin(), data.end()),
+                   AdaptCallback(std::move(success), std::move(failure)));
 }
 
 void VpnService::NotifyConnectionStateChanged(const std::string& extension_id,
-                                              api_vpn::VpnConnectionState state,
+                                              bool connection_success,
                                               SuccessCallback success,
                                               FailureCallback failure) {
-  if (!DoesActiveConfigurationExistAndIsAccessAuthorized(extension_id)) {
-    std::move(failure).Run(std::string(), std::string("Unauthorized access."));
-    return;
-  }
-
-  shill_client_->UpdateConnectionState(active_configuration_->object_path(),
-                                       static_cast<uint32_t>(state),
-                                       std::move(success), std::move(failure));
+  GetVpnServiceForExtension(extension_id)
+      ->NotifyConnectionStateChanged(
+          connection_success,
+          AdaptCallback(std::move(success), std::move(failure)));
 }
 
-bool VpnService::VerifyConfigExistsForTesting(
-    const std::string& extension_id,
-    const std::string& configuration_name) {
-  const std::string key = GetKey(extension_id, configuration_name);
-  return base::Contains(key_to_configuration_map_, key);
+std::unique_ptr<content::VpnServiceProxy> VpnService::GetVpnServiceProxy() {
+  return std::make_unique<VpnServiceProxyImpl>(weak_factory_.GetWeakPtr());
 }
 
-bool VpnService::VerifyConfigIsConnectedForTesting(
-    const std::string& extension_id) {
-  return DoesActiveConfigurationExistAndIsAccessAuthorized(extension_id);
-}
-
-void VpnService::DestroyConfigurationsForExtension(
-    const extensions::Extension* extension) {
-  std::vector<VpnConfiguration*> to_be_destroyed;
-  for (const auto& iter : key_to_configuration_map_) {
-    if (iter.second->extension_id() == extension->id()) {
-      to_be_destroyed.push_back(iter.second.get());
-    }
-  }
-
-  for (auto* iter : to_be_destroyed) {
-    DestroyConfiguration(extension->id(),             // Extension ID
-                         iter->configuration_name(),  // Configuration name
-                         base::DoNothing(),
-                         base::BindOnce(DoNothingFailureCallback));
-  }
-}
-
-void VpnService::OnExtensionUninstalled(
-    content::BrowserContext* browser_context,
-    const extensions::Extension* extension,
-    extensions::UninstallReason reason) {
-  if (browser_context != browser_context_) {
-    NOTREACHED();
-    return;
-  }
-
-  DestroyConfigurationsForExtension(extension);
+void VpnService::OnExtensionUninstalled(content::BrowserContext*,
+                                        const extensions::Extension* extension,
+                                        extensions::UninstallReason) {
+  GetVpnService()->MaybeFailActiveConnectionAndDestroyConfigurations(
+      extension->id(), /*destroy_configurations=*/true);
+  extension_id_to_service_.erase(extension->id());
 }
 
 void VpnService::OnExtensionUnloaded(
-    content::BrowserContext* browser_context,
+    content::BrowserContext*,
     const extensions::Extension* extension,
     extensions::UnloadedExtensionReason reason) {
-  if (browser_context != browser_context_) {
-    NOTREACHED();
-    return;
-  }
-
-  if (active_configuration_ &&
-      active_configuration_->extension_id() == extension->id()) {
-    shill_client_->UpdateConnectionState(
-        active_configuration_->object_path(),
-        static_cast<uint32_t>(api_vpn::VPN_CONNECTION_STATE_FAILURE),
-        base::DoNothing(), base::BindOnce(DoNothingFailureCallback));
-  }
-  if (reason == extensions::UnloadedExtensionReason::DISABLE ||
-      reason == extensions::UnloadedExtensionReason::BLOCKLIST) {
-    DestroyConfigurationsForExtension(extension);
+  bool destroy_configurations =
+      reason == extensions::UnloadedExtensionReason::DISABLE ||
+      reason == extensions::UnloadedExtensionReason::BLOCKLIST;
+  GetVpnService()->MaybeFailActiveConnectionAndDestroyConfigurations(
+      extension->id(), destroy_configurations);
+  if (destroy_configurations) {
+    extension_id_to_service_.erase(extension->id());
   }
 }
 
-void VpnService::OnCreateConfigurationSuccess(
-    VpnService::SuccessCallback callback,
-    VpnConfiguration* configuration,
-    const std::string& service_path,
-    const std::string& guid) {
-  configuration->set_service_path(service_path);
-  service_path_to_configuration_map_[service_path] = configuration;
-  shill_client_->AddShillThirdPartyVpnObserver(configuration->object_path(),
-                                               configuration);
-  std::move(callback).Run();
+// static
+crosapi::mojom::VpnService* VpnService::GetVpnService() {
+  DCHECK(crosapi::CrosapiManager::IsInitialized());
+  return crosapi::CrosapiManager::Get()->crosapi_ash()->vpn_service_ash();
 }
 
-void VpnService::OnCreateConfigurationFailure(
-    VpnService::FailureCallback callback,
-    VpnConfiguration* configuration,
-    const std::string& error_name) {
-  DestroyConfigurationInternal(configuration);
-  std::move(callback).Run(error_name, std::string());
+mojo::Remote<crosapi::mojom::VpnServiceForExtension>&
+VpnService::GetVpnServiceForExtension(const std::string& extension_id) {
+  auto it = extension_id_to_service_.find(extension_id);
+  if (it == extension_id_to_service_.end()) {
+    it = extension_id_to_service_.insert(
+        it, {extension_id, std::make_unique<VpnServiceForExtension>(
+                               extension_id, browser_context_)});
+  }
+  const auto& service = it->second;
+  return service->Proxy();
 }
 
-void VpnService::OnRemoveConfigurationSuccess(
-    VpnService::SuccessCallback callback) {
-  std::move(callback).Run();
-}
-
-void VpnService::OnRemoveConfigurationFailure(
-    VpnService::FailureCallback callback,
-    const std::string& error_name) {
-  std::move(callback).Run(error_name, std::string());
-}
-
-void VpnService::SendSignalToExtension(
+void VpnService::BindPepperVpnProxy(
     const std::string& extension_id,
-    extensions::events::HistogramValue histogram_value,
-    const std::string& event_name,
-    std::vector<base::Value> event_args) {
-  std::unique_ptr<extensions::Event> event(new extensions::Event(
-      histogram_value, event_name, std::move(event_args), browser_context_));
-
-  event_router_->DispatchEventToExtension(extension_id, std::move(event));
-}
-
-void VpnService::SetActiveConfiguration(
-    VpnService::VpnConfiguration* configuration) {
-  active_configuration_ = configuration;
-}
-
-VpnService::VpnConfiguration* VpnService::CreateConfigurationInternal(
-    const std::string& extension_id,
-    const std::string& configuration_name,
-    const std::string& key) {
-  VpnConfiguration* configuration = new VpnConfiguration(
-      extension_id, configuration_name, key, weak_factory_.GetWeakPtr());
-  key_to_configuration_map_[key] = base::WrapUnique(configuration);
-  return configuration;
-}
-
-void VpnService::DestroyConfigurationInternal(VpnConfiguration* configuration) {
-  std::unique_ptr<VpnConfiguration> configuration_ptr =
-      std::move(key_to_configuration_map_[configuration->key()]);
-  key_to_configuration_map_.erase(configuration->key());
-  if (active_configuration_ == configuration) {
-    active_configuration_ = nullptr;
-  }
-  if (!configuration->service_path().empty()) {
-    shill_client_->RemoveShillThirdPartyVpnObserver(
-        configuration->object_path());
-    service_path_to_configuration_map_.erase(configuration->service_path());
-  }
-}
-
-bool VpnService::DoesActiveConfigurationExistAndIsAccessAuthorized(
-    const std::string& extension_id) {
-  return active_configuration_ &&
-         active_configuration_->extension_id() == extension_id;
-}
-
-void VpnService::Bind(
-    const std::string& extension_id,
-    const std::string& configuration_id,
     const std::string& configuration_name,
     SuccessCallback success,
     FailureCallback failure,
     std::unique_ptr<content::PepperVpnProviderResourceHostProxy>
         pepper_vpn_provider_proxy) {
-  // The ID is the configuration name for now. This may change in the future.
-  const std::string key = GetKey(extension_id, configuration_id);
-  if (!base::Contains(key_to_configuration_map_, key)) {
-    std::move(failure).Run(std::string(),
-                           std::string("Unauthorized access. "
-                                       "The configuration does not exist."));
-    return;
-  }
+  // Here we create a PepperVpnProxyAdapter that will forward everything to the
+  // underlying PepperVpnProviderResourceHostProxy and bind it via crosapi. Note
+  // that the crosapi call might be unsuccessful if the active vpn configuration
+  // is not owned by the given extension; therefore we don't create the
+  // SelfOwnedReceiver right away, but instead do it in the callback on success
+  // or reset the entangled pipe on failure.
+  auto pepper_adapter = std::make_unique<PepperVpnProxyAdapter>(
+      std::move(pepper_vpn_provider_proxy));
+  mojo::PendingRemote<crosapi::mojom::PepperVpnProxyObserver> pepper_client;
 
-  VpnConfiguration* configuration = key_to_configuration_map_[key].get();
-  if (active_configuration_ != configuration) {
-    std::move(failure).Run(std::string(),
-                           std::string("Unauthorized access. "
-                                       "The configuration is not active."));
-    return;
-  }
+  auto callback = base::BindOnce(
+      &VpnService::OnBindPepperVpnProxy, weak_factory_.GetWeakPtr(),
+      std::move(success), std::move(failure), std::move(pepper_adapter),
+      pepper_client.InitWithNewPipeAndPassReceiver());
 
-  if (configuration->extension_id() != extension_id ||
-      configuration->configuration_name() != configuration_name) {
-    std::move(failure).Run(
-        std::string(),
-        std::string("Unauthorized access. "
-                    "Configuration name or extension ID mismatch."));
-    return;
-  }
-
-  const std::string service_path = configuration->service_path();
-  if (service_path.empty()) {
-    std::move(failure).Run(std::string(), std::string("Pending create."));
-    return;
-  }
-
-  // Connection authorized. All packets will be routed through the Pepper API.
-  configuration->set_pepper_proxy(std::move(pepper_vpn_provider_proxy));
-
-  std::move(success).Run();
+  GetVpnServiceForExtension(extension_id)
+      ->BindPepperVpnProxyObserver(configuration_name, std::move(pepper_client),
+                                   std::move(callback));
 }
 
-std::unique_ptr<content::VpnServiceProxy> VpnService::GetVpnServiceProxy() {
-  return base::WrapUnique(new VpnServiceProxyImpl(weak_factory_.GetWeakPtr()));
+void VpnService::OnBindPepperVpnProxy(
+    SuccessCallback success,
+    FailureCallback failure,
+    std::unique_ptr<PepperVpnProxyAdapter> pepper_adapter,
+    mojo::PendingReceiver<crosapi::mojom::PepperVpnProxyObserver>
+        pepper_receiver,
+    crosapi::mojom::VpnErrorResponsePtr error) {
+  if (error) {
+    pepper_receiver.reset();
+    RunFailureCallback(std::move(failure), error->name, error->message);
+  } else {
+    // Gets reset when the active configuration in ash gets destroyed.
+    mojo::MakeSelfOwnedReceiver(std::move(pepper_adapter),
+                                std::move(pepper_receiver));
+    RunSuccessCallback(std::move(success));
+  }
 }
 
-const std::string VpnService::GetSingleServicepathForTesting() {
-  if (service_path_to_configuration_map_.size() == 1)
-    return service_path_to_configuration_map_.begin()->first;
-  return std::string();
+VpnService::PepperVpnProxyAdapter::PepperVpnProxyAdapter(
+    std::unique_ptr<content::PepperVpnProviderResourceHostProxy>
+        pepper_vpn_proxy)
+    : pepper_vpn_proxy_(std::move(pepper_vpn_proxy)) {}
+
+VpnService::PepperVpnProxyAdapter::~PepperVpnProxyAdapter() = default;
+
+void VpnService::PepperVpnProxyAdapter::OnUnbind() {
+  pepper_vpn_proxy_->SendOnUnbind();
+  pepper_vpn_proxy_.reset();
+}
+
+void VpnService::PepperVpnProxyAdapter::OnPacketReceived(
+    const std::vector<uint8_t>& data) {
+  DCHECK(pepper_vpn_proxy_);
+  pepper_vpn_proxy_->SendOnPacketReceived(
+      std::vector<char>(data.begin(), data.end()));
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/extensions/vpn_provider/vpn_service.h b/chrome/browser/chromeos/extensions/vpn_provider/vpn_service.h
index 43d22b2..b9658ae 100644
--- a/chrome/browser/chromeos/extensions/vpn_provider/vpn_service.h
+++ b/chrome/browser/chromeos/extensions/vpn_provider/vpn_service.h
@@ -5,82 +5,84 @@
 #ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_VPN_PROVIDER_VPN_SERVICE_H_
 #define CHROME_BROWSER_CHROMEOS_EXTENSIONS_VPN_PROVIDER_VPN_SERVICE_H_
 
-#include <map>
 #include <memory>
 #include <string>
 #include <vector>
 
 #include "base/callback.h"
+#include "base/containers/flat_map.h"
 #include "base/memory/weak_ptr.h"
+#include "base/scoped_observation.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/extensions/vpn_provider/vpn_service_interface.h"
-#include "chromeos/network/network_configuration_observer.h"
-#include "chromeos/network/network_state_handler_observer.h"
+#include "chromeos/crosapi/mojom/vpn_service.mojom.h"
+#include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_event_histogram_value.h"
+#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_registry_observer.h"
+#include "extensions/browser/unloaded_extension_reason.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
 
 namespace content {
 
 class BrowserContext;
 class PepperVpnProviderResourceHostProxy;
-class VpnServiceProxy;
 
 }  // namespace content
 
 namespace extensions {
 
-class EventRouter;
 class ExtensionRegistry;
 
 }  // namespace extensions
 
 namespace chromeos {
 
-class NetworkConfigurationHandler;
-class NetworkProfileHandler;
-class NetworkStateHandler;
-class ShillThirdPartyVpnDriverClient;
+class VpnServiceForExtension
+    : public crosapi::mojom::EventObserverForExtension {
+ public:
+  VpnServiceForExtension(const std::string& extension_id,
+                         content::BrowserContext*);
+  ~VpnServiceForExtension() override;
+
+  VpnServiceForExtension(const VpnServiceForExtension&) = delete;
+  VpnServiceForExtension& operator=(const VpnServiceForExtension&) = delete;
+
+  // crosapi::mojom::EventObserverForExtension:
+  void OnAddDialog() override;
+  void OnConfigureDialog(const std::string& configuration_name) override;
+  void OnConfigRemoved(const std::string& configuration_name) override;
+  void OnPlatformMessage(const std::string& configuration_name,
+                         int32_t platform_message,
+                         const absl::optional<std::string>& error) override;
+  void OnPacketReceived(const std::vector<uint8_t>& data) override;
+
+  mojo::Remote<crosapi::mojom::VpnServiceForExtension>& Proxy() {
+    return vpn_service_;
+  }
+
+ private:
+  void DispatchEvent(std::unique_ptr<extensions::Event>) const;
+
+  const std::string extension_id_;
+  content::BrowserContext* browser_context_;
+
+  mojo::Remote<crosapi::mojom::VpnServiceForExtension> vpn_service_;
+  mojo::Receiver<crosapi::mojom::EventObserverForExtension> receiver_{this};
+};
 
 // The class manages the VPN configurations.
 class VpnService : public extensions::api::VpnServiceInterface,
-                   public NetworkConfigurationObserver,
-                   public NetworkStateHandlerObserver,
                    public extensions::ExtensionRegistryObserver {
  public:
-  VpnService(content::BrowserContext* browser_context,
-             const std::string& userid_hash,
-             extensions::ExtensionRegistry* extension_registry,
-             extensions::EventRouter* event_router,
-             ShillThirdPartyVpnDriverClient* shill_client,
-             NetworkConfigurationHandler* network_configuration_handler,
-             NetworkProfileHandler* network_profile_handler,
-             NetworkStateHandler* network_state_handler);
+  explicit VpnService(content::BrowserContext*);
+  ~VpnService() override;
 
   VpnService(const VpnService&) = delete;
   VpnService& operator=(const VpnService&) = delete;
 
-  ~VpnService() override;
-
-  void SendPlatformError(const std::string& extension_id,
-                         const std::string& configuration_name,
-                         const std::string& error_message);
-
-  // NetworkConfigurationObserver:
-  void OnConfigurationRemoved(const std::string& service_path,
-                              const std::string& guid) override;
-
-  // NetworkStateHandlerObserver:
-  void NetworkListChanged() override;
-
-  // ExtensionRegistryObserver:
-  void OnExtensionUninstalled(content::BrowserContext* browser_context,
-                              const extensions::Extension* extension,
-                              extensions::UninstallReason reason) override;
-  void OnExtensionUnloaded(content::BrowserContext* browser_context,
-                           const extensions::Extension* extension,
-                           extensions::UnloadedExtensionReason reason) override;
-
-  // extensions::api::VpnServiceThinClientDelegate:
+  // extensions::api::VpnServiceInterface:
   void SendShowAddDialogToExtension(const std::string& extension_id) override;
   void SendShowConfigureDialogToExtension(
       const std::string& extension_id,
@@ -101,116 +103,80 @@
                   const std::vector<char>& data,
                   SuccessCallback,
                   FailureCallback) override;
-  void NotifyConnectionStateChanged(
-      const std::string& extension_id,
-      extensions::api::vpn_provider::VpnConnectionState,
-      SuccessCallback,
-      FailureCallback) override;
+  void NotifyConnectionStateChanged(const std::string& extension_id,
+                                    bool connection_success,
+                                    SuccessCallback,
+                                    FailureCallback) override;
   std::unique_ptr<content::VpnServiceProxy> GetVpnServiceProxy() override;
 
-  // Verifies if a configuration with name |configuration_name| exists for the
-  // extension with id |extension_id|.
-  bool VerifyConfigExistsForTesting(const std::string& extension_id,
-                                    const std::string& configuration_name);
-
-  // Verifies if the extension has a configuration that is connected.
-  bool VerifyConfigIsConnectedForTesting(const std::string& extension_id);
-
-  // Gets the unique key for the configuration |configuration_name| created by
-  // the extension with id |extension_id|.
-  // This method is made public for testing.
-  static std::string GetKey(const std::string& extension_id,
-                            const std::string& configuration_name);
-
-  // Returns the single entry of |service_path_to_configuration_map_| for
-  // testing (see VpnProviderApiTest);
-  const std::string GetSingleServicepathForTesting();
+  // ExtensionRegistryObserver:
+  void OnExtensionUninstalled(content::BrowserContext*,
+                              const extensions::Extension*,
+                              extensions::UninstallReason) override;
+  void OnExtensionUnloaded(content::BrowserContext*,
+                           const extensions::Extension*,
+                           extensions::UnloadedExtensionReason) override;
 
  private:
-  class VpnConfiguration;
   class VpnServiceProxyImpl;
+  class PepperVpnProxyAdapter;
+  friend class VpnServiceForExtension;
+  friend class VpnServiceFactory;
 
-  using StringToConfigurationMap = std::map<std::string, VpnConfiguration*>;
-  using StringToOwnedConfigurationMap =
-      std::map<std::string, std::unique_ptr<VpnConfiguration>>;
+  static crosapi::mojom::VpnService* GetVpnService();
 
-  // Callback used to indicate that configuration was successfully created.
-  void OnCreateConfigurationSuccess(SuccessCallback callback,
-                                    VpnConfiguration* configuration,
-                                    const std::string& service_path,
-                                    const std::string& guid);
+  mojo::Remote<crosapi::mojom::VpnServiceForExtension>&
+  GetVpnServiceForExtension(const std::string& extension_id);
 
-  // Callback used to indicate that configuration creation failed.
-  void OnCreateConfigurationFailure(FailureCallback callback,
-                                    VpnConfiguration* configuration,
-                                    const std::string& error_name);
-
-  // Callback used to indicate that removing a configuration succeeded.
-  void OnRemoveConfigurationSuccess(SuccessCallback callback);
-
-  // Callback used to indicate that removing a configuration failed.
-  void OnRemoveConfigurationFailure(FailureCallback callback,
-                                    const std::string& error_name);
-
-  void OnGetShillProperties(const std::string& service_path,
-                            absl::optional<base::Value> dictionary);
-
-  // Creates and adds the configuration to the internal store.
-  VpnConfiguration* CreateConfigurationInternal(
+  // Binds |pepper_vpn_provider_proxy| to the active configuration if it's owned
+  // by extension with id |extension_id|. On success all packets will be routed
+  // through Pepper API.
+  void BindPepperVpnProxy(
       const std::string& extension_id,
       const std::string& configuration_name,
-      const std::string& key);
+      SuccessCallback,
+      FailureCallback,
+      std::unique_ptr<content::PepperVpnProviderResourceHostProxy>);
 
-  // Removes configuration from the internal store and destroys it.
-  void DestroyConfigurationInternal(VpnConfiguration* configuration);
+  void OnBindPepperVpnProxy(
+      SuccessCallback,
+      FailureCallback,
+      std::unique_ptr<PepperVpnProxyAdapter>,
+      mojo::PendingReceiver<crosapi::mojom::PepperVpnProxyObserver>,
+      crosapi::mojom::VpnErrorResponsePtr);
 
-  // Verifies if |active_configuration_| exists and if the extension with id
-  // |extension_id| is authorized to access it.
-  bool DoesActiveConfigurationExistAndIsAccessAuthorized(
-      const std::string& extension_id);
+  raw_ptr<content::BrowserContext> browser_context_;
 
-  // Send an event with name |event_name| and arguments |event_args| to the
-  // extension with id |extension_id|.
-  void SendSignalToExtension(const std::string& extension_id,
-                             extensions::events::HistogramValue histogram_value,
-                             const std::string& event_name,
-                             std::vector<base::Value> event_args);
+  base::ScopedObservation<extensions::ExtensionRegistry,
+                          extensions::ExtensionRegistryObserver>
+      extension_registry_observer_{this};
 
-  // Destroy configurations belonging to the extension.
-  void DestroyConfigurationsForExtension(
-      const extensions::Extension* extension);
-
-  // Set the active configuration.
-  void SetActiveConfiguration(VpnConfiguration* configuration);
-
-  void Bind(const std::string& extension_id,
-            const std::string& configuration_id,
-            const std::string& configuration_name,
-            SuccessCallback success,
-            FailureCallback failure,
-            std::unique_ptr<content::PepperVpnProviderResourceHostProxy>
-                pepper_vpn_provider_proxy);
-
-  content::BrowserContext* browser_context_;
-  std::string userid_hash_;
-
-  extensions::ExtensionRegistry* extension_registry_;
-  extensions::EventRouter* event_router_;
-  ShillThirdPartyVpnDriverClient* shill_client_;
-  NetworkConfigurationHandler* network_configuration_handler_;
-  NetworkProfileHandler* network_profile_handler_;
-  NetworkStateHandler* network_state_handler_;
-
-  VpnConfiguration* active_configuration_;
-
-  StringToOwnedConfigurationMap key_to_configuration_map_;
-
-  // Service path does not own the VpnConfigurations.
-  StringToConfigurationMap service_path_to_configuration_map_;
+  base::flat_map<std::string, std::unique_ptr<VpnServiceForExtension>>
+      extension_id_to_service_;
 
   base::WeakPtrFactory<VpnService> weak_factory_{this};
 };
 
+// Listens to incoming events and forwards them to the underlying
+// PepperVpnProviderResourseHostProxy.
+// * ::OnUnbind() -> pepper->SendOnUnbind()
+// * ::OnPacketReceived(...) -> pepper->SendOnPacketReceived(...)
+class VpnService::PepperVpnProxyAdapter
+    : public crosapi::mojom::PepperVpnProxyObserver {
+ public:
+  explicit PepperVpnProxyAdapter(
+      std::unique_ptr<content::PepperVpnProviderResourceHostProxy>);
+  ~PepperVpnProxyAdapter() override;
+
+  // crosapi::mojom::PepperVpnProxyObserver:
+  void OnUnbind() override;
+  void OnPacketReceived(const std::vector<uint8_t>& data) override;
+
+ private:
+  std::unique_ptr<content::PepperVpnProviderResourceHostProxy>
+      pepper_vpn_proxy_;
+};
+
 }  // namespace chromeos
 
 #endif  // CHROME_BROWSER_CHROMEOS_EXTENSIONS_VPN_PROVIDER_VPN_SERVICE_H_
diff --git a/chrome/browser/chromeos/extensions/vpn_provider/vpn_service_factory.cc b/chrome/browser/chromeos/extensions/vpn_provider/vpn_service_factory.cc
index 1738067..0424a574 100644
--- a/chrome/browser/chromeos/extensions/vpn_provider/vpn_service_factory.cc
+++ b/chrome/browser/chromeos/extensions/vpn_provider/vpn_service_factory.cc
@@ -6,12 +6,8 @@
 
 #include "base/memory/singleton.h"
 #include "chrome/browser/chromeos/extensions/vpn_provider/vpn_service.h"
-#include "chromeos/dbus/shill/shill_third_party_vpn_driver_client.h"
 #include "chromeos/login/login_state/login_state.h"
-#include "chromeos/network/network_handler.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "extensions/browser/event_router.h"
-#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extensions_browser_client.h"
 
 namespace chromeos {
@@ -45,6 +41,10 @@
 
 KeyedService* VpnServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
+  if (!VpnService::GetVpnService()) {
+    return nullptr;
+  }
+
   std::string context_user_hash =
       extensions::ExtensionsBrowserClient::Get()->GetUserIdHashFromContext(
           context);
@@ -54,13 +54,7 @@
     return nullptr;
   }
 
-  return new VpnService(context, context_user_hash,
-                        extensions::ExtensionRegistry::Get(context),
-                        extensions::EventRouter::Get(context),
-                        ShillThirdPartyVpnDriverClient::Get(),
-                        NetworkHandler::Get()->network_configuration_handler(),
-                        NetworkHandler::Get()->network_profile_handler(),
-                        NetworkHandler::Get()->network_state_handler());
+  return new VpnService(context);
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/extensions/vpn_provider/vpn_service_interface.h b/chrome/browser/chromeos/extensions/vpn_provider/vpn_service_interface.h
index beac89dea..c06a8ff 100644
--- a/chrome/browser/chromeos/extensions/vpn_provider/vpn_service_interface.h
+++ b/chrome/browser/chromeos/extensions/vpn_provider/vpn_service_interface.h
@@ -72,14 +72,13 @@
                           SuccessCallback,
                           FailureCallback) = 0;
 
-  // Notifies connection state |state| to the active VPN configuration after
+  // Notifies new connection state to the active VPN configuration after
   // verifying that it belongs to the extension with id |extension_id|.
   // Calls |success| or |failure| based on the outcome.
-  virtual void NotifyConnectionStateChanged(
-      const std::string& extension_id,
-      extensions::api::vpn_provider::VpnConnectionState,
-      SuccessCallback,
-      FailureCallback) = 0;
+  virtual void NotifyConnectionStateChanged(const std::string& extension_id,
+                                            bool connection_success,
+                                            SuccessCallback,
+                                            FailureCallback) = 0;
 
   // Returns a VpnServiceProxy that is used by Pepper API.
   virtual std::unique_ptr<content::VpnServiceProxy> GetVpnServiceProxy() = 0;
diff --git a/chrome/browser/extensions/api/printing/print_job_submitter.cc b/chrome/browser/extensions/api/printing/print_job_submitter.cc
index 08d75fea..0400f99 100644
--- a/chrome/browser/extensions/api/printing/print_job_submitter.cc
+++ b/chrome/browser/extensions/api/printing/print_job_submitter.cc
@@ -81,7 +81,7 @@
       Profile::FromBrowserContext(browser_context)
           ->GetPrefs()
           ->GetList(prefs::kPrintingAPIExtensionsAllowlist);
-  return !base::Contains(list->GetListDeprecated(), base::Value(extension_id));
+  return !base::Contains(list->GetList(), base::Value(extension_id));
 }
 
 }  // namespace
diff --git a/chrome/browser/extensions/api/printing/printing_api_handler_unittest.cc b/chrome/browser/extensions/api/printing/printing_api_handler_unittest.cc
index 8014e25..ba3fe06 100644
--- a/chrome/browser/extensions/api/printing/printing_api_handler_unittest.cc
+++ b/chrome/browser/extensions/api/printing/printing_api_handler_unittest.cc
@@ -63,11 +63,11 @@
                            api::printing::JobStatus expected_status) const {
     EXPECT_EQ(expected_extension_id, extension_id_);
     ASSERT_TRUE(event_args_.is_list());
-    ASSERT_EQ(2u, event_args_.GetListDeprecated().size());
-    const base::Value& job_id = event_args_.GetListDeprecated()[0];
+    ASSERT_EQ(2u, event_args_.GetList().size());
+    const base::Value& job_id = event_args_.GetList()[0];
     ASSERT_TRUE(job_id.is_string());
     EXPECT_EQ(expected_job_id, job_id.GetString());
-    const base::Value& job_status = event_args_.GetListDeprecated()[1];
+    const base::Value& job_status = event_args_.GetList()[1];
     ASSERT_TRUE(job_status.is_string());
     EXPECT_EQ(expected_status,
               api::printing::ParseJobStatus(job_status.GetString()));
@@ -646,9 +646,9 @@
   ASSERT_TRUE(color);
   const base::Value* color_options = color->FindListKey("option");
   ASSERT_TRUE(color_options);
-  ASSERT_EQ(1u, color_options->GetListDeprecated().size());
+  ASSERT_EQ(1u, color_options->GetList().size());
   const std::string* color_type =
-      color_options->GetListDeprecated()[0].FindStringKey("type");
+      color_options->GetList()[0].FindStringKey("type");
   ASSERT_TRUE(color_type);
   EXPECT_EQ("STANDARD_MONOCHROME", *color_type);
 
@@ -658,10 +658,10 @@
   const base::Value* page_orientation_options =
       page_orientation->FindListKey("option");
   ASSERT_TRUE(page_orientation_options);
-  ASSERT_EQ(3u, page_orientation_options->GetListDeprecated().size());
+  ASSERT_EQ(3u, page_orientation_options->GetList().size());
   std::vector<std::string> page_orientation_types;
   for (const base::Value& page_orientation_option :
-       page_orientation_options->GetListDeprecated()) {
+       page_orientation_options->GetList()) {
     const std::string* page_orientation_type =
         page_orientation_option.FindStringKey("type");
     ASSERT_TRUE(page_orientation_type);
diff --git a/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc b/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc
index c04959d2..04aed984 100644
--- a/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc
+++ b/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc
@@ -7,12 +7,15 @@
 
 #include "base/bind.h"
 #include "base/callback_helpers.h"
+#include "base/containers/contains.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/test/test_future.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/chromeos/extensions/vpn_provider/vpn_provider_api.h"
 #include "chrome/browser/chromeos/extensions/vpn_provider/vpn_service.h"
 #include "chrome/browser/chromeos/extensions/vpn_provider/vpn_service_factory.h"
+#include "chrome/browser/chromeos/extensions/vpn_provider/vpn_service_interface.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h"
@@ -22,6 +25,8 @@
 #include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_profile_handler.h"
 #include "content/public/browser/browser_context.h"
+#include "content/public/browser/pepper_vpn_provider_resource_host_proxy.h"
+#include "content/public/browser/vpn_service_proxy.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/api_test_utils.h"
@@ -31,8 +36,9 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-using testing::_;
-using testing::Invoke;
+#include "chrome/browser/ash/crosapi/crosapi_ash.h"
+#include "chrome/browser/ash/crosapi/crosapi_manager.h"
+#include "chrome/browser/ash/crosapi/vpn_service_ash.h"
 
 namespace chromeos {
 
@@ -42,6 +48,7 @@
 
 const char kNetworkProfilePath[] = "/network/test";
 const char kTestConfig[] = "testconfig";
+const char kPacket[] = "feebdaed";
 const char* kParameterValues[] = {"10.10.10.10",
                                   "24",
                                   "63.145.213.129/32 63.145.212.0/24",
@@ -66,6 +73,10 @@
 void DoNothingSuccessCallback(const std::string& service_path,
                               const std::string& guid) {}
 
+crosapi::VpnServiceAsh* GetVpnServiceAsh() {
+  return crosapi::CrosapiManager::Get()->crosapi_ash()->vpn_service_ash();
+}
+
 }  // namespace
 
 // Records the number of calls and their parameters. Always replies successfully
@@ -136,8 +147,7 @@
   void LoadVpnExtension() {
     extension_ = LoadExtension(test_data_dir_.AppendASCII("vpn_provider"));
     extension_id_ = extension_->id();
-    service_ = static_cast<chromeos::VpnService*>(
-        VpnServiceFactory::GetForBrowserContext(profile()));
+    service_ = VpnServiceFactory::GetForBrowserContext(profile());
     content::RunAllPendingInMessageLoop();
   }
 
@@ -146,22 +156,43 @@
     return RunExtensionTest("vpn_provider", {.page_url = url.spec().c_str()});
   }
 
-  std::string GetKey(const std::string& config_name) {
-    return service_->GetKey(extension_id_, config_name);
+  std::string GetKey(const std::string& configuration_name) const {
+    return crosapi::VpnServiceForExtensionAsh::GetKey(extension_id_,
+                                                      configuration_name);
   }
 
-  bool DoesConfigExist(const std::string& config_name) {
-    return service_->VerifyConfigExistsForTesting(extension_id_, config_name);
+  bool DoesConfigExist(const std::string& configuration_name) const {
+    const auto& mapping = GetVpnServiceAsh()->extension_id_to_service_;
+    if (!base::Contains(mapping, extension_id_)) {
+      return false;
+    }
+    return base::Contains(mapping.at(extension_id_)->key_to_configuration_map_,
+                          GetKey(configuration_name));
   }
 
-  bool IsConfigConnected() {
-    return service_->VerifyConfigIsConnectedForTesting(extension_id_);
+  bool IsConfigConnected() const {
+    const auto& mapping = GetVpnServiceAsh()->extension_id_to_service_;
+    if (!base::Contains(mapping, extension_id_)) {
+      return false;
+    }
+    return mapping.at(extension_id_)->OwnsActiveConfiguration();
   }
 
   std::string GetSingleServicePath() {
-    std::string service_path = service_->GetSingleServicepathForTesting();
-    EXPECT_FALSE(service_path.empty());
-    return service_path;
+    auto* vpn_service_ash = GetVpnServiceAsh();
+    std::vector<std::string> service_paths;
+    for (const auto& [extension_id, service] :
+         vpn_service_ash->extension_id_to_service_) {
+      const auto& service_path_map =
+          service->service_path_to_configuration_map_;
+      if (service_path_map.empty()) {
+        continue;
+      }
+      DCHECK_EQ(service_path_map.size(), 1U);
+      service_paths.push_back(service_path_map.begin()->first);
+    }
+    EXPECT_EQ(service_paths.size(), 1U);
+    return service_paths[0];
   }
 
   bool CreateConfigForTest(const std::string& name) {
@@ -196,9 +227,19 @@
     return properties.is_dict();
   }
 
+  void SendPlatformError(const std::string& extension_id,
+                         const std::string& configuration_name,
+                         const std::string& error_message) {
+    const auto& mapping = GetVpnServiceAsh()->extension_id_to_service_;
+    DCHECK(base::Contains(mapping, extension_id));
+    auto* service = mapping.at(extension_id).get();
+    service->DispatchOnPlatformMessageEvent(
+        configuration_name, api_vpn::PLATFORM_MESSAGE_ERROR, error_message);
+  }
+
  protected:
   TestShillThirdPartyVpnDriverClient* test_client_ = nullptr;  // Unowned
-  VpnService* service_ = nullptr;
+  extensions::api::VpnServiceInterface* service_ = nullptr;
   std::string extension_id_;
   std::string service_path_;
   const extensions::Extension* extension_ = nullptr;
@@ -291,8 +332,7 @@
     ASSERT_TRUE(value);
     EXPECT_EQ(kParameterValues[i], *value);
   }
-  const char kPacket[] = "feebdaed";
-  std::vector<char> packet(&kPacket[0], &kPacket[8]);
+  std::vector<char> packet(std::begin(kPacket), std::prev(std::end(kPacket)));
   EXPECT_EQ(packet, test_client_->ip_packet_);
 
   packet.assign(test_client_->ip_packet_.rbegin(),
@@ -325,7 +365,7 @@
   EXPECT_TRUE(DoesConfigExist(kTestConfig));
 
   extensions::ResultCatcher catcher;
-  service_->SendPlatformError(extension_id_, kTestConfig, "error_message");
+  SendPlatformError(extension_id_, kTestConfig, "error_message");
   service_->SendShowAddDialogToExtension(extension_id_);
   service_->SendShowConfigureDialogToExtension(extension_id_, kTestConfig);
   EXPECT_TRUE(catcher.GetNextResult());
@@ -403,4 +443,66 @@
   EXPECT_FALSE(HasService(service_path));
 }
 
+class FakePepperVpnProviderResourceHostProxy
+    : public content::PepperVpnProviderResourceHostProxy {
+ public:
+  FakePepperVpnProviderResourceHostProxy(
+      base::test::TestFuture<bool>* unbind,
+      base::test::TestFuture<std::vector<char>>* data)
+      : unbind_(unbind), data_(data) {}
+
+  void SendOnUnbind() override { unbind_->SetValue(true); }
+
+  void SendOnPacketReceived(const std::vector<char>& data) override {
+    data_->SetValue(data);
+  }
+
+ private:
+  raw_ptr<base::test::TestFuture<bool>> unbind_;
+  raw_ptr<base::test::TestFuture<std::vector<char>>> data_;
+};
+
+IN_PROC_BROWSER_TEST_F(VpnProviderApiTest, PepperProxy) {
+  LoadVpnExtension();
+  AddNetworkProfileForUser();
+
+  base::test::TestFuture<bool> unbind;
+  base::test::TestFuture<std::vector<char>> data;
+  // This class will be used as a receiver for mojo::SelfOwnedReceiver.
+  // Therefore it's unsafe to keep these TestFuture-s as members (especially
+  // |unbind|).
+  auto pepper_proxy =
+      std::make_unique<FakePepperVpnProviderResourceHostProxy>(&unbind, &data);
+
+  extensions::ResultCatcher catcher;
+
+  // Create config and imitate the platform sending a
+  // PLATFORM_MESSAGE_CONNECTED.
+  EXPECT_TRUE(RunTest("createConfigConnectForBind"));
+  ASSERT_TRUE(catcher.GetNextResult());
+  const std::string object_path = shill::kObjectPathBase + GetKey(kTestConfig);
+  test_client_->OnPlatformMessage(object_path,
+                                  api_vpn::PLATFORM_MESSAGE_CONNECTED);
+  ASSERT_TRUE(catcher.GetNextResult());
+
+  // Synchronously bind the fake pepper proxy.
+  base::RunLoop run_loop;
+  service_->GetVpnServiceProxy()->Bind(
+      extension_id_, {}, kTestConfig, run_loop.QuitClosure(), base::DoNothing(),
+      std::move(pepper_proxy));
+  run_loop.Run();
+
+  // Assert that packets are routed through the proxy.
+  test_client_->OnPacketReceived(
+      object_path, std::vector<char>{std::begin(kPacket), std::end(kPacket)});
+  ASSERT_TRUE(data.Wait());
+
+  // Assert that pepper proxy receives an OnUnbind event on
+  // PLATFORM_MESSAGE_DISCONNECTED.
+  test_client_->OnPlatformMessage(object_path,
+                                  api_vpn::PLATFORM_MESSAGE_DISCONNECTED);
+  ASSERT_TRUE(catcher.GetNextResult());
+  ASSERT_TRUE(unbind.Wait());
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service.cc b/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service.cc
index 5f9436c..11ee113d 100644
--- a/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service.cc
+++ b/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service.cc
@@ -194,13 +194,21 @@
   if (!sink)
     return;
 
-  // Check to see if route was created by an access code sink.
   if (!sink->is_cast_sink()) {
     return;
   }
+
+  // Check to see if route was created by an access code sink.
+  CastDiscoveryType type = sink->cast_data().discovery_type;
+  if (type != CastDiscoveryType::kAccessCodeManualEntry &&
+        type != CastDiscoveryType::kAccessCodeRememberedDevice) {
+    return;
+  }
+
   media_router_->GetLogger()->LogInfo(
-      mojom::LogCategory::kDiscovery, kLoggerComponent,
-      "An Access Code Cast route has ended.", sink->id(), "", "");
+    mojom::LogCategory::kDiscovery, kLoggerComponent,
+    "An Access Code Cast route has ended.", sink->id(), "", "");
+
   // There are two possible cases here. The common case is that a route for
   // the specified sink has been terminated by local or remote user
   // interaction. In this case, call OnAccessCodeRouteRemoved to check whether
@@ -218,9 +226,6 @@
     std::move(it->second).Run(AddSinkResultCode::OK, sink->id());
     pending_callbacks_.erase(sink->id());
   } else {
-    CastDiscoveryType type = sink->cast_data().discovery_type;
-    if (type == CastDiscoveryType::kAccessCodeManualEntry ||
-        type == CastDiscoveryType::kAccessCodeRememberedDevice) {
       // Need to pause just a little bit before attempting to remove the sink.
       // Sometimes sinks terminate their routes and immediately start another
       // (tab content transitions for example), so wait just a little while
@@ -230,7 +235,6 @@
           base::BindOnce(&AccessCodeCastSinkService::OnAccessCodeRouteRemoved,
                          weak_ptr_factory_.GetWeakPtr(), sink),
           kExpirationDelay);
-    }
   }
 }
 
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index d4c3d3a..d3821e5 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -126,6 +126,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/context_menu_data/untrustworthy_context_menu_params.h"
 #include "third_party/blink/public/common/input/web_input_event.h"
+#include "third_party/blink/public/common/input/web_mouse_event.h"
 #include "third_party/blink/public/mojom/context_menu/context_menu.mojom.h"
 #include "ui/accessibility/ax_action_data.h"
 #include "ui/accessibility/ax_enum_util.h"
@@ -2061,6 +2062,30 @@
   menu_interceptor.Wait();
 }
 
+IN_PROC_BROWSER_TEST_F(PDFExtensionTest,
+                       ContextMenuPrintCommandEmbeddedExtensionMainFrame) {
+  content::WebContents* guest_contents = LoadPdfGetGuestContents(
+      embedded_test_server()->GetURL("/pdf/pdf_embed.html"));
+  content::RenderFrameHost* plugin_frame = GetPluginFrame(guest_contents);
+  ASSERT_TRUE(plugin_frame);
+
+  // Makes sure that the correct frame invoked the context menu.
+  content::ContextMenuInterceptor menu_interceptor(
+      guest_contents->GetMainFrame());
+
+  // Executes the print command as soon as the context menu is shown.
+  ContextMenuNotificationObserver context_menu_observer(IDC_PRINT);
+
+  PrintObserver print_observer(guest_contents, plugin_frame);
+  content::SimulateMouseClickAt(guest_contents,
+                                blink::WebInputEvent::kNoModifiers,
+                                blink::WebMouseEvent::Button::kLeft, {1, 1});
+  guest_contents->GetMainFrame()->GetRenderWidgetHost()->ShowContextMenuAtPoint(
+      {1, 1}, ui::MENU_SOURCE_MOUSE);
+  print_observer.WaitForPrintPreview();
+  menu_interceptor.Wait();
+}
+
 IN_PROC_BROWSER_TEST_F(PDFExtensionTest, ContextMenuPrintCommandPluginFrame) {
   content::WebContents* guest_contents =
       LoadPdfGetGuestContents(embedded_test_server()->GetURL("/pdf/test.pdf"));
@@ -2081,6 +2106,28 @@
   menu_interceptor.Wait();
 }
 
+// TODO(crbug.com/1330032): Fix flakiness.
+IN_PROC_BROWSER_TEST_F(PDFExtensionTest,
+                       DISABLED_ContextMenuPrintCommandEmbeddedPluginFrame) {
+  content::WebContents* guest_contents = LoadPdfGetGuestContents(
+      embedded_test_server()->GetURL("/pdf/pdf_embed.html"));
+  content::RenderFrameHost* plugin_frame = GetPluginFrame(guest_contents);
+  ASSERT_TRUE(plugin_frame);
+
+  // Makes sure that the correct frame invoked the context menu.
+  content::ContextMenuInterceptor menu_interceptor(plugin_frame);
+
+  // Executes the print command as soon as the context menu is shown.
+  ContextMenuNotificationObserver context_menu_observer(IDC_PRINT);
+
+  PrintObserver print_observer(guest_contents, plugin_frame);
+  SetInputFocusOnPlugin(guest_contents);
+  plugin_frame->GetRenderWidgetHost()->ShowContextMenuAtPoint(
+      {1, 1}, ui::MENU_SOURCE_MOUSE);
+  print_observer.WaitForPrintPreview();
+  menu_interceptor.Wait();
+}
+
 IN_PROC_BROWSER_TEST_F(PDFExtensionTest, PrintButton) {
   content::WebContents* guest_contents =
       LoadPdfGetGuestContents(embedded_test_server()->GetURL("/pdf/test.pdf"));
diff --git a/chrome/browser/printing/print_preview_sticky_settings.cc b/chrome/browser/printing/print_preview_sticky_settings.cc
index 1f47377b..1420bb0 100644
--- a/chrome/browser/printing/print_preview_sticky_settings.cc
+++ b/chrome/browser/printing/print_preview_sticky_settings.cc
@@ -82,9 +82,8 @@
     return {};
 
   std::vector<std::string> printers;
-  printers.reserve(recent_destinations->GetListDeprecated().size());
-  for (const auto& recent_destination :
-       recent_destinations->GetListDeprecated()) {
+  printers.reserve(recent_destinations->GetList().size());
+  for (const auto& recent_destination : recent_destinations->GetList()) {
     const std::string* printer_id = recent_destination.FindStringKey(kId);
     if (!printer_id)
       continue;
diff --git a/chrome/browser/printing/print_view_manager_common.cc b/chrome/browser/printing/print_view_manager_common.cc
index fe86f14..376dcc8 100644
--- a/chrome/browser/printing/print_view_manager_common.cc
+++ b/chrome/browser/printing/print_view_manager_common.cc
@@ -28,24 +28,15 @@
 namespace printing {
 
 namespace {
-// Returns true if `contents` is a full page MimeHandlerViewGuest plugin.
-bool IsFullPagePlugin(content::WebContents* contents) {
-#if BUILDFLAG(ENABLE_EXTENSIONS)
-  auto* guest_view =
-      extensions::MimeHandlerViewGuest::FromWebContents(contents);
-  if (guest_view && guest_view->is_full_page_plugin())
-    return true;
-#endif
-  return false;
-}
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
-// Stores `guest_contents` in `result` and returns true if
-// `IsFullPagePlugin(guest_contents)`. Otherwise, returns false and `result`
-// remains unchanged.
+// Stores `guest_contents` in `result` and returns true if `guest_contents` is a
+// full-page `MimeHandlerViewGuest`.
 bool StoreFullPagePlugin(content::WebContents** result,
                          content::WebContents* guest_contents) {
-  if (IsFullPagePlugin(guest_contents)) {
+  auto* guest_view =
+      extensions::MimeHandlerViewGuest::FromWebContents(guest_contents);
+  if (guest_view && guest_view->is_full_page_plugin()) {
     *result = guest_contents;
     return true;
   }
@@ -56,16 +47,14 @@
 // Pick the right RenderFrameHost based on the WebContents.
 content::RenderFrameHost* GetRenderFrameHostToUse(
     content::WebContents* contents) {
-  if (!IsFullPagePlugin(contents))
-    return GetFrameToPrint(contents);
-
 #if BUILDFLAG(ENABLE_PDF)
+  // Pick the plugin frame if `contents` is a PDF viewer guest.
   content::RenderFrameHost* pdf_rfh =
       pdf_frame_util::FindPdfChildFrame(contents->GetMainFrame());
   if (pdf_rfh)
     return pdf_rfh;
 #endif
-  return contents->GetMainFrame();
+  return GetFrameToPrint(contents);
 }
 
 }  // namespace
diff --git a/chrome/browser/resources/chromeos/accessibility/.eslintrc.js b/chrome/browser/resources/chromeos/accessibility/.eslintrc.js
index 14271ef..91fa561 100644
--- a/chrome/browser/resources/chromeos/accessibility/.eslintrc.js
+++ b/chrome/browser/resources/chromeos/accessibility/.eslintrc.js
@@ -7,6 +7,7 @@
     'brace-style' : ['error', '1tbs'],
     'curly' : ['error', 'multi-line', 'consistent'],
     'eqeqeq' : ['error', 'always', {'null' : 'ignore'}],
+    'no-confusing-arrow' : ['error'],
     'no-console' : 'off',
     'no-throw-literal' : 'off',
     'object-shorthand' : ['error', 'always'],
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/accessibility_common_test.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/accessibility_common_test.js
index 94091d8f..20d8b9f 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/accessibility_common_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/accessibility_common_test.js
@@ -62,18 +62,18 @@
     let pref = await this.getPref('settings.a11y.autoclick');
     assertEquals('settings.a11y.autoclick', pref.key);
     assertTrue(pref.value);
-    assertTrue(!!accessibilityCommon.getAutoclickForTest());
+    assertTrue(Boolean(accessibilityCommon.getAutoclickForTest()));
 
     // Next, flip on screen magnifier and verify all prefs and internal state.
     await this.setPref('settings.a11y.screen_magnifier', true);
     pref = await this.getPref('settings.a11y.autoclick');
     assertEquals('settings.a11y.autoclick', pref.key);
     assertTrue(pref.value);
-    assertTrue(!!accessibilityCommon.getAutoclickForTest());
+    assertTrue(Boolean(accessibilityCommon.getAutoclickForTest()));
     pref = await this.getPref('settings.a11y.screen_magnifier');
     assertEquals('settings.a11y.screen_magnifier', pref.key);
     assertTrue(pref.value);
-    assertTrue(!!accessibilityCommon.getMagnifierForTest());
+    assertTrue(Boolean(accessibilityCommon.getMagnifierForTest()));
 
     // Then, flip off autoclick and verify all prefs and internal state.
     await this.setPref('settings.a11y.autoclick', false);
@@ -84,7 +84,7 @@
     pref = await this.getPref('settings.a11y.screen_magnifier');
     assertEquals('settings.a11y.screen_magnifier', pref.key);
     assertTrue(pref.value);
-    assertTrue(!!accessibilityCommon.getMagnifierForTest());
+    assertTrue(Boolean(accessibilityCommon.getMagnifierForTest()));
 
     // Unfortunately, turning off all features would remove the extension. Flip
     // autoclick back on.
@@ -92,18 +92,18 @@
     pref = await this.getPref('settings.a11y.autoclick');
     assertEquals('settings.a11y.autoclick', pref.key);
     assertTrue(pref.value);
-    assertTrue(!!accessibilityCommon.getAutoclickForTest());
+    assertTrue(Boolean(accessibilityCommon.getAutoclickForTest()));
     pref = await this.getPref('settings.a11y.screen_magnifier');
     assertEquals('settings.a11y.screen_magnifier', pref.key);
     assertTrue(pref.value);
-    assertTrue(!!accessibilityCommon.getMagnifierForTest());
+    assertTrue(Boolean(accessibilityCommon.getMagnifierForTest()));
 
     // And, finally flip screen magnifier off.
     await this.setPref('settings.a11y.screen_magnifier', false);
     pref = await this.getPref('settings.a11y.autoclick');
     assertEquals('settings.a11y.autoclick', pref.key);
     assertTrue(pref.value);
-    assertTrue(!!accessibilityCommon.getAutoclickForTest());
+    assertTrue(Boolean(accessibilityCommon.getAutoclickForTest()));
     pref = await this.getPref('settings.a11y.screen_magnifier');
     assertEquals('settings.a11y.screen_magnifier', pref.key);
     assertFalse(pref.value);
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier.js
index 4bf5948..d1eaac66 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier.js
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier.js
@@ -173,7 +173,7 @@
     prefs.forEach((pref) => {
       switch (pref.key) {
         case Magnifier.Prefs.SCREEN_MAGNIFIER_FOCUS_FOLLOWING:
-          this.screenMagnifierFocusFollowing_ = !!pref.value;
+          this.screenMagnifierFocusFollowing_ = Boolean(pref.value);
           break;
         default:
           return;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
index 6635b48..2d7e7a3 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
@@ -6,6 +6,7 @@
 import {ChromeVoxState} from '/chromevox/background/chromevox_state.js';
 import {ChromeVoxBackground} from '/chromevox/background/classic_background.js';
 import {CommandHandler} from '/chromevox/background/command_handler.js';
+import {ConsoleTts} from '/chromevox/background/console_tts.js';
 import {DesktopAutomationHandler} from '/chromevox/background/desktop_automation_handler.js';
 import {DesktopAutomationInterface} from '/chromevox/background/desktop_automation_interface.js';
 import {DownloadHandler} from '/chromevox/background/download_handler.js';
@@ -85,6 +86,7 @@
     });
 
     BackgroundKeyboardHandler.init();
+    ConsoleTts.init();
     DesktopAutomationHandler.init();
     DownloadHandler.init();
     FindHandler.init();
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/classic_background.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/classic_background.js
index 04ad1bf..6e3c24f3 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/classic_background.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/classic_background.js
@@ -24,10 +24,6 @@
   constructor() {
     ChromeVoxBackground.readPrefs();
 
-    const consoleTts = ConsoleTts.getInstance();
-    consoleTts.setEnabled(
-        ChromeVoxPrefs.instance.getPrefs()['enableSpeechLogging'] === 'true');
-
     /**
      * Chrome's actual TTS which knows and cares about pitch, volume, etc.
      * @type {TtsBackground}
@@ -38,7 +34,9 @@
     /**
      * @type {TtsInterface}
      */
-    this.tts = new CompositeTts().add(this.backgroundTts_).add(consoleTts);
+    this.tts = new CompositeTts()
+                   .add(this.backgroundTts_)
+                   .add(ConsoleTts.getInstance());
 
     this.addBridgeListener();
 
@@ -58,12 +56,11 @@
 
     // Set up a message passing system for goog.provide() calls from
     // within the content scripts.
-    chrome.extension.onMessage.addListener(function(request, sender, callback) {
+    chrome.extension.onMessage.addListener((request, sender, callback) => {
       if (request['srcFile']) {
         const srcFile = request['srcFile'];
-        InjectedScriptLoader.fetchCode([srcFile], function(code) {
-          callback({'code': code[srcFile]});
-        });
+        InjectedScriptLoader.fetchCode(
+            [srcFile], code => callback({'code': code[srcFile]}));
       }
       return true;
     });
@@ -204,9 +201,7 @@
             'window.CLOSURE_NO_DEPS = true\n');
 
         // Now inject the ChromeVox content script code into the tab.
-        listOfFiles.forEach(function(file) {
-          executeScript(code[file]);
-        });
+        listOfFiles.forEach(file => executeScript(code[file]));
       }
     };
 
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/console_tts.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/console_tts.js
index f053cd1..69b39f0 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/console_tts.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/console_tts.js
@@ -5,6 +5,7 @@
 /**
  * @fileoverview A TTS engine that writes to window.console.
  */
+import {ChromeVoxPrefs} from '/chromevox/background/prefs.js';
 
 /**
  * @implements {TtsInterface}
@@ -19,6 +20,12 @@
     this.enabled_ = false;
   }
 
+  static init() {
+    const consoleTts = ConsoleTts.getInstance();
+    consoleTts.setEnabled(
+        ChromeVoxPrefs.instance.getPrefs()['enableSpeechLogging'] === 'true');
+  }
+
   /** @return {!ConsoleTts} */
   static getInstance() {
     if (!ConsoleTts.instance_) {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/logging/log_store.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/logging/log_store.js
index 6a8017c..71dc266 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/logging/log_store.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/logging/log_store.js
@@ -160,8 +160,8 @@
 LogStore.instance;
 
 BridgeHelper.registerHandler(
-    BridgeTargets.LOG_STORE, BridgeActions.CLEAR_LOG,
+    BridgeConstants.LogStore.TARGET, BridgeConstants.LogStore.Action.CLEAR_LOG,
     () => LogStore.instance.clearLog());
 BridgeHelper.registerHandler(
-    BridgeTargets.LOG_STORE, BridgeActions.GET_LOGS,
+    BridgeConstants.LogStore.TARGET, BridgeConstants.LogStore.Action.GET_LOGS,
     () => LogStore.instance.getLogs());
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/background_bridge.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/background_bridge.js
index 0d04aa75..e90cea23 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/background_bridge.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/background_bridge.js
@@ -179,7 +179,8 @@
    */
   async clearLog() {
     return BridgeHelper.sendMessage(
-        BridgeTargets.LOG_STORE, BridgeActions.CLEAR_LOG);
+        BridgeConstants.LogStore.TARGET,
+        BridgeConstants.LogStore.Action.CLEAR_LOG);
   },
 
   /**
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/bridge_constants.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/bridge_constants.js
index a020bb7..872f71b7 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/bridge_constants.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/bridge_constants.js
@@ -14,7 +14,6 @@
 /** @enum {string} */
 BridgeTargets = {
   EVENT_STREAM_LOGGER: 'EventStreamLogger',
-  LOG_STORE: 'LogStore',
   PANEL: 'Panel',
   PANEL_BACKGROUND: 'PanelBackground',
   USER_ACTION_MONITOR: 'UserActionMonitor',
@@ -101,6 +100,16 @@
       SET_ENABLED: 'setEnabled',
     },
   },
+
+  LogStore: {
+    /** @public {BridgeTarget} */
+    TARGET: 'LogStore',
+    /** @enum {string} */
+    Action: {
+      CLEAR_LOG: 'clearLog',
+      GET_LOGS: 'getLogs',
+    },
+  },
 };
 
 /**
@@ -108,7 +117,6 @@
  */
 BridgeActions = {
   ADD_MENU_ITEM: 'addMenuItem',
-  CLEAR_LOG: 'clearLog',
   CREATE: 'create',
   CREATE_ALL_NODE_MENU_BACKGROUNDS: 'createAllNodeMenuBackgrounds',
   CREATE_NEW_I_SEARCH: 'createNewISearch',
@@ -116,7 +124,6 @@
   DESTROY_I_SEARCH: 'destroyISearch',
   FOCUS_TAB: 'focusTab',
   GET_ACTIONS_FOR_CURRENT_NODE: 'getActionsForCurrentNode',
-  GET_LOGS: 'getLogs',
   GET_TAB_MENU_DATA: 'getTabMenuData',
   INCREMENTAL_SEARCH: 'incrementalSearch',
   NODE_MENU_CALLBACK: 'nodeMenuCallback',
@@ -138,6 +145,7 @@
  *           BridgeConstants.ChromeVoxState.Action |
  *           BridgeConstants.CommandHandler.Action |
  *           BridgeConstants.EventSourceState.Action |
- *           BridgeConstants.GestureCommandHandler.Action}
+ *           BridgeConstants.GestureCommandHandler.Action |
+ *           BridgeConstants.LogStore.Action}
  */
 BridgeAction;
diff --git a/chrome/browser/resources/chromeos/accessibility/common/automation_predicate.js b/chrome/browser/resources/chromeos/accessibility/common/automation_predicate.js
index 6fc04a0..3d5a7893 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/automation_predicate.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/automation_predicate.js
@@ -176,7 +176,7 @@
    */
   static editText(node) {
     return node.role === Role.TEXT_FIELD ||
-        (node.state[State.EDITABLE] && !!node.parent &&
+        (node.state[State.EDITABLE] && Boolean(node.parent) &&
          !node.parent.state[State.EDITABLE]);
   }
 
@@ -185,7 +185,7 @@
    * @return {boolean}
    */
   static image(node) {
-    return node.isImage && !!(node.name || node.url);
+    return node.isImage && Boolean(node.name || node.url);
   }
 
   /**
@@ -211,11 +211,11 @@
    * @return {boolean}
    */
   static touchLeaf(node) {
-    return !!(!node.firstChild && node.name) || node.role === Role.BUTTON ||
-        node.role === Role.CHECK_BOX || node.role === Role.POP_UP_BUTTON ||
-        node.role === Role.PORTAL || node.role === Role.RADIO_BUTTON ||
-        node.role === Role.SLIDER || node.role === Role.SWITCH ||
-        node.role === Role.TEXT_FIELD ||
+    return Boolean(!node.firstChild && node.name) ||
+        node.role === Role.BUTTON || node.role === Role.CHECK_BOX ||
+        node.role === Role.POP_UP_BUTTON || node.role === Role.PORTAL ||
+        node.role === Role.RADIO_BUTTON || node.role === Role.SLIDER ||
+        node.role === Role.SWITCH || node.role === Role.TEXT_FIELD ||
         node.role === Role.TEXT_FIELD_WITH_COMBO_BOX ||
         (node.role === Role.MENU_ITEM && !hasActionableDescendant(node)) ||
         // Simple list items should be leaves.
@@ -269,18 +269,19 @@
    * @return {boolean}
    */
   static leaf(node) {
-    return AutomationPredicate.touchLeaf(node) || node.role === Role.LIST_BOX ||
+    return Boolean(
+        AutomationPredicate.touchLeaf(node) || node.role === Role.LIST_BOX ||
         // A node acting as a label should be a leaf if it has no actionable
         // controls.
-        (!!node.labelFor && node.labelFor.length > 0 &&
+        (node.labelFor && node.labelFor.length > 0 &&
          !isActionableOrHasActionableDescendant(node)) ||
-        (!!node.descriptionFor && node.descriptionFor.length > 0 &&
+        (node.descriptionFor && node.descriptionFor.length > 0 &&
          !isActionableOrHasActionableDescendant(node)) ||
         (node.activeDescendantFor && node.activeDescendantFor.length > 0) ||
         node.state[State.INVISIBLE] || node.children.every(function(n) {
           return n.state[State.INVISIBLE];
         }) ||
-        !!AutomationPredicate.math(node);
+        AutomationPredicate.math(node));
   }
 
   /**
@@ -288,7 +289,7 @@
    * @return {boolean}
    */
   static leafWithText(node) {
-    return AutomationPredicate.leaf(node) && !!(node.name || node.value);
+    return AutomationPredicate.leaf(node) && Boolean(node.name || node.value);
   }
 
   /**
@@ -478,12 +479,12 @@
         return true;
       case Role.DIALOG:
         if (node.root.role !== Role.DESKTOP) {
-          return !!node.modal;
+          return Boolean(node.modal);
         }
 
         // The below logic handles nested dialogs properly in the desktop tree
         // like that found in a bubble view.
-        return !!node.parent && node.parent.role === Role.WINDOW &&
+        return Boolean(node.parent) && node.parent.role === Role.WINDOW &&
             node.parent.children.every(function(child) {
               return node.role === Role.WINDOW || node.role === Role.DIALOG;
             });
@@ -583,7 +584,7 @@
    * @return {boolean}
    */
   static checkable(node) {
-    return !!node.checked;
+    return Boolean(node.checked);
   }
 
   /**
@@ -703,7 +704,7 @@
    * @return {boolean}
    */
   static autoScrollable(node) {
-    return !!node.scrollable &&
+    return Boolean(node.scrollable) &&
         (node.standardActions.includes(
              chrome.automation.ActionType.SCROLL_FORWARD) ||
          node.standardActions.includes(
@@ -717,7 +718,8 @@
    * @return {boolean}
    */
   static math(node) {
-    return node.role === Role.MATH || !!node.htmlAttributes['data-mathml'];
+    return node.role === Role.MATH ||
+        Boolean(node.htmlAttributes['data-mathml']);
   }
 
   /**
diff --git a/chrome/browser/resources/chromeos/accessibility/common/automation_predicate_test.js b/chrome/browser/resources/chromeos/accessibility/common/automation_predicate_test.js
index 56cc8c2..b2d66794 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/automation_predicate_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/automation_predicate_test.js
@@ -15,10 +15,11 @@
   const root = await this.runWithLoadedTree(site);
   // Text field is equivalent to text field with combo box.
   const textField = root.find({role: chrome.automation.RoleType.TEXT_FIELD});
-  assertTrue(!!textField, 'No text field found.');
+  assertTrue(Boolean(textField), 'No text field found.');
   const textFieldWithComboBox =
       root.find({role: chrome.automation.RoleType.TEXT_FIELD_WITH_COMBO_BOX});
-  assertTrue(!!textFieldWithComboBox, 'No text field with combo box found.');
+  assertTrue(
+      Boolean(textFieldWithComboBox), 'No text field with combo box found.');
 
   // Gather all potential predicate names.
   const keys = Object.getOwnPropertyNames(AutomationPredicate);
@@ -32,7 +33,7 @@
     const predicate = AutomationPredicate[key];
     if (predicate(textField)) {
       assertTrue(
-          !!predicate(textFieldWithComboBox),
+          Boolean(predicate(textFieldWithComboBox)),
           `Textfield with combo box should match predicate ${key}`);
     }
   }
diff --git a/chrome/browser/resources/chromeos/accessibility/common/testing/mock_accessibility_private.js b/chrome/browser/resources/chromeos/accessibility/common/testing/mock_accessibility_private.js
index c0971ea..23be538b 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/testing/mock_accessibility_private.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/testing/mock_accessibility_private.js
@@ -179,7 +179,7 @@
    * Called when AccessibilityCommon wants to set the focus rings. We can
    * assume that it is only setting one set of rings at a time, and safely
    * extract focusRingInfos[0].rects.
-   * @param {!Array<!!chrome.accessibilityPrivate.FocusRingInfo>} focusRingInfos
+   * @param {!Array<!chrome.accessibilityPrivate.FocusRingInfo>} focusRingInfos
    */
   setFocusRings: (focusRingInfos) => {
     MockAccessibilityPrivate.focusRings_ = focusRingInfos;
diff --git a/chrome/browser/resources/chromeos/accessibility/common/testing/mock_speech_recognition_private.js b/chrome/browser/resources/chromeos/accessibility/common/testing/mock_speech_recognition_private.js
index f063602..89ee2ca 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/testing/mock_speech_recognition_private.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/testing/mock_speech_recognition_private.js
@@ -159,7 +159,7 @@
         this.started_,
         'Speech recognition should be active when firing a result event');
     assertTrue(
-        !!this.onResultListener_,
+        Boolean(this.onResultListener_),
         'Client should have added an onResult listener');
 
     // The real API will fire an onResult event.
@@ -172,7 +172,8 @@
         this.started_,
         'Speech recognition should be active when firing a stop event');
     assertTrue(
-        !!this.onStopListener_, 'Client should have added an onStop listener');
+        Boolean(this.onStopListener_),
+        'Client should have added an onStop listener');
 
     // The real API will turn off speech recognition and fire an onStop event.
     this.started_ = false;
@@ -185,7 +186,7 @@
         this.started_,
         'Speech recognition should be active when firing an error event');
     assertTrue(
-        !!this.onErrorListener_,
+        Boolean(this.onErrorListener_),
         'Client should have added an onError listener');
 
     // The real API will fire an onError and an onStop event.
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils.js
index eccc211..8a86fc8 100644
--- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils.js
+++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils.js
@@ -66,7 +66,7 @@
    * @return {boolean} whether this node was marked user-select:none
    */
   static isNotSelectable(node) {
-    return !!(
+    return Boolean(
         node &&
         (node.notUserSelectableStyle ||
          (node.parent && node.parent.notUserSelectableStyle)));
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js
index f58baf8..4f95d571 100644
--- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js
+++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js
@@ -265,7 +265,7 @@
             if (pref === undefined) {
               return;
             }
-            this.enhancedNetworkVoicesAllowed_ = !!pref.value;
+            this.enhancedNetworkVoicesAllowed_ = Boolean(pref.value);
           });
     };
     const updatePrefs = () => {
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/item_scan_manager_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/item_scan_manager_test.js
index 61f4f603..4115c30 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/item_scan_manager_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/item_scan_manager_test.js
@@ -483,11 +483,11 @@
       // Trigger a children changed on the group.
       const automationGroup =
           rootWebArea.find({role: chrome.automation.RoleType.GROUP});
-      assertTrue(!!automationGroup);
+      assertTrue(Boolean(automationGroup));
       const group = Navigator.byItem.group_;
-      assertTrue(!!group);
+      assertTrue(Boolean(group));
       const handler = group.childrenChangedHandler_;
-      assertTrue(!!handler);
+      assertTrue(Boolean(handler));
 
       // Fake a children changed event.
       handler.eventStack_ = [{
@@ -545,21 +545,21 @@
              widget1.className !== 'Widget') {
         widget1 = widget1.parent;
       }
-      assertTrue(!!widget1);
+      assertTrue(Boolean(widget1));
 
       let widget2 = button2.automationNode;
       while (widget2.role !== chrome.automation.RoleType.WINDOW ||
              widget2.className !== 'Widget') {
         widget2 = widget2.parent;
       }
-      assertTrue(!!widget2);
+      assertTrue(Boolean(widget2));
 
       const titleBar1 =
           widget1.find({role: chrome.automation.RoleType.TITLE_BAR});
-      assertTrue(!!titleBar1);
+      assertTrue(Boolean(titleBar1));
       const titleBar2 =
           widget2.find({role: chrome.automation.RoleType.TITLE_BAR});
-      assertTrue(!!titleBar2);
+      assertTrue(Boolean(titleBar2));
 
       // The focus is currently on widget2 (since button2 has focus). Start with
       // focusing widget1 which should occur as a result of moving SA to title
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node_test.js
index bd2f2e99..712100e 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node_test.js
@@ -33,10 +33,10 @@
     root.children_ = [groupNode];
 
     // Try asking for the location of the group.
-    assertTrue(!!groupNode.location);
+    assertTrue(Boolean(groupNode.location));
 
     // Try again after clearing one of the button's underlying node.
     buttonNode.baseNode_ = undefined;
-    assertTrue(!!groupNode.location);
+    assertTrue(Boolean(groupNode.location));
   });
 });
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/keyboard_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/keyboard_node.js
index acfefec..11dd273 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/keyboard_node.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/keyboard_node.js
@@ -185,9 +185,9 @@
    */
   static isKeyboardVisible_() {
     const keyboardObject = KeyboardRootNode.getKeyboardObject();
-    return !!keyboardObject &&
-        SwitchAccessPredicate.isVisible(keyboardObject) &&
-        !!keyboardObject.find({role: chrome.automation.RoleType.ROOT_WEB_AREA});
+    return Boolean(
+        keyboardObject && SwitchAccessPredicate.isVisible(keyboardObject) &&
+        keyboardObject.find({role: chrome.automation.RoleType.ROOT_WEB_AREA}));
   }
 
   /**
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/slider_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/slider_node.js
index a68610b..d1ebed8 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/slider_node.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/slider_node.js
@@ -17,7 +17,7 @@
    */
   constructor(baseNode, parent) {
     super(baseNode, parent);
-    this.isCustomSlider_ = !!baseNode.htmlAttributes.role;
+    this.isCustomSlider_ = Boolean(baseNode.htmlAttributes.role);
   }
 
   /** @override */
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/switch_access_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/switch_access_node.js
index d2923cb..d3558a1 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/switch_access_node.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/switch_access_node.js
@@ -180,7 +180,7 @@
    * @return {boolean}
    */
   isValidAndVisible() {
-    return this.valid_ && !!this.location;
+    return this.valid_ && Boolean(this.location);
   }
 
   /**
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/preference_manager.js b/chrome/browser/resources/chromeos/accessibility/switch_access/preference_manager.js
index 79f6ebc..9714677b 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/preference_manager.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/preference_manager.js
@@ -106,7 +106,9 @@
     const previousSet = previousPref ? Object.keys(previousPref).length : false;
 
     const autoScanEnabled =
-        !!this.getBoolean_(SAConstants.Preference.AUTO_SCAN_ENABLED);
+        // getBoolean_() returns null if a value is not found, so we force the
+        // value to be a boolean (defaulting to false).
+        Boolean(this.getBoolean_(SAConstants.Preference.AUTO_SCAN_ENABLED));
 
     if (!selectSet) {
       return false;
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/saatlite/compiler/parser.js b/chrome/browser/resources/chromeos/accessibility/switch_access/saatlite/compiler/parser.js
index 460598654..5fbbeda 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/saatlite/compiler/parser.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/saatlite/compiler/parser.js
@@ -1311,7 +1311,7 @@
             // info.value = null;
             // info.value_stack = null;
             // ...
-            var rec = !!this.recoverable;
+            var rec = Boolean(this.recoverable);
             for (var key in this) {
               if (this.hasOwnProperty(key) && typeof key === 'object') {
                 this[key] = undefined;
@@ -2043,7 +2043,7 @@
         /** @constructor */
         var pei = {
           errStr: msg,
-          recoverable: !!recoverable,
+          recoverable: Boolean(recoverable),
           text: this.match,  // This one MAY be empty; userland code should use
                              // the `upcomingInput` API to obtain more text
                              // which follows the 'lexer cursor position'...
@@ -2070,7 +2070,7 @@
             // info.yy = null;
             // info.lexer = null;
             // ...
-            var rec = !!this.recoverable;
+            var rec = Boolean(this.recoverable);
 
             for (var key in this) {
               if (this.hasOwnProperty(key) && typeof key === 'object') {
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_predicate.js b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_predicate.js
index 6addb45..869087e 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_predicate.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_predicate.js
@@ -181,9 +181,10 @@
    * @param {AutomationNode} node
    * @return {boolean}
    */
-  isVisible: (node) => !node.state[StateType.OFFSCREEN] && !!node.location &&
+  isVisible: (node) => Boolean(
+      !node.state[StateType.OFFSCREEN] && node.location &&
       node.location.top >= 0 && node.location.left >= 0 &&
-      !node.state[StateType.INVISIBLE],
+      !node.state[StateType.INVISIBLE]),
 
   /**
    * Returns true if there is an interesting node in the subtree containing
@@ -215,17 +216,18 @@
    * @param {AutomationNode} node
    * @return {boolean}
    */
-  isTextInput: (node) => !!node && !!node.state[StateType.EDITABLE],
+  isTextInput: (node) => Boolean(node && node.state[StateType.EDITABLE]),
 
   /**
    * Returns true if |node| should be considered a window.
    * @param {AutomationNode} node
    * @return {boolean}
    */
-  isWindow: (node) => !!node &&
+  isWindow: (node) => Boolean(
+      node &&
       (node.role === chrome.automation.RoleType.WINDOW ||
-       (node.role === chrome.automation.RoleType.CLIENT && !!node.parent &&
-        node.parent.role === chrome.automation.RoleType.WINDOW)),
+       (node.role === chrome.automation.RoleType.CLIENT && node.parent &&
+        node.parent.role === chrome.automation.RoleType.WINDOW))),
 
   /**
    * Returns a Restrictions object ready to be passed to AutomationTreeWalker.
diff --git a/chrome/browser/resources/connectors_internals/BUILD.gn b/chrome/browser/resources/connectors_internals/BUILD.gn
index 86ad7c8c..431f457 100644
--- a/chrome/browser/resources/connectors_internals/BUILD.gn
+++ b/chrome/browser/resources/connectors_internals/BUILD.gn
@@ -3,22 +3,33 @@
 # found in the LICENSE file.
 
 import("//tools/grit/grit_rule.gni")
-import("//tools/grit/preprocess_if_expr.gni")
-import("//tools/polymer/html_to_js.gni")
+import("//tools/polymer/html_to_wrapper.gni")
 import("//tools/typescript/ts_library.gni")
 import("//ui/webui/resources/tools/generate_grd.gni")
 
-preprocess_folder = "preprocessed"
 resources_grd_file = "$target_gen_dir/resources.grd"
 
-ts_files = [
+web_component_files = [
   "app.ts",
   "connectors_tabs.ts",
   "zero_trust_connector.ts",
 ]
 
-html_to_js("web_components") {
-  js_files = ts_files
+# Files that are passed as input to html_to_wrapper().
+html_files = []
+foreach(f, web_component_files) {
+  html_files += [ string_replace(f, ".ts", ".html") ]
+}
+
+# Files that are generated by html_to_wrapper().
+html_wrapper_files = []
+foreach(f, html_files) {
+  html_wrapper_files += [ f + ".ts" ]
+}
+
+html_to_wrapper("html_wrapper_files") {
+  in_files = html_files
+  template = "native"
 }
 
 copy("copy_mojo") {
@@ -28,25 +39,25 @@
   mojom_folder =
       "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/connectors_internals/"
   sources = [ "$mojom_folder/connectors_internals.mojom-webui.js" ]
-  outputs = [ "$target_gen_dir/$preprocess_folder/{{source_file_part}}" ]
+  outputs = [ "$target_gen_dir/{{source_file_part}}" ]
 }
 
-preprocess_if_expr("preprocess_web_components") {
-  deps = [ ":web_components" ]
-  in_folder = target_gen_dir
-  out_folder = "$target_gen_dir/$preprocess_folder"
-  in_files = ts_files
+copy("copy_src") {
+  sources = web_component_files
+  outputs = [ "$target_gen_dir/{{source_file_part}}" ]
 }
 
 ts_library("build_ts") {
-  root_dir = "$target_gen_dir/$preprocess_folder"
+  root_dir = target_gen_dir
   out_dir = "$target_gen_dir/tsc"
   tsconfig_base = "tsconfig_base.json"
-  in_files = ts_files + [ "connectors_internals.mojom-webui.js" ]
+  in_files = web_component_files + html_wrapper_files +
+             [ "connectors_internals.mojom-webui.js" ]
   deps = [ "//ui/webui/resources:library" ]
   extra_deps = [
     ":copy_mojo",
-    ":preprocess_web_components",
+    ":copy_src",
+    ":html_wrapper_files",
   ]
 }
 
diff --git a/chrome/browser/resources/connectors_internals/app.ts b/chrome/browser/resources/connectors_internals/app.ts
index 870d7f9..510141c 100644
--- a/chrome/browser/resources/connectors_internals/app.ts
+++ b/chrome/browser/resources/connectors_internals/app.ts
@@ -7,8 +7,8 @@
 
 import {CustomElement} from 'chrome://resources/js/custom_element.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {getTrustedHTML} from 'chrome://resources/js/static_types.js';
 
+import {getTemplate} from './app.html.js';
 import {ConnectorsTabsElement} from './connectors_tabs.js';
 
 class ConnectorsInternalsAppElement extends CustomElement {
@@ -17,7 +17,7 @@
   }
 
   static override get template() {
-    return getTrustedHTML`{__html_template__}`;
+    return getTemplate();
   }
 
   constructor() {
diff --git a/chrome/browser/resources/connectors_internals/connectors_tabs.ts b/chrome/browser/resources/connectors_internals/connectors_tabs.ts
index 78a1506..1e3fc1f 100644
--- a/chrome/browser/resources/connectors_internals/connectors_tabs.ts
+++ b/chrome/browser/resources/connectors_internals/connectors_tabs.ts
@@ -6,8 +6,8 @@
 
 import {CustomElement} from 'chrome://resources/js/custom_element.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {getTrustedHTML} from 'chrome://resources/js/static_types.js';
 
+import {getTemplate} from './connectors_tabs.html.js';
 import {ZeroTrustConnectorElement} from './zero_trust_connector.js';
 
 interface ConnectorTab {
@@ -37,7 +37,7 @@
   }
 
   static override get template() {
-    return getTrustedHTML`{__html_template__}`;
+    return getTemplate();
   }
 
   private get tabHeaders(): NodeList {
diff --git a/chrome/browser/resources/connectors_internals/zero_trust_connector.ts b/chrome/browser/resources/connectors_internals/zero_trust_connector.ts
index 4fe5a81..985f3630 100644
--- a/chrome/browser/resources/connectors_internals/zero_trust_connector.ts
+++ b/chrome/browser/resources/connectors_internals/zero_trust_connector.ts
@@ -3,9 +3,9 @@
 // found in the LICENSE file.
 
 import {CustomElement} from 'chrome://resources/js/custom_element.js';
-import {getTrustedHTML} from 'chrome://resources/js/static_types.js';
 
 import {KeyInfo, KeyManagerInitializedValue, KeyTrustLevel, KeyType, PageHandler, PageHandlerInterface, ZeroTrustState} from './connectors_internals.mojom-webui.js';
+import {getTemplate} from './zero_trust_connector.html.js';
 
 const TrustLevelStringMap = {
   [KeyTrustLevel.UNSPECIFIED]: 'Unspecified',
@@ -25,7 +25,7 @@
   }
 
   static override get template() {
-    return getTrustedHTML`{__html_template__}`;
+    return getTemplate();
   }
 
   public set enabledString(str: string) {
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_browser_proxy.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_browser_proxy.js
index 7f9c33a..d117609f 100644
--- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_browser_proxy.js
@@ -39,8 +39,21 @@
   setSelectedAlbums(settings) {}
 }
 
+/** @type {?AmbientModeBrowserProxy} */
+let instance = null;
+
 /** @implements {AmbientModeBrowserProxy} */
 export class AmbientModeBrowserProxyImpl {
+  /** @return {!AmbientModeBrowserProxy} */
+  static getInstance() {
+    return instance || (instance = new AmbientModeBrowserProxyImpl());
+  }
+
+  /** @param {!AmbientModeBrowserProxy} obj */
+  static setInstance(obj) {
+    instance = obj;
+  }
+
   /** @override */
   requestSettings() {
     chrome.send('requestSettings');
@@ -60,17 +73,4 @@
   setSelectedAlbums(settings) {
     chrome.send('setSelectedAlbums', [settings]);
   }
-
-  /** @return {!AmbientModeBrowserProxy} */
-  static getInstance() {
-    return instance || (instance = new AmbientModeBrowserProxyImpl());
-  }
-
-  /** @param {!AmbientModeBrowserProxy} obj */
-  static setInstance(obj) {
-    instance = obj;
-  }
 }
-
-/** @type {?AmbientModeBrowserProxy} */
-let instance = null;
diff --git a/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_page_browser_proxy.js b/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_page_browser_proxy.js
index 487fc233..2217bde4 100644
--- a/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_page_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_page_browser_proxy.js
@@ -10,15 +10,13 @@
   isDeviceBlockedByPolicy(address) {}
 }
 
+/** @type {?BluetoothPageBrowserProxy} */
+let instance = null;
+
 /**
  * @implements {BluetoothPageBrowserProxy}
  */
 export class BluetoothPageBrowserProxyImpl {
-  /** @override */
-  isDeviceBlockedByPolicy(address) {
-    return sendWithPromise('isDeviceBlockedByPolicy', address);
-  }
-
   /** @return {!BluetoothPageBrowserProxy} */
   static getInstance() {
     return instance || (instance = new BluetoothPageBrowserProxyImpl());
@@ -28,7 +26,9 @@
   static setInstance(obj) {
     instance = obj;
   }
-}
 
-/** @type {?BluetoothPageBrowserProxy} */
-let instance = null;
+  /** @override */
+  isDeviceBlockedByPolicy(address) {
+    return sendWithPromise('isDeviceBlockedByPolicy', address);
+  }
+}
diff --git a/chrome/browser/resources/settings/chromeos/date_time_page/timezone_browser_proxy.js b/chrome/browser/resources/settings/chromeos/date_time_page/timezone_browser_proxy.js
index e5b336f..2fb18a6 100644
--- a/chrome/browser/resources/settings/chromeos/date_time_page/timezone_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/date_time_page/timezone_browser_proxy.js
@@ -21,8 +21,21 @@
   getTimeZones() {}
 }
 
+/** @type {?TimeZoneBrowserProxy} */
+let instance = null;
+
 /** @implements {TimeZoneBrowserProxy} */
 export class TimeZoneBrowserProxyImpl {
+  /** @return {!TimeZoneBrowserProxy} */
+  static getInstance() {
+    return instance || (instance = new TimeZoneBrowserProxyImpl());
+  }
+
+  /** @param {!TimeZoneBrowserProxy} obj */
+  static setInstance(obj) {
+    instance = obj;
+  }
+
   /** @override */
   showParentAccessForTimeZone() {
     chrome.send('handleShowParentAccessForTimeZone');
@@ -42,17 +55,4 @@
   getTimeZones() {
     return sendWithPromise('getTimeZones');
   }
-
-  /** @return {!TimeZoneBrowserProxy} */
-  static getInstance() {
-    return instance || (instance = new TimeZoneBrowserProxyImpl());
-  }
-
-  /** @param {!TimeZoneBrowserProxy} obj */
-  static setInstance(obj) {
-    instance = obj;
-  }
 }
-
-/** @type {?TimeZoneBrowserProxy} */
-let instance = null;
diff --git a/chrome/browser/resources/settings/chromeos/device_page/device_page_browser_proxy.js b/chrome/browser/resources/settings/chromeos/device_page/device_page_browser_proxy.js
index dbcbccdf..e31f169 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/device_page_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/device_page/device_page_browser_proxy.js
@@ -236,10 +236,23 @@
   openMyFiles() {}
 }
 
+/** @type {?DevicePageBrowserProxy} */
+let instance = null;
+
 /**
  * @implements {DevicePageBrowserProxy}
  */
 export class DevicePageBrowserProxyImpl {
+  /** @return {!DevicePageBrowserProxy} */
+  static getInstance() {
+    return instance || (instance = new DevicePageBrowserProxyImpl());
+  }
+
+  /** @param {!DevicePageBrowserProxy} obj */
+  static setInstance(obj) {
+    instance = obj;
+  }
+
   /** @override */
   initializePointers() {
     chrome.send('initializePointerSettings');
@@ -354,17 +367,4 @@
   openMyFiles() {
     chrome.send('openMyFiles');
   }
-
-  /** @return {!DevicePageBrowserProxy} */
-  static getInstance() {
-    return instance || (instance = new DevicePageBrowserProxyImpl());
-  }
-
-  /** @param {!DevicePageBrowserProxy} obj */
-  static setInstance(obj) {
-    instance = obj;
-  }
 }
-
-/** @type {?DevicePageBrowserProxy} */
-let instance = null;
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/about_page_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_about_page/about_page_browser_proxy.js
index e8d3869..f168481 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/about_page_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/about_page_browser_proxy.js
@@ -246,10 +246,23 @@
   setConsumerAutoUpdate(enable) {}
 }
 
+/** @type {?AboutPageBrowserProxy} */
+let instance = null;
+
 /**
  * @implements {AboutPageBrowserProxy}
  */
 export class AboutPageBrowserProxyImpl {
+  /** @return {!AboutPageBrowserProxy} */
+  static getInstance() {
+    return instance || (instance = new AboutPageBrowserProxyImpl());
+  }
+
+  /** @param {!AboutPageBrowserProxy} obj */
+  static setInstance(obj) {
+    instance = obj;
+  }
+
   /** @override */
   pageReady() {
     chrome.send('aboutPageReady');
@@ -352,17 +365,4 @@
   setConsumerAutoUpdate(enable) {
     chrome.send('setConsumerAutoUpdate', [enable]);
   }
-
-  /** @return {!AboutPageBrowserProxy} */
-  static getInstance() {
-    return instance || (instance = new AboutPageBrowserProxyImpl());
-  }
-
-  /** @param {!AboutPageBrowserProxy} obj */
-  static setInstance(obj) {
-    instance = obj;
-  }
 }
-
-/** @type {?AboutPageBrowserProxy} */
-let instance = null;
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/device_name_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_about_page/device_name_browser_proxy.js
index f5bce8b..ed046079 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/device_name_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/device_name_browser_proxy.js
@@ -29,20 +29,13 @@
   attemptSetDeviceName(name) {}
 }
 
+/** @type {?DeviceNameBrowserProxy} */
+let instance = null;
+
 /**
  * @implements {DeviceNameBrowserProxy}
  */
 export class DeviceNameBrowserProxyImpl {
-  /** @override */
-  notifyReadyForDeviceName() {
-    return chrome.send('notifyReadyForDeviceName');
-  }
-
-  /** @override */
-  attemptSetDeviceName(name) {
-    return sendWithPromise('attemptSetDeviceName', name);
-  }
-
   /** @return {!DeviceNameBrowserProxy} */
   static getInstance() {
     return instance || (instance = new DeviceNameBrowserProxyImpl());
@@ -52,7 +45,14 @@
   static setInstance(obj) {
     instance = obj;
   }
-}
 
-/** @type {?DeviceNameBrowserProxy} */
-let instance = null;
+  /** @override */
+  notifyReadyForDeviceName() {
+    return chrome.send('notifyReadyForDeviceName');
+  }
+
+  /** @override */
+  attemptSetDeviceName(name) {
+    return sendWithPromise('attemptSetDeviceName', name);
+  }
+}
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_browser_proxy.js
index 26ebbfb..f6ca0a8 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_browser_proxy.js
@@ -30,20 +30,13 @@
   showAndroidAppsSettings(keyboardAction) {}
 }
 
+/** @type {?AndroidAppsBrowserProxy} */
+let instance = null;
+
 /**
  * @implements {AndroidAppsBrowserProxy}
  */
 export class AndroidAppsBrowserProxyImpl {
-  /** @override */
-  requestAndroidAppsInfo() {
-    chrome.send('requestAndroidAppsInfo');
-  }
-
-  /** @override */
-  showAndroidAppsSettings(keyboardAction) {
-    chrome.send('showAndroidAppsSettings', [keyboardAction]);
-  }
-
   /** @return {!AndroidAppsBrowserProxy} */
   static getInstance() {
     return instance || (instance = new AndroidAppsBrowserProxyImpl());
@@ -53,7 +46,14 @@
   static setInstance(obj) {
     instance = obj;
   }
-}
 
-/** @type {?AndroidAppsBrowserProxy} */
-let instance = null;
+  /** @override */
+  requestAndroidAppsInfo() {
+    chrome.send('requestAndroidAppsInfo');
+  }
+
+  /** @override */
+  showAndroidAppsSettings(keyboardAction) {
+    chrome.send('showAndroidAppsSettings', [keyboardAction]);
+  }
+}
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/browser_proxy.js
index 4d551a9..3b7b2fbf 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/browser_proxy.js
@@ -18,7 +18,20 @@
 
 import {FakePageHandler} from './fake_page_handler.js';
 
+/** @type {?BrowserProxy} */
+let instance = null;
+
 export class BrowserProxy {
+  /** @return {!BrowserProxy} */
+  static getInstance() {
+    return instance || (instance = new BrowserProxy());
+  }
+
+  /** @param {!BrowserProxy} obj */
+  static setInstance(obj) {
+    instance = obj;
+  }
+
   constructor() {
     /** @type {appManagement.mojom.PageCallbackRouter} */
     this.callbackRouter = new appManagement.mojom.PageCallbackRouter();
@@ -114,17 +127,4 @@
       this.callbackRouter = ComponentBrowserProxy.getInstance().callbackRouter;
     }
   }
-
-  /** @return {!BrowserProxy} */
-  static getInstance() {
-    return instance || (instance = new BrowserProxy());
-  }
-
-  /** @param {!BrowserProxy} obj */
-  static setInstance(obj) {
-    instance = obj;
-  }
 }
-
-/** @type {?BrowserProxy} */
-let instance = null;
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_browser_proxy.js
index fe9534e..b907a417 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_browser_proxy.js
@@ -22,18 +22,11 @@
   relaunchPluginVm() {}
 }
 
+/** @type {?PluginVmBrowserProxy} */
+let instance = null;
+
 /** @implements {PluginVmBrowserProxy} */
 export class PluginVmBrowserProxyImpl {
-  /** @override */
-  isRelaunchNeededForNewPermissions() {
-    return sendWithPromise('isRelaunchNeededForNewPermissions');
-  }
-
-  /** @override */
-  relaunchPluginVm() {
-    chrome.send('relaunchPluginVm');
-  }
-
   /** @return {!PluginVmBrowserProxy} */
   static getInstance() {
     return instance || (instance = new PluginVmBrowserProxyImpl());
@@ -43,7 +36,14 @@
   static setInstance(obj) {
     instance = obj;
   }
-}
 
-/** @type {?PluginVmBrowserProxy} */
-let instance = null;
+  /** @override */
+  isRelaunchNeededForNewPermissions() {
+    return sendWithPromise('isRelaunchNeededForNewPermissions');
+  }
+
+  /** @override */
+  relaunchPluginVm() {
+    chrome.send('relaunchPluginVm');
+  }
+}
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/store.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/store.js
index 519b178e..183cbc2 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/store.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/store.js
@@ -13,11 +13,10 @@
  * the store.
  */
 
-export class AppManagementStore extends Store {
-  constructor() {
-    super(createEmptyState(), reduceAction);
-  }
+/** @type {?AppManagementStore} */
+let instance = null;
 
+export class AppManagementStore extends Store {
   /** @return {!AppManagementStore} */
   static getInstance() {
     return instance || (instance = new AppManagementStore());
@@ -27,7 +26,8 @@
   static setInstance(obj) {
     instance = obj;
   }
-}
 
-/** @type {?AppManagementStore} */
-let instance = null;
+  constructor() {
+    super(createEmptyState(), reduceAction);
+  }
+}
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage_browser_proxy.js
index 0260a01f..d4a9e7d 100644
--- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage_browser_proxy.js
@@ -11,15 +11,13 @@
   requestFastPairDeviceSupport() {}
 }
 
+/** @type {?OsBluetoothDevicesSubpageBrowserProxy} */
+let instance = null;
+
 /**
  * @implements {OsBluetoothDevicesSubpageBrowserProxy}
  */
 export class OsBluetoothDevicesSubpageBrowserProxyImpl {
-  /** @override */
-  requestFastPairDeviceSupport() {
-    chrome.send('requestFastPairDeviceSupportStatus');
-  }
-
   /** @return {!OsBluetoothDevicesSubpageBrowserProxy} */
   static getInstance() {
     return instance ||
@@ -30,7 +28,9 @@
   static setInstance(obj) {
     instance = obj;
   }
-}
 
-/** @type {?OsBluetoothDevicesSubpageBrowserProxy} */
-let instance = null;
+  /** @override */
+  requestFastPairDeviceSupport() {
+    chrome.send('requestFastPairDeviceSupportStatus');
+  }
+}
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/languages_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_languages_page/languages_browser_proxy.js
index ebc406e..5ade78d 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/languages_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/languages_browser_proxy.js
@@ -28,10 +28,23 @@
   getInputMethodPrivate() {}
 }
 
+/** @type {?LanguagesBrowserProxy} */
+let instance = null;
+
 /**
  * @implements {LanguagesBrowserProxy}
  */
 export class LanguagesBrowserProxyImpl {
+  /** @return {!LanguagesBrowserProxy} */
+  static getInstance() {
+    return instance || (instance = new LanguagesBrowserProxyImpl());
+  }
+
+  /** @param {!LanguagesBrowserProxy} obj */
+  static setInstance(obj) {
+    instance = obj;
+  }
+
   /** @override */
   setProspectiveUILanguage(languageCode) {
     chrome.send('setProspectiveUILanguage', [languageCode]);
@@ -52,17 +65,4 @@
   getInputMethodPrivate() {
     return /** @type {!InputMethodPrivate} */ (chrome.inputMethodPrivate);
   }
-
-  /** @return {!LanguagesBrowserProxy} */
-  static getInstance() {
-    return instance || (instance = new LanguagesBrowserProxyImpl());
-  }
-
-  /** @param {!LanguagesBrowserProxy} obj */
-  static setInstance(obj) {
-    instance = obj;
-  }
 }
-
-/** @type {?LanguagesBrowserProxy} */
-let instance = null;
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/languages_metrics_proxy.js b/chrome/browser/resources/settings/chromeos/os_languages_page/languages_metrics_proxy.js
index f019f1e..96ffd86 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/languages_metrics_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/languages_metrics_proxy.js
@@ -87,8 +87,21 @@
   recordShortcutReminderDismissed(value) {}
 }
 
+/** @type {?LanguagesMetricsProxy} */
+let instance = null;
+
 /** @implements {LanguagesMetricsProxy} */
 export class LanguagesMetricsProxyImpl {
+  /** @return {!LanguagesMetricsProxy} */
+  static getInstance() {
+    return instance || (instance = new LanguagesMetricsProxyImpl());
+  }
+
+  /** @param {!LanguagesMetricsProxy} obj */
+  static setInstance(obj) {
+    instance = obj;
+  }
+
   /** @override */
   recordInteraction(interaction) {
     chrome.metricsPrivate.recordEnumerationValue(
@@ -144,17 +157,4 @@
         'ChromeOS.Settings.Inputs.ShortcutReminderDismissed', value,
         Object.keys(InputsShortcutReminderState).length);
   }
-
-  /** @return {!LanguagesMetricsProxy} */
-  static getInstance() {
-    return instance || (instance = new LanguagesMetricsProxyImpl());
-  }
-
-  /** @param {!LanguagesMetricsProxy} obj */
-  static setInstance(obj) {
-    instance = obj;
-  }
 }
-
-/** @type {?LanguagesMetricsProxy} */
-let instance = null;
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/account_manager_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_people_page/account_manager_browser_proxy.js
index 6f989513..0a9e5ce2 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/account_manager_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/account_manager_browser_proxy.js
@@ -63,10 +63,23 @@
   changeArcAvailability(account, isAvailableInArc) {}
 }
 
+/** @type {?AccountManagerBrowserProxy} */
+let instance = null;
+
 /**
  * @implements {AccountManagerBrowserProxy}
  */
 export class AccountManagerBrowserProxyImpl {
+  /** @return {!AccountManagerBrowserProxy} */
+  static getInstance() {
+    return instance || (instance = new AccountManagerBrowserProxyImpl());
+  }
+
+  /** @param {!AccountManagerBrowserProxy} obj */
+  static setInstance(obj) {
+    instance = obj;
+  }
+
   /** @override */
   getAccounts() {
     return sendWithPromise('getAccounts');
@@ -96,17 +109,4 @@
   changeArcAvailability(account, isAvailableInArc) {
     chrome.send('changeArcAvailability', [account, isAvailableInArc]);
   }
-
-  /** @return {!AccountManagerBrowserProxy} */
-  static getInstance() {
-    return instance || (instance = new AccountManagerBrowserProxyImpl());
-  }
-
-  /** @param {!AccountManagerBrowserProxy} obj */
-  static setInstance(obj) {
-    instance = obj;
-  }
 }
-
-/** @type {?AccountManagerBrowserProxy} */
-let instance = null;
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_browser_proxy.js
index 998a6b5..52096ec 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_browser_proxy.js
@@ -97,10 +97,23 @@
   fakeScanComplete() {}
 }
 
+/** @type {?FingerprintBrowserProxy} */
+let instance = null;
+
 /**
  * @implements {FingerprintBrowserProxy}
  */
 export class FingerprintBrowserProxyImpl {
+  /** @return {!FingerprintBrowserProxy} */
+  static getInstance() {
+    return instance || (instance = new FingerprintBrowserProxyImpl());
+  }
+
+  /** @param {!FingerprintBrowserProxy} obj */
+  static setInstance(obj) {
+    instance = obj;
+  }
+
   /** @override */
   getFingerprintsList() {
     return sendWithPromise('getFingerprintsList');
@@ -140,17 +153,4 @@
   fakeScanComplete() {
     chrome.send('fakeScanComplete');
   }
-
-  /** @return {!FingerprintBrowserProxy} */
-  static getInstance() {
-    return instance || (instance = new FingerprintBrowserProxyImpl());
-  }
-
-  /** @param {!FingerprintBrowserProxy} obj */
-  static setInstance(obj) {
-    instance = obj;
-  }
 }
-
-/** @type {?FingerprintBrowserProxy} */
-let instance = null;
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_browser_proxy.js
index d2575d0..1e0dfda3 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_browser_proxy.js
@@ -49,10 +49,23 @@
   setOsSyncDatatypes(osSyncPrefs) {}
 }
 
+/** @type {?OsSyncBrowserProxy} */
+let instance = null;
+
 /**
  * @implements {OsSyncBrowserProxy}
  */
 export class OsSyncBrowserProxyImpl {
+  /** @return {!OsSyncBrowserProxy} */
+  static getInstance() {
+    return instance || (instance = new OsSyncBrowserProxyImpl());
+  }
+
+  /** @param {!OsSyncBrowserProxy} obj */
+  static setInstance(obj) {
+    instance = obj;
+  }
+
   /** @override */
   didNavigateToOsSyncPage() {
     chrome.send('DidNavigateToOsSyncPage');
@@ -72,17 +85,4 @@
   setOsSyncDatatypes(osSyncPrefs) {
     return chrome.send('SetOsSyncDatatypes', [osSyncPrefs]);
   }
-
-  /** @return {!OsSyncBrowserProxy} */
-  static getInstance() {
-    return instance || (instance = new OsSyncBrowserProxyImpl());
-  }
-
-  /** @param {!OsSyncBrowserProxy} obj */
-  static setInstance(obj) {
-    instance = obj;
-  }
 }
-
-/** @type {?OsSyncBrowserProxy} */
-let instance = null;
diff --git a/chrome/browser/resources/settings/chromeos/os_privacy_page/metrics_consent_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_privacy_page/metrics_consent_browser_proxy.js
index 6166dcf57..59034612 100644
--- a/chrome/browser/resources/settings/chromeos/os_privacy_page/metrics_consent_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/os_privacy_page/metrics_consent_browser_proxy.js
@@ -43,18 +43,11 @@
   updateMetricsConsent(consent) {}
 }
 
+/** @type {?MetricsConsentBrowserProxy} */
+let instance = null;
+
 /** @implements {MetricsConsentBrowserProxy} */
 export class MetricsConsentBrowserProxyImpl {
-  /** @override */
-  getMetricsConsentState() {
-    return sendWithPromise('getMetricsConsentState');
-  }
-
-  /** @override */
-  updateMetricsConsent(consent) {
-    return sendWithPromise('updateMetricsConsent', {consent: consent});
-  }
-
   /** @return {!MetricsConsentBrowserProxy} */
   static getInstance() {
     return instance || (instance = new MetricsConsentBrowserProxyImpl());
@@ -64,7 +57,14 @@
   static setInstance(obj) {
     instance = obj;
   }
-}
 
-/** @type {?MetricsConsentBrowserProxy} */
-let instance = null;
+  /** @override */
+  getMetricsConsentState() {
+    return sendWithPromise('getMetricsConsentState');
+  }
+
+  /** @override */
+  updateMetricsConsent(consent) {
+    return sendWithPromise('updateMetricsConsent', {consent: consent});
+  }
+}
diff --git a/chrome/browser/resources/settings/chromeos/os_privacy_page/peripheral_data_access_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_privacy_page/peripheral_data_access_browser_proxy.js
index 43624cf..57b1e32 100644
--- a/chrome/browser/resources/settings/chromeos/os_privacy_page/peripheral_data_access_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/os_privacy_page/peripheral_data_access_browser_proxy.js
@@ -32,8 +32,21 @@
   getPolicyState() {}
 }
 
+/** @type {?PeripheralDataAccessBrowserProxy} */
+let instance = null;
+
 /** @implements {PeripheralDataAccessBrowserProxy} */
 export class PeripheralDataAccessBrowserProxyImpl {
+  /** @return {!PeripheralDataAccessBrowserProxy} */
+  static getInstance() {
+    return instance || (instance = new PeripheralDataAccessBrowserProxyImpl());
+  }
+
+  /** @param {!PeripheralDataAccessBrowserProxy} obj */
+  static setInstance(obj) {
+    instance = obj;
+  }
+
   /**
    * @override
    * @return {!Promise<boolean>}
@@ -49,17 +62,4 @@
   getPolicyState() {
     return sendWithPromise('getPolicyState');
   }
-
-  /** @return {!PeripheralDataAccessBrowserProxy} */
-  static getInstance() {
-    return instance || (instance = new PeripheralDataAccessBrowserProxyImpl());
-  }
-
-  /** @param {!PeripheralDataAccessBrowserProxy} obj */
-  static setInstance(obj) {
-    instance = obj;
-  }
 }
-
-/** @type {?PeripheralDataAccessBrowserProxy} */
-let instance = null;
diff --git a/chrome/browser/resources/settings/chromeos/os_reset_page/os_reset_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_reset_page/os_reset_browser_proxy.js
index 486777a..5543ca62 100644
--- a/chrome/browser/resources/settings/chromeos/os_reset_page/os_reset_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/os_reset_page/os_reset_browser_proxy.js
@@ -15,20 +15,13 @@
   requestFactoryResetRestart() {}
 }
 
+/** @type {?OsResetBrowserProxy} */
+let instance = null;
+
 /**
  * @implements {OsResetBrowserProxy}
  */
 export class OsResetBrowserProxyImpl {
-  /** @override */
-  onPowerwashDialogShow() {
-    chrome.send('onPowerwashDialogShow');
-  }
-
-  /** @override */
-  requestFactoryResetRestart() {
-    chrome.send('requestFactoryResetRestart');
-  }
-
   /** @return {!OsResetBrowserProxy} */
   static getInstance() {
     return instance || (instance = new OsResetBrowserProxyImpl());
@@ -38,7 +31,14 @@
   static setInstance(obj) {
     instance = obj;
   }
-}
 
-/** @type {?OsResetBrowserProxy} */
-let instance = null;
+  /** @override */
+  onPowerwashDialogShow() {
+    chrome.send('onPowerwashDialogShow');
+  }
+
+  /** @override */
+  requestFactoryResetRestart() {
+    chrome.send('requestFactoryResetRestart');
+  }
+}
diff --git a/chrome/browser/resources/settings/chromeos/os_search_page/search_engines_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_search_page/search_engines_browser_proxy.js
index b3a4b3e..34d107ab 100644
--- a/chrome/browser/resources/settings/chromeos/os_search_page/search_engines_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/os_search_page/search_engines_browser_proxy.js
@@ -50,20 +50,13 @@
   getSearchEnginesList() {}
 }
 
+/** @type {?SearchEnginesBrowserProxy} */
+let instance = null;
+
 /**
  * @implements {SearchEnginesBrowserProxy}
  */
 export class SearchEnginesBrowserProxyImpl {
-  /** @override */
-  setDefaultSearchEngine(modelIndex) {
-    chrome.send('setDefaultSearchEngine', [modelIndex]);
-  }
-
-  /** @override */
-  getSearchEnginesList() {
-    return sendWithPromise('getSearchEnginesList');
-  }
-
   /** @return {!SearchEnginesBrowserProxy} */
   static getInstance() {
     return instance || (instance = new SearchEnginesBrowserProxyImpl());
@@ -73,7 +66,14 @@
   static setInstance(obj) {
     instance = obj;
   }
-}
 
-/** @type {?SearchEnginesBrowserProxy} */
-let instance = null;
+  /** @override */
+  setDefaultSearchEngine(modelIndex) {
+    chrome.send('setDefaultSearchEngine', [modelIndex]);
+  }
+
+  /** @override */
+  getSearchEnginesList() {
+    return sendWithPromise('getSearchEnginesList');
+  }
+}
diff --git a/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_browser_proxy.js b/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_browser_proxy.js
index 60179d18..2409379 100644
--- a/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_browser_proxy.js
@@ -22,18 +22,11 @@
   launchFamilyLinkSettings() {}
 }
 
+/** @type {?ParentalControlsBrowserProxy} */
+let instance = null;
+
 /** @implements {ParentalControlsBrowserProxy} */
 export class ParentalControlsBrowserProxyImpl {
-  /** @override */
-  showAddSupervisionDialog() {
-    chrome.send('showAddSupervisionDialog');
-  }
-
-  /** @override */
-  launchFamilyLinkSettings() {
-    chrome.send('launchFamilyLinkSettings');
-  }
-
   /** @return {!ParentalControlsBrowserProxy} */
   static getInstance() {
     return instance || (instance = new ParentalControlsBrowserProxyImpl());
@@ -43,7 +36,14 @@
   static setInstance(obj) {
     instance = obj;
   }
-}
 
-/** @type {?ParentalControlsBrowserProxy} */
-let instance = null;
+  /** @override */
+  showAddSupervisionDialog() {
+    chrome.send('showAddSupervisionDialog');
+  }
+
+  /** @override */
+  launchFamilyLinkSettings() {
+    chrome.send('launchFamilyLinkSettings');
+  }
+}
diff --git a/chrome/browser/resources/settings/chromeos/personalization_page/change_picture_browser_proxy.js b/chrome/browser/resources/settings/chromeos/personalization_page/change_picture_browser_proxy.js
index fec2af1..c5eb6b1 100644
--- a/chrome/browser/resources/settings/chromeos/personalization_page/change_picture_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/personalization_page/change_picture_browser_proxy.js
@@ -61,10 +61,23 @@
   requestSelectedImage() {}
 }
 
+/** @type {?ChangePictureBrowserProxy} */
+let instance = null;
+
 /**
  * @implements {ChangePictureBrowserProxy}
  */
 export class ChangePictureBrowserProxyImpl {
+  /** @return {!ChangePictureBrowserProxy} */
+  static getInstance() {
+    return instance || (instance = new ChangePictureBrowserProxyImpl());
+  }
+
+  /** @param {!ChangePictureBrowserProxy} obj */
+  static setInstance(obj) {
+    instance = obj;
+  }
+
   /** @override */
   initialize() {
     chrome.send('onChangePicturePageInitialized');
@@ -99,17 +112,4 @@
   requestSelectedImage() {
     chrome.send('requestSelectedImage');
   }
-
-  /** @return {!ChangePictureBrowserProxy} */
-  static getInstance() {
-    return instance || (instance = new ChangePictureBrowserProxyImpl());
-  }
-
-  /** @param {!ChangePictureBrowserProxy} obj */
-  static setInstance(obj) {
-    instance = obj;
-  }
 }
-
-/** @type {?ChangePictureBrowserProxy} */
-let instance = null;
diff --git a/chrome/browser/resources/settings/chromeos/personalization_page/personalization_hub_browser_proxy.js b/chrome/browser/resources/settings/chromeos/personalization_page/personalization_hub_browser_proxy.js
index 6d575c9..cfefdfd 100644
--- a/chrome/browser/resources/settings/chromeos/personalization_page/personalization_hub_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/personalization_page/personalization_hub_browser_proxy.js
@@ -7,15 +7,13 @@
   openPersonalizationHub() {}
 }
 
+/** @type {?PersonalizationHubBrowserProxy} */
+let instance = null;
+
 /**
  * @implements {PersonalizationHubBrowserProxy}
  */
 export class PersonalizationHubBrowserProxyImpl {
-  /** @override */
-  openPersonalizationHub() {
-    chrome.send('openPersonalizationHub');
-  }
-
   /** @return {!PersonalizationHubBrowserProxy} */
   static getInstance() {
     return instance || (instance = new PersonalizationHubBrowserProxyImpl());
@@ -25,7 +23,9 @@
   static setInstance(obj) {
     instance = obj;
   }
-}
 
-/** @type {?PersonalizationHubBrowserProxy} */
-let instance = null;
+  /** @override */
+  openPersonalizationHub() {
+    chrome.send('openPersonalizationHub');
+  }
+}
diff --git a/chrome/browser/resources/settings/chromeos/personalization_page/wallpaper_browser_proxy.js b/chrome/browser/resources/settings/chromeos/personalization_page/wallpaper_browser_proxy.js
index 1ec8321..c3e93de1 100644
--- a/chrome/browser/resources/settings/chromeos/personalization_page/wallpaper_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/personalization_page/wallpaper_browser_proxy.js
@@ -20,10 +20,23 @@
   openWallpaperManager() {}
 }
 
+/** @type {?WallpaperBrowserProxy} */
+let instance = null;
+
 /**
  * @implements {WallpaperBrowserProxy}
  */
 export class WallpaperBrowserProxyImpl {
+  /** @return {!WallpaperBrowserProxy} */
+  static getInstance() {
+    return instance || (instance = new WallpaperBrowserProxyImpl());
+  }
+
+  /** @param {!WallpaperBrowserProxy} obj */
+  static setInstance(obj) {
+    instance = obj;
+  }
+
   /** @override */
   isWallpaperSettingVisible() {
     return sendWithPromise('isWallpaperSettingVisible');
@@ -38,17 +51,4 @@
   openWallpaperManager() {
     chrome.send('openWallpaperManager');
   }
-
-  /** @return {!WallpaperBrowserProxy} */
-  static getInstance() {
-    return instance || (instance = new WallpaperBrowserProxyImpl());
-  }
-
-  /** @param {!WallpaperBrowserProxy} obj */
-  static setInstance(obj) {
-    instance = obj;
-  }
 }
-
-/** @type {?WallpaperBrowserProxy} */
-let instance = null;
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_bn.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_bn.xtb
index 032486f..37887e17 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_bn.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_bn.xtb
@@ -1078,6 +1078,7 @@
 <translation id="6824899148643461612"><ph name="TAB_TITLE" />, ট্যাব বেছে নেওয়া হয়েছে</translation>
 <translation id="6828070228333235514">দাম ট্র্যাক করা বন্ধ করুন</translation>
 <translation id="6833996806551876956">গোপনীয়তা স্যান্ডবক্স ট্রায়াল</translation>
+<translation id="6836206421467243968">নতুন ব্যাকগ্রাউন্ড ট্যাব গ্রুপ হিসেবে <ph name="TITLE_OF_GROUP" /> ট্যাব গ্রুপ ফিরিয়ে আনুন।</translation>
 <translation id="6846298663435243399">লোড হচ্ছে...</translation>
 <translation id="6850409657436465440">ডাউনলোডটি এখনও চলছে</translation>
 <translation id="6850830437481525139"><ph name="TAB_COUNT" />টি ট্যাব বন্ধ হয়েছে</translation>
@@ -1140,6 +1141,7 @@
 <translation id="7187993566681480880">এই সুরক্ষা আপনাকে Chrome-এ সাইন-ইন করা অবস্থাতে নিরাপদে রাখে এবং যদি অন্যান্য Google অ্যাপে আপনি সাইন-ইন করে থাকেন, সেখানেও আপনার নিরাপত্তার বিষয়টি উন্নত করতে এটিকে ব্যবহার করা যেতে পারে।</translation>
 <translation id="7191430249889272776">পটভূমিতে ট্যাব খোলা হয়েছে।</translation>
 <translation id="7196215469483532480">গোপনীয়তা সম্পর্কিত গাইডের ব্যাখ্যা সম্পূর্ণ স্ক্রিন জুড়ে খুলেছে</translation>
+<translation id="7207760545532569765">নতুন ব্যাকগ্রাউন্ড ট্যাব হিসেবে <ph name="TAB_COUNT" />টি ট্যাব ফিরিয়ে আনুন।</translation>
 <translation id="7208109991155904980">প্রতিক্রিয়া সরানো হয়েছে</translation>
 <translation id="7222235798733126207">সাইটের মধ্যে শেয়ারিং সীমিত</translation>
 <translation id="7227218174981371415">{FILE_COUNT,plural, =1{১টি ডাউনলোড বাকি আছে}one{#টি ডাউনলোড বাকি আছে}other{#টি ডাউনলোড বাকি আছে}}</translation>
@@ -1518,6 +1520,7 @@
 <translation id="9148126808321036104">আবার সাইন-ইন করুন</translation>
 <translation id="9155898266292537608">এছাড়াও কোনও শব্দের উপরে ট্যাপ করেও খুঁজতে পারেন</translation>
 <translation id="9158770349521403363">শুধুমাত্র কন্টেন্ট শেয়ার করুন</translation>
+<translation id="9159716826369098114">নতুন ব্যাকগ্রাউন্ড ট্যাব গ্রুপ হিসেবে <ph name="TAB_COUNT" />টি ট্যাবের ট্যাব গ্রুপ ফিরিয়ে আনুন।</translation>
 <translation id="916446198114569890">আপনি যেসব URL ভিজিট করেন তা আপনার Google অ্যাকাউন্টে সেভ করা হয়</translation>
 <translation id="9169507124922466868">নেভিগেশনের ইতিহাস অর্ধেক খোলা রয়েছে</translation>
 <translation id="9187955620966010988">প্রতিক্রিয়া অ্যাডজাস্ট করা হয়েছে</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_bs.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_bs.xtb
index 246794db..6d649f95 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_bs.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_bs.xtb
@@ -1139,7 +1139,7 @@
 <translation id="7187993566681480880">Štiti vas na Chromeu i može se koristiti da poboljša vašu sigurnost u drugim Googleovim aplikacijama kada ste prijavljeni.</translation>
 <translation id="7191430249889272776">Kartica je otvorena u pozadini.</translation>
 <translation id="7196215469483532480">Objašnjenje vodiča za privatnost je otvoreno u punoj veličini</translation>
-<translation id="7207760545532569765">Vratite <ph name="TAB_COUNT" /> kartica kao nove pozadinske kartice.</translation>
+<translation id="7207760545532569765">Vratite kartice (njih <ph name="TAB_COUNT" />) kao nove pozadinske kartice.</translation>
 <translation id="7208109991155904980">Reakcija je pomjerena</translation>
 <translation id="7222235798733126207">Ograničeno dijeljenje između web lokacija</translation>
 <translation id="7227218174981371415">{FILE_COUNT,plural, =1{1 preuzimanje na čekanju}one{# preuzimanje na čekanju}few{# preuzimanja na čekanju}other{# preuzimanja na čekanju}}</translation>
@@ -1518,7 +1518,7 @@
 <translation id="9148126808321036104">Prijavi se ponovo</translation>
 <translation id="9155898266292537608">Također možete pretraživati brzim dodirom riječi</translation>
 <translation id="9158770349521403363">Dijeli samo sadržaj</translation>
-<translation id="9159716826369098114">Vratite grupu od <ph name="TAB_COUNT" /> kartica kao novu pozadinsku grupu kartica.</translation>
+<translation id="9159716826369098114">Vratite grupu kartica (broj kartica: <ph name="TAB_COUNT" />) kao novu pozadinsku grupu kartica.</translation>
 <translation id="916446198114569890">URL-ovi koje posjećujete pohranjuju se na vaš Google račun</translation>
 <translation id="9169507124922466868">Historija navigacije je napola otvorena</translation>
 <translation id="9187955620966010988">Reakcija je podešena</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_el.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_el.xtb
index 8e60b62..ecf817b 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_el.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_el.xtb
@@ -1076,6 +1076,7 @@
 <translation id="6824899148643461612"><ph name="TAB_TITLE" />, καρτέλα, επιλέχθηκε</translation>
 <translation id="6828070228333235514">Διακοπή παρακολούθησης τιμής</translation>
 <translation id="6833996806551876956">Δοκιμή Πλαίσιο ιδιωτικότητας</translation>
+<translation id="6836206421467243968">Επαναφέρετε την ομάδα καρτελών <ph name="TITLE_OF_GROUP" /> ως νέα ομάδα καρτελών στο παρασκήνιο.</translation>
 <translation id="6846298663435243399">Φόρτωση…</translation>
 <translation id="6850409657436465440">Η λήψη σας βρίσκεται ακόμα σε εξέλιξη</translation>
 <translation id="6850830437481525139">Έκλεισαν <ph name="TAB_COUNT" /> καρτέλες</translation>
@@ -1138,6 +1139,7 @@
 <translation id="7187993566681480880">Διατηρεί την ασφάλειά σας στο Chrome και μπορεί να χρησιμοποιηθεί για τη βελτίωση της ασφάλειάς σας σε άλλες εφαρμογές Google όταν είστε συνδεδεμένοι.</translation>
 <translation id="7191430249889272776">Η καρτέλα άνοιξε στο παρασκήνιο.</translation>
 <translation id="7196215469483532480">Η επεξήγηση Οδηγού απορρήτου άνοιξε σε πλήρες ύψος.</translation>
+<translation id="7207760545532569765">Επαναφέρετε <ph name="TAB_COUNT" /> καρτέλες ως νέες καρτέλες στο παρασκήνιο.</translation>
 <translation id="7208109991155904980">Η αντίδραση μεταφέρθηκε</translation>
 <translation id="7222235798733126207">Περιορισμένη κοινοποίηση μεταξύ ιστοτόπων</translation>
 <translation id="7227218174981371415">{FILE_COUNT,plural, =1{1 λήψη σε εκκρεμότητα}other{# λήψεις σε εκκρεμότητα}}</translation>
@@ -1516,6 +1518,7 @@
 <translation id="9148126808321036104">Συνδεθείτε ξανά</translation>
 <translation id="9155898266292537608">Επίσης, μπορείτε να κάνετε αναζήτηση με ένα γρήγορο πάτημα σε μια λέξη</translation>
 <translation id="9158770349521403363">Κοινοποίηση μόνο περιεχομένου</translation>
+<translation id="9159716826369098114">Επαναφέρετε την ομάδα καρτελών με τις <ph name="TAB_COUNT" /> καρτέλες ως νέα ομάδα καρτελών στο παρασκήνιο.</translation>
 <translation id="916446198114569890">Τα URL που επισκέπτεστε αποθηκεύονται στον Λογαριασμό σας Google</translation>
 <translation id="9169507124922466868">Το ιστορικό πλοήγησης έχει ανοίξει κατά το ήμισυ</translation>
 <translation id="9187955620966010988">Η αντίδραση προσαρμόστηκε</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_mn.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_mn.xtb
index a9fcedc8..1536b45 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_mn.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_mn.xtb
@@ -1075,6 +1075,7 @@
 <translation id="6824899148643461612"><ph name="TAB_TITLE" />, таб, сонгосон</translation>
 <translation id="6828070228333235514">Үнэ хянахыг зогсоох</translation>
 <translation id="6833996806551876956">Нууцлалын sandbox-н туршилт</translation>
+<translation id="6836206421467243968"><ph name="TITLE_OF_GROUP" /> табын бүлгийг шинэ дэвсгэр табын бүлгээр сэргээнэ үү.</translation>
 <translation id="6846298663435243399">Ачаалж байна...</translation>
 <translation id="6850409657436465440">Таны таталт үргэлжилж байна</translation>
 <translation id="6850830437481525139"><ph name="TAB_COUNT" /> табыг хаасан</translation>
@@ -1137,6 +1138,7 @@
 <translation id="7187993566681480880">Таныг нэвтэрсэн үед Chrome дээр таны аюулгүй байдлыг хангадаг бөгөөд Google-н бусад апп дахь таны аюулгүй байдлыг сайжруулахын тулд ашиглагдах боломжтой.</translation>
 <translation id="7191430249889272776">Арын дэвсгэр дээр нээсэн цонх.</translation>
 <translation id="7196215469483532480">Нууцлалын хөтчийн тайлбарыг бүтэн хэмжээгээр нээсэн</translation>
+<translation id="7207760545532569765"><ph name="TAB_COUNT" /> табыг шинэ дэвсгэр табаар сэргээнэ үү.</translation>
 <translation id="7208109991155904980">Хариу үйлдлийг зөөсөн</translation>
 <translation id="7222235798733126207">Сайт хооронд хуваалцахыг хязгаарлаарай</translation>
 <translation id="7227218174981371415">{FILE_COUNT,plural, =1{1 таталт хүлээгдэж байна}other{# таталт хүлээгдэж байна}}</translation>
@@ -1515,6 +1517,7 @@
 <translation id="9148126808321036104">Дансандаа дахин нэвтрэх</translation>
 <translation id="9155898266292537608">Мөн та үгийг хурдан товшоод хайх боломжтой</translation>
 <translation id="9158770349521403363">Зөвхөн контент хуваалцана уу</translation>
+<translation id="9159716826369098114"><ph name="TAB_COUNT" /> табтай табын бүлгийг шинэ дэвсгэр табын бүлгээр сэргээнэ үү.</translation>
 <translation id="916446198114569890">Таны зочилсон URL-уудыг таны Google Бүртгэлд хадгалсан</translation>
 <translation id="9169507124922466868">Навигацын түүхийг хагас нээлээ</translation>
 <translation id="9187955620966010988">Хариу үйлдлийг тохируулсан</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_mr.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_mr.xtb
index 786191a5..5cb2fb3 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_mr.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_mr.xtb
@@ -1076,6 +1076,7 @@
 <translation id="6824899148643461612"><ph name="TAB_TITLE" /> हा टॅब निवडला</translation>
 <translation id="6828070228333235514">किमतीचा माग ठेवणे बंद करा</translation>
 <translation id="6833996806551876956">गोपनीयता सॅंडबॉक्स याची चाचणी</translation>
+<translation id="6836206421467243968">नवीन बॅकग्राउंड टॅब गट म्हणून <ph name="TITLE_OF_GROUP" /> टॅब गट रिस्टोअर करा.</translation>
 <translation id="6846298663435243399">लोड करत आहे...</translation>
 <translation id="6850409657436465440">तुमचे डाउनलोड अजून प्रगतीपथावर आहे</translation>
 <translation id="6850830437481525139"><ph name="TAB_COUNT" /> टॅब बंद केले</translation>
@@ -1138,6 +1139,7 @@
 <translation id="7187993566681480880">तुम्हाला Chrome वर सुरक्षित ठेवते आणि तुम्ही साइन इन केलेले असताना इतर Google अ‍ॅप्समध्ये तुमच्या सुरक्षेत सुधारणा करण्यासाठी वापरले जाऊ शकते.</translation>
 <translation id="7191430249889272776">पार्श्वभूमीवर उघडा असलेला टॅब.</translation>
 <translation id="7196215469483532480">गोपनीयता मार्गदर्शक स्पष्टीकरण पूर्ण उंचीवर उघडले आहे</translation>
+<translation id="7207760545532569765">नवीन बॅकग्राउंड टॅब गट म्हणून <ph name="TAB_COUNT" /> टॅब रिस्टोअर करा.</translation>
 <translation id="7208109991155904980">प्रतिक्रिया हलवली</translation>
 <translation id="7222235798733126207">साइटदरम्यान मर्यादित शेअरिंग</translation>
 <translation id="7227218174981371415">{FILE_COUNT,plural, =1{एक डाउनलोड बाकी आहे}other{# डाउनलोड बाकी आहेत}}</translation>
@@ -1516,6 +1518,7 @@
 <translation id="9148126808321036104">पुन्हा साइन इन करा </translation>
 <translation id="9155898266292537608">तुम्ही शब्दावर जलद टॅप करूनदेखील शोधू शकता</translation>
 <translation id="9158770349521403363">फक्त आशय शेअर करा</translation>
+<translation id="9159716826369098114">नवीन बॅकग्राउंड टॅब गट म्हणून <ph name="TAB_COUNT" /> टॅबचा टॅब गट रिस्टोअर करा.</translation>
 <translation id="916446198114569890">तुम्ही भेट देता त्या URL तुमच्या Google खात्यामध्ये सेव्ह केल्या जातात</translation>
 <translation id="9169507124922466868">नेव्हिगेशन इतिहास अर्धा उघडा आहे</translation>
 <translation id="9187955620966010988">प्रतिक्रिया अ‍ॅडजस्ट केली आहे</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pl.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pl.xtb
index 9640b7b09..ff38fa128 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pl.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pl.xtb
@@ -1076,6 +1076,7 @@
 <translation id="6824899148643461612">Wybrano kartę <ph name="TAB_TITLE" /></translation>
 <translation id="6828070228333235514">Przestań monitorować cenę</translation>
 <translation id="6833996806551876956">Okres próbny piaskownicy prywatności</translation>
+<translation id="6836206421467243968">Przywróć grupę kart <ph name="TITLE_OF_GROUP" /> jako nową grupę kart w tle.</translation>
 <translation id="6846298663435243399">Wczytuję…</translation>
 <translation id="6850409657436465440">Pobieranie wciąż trwa</translation>
 <translation id="6850830437481525139">Zamknięte karty: <ph name="TAB_COUNT" /></translation>
@@ -1138,6 +1139,7 @@
 <translation id="7187993566681480880">Dba o Twoje bezpieczeństwo w Chrome i może poprawiać Twoje bezpieczeństwo w innych aplikacjach Google, gdy się w nich zalogujesz.</translation>
 <translation id="7191430249889272776">Karta otwarta w tle.</translation>
 <translation id="7196215469483532480">Wyjaśnienie dotyczące Przewodnika po prywatności jest otwarte na całą wysokość</translation>
+<translation id="7207760545532569765">Przywróć karty (<ph name="TAB_COUNT" />) jako nowe karty w tle.</translation>
 <translation id="7208109991155904980">Reakcja została przeniesiona</translation>
 <translation id="7222235798733126207">Ograniczone udostępnianie treści między witrynami</translation>
 <translation id="7227218174981371415">{FILE_COUNT,plural, =1{1 plik oczekuje na pobranie}few{# pliki oczekują na pobranie}many{# plików oczekuje na pobranie}other{# pliku oczekuje na pobranie}}</translation>
@@ -1516,6 +1518,7 @@
 <translation id="9148126808321036104">Zaloguj się ponownie</translation>
 <translation id="9155898266292537608">Możesz też wyszukiwać szybkim kliknięciem słowa</translation>
 <translation id="9158770349521403363">Udostępnij tylko treść</translation>
+<translation id="9159716826369098114">Przywróć grupę <ph name="TAB_COUNT" /> kart jako nową grupę kart w tle.</translation>
 <translation id="916446198114569890">Odwiedzane adresy URL są zapisywane na Twoim koncie Google</translation>
 <translation id="9169507124922466868">Historia nawigacji jest otwarta w połowie</translation>
 <translation id="9187955620966010988">Reakcja została dostosowana</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-BR.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-BR.xtb
index 7c8f9743..38912585 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-BR.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-BR.xtb
@@ -1077,6 +1077,7 @@
 <translation id="6824899148643461612">A guia <ph name="TAB_TITLE" /> está selecionada</translation>
 <translation id="6828070228333235514">Parar de monitorar preço</translation>
 <translation id="6833996806551876956">Teste da Privacy Sandbox</translation>
+<translation id="6836206421467243968">Restaurar grupo <ph name="TITLE_OF_GROUP" /> como um novo grupo de guias em segundo plano.</translation>
 <translation id="6846298663435243399">Carregando…</translation>
 <translation id="6850409657436465440">Seu download ainda está em andamento</translation>
 <translation id="6850830437481525139"><ph name="TAB_COUNT" /> guias fechadas</translation>
@@ -1139,6 +1140,7 @@
 <translation id="7187993566681480880">Protege você no Chrome e pode ser usado para melhorar a segurança em outros apps do Google quando sua conta está conectada.</translation>
 <translation id="7191430249889272776">Guia aberta no plano de fundo.</translation>
 <translation id="7196215469483532480">Explicação sobre o Guia de privacidade aberta no tamanho máximo</translation>
+<translation id="7207760545532569765">Restaurar <ph name="TAB_COUNT" /> guias como novas guias em segundo plano.</translation>
 <translation id="7208109991155904980">Reação movida</translation>
 <translation id="7222235798733126207">Compartilhamento entre sites limitado</translation>
 <translation id="7227218174981371415">{FILE_COUNT,plural, =1{1 download pendente}one{# download pendente}other{# downloads pendentes}}</translation>
@@ -1517,6 +1519,7 @@
 <translation id="9148126808321036104">Faça login novamente</translation>
 <translation id="9155898266292537608">Você também pode pesquisar com um toque rápido em uma palavra</translation>
 <translation id="9158770349521403363">Compartilhar apenas o conteúdo</translation>
+<translation id="9159716826369098114">Restaurar grupo de <ph name="TAB_COUNT" /> guias como um novo grupo de guias em segundo plano.</translation>
 <translation id="916446198114569890">Os URLs que você acessa ficam armazenados na sua Conta do Google</translation>
 <translation id="9169507124922466868">Histórico de navegação parcialmente aberto</translation>
 <translation id="9187955620966010988">Reação ajustada</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-PT.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-PT.xtb
index 45017ad..797109a 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-PT.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-PT.xtb
@@ -1076,6 +1076,7 @@
 <translation id="6824899148643461612"><ph name="TAB_TITLE" />, separador, selecionado</translation>
 <translation id="6828070228333235514">Parar monitorização do preço</translation>
 <translation id="6833996806551876956">Avaliação do Privacy Sandbox</translation>
+<translation id="6836206421467243968">Restaure o grupo de separadores <ph name="TITLE_OF_GROUP" /> como um novo grupo de separadores em segundo plano.</translation>
 <translation id="6846298663435243399">A carregar...</translation>
 <translation id="6850409657436465440">A transferência ainda está em curso.</translation>
 <translation id="6850830437481525139"><ph name="TAB_COUNT" /> separadores fechados</translation>
@@ -1138,6 +1139,7 @@
 <translation id="7187993566681480880">Mantém a sua segurança no Chrome e pode ser utilizada para melhorar a sua segurança noutras apps Google quando tem sessão iniciada.</translation>
 <translation id="7191430249889272776">Separador aberto em segundo plano.</translation>
 <translation id="7196215469483532480">Explicação do guia de privacidade aberta à altura total</translation>
+<translation id="7207760545532569765">Restaure <ph name="TAB_COUNT" /> separadores como novos separadores em segundo plano.</translation>
 <translation id="7208109991155904980">Reação movida</translation>
 <translation id="7222235798733126207">Partilha limitada entre sites</translation>
 <translation id="7227218174981371415">{FILE_COUNT,plural, =1{1 transferência pendente}other{# transferências pendentes}}</translation>
@@ -1516,6 +1518,7 @@
 <translation id="9148126808321036104">Iniciar sessão novamente</translation>
 <translation id="9155898266292537608">Também pode pesquisar ao tocar rapidamente numa palavra.</translation>
 <translation id="9158770349521403363">Apenas partilhar conteúdo</translation>
+<translation id="9159716826369098114">Restaure o grupo de <ph name="TAB_COUNT" /> separadores como um novo grupo de separadores em segundo plano.</translation>
 <translation id="916446198114569890">Os URLs que visita são guardados na sua Conta Google</translation>
 <translation id="9169507124922466868">O histórico de navegação está aberto até meio.</translation>
 <translation id="9187955620966010988">Reação ajustada</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sk.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sk.xtb
index 8eab9c5..2072fb2 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sk.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sk.xtb
@@ -1076,6 +1076,7 @@
 <translation id="6824899148643461612"><ph name="TAB_TITLE" />, karta, vybrané</translation>
 <translation id="6828070228333235514">Prestať sledovať cenu</translation>
 <translation id="6833996806551876956">Skúšobné obdobie karantény ochrany súkromia</translation>
+<translation id="6836206421467243968">Obnovte skupinu kariet <ph name="TITLE_OF_GROUP" /> ako novú skupinu kariet na pozadí.</translation>
 <translation id="6846298663435243399">Načítava sa…</translation>
 <translation id="6850409657436465440">Sťahovanie stále prebieha</translation>
 <translation id="6850830437481525139">Všetky karty sú zatvorené (<ph name="TAB_COUNT" />)</translation>
@@ -1138,6 +1139,7 @@
 <translation id="7187993566681480880">Chráni vás v Chrome a môže zlepšiť zabezpečenie v ďalších aplikáciách Google, keď sa prihlásite.</translation>
 <translation id="7191430249889272776">Karta je otvorená na pozadí.</translation>
 <translation id="7196215469483532480">Vysvetlenie sprievodcu ochranou súkromia je otvorené na celú výšku</translation>
+<translation id="7207760545532569765">Obnovte karty (<ph name="TAB_COUNT" />) ako nové karty na pozadí.</translation>
 <translation id="7208109991155904980">Reakcia bola presunutá</translation>
 <translation id="7222235798733126207">Obmedzené zdieľanie medzi webmi</translation>
 <translation id="7227218174981371415">{FILE_COUNT,plural, =1{Na stiahnutie čaká 1 položka}few{Na stiahnutie čakajú # položky}many{# downloads pending}other{Na stiahnutie čaká # položiek}}</translation>
@@ -1516,6 +1518,7 @@
 <translation id="9148126808321036104">Znova sa prihlásiť</translation>
 <translation id="9155898266292537608">Vyhľadávať môžete aj rýchlym klepnutím na slovo</translation>
 <translation id="9158770349521403363">Zdieľať iba obsah</translation>
+<translation id="9159716826369098114">Obnovte skupinu kariet s <ph name="TAB_COUNT" /> kartami ako novú skupinu kariet na pozadí.</translation>
 <translation id="916446198114569890">Webové adresy, ktoré navštívite, sa uložia do vášho účtu Google</translation>
 <translation id="9169507124922466868">História navigácie je dopoly otvorená</translation>
 <translation id="9187955620966010988">Reakcia bola upravená</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_te.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_te.xtb
index 5247cef..104aea6 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_te.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_te.xtb
@@ -1076,6 +1076,7 @@
 <translation id="6824899148643461612"><ph name="TAB_TITLE" />, ట్యాబ్‌ను ఎంచుకున్నారు</translation>
 <translation id="6828070228333235514">ధరను ట్రాక్ చేయడాన్ని ఆపివేయండి</translation>
 <translation id="6833996806551876956">గోప్యతా శాండ్‌బాక్స్ ట్రయల్</translation>
+<translation id="6836206421467243968"><ph name="TITLE_OF_GROUP" /> ట్యాబ్ గ్రూప్‌ను కొత్త బ్యాక్‌గ్రౌండ్ ట్యాబ్ గ్రూప్‌గా రీస్టోర్ చేయండి.</translation>
 <translation id="6846298663435243399">లోడ్ చేస్తున్నాము…</translation>
 <translation id="6850409657436465440">మీ డౌన్‌లోడ్‌‌ ఇప్పటికీ జరుగుతోంది</translation>
 <translation id="6850830437481525139"><ph name="TAB_COUNT" /> ట్యాబ్‌లు మూసివేయబడ్డాయి</translation>
@@ -1138,6 +1139,7 @@
 <translation id="7187993566681480880">Chromeలో మిమ్మల్ని సురక్షితంగా ఉంచుతుంది, మీరు సైన్ ఇన్ చేసినప్పుడు ఇతర Google యాప్‌లలో మీ భద్రతను మెరుగుపరచడానికి ఉపయోగించబడవచ్చు.</translation>
 <translation id="7191430249889272776">బ్యాక్‌గ్రౌండ్‌లో ట్యాబ్ తెరవబడింది.</translation>
 <translation id="7196215469483532480">గోప్యతా గైడ్ వివరణ షీట్ ఫుల్-స్క్రీన్‌లో తెరవబడింది</translation>
+<translation id="7207760545532569765">బ్యాక్‌గ్రౌండ్ ట్యాబ్‌లుగా <ph name="TAB_COUNT" />ట్యాబ్‌లను రీస్టోర్ చేయండి.</translation>
 <translation id="7208109991155904980">ప్రతిస్పందన తరలించబడింది</translation>
 <translation id="7222235798733126207">సైట్‌ల మధ్య పరిమిత షేరింగ్</translation>
 <translation id="7227218174981371415">{FILE_COUNT,plural, =1{1 డౌన్‌లోడ్ పెండింగ్‌లో ఉంది}other{# డౌన్‌లోడ్‌లు పెండింగ్‌లో ఉన్నాయి}}</translation>
@@ -1516,6 +1518,7 @@
 <translation id="9148126808321036104">మళ్ళీ సైన్ ఇన్ చేయండి</translation>
 <translation id="9155898266292537608">ఒక పదంపై నొక్కడం ద్వారా కూడా మీరు త్వరగా వెతకవచ్చు</translation>
 <translation id="9158770349521403363">కంటెంట్‌ను మాత్రమే షేర్ చేయండి</translation>
+<translation id="9159716826369098114"><ph name="TAB_COUNT" /> ట్యాబ్‌ల ట్యాబ్ గ్రూప్‌ను కొత్త బ్యాక్‌గ్రౌండ్ ట్యాబ్ గ్రూప్‌గా రీస్టోర్ చేయండి.</translation>
 <translation id="916446198114569890">మీరు సందర్శించే URLలు మీ Google ఖాతాకు సేవ్ చేయబడతాయి</translation>
 <translation id="9169507124922466868">నావిగేషన్ చరిత్ర సగం తెరిచి ఉంది</translation>
 <translation id="9187955620966010988">ప్రతిస్పందన సర్దుబాటు చేయబడింది</translation>
diff --git a/chrome/browser/ui/app_list/search/open_tab_result.cc b/chrome/browser/ui/app_list/search/open_tab_result.cc
index 78411b3..a0cd68cd 100644
--- a/chrome/browser/ui/app_list/search/open_tab_result.cc
+++ b/chrome/browser/ui/app_list/search/open_tab_result.cc
@@ -104,15 +104,15 @@
   std::u16string url = base::UTF8ToUTF16(match_.destination_url.spec());
   SetDetailsTextVector(
       {CreateStringTextItem(url).SetTextTags({Tag(Tag::URL, 0, url.length())}),
-       CreateStringTextItem(kUrlDelimiter),
-       CreateStringTextItem(IDS_APP_LIST_OPEN_TAB_HINT)
+       CreateStringTextItem(l10n_util::GetStringFUTF16(
+                                IDS_APP_LIST_OPEN_TAB_HINT, kUrlDelimiter))
            .SetOverflowBehavior(
                ash::SearchResultTextItem::OverflowBehavior::kNoElide)});
 
-  SetAccessibleName(
-      base::JoinString({match_.description, url,
-                        l10n_util::GetStringUTF16(IDS_APP_LIST_OPEN_TAB_HINT)},
-                       kA11yDelimiter));
+  SetAccessibleName(base::JoinString(
+      {match_.description, url,
+       l10n_util::GetStringFUTF16(IDS_APP_LIST_OPEN_TAB_HINT, u"")},
+      kA11yDelimiter));
 }
 
 void OpenTabResult::UpdateIcon() {
diff --git a/chrome/browser/ui/app_list/search/open_tab_result_unittest.cc b/chrome/browser/ui/app_list/search/open_tab_result_unittest.cc
index 0127c50..9bef83f 100644
--- a/chrome/browser/ui/app_list/search/open_tab_result_unittest.cc
+++ b/chrome/browser/ui/app_list/search/open_tab_result_unittest.cc
@@ -49,14 +49,14 @@
       MakeResult(u"query", u"queryabc", u"http://www.website.com");
 
   EXPECT_EQ(result->title(), u"queryabc");
-  EXPECT_EQ(
-      StringFromTextVector(result->details_text_vector()),
-      base::StrCat({u"http://www.website.com/ - ",
-                    l10n_util::GetStringUTF16(IDS_APP_LIST_OPEN_TAB_HINT)}));
-  EXPECT_EQ(
-      result->accessible_name(),
-      base::StrCat({u"queryabc, http://www.website.com/, ",
-                    l10n_util::GetStringUTF16(IDS_APP_LIST_OPEN_TAB_HINT)}));
+  EXPECT_EQ(StringFromTextVector(result->details_text_vector()),
+            base::StrCat({u"http://www.website.com/",
+                          l10n_util::GetStringFUTF16(IDS_APP_LIST_OPEN_TAB_HINT,
+                                                     u" - ")}));
+  EXPECT_EQ(result->accessible_name(),
+            base::StrCat({u"queryabc, http://www.website.com/",
+                          l10n_util::GetStringFUTF16(IDS_APP_LIST_OPEN_TAB_HINT,
+                                                     u", ")}));
 }
 
 TEST_F(OpenTabResultTest, ManuallyCalculateRelevance) {
diff --git a/chrome/browser/ui/webui/managed_ui_handler_unittest.cc b/chrome/browser/ui/webui/managed_ui_handler_unittest.cc
index 8bcc478..24b1c406 100644
--- a/chrome/browser/ui/webui/managed_ui_handler_unittest.cc
+++ b/chrome/browser/ui/webui/managed_ui_handler_unittest.cc
@@ -62,7 +62,7 @@
   void InitializeHandler() {
     TestManagedUIHandler::InitializeInternal(
         &web_ui_, source_->GetWebUIDataSource(), profile());
-    web_ui_.HandleReceivedMessage("observeManagedUI", /*args=*/nullptr);
+    web_ui_.HandleReceivedMessage("observeManagedUI", base::Value::List());
   }
 
   bool IsSourceManaged() {
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
index 0fb654a6..af3b160 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -525,9 +525,8 @@
     return;
 
   std::vector<mojom::PrinterType> deny_list;
-  deny_list.reserve(deny_list_from_prefs->GetListDeprecated().size());
-  for (const base::Value& deny_list_value :
-       deny_list_from_prefs->GetListDeprecated()) {
+  deny_list.reserve(deny_list_from_prefs->GetList().size());
+  for (const base::Value& deny_list_value : deny_list_from_prefs->GetList()) {
     const std::string& deny_list_str = deny_list_value.GetString();
     mojom::PrinterType printer_type;
     if (deny_list_str == "extension")
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos_unittest.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos_unittest.cc
index 2d1436d..e8fc9e6 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos_unittest.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos_unittest.cc
@@ -173,13 +173,12 @@
 TEST_F(PrintPreviewHandlerChromeOSTest, ChoosePrintServersNoAsh) {
   DisableAshChrome();
 
-  base::Value selected_args(base::Value::Type::LIST);
-  base::Value selected_ids_js(base::Value::Type::LIST);
+  base::Value::List selected_args;
+  base::Value::List selected_ids_js;
   selected_ids_js.Append(kSelectedPrintServerId);
   selected_args.Append(std::move(selected_ids_js));
 
-  web_ui()->HandleReceivedMessage("choosePrintServers",
-                                  &base::Value::AsListValue(selected_args));
+  web_ui()->HandleReceivedMessage("choosePrintServers", selected_args);
   AssertWebUIEventFired(*web_ui()->call_data().back(),
                         "server-printers-loading");
   EXPECT_EQ(web_ui()->call_data().back()->arg2()->GetBool(), true);
@@ -187,10 +186,9 @@
 
 TEST_F(PrintPreviewHandlerChromeOSTest, GetPrintServersConfigNoAsh) {
   DisableAshChrome();
-  base::Value args(base::Value::Type::LIST);
+  base::Value::List args;
   args.Append("callback_id");
-  web_ui()->HandleReceivedMessage("getPrintServersConfig",
-                                  &base::Value::AsListValue(args));
+  web_ui()->HandleReceivedMessage("getPrintServersConfig", args);
   EXPECT_EQ("cr.webUIResponse", web_ui()->call_data().back()->function_name());
   EXPECT_EQ(base::Value("callback_id"), *web_ui()->call_data().back()->arg1());
   EXPECT_EQ(base::Value(true), *web_ui()->call_data().back()->arg2());
@@ -198,21 +196,19 @@
 }
 
 TEST_F(PrintPreviewHandlerChromeOSTest, ChoosePrintServers) {
-  base::Value selected_args(base::Value::Type::LIST);
-  base::Value selected_ids_js(base::Value::Type::LIST);
+  base::Value::List selected_args;
+  base::Value::List selected_ids_js;
   selected_ids_js.Append(kSelectedPrintServerId);
   selected_args.Append(std::move(selected_ids_js));
 
-  base::Value none_selected_args(base::Value::Type::LIST);
-  base::Value none_selected_js(base::Value::Type::LIST);
+  base::Value::List none_selected_args;
+  base::Value::List none_selected_js;
   none_selected_args.Append(std::move(none_selected_js));
 
-  web_ui()->HandleReceivedMessage("choosePrintServers",
-                                  &base::Value::AsListValue(selected_args));
+  web_ui()->HandleReceivedMessage("choosePrintServers", selected_args);
   EXPECT_THAT(TakePrintServerIds(),
               testing::ElementsAre(std::string(kSelectedPrintServerId)));
-  web_ui()->HandleReceivedMessage(
-      "choosePrintServers", &base::Value::AsListValue(none_selected_args));
+  web_ui()->HandleReceivedMessage("choosePrintServers", none_selected_args);
   EXPECT_THAT(TakePrintServerIds(), testing::IsEmpty());
   AssertWebUIEventFired(*web_ui()->call_data().back(),
                         "server-printers-loading");
@@ -232,8 +228,8 @@
   ChangePrintServersConfig(std::move(config));
   auto* call_data = web_ui()->call_data().back().get();
   AssertWebUIEventFired(*call_data, "print-servers-config-changed");
-  base::Value::ConstListView printer_list =
-      call_data->arg2()->FindListKey("printServers")->GetListDeprecated();
+  const base::Value::List& printer_list =
+      call_data->arg2()->FindListKey("printServers")->GetList();
   bool is_single_server_fetching_mode =
       call_data->arg2()->FindBoolKey("isSingleServerFetchingMode").value();
 
@@ -243,10 +239,9 @@
   EXPECT_EQ(*first_printer.FindStringKey("name"), kSelectedPrintServerName);
   EXPECT_EQ(is_single_server_fetching_mode, false);
 
-  base::Value args(base::Value::Type::LIST);
+  base::Value::List args;
   args.Append("callback_id");
-  web_ui()->HandleReceivedMessage("getPrintServersConfig",
-                                  &base::Value::AsListValue(args));
+  web_ui()->HandleReceivedMessage("getPrintServersConfig", args);
   const base::Value kExpectedConfig = base::test::ParseJson(R"({
     "isSingleServerFetchingMode": false,
     "printServers": [ {
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_utils.cc b/chrome/browser/ui/webui/print_preview/print_preview_utils.cc
index ca4ed70..1e45dcf 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_utils.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_utils.cc
@@ -119,8 +119,8 @@
     return true;
   const base::Value* options_list =
       select_cap->FindKeyOfType(kOptionKey, base::Value::Type::LIST);
-  if (!options_list || options_list->GetListDeprecated().empty() ||
-      GetFilteredList(options_list, ValueIsNull).GetListDeprecated().empty()) {
+  if (!options_list || options_list->GetList().empty() ||
+      GetFilteredList(options_list, ValueIsNull).GetList().empty()) {
     return true;
   }
   return false;
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
index 88849c6..17c3374 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -864,10 +864,11 @@
   // Empty manufacturer queries may be triggered as a part of the ui
   // initialization, and should just return empty results.
   if (manufacturer.empty()) {
-    base::DictionaryValue response;
-    response.SetBoolKey("success", true);
-    response.SetKey("models", base::ListValue());
-    ResolveJavascriptCallback(base::Value(callback_id), response);
+    base::Value::Dict response;
+    response.Set("success", true);
+    response.Set("models", base::Value::List());
+    ResolveJavascriptCallback(base::Value(callback_id),
+                              base::Value(std::move(response)));
     return;
   }
 
@@ -911,16 +912,17 @@
     const std::string& callback_id,
     PpdProvider::CallbackResultCode result_code,
     const std::vector<std::string>& manufacturers) {
-  base::ListValue manufacturers_value;
+  base::Value::List manufacturers_value;
   if (result_code == PpdProvider::SUCCESS) {
     for (const std::string& manufacturer : manufacturers) {
       manufacturers_value.Append(manufacturer);
     }
   }
-  base::DictionaryValue response;
-  response.SetBoolKey("success", result_code == PpdProvider::SUCCESS);
-  response.SetKey("manufacturers", std::move(manufacturers_value));
-  ResolveJavascriptCallback(base::Value(callback_id), response);
+  base::Value::Dict response;
+  response.Set("success", result_code == PpdProvider::SUCCESS);
+  response.Set("manufacturers", std::move(manufacturers_value));
+  ResolveJavascriptCallback(base::Value(callback_id),
+                            base::Value(std::move(response)));
 }
 
 void CupsPrintersHandler::ResolvePrintersDone(
@@ -928,17 +930,18 @@
     const std::string& callback_id,
     PpdProvider::CallbackResultCode result_code,
     const PpdProvider::ResolvedPrintersList& printers) {
-  base::ListValue printers_value;
+  base::Value::List printers_value;
   if (result_code == PpdProvider::SUCCESS) {
     resolved_printers_[manufacturer] = printers;
     for (const auto& printer : printers) {
       printers_value.Append(printer.name);
     }
   }
-  base::DictionaryValue response;
-  response.SetBoolKey("success", result_code == PpdProvider::SUCCESS);
-  response.SetKey("models", std::move(printers_value));
-  ResolveJavascriptCallback(base::Value(callback_id), response);
+  base::Value::Dict response;
+  response.Set("success", result_code == PpdProvider::SUCCESS);
+  response.Set("models", std::move(printers_value));
+  ResolveJavascriptCallback(base::Value(callback_id),
+                            base::Value(std::move(response)));
 }
 
 void CupsPrintersHandler::FileSelected(const base::FilePath& path,
@@ -1043,24 +1046,20 @@
     return;
   }
 
-  std::unique_ptr<base::ListValue> automatic_printers_list =
-      std::make_unique<base::ListValue>();
-  for (const Printer& printer : automatic_printers_) {
-    automatic_printers_list->Append(GetCupsPrinterInfo(printer));
-  }
+  base::Value::List automatic_printers_list;
+  for (const Printer& printer : automatic_printers_)
+    automatic_printers_list.Append(GetCupsPrinterInfo(printer));
 
-  std::unique_ptr<base::ListValue> discovered_printers_list =
-      std::make_unique<base::ListValue>();
-  for (const Printer& printer : discovered_printers_) {
-    discovered_printers_list->Append(GetCupsPrinterInfo(printer));
-  }
+  base::Value::List discovered_printers_list;
+  for (const Printer& printer : discovered_printers_)
+    discovered_printers_list.Append(GetCupsPrinterInfo(printer));
 
   PRINTER_LOG(DEBUG) << "Discovered printers updating. Automatic: "
-                     << automatic_printers_list->GetListDeprecated().size()
-                     << " Discovered: "
-                     << discovered_printers_list->GetListDeprecated().size();
-  FireWebUIListener("on-nearby-printers-changed", *automatic_printers_list,
-                    *discovered_printers_list);
+                     << automatic_printers_list.size()
+                     << " Discovered: " << discovered_printers_list.size();
+  FireWebUIListener("on-nearby-printers-changed",
+                    base::Value(std::move(automatic_printers_list)),
+                    base::Value(std::move(discovered_printers_list)));
 }
 
 void CupsPrintersHandler::HandleAddDiscoveredPrinter(
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc
index 09b52438..9e9afa7 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/callback_helpers.h"
 #include "base/files/file_path.h"
 #include "base/json/json_string_value_serializer.h"
+#include "base/test/values_test_util.h"
 #include "base/values.h"
 #include "chrome/browser/ash/printing/printing_stubs.h"
 #include "chrome/browser/download/chrome_download_manager_delegate.h"
@@ -31,21 +32,6 @@
 
 class CupsPrintersHandlerTest;
 
-namespace {
-
-// Converts JSON string to base::ListValue object.
-// On failure, returns NULL and fills |*error| string.
-std::unique_ptr<base::ListValue> GetJSONAsListValue(const std::string& json,
-                                                    std::string* error) {
-  auto ret = base::ListValue::From(
-      JSONStringValueDeserializer(json).Deserialize(nullptr, error));
-  if (!ret)
-    *error = "Value is not a list.";
-  return ret;
-}
-
-}  // namespace
-
 // Callback used for testing CupsAddAutoConfiguredPrinter().
 void AddedPrinter(int32_t status) {
   ASSERT_EQ(status, 0);
@@ -222,11 +208,10 @@
     ["testprinter1", "Test Printer 1"]
   )";
   std::string error;
-  std::unique_ptr<base::ListValue> remove_printers(
-      GetJSONAsListValue(remove_list, &error));
-  ASSERT_TRUE(remove_printers) << "Error deserializing list: " << error;
+  base::Value remove_printers = base::test::ParseJson(remove_list);
+  ASSERT_TRUE(remove_printers.is_list());
 
-  web_ui_.HandleReceivedMessage("removeCupsPrinter", remove_printers.get());
+  web_ui_.HandleReceivedMessage("removeCupsPrinter", remove_printers.GetList());
 
   // We expect this printer removal to fail since the printer should have
   // already been removed by the previous call to 'removeCupsPrinter'.
@@ -256,10 +241,9 @@
   ui::SelectFileDialog::SetFactory(
       new TestSelectFileDialogFactory(&expected_file_type_info));
 
-  base::Value args(base::Value::Type::LIST);
+  base::Value::List args;
   args.Append("handleFunctionName");
-  web_ui_.HandleReceivedMessage("selectPPDFile",
-                                &base::Value::AsListValue(args));
+  web_ui_.HandleReceivedMessage("selectPPDFile", args);
 }
 
 }  // namespace settings.
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 3d96104..826dadf3 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1653674373-ae360f838a4fa534e501473833b13cfbbd93791b.profdata
+chrome-linux-main-1653738865-42809a41ca50b9125582fc5a460bb8afe428e76f.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index c86ae9b..7761f669 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1653674373-93e7a7459c3f91f24d82ce4da21ea54e657793e2.profdata
+chrome-mac-arm-main-1653738865-a6004ac5e9ac4b2e6f275d60209e3871ee91c367.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index db6849e..ae3aa3b 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1653674373-ea5fe4c1bad0af9f9937b9344482cc6a8e01974d.profdata
+chrome-mac-main-1653738865-e86d159c50fe9803becd6a6c995dc9314a96947e.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index fcf91e8..b2be010f 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1653674373-acea6486b590716fd115fd9b37b69c6003616bc8.profdata
+chrome-win32-main-1653738865-9a5cf909c21b271b8e0b23fe13f0030688c3d73e.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 91174da..dd87282 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1653682408-7e1dd82cfc97a287ee426e4efb8f4a3dc5bb5f1f.profdata
+chrome-win64-main-1653749916-1c8d23c8554410a9dba3c3303cb8f0dab46e36e0.profdata
diff --git a/chrome/test/data/extensions/api_test/vpn_provider/basic.js b/chrome/test/data/extensions/api_test/vpn_provider/basic.js
index c8615b7..bea399f 100644
--- a/chrome/test/data/extensions/api_test/vpn_provider/basic.js
+++ b/chrome/test/data/extensions/api_test/vpn_provider/basic.js
@@ -159,6 +159,24 @@
       chrome.test.succeed();
     });
   },
+  createConfigConnectForBind: function() {
+    chrome.vpnProvider.onPlatformMessage.addListener(function(config_name,
+                                                              message, error) {
+      if (message === 'connected') {
+        chrome.test.assertEq(config_name, 'testconfig');
+        chrome.vpnProvider.notifyConnectionStateChanged('connected', () => {
+          chrome.test.succeed();
+        });
+      } else {
+        chrome.test.assertEq(message, 'disconnected');
+        chrome.test.succeed();
+      }
+    });
+    chrome.vpnProvider.createConfig('testconfig', function() {
+      chrome.test.assertEq(chrome.runtime.lastError, undefined);
+      chrome.test.succeed();
+    });
+  },
   createConfigConnectAndDisconnect: function() {
     // The test sets up a set of listeners and creates a config.
     // The created config is connected to by the C++ side, which initiates the
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index b31aa6c..8bc1b9d 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -141,7 +141,6 @@
     if (is_chromeos_ash) {
       gen_include_files +=
           [ "settings/chromeos/a11y/os_settings_accessibility_v3_test.js" ]
-      deps += [ ":modulize" ]
     }
 
     if (is_chromeos_ash || is_win || is_mac) {
@@ -219,13 +218,6 @@
       data += [ "$root_gen_dir/chrome/test/data/webui/inline_login/inline_login_test_util.js" ]
     }
 
-    if (is_chromeos_ash) {
-      data += [
-        "$root_gen_dir/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/integration_test.m.js",
-        "$root_gen_dir/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/setup_succeeded_page_test.m.js",
-        "$root_gen_dir/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/start_setup_page_test.m.js",
-      ]
-    }
     defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
   }
 
@@ -303,12 +295,6 @@
   }
 }
 
-if (is_chromeos_ash) {
-  group("modulize") {
-    deps = [ "./cr_components/chromeos:modulize" ]
-  }
-}
-
 group("closure_compile") {
   deps = [
     ":closure_compile_local",
diff --git a/chrome/test/data/webui/chromeos/diagnostics/input_list_test.js b/chrome/test/data/webui/chromeos/diagnostics/input_list_test.js
index 41e940d..43d812b 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/input_list_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/input_list_test.js
@@ -11,7 +11,7 @@
 import {setInputDataProviderForTesting} from 'chrome://diagnostics/mojo_interface_provider.js';
 
 import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
-import {flushTasks} from '../../test_util.js';
+import {flushTasks, isVisible} from '../../test_util.js';
 
 import {TestDiagnosticsBrowserProxy} from './test_diagnostics_browser_proxy.js';
 
@@ -63,15 +63,6 @@
     return /** @type {!InputCardElement} */ (card);
   }
 
-  /**
-   * Returns whether the element both exists and is visible.
-   * @param {?Element} element
-   * @return {boolean}
-   */
-  function isVisible(element) {
-    return !!element && element.style.display !== 'none';
-  }
-
   test('InputListPopulated', async () => {
     await initializeInputList();
     assertEquals(
diff --git a/chrome/test/data/webui/cr_components/BUILD.gn b/chrome/test/data/webui/cr_components/BUILD.gn
index 99ea37f..d8efa3b 100644
--- a/chrome/test/data/webui/cr_components/BUILD.gn
+++ b/chrome/test/data/webui/cr_components/BUILD.gn
@@ -27,6 +27,7 @@
   "app_management/permission_item_test.ts",
   "app_management/window_mode_item_test.ts",
   "customize_themes_test.ts",
+  "history_clusters_test.ts",
   "managed_dialog_test.ts",
   "most_visited_focus_test.ts",
   "most_visited_test.ts",
@@ -66,6 +67,7 @@
   deps = [
     "//ui/webui/resources/cr_components/app_management:build_ts",
     "//ui/webui/resources/cr_components/customize_themes:build_ts",
+    "//ui/webui/resources/cr_components/history_clusters:build_ts",
     "//ui/webui/resources/cr_components/most_visited:build_ts",
   ]
 
diff --git a/chrome/test/data/webui/cr_components/chromeos/BUILD.gn b/chrome/test/data/webui/cr_components/chromeos/BUILD.gn
index c04d7b0..960b07d 100644
--- a/chrome/test/data/webui/cr_components/chromeos/BUILD.gn
+++ b/chrome/test/data/webui/cr_components/chromeos/BUILD.gn
@@ -5,10 +5,6 @@
 
 assert(is_chromeos, "CrComponents Chromeos tests are Chrome OS only.")
 
-group("modulize") {
-  deps = [ "multidevice_setup:modulize" ]
-}
-
 group("closure_compile") {
   deps = [
     "bluetooth:closure_compile",
diff --git a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js
index 1bb9f7b..88a7fd3 100644
--- a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js
+++ b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js
@@ -72,9 +72,9 @@
 ].forEach(test => registerTest('TrafficCounters', 'network', ...test));
 
 [
- ['Integration', 'multidevice_setup/integration_test.m.js'],
- ['SetupSucceededPage', 'multidevice_setup/setup_succeeded_page_test.m.js'],
- ['StartSetupPage', 'multidevice_setup/start_setup_page_test.m.js'],
+ ['Integration', 'multidevice_setup/integration_test.js'],
+ ['SetupSucceededPage', 'multidevice_setup/setup_succeeded_page_test.js'],
+ ['StartSetupPage', 'multidevice_setup/start_setup_page_test.js'],
 ].forEach(test => registerTest('MultiDeviceSetup', 'multidevice-setup', ...test));
 
 [
diff --git a/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/BUILD.gn b/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/BUILD.gn
index 3e26e52..ae1922e1 100644
--- a/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/BUILD.gn
+++ b/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/BUILD.gn
@@ -1,18 +1,3 @@
 # Copyright 2020 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
-
-import("//chrome/test/data/webui/namespace_rewrites.gni")
-import("//chrome/test/data/webui/settings/chromeos/os_namespace_rewrites.gni")
-import("//ui/webui/resources/cr_components/chromeos/os_cr_components.gni")
-import("//ui/webui/resources/tools/js_modulizer.gni")
-
-js_modulizer("modulize") {
-  input_files = [
-    "integration_test.js",
-    "setup_succeeded_page_test.js",
-    "start_setup_page_test.js",
-  ]
-  namespace_rewrites = cr_components_chromeos_namespace_rewrites +
-                       os_test_namespace_rewrites + test_namespace_rewrites
-}
diff --git a/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/integration_test.js b/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/integration_test.js
index 2e112e01..28cbe27 100644
--- a/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/integration_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/integration_test.js
@@ -2,17 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// clang-format off
-// #import 'chrome://multidevice-setup/strings.m.js';
-// #import 'chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup.m.js';
+import 'chrome://multidevice-setup/strings.m.js';
+import 'chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup.m.js';
 
-// #import {TestMultideviceSetupBrowserProxy} from './setup_succeeded_page_test.m.js';
-// #import {FakeQuickUnlockPrivate} from '../../../settings/chromeos/fake_quick_unlock_private.js';
-// #import {BrowserProxyImpl} from 'chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.m.js';
-// #import {FakeMojoService} from 'chrome://resources/cr_components/chromeos/multidevice_setup/fake_mojo_service.m.js';
-// #import {waitBeforeNextRender, eventToPromise} from '../../../test_util.js';
-// #import {flush, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-// clang-format on
+import {FakeMojoService} from 'chrome://resources/cr_components/chromeos/multidevice_setup/fake_mojo_service.m.js';
+import {BrowserProxyImpl} from 'chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.m.js';
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {FakeQuickUnlockPrivate} from '../../../settings/chromeos/fake_quick_unlock_private.js';
+import {eventToPromise, waitBeforeNextRender} from '../../../test_util.js';
+
+import {TestMultideviceSetupBrowserProxy} from './setup_succeeded_page_test.js';
+
 
 /** @fileoverview Suite of integration tests for MultiDevice setup WebUI. */
 /** @implements {multidevice_setup.MultiDeviceSetupDelegate} */
@@ -105,7 +106,7 @@
   /** @type {!FakeMojoService} */
   let fakeMojoService;
 
-  /** @type {!settings.FakeQuickUnlockPrivate} */
+  /** @type {!FakeQuickUnlockPrivate} */
   let fakeQuickUnlockPrivate;
 
   /** @type {?TestMultideviceSetupBrowserProxy} */
@@ -119,13 +120,8 @@
   const WRONG_PASSWORD = 'wrongPassword';
 
   setup(async () => {
-    // The OOBE host uses polyfill which requires the test to wait until HTML
-    // imports have finished loading before initiating any tests. The Polymer 3
-    // version of the test does not use the OOBE host so this line should not
-    // execute.
-    /* #ignore */ await cr.ui.Oobe.waitForOobeToLoad();
     browserProxy = new TestMultideviceSetupBrowserProxy();
-    multidevice_setup.BrowserProxyImpl.instance_ = browserProxy;
+    BrowserProxyImpl.instance_ = browserProxy;
 
     multiDeviceSetupElement = document.createElement('multidevice-setup');
     multiDeviceSetupElement.delegate = new FakeDelegate();
@@ -134,13 +130,13 @@
         new FakeMojoInterfaceProviderImpl(fakeMojoService);
 
     document.body.appendChild(multiDeviceSetupElement);
-    Polymer.dom.flush();
+    flush();
 
     forwardButton = multiDeviceSetupElement.$$('button-bar').$$('#forward');
     cancelButton = multiDeviceSetupElement.$$('button-bar').$$('#cancel');
     backwardButton = multiDeviceSetupElement.$$('button-bar').$$('#backward');
 
-    fakeQuickUnlockPrivate = new settings.FakeQuickUnlockPrivate();
+    fakeQuickUnlockPrivate = new FakeQuickUnlockPrivate();
     fakeQuickUnlockPrivate.accountPassword = CORRECT_PASSWORD;
     multiDeviceSetupElement.$$(PASSWORD).quickUnlockPrivate_ =
         fakeQuickUnlockPrivate;
@@ -159,9 +155,8 @@
    */
   function setVisiblePage(visiblePageName) {
     multiDeviceSetupElement.visiblePageName = visiblePageName;
-    Polymer.dom.flush();
-    return test_util.waitBeforeNextRender(
-        multiDeviceSetupElement.$$(visiblePageName));
+    flush();
+    return waitBeforeNextRender(multiDeviceSetupElement.$$(visiblePageName));
   }
 
   /**
@@ -170,8 +165,8 @@
    */
   function enterPassword(input) {
     multiDeviceSetupElement.$$(PASSWORD).$$('#passwordInput').value = input;
-    Polymer.dom.flush();
-    return test_util.waitBeforeNextRender(multiDeviceSetupElement);
+    flush();
+    return waitBeforeNextRender(multiDeviceSetupElement);
   }
 
   function getNumSetHostDeviceCalls() {
@@ -191,7 +186,7 @@
   test('SetupSucceededPage forward button closes UI', () => {
     return setVisiblePage(SUCCESS).then(() => {
       const whenSetupExits =
-          test_util.eventToPromise('setup-exited', multiDeviceSetupElement);
+          eventToPromise('setup-exited', multiDeviceSetupElement);
       forwardButton.click();
       return whenSetupExits;
     });
@@ -203,7 +198,7 @@
     setMode(false /* isOobeMode */);
     return setVisiblePage(SUCCESS).then(() => {
       const whenSetupExits =
-          test_util.eventToPromise('setup-exited', multiDeviceSetupElement);
+          eventToPromise('setup-exited', multiDeviceSetupElement);
       multiDeviceSetupElement.$$(SUCCESS).$$('#settings-link').click();
       return whenSetupExits;
     });
@@ -227,7 +222,7 @@
     return setVisiblePage(START)
         .then(() => {
           const whenSetupExits =
-              test_util.eventToPromise('setup-exited', multiDeviceSetupElement);
+              eventToPromise('setup-exited', multiDeviceSetupElement);
           cancelButton.click();
           return whenSetupExits;
         })
@@ -245,8 +240,8 @@
         return setVisiblePage(START)
             .then(() => {
               multiDeviceSetupElement.delegate.shouldSetHostSucceed = true;
-              const whenSetupExits = test_util.eventToPromise(
-                  'setup-exited', multiDeviceSetupElement);
+              const whenSetupExits =
+                  eventToPromise('setup-exited', multiDeviceSetupElement);
               forwardButton.click();
               return whenSetupExits;
             })
@@ -263,7 +258,7 @@
     return setVisiblePage(START)
         .then(() => {
           const whenSetupExits =
-              test_util.eventToPromise('setup-exited', multiDeviceSetupElement);
+              eventToPromise('setup-exited', multiDeviceSetupElement);
           cancelButton.click();
           return whenSetupExits;
         })
@@ -290,7 +285,7 @@
     return setVisiblePage(PASSWORD)
         .then(() => {
           const whenSetupExits =
-              test_util.eventToPromise('setup-exited', multiDeviceSetupElement);
+              eventToPromise('setup-exited', multiDeviceSetupElement);
           cancelButton.click();
           return whenSetupExits;
         })
@@ -304,7 +299,7 @@
 
     return setVisiblePage(PASSWORD)
         .then(() => {
-          const whenPageChanges = test_util.eventToPromise(
+          const whenPageChanges = eventToPromise(
               'visible-page-name-changed', multiDeviceSetupElement);
           backwardButton.click();
           return whenPageChanges;
@@ -327,7 +322,7 @@
             })
             .then(() => {
               multiDeviceSetupElement.delegate.shouldSetHostSucceed = true;
-              const whenPageChanges = test_util.eventToPromise(
+              const whenPageChanges = eventToPromise(
                   'visible-page-name-changed', multiDeviceSetupElement);
               forwardButton.click();
               return whenPageChanges;
@@ -351,8 +346,8 @@
             .then(() => {
               multiDeviceSetupElement.delegate.shouldSetHostSucceed = true;
               forwardButton.click();
-              Polymer.dom.flush();
-              return test_util.waitBeforeNextRender(multiDeviceSetupElement);
+              flush();
+              return waitBeforeNextRender(multiDeviceSetupElement);
             })
             .then(() => {
               assertEquals(PASSWORD, multiDeviceSetupElement.visiblePageName);
@@ -372,8 +367,8 @@
             })
             .then(() => {
               forwardButton.click();
-              Polymer.dom.flush();
-              return test_util.waitBeforeNextRender(multiDeviceSetupElement);
+              flush();
+              return waitBeforeNextRender(multiDeviceSetupElement);
             })
             .then(() => {
               assertTrue(multiDeviceSetupElement.forwardButtonDisabled);
diff --git a/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/setup_succeeded_page_test.js b/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/setup_succeeded_page_test.js
index 6a87c3a..516828b4 100644
--- a/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/setup_succeeded_page_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/setup_succeeded_page_test.js
@@ -2,23 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// clang-format off
-// #import 'chrome://multidevice-setup/strings.m.js';
-// #import 'chrome://resources/cr_components/chromeos/multidevice_setup/setup_succeeded_page.m.js';
-
-// #import {TestBrowserProxy} from '../../../test_browser_proxy.js';
-// #import {BrowserProxyImpl} from 'chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.m.js';
-// clang-format on
-
 /**
  * @fileoverview Suite of tests for page-specific behaviors of
  * SetupSucceededPage.
  */
 
+import 'chrome://multidevice-setup/strings.m.js';
+import 'chrome://resources/cr_components/chromeos/multidevice_setup/setup_succeeded_page.m.js';
+
+import {BrowserProxyImpl} from 'chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.m.js';
+
+import {TestBrowserProxy} from '../../../test_browser_proxy.js';
+
 /**
- * @implements {multidevice_setup.BrowserProxy}
+ * @implements {BrowserProxy}
  */
-/* #export */ class TestMultideviceSetupBrowserProxy extends TestBrowserProxy {
+export class TestMultideviceSetupBrowserProxy extends TestBrowserProxy {
   constructor() {
     super(['getProfileInfo', 'openMultiDeviceSettings']);
   }
@@ -45,9 +44,8 @@
   let browserProxy = null;
 
   setup(async () => {
-    /* #ignore */ await cr.ui.Oobe.waitForOobeToLoad();
     browserProxy = new TestMultideviceSetupBrowserProxy();
-    multidevice_setup.BrowserProxyImpl.instance_ = browserProxy;
+    BrowserProxyImpl.instance_ = browserProxy;
 
     setupSucceededPageElement = document.createElement('setup-succeeded-page');
     document.body.appendChild(setupSucceededPageElement);
diff --git a/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/start_setup_page_test.js b/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/start_setup_page_test.js
index 22ea2be..b803836 100644
--- a/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/start_setup_page_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/multidevice_setup/start_setup_page_test.js
@@ -2,12 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// clang-format off
-// #import 'chrome://multidevice-setup/strings.m.js';
-// #import 'chrome://resources/cr_components/chromeos/multidevice_setup/start_setup_page.m.js';
+import 'chrome://multidevice-setup/strings.m.js';
+import 'chrome://resources/cr_components/chromeos/multidevice_setup/start_setup_page.m.js';
 
-// #import {flush, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-// clang-format on
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 /**
  * In the testing framework, a click on a select option does not cause a
@@ -65,15 +63,10 @@
   ];
 
   setup(async () => {
-    // The OOBE host uses polyfill which requires the test to wait until HTML
-    // imports have finished loading before initiating any tests. The Polymer 3
-    // version of the test does not use the OOBE host so this line should not
-    // execute.
-    /* #ignore */ await cr.ui.Oobe.waitForOobeToLoad();
     startSetupPageElement = document.createElement('start-setup-page');
     document.body.appendChild(startSetupPageElement);
     startSetupPageElement.devices = DEVICES;
-    Polymer.dom.flush();
+    flush();
     emulateDropdownBehavior(startSetupPageElement.$.deviceDropdown);
   });
 
diff --git a/chrome/test/data/webui/cr_components/chromeos/network/network_select_test.js b/chrome/test/data/webui/cr_components/chromeos/network/network_select_test.js
index 29c3b00..2b8e616 100644
--- a/chrome/test/data/webui/cr_components/chromeos/network/network_select_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/network/network_select_test.js
@@ -11,11 +11,6 @@
   let networkSelect;
 
   setup(async function() {
-    // The OOBE host uses polyfill which requires the test to wait until HTML
-    // imports have finished loading before initiating any tests. The Polymer 3
-    // version of the test does not use the OOBE host so this line should not
-    // execute.
-    // await cr.ui.Oobe.waitForOobeToLoad();
     networkSelect = document.createElement('network-select');
     document.body.appendChild(networkSelect);
     flush();
diff --git a/chrome/test/data/webui/cr_components/cr_components_mojo_browsertest.js b/chrome/test/data/webui/cr_components/cr_components_mojo_browsertest.js
index 98b0611..dd31a55f 100644
--- a/chrome/test/data/webui/cr_components/cr_components_mojo_browsertest.js
+++ b/chrome/test/data/webui/cr_components/cr_components_mojo_browsertest.js
@@ -32,6 +32,18 @@
   mocha.run();
 });
 
+var CrComponentsHistoryClustersTest =
+    class extends CrComponentsMojoBrowserTest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://history/test_loader.html?module=cr_components/history_clusters_test.js&host=webui-test';
+  }
+};
+
+TEST_F('CrComponentsHistoryClustersTest', 'All', function() {
+  mocha.run();
+});
+
 var CrComponentsMostVisitedTest = class extends CrComponentsMojoBrowserTest {
   /** @override */
   get browsePreload() {
diff --git a/chrome/test/data/webui/cr_components/history_clusters_test.ts b/chrome/test/data/webui/cr_components/history_clusters_test.ts
new file mode 100644
index 0000000..a3995892
--- /dev/null
+++ b/chrome/test/data/webui/cr_components/history_clusters_test.ts
@@ -0,0 +1,59 @@
+// 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.
+
+import 'chrome://history/strings.m.js';
+import 'chrome://webui-test/mojo_webui_test_support.js';
+
+import {BrowserProxyImpl} from 'chrome://resources/cr_components/history_clusters/browser_proxy.js';
+import {HistoryClustersElement} from 'chrome://resources/cr_components/history_clusters/clusters.js';
+import {Cluster, PageCallbackRouter, PageHandlerRemote, QueryResult} from 'chrome://resources/cr_components/history_clusters/history_clusters.mojom-webui.js';
+import {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
+import {flushTasks} from 'chrome://webui-test/test_util.js';
+
+let handler: PageHandlerRemote&TestBrowserProxy;
+let callbackRouterRemote: PageCallbackRouter;
+
+function createBrowserProxy() {
+  handler = TestBrowserProxy.fromClass(PageHandlerRemote);
+  const callbackRouter = new PageCallbackRouter();
+  BrowserProxyImpl.setInstance(new BrowserProxyImpl(handler, callbackRouter));
+  callbackRouterRemote = callbackRouter.$.bindNewPipeAndPassRemote();
+}
+
+suite('history-clusters', () => {
+  setup(() => {
+    document.body.innerHTML = '';
+
+    createBrowserProxy();
+  });
+
+  test('Basic end-to-end', async () => {
+    const clustersElement = new HistoryClustersElement();
+    document.body.appendChild(clustersElement);
+
+    const query = await handler.whenCalled('startQueryClusters');
+    assertEquals(query, '');
+
+    const cluster1 = new Cluster();
+    cluster1.visits = [];
+    cluster1.labelMatchPositions = [];
+    cluster1.relatedSearches = [];
+    const cluster2 = new Cluster();
+    cluster2.visits = [];
+    cluster2.labelMatchPositions = [];
+    cluster2.relatedSearches = [];
+
+    const queryResult = new QueryResult();
+    queryResult.query = '';
+    queryResult.clusters = [cluster1, cluster2];
+
+    callbackRouterRemote.onClustersQueryResult(queryResult);
+    await callbackRouterRemote.$.flushForTesting();
+    flushTasks();
+
+    const ironListItems = clustersElement.$.clusters.items!;
+    assertEquals(ironListItems.length, 2);
+  });
+});
diff --git a/chrome/test/data/webui/cr_elements/BUILD.gn b/chrome/test/data/webui/cr_elements/BUILD.gn
index bcf2175..9588bbb 100644
--- a/chrome/test/data/webui/cr_elements/BUILD.gn
+++ b/chrome/test/data/webui/cr_elements/BUILD.gn
@@ -62,6 +62,7 @@
     "cr_toolbar_focus_tests.ts",
     "cr_toolbar_search_field_tests.ts",
     "cr_toolbar_test.ts",
+    "cr_tree_test.ts",
     "cr_view_manager_test.ts",
     "find_shortcut_mixin_test.ts",
     "iron_list_focus_test.ts",
diff --git a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
index 5be277db..4780c336 100644
--- a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
+++ b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
@@ -388,3 +388,14 @@
 TEST_F('CrElementsToolbarTest', 'All', function() {
   mocha.run();
 });
+
+var CrElementsTreeTest = class extends CrElementsBrowserTest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://test/test_loader.html?module=cr_elements/cr_tree_test.js&host=webui-test';
+  }
+};
+
+TEST_F('CrElementsTreeTest', 'All', function() {
+  mocha.run();
+});
diff --git a/chrome/test/data/webui/cr_elements/cr_tree_test.ts b/chrome/test/data/webui/cr_elements/cr_tree_test.ts
new file mode 100644
index 0000000..c83aa49
--- /dev/null
+++ b/chrome/test/data/webui/cr_elements/cr_tree_test.ts
@@ -0,0 +1,139 @@
+// 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.
+
+// clang-format off
+import 'chrome://resources/cr_elements/cr_tree/cr_tree_item.js';
+import 'chrome://resources/cr_elements/cr_tree/cr_tree.js';
+
+import {CrTreeElement} from 'chrome://resources/cr_elements/cr_tree/cr_tree.js';
+import {CrTreeItemElement, SELECTED_ATTR} from 'chrome://resources/cr_elements/cr_tree/cr_tree_item.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {eventToPromise} from 'chrome://webui-test/test_util.js';
+
+// clang-format on
+
+suite('cr-tree', function() {
+  let tree: CrTreeElement;
+  let root: CrTreeItemElement;
+  let foo: CrTreeItemElement;
+  let bar: CrTreeItemElement;
+  let baz: CrTreeItemElement;
+
+  setup(() => {
+    document.body.innerHTML = '';
+    tree = document.createElement('cr-tree');
+    document.body.appendChild(tree);
+
+    root = document.createElement('cr-tree-item');
+    root.label = 'Root';
+    foo = document.createElement('cr-tree-item');
+    foo.label = 'Foo';
+    bar = document.createElement('cr-tree-item');
+    bar.label = 'Bar';
+    baz = document.createElement('cr-tree-item');
+    baz.label = 'Baz';
+
+    bar.add(baz);
+    root.add(foo);
+    root.add(bar);
+    tree.add(root);
+  });
+
+  // Check tree structure is created correctly.
+  test('items', () => {
+    assertTrue(tree.hasChildren);
+    assertEquals(1, tree.items.length);
+    assertEquals(root, tree.items[0]);
+    assertEquals(tree, root.tree);
+
+    assertTrue(root.hasChildren);
+    assertEquals(2, root.items.length);
+    assertEquals(foo, root.items[0]);
+    assertEquals(bar, root.items[1]);
+    assertEquals(tree, root.tree);
+    assertEquals(tree, root.parentItem);
+
+    assertFalse(foo.hasChildren);
+    assertEquals(0, foo.items.length);
+    assertEquals(tree, foo.tree);
+    assertEquals(root, foo.parentItem);
+
+    assertTrue(bar.hasChildren);
+    assertEquals(1, bar.items.length);
+    assertEquals(baz, bar.items[0]);
+    assertEquals(tree, bar.tree);
+    assertEquals(root, bar.parentItem);
+
+    assertFalse(baz.hasChildren);
+    assertEquals(0, baz.items.length);
+    assertEquals(tree, baz.tree);
+    assertEquals(bar, baz.parentItem);
+  });
+
+  // Verify selecting an item expands its ancestors.
+  test('selection', async () => {
+    assertFalse(root.expanded);
+    assertFalse(bar.expanded);
+    assertFalse(foo.hasAttribute(SELECTED_ATTR));
+    const whenExpand = eventToPromise('cr-tree-item-expand', tree);
+    tree.selectedItem = foo;
+    await whenExpand;
+    assertTrue(foo.hasAttribute(SELECTED_ATTR));
+    assertFalse(root.hasAttribute(SELECTED_ATTR));
+    assertTrue(root.expanded);
+    assertFalse(bar.hasAttribute(SELECTED_ATTR));
+    assertFalse(bar.expanded);
+  });
+
+  test('collapse/expand with arrow keys', async () => {
+    // Expand root
+    tree.selectedItem = root;
+    let whenExpand = eventToPromise('cr-tree-item-expand', tree);
+    tree.dispatchEvent(new KeyboardEvent('keydown', {key: 'ArrowRight'}));
+    await whenExpand;
+    assertTrue(root.expanded);
+    assertFalse(bar.expanded);
+
+    // Select bar
+    tree.dispatchEvent(new KeyboardEvent('keydown', {key: 'ArrowDown'}));
+    tree.dispatchEvent(new KeyboardEvent('keydown', {key: 'ArrowDown'}));
+    assertEquals(bar, tree.selectedItem);
+
+    // Expand bar
+    whenExpand = eventToPromise('cr-tree-item-expand', tree);
+    tree.dispatchEvent(new KeyboardEvent('keydown', {key: 'ArrowRight'}));
+    await whenExpand;
+    assertTrue(root.expanded);
+    assertTrue(bar.expanded);
+
+    // Re-select root
+    tree.dispatchEvent(new KeyboardEvent('keydown', {key: 'ArrowUp'}));
+    tree.dispatchEvent(new KeyboardEvent('keydown', {key: 'ArrowUp'}));
+    assertEquals(root, tree.selectedItem);
+
+    // Collapse root
+    const whenCollapse = eventToPromise('cr-tree-item-collapse', tree);
+    tree.dispatchEvent(new KeyboardEvent('keydown', {key: 'ArrowLeft'}));
+    await whenCollapse;
+    assertFalse(root.expanded);
+    assertTrue(bar.expanded);
+  });
+
+  test('removal', async () => {
+    const whenExpand = eventToPromise('cr-tree-item-expand', tree);
+    tree.selectedItem = baz;
+    await whenExpand;
+    assertTrue(bar.hasChildren);
+    assertEquals(1, bar.items.length);
+    assertFalse(bar.hasAttribute(SELECTED_ATTR));
+    assertTrue(baz.hasAttribute(SELECTED_ATTR));
+    const whenChange = eventToPromise('cr-tree-change', tree);
+    bar.removeTreeItem(baz);
+    await whenChange;
+    assertEquals(bar, tree.selectedItem);
+    assertTrue(bar.hasAttribute(SELECTED_ATTR));
+    assertFalse(bar.hasChildren);
+    assertEquals(0, bar.items.length);
+  });
+});
diff --git a/chrome/test/data/webui/settings/chromeos/crostini_page_test.js b/chrome/test/data/webui/settings/chromeos/crostini_page_test.js
index c3ce1e4..d8af9f7 100644
--- a/chrome/test/data/webui/settings/chromeos/crostini_page_test.js
+++ b/chrome/test/data/webui/settings/chromeos/crostini_page_test.js
@@ -2,16 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {TestGuestOsBrowserProxy} from './test_guest_os_browser_proxy.js';
-import {TestCrostiniBrowserProxy} from './test_crostini_browser_proxy.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
-import {flush} from'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {getDeepActiveElement} from 'chrome://resources/js/util.m.js';
+import {CrostiniBrowserProxyImpl, GuestOsBrowserProxyImpl} from 'chrome://os-settings/chromeos/lazy_load.js';
 import {Router, routes} from 'chrome://os-settings/chromeos/os_settings.js';
-import {eventToPromise, flushTasks, waitAfterNextRender} from 'chrome://test/test_util.js';
-import {GuestOsBrowserProxyImpl, CrostiniBrowserProxyImpl} from 'chrome://os-settings/chromeos/lazy_load.js';
 import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {getDeepActiveElement} from 'chrome://resources/js/util.m.js';
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {eventToPromise, flushTasks, isVisible, waitAfterNextRender} from 'chrome://test/test_util.js';
+
+import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+
+import {TestCrostiniBrowserProxy} from './test_crostini_browser_proxy.js';
+import {TestGuestOsBrowserProxy} from './test_guest_os_browser_proxy.js';
 
 /** @type {?SettingsCrostiniPageElement} */
 let crostiniPage = null;
@@ -47,15 +49,6 @@
   flush();
 }
 
-/**
- * Checks whether a given element is visible to the user.
- * @param {!Element} element
- * @returns {boolean}
- */
-function isVisible(element) {
-  return !!(element && element.getBoundingClientRect().width > 0);
-}
-
 suite('CrostiniPageTests', function() {
   setup(function() {
     crostiniBrowserProxy = new TestCrostiniBrowserProxy();
diff --git a/chrome/test/data/webui/settings/chromeos/device_page_tests.js b/chrome/test/data/webui/settings/chromeos/device_page_tests.js
index ca0543cf..dfc0d50 100644
--- a/chrome/test/data/webui/settings/chromeos/device_page_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/device_page_tests.js
@@ -10,7 +10,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {getDeepActiveElement} from 'chrome://resources/js/util.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {flushTasks, waitAfterNextRender} from 'chrome://test/test_util.js';
+import {flushTasks, isVisible, waitAfterNextRender} from 'chrome://test/test_util.js';
 
 import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
 
@@ -628,17 +628,6 @@
   }
 
   /**
-   * Returns whether the element both exists and is visible.
-   * @param {?Element} element
-   * @return {boolean}
-   */
-  function isVisible(element) {
-    // offsetWidth and offsetHeight reflect more ways that an element could be
-    // hidden, compared to checking the hidden attribute directly.
-    return !!element && element.offsetWidth > 0 && element.offsetHeight > 0;
-  }
-
-  /**
    * Checks that the deep link to a setting focuses the correct element.
    * @param {!Route} route
    * @param {!string} settingId
diff --git a/chrome/test/data/webui/settings/chromeos/fingerprint_browsertest_chromeos.js b/chrome/test/data/webui/settings/chromeos/fingerprint_browsertest_chromeos.js
index 62ec71b..cf922db 100644
--- a/chrome/test/data/webui/settings/chromeos/fingerprint_browsertest_chromeos.js
+++ b/chrome/test/data/webui/settings/chromeos/fingerprint_browsertest_chromeos.js
@@ -5,7 +5,7 @@
 import {FingerprintBrowserProxyImpl, FingerprintResultType, FingerprintSetupStep, Router, routes} from 'chrome://os-settings/chromeos/os_settings.js';
 import {getDeepActiveElement} from 'chrome://resources/js/util.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {flushTasks, waitAfterNextRender} from 'chrome://test/test_util.js';
+import {flushTasks, isVisible, waitAfterNextRender} from 'chrome://test/test_util.js';
 
 import {TestBrowserProxy} from '../../test_browser_proxy.js';
 
@@ -121,13 +121,6 @@
     addAnotherButton = dialog.shadowRoot.querySelector('#addAnotherButton');
   }
 
-  /**
-   * @param {!Element} element
-   */
-  function isVisible(element) {
-    return element.offsetWidth > 0 && element.offsetHeight > 0;
-  }
-
   setup(function() {
     browserProxy = new TestFingerprintBrowserProxy();
     FingerprintBrowserProxyImpl.setInstance(browserProxy);
diff --git a/chrome/test/data/webui/settings/chromeos/manage_accessibility_page_tests.js b/chrome/test/data/webui/settings/chromeos/manage_accessibility_page_tests.js
index 407b6550..1fde14f3 100644
--- a/chrome/test/data/webui/settings/chromeos/manage_accessibility_page_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/manage_accessibility_page_tests.js
@@ -3,20 +3,13 @@
 // found in the LICENSE file.
 
 import 'chrome://os-settings/chromeos/lazy_load.js';
-import {DevicePageBrowserProxy, DevicePageBrowserProxyImpl, routes, Router} from 'chrome://os-settings/chromeos/os_settings.js';
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
-import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {getDeepActiveElement} from 'chrome://resources/js/util.m.js';
-import {eventToPromise, waitBeforeNextRender, waitAfterNextRender} from 'chrome://test/test_util.js';
 
-/**
- * Checks whether a given element is visible to the user.
- * @param {!Element} element
- * @returns {boolean}
- */
-function isVisible(element) {
-  return !!(element && element.getBoundingClientRect().width > 0);
-}
+import {DevicePageBrowserProxy, DevicePageBrowserProxyImpl, Router, routes} from 'chrome://os-settings/chromeos/os_settings.js';
+import {getDeepActiveElement} from 'chrome://resources/js/util.m.js';
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {eventToPromise, isVisible, waitAfterNextRender, waitBeforeNextRender} from 'chrome://test/test_util.js';
+
+import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
 
 suite('ManageAccessibilityPageTests', function() {
   let page = null;
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_ui_test_2.js b/chrome/test/data/webui/settings/chromeos/os_settings_ui_test_2.js
index 45c864a..85a70274 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_ui_test_2.js
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_ui_test_2.js
@@ -6,13 +6,12 @@
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {eventToPromise, waitBeforeNextRender} from '../../../test_util.js';
+import {eventToPromise, isVisible, waitBeforeNextRender} from '../../../test_util.js';
 import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
 import {FakeContactManager} from '../../nearby_share/shared/fake_nearby_contact_manager.js';
 import {FakeNearbyShareSettings} from '../../nearby_share/shared/fake_nearby_share_settings.js';
 
 import {FakeUserActionRecorder} from './fake_user_action_recorder.js';
-import {isVisible} from './test_util.js';
 
 suite('os-settings-ui', () => {
   let ui;
diff --git a/chrome/test/data/webui/settings/chromeos/quick_unlock_authenticate_browsertest_chromeos.js b/chrome/test/data/webui/settings/chromeos/quick_unlock_authenticate_browsertest_chromeos.js
index b0fc98d..4fdff619 100644
--- a/chrome/test/data/webui/settings/chromeos/quick_unlock_authenticate_browsertest_chromeos.js
+++ b/chrome/test/data/webui/settings/chromeos/quick_unlock_authenticate_browsertest_chromeos.js
@@ -9,7 +9,7 @@
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {FakeSettingsPrivate} from 'chrome://test/settings/chromeos/fake_settings_private.js';
 
-import {eventToPromise, waitAfterNextRender, waitBeforeNextRender} from '../../../test_util.js';
+import {eventToPromise, isVisible as testUtilIsVisible, waitAfterNextRender, waitBeforeNextRender} from '../../../test_util.js';
 import {assertEquals, assertFalse, assertNotEquals, assertTrue} from '../../chai_assert.js';
 
 import {FakeQuickUnlockPrivate} from './fake_quick_unlock_private.js';
@@ -25,28 +25,8 @@
  * @param {!Element} element
  */
 function isVisible(element) {
-  while (element) {
-    if (element.offsetWidth <= 0 || element.offsetHeight <= 0 ||
-        element.hidden ||
-        window.getComputedStyle(element).visibility === 'hidden') {
-      return false;
-    }
-
-    element = element.parentElement;
-
-    if (element) {
-      // cr-dialog itself will always be 0x0. It's the inner native <dialog>
-      // that has actual dimensions.
-      // (The same about PIN-KEYBOARD.)
-      if (element.tagName === 'CR-DIALOG') {
-        element = element.getNative();
-      } else if (element.tagName === 'PIN-KEYBOARD') {
-        element = element.$.root;
-      }
-    }
-  }
-
-  return true;
+  return testUtilIsVisible(element) &&
+      window.getComputedStyle(element).visibility !== 'hidden';
 }
 
 /**
diff --git a/chrome/test/data/webui/settings/chromeos/test_util.js b/chrome/test/data/webui/settings/chromeos/test_util.js
deleted file mode 100644
index cb936c7..0000000
--- a/chrome/test/data/webui/settings/chromeos/test_util.js
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2020 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.
-
-/**
- * Returns whether the element both exists and is visible.
- * @param {?Element} element
- * @return {boolean}
- */
-export function isVisible(element) {
-  // offsetWidth and offsetHeight reflect more ways that an element could be
-  // hidden, compared to checking the hidden attribute directly.
-  return !!element && element.getBoundingClientRect().width > 0 &&
-      element.getBoundingClientRect().height > 0;
-}
diff --git a/chromeos/crosapi/mojom/BUILD.gn b/chromeos/crosapi/mojom/BUILD.gn
index a8395b26..a35237e 100644
--- a/chromeos/crosapi/mojom/BUILD.gn
+++ b/chromeos/crosapi/mojom/BUILD.gn
@@ -76,6 +76,7 @@
     "url_handler.mojom",
     "video_capture.mojom",
     "vpn_extension_observer.mojom",
+    "vpn_service.mojom",
     "web_app_service.mojom",
     "web_app_types.mojom",
     "web_page_info.mojom",
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom
index 5fdc66c..c3f0700 100644
--- a/chromeos/crosapi/mojom/crosapi.mojom
+++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -67,6 +67,7 @@
 import "chromeos/crosapi/mojom/timezone.mojom";
 import "chromeos/crosapi/mojom/tts.mojom";
 import "chromeos/crosapi/mojom/url_handler.mojom";
+import "chromeos/crosapi/mojom/vpn_service.mojom";
 import "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom";
 import "chromeos/crosapi/mojom/video_capture.mojom";
 import "chromeos/crosapi/mojom/kiosk_session_service.mojom";
@@ -109,8 +110,8 @@
 // please note the milestone when you added it, to help us reason about
 // compatibility between the client applications and older ash-chrome binaries.
 //
-// Next version: 79
-// Next method id: 82
+// Next version: 80
+// Next method id: 83
 [Stable, Uuid="8b79c34f-2bf8-4499-979a-b17cac522c1e",
  RenamedFrom="crosapi.mojom.AshChromeService"]
 interface Crosapi {
@@ -509,12 +510,18 @@
   // lacros to ash.
   // Added in M96.
   [MinVersion=49] BindKioskSessionService@53(
-    pending_receiver<KioskSessionService> receiver);
+      pending_receiver<KioskSessionService> receiver);
 
   // Binds the chrome app kiosk service. This service is used to install and
   // launch the chrome app inside lacros.
   [MinVersion=73] BindChromeAppKioskService@76(
-    pending_receiver<ChromeAppKioskService> receiver);
+      pending_receiver<ChromeAppKioskService> receiver);
+
+  // Binds the vpn service. This service is used to facilirate
+  // communication between chrome.vpnProvider extension in lacros and the
+  // network services in ash.
+  [MinVersion=79] BindVpnService@82(
+      pending_receiver<VpnService> receiver);
 
   // Binds the web page info factory interface which allows ash to request web
   // page info from Lacros.
diff --git a/chromeos/crosapi/mojom/launcher_search.mojom b/chromeos/crosapi/mojom/launcher_search.mojom
index 42d65ea..0835af4 100644
--- a/chromeos/crosapi/mojom/launcher_search.mojom
+++ b/chromeos/crosapi/mojom/launcher_search.mojom
@@ -157,13 +157,17 @@
   OnSearchResultsReceived@0(SearchStatus status, array<SearchResult>? result);
 };
 
-// Interface to send query from ash to lacros. Implemented in lacros.
+// Interface to send search queries from ash to lacros. Implemented in lacros.
 // Next min method ID: 2
 [Stable, Uuid="c2d77467-b04d-4b10-8f54-de52c3cbe30d"]
 interface SearchController {
   // Sends search queries from ash to lacros. If a search query is called while
   // there is an in-flight search query, the in-flight search query will be
-  // cancelled before the new search query being executed.
+  // cancelled before the new search query is executed.
+  //
+  // Returns the pipe to bind to the implementation of `SearchResultsPublisher`
+  // that should receive the results of this search. Returns a new pipe each
+  // invocation so that each pipe conceptually represents a single search.
   Search@0(mojo_base.mojom.String16 query) =>
       (pending_associated_receiver<SearchResultsPublisher> publisher);
 };
diff --git a/chromeos/crosapi/mojom/vpn_service.mojom b/chromeos/crosapi/mojom/vpn_service.mojom
new file mode 100644
index 0000000..e82d05d
--- /dev/null
+++ b/chromeos/crosapi/mojom/vpn_service.mojom
@@ -0,0 +1,135 @@
+// 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.
+
+module crosapi.mojom;
+
+import "mojo/public/mojom/base/values.mojom";
+
+[Stable]
+struct VpnErrorResponse {
+  string? name@0;
+  string? message@1;
+};
+
+// Adapter that allows packets received by ash to be routed through
+// PepperVpnProviderResourceHostProxy running in lacros.
+// See content/public/browser/pepper_vpn_provider_resource_host_proxy.h for
+// details.
+// Next version: 1
+// Next method id: 2
+[Stable, Uuid="abf3cd5e-a471-40a1-947b-3be9f8519da4"]
+interface PepperVpnProxyObserver {
+  // Invoked when the active Vpn configuration disconnects.
+  // Corresponds to
+  //    PepperVpnProviderResourceHostProxy::SendOnUnbind().
+  OnUnbind@0();
+
+  // Invoked when the active Vpn configuration receives |data| packet.
+  // Corresponds to
+  //    PepperVpnProviderResourceHostProxy::SendOnPacketReceived(...).
+  OnPacketReceived@1(array<uint8> data);
+};
+
+// Listens to events dispatched by VpnServiceForExtension.
+// See
+//   * chrome.vpnProvider.onPlatformMessage
+//   * chrome.vpnProvider.onPacketReceived
+//   * chrome.vpnProvider.onConfigRemoved
+//   * chrome.vpnProvider.onUIEvent
+// Next version: 1
+// Next method id: 1
+[Stable, Uuid="76ed414e-1710-4b5c-895d-181714376511"]
+interface EventObserverForExtension {
+  // Dispatches UI_EVENT_SHOWADDDIALOG.
+  OnAddDialog@0();
+
+  // Dispatches UI_EVENT_SHOWCONFIGUREDIALOG.
+  OnConfigureDialog@1(string configuration_name);
+
+  // Dispatches OnConfigRemoved event.
+  OnConfigRemoved@2(string configuration_name);
+
+  // Dispatches OnPlatformMessage event.
+  OnPlatformMessage@3(string configuration_name,
+      int32 platform_message, string? error);
+
+  // Dispatches OnPacketReceived event.
+  OnPacketReceived@4(array<uint8> data);
+};
+
+// VpnServiceForExtension manages VPN configurations for a specific extension.
+// Next version: 1
+// Next method id: 8
+[Stable, Uuid="6743d9c7-e6c1-4f12-8f6c-571264044dea"]
+interface VpnServiceForExtension {
+  // Creates a new VPN configuration with |configuration_name| as the name and
+  // attaches it to the extension.
+  // See chrome.vpnProvider.createConfiguration(...)
+  CreateConfiguration@0(string configuration_name)
+      => (VpnErrorResponse? error);
+
+  // Destroys the VPN configuration with |configuration_name| after verifying
+  // that it belongs to the extension.
+  // See chrome.vpnProvider.destroyConfiguration(...)
+  DestroyConfiguration@1(string configuration_name)
+      => (VpnErrorResponse? error);
+
+  // Set |parameters| for the active VPN configuration after verifying that it
+  // belongs to the extension.
+  // See chrome.vpnProvider.setParameters(...)
+  // We use mojo_base.mojom.DictionaryValue as the type because:
+  // * The shill counterpart is stable and expects base::Value with type=dict.
+  // * Both the supplier and consumer of this information uses a type
+  //   interchangeable with mojo_base.mojom.DictionaryValue. While we could add
+  //   a translation layer to a strongly typed mojom struct, this adds an
+  //   overhead and the potential for errors with no benefit.
+  SetParameters@2(mojo_base.mojom.DictionaryValue parameters)
+      => (VpnErrorResponse? error);
+
+  // Sends an IP packet contained in |data| to the active VPN configuration
+  // after verifying that it belongs to the extension.
+  // See chrome.vpnProvider.sendPacket(...)
+  SendPacket@3(array<uint8> data)
+      => (VpnErrorResponse? error);
+
+  // Notifies new connection state to the active VPN configuration after
+  // verifying that it belongs to the extension.
+  // See chrome.vpnProvider.notifyConnectionStateChanged(...)
+  NotifyConnectionStateChanged@4(bool connection_success)
+      => (VpnErrorResponse? error);
+
+  // Binds |pepper_vpn_proxy_observer| to the active configuration if it belongs
+  // to the extension and has name equal to
+  // |configuration_name|. On success all packets will be routed through
+  // Pepper API.
+  BindPepperVpnProxyObserver@5(string configuration_name,
+      pending_remote<PepperVpnProxyObserver> pepper_vpn_proxy_observer)
+      => (VpnErrorResponse? error);
+
+  // Informs all connected clients that an ADD_DIALOG event should be dispatched
+  // to the extension.
+  DispatchAddDialogEvent@6();
+
+  // Informs all connected clients that a CONFIGURE_DIALOG event should be
+  // dispatched to the extension.
+  DispatchConfigureDialogEvent@7(string configuration_name);
+};
+
+// VpnService manages VPN connections on the ash side.
+// Next version: 1
+// Next method id: 2
+[Stable, Uuid="52659296-1b2a-4b8d-a219-0ca57710fe03"]
+interface VpnService {
+  // Registers a service for the given extension and allows ash to send events
+  // via |observer|.
+  RegisterVpnServiceForExtension@0(string extension_id,
+      pending_receiver<VpnServiceForExtension> receiver,
+      pending_remote<EventObserverForExtension> observer);
+
+  // Updates current Vpn connection state to FAILURE if the active configuration
+  // belongs to extension with id |extension_id|. If |destroy_configurations| is
+  // true, also destroys all configurations owned by this extension.
+  MaybeFailActiveConnectionAndDestroyConfigurations@1(string extension_id,
+      bool destroy_configurations);
+};
\ No newline at end of file
diff --git a/chromeos/network/client_cert_util.cc b/chromeos/network/client_cert_util.cc
index e8ae7f7..5b01f73 100644
--- a/chromeos/network/client_cert_util.cc
+++ b/chromeos/network/client_cert_util.cc
@@ -10,6 +10,7 @@
 
 #include <list>
 
+#include "base/check.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
@@ -21,6 +22,7 @@
 #include "net/cert/scoped_nss_types.h"
 #include "net/cert/x509_certificate.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 namespace chromeos {
@@ -280,62 +282,154 @@
 
 ClientCertConfig::~ClientCertConfig() = default;
 
+ResolvedCert::ResolvedCert(
+    Status status,
+    int slot_id,
+    const std::string& pkcs11_id,
+    base::flat_map<std::string, std::string> variable_expansions)
+    : status_(status),
+      slot_id_(slot_id),
+      pkcs11_id_(pkcs11_id),
+      variable_expansions_(variable_expansions) {}
+
+ResolvedCert::~ResolvedCert() = default;
+
+ResolvedCert::ResolvedCert(ResolvedCert&& other) = default;
+
+ResolvedCert& ResolvedCert::operator=(ResolvedCert&& other) = default;
+
+// static
+ResolvedCert ResolvedCert::NotKnownYet() {
+  return ResolvedCert(Status::kNotKnownYet, -1, std::string(), {});
+}
+
+// static
+ResolvedCert ResolvedCert::NothingMatched() {
+  return ResolvedCert(Status::kNothingMatched, -1, std::string(), {});
+}
+
+// static
+ResolvedCert ResolvedCert::CertMatched(
+    int slot_id,
+    const std::string& pkcs11_id,
+    base::flat_map<std::string, std::string> variable_expansions) {
+  return ResolvedCert(Status::kCertMatched, slot_id, pkcs11_id,
+                      std::move(variable_expansions));
+}
+
+ResolvedCert::Status ResolvedCert::status() const {
+  return status_;
+}
+
+int ResolvedCert::slot_id() const {
+  DCHECK_EQ(status(), Status::kCertMatched);
+  return slot_id_;
+}
+
+const std::string& ResolvedCert::pkcs11_id() const {
+  DCHECK_EQ(status(), Status::kCertMatched);
+  return pkcs11_id_;
+}
+
+const base::flat_map<std::string, std::string>
+ResolvedCert::variable_expansions() const {
+  DCHECK_EQ(status(), Status::kCertMatched);
+  return variable_expansions_;
+}
+
+bool operator==(const ResolvedCert& lhs, const ResolvedCert& rhs) {
+  return lhs.status() == rhs.status() && lhs.slot_id() == rhs.slot_id() &&
+         lhs.pkcs11_id() == rhs.pkcs11_id() &&
+         lhs.variable_expansions() == rhs.variable_expansions();
+}
+
+// Uses a template type to easily implement a const and a non-const version.
+template <typename DictType>
+DictType* GetOncClientCertConfigDict(DictType& network_config,
+                                     ConfigType* out_config_type) {
+  DictType* wifi = network_config.FindDict(::onc::network_config::kWiFi);
+  if (wifi) {
+    DictType* eap = wifi->FindDict(::onc::wifi::kEAP);
+    if (!eap)
+      return nullptr;
+    if (out_config_type)
+      *out_config_type = ConfigType::kEap;
+    return eap;
+  }
+
+  DictType* ethernet =
+      network_config.FindDict(::onc::network_config::kEthernet);
+  if (ethernet) {
+    DictType* eap = ethernet->FindDict(::onc::wifi::kEAP);
+    if (!eap)
+      return nullptr;
+    if (out_config_type)
+      *out_config_type = ConfigType::kEap;
+    return eap;
+  }
+
+  DictType* vpn = network_config.FindDict(::onc::network_config::kVPN);
+  if (vpn) {
+    DictType* openvpn = vpn->FindDict(::onc::vpn::kOpenVPN);
+    DictType* ipsec = vpn->FindDict(::onc::vpn::kIPsec);
+    DictType* l2tp = vpn->FindDict(::onc::vpn::kL2TP);
+    if (openvpn) {
+      if (out_config_type)
+        *out_config_type = ConfigType::kOpenVpn;
+      return openvpn;
+    }
+    if (ipsec) {
+      // Currently we support two kinds of IPsec-based VPN:
+      // - L2TP/IPsec: IKE version is 1 and |l2tp| is set;
+      // - IKEv2: IKE version is 2 and |l2tp| is not set.
+      // Thus we only use |l2tp| to distinguish between these two cases.
+      if (out_config_type)
+        *out_config_type = l2tp ? ConfigType::kL2tpIpsec : ConfigType::kIkev2;
+      return ipsec;
+    }
+  }
+
+  return nullptr;
+}
+
 void OncToClientCertConfig(::onc::ONCSource onc_source,
                            const base::Value::Dict& network_config,
                            ClientCertConfig* cert_config) {
   *cert_config = ClientCertConfig();
 
-  const base::Value::Dict* dict_with_client_cert = nullptr;
-
-  const base::Value::Dict* wifi =
-      network_config.FindDict(::onc::network_config::kWiFi);
-  if (wifi) {
-    const base::Value::Dict* eap = wifi->FindDict(::onc::wifi::kEAP);
-    if (!eap)
-      return;
-
-    dict_with_client_cert = eap;
-    cert_config->location = ConfigType::kEap;
-  }
-
-  const base::Value::Dict* vpn =
-      network_config.FindDict(::onc::network_config::kVPN);
-  if (vpn) {
-    const base::Value::Dict* openvpn = vpn->FindDict(::onc::vpn::kOpenVPN);
-    const base::Value::Dict* ipsec = vpn->FindDict(::onc::vpn::kIPsec);
-    const base::Value::Dict* l2tp = vpn->FindDict(::onc::vpn::kL2TP);
-    if (openvpn) {
-      dict_with_client_cert = openvpn;
-      cert_config->location = ConfigType::kOpenVpn;
-    } else if (ipsec) {
-      dict_with_client_cert = ipsec;
-      // Currently we support two kinds of IPsec-based VPN:
-      // - L2TP/IPsec: IKE version is 1 and |l2tp| is set;
-      // - IKEv2: IKE version is 2 and |l2tp| is not set.
-      // Thus we only use |l2tp| to distinguish between these two cases.
-      cert_config->location =
-          l2tp ? ConfigType::kL2tpIpsec : ConfigType::kIkev2;
-    } else {
-      return;
-    }
-  }
-
-  const base::Value::Dict* ethernet =
-      network_config.FindDict(::onc::network_config::kEthernet);
-  if (ethernet) {
-    const base::Value::Dict* eap = ethernet->FindDict(::onc::wifi::kEAP);
-    if (!eap)
-      return;
-    dict_with_client_cert = eap;
-    cert_config->location = ConfigType::kEap;
-  }
-
+  const base::Value::Dict* dict_with_client_cert =
+      GetOncClientCertConfigDict(network_config, &(cert_config->location));
   if (dict_with_client_cert) {
     GetClientCertTypeAndDescriptor(onc_source, *dict_with_client_cert,
                                    cert_config);
   }
 }
 
+void SetResolvedCertInOnc(const ResolvedCert& resolved_cert,
+                          base::Value& network_config) {
+  if (resolved_cert.status() == ResolvedCert::Status::kNotKnownYet)
+    return;
+
+  base::Value::Dict* dict_with_client_cert = GetOncClientCertConfigDict(
+      network_config.GetDict(), /*out_config_type=*/nullptr);
+  if (!dict_with_client_cert)
+    return;
+  dict_with_client_cert->Set(::onc::client_cert::kClientCertType,
+                             base::Value(::onc::client_cert::kPKCS11Id));
+  if (resolved_cert.status() == ResolvedCert::Status::kNothingMatched) {
+    // Empty PKCS11Id means that no certificate has been selected and it
+    // should be cleared in shill.
+    dict_with_client_cert->Set(::onc::client_cert::kClientCertPKCS11Id,
+                               std::string());
+  } else {
+    dict_with_client_cert->Set(
+        ::onc::client_cert::kClientCertPKCS11Id,
+        base::Value(base::StringPrintf("%i:%s", resolved_cert.slot_id(),
+                                       resolved_cert.pkcs11_id().c_str())));
+  }
+  dict_with_client_cert->Remove(::onc::client_cert::kClientCertPattern);
+}
+
 }  // namespace client_cert
 
 }  // namespace chromeos
diff --git a/chromeos/network/client_cert_util.h b/chromeos/network/client_cert_util.h
index e0d6968..c9ac9c4 100644
--- a/chromeos/network/client_cert_util.h
+++ b/chromeos/network/client_cert_util.h
@@ -9,9 +9,11 @@
 #include <vector>
 
 #include "base/component_export.h"
+#include "base/containers/flat_map.h"
 #include "base/memory/ref_counted.h"
 #include "chromeos/ash/components/network/onc/onc_certificate_pattern.h"
 #include "components/onc/onc_constants.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
 
 namespace base {
 class Value;
@@ -67,6 +69,66 @@
   ::onc::ONCSource onc_source;
 };
 
+// Identifies a resolved client certificate (e.g. after matching existing client
+// certificates against an ONC ClientCertPattern).
+// Can also signify that no certificate has been resolved yet - see the Status
+// enum.
+class COMPONENT_EXPORT(CHROMEOS_NETWORK) ResolvedCert {
+ public:
+  ~ResolvedCert();
+  ResolvedCert(ResolvedCert&& other);
+  ResolvedCert& operator=(ResolvedCert&& other);
+
+  static ResolvedCert NotKnownYet();
+  static ResolvedCert NothingMatched();
+  static ResolvedCert CertMatched(
+      int slot_id,
+      const std::string& pkcs11_id,
+      base::flat_map<std::string, std::string> variable_expansions);
+
+  enum class Status {
+    // It is not known yet if a matching client certificate exists.
+    kNotKnownYet,
+    // No matching client certificate has been found.
+    kNothingMatched,
+    // A matching client certificate has been found.
+    kCertMatched
+  };
+
+  Status status() const;
+
+  // The PKCS#11 slot id the resolved certificate is stored on.
+  // Only callable if `status()` is `Status::kCertMatched`.
+  int slot_id() const;
+  // The PKCS#11 object id of the resolved certificiate.
+  // Only callable if `status()` is `Status::kCertMatched`.
+  const std::string& pkcs11_id() const;
+  // ONC Variable expansions extracted from the resolved certificate.
+  // Only callable if `status()` is `Status::kCertMatched`.
+  const base::flat_map<std::string, std::string> variable_expansions() const;
+
+ private:
+  ResolvedCert(Status status,
+               int slot_id,
+               const std::string& pkcs11_id,
+               base::flat_map<std::string, std::string> variable_expansions);
+  // The status of certificate resolution.
+  Status status_;
+
+  // The PKCS11 slot on which the certificate is stored.
+  // Only relevant if `status` is `Status::kCertMatched`.
+  int slot_id_;
+  // The PKCS11 object id of the certificate and private key.
+  // Only relevant if `status` is `Status::kCertMatched`.
+  std::string pkcs11_id_;
+  // ONC Variable expansions generated from the certificate's contents.
+  // Only relevant if `status` is `Status::kCertMatched`.
+  base::flat_map<std::string, std::string> variable_expansions_;
+};
+
+COMPONENT_EXPORT(CHROMEOS_NETWORK)
+bool operator==(const ResolvedCert& lhs, const ResolvedCert& rhs);
+
 // Returns the PKCS11 and slot ID of |cert_id|, which is expected to be a
 // value of the Shill property |kEapCertIdProperty| or |kEapKeyIdProperty|,
 // either of format "<pkcs11_id>" or "<slot_id>:<pkcs11_id>".
@@ -109,6 +171,16 @@
                            const base::Value::Dict& network_config,
                            ClientCertConfig* cert_config);
 
+// Sets the client certificate described by `network_config` as the selected
+// client certificate of `network_config`.
+// If `resolved_cert` has `Status::kNotKnownYet`, will not modify
+// `network_config`. If `resolved_cert` is `Status::kNoCert`, will set an empty
+// PKCS11Id. Otherwise will configure `network_config` to use the PKCS11Id from
+// `resolved_cert`.
+COMPONENT_EXPORT(CHROMEOS_NETWORK)
+void SetResolvedCertInOnc(const ResolvedCert& resolved_cert,
+                          base::Value& network_config);
+
 }  // namespace client_cert
 
 }  // namespace chromeos
diff --git a/chromeos/network/client_cert_util_unittest.cc b/chromeos/network/client_cert_util_unittest.cc
index badfcac..6117e08e 100644
--- a/chromeos/network/client_cert_util_unittest.cc
+++ b/chromeos/network/client_cert_util_unittest.cc
@@ -343,6 +343,7 @@
 TEST(ClientCertUtilTest, OncToClientCertConfig_Wifi_Pattern) {
   base::Value network_config = base::test::ParseJson(
       R"({
+         "Type": "WiFi",
          "WiFi": {
            "EAP": {
              "Identity": "identity_value",
@@ -370,6 +371,7 @@
 TEST(ClientCertUtilTest, OncToClientCertConfig_Wifi_Ref) {
   base::Value network_config = base::test::ParseJson(
       R"({
+         "Type": "WiFi",
          "WiFi": {
            "EAP": {
              "Identity": "identity_value",
@@ -393,6 +395,7 @@
 TEST(ClientCertUtilTest, OncToClientCertConfig_Wifi_ProvisioningProfileId) {
   base::Value network_config = base::test::ParseJson(
       R"({
+         "Type": "WiFi",
          "WiFi": {
            "EAP": {
              "Identity": "identity_value",
@@ -420,6 +423,7 @@
 TEST(ClientCertUtilTest, OncToClientCertConfig_Ethernet_ProvisioningProfileId) {
   base::Value network_config = base::test::ParseJson(
       R"({
+         "Type": "Ethernet",
          "Ethernet": {
            "EAP": {
              "Identity": "identity_value",
@@ -444,6 +448,7 @@
 TEST(ClientCertUtilTest, OncToClientCertConfig_OpenVPN_ProvisioningProfileId) {
   base::Value network_config = base::test::ParseJson(
       R"({
+         "Type": "VPN",
          "VPN": {
            "OpenVPN": {
              "Identity": "identity_value",
@@ -469,6 +474,7 @@
      OncToClientCertConfig_L2TPIPsec_ProvisioningProfileId) {
   base::Value network_config = base::test::ParseJson(
       R"({
+         "Type": "VPN",
          "VPN": {
            "L2TP": { },
            "IPsec": {
@@ -494,6 +500,7 @@
 TEST(ClientCertUtilTest, OncToClientCertConfig_IKEv2_ProvisioningProfileId) {
   base::Value network_config = base::test::ParseJson(
       R"({
+         "Type": "VPN",
          "VPN": {
            "IPsec": {
              "Identity": "identity_value",
@@ -515,4 +522,180 @@
   EXPECT_EQ(cert_config.onc_source, ::onc::ONC_SOURCE_USER_POLICY);
 }
 
+TEST(ClientCertUtilTest, SetResolvedCertForEthernetEap) {
+  base::Value network_config = base::test::ParseJson(
+      R"({
+         "Type": "Ethernet",
+         "Ethernet": {
+           "Authentication": "8021X",
+           "EAP": {
+             "ClientCertType": "Pattern",
+             "ClientCertPattern": {
+               "Subject": {
+                 "CommonName": "Test"
+               }
+             }
+           }
+         }
+       })");
+  SetResolvedCertInOnc(ResolvedCert::CertMatched(1, "pkcs11_id", {}),
+                       network_config);
+  EXPECT_THAT(network_config, base::test::IsJson(
+                                  R"({
+         "Type": "Ethernet",
+         "Ethernet": {
+           "Authentication": "8021X",
+           "EAP": {
+             "ClientCertType": "PKCS11Id",
+             "ClientCertPKCS11Id": "1:pkcs11_id"
+           }
+         }
+       })"));
+}
+
+TEST(ClientCertUtilTest, SetResolvedCertForWifiEap) {
+  base::Value network_config = base::test::ParseJson(
+      R"({
+         "Type": "WiFi",
+         "WiFi": {
+           "Security": "WPA-EAP",
+           "EAP": {
+             "ClientCertType": "Pattern",
+             "ClientCertPattern": {
+               "Subject": {
+                 "CommonName": "Test"
+               }
+             }
+           }
+         }
+       })");
+  SetResolvedCertInOnc(ResolvedCert::CertMatched(1, "pkcs11_id", {}),
+                       network_config);
+  EXPECT_THAT(network_config, base::test::IsJson(
+                                  R"({
+         "Type": "WiFi",
+         "WiFi": {
+           "Security": "WPA-EAP",
+           "EAP": {
+             "ClientCertType": "PKCS11Id",
+             "ClientCertPKCS11Id": "1:pkcs11_id"
+           }
+         }
+       })"));
+}
+
+TEST(ClientCertUtilTest, SetResolvedCertForOpenVpn) {
+  base::Value network_config = base::test::ParseJson(
+      R"({
+         "Type": "VPN",
+         "VPN": {
+           "Type": "OpenVPN",
+           "OpenVPN": {
+             "ClientCertType": "Pattern",
+             "ClientCertPattern": {
+               "Subject": {
+                 "CommonName": "Test"
+               }
+             }
+           }
+         }
+       })");
+  SetResolvedCertInOnc(ResolvedCert::CertMatched(1, "pkcs11_id", {}),
+                       network_config);
+  EXPECT_THAT(network_config, base::test::IsJson(
+                                  R"({
+         "Type": "VPN",
+         "VPN": {
+           "Type": "OpenVPN",
+           "OpenVPN": {
+             "ClientCertType": "PKCS11Id",
+             "ClientCertPKCS11Id": "1:pkcs11_id"
+           }
+         }
+       })"));
+}
+
+TEST(ClientCertUtilTest, SetResolvedCertForLt2pIpsecVpn) {
+  base::Value network_config = base::test::ParseJson(
+      R"({
+         "Type": "VPN",
+         "VPN": {
+           "Type": "L2TP-IPsec",
+           "IPsec": {
+             "ClientCertType": "Pattern",
+             "ClientCertPattern": {
+               "Subject": {
+                 "CommonName": "Test"
+               }
+             }
+           }
+         }
+       })");
+  SetResolvedCertInOnc(ResolvedCert::CertMatched(1, "pkcs11_id", {}),
+                       network_config);
+  EXPECT_THAT(network_config, base::test::IsJson(
+                                  R"({
+         "Type": "VPN",
+         "VPN": {
+           "Type": "L2TP-IPsec",
+           "IPsec": {
+             "ClientCertType": "PKCS11Id",
+             "ClientCertPKCS11Id": "1:pkcs11_id"
+           }
+         }
+       })"));
+}
+
+// Tests that the NotKnownYet state doesn't change the ONC value.
+TEST(ClientCertUtilTest, NotKnownYet) {
+  base::Value network_config = base::test::ParseJson(
+      R"({
+         "Type": "Ethernet",
+         "Ethernet": {
+           "Authentication": "8021X",
+           "EAP": {
+             "ClientCertType": "Pattern",
+             "ClientCertPattern": {
+               "Subject": {
+                 "CommonName": "Test"
+               }
+             }
+           }
+         }
+       })");
+  base::Value network_config_orig = network_config.Clone();
+  SetResolvedCertInOnc(ResolvedCert::NotKnownYet(), network_config);
+  EXPECT_THAT(network_config, base::test::IsJson(network_config_orig));
+}
+
+TEST(ClientCertUtilTest, NoCert) {
+  base::Value network_config = base::test::ParseJson(
+      R"({
+         "Type": "Ethernet",
+         "Ethernet": {
+           "Authentication": "8021X",
+           "EAP": {
+             "ClientCertType": "Pattern",
+             "ClientCertPattern": {
+               "Subject": {
+                 "CommonName": "Test"
+               }
+             }
+           }
+         }
+       })");
+  SetResolvedCertInOnc(ResolvedCert::NothingMatched(), network_config);
+  EXPECT_THAT(network_config, base::test::IsJson(
+                                  R"({
+         "Type": "Ethernet",
+         "Ethernet": {
+           "Authentication": "8021X",
+           "EAP": {
+             "ClientCertType": "PKCS11Id",
+             "ClientCertPKCS11Id": ""
+           }
+         }
+       })"));
+}
+
 }  // namespace chromeos::client_cert
diff --git a/chromeos/printing/ppd_metadata_parser.cc b/chromeos/printing/ppd_metadata_parser.cc
index e14fb2f3..e8f632fb 100644
--- a/chromeos/printing/ppd_metadata_parser.cc
+++ b/chromeos/printing/ppd_metadata_parser.cc
@@ -43,7 +43,7 @@
   bool unnested_is_empty = true;
   switch (target_type) {
     case base::Value::Type::LIST:
-      unnested_is_empty = unnested->GetListDeprecated().empty();
+      unnested_is_empty = unnested->GetList().empty();
       break;
     case base::Value::Type::DICTIONARY:
       unnested_is_empty = unnested->DictEmpty();
@@ -138,13 +138,12 @@
     return absl::nullopt;
   }
   const base::Value* const ppd_metadata_list = value.FindListKey("ppdMetadata");
-  if (!ppd_metadata_list ||
-      ppd_metadata_list->GetListDeprecated().size() == 0) {
+  if (!ppd_metadata_list || ppd_metadata_list->GetList().empty()) {
     return absl::nullopt;
   }
 
   ParsedIndexValues parsed_index_values;
-  for (const base::Value& v : ppd_metadata_list->GetListDeprecated()) {
+  for (const base::Value& v : ppd_metadata_list->GetList()) {
     absl::optional<ParsedIndexLeaf> parsed_index_leaf = ParsedIndexLeafFrom(v);
     if (parsed_index_leaf.has_value()) {
       parsed_index_values.values.push_back(parsed_index_leaf.value());
@@ -189,7 +188,7 @@
   }
 
   std::vector<std::string> locales;
-  for (const auto& iter : as_value.value().GetListDeprecated()) {
+  for (const auto& iter : as_value.value().GetList()) {
     if (!iter.is_string())
       continue;
     locales.push_back(iter.GetString());
@@ -281,7 +280,7 @@
   }
 
   ParsedUsbVendorIdMap usb_vendor_ids;
-  for (const auto& usb_vendor_description : as_value->GetListDeprecated()) {
+  for (const auto& usb_vendor_description : as_value->GetList()) {
     if (!usb_vendor_description.is_dict()) {
       continue;
     }
@@ -310,7 +309,7 @@
   }
 
   ParsedPrinters printers;
-  for (const auto& printer_value : as_value->GetListDeprecated()) {
+  for (const auto& printer_value : as_value->GetList()) {
     if (!printer_value.is_dict()) {
       continue;
     }
diff --git a/chromeos/printing/printer_translator_unittest.cc b/chromeos/printing/printer_translator_unittest.cc
index 0cf8f1d..c3795763 100644
--- a/chromeos/printing/printer_translator_unittest.cc
+++ b/chromeos/printing/printer_translator_unittest.cc
@@ -331,9 +331,9 @@
 
   const base::Value* status_reasons =
       printer_status_dict.FindListPath("statusReasons");
-  EXPECT_EQ(1u, status_reasons->GetListDeprecated().size());
+  EXPECT_EQ(1u, status_reasons->GetList().size());
 
-  for (const base::Value& status_reason : status_reasons->GetListDeprecated()) {
+  for (const base::Value& status_reason : status_reasons->GetList()) {
     EXPECT_EQ(static_cast<int>(CupsPrinterStatusReason::Reason::kDoorOpen),
               *status_reason.FindIntPath("reason"));
     EXPECT_EQ(static_cast<int>(CupsPrinterStatusReason::Severity::kError),
@@ -360,8 +360,8 @@
   const base::Value* status_reasons =
       printer_status_dict.FindListPath("statusReasons");
 
-  auto status_reasons_list = status_reasons->GetListDeprecated();
-  EXPECT_EQ(2u, status_reasons_list.size());
+  const auto& status_reasons_list = status_reasons->GetList();
+  ASSERT_EQ(2u, status_reasons_list.size());
   EXPECT_EQ(static_cast<int>(CupsPrinterStatusReason::Reason::kLowOnPaper),
             status_reasons_list[0].FindIntPath("reason"));
   EXPECT_EQ(static_cast<int>(CupsPrinterStatusReason::Severity::kWarning),
diff --git a/chromeos/services/assistant/public/cpp/BUILD.gn b/chromeos/services/assistant/public/cpp/BUILD.gn
index 97d613c..8480fb2 100644
--- a/chromeos/services/assistant/public/cpp/BUILD.gn
+++ b/chromeos/services/assistant/public/cpp/BUILD.gn
@@ -48,8 +48,4 @@
     "//chromeos/ash/components/assistant:buildflags",
     "//components/prefs",
   ]
-
-  if (enable_cros_libassistant) {
-    deps += [ "//chromeos/assistant/internal:buildflags" ]
-  }
 }
diff --git a/chromeos/services/assistant/public/cpp/features.cc b/chromeos/services/assistant/public/cpp/features.cc
index e65ca39..16a779c8 100644
--- a/chromeos/services/assistant/public/cpp/features.cc
+++ b/chromeos/services/assistant/public/cpp/features.cc
@@ -6,12 +6,6 @@
 
 #include "ash/constants/ash_features.h"
 #include "base/feature_list.h"
-#include "build/buildflag.h"
-#include "chromeos/ash/components/assistant/buildflags.h"
-
-#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
-#include "chromeos/assistant/internal/buildflags.h"
-#endif  // BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
 
 namespace chromeos {
 namespace assistant {
@@ -102,16 +96,7 @@
 }
 
 bool IsLibAssistantV2Enabled() {
-// Enforce V2 when using the prebuilt library.
-#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
-#if BUILDFLAG(IS_PREBUILT_LIBASSISTANT)
-  return true;
-#else
   return base::FeatureList::IsEnabled(kEnableLibAssistantV2);
-#endif  // BUILDFLAG(IS_PREBUILT_LIBASSISTANT)
-#else
-  return false;
-#endif  // BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
 }
 
 }  // namespace features
diff --git a/chromeos/services/libassistant/BUILD.gn b/chromeos/services/libassistant/BUILD.gn
index 2f20d8d..2ac4e0e 100644
--- a/chromeos/services/libassistant/BUILD.gn
+++ b/chromeos/services/libassistant/BUILD.gn
@@ -128,7 +128,6 @@
     "//chromeos/ash/components/assistant:buildflags",
     "//chromeos/ash/resources",
     "//chromeos/assistant/internal",
-    "//chromeos/assistant/internal:buildflags",
     "//chromeos/assistant/internal:libassistant",
     "//chromeos/assistant/internal:libassistant_shared_headers",
     "//chromeos/assistant/internal:support",
diff --git a/chromeos/services/libassistant/chromium_api_delegate.cc b/chromeos/services/libassistant/chromium_api_delegate.cc
index 699c44a..eb7affe 100644
--- a/chromeos/services/libassistant/chromium_api_delegate.cc
+++ b/chromeos/services/libassistant/chromium_api_delegate.cc
@@ -21,12 +21,10 @@
 
 ChromiumApiDelegate::~ChromiumApiDelegate() = default;
 
-#if !BUILDFLAG(IS_PREBUILT_LIBASSISTANT)
 assistant_client::HttpConnectionFactory*
 ChromiumApiDelegate::GetHttpConnectionFactory() {
   return &http_connection_factory_;
 }
-#endif  // !BUILDFLAG(IS_PREBUILT_LIBASSISTANT)
 
 }  // namespace libassistant
 }  // namespace chromeos
diff --git a/chromeos/services/libassistant/chromium_api_delegate.h b/chromeos/services/libassistant/chromium_api_delegate.h
index d0ddcb1..a5e7ee2e 100644
--- a/chromeos/services/libassistant/chromium_api_delegate.h
+++ b/chromeos/services/libassistant/chromium_api_delegate.h
@@ -21,24 +21,6 @@
 
 class ChromiumHttpConnectionFactory;
 
-// TODO(b/195985225): `ChromeOSApiDelegate` is not supported in the prebuilt
-// library.
-#if BUILDFLAG(IS_PREBUILT_LIBASSISTANT)
-class ChromiumApiDelegate {
- public:
-  explicit ChromiumApiDelegate(
-      std::unique_ptr<network::PendingSharedURLLoaderFactory>
-          pending_url_loader_factory);
-
-  ChromiumApiDelegate(const ChromiumApiDelegate&) = delete;
-  ChromiumApiDelegate& operator=(const ChromiumApiDelegate&) = delete;
-
-  ~ChromiumApiDelegate();
-
- private:
-  ChromiumHttpConnectionFactory http_connection_factory_;
-};
-#else
 class ChromiumApiDelegate : public assistant_client::ChromeOSApiDelegate {
  public:
   explicit ChromiumApiDelegate(
@@ -58,7 +40,6 @@
  private:
   ChromiumHttpConnectionFactory http_connection_factory_;
 };
-#endif  // BUILDFLAG(IS_PREBUILT_LIBASSISTANT)
 
 }  // namespace libassistant
 }  // namespace chromeos
diff --git a/chromeos/services/libassistant/conversation_state_listener_impl.cc b/chromeos/services/libassistant/conversation_state_listener_impl.cc
index 0f8daa18..d5c9b058 100644
--- a/chromeos/services/libassistant/conversation_state_listener_impl.cc
+++ b/chromeos/services/libassistant/conversation_state_listener_impl.cc
@@ -122,11 +122,6 @@
     case Resolution::LONGFORM_KEEP_MIC_OPEN:
       NOTREACHED();
       return;
-#if BUILDFLAG(IS_PREBUILT_LIBASSISTANT)
-    case Resolution::BLUE_STEEL_ON_DEVICE_REJECTION:
-      NOTREACHED();
-      return;
-#endif  // BUILDFLAG(IS_PREBUILT_LIBASSISTANT)
   }
 }
 
diff --git a/chromeos/services/libassistant/grpc/assistant_client_v1.cc b/chromeos/services/libassistant/grpc/assistant_client_v1.cc
index a757da8..79d9f40 100644
--- a/chromeos/services/libassistant/grpc/assistant_client_v1.cc
+++ b/chromeos/services/libassistant/grpc/assistant_client_v1.cc
@@ -348,11 +348,9 @@
 
 void AssistantClientV1::SetChromeOSApiDelegate(
     assistant_client::ChromeOSApiDelegate* delegate) {
-#if !BUILDFLAG(IS_PREBUILT_LIBASSISTANT)
   assistant_manager_internal()
       ->GetFuchsiaApiHelperOrDie()
       ->SetChromeOSApiDelegate(delegate);
-#endif  // !BUILDFLAG(IS_PREBUILT_LIBASSISTANT)
 }
 
 bool AssistantClientV1::StartGrpcServices() {
diff --git a/chromeos/services/libassistant/service_controller.cc b/chromeos/services/libassistant/service_controller.cc
index c05fc10d..6dab85a2 100644
--- a/chromeos/services/libassistant/service_controller.cc
+++ b/chromeos/services/libassistant/service_controller.cc
@@ -120,7 +120,10 @@
     return;
   }
 
-  libassistant_factory_.LoadLibassistantLibraryFromDlc(config->dlc_path);
+  // Currently only V1 library is uploaded to DLC.
+  if (!chromeos::assistant::features::IsLibAssistantV2Enabled()) {
+    libassistant_factory_.LoadLibassistantLibraryFromDlc(config->dlc_path);
+  }
 
   auto assistant_manager = libassistant_factory_.CreateAssistantManager(
       ToLibassistantConfig(*config));
@@ -321,9 +324,9 @@
     mojo::PendingRemote<network::mojom::URLLoaderFactory>
         url_loader_factory_remote) {
   CreateChromiumApiDelegate(std::move(url_loader_factory_remote));
-#if !BUILDFLAG(IS_PREBUILT_LIBASSISTANT)
-  assistant_client_->SetChromeOSApiDelegate(chromium_api_delegate_.get());
-#endif  // !BUILDFLAG(IS_PREBUILT_LIBASSISTANT)
+  if (!chromeos::assistant::features::IsLibAssistantV2Enabled()) {
+    assistant_client_->SetChromeOSApiDelegate(chromium_api_delegate_.get());
+  }
 }
 
 void ServiceController::CreateChromiumApiDelegate(
diff --git a/chromeos/strings/chromeos_strings_am.xtb b/chromeos/strings/chromeos_strings_am.xtb
index 1978f95..f29abd1 100644
--- a/chromeos/strings/chromeos_strings_am.xtb
+++ b/chromeos/strings/chromeos_strings_am.xtb
@@ -234,6 +234,7 @@
 <translation id="315738237743207937">ተያዥ መግቢያ ተገኝቷል</translation>
 <translation id="3170673040743561620">ሰነድዎን በቃኚው ላይ ያስቀምጡት</translation>
 <translation id="3188257591659621405">የእኔ ፋይሎች</translation>
+<translation id="319101249942218879">የአምሳያ ምስል ተለውጧል</translation>
 <translation id="3192947282887913208">የድምጽ ፋይሎች</translation>
 <translation id="3199982728237701504">ሰነድ መጋቢ (ባለሁለት ጎን)</translation>
 <translation id="320091191259649613">ከዝማኔው በኋላ አሁንም ችግሩን ካዩት ክፍለ-አካሉ አዲስ ብቁ የሆነ እና እስካሁን ወደ የውሂብ ጎታ ያልታከለ ሊሆን ይችላል።</translation>
diff --git a/chromeos/strings/chromeos_strings_bn.xtb b/chromeos/strings/chromeos_strings_bn.xtb
index 40a2bfd..e759d82f 100644
--- a/chromeos/strings/chromeos_strings_bn.xtb
+++ b/chromeos/strings/chromeos_strings_bn.xtb
@@ -86,6 +86,7 @@
 <translation id="1645954272419197032">ডিভাইসের তথ্য নিশ্চিত করুন</translation>
 <translation id="1662989795263954667">বন্ধ হয়ে গেছে - প্রিন্টারে কালি ফুরিয়ে গেছে</translation>
 <translation id="1668469839109562275">বিল্ট-ইন ভিপিএন</translation>
+<translation id="1672499492233627739">ওয়েবক্যাম ভিডিও ফিড</translation>
 <translation id="1676557873873341166">ভিডিও ক্যাপচার করা হচ্ছে</translation>
 <translation id="1703835215927279855">Letter</translation>
 <translation id="1706391837335750954">DNS সমাধানকারী স্ক্রিন পিন করা</translation>
@@ -216,6 +217,7 @@
 <translation id="3008341117444806826">রিফ্রেশ করুন</translation>
 <translation id="3009958530611748826">কোন ফোল্ডারে সেভ করতে চান তা বেছে নিন</translation>
 <translation id="3017079585324758401">ব্যাকগ্রাউন্ড</translation>
+<translation id="3027578600144895987">ক্যামেরা বন্ধ করুন</translation>
 <translation id="3031560714565892478">ডিভাইস একটি ভিডিও ক্যামেরা।</translation>
 <translation id="3054177598518735801"><ph name="CURRENT_VALUE" />mA</translation>
 <translation id="3056720590588772262">এন্ডপয়েন্ট</translation>
diff --git a/chromeos/strings/chromeos_strings_bs.xtb b/chromeos/strings/chromeos_strings_bs.xtb
index eccec23..f2b550e 100644
--- a/chromeos/strings/chromeos_strings_bs.xtb
+++ b/chromeos/strings/chromeos_strings_bs.xtb
@@ -86,7 +86,7 @@
 <translation id="1645954272419197032">Potvrdite informacije s uređaja</translation>
 <translation id="1662989795263954667">Zaustavljeno – nema tinte</translation>
 <translation id="1668469839109562275">Ugrađeni VPN</translation>
-<translation id="1672499492233627739">Videofeed web-kamere</translation>
+<translation id="1672499492233627739">Sažetak sadržaja videozapisa web kamere</translation>
 <translation id="1676557873873341166">Snimanje videozapisa</translation>
 <translation id="1703835215927279855">Letter</translation>
 <translation id="1706391837335750954">DNS razrješivač je prisutan</translation>
diff --git a/chromeos/strings/chromeos_strings_el.xtb b/chromeos/strings/chromeos_strings_el.xtb
index 400a3d59..0b75921 100644
--- a/chromeos/strings/chromeos_strings_el.xtb
+++ b/chromeos/strings/chromeos_strings_el.xtb
@@ -86,6 +86,7 @@
 <translation id="1645954272419197032">Επιβεβαιώστε τις πληροφορίες συσκευής</translation>
 <translation id="1662989795263954667">Διακοπή - Τελείωσε το μελάνι</translation>
 <translation id="1668469839109562275">Ενσωματωμένο VPN</translation>
+<translation id="1672499492233627739">Ροή βίντεο webcam</translation>
 <translation id="1676557873873341166">Λήψη βίντεο</translation>
 <translation id="1703835215927279855">Letter</translation>
 <translation id="1706391837335750954">Παρουσία επίλυσης DNS</translation>
@@ -216,6 +217,7 @@
 <translation id="3008341117444806826">ΑΝΑΝΕΩΣΗ</translation>
 <translation id="3009958530611748826">Επιλέξτε έναν φάκελο στον οποίο θέλετε να γίνεται αποθήκευση.</translation>
 <translation id="3017079585324758401">Φόντο</translation>
+<translation id="3027578600144895987">Κλείστε την κάμερα</translation>
 <translation id="3031560714565892478">Η συσκευή είναι κάμερα βίντεο.</translation>
 <translation id="3054177598518735801"><ph name="CURRENT_VALUE" /> mA</translation>
 <translation id="3056720590588772262">Σημείο λήξης</translation>
diff --git a/chromeos/strings/chromeos_strings_ka.xtb b/chromeos/strings/chromeos_strings_ka.xtb
index bed810e..42bd0b7 100644
--- a/chromeos/strings/chromeos_strings_ka.xtb
+++ b/chromeos/strings/chromeos_strings_ka.xtb
@@ -492,6 +492,7 @@
 <translation id="5478289488939624992">{ATTEMPTS_LEFT,plural, =1{დარჩენილია {0} მცდელობა}other{დარჩენილია {0} მცდელობა}}</translation>
 <translation id="5493614766091057239"><ph name="VERDICT" />: <ph name="PROBLEMS" /></translation>
 <translation id="5499114900554609492">სკანირება ვერ შესრულდა</translation>
+<translation id="5499762266711462226">კლავიატურის ფერს განსაზღვრავს ფონი</translation>
 <translation id="5502931783115429516">Android არ არის გაშვებული</translation>
 <translation id="5507300744274596613">დარწმუნდით, რომ Chrome OS განახლებულია</translation>
 <translation id="5519195206574732858">LTE</translation>
diff --git a/chromeos/strings/chromeos_strings_mn.xtb b/chromeos/strings/chromeos_strings_mn.xtb
index 13d45da..3bd5c36 100644
--- a/chromeos/strings/chromeos_strings_mn.xtb
+++ b/chromeos/strings/chromeos_strings_mn.xtb
@@ -86,6 +86,7 @@
 <translation id="1645954272419197032">Төхөөрөмжийн мэдээллийг баталгаажуулна уу</translation>
 <translation id="1662989795263954667">Зогссон - Хэвлэгчийн хор дууссан</translation>
 <translation id="1668469839109562275">Бүрэлдэхүүн VPN</translation>
+<translation id="1672499492233627739">Вебкамерын видео хангамж</translation>
 <translation id="1676557873873341166">Видео бичиж байна</translation>
 <translation id="1703835215927279855">Захидал</translation>
 <translation id="1706391837335750954">DNS тайлагчийг үзүүлэх</translation>
@@ -216,6 +217,7 @@
 <translation id="3008341117444806826">ДАХИН ШИНЭЧЛЭХ</translation>
 <translation id="3009958530611748826">Хадгалах фолдероо сонгоно уу</translation>
 <translation id="3017079585324758401">Арын дэвсгэр</translation>
+<translation id="3027578600144895987">Камерыг хаах</translation>
 <translation id="3031560714565892478">Төхөөрөмж нь видео камер байна.</translation>
 <translation id="3054177598518735801"><ph name="CURRENT_VALUE" />мA</translation>
 <translation id="3056720590588772262">Төгсгөлийн цэг</translation>
diff --git a/chromeos/strings/chromeos_strings_mr.xtb b/chromeos/strings/chromeos_strings_mr.xtb
index c43eafe..175b243 100644
--- a/chromeos/strings/chromeos_strings_mr.xtb
+++ b/chromeos/strings/chromeos_strings_mr.xtb
@@ -86,6 +86,7 @@
 <translation id="1645954272419197032">कृपया डिव्हाइसची माहिती कंफर्म करा</translation>
 <translation id="1662989795263954667">थांबले - शाई संपली आहे</translation>
 <translation id="1668469839109562275">बिल्ट-इन VPN</translation>
+<translation id="1672499492233627739">वेबकॅम व्हिडिओ फीड</translation>
 <translation id="1676557873873341166">व्हिडिओ घेत आहे</translation>
 <translation id="1703835215927279855">Letter</translation>
 <translation id="1706391837335750954">DNS रिसॉल्व्हर प्रेझेंट</translation>
@@ -216,6 +217,7 @@
 <translation id="3008341117444806826">रिफ्रेश करा</translation>
 <translation id="3009958530611748826">ज्यामध्ये सेव्ह करायचे आहे ते फोल्डर निवडा</translation>
 <translation id="3017079585324758401">बॅकग्राउंड</translation>
+<translation id="3027578600144895987">कॅमेरा बंद करा</translation>
 <translation id="3031560714565892478">डिव्हाइस हे व्हिडिओ कॅमेरा आहे.</translation>
 <translation id="3054177598518735801"><ph name="CURRENT_VALUE" />mA</translation>
 <translation id="3056720590588772262">एंडपॉइंट</translation>
diff --git a/chromeos/strings/chromeos_strings_my.xtb b/chromeos/strings/chromeos_strings_my.xtb
index dee81b3..7ffc1f1 100644
--- a/chromeos/strings/chromeos_strings_my.xtb
+++ b/chromeos/strings/chromeos_strings_my.xtb
@@ -32,7 +32,7 @@
 <translation id="1270369111467284986">စတင်ဝင်ရန်စာမျက်နှာကို သံသယရှိသည်</translation>
 <translation id="1290331692326790741">လိုင်းအား မကောင်းပါ</translation>
 <translation id="1301069673413256657">GSM</translation>
-<translation id="1308067967278144752">Write Protect ဖွင့်ခြင်း</translation>
+<translation id="1308067967278144752">‘ပြင်ခွင့်မရှိမုဒ်’ ဖွင့်ခြင်း</translation>
 <translation id="1308754910631152188">အပ်ဒိတ်လုပ်နေသည် (<ph name="PERCENTAGE_VALUE" />% ပြီးပါပြီ)</translation>
 <translation id="1310380015393971138"><ph name="NETWORK_NAME" /> ကွန်ရက်ကို မရနိုင်ပါ</translation>
 <translation id="131421566576084655">နောက်ဆုံး ဒေတာပြင်ဆင်သတ်မှတ်သည့်ရက်စွဲ ရှာမတွေ့ပါ</translation>
@@ -105,7 +105,7 @@
 <translation id="1801418420130173017">မှောင်သည့် အပြင်အဆင် ပိတ်ရန်</translation>
 <translation id="1807246157184219062">အလင်း</translation>
 <translation id="1827738518074806965">ပန်းချီပြခန်း</translation>
-<translation id="1840835860961531162">Write Protect ပိတ်ရန်</translation>
+<translation id="1840835860961531162">‘ပြင်ခွင့်မရှိမုဒ်’ ပိတ်ခြင်း</translation>
 <translation id="1851218745569890714">ဗီဒီယိုအစည်းအဝေး</translation>
 <translation id="1852934301711881861">ChromeOS Flex ထည့်သွင်းရန်</translation>
 <translation id="1856388568474281774">အောက်ညွှန်မြား</translation>
@@ -283,7 +283,7 @@
 <translation id="3621202678540785336">ထည့်သွင်းမှု</translation>
 <translation id="3632579075709132555">အချက်အလက်ကာကွယ်ရေး ဖန်သားပြင်ပြောင်းရန်</translation>
 <translation id="3643810137582748570">ချိန်ညှိမှုကို ကျော်ရန်</translation>
-<translation id="3678765385266369662">Write Protect ကို ပိတ်လိုသည့်ပုံစံကို ရွေးချယ်ပါ</translation>
+<translation id="3678765385266369662">‘ပြင်ခွင့်မရှိမုဒ်’ ပိတ်လိုသည့်ပုံစံကို ရွေးပါ</translation>
 <translation id="3689839747745352263"><ph name="TEST_NAME" /> စစ်ဆေးမှု</translation>
 <translation id="370665806235115550">တင်ပေးနေ...</translation>
 <translation id="3708186454126126312">ယခင် ချိတ်ဆက်ထားသည်များ</translation>
@@ -449,7 +449,7 @@
 <translation id="5166918508782100047">အမြန်အဖြေများ ဆက်တင်</translation>
 <translation id="5168185087976003268">ဘက်ထရီအခြေအနေ</translation>
 <translation id="5170568018924773124">ဖိုလ်ဒါ ထဲမှာ ပြရန်</translation>
-<translation id="5179530508336824319">လာမည့်စခရင်သို့ ရှေ့ဆက်ရန် Write Protect ဖွင့်ပါ။ ညွှန်ကြားချက်များအတွက် စက်ထုတ်လုပ်သူ၏ အကူအညီစာမျက်နှာသို့ သွားပါ။</translation>
+<translation id="5179530508336824319">လာမည့်စခရင်သို့ ရှေ့ဆက်ရန် ပြင်ခွင့်မရှိမုဒ်ကို ဖွင့်ပါ။ ညွှန်ကြားချက်များအတွက် စက်ထုတ်လုပ်သူ၏ အကူအညီစာမျက်နှာသို့ သွားပါ။</translation>
 <translation id="5190187232518914472">သင့်အကြိုက်ဆုံး အမှတ်တရအချိန်များကို ပြန်လည်ခံစားကြည့်ပါ။ အယ်လ်ဘမ်များ ထည့်ရန် သို့မဟုတ် တည်းဖြတ်ရန် <ph name="LINK_BEGIN" />Google Photos<ph name="LINK_END" /> သို့သွားပါ။</translation>
 <translation id="5212543919916444558">သင့်မျက်နှာပြင်တွင် ကျွန်ုပ်ကူညီနိုင်သည့် အကြောင်းအရာများကို မတွေ့ပါ။ မိုက်ကို တို့ပြီး နှစ်သက်ရာ မေးနိုင်ပါသည်။</translation>
 <translation id="5212593641110061691">Tabloid</translation>
@@ -463,7 +463,7 @@
 <translation id="5275828089655680674">ပုံမှန်အစီအစဉ်များသို့ ပြန်သွားရန်</translation>
 <translation id="5286252187236914003">L2TP/IPsec</translation>
 <translation id="5294769550414936029">ဗားရှင်း <ph name="MILESTONE_VERSION" /></translation>
-<translation id="5298334025463010990">လာမည့်စခရင်သို့ ရှေ့ဆက်ရန် Write Protect ပိတ်ပါ။ ညွှန်ကြားချက်များအတွက် စက်ထုတ်လုပ်သူ၏ အကူအညီစာမျက်နှာသို့ သွားပါ။</translation>
+<translation id="5298334025463010990">လာမည့်စခရင်သို့ ရှေ့ဆက်ရန် ပြင်ခွင့်မရှိမုဒ်ကို ပိတ်ပါ။ ညွှန်ကြားချက်များအတွက် စက်ထုတ်လုပ်သူ၏ အကူအညီစာမျက်နှာသို့ သွားပါ။</translation>
 <translation id="5300814202279832142">ဝင်းဒိုးကို မျက်နှာပြင်နေရာသို့ ရွှေ့ရန်</translation>
 <translation id="5304899856529773394">EVDO</translation>
 <translation id="5308380583665731573">ချိတ်ဆက်ရန်</translation>
@@ -492,6 +492,7 @@
 <translation id="5478289488939624992">{ATTEMPTS_LEFT,plural, =1{{0} ကြိမ် ကြိုးပမ်းနိုင်သည်}other{{0} ကြိမ် ကြိုးပမ်းနိုင်သည်}}</translation>
 <translation id="5493614766091057239"><ph name="VERDICT" />− <ph name="PROBLEMS" /></translation>
 <translation id="5499114900554609492">စကင်ဖတ်၍ မရပါ</translation>
+<translation id="5499762266711462226">ကီးဘုတ်အရောင်က နောက်ခံအပေါ် မူတည်သည်</translation>
 <translation id="5502931783115429516">Android မလုပ်ဆောင်တော့ပါ</translation>
 <translation id="5507300744274596613">Chrome OS အပ်ဒိတ်ဖြစ်နေကြောင်း သေချာပါစေ</translation>
 <translation id="5519195206574732858">LTE</translation>
diff --git a/chromeos/strings/chromeos_strings_no.xtb b/chromeos/strings/chromeos_strings_no.xtb
index fb71b81..7c4a179 100644
--- a/chromeos/strings/chromeos_strings_no.xtb
+++ b/chromeos/strings/chromeos_strings_no.xtb
@@ -234,6 +234,7 @@
 <translation id="315738237743207937">Oppdaget en obligatorisk side</translation>
 <translation id="3170673040743561620">Legg dokumentet på skanneren</translation>
 <translation id="3188257591659621405">Mine filer</translation>
+<translation id="319101249942218879">Brukerbildet er endret</translation>
 <translation id="3192947282887913208">Lydfiler</translation>
 <translation id="3199982728237701504">Dokumentmater (tosidig)</translation>
 <translation id="320091191259649613">Hvis du fremdeles ser problemet etter oppdateringen, er det mulig at komponenten nylig er kvalifisert og ikke er lagt inn i databasen ennå.</translation>
diff --git a/chromeos/strings/chromeos_strings_or.xtb b/chromeos/strings/chromeos_strings_or.xtb
index db9a267..10876a43d 100644
--- a/chromeos/strings/chromeos_strings_or.xtb
+++ b/chromeos/strings/chromeos_strings_or.xtb
@@ -234,6 +234,7 @@
 <translation id="315738237743207937">କ୍ୟାପ୍ଟିଭ୍ ପୋର୍ଟାଲକୁ ଚିହ୍ନଟ କରାଯାଇଛି</translation>
 <translation id="3170673040743561620">ଆପଣଙ୍କ ଡକ୍ୟୁମେଣ୍ଟକୁ ସ୍କାନରରେ ରଖନ୍ତୁ</translation>
 <translation id="3188257591659621405">ମୋ ଫାଇଲ୍‌ଗୁଡ଼ିକ</translation>
+<translation id="319101249942218879">ଅବତାର ଇମେଜ ପରିବର୍ତ୍ତନ କରାଯାଇଛି</translation>
 <translation id="3192947282887913208">ଅଡିଓ ଫାଇଲ୍ସ</translation>
 <translation id="3199982728237701504">ଡକ୍ୟୁମେଣ୍ଟ ଫିଡର୍ (ଦୁଇ-ପାର୍ଶ୍ୱ)</translation>
 <translation id="320091191259649613">ଯଦି ଆପଣ ଅପଡେଟ ହେବା ପରେ ମଧ୍ୟ ସମସ୍ୟା ଦେଖନ୍ତି, ତେବେ କମ୍ପୋନେଣ୍ଟଟି ନୂଆ କରି ଯୋଗ୍ୟ ହୋଇଥିବା ଏବଂ ଏହାକୁ ଏପର୍ଯ୍ୟନ୍ତ ଡାଟାବେସରେ ଯୋଗ କରାଯାଇନଥିବା ସମ୍ଭବ ଅଟେ।</translation>
diff --git a/chromeos/strings/chromeos_strings_pa.xtb b/chromeos/strings/chromeos_strings_pa.xtb
index 1f48678f..2d38634 100644
--- a/chromeos/strings/chromeos_strings_pa.xtb
+++ b/chromeos/strings/chromeos_strings_pa.xtb
@@ -234,6 +234,7 @@
 <translation id="315738237743207937">ਕੈਪਟਿਵ ਪੋਰਟਲ ਦਾ ਪਤਾ ਲੱਗਾ</translation>
 <translation id="3170673040743561620">ਆਪਣੇ ਦਸਤਾਵੇਜ਼ ਨੂੰ ਸਕੈਨਰ 'ਤੇ ਰੱਖੋ</translation>
 <translation id="3188257591659621405">ਮੇਰੀਆਂ ਫ਼ਾਈਲਾਂ</translation>
+<translation id="319101249942218879">ਅਵਤਾਰ ਚਿੱਤਰ ਬਦਲਿਆ ਗਿਆ</translation>
 <translation id="3192947282887913208">ਆਡੀਓ ਫਾਈਲ</translation>
 <translation id="3199982728237701504">ਦਸਤਾਵੇਜ਼ ਫ਼ੀਡਰ (ਦੋ ਪਾਸੜ)</translation>
 <translation id="320091191259649613">ਜੇ ਤੁਹਾਨੂੰ ਅੱਪਡੇਟ ਤੋਂ ਬਾਅਦ ਵੀ ਸਮੱਸਿਆ ਦਿਖਾਈ ਦਿੰਦੀ ਹੈ, ਤਾਂ ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਤੱਤ ਹਾਲ ਹੀ ਵਿੱਚ ਯੋਗ ਬਣਿਆ ਹੋਵੇ ਅਤੇ ਇਸਨੂੰ ਹਾਲੇ ਡਾਟਾਬੇਸ ਵਿੱਚ ਅੱਪਡੇਟ ਨਾ ਕੀਤਾ ਗਿਆ ਹੋਵੇ।</translation>
diff --git a/chromeos/strings/chromeos_strings_pl.xtb b/chromeos/strings/chromeos_strings_pl.xtb
index 910f97f1..ba4e9ed 100644
--- a/chromeos/strings/chromeos_strings_pl.xtb
+++ b/chromeos/strings/chromeos_strings_pl.xtb
@@ -86,6 +86,7 @@
 <translation id="1645954272419197032">Potwierdź informacje o urządzeniu</translation>
 <translation id="1662989795263954667">Zatrzymano – brak tuszu</translation>
 <translation id="1668469839109562275">Wbudowana sieć VPN</translation>
+<translation id="1672499492233627739">Przekaz z kamery internetowej</translation>
 <translation id="1676557873873341166">Nagrywam obraz</translation>
 <translation id="1703835215927279855">Letter</translation>
 <translation id="1706391837335750954">Resolver DNS – obecność</translation>
@@ -216,6 +217,7 @@
 <translation id="3008341117444806826">ODŚWIEŻ</translation>
 <translation id="3009958530611748826">Wybierz folder zapisu</translation>
 <translation id="3017079585324758401">Tło</translation>
+<translation id="3027578600144895987">Zamknij kamerę</translation>
 <translation id="3031560714565892478">Urządzenie to kamera wideo.</translation>
 <translation id="3054177598518735801"><ph name="CURRENT_VALUE" /> mA</translation>
 <translation id="3056720590588772262">Punkt końcowy</translation>
diff --git a/chromeos/strings/chromeos_strings_pt-BR.xtb b/chromeos/strings/chromeos_strings_pt-BR.xtb
index f7671a76..188309f 100644
--- a/chromeos/strings/chromeos_strings_pt-BR.xtb
+++ b/chromeos/strings/chromeos_strings_pt-BR.xtb
@@ -86,6 +86,7 @@
 <translation id="1645954272419197032">Confirme as informações do dispositivo</translation>
 <translation id="1662989795263954667">Parado (sem tinta)</translation>
 <translation id="1668469839109562275">VPN integrado</translation>
+<translation id="1672499492233627739">Feed de vídeo da webcam</translation>
 <translation id="1676557873873341166">Captura de vídeo ativada</translation>
 <translation id="1703835215927279855">Carta</translation>
 <translation id="1706391837335750954">Resolvedor de DNS presente</translation>
@@ -216,6 +217,7 @@
 <translation id="3008341117444806826">ATUALIZAR</translation>
 <translation id="3009958530611748826">Selecione em que pasta quer salvar</translation>
 <translation id="3017079585324758401">Plano de fundo</translation>
+<translation id="3027578600144895987">Fechar a câmera</translation>
 <translation id="3031560714565892478">Este dispositivo é uma câmera de vídeo.</translation>
 <translation id="3054177598518735801"><ph name="CURRENT_VALUE" /> mA</translation>
 <translation id="3056720590588772262">Endpoint</translation>
@@ -234,6 +236,7 @@
 <translation id="315738237743207937">Portal cativo detectado</translation>
 <translation id="3170673040743561620">Coloque o documento no scanner</translation>
 <translation id="3188257591659621405">Meus arquivos</translation>
+<translation id="319101249942218879">A imagem do avatar foi alterada</translation>
 <translation id="3192947282887913208">Arquivos de áudio</translation>
 <translation id="3199982728237701504">Alimentador de documentos (frente e verso)</translation>
 <translation id="320091191259649613">Se o problema persistir após a atualização, é possível que o componente tenha sido qualificado recentemente e ainda não esteja no banco de dados.</translation>
diff --git a/chromeos/strings/chromeos_strings_pt-PT.xtb b/chromeos/strings/chromeos_strings_pt-PT.xtb
index 647f079..2dfdb01b 100644
--- a/chromeos/strings/chromeos_strings_pt-PT.xtb
+++ b/chromeos/strings/chromeos_strings_pt-PT.xtb
@@ -86,6 +86,7 @@
 <translation id="1645954272419197032">Confirme as informações do dispositivo</translation>
 <translation id="1662989795263954667">Parada – Sem tinta</translation>
 <translation id="1668469839109562275">VPN incorporada</translation>
+<translation id="1672499492233627739">Feed de vídeo da câmara Web</translation>
 <translation id="1676557873873341166">A gravar vídeo</translation>
 <translation id="1703835215927279855">Letter</translation>
 <translation id="1706391837335750954">Resolvedor de DNS presente</translation>
@@ -216,6 +217,7 @@
 <translation id="3008341117444806826">ATUALIZAR</translation>
 <translation id="3009958530611748826">Selecione uma pasta onde guardar</translation>
 <translation id="3017079585324758401">Fundo</translation>
+<translation id="3027578600144895987">Fechar câmara</translation>
 <translation id="3031560714565892478">O dispositivo é uma câmara de vídeo.</translation>
 <translation id="3054177598518735801"><ph name="CURRENT_VALUE" /> mA</translation>
 <translation id="3056720590588772262">Ponto final</translation>
@@ -491,6 +493,7 @@
 <translation id="5478289488939624992">{ATTEMPTS_LEFT,plural, =1{{0} tentativa restante.}other{{0} tentativas restantes.}}</translation>
 <translation id="5493614766091057239"><ph name="VERDICT" />: <ph name="PROBLEMS" /></translation>
 <translation id="5499114900554609492">Não foi possível concluir a digitalização</translation>
+<translation id="5499762266711462226">A cor do teclado baseia-se na imagem de fundo</translation>
 <translation id="5502931783115429516">O Android não está a funcionar</translation>
 <translation id="5507300744274596613">Certifique-se de que o Chrome OS está atualizado</translation>
 <translation id="5519195206574732858">LTE</translation>
diff --git a/chromeos/strings/chromeos_strings_sk.xtb b/chromeos/strings/chromeos_strings_sk.xtb
index 5924d4d..ad9d88e1 100644
--- a/chromeos/strings/chromeos_strings_sk.xtb
+++ b/chromeos/strings/chromeos_strings_sk.xtb
@@ -86,6 +86,7 @@
 <translation id="1645954272419197032">Potvrďte informácie zo zariadení</translation>
 <translation id="1662989795263954667">Zastavené – minul sa atrament</translation>
 <translation id="1668469839109562275">Vstavaná sieť VPN</translation>
+<translation id="1672499492233627739">Videoprenos z webovej kamery</translation>
 <translation id="1676557873873341166">Nahráva sa video</translation>
 <translation id="1703835215927279855">Letter</translation>
 <translation id="1706391837335750954">Prekladač DNS je prítomný</translation>
@@ -216,6 +217,7 @@
 <translation id="3008341117444806826">OBNOVIŤ</translation>
 <translation id="3009958530611748826">Vyberte priečinok na uloženie</translation>
 <translation id="3017079585324758401">Pozadie</translation>
+<translation id="3027578600144895987">Zavrieť kameru</translation>
 <translation id="3031560714565892478">Zariadenie je videokamera.</translation>
 <translation id="3054177598518735801"><ph name="CURRENT_VALUE" /> mA</translation>
 <translation id="3056720590588772262">Konečný bod</translation>
diff --git a/chromeos/strings/chromeos_strings_sr-Latn.xtb b/chromeos/strings/chromeos_strings_sr-Latn.xtb
index 74b6c818..4c71d686 100644
--- a/chromeos/strings/chromeos_strings_sr-Latn.xtb
+++ b/chromeos/strings/chromeos_strings_sr-Latn.xtb
@@ -236,6 +236,7 @@
 <translation id="315738237743207937">Otkriven je ulazni portal</translation>
 <translation id="3170673040743561620">Postavite dokument na skener</translation>
 <translation id="3188257591659621405">Moje datoteke</translation>
+<translation id="319101249942218879">Slika avatara je promenjena</translation>
 <translation id="3192947282887913208">Audio datoteke</translation>
 <translation id="3199982728237701504">Uvlačenje dokumenta (dvostrano)</translation>
 <translation id="320091191259649613">Ako i dalje vidite problem posle ažuriranja, moguće je da je komponenta odskora kvalifikovana i da još uvek nije dospela u bazu podataka.</translation>
diff --git a/chromeos/strings/chromeos_strings_sr.xtb b/chromeos/strings/chromeos_strings_sr.xtb
index 0cbdc8c..fc15afff 100644
--- a/chromeos/strings/chromeos_strings_sr.xtb
+++ b/chromeos/strings/chromeos_strings_sr.xtb
@@ -236,6 +236,7 @@
 <translation id="315738237743207937">Откривен је улазни портал</translation>
 <translation id="3170673040743561620">Поставите документ на скенер</translation>
 <translation id="3188257591659621405">Моје датотеке</translation>
+<translation id="319101249942218879">Слика аватара је промењена</translation>
 <translation id="3192947282887913208">Аудио датотеке</translation>
 <translation id="3199982728237701504">Увлачење документа (двострано)</translation>
 <translation id="320091191259649613">Ако и даље видите проблем после ажурирања, могуће је да је компонента одскора квалификована и да још увек није доспела у базу података.</translation>
diff --git a/chromeos/strings/chromeos_strings_te.xtb b/chromeos/strings/chromeos_strings_te.xtb
index 2a8698a..6b5e458 100644
--- a/chromeos/strings/chromeos_strings_te.xtb
+++ b/chromeos/strings/chromeos_strings_te.xtb
@@ -86,6 +86,7 @@
 <translation id="1645954272419197032">దయచేసి పరికర సమాచారాన్ని నిర్ధారించండి</translation>
 <translation id="1662989795263954667">ఆగిపోయింది - ఇంక్ లేదు</translation>
 <translation id="1668469839109562275">బిల్ట్-ఇన్ VPN</translation>
+<translation id="1672499492233627739">వెబ్‌క్యామ్ వీడియో ఫీడ్</translation>
 <translation id="1676557873873341166">వీడియో తీస్తోంది</translation>
 <translation id="1703835215927279855">లెటర్</translation>
 <translation id="1706391837335750954">DNS రిసాల్వర్ అందుబాటులో ఉంది</translation>
@@ -216,6 +217,7 @@
 <translation id="3008341117444806826">రిఫ్రెష్ చేయి</translation>
 <translation id="3009958530611748826">దీనిలో సేవ్ చేయడానికి ఫోల్డర్‌ను ఎంచుకోండి</translation>
 <translation id="3017079585324758401">నేపథ్యం</translation>
+<translation id="3027578600144895987">కెమెరాను మూసివేయండి</translation>
 <translation id="3031560714565892478">పరికర రకం వీడియో కెమెరా.</translation>
 <translation id="3054177598518735801"><ph name="CURRENT_VALUE" />mA</translation>
 <translation id="3056720590588772262">ముగింపుపాయింట్</translation>
diff --git a/chromeos/strings/chromeos_strings_ur.xtb b/chromeos/strings/chromeos_strings_ur.xtb
index 000e3c3..3ff2eb08a 100644
--- a/chromeos/strings/chromeos_strings_ur.xtb
+++ b/chromeos/strings/chromeos_strings_ur.xtb
@@ -234,6 +234,7 @@
 <translation id="315738237743207937">کیپٹو پورٹل کا پتا چلا</translation>
 <translation id="3170673040743561620">اپنی دستاویز کو اسکینر پر رکھیں</translation>
 <translation id="3188257591659621405">میری فائلز</translation>
+<translation id="319101249942218879">اوتار تصویر تبدیل کی گئی</translation>
 <translation id="3192947282887913208">آڈیو فائلز</translation>
 <translation id="3199982728237701504">دستاویز فیڈر (دو طرفہ)</translation>
 <translation id="320091191259649613">اگر اپ ڈیٹ کے بعد بھی آپ کو مسئلہ نظر آتا ہے تو یہ ہو سکتا ہے کہ جزو ابھی کوالیفائی ہوا ہو اور ڈیٹا بیس میں ابھی تک اپ ڈیٹ نہیں کیا گیا ہو۔</translation>
diff --git a/chromeos/strings/chromeos_strings_zh-HK.xtb b/chromeos/strings/chromeos_strings_zh-HK.xtb
index 1631d124..880aa958 100644
--- a/chromeos/strings/chromeos_strings_zh-HK.xtb
+++ b/chromeos/strings/chromeos_strings_zh-HK.xtb
@@ -493,6 +493,7 @@
 <translation id="5478289488939624992">{ATTEMPTS_LEFT,plural, =1{剩餘嘗試次數:{0} 次}other{剩餘嘗試次數:{0} 次}}</translation>
 <translation id="5493614766091057239"><ph name="VERDICT" />:<ph name="PROBLEMS" /></translation>
 <translation id="5499114900554609492">無法完成掃描</translation>
+<translation id="5499762266711462226">鍵盤顏色是根據桌布而定</translation>
 <translation id="5502931783115429516">Android 未執行</translation>
 <translation id="5507300744274596613">確保 Chrome OS 為最新版本</translation>
 <translation id="5519195206574732858">LTE</translation>
diff --git a/components/certificate_transparency/data/log_list.json b/components/certificate_transparency/data/log_list.json
index 5219bdb..b143e80 100644
--- a/components/certificate_transparency/data/log_list.json
+++ b/components/certificate_transparency/data/log_list.json
@@ -1,6 +1,6 @@
 {
-  "version": "9.25",
-  "log_list_timestamp": "2022-05-27T12:55:13Z",
+  "version": "9.26",
+  "log_list_timestamp": "2022-05-28T12:54:33Z",
   "operators": [
     {
       "name": "Google",
diff --git a/components/cloud_devices/common/printer_description.cc b/components/cloud_devices/common/printer_description.cc
index 3ce69e02..7c9c71ae 100644
--- a/components/cloud_devices/common/printer_description.cc
+++ b/components/cloud_devices/common/printer_description.cc
@@ -1038,8 +1038,7 @@
     if (document_types_supported) {
       if (!document_types_supported->is_list())
         return false;
-      for (const auto& type_value :
-           document_types_supported->GetListDeprecated()) {
+      for (const auto& type_value : document_types_supported->GetList()) {
         if (!type_value.is_string())
           return false;
 
diff --git a/components/policy/resources/policy_templates_es.xtb b/components/policy/resources/policy_templates_es.xtb
index 62eea656..9864531 100644
--- a/components/policy/resources/policy_templates_es.xtb
+++ b/components/policy/resources/policy_templates_es.xtb
@@ -3642,6 +3642,7 @@
 <translation id="4960597185231686653">Un indicador booleano que especifica si el teclado en pantalla permite usar la función de entrada de voz.</translation>
 <translation id="4970046075219007744">Permite que las aplicaciones web soliciten al usuario que les conceda acceso a ciertos tipos de archivo a través de la API File Handling</translation>
 <translation id="4970855112942626932">Inhabilitar inicio de sesión en el navegador</translation>
+<translation id="4974091268178043378">Modo de color de Chrome OS</translation>
 <translation id="4976928720873547342">Si se establece esta política, todos los tipos de datos especificados se excluirán de la sincronización de <ph name="CHROME_SYNC_NAME" /> y de la sincronización del perfil de roaming. Esto puede ser útil para reducir el tamaño del perfil de roaming o para limitar el tipo de datos que se suban a los servidores de <ph name="CHROME_SYNC_NAME" />.
 
       Los tipos de datos actuales para esta política son los siguientes: "bookmarks", "readingList", "preferences", "passwords", "autofill", "themes", "typedUrls", "extensions", "apps", "tabs" y "wifiConfigurations". Estos nombres distinguen entre mayúsculas y minúsculas.</translation>
@@ -4405,6 +4406,7 @@
 
       Los usuarios no podrán modificar este ajuste.</translation>
 <translation id="5848438019586925019">El algoritmo para generar pares de claves.</translation>
+<translation id="5851248808417680865">Usar el tema oscuro</translation>
 <translation id="585270638818921943">Evitar que el usuario utilice aplicaciones Android de fuentes que no son de confianza</translation>
 <translation id="5853547031212075792">Permitir que los usuarios habiliten el modo solo‑HTTPS</translation>
 <translation id="5859344336338527083">Si se define esta política, se especificarán las URL que pueden instalar extensiones, aplicaciones y temas. Antes de la versión 21 de <ph name="PRODUCT_NAME" />, los usuarios podían hacer clic en un enlace a un archivo .crx y <ph name="PRODUCT_NAME" /> les ofrecería la opción de instalar el archivo después de mostrar algunas advertencias. A continuación, esos archivos debían descargarse y arrastrarse a la página de configuración de <ph name="PRODUCT_NAME" />. Esta opción permite que determinadas URL sigan utilizando el proceso de instalación anterior, que era más sencillo.
@@ -4581,6 +4583,7 @@
 
       Esta política solo es efectiva cuando el equipo está registrado en <ph name="CLOUD_MANAGEMENT_ENROLLMENT_TOKEN" /> para <ph name="PRODUCT_NAME" />.
       Para <ph name="PRODUCT_OS_NAME" />, esta política siempre es efectiva.</translation>
+<translation id="6019162469732742754">Usar el modo automático</translation>
 <translation id="6019606564278029236">Habilitar la interacción de los usuarios remotos con ventanas con permisos de administrador en sesiones de asistencia remota</translation>
 <translation id="6022948604095165524">Acción al iniciar</translation>
 <translation id="602318745029752898">Permitir las voces de conversión de texto a voz de red mejorada en Enunciar selección</translation>
@@ -5584,6 +5587,7 @@
 <translation id="7019805045859631636">Rápido</translation>
 <translation id="7025332601572838001">Configuración del comportamiento de los Términos del Servicio durante la primera ejecución de CCT</translation>
 <translation id="7026351325994257733">Permitir que las configuraciones de la red Wi‑Fi se sincronicen en los dispositivos <ph name="PRODUCT_OS_NAME" /> y en un teléfono Android conectado.</translation>
+<translation id="7027057540229843762">Usar el tema claro</translation>
 <translation id="7027785306666625591">Configura la administración de energía en <ph name="PRODUCT_OS_NAME" />.
 
 Estas políticas te permiten configurar el comportamiento de <ph name="PRODUCT_OS_NAME" /> cuando el usuario permanece inactivo durante un periodo de tiempo determinado.</translation>
@@ -7148,6 +7152,9 @@
 
       "http://acme.com/ABC" solo sería coincidencia en IESiteListMode.</translation>
 <translation id="8736538322216687231">Aplicar el modo restringido en YouTube como mínimo</translation>
+<translation id="8744844164152340112">Controla el tema utilizado para renderizar la interfaz de usuario la primera vez que se usa el dispositivo y durante la sesión (oscuro/claro/automático).
+      El modo automático cambia automáticamente entre los temas oscuro y claro al amanecer y al atardecer.
+      Esta política debería recomendarse para ofrecer a los usuarios la opción de cambiar el tema en la configuración del sistema.</translation>
 <translation id="8745669971728319820">Esta política determina si se recoge información sobre extensiones y complementos.
 
       Si no se establece la política <ph name="CLOUD_REPORTING_ENABLED_POLICY_NAME" /> o se inhabilita, esta se ignorará.
diff --git a/components/policy/resources/policy_templates_fr.xtb b/components/policy/resources/policy_templates_fr.xtb
index dc87923..c8c65e5 100644
--- a/components/policy/resources/policy_templates_fr.xtb
+++ b/components/policy/resources/policy_templates_fr.xtb
@@ -3611,6 +3611,7 @@
 <translation id="4960597185231686653">Indicateur booléen spécifiant si la saisie vocale est disponible ou non avec le clavier à l'écran.</translation>
 <translation id="4970046075219007744">Autoriser les applications Web à demander aux utilisateurs l'accès à ces types de fichiers via l'API File Handling</translation>
 <translation id="4970855112942626932">Désactiver la connexion au navigateur</translation>
+<translation id="4974091268178043378">Mode couleur de Chrome OS</translation>
 <translation id="4976928720873547342">Si cette règle est configurée, tous les types de données spécifiés ne seront pas synchronisés avec <ph name="CHROME_SYNC_NAME" /> ni avec le profil itinérant. Cela peut permettre de réduire la taille du profil itinérant ou de limiter les types de données importés sur les serveurs <ph name="CHROME_SYNC_NAME" />.
 
       Les types de données actuels pour cette règle sont : "bookmarks", "readingList", "preferences", "passwords", "autofill", "themes", "typedUrls", "extensions", "apps", "tabs" et "wifiConfigurations". Ces noms sont sensibles à la casse.</translation>
@@ -4375,6 +4376,7 @@
 
       Les utilisateurs ne peuvent pas modifier ce paramètre.</translation>
 <translation id="5848438019586925019">Algorithme pour la génération de paires de clés.</translation>
+<translation id="5851248808417680865">Utiliser le thème sombre</translation>
 <translation id="585270638818921943">Empêche l'utilisateur de se servir d'applications Android provenant de sources non approuvées</translation>
 <translation id="5853547031212075792">Autoriser les utilisateurs à activer le mode HTTPS uniquement</translation>
 <translation id="5859344336338527083">Permet de déterminer quelles URL peuvent installer des extensions, des applications et des thèmes. Avant la version 21 de <ph name="PRODUCT_NAME" />, les utilisateurs pouvaient cliquer sur un lien qui renvoyait vers un fichier *.crx, et <ph name="PRODUCT_NAME" /> leur proposait d'installer ce fichier, tout en affichant d'abord quelques avertissements. Depuis, les fichiers de ce type doivent être téléchargés et glissés vers la page des paramètres <ph name="PRODUCT_NAME" />. Cette règle permet d'appliquer à des URL spécifiques l'ancienne procédure d'installation, plus facile à suivre.
@@ -4543,6 +4545,7 @@
 
       Cette règle n'est appliquée que si l'ordinateur est enregistré avec la règle <ph name="CLOUD_MANAGEMENT_ENROLLMENT_TOKEN" /> pour <ph name="PRODUCT_NAME" />.
       Elle est toujours appliquée pour <ph name="PRODUCT_OS_NAME" />.</translation>
+<translation id="6019162469732742754">Utiliser le mode Auto</translation>
 <translation id="6019606564278029236">Activer les interactions des utilisateurs distants avec des fenêtres élevées dans les sessions d'assistance à distance</translation>
 <translation id="6022948604095165524">Action au démarrage</translation>
 <translation id="602318745029752898">Autoriser la synthèse vocale améliorée via le réseau pour Sélectionner pour prononcer</translation>
@@ -5528,6 +5531,7 @@
 <translation id="7019805045859631636">Rapide</translation>
 <translation id="7025332601572838001">Configurer le comportement de la boîte de dialogue des conditions d'utilisation la première fois que des onglets personnalisés Chrome sont exécutés</translation>
 <translation id="7026351325994257733">Autoriser la synchronisation des configurations du réseau Wi-Fi entre les appareils <ph name="PRODUCT_OS_NAME" /> et un téléphone Android connecté.</translation>
+<translation id="7027057540229843762">Utiliser le thème clair</translation>
 <translation id="7027785306666625591">Configurer la gestion de l'alimentation dans <ph name="PRODUCT_OS_NAME" />
 
       Ces règles vous permettent de configurer le comportement du système d'exploitation "<ph name="PRODUCT_OS_NAME" />" lorsque l'utilisateur est inactif pendant un certain temps.</translation>
@@ -7083,6 +7087,9 @@
 
       "http://acme.com/ABC" ne correspond qu'en "IESiteListMode".</translation>
 <translation id="8736538322216687231">Appliquer un mode restreint minimal sur YouTube</translation>
+<translation id="8744844164152340112">Contrôle le thème utilisé pour afficher l'UI pendant la configuration initiale et en cours de session (sombre/clair/auto).
+      Le mode Auto alterne automatiquement entre le thème sombre et le thème clair au lever et au coucher du soleil.
+      Cette règle devrait être recommandée, car elle permet aux utilisateurs de modifier le thème dans les paramètres système.</translation>
 <translation id="8745669971728319820">Cette règle détermine si les informations sur les extensions et les plug-ins doivent être enregistrées.
 
       Cette règle est ignorée si la règle <ph name="CLOUD_REPORTING_ENABLED_POLICY_NAME" /> n'est pas définie ou si elle est désactivée.
diff --git a/components/policy/resources/policy_templates_tr.xtb b/components/policy/resources/policy_templates_tr.xtb
index 93697cc..283d20a 100644
--- a/components/policy/resources/policy_templates_tr.xtb
+++ b/components/policy/resources/policy_templates_tr.xtb
@@ -3607,6 +3607,7 @@
 <translation id="4960597185231686653">Dokunmatik klavyede ses girişi özelliği sunulup sunulamayacağını gösteren bir boole flag'i.</translation>
 <translation id="4970046075219007744">Web uygulamalarının, kullanıcıdan File Handling API üzerinden dosya türlerine erişim istemesine izin ver</translation>
 <translation id="4970855112942626932">Tarayıcıda oturum açmayı devre dışı bırak</translation>
+<translation id="4974091268178043378">ChromeOS renk modu</translation>
 <translation id="4976928720873547342">Bu politika ayarlanırsa belirtilen tüm veri türleri hem <ph name="CHROME_SYNC_NAME" /> senkronizasyonunun hem de dolaşım profili senkronizasyonunun dışında tutulur. Bu, dolaşım profilinin boyutunu küçültmeye veya <ph name="CHROME_SYNC_NAME" /> sunucularına yüklenen veri türlerini sınırlandırmaya yarayabilir.
 
       Şu anda bu politika kapsamında bulunan veri türleri şunlardır: "bookmarks", "readingList", "preferences", "passwords", "autofill", "themes", "typedUrls", "extensions", "apps", "tabs", "wifiConfigurations". Bu adlar büyük/küçük harfe duyarlıdır.</translation>
@@ -4358,6 +4359,7 @@
 
       Kullanıcılar bu ayarı değiştiremez.</translation>
 <translation id="5848438019586925019">Anahtar çifti oluşturmak için kullanılan algoritma.</translation>
+<translation id="5851248808417680865">Koyu temayı kullan</translation>
 <translation id="585270638818921943">Kullanıcının güvenilmeyen kaynaklardan Android uygulamaları kullanmasını engelle</translation>
 <translation id="5853547031212075792">Kullanıcıların Yalnızca HTTPS Modunu etkinleştirmesine izin ver</translation>
 <translation id="5859344336338527083">Politikayı ayarlamak uzantı, uygulama ve tema yükleyebilecek URL'leri belirtir. <ph name="PRODUCT_NAME" /> 21 sürümünden önce, kullanıcılar bir *.crx dosyası bağlantısını tıklayarak <ph name="PRODUCT_NAME" /> ürününün birkaç uyarıdan sonra dosyayı yüklemesini sağlayabiliyordu. Daha sonra, bu tür dosyaların indirilip <ph name="PRODUCT_NAME" /> ayarları sayfasına sürüklenmesi zorunlu hale getirilmiştir. Bu ayar, belirli URL'lerin eski, daha kolay yükleme akışına sahip olmasına olanak tanır.
@@ -4528,6 +4530,7 @@
 
       Bu politika yalnızca <ph name="PRODUCT_NAME" /> için makinenin <ph name="CLOUD_MANAGEMENT_ENROLLMENT_TOKEN" /> kaydı yapıldığında geçerli olur.
       <ph name="PRODUCT_OS_NAME" /> için bu politika her zaman geçerlidir.</translation>
+<translation id="6019162469732742754">Otomatik modu kullan</translation>
 <translation id="6019606564278029236">Uzaktan destek oturumlarında yükseltilmiş pencerelerle uzaktan kullanıcı etkileşimini etkinleştir</translation>
 <translation id="6022948604095165524">Başlangıçtaki işlem</translation>
 <translation id="602318745029752898">Seç ve Dinle özelliğinde gelişmiş ağ metin okuma seslerine izin ver</translation>
@@ -5528,6 +5531,7 @@
 <translation id="7019805045859631636">Hızlı</translation>
 <translation id="7025332601572838001">CCT için ilk çalıştırma sırasında Hizmet Şartları davranışını yapılandırma</translation>
 <translation id="7026351325994257733"><ph name="PRODUCT_OS_NAME" /> cihazlar ve bağlı Android telefon arasında kablosuz ağ yapılandırmalarının senkronize edilmesine izin ver.</translation>
+<translation id="7027057540229843762">Açık temayı kullan</translation>
 <translation id="7027785306666625591"><ph name="PRODUCT_OS_NAME" /> sisteminde güç yönetimini yapılandırın.
 
       Bu politikalar, kullanıcı belirli bir süre boyunca hiçbir şey yapmadığında <ph name="PRODUCT_OS_NAME" /> sisteminin çalışma biçimini yapılandırmanıza olanak verir.</translation>
@@ -7077,6 +7081,9 @@
 
       "http://acme.com/ABC" yalnızca "IESiteListMode" modunda eşleşir.</translation>
 <translation id="8736538322216687231">Minimum YouTube Kısıtlı Modu'nu zorla</translation>
+<translation id="8744844164152340112">OOBE ve oturum sırasında kullanıcı arayüzü oluşturmak için kullanılan temayı kontrol eder (koyu/açık/otomatik).
+      Otomatik mod, gün doğumu ve gün batımında otomatik olarak koyu ve açık tema arasında geçiş yapar.
+      Kullanıcıların sistem ayarlarında temayı değiştirmesine imkan veren bu politika önerilmelidir.</translation>
 <translation id="8745669971728319820">Bu politika, uzantı ve eklenti bilgilerinin bildirilip bildirilmeyeceğini kontrol eder.
 
       <ph name="CLOUD_REPORTING_ENABLED_POLICY_NAME" /> politikası ayarlanmadan bırakıldığında veya devre dışı değerine ayarlandığında bu politika yok sayılır.
diff --git a/components/policy/resources/policy_templates_uk.xtb b/components/policy/resources/policy_templates_uk.xtb
index 1c7b5a0..aaa5d2f 100644
--- a/components/policy/resources/policy_templates_uk.xtb
+++ b/components/policy/resources/policy_templates_uk.xtb
@@ -3635,6 +3635,7 @@
 <translation id="4960597185231686653">Логічне значення експериментального параметра, яке вказує, чи може екранна клавіатура пропонувати голосовий ввід.</translation>
 <translation id="4970046075219007744">Дозволити веб-додаткам запитувати в користувача дозвіл на доступ до певних типів файлів через File Handling API</translation>
 <translation id="4970855112942626932">Вимкнути вхід в обліковий запис у веб-переглядачі</translation>
+<translation id="4974091268178043378">Режим кольору в ОС Chrome</translation>
 <translation id="4976928720873547342">Якщо це правило налаштувати, усі вказані типи даних не будуть синхронізуватися в сервісі <ph name="CHROME_SYNC_NAME" /> і в переміщуваному профілі. Це може допомогти зменшити розмір переміщуваного профілю або обмежити типи даних, які завантажуються на сервери сервісу <ph name="CHROME_SYNC_NAME" />.
 
       Поточні типи даних для цього правила: bookmarks, preferences, passwords, autofill, themes, typedUrls, extensions, apps, tabs, wifiConfigurations. У назвах враховується регістр.</translation>
@@ -4396,6 +4397,7 @@
 
       Користувачі не можуть змінювати це налаштування.</translation>
 <translation id="5848438019586925019">Алгоритм створення пар ключів.</translation>
+<translation id="5851248808417680865">Застосувати темну тему</translation>
 <translation id="585270638818921943">Заборонити користувачеві завантажувати додатки для Android із ненадійних джерел</translation>
 <translation id="5853547031212075792">Дозволити користувачам вмикати режим "Лише HTTPS"</translation>
 <translation id="5859344336338527083">Налаштування цього правила визначають URL-адреси, з яких можна встановлювати розширення, додатки й теми. У попередніх версіях (до <ph name="PRODUCT_NAME" /> 21) користувачі могли натиснути посилання на файл *.crx і після кількох застережень установити його в <ph name="PRODUCT_NAME" />. У новіших версіях такі файли потрібно завантажувати й перетягувати на сторінку налаштувань <ph name="PRODUCT_NAME" />. Цей параметр дозволяє старіший і простіший процес встановлення з певних URL-адрес.
@@ -4571,6 +4573,7 @@
 
       Це правило працює, лише коли комп'ютер зареєстровано відповідно до правила <ph name="CLOUD_MANAGEMENT_ENROLLMENT_TOKEN" /> для <ph name="PRODUCT_NAME" />.
       Для <ph name="PRODUCT_OS_NAME" /> це правило діє завжди.</translation>
+<translation id="6019162469732742754">Застосувати автоматичний режим</translation>
 <translation id="6019606564278029236">Дозволити віддаленим користувачам взаємодіяти з вікнами на робочому столі під час сеансів віддаленої допомоги</translation>
 <translation id="6022948604095165524">Дія під час запуску</translation>
 <translation id="602318745029752898">Дозволити покращені голоси для синтезу мовлення через мережу під час використання функції "Читання з екрана"</translation>
@@ -5570,6 +5573,7 @@
 <translation id="7019805045859631636">Fast</translation>
 <translation id="7025332601572838001">Налаштування поведінки Умов використання під час першого запуску спеціальної вкладки Chrome</translation>
 <translation id="7026351325994257733">Дозволити налаштуванням мережі Wi-Fi синхронізуватися між пристроями <ph name="PRODUCT_OS_NAME" /> і підключеним телефоном Android.</translation>
+<translation id="7027057540229843762">Застосувати світлу тему</translation>
 <translation id="7027785306666625591">Налаштовувати керування живленням в <ph name="PRODUCT_OS_NAME" />.
 
       Це правило дозволяє налаштувати поведінку <ph name="PRODUCT_OS_NAME" />, коли користувач залишається неактивним упродовж певного часу.</translation>
@@ -7129,6 +7133,9 @@
 
       "http://acme.com/ABC" збігатиметься лише в режимі IESiteListMode.</translation>
 <translation id="8736538322216687231">Примусово застосувати мінімальний безпечний режим на YouTube</translation>
+<translation id="8744844164152340112">Визначає, яка тема (темна, світла або автоматичний режим) буде використовуватися в інтерфейсі під час першого запуску й сеансу.
+      Якщо вибрати автоматичний режим, тема змінюватиметься залежно від часу добу.
+      Це правило має бути рекомендованим, щоб користувачі могли змінити тему в налаштуваннях системи.</translation>
 <translation id="8745669971728319820">Це правило визначає, чи повідомляти дані розширень і плагінів.
 
       Якщо правило <ph name="CLOUD_REPORTING_ENABLED_POLICY_NAME" /> не налаштовано або для нього вибрано значення disabled, це правило ігноруватиметься.
diff --git a/components/policy/resources/policy_templates_vi.xtb b/components/policy/resources/policy_templates_vi.xtb
index 9292763..61d4cb4 100644
--- a/components/policy/resources/policy_templates_vi.xtb
+++ b/components/policy/resources/policy_templates_vi.xtb
@@ -3632,6 +3632,7 @@
 <translation id="4960597185231686653">Một cờ boolean cho biết liệu bàn phím ảo có thể cung cấp tính năng nhập bằng giọng nói hay không.</translation>
 <translation id="4970046075219007744">Cho phép các ứng dụng web yêu cầu người dùng cấp quyền truy cập vào các loại tệp thông qua API Xử lý tệp</translation>
 <translation id="4970855112942626932">Vô hiệu hóa đăng nhập vào trình duyệt</translation>
+<translation id="4974091268178043378">Chế độ màu trên ChromeOS</translation>
 <translation id="4976928720873547342">Nếu bạn đặt chính sách này, thì hệ thống sẽ loại trừ tất cả loại dữ liệu đã chỉ định khỏi quá trình đồng bộ hóa của <ph name="CHROME_SYNC_NAME" /> cũng như quá trình đồng bộ hóa cấu hình chuyển vùng. Điều này có thể giúp giảm kích thước của cấu hình chuyển vùng hoặc giới hạn loại dữ liệu đã tải lên các máy chủ <ph name="CHROME_SYNC_NAME" />.
 
       Chính sách này hiện áp dụng cho các loại dữ liệu sau: "bookmarks", "readingList", "preferences", "passwords", "autofill", "themes", "typedUrls", "extensions", "apps", "tabs", "wifiConfigurations". Tên của các loại dữ liệu đó phân biệt chữ hoa chữ thường!</translation>
@@ -4394,6 +4395,7 @@
 
       Người dùng không thể quản lý tùy chọn cài đặt này.</translation>
 <translation id="5848438019586925019">Thuật toán để tạo cặp khóa.</translation>
+<translation id="5851248808417680865">Sử dụng Giao diện tối</translation>
 <translation id="585270638818921943">Ngăn người dùng sử dụng các ứng dụng Android từ những nguồn không tin cậy</translation>
 <translation id="5853547031212075792">Cho phép người dùng bật chế độ Chỉ giao thức HTTPS</translation>
 <translation id="5859344336338527083">Nếu bạn đặt chính sách này, thì hệ thống sẽ chỉ định những URL nào có thể cài đặt tiện ích, ứng dụng và giao diện. Trước <ph name="PRODUCT_NAME" /> 21, người dùng có thể nhấp vào một đường liên kết tới tệp *.crx và <ph name="PRODUCT_NAME" /> sẽ đề xuất cài đặt tệp này sau một vài cảnh báo. Về sau, người dùng phải tải các tệp này xuống và kéo vào trang cài đặt <ph name="PRODUCT_NAME" />. Tùy chọn cài đặt này cho phép các URL cụ thể thực hiện theo quy trình cài đặt cũ, dễ dàng hơn.
@@ -4559,6 +4561,7 @@
 
       Chính sách này chỉ có hiệu lực khi máy đã đăng ký chính sách <ph name="CLOUD_MANAGEMENT_ENROLLMENT_TOKEN" /> đối với <ph name="PRODUCT_NAME" />.
       Chính sách này luôn có hiệu lực đối với <ph name="PRODUCT_OS_NAME" />.</translation>
+<translation id="6019162469732742754">Sử dụng chế độ Tự động</translation>
 <translation id="6019606564278029236">Cho phép người dùng từ xa tương tác với cửa sổ bật lên trong phiên hỗ trợ từ xa</translation>
 <translation id="6022948604095165524">Tác vụ khi khởi động</translation>
 <translation id="602318745029752898">Cho phép dùng các giọng nói của tính năng chuyển văn bản sang lời nói trên mạng nâng cao trong tính năng Chọn để nói</translation>
@@ -5547,6 +5550,7 @@
 <translation id="7019805045859631636">Nhanh</translation>
 <translation id="7025332601572838001">Định cấu hình hoạt động của Điều khoản dịch vụ (ToS) trong lần chạy đầu tiên của CCT</translation>
 <translation id="7026351325994257733">Cho phép đồng bộ hóa các cấu hình mạng Wi-Fi trên nhiều thiết bị <ph name="PRODUCT_OS_NAME" /> với một điện thoại Android đã kết nối.</translation>
+<translation id="7027057540229843762">Sử dụng Giao diện sáng</translation>
 <translation id="7027785306666625591">Định cấu hình việc quản lý nguồn trong <ph name="PRODUCT_OS_NAME" />.
 
       Những chính sách này cho phép bạn định cấu hình cách <ph name="PRODUCT_OS_NAME" /> hoạt động khi người dùng duy trì chế độ rảnh trong một khoảng thời gian.</translation>
@@ -7111,6 +7115,9 @@
 
       "http://acme.com/ABC" sẽ chỉ khớp ở chế độ "IESiteListMode".</translation>
 <translation id="8736538322216687231">Buộc sử dụng Chế độ hạn chế tối thiểu trên YouTube</translation>
+<translation id="8744844164152340112">Cài đặt giao diện dùng để kết xuất giao diện người dùng khi OOBE và trong phiên sử dụng (tối/sáng/tự động).
+      Chế độ tự động sẽ tự động chuyển đổi giữa giao diện tối và giao diện sáng tại thời điểm bình minh và hoàng hôn.
+      Nên đề xuất chính sách này, cho phép người dùng thay đổi giao diện trong phần cài đặt hệ thống.</translation>
 <translation id="8745669971728319820">Chính sách này kiểm soát việc có báo cáo thông tin về trình bổ trợ và tiện ích hay không.
 
       Khi bạn không đặt chính sách <ph name="CLOUD_REPORTING_ENABLED_POLICY_NAME" /> hoặc đặt thành tắt, thì chính sách này sẽ bị bỏ qua.
diff --git a/components/policy/resources/policy_templates_zh-TW.xtb b/components/policy/resources/policy_templates_zh-TW.xtb
index 7b35329a..359b730 100644
--- a/components/policy/resources/policy_templates_zh-TW.xtb
+++ b/components/policy/resources/policy_templates_zh-TW.xtb
@@ -3573,6 +3573,7 @@
 <translation id="4960597185231686653">布林值標記,表示螢幕小鍵盤是否能提供語音輸入功能。</translation>
 <translation id="4970046075219007744">允許網頁應用程式要求使用者授予透過 File Handling API 存取特定類型檔案的權限</translation>
 <translation id="4970855112942626932">禁止登入瀏覽器</translation>
+<translation id="4974091268178043378">Chrome OS 色彩模式</translation>
 <translation id="4976928720873547342">如果設定了這項政策,系統會將所有指定的資料類型從同步處理作業 (包含 <ph name="CHROME_SYNC_NAME" />和漫遊設定檔的同步處理作業) 中排除。這有助於縮減漫遊設定檔的大小,或限制上傳到 <ph name="CHROME_SYNC_NAME" />伺服器的資料類型。
 
       這項政策目前涵蓋的資料類型為:「bookmarks」、「readingList」、「preferences」、「passwords」、「autofill」、「themes」、「typedUrls」、「extensions」、「apps」、「tabs」、「wifiConfigurations」。這些名稱有大小寫之分。</translation>
@@ -4308,6 +4309,7 @@
 
       使用者無法變更這項設定。</translation>
 <translation id="5848438019586925019">用於產生金鑰組的演算法。</translation>
+<translation id="5851248808417680865">使用深色主題</translation>
 <translation id="585270638818921943">禁止使用者使用來源不受信任的 Android 應用程式</translation>
 <translation id="5853547031212075792">允許使用者啟用僅限 HTTPS 模式</translation>
 <translation id="5859344336338527083">你可以透過這項政策,指定可安裝擴充功能、應用程式和主題的網址。在 <ph name="PRODUCT_NAME" /> 21 以前的版本中,使用者只要點選 *.crx 檔案的連結,<ph name="PRODUCT_NAME" /> 就會在顯示幾則警告訊息後,詢問使用者是否要安裝該檔案。在後續版本中,使用者則必須先下載這類檔案,再將檔案拖曳至 <ph name="PRODUCT_NAME" /> 設定頁面中。透過這項設定,你可以允許特定網址使用較簡易的舊式安裝流程。
@@ -4474,6 +4476,7 @@
 
       如果是 <ph name="PRODUCT_NAME" />,只有在已透過 <ph name="CLOUD_MANAGEMENT_ENROLLMENT_TOKEN" /> 註冊裝置的情況下,這項政策才會生效。
       如果是 <ph name="PRODUCT_OS_NAME" />,這項政策會一律生效。</translation>
+<translation id="6019162469732742754">使用自動模式</translation>
 <translation id="6019606564278029236">允許遠端使用者在遠端協助工作階段中操控權限較高的視窗</translation>
 <translation id="6022948604095165524">起始動作</translation>
 <translation id="602318745029752898">允許使用隨選朗讀中的加強型網路文字轉語音功能</translation>
@@ -5453,6 +5456,7 @@
 <translation id="7019805045859631636">快</translation>
 <translation id="7025332601572838001">設定第一次執行 CCT 時的《服務條款》相關行為</translation>
 <translation id="7026351325994257733">允許在搭載 <ph name="PRODUCT_OS_NAME" />的裝置和已連結的 Android 手機上,將 Wi-Fi 網路設定保持同步。</translation>
+<translation id="7027057540229843762">使用淺色主題</translation>
 <translation id="7027785306666625591">設定 <ph name="PRODUCT_OS_NAME" /> 的電源管理。
 
       這些政策可讓你設定當使用者閒置一段時間後,要讓 <ph name="PRODUCT_OS_NAME" /> 採取的動作。</translation>
@@ -6979,6 +6983,9 @@
 
       不過,「http://notexample.com/」、「http://example.com.invalid.com/」、「http://example.comabc/」只有在「Default」模式下才會是相符的結果;「http://acme.com/ABC」則只會在「IESiteListMode」模式下才會是相符的結果。</translation>
 <translation id="8736538322216687231">強制執行低度的 YouTube 嚴格篩選模式</translation>
+<translation id="8744844164152340112">控管在 OOBE 和工作階段期間用於算繪 UI 的主題 (深色/淺色/自動)。
+      自動模式會在日出和日落時,自動在深色和淺色主題間切換。
+      建議採用這項政策,讓使用者能夠在系統設定中變更主題。</translation>
 <translation id="8745669971728319820">這項政策可控管系統是否要回報擴充功能和外掛程式資訊。
 
       如果不設定 <ph name="CLOUD_REPORTING_ENABLED_POLICY_NAME" /> 政策或設為停用,系統會忽略這項政策。
diff --git a/components/strings/components_strings_ka.xtb b/components/strings/components_strings_ka.xtb
index a227ec13..a8e8cbd 100644
--- a/components/strings/components_strings_ka.xtb
+++ b/components/strings/components_strings_ka.xtb
@@ -480,6 +480,7 @@
 <translation id="2215963164070968490">ძაღლები</translation>
 <translation id="2218879909401188352"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />-ზე შეტევის შედეგად თქვენს მოწყობილობაზე შეიძლება დაინსტალირდეს სახიფათო აპები, რომლებსაც შეუძლია თქვენი მოწყობილობის დაზიანება, მობილური სერვისის საფასურის ფარულად გაზრდა თუ პერსონალური ინფორმაციის მოპარვა. <ph name="BEGIN_LEARN_MORE_LINK" />შეიტყვეთ მეტი<ph name="END_LEARN_MORE_LINK" /></translation>
 <translation id="2219658597883514593">სახელმძღვანელოს თავიდან გაშვება</translation>
+<translation id="2219735899272417925">საჭიროა მოწყობილობის გადაყენება</translation>
 <translation id="2224337661447660594">ინტერნეტ-კავშირი არ არის</translation>
 <translation id="2230458221926704099">გაასწორეთ თქვენი კავშირი <ph name="BEGIN_LINK" />დიაგნოსტიკური აპის<ph name="END_LINK" /> მეშვეობით</translation>
 <translation id="2239100178324503013">ახლავე გაგზავნა</translation>
diff --git a/components/strings/components_strings_my.xtb b/components/strings/components_strings_my.xtb
index 738ec0b..47e81299e 100644
--- a/components/strings/components_strings_my.xtb
+++ b/components/strings/components_strings_my.xtb
@@ -485,6 +485,7 @@
 <translation id="2215963164070968490">ခွေးများ</translation>
 <translation id="2218879909401188352"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> ရှိ လက်ရှိတိုက်ခိုက်သူများသည် သင့်စက်ပစ္စည်းကို ပျက်စီးစေနိုင်သည့် အန္တရာယ်ရှိသောအက်ပ်များ ထည့်သွင်းခြင်း၊ ဖုန်းခငွေပိုမိုကုန်ကျစေခြင်း သို့မဟုတ် သင်၏ ကိုယ်ရေးကိုယ်တာ အချက်အလက်များကို ခိုးယူခြင်းတို့ ပြုလုပ်နိုင်ပါသည်။ <ph name="BEGIN_LEARN_MORE_LINK" />ပိုမိုလေ့လာရန်<ph name="END_LEARN_MORE_LINK" /></translation>
 <translation id="2219658597883514593">ရှင်းလင်းပို့ချချက် ပြန်စရန်</translation>
+<translation id="2219735899272417925">စက်ကို ပြင်ဆင်သတ်မှတ်ရန် လိုအပ်သည်</translation>
 <translation id="2224337661447660594">အင်တာနက် မရှိပါ</translation>
 <translation id="2230458221926704099">သင့်ချိတ်ဆက်မှုအား <ph name="BEGIN_LINK" />ပြဿနာအဖြေရှာသည့် အက်ပ်<ph name="END_LINK" /> ကိုအသုံးပြုပြီး ဖြေရှင်းပါ</translation>
 <translation id="2239100178324503013">ယခုပို့ရန်</translation>
diff --git a/components/strings/components_strings_pt-PT.xtb b/components/strings/components_strings_pt-PT.xtb
index 7fd46cf..f36e95ee3 100644
--- a/components/strings/components_strings_pt-PT.xtb
+++ b/components/strings/components_strings_pt-PT.xtb
@@ -484,6 +484,7 @@
 <translation id="2215963164070968490">Cães</translation>
 <translation id="2218879909401188352">Os utilizadores mal-intencionados que se encontram em <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> podem instalar aplicações perigosas que danificam o dispositivo, adicionam cobranças ocultas à fatura de dados móveis ou roubam as suas informações pessoais. <ph name="BEGIN_LEARN_MORE_LINK" />Saiba mais<ph name="END_LEARN_MORE_LINK" /></translation>
 <translation id="2219658597883514593">Reiniciar tutorial</translation>
+<translation id="2219735899272417925">É necessário repor o dispositivo</translation>
 <translation id="2224337661447660594">Sem Internet</translation>
 <translation id="2230458221926704099">Utilize a <ph name="BEGIN_LINK" />aplicação de diagnóstico<ph name="END_LINK" /> para corrigir a ligação</translation>
 <translation id="2239100178324503013">Enviar agora</translation>
diff --git a/components/strings/components_strings_zh-HK.xtb b/components/strings/components_strings_zh-HK.xtb
index dd65a963..6225f6f5 100644
--- a/components/strings/components_strings_zh-HK.xtb
+++ b/components/strings/components_strings_zh-HK.xtb
@@ -480,6 +480,7 @@
 <translation id="2215963164070968490">狗</translation>
 <translation id="2218879909401188352">目前在 <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> 上的攻擊者可能會安裝危險的應用程式來損害您的裝置、暗中加入隱藏的流動服務費用,或竊取您的個人資料。<ph name="BEGIN_LEARN_MORE_LINK" />瞭解詳情<ph name="END_LEARN_MORE_LINK" /></translation>
 <translation id="2219658597883514593">重新啟動教學課程</translation>
+<translation id="2219735899272417925">必須重設裝置</translation>
 <translation id="2224337661447660594">沒有互聯網</translation>
 <translation id="2230458221926704099">請使用<ph name="BEGIN_LINK" />診斷應用程式<ph name="END_LINK" />修正連線問題</translation>
 <translation id="2239100178324503013">立即傳送</translation>
diff --git a/components/url_formatter/spoof_checks/idn_spoof_checker.cc b/components/url_formatter/spoof_checks/idn_spoof_checker.cc
index e5b11df..bbd09a1 100644
--- a/components/url_formatter/spoof_checks/idn_spoof_checker.cc
+++ b/components/url_formatter/spoof_checks/idn_spoof_checker.cc
@@ -317,10 +317,12 @@
 
   // These characters are, or look like, digits. A domain label entirely made of
   // digit-lookalikes or digits is blocked.
+  // IMPORTANT: When you add a new character here, make sure to add it to
+  // extra_confusable_mapper_ in skeleton_generator.cc too.
   digits_ = icu::UnicodeSet(UNICODE_STRING_SIMPLE("[0-9]"), status);
   digits_.freeze();
   digit_lookalikes_ = icu::UnicodeSet(
-      icu::UnicodeString::fromUTF8("[θ२২੨੨૨೩೭շзҙӡउওਤ੩૩౩ဒვპੜ੫丩ㄐճ৪੪୫૭୨౨]"),
+      icu::UnicodeString::fromUTF8("[θ२২੨੨૨೩೭շзҙӡउওਤ੩૩౩ဒვპੜკ੫丩ㄐճ৪੪୫૭୨౨]"),
       status);
   digit_lookalikes_.freeze();
 
@@ -417,6 +419,7 @@
       }
     }
     // Disallow domains that contain only numbers and number-spoofs.
+    // This check is reached if domain characters come from single script.
     if (IsDigitLookalike(label_string))
       return Result::kDigitLookalikes;
 
@@ -424,6 +427,10 @@
   }
 
   // Disallow domains that contain only numbers and number-spoofs.
+  // This check is reached if domain characters are from different scripts.
+  // This is generally rare. An example case when it would return true is when
+  // the domain contains Latin + Japanese characters that are also digit
+  // lookalikes.
   if (IsDigitLookalike(label_string))
     return Result::kDigitLookalikes;
 
diff --git a/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc b/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
index a26749c..274cff9b 100644
--- a/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
+++ b/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
@@ -1079,6 +1079,22 @@
     // not a top domain. Should not be decoded to unicode.
     {"xn--xample-9ua.test.xn--nt-bja", u"\u00e9xample.test.n\u00e9t", kUnsafe},
 
+    // Digit lookalike check of 16კ.com with character “კ” (U+10D9)
+    // Test case for https://crbug.com/1156531
+    {"xn--16-1ik.com", u"16\u10d9.com", kUnsafe},
+
+    // Skeleton generator check of officeკ65.com with character “კ” (U+10D9)
+    // Test case for https://crbug.com/1156531
+    {"xn--office65-l04a.com", u"office\u10d965.com", kUnsafe},
+
+    // Digit lookalike check of 16ੜ.com with character “ੜ” (U+0A5C)
+    // Test case for https://crbug.com/1156531 (missed skeleton map)
+    {"xn--16-ogg.com", u"16\u0a5c.com", kUnsafe},
+
+    // Skeleton generator check of officeੜ65.com with character “ੜ” (U+0A5C)
+    // Test case for https://crbug.com/1156531 (missed skeleton map)
+    {"xn--office65-hts.com", u"office\u0a5c65.com", kUnsafe},
+
     // New test cases go ↑↑ above.
 
     // /!\ WARNING: You MUST use tools/security/idn_test_case_generator.py to
@@ -1178,7 +1194,11 @@
       {u"łest.net", "test.net"},
       {u"łesł.net", "test.net"},
       // Test case for https://crbug.com/1207187
-      {u"စ2.com", "o2.com"}};
+      {u"စ2.com", "o2.com"},
+      // Test case for https://crbug.com/1156531
+      {u"კ9.com", "39.com"},
+      // Test case for https://crbug.com/1156531 (missed skeleton map)
+      {u"ੜ9.com", "39.com"}};
   for (const TestCase& test_case : kTestCases) {
     const TopDomainEntry entry =
         IDNSpoofChecker().GetSimilarTopDomain(test_case.hostname);
diff --git a/components/url_formatter/spoof_checks/skeleton_generator.cc b/components/url_formatter/spoof_checks/skeleton_generator.cc
index 8f04ea15..3ba02470 100644
--- a/components/url_formatter/spoof_checks/skeleton_generator.cc
+++ b/components/url_formatter/spoof_checks/skeleton_generator.cc
@@ -76,7 +76,7 @@
   lgc_letters_n_ascii_.freeze();
 
   // Supplement the Unicode confusable list by the following mapping.
-  // NOTE: Adding a digit-lookalike? Add it to digit_lookalikes_ in
+  // IMPORTANT: Adding a digit-lookalike? Add it to digit_lookalikes_ in
   // idn_spoof_checker.cc, too.
   //   - {U+00E6 (æ), U+04D5 (ӕ)}  => "ae"
   //   - {U+03FC (ϼ), U+048F (ҏ)} => p
@@ -111,7 +111,7 @@
   //      U+0ce9 (೩), U+0ced (೭), U+0577 (շ)} => 2,
   //   - {U+0437 (з), U+0499 (ҙ), U+04E1 (ӡ), U+0909 (उ), U+0993 (ও),
   //      U+0A24 (ਤ), U+0A69 (੩), U+0AE9 (૩), U+0C69 (౩),
-  //      U+1012 (ဒ), U+10D5 (ვ), U+10DE (პ)} => 3
+  //      U+1012 (ဒ), U+10D5 (ვ), U+10DE (პ), U+0A5C (ੜ), U+10D9 (კ)} => 3
   //   - {U+0A6B (੫), U+4E29 (丩), U+3110 (ㄐ)} => 4,
   //   - U+0573 (ճ) => 6
   //   - {U+09EA (৪), U+0A6A (੪), U+0b6b (୫)} => 8,
@@ -134,7 +134,7 @@
               "[บບ] > u;"
               "[θ] > 0;"
               "[२২੨੨૨೩೭շ] > 2;"
-              "[зҙӡउওਤ੩૩౩ဒვპ] > 3;"
+              "[зҙӡउওਤ੩૩౩ဒვპੜკ] > 3;"
               "[੫丩ㄐ] > 4;"
               "[ճ] > 6;"
               "[৪੪୫] > 8;"
diff --git a/content/public/test/test_web_ui.cc b/content/public/test/test_web_ui.cc
index da65e09..c88a2bb 100644
--- a/content/public/test/test_web_ui.cc
+++ b/content/public/test/test_web_ui.cc
@@ -26,7 +26,7 @@
 }
 
 void TestWebUI::HandleReceivedMessage(const std::string& handler_name,
-                                      const base::ListValue* args) {
+                                      const base::Value::List& args) {
   const auto callbacks_map_it = message_callbacks_.find(handler_name);
   if (callbacks_map_it != message_callbacks_.end()) {
     // Create a copy of the callbacks before running them. Without this, it
@@ -34,23 +34,30 @@
     // handler during iteration of the vector, resulting in undefined behavior.
     std::vector<MessageCallback> callbacks_to_run = callbacks_map_it->second;
     for (auto& callback : callbacks_to_run)
-      callback.Run(args->GetList());
+      callback.Run(args);
     return;
   }
 
   const auto deprecated_callbacks_map_it =
       deprecated_message_callbacks_.find(handler_name);
   if (deprecated_callbacks_map_it != deprecated_message_callbacks_.end()) {
+    base::Value args_copy(args.Clone());
     // Create a copy of the callbacks before running them. Without this, it
     // could be possible for the callback's handler to register a new message
     // handler during iteration of the vector, resulting in undefined behavior.
     std::vector<DeprecatedMessageCallback> callbacks_to_run =
         deprecated_callbacks_map_it->second;
+    const base::ListValue& args_list = base::Value::AsListValue(args_copy);
     for (auto& callback : callbacks_to_run)
-      callback.Run(args);
+      callback.Run(&args_list);
   }
 }
 
+void TestWebUI::HandleReceivedMessage(const std::string& handler_name,
+                                      const base::ListValue* args) {
+  HandleReceivedMessage(handler_name, args->GetList());
+}
+
 WebContents* TestWebUI::GetWebContents() {
   return web_contents_;
 }
diff --git a/content/public/test/test_web_ui.h b/content/public/test/test_web_ui.h
index 3ae197e..df62984 100644
--- a/content/public/test/test_web_ui.h
+++ b/content/public/test/test_web_ui.h
@@ -30,6 +30,10 @@
 
   void ClearTrackedCalls();
   void HandleReceivedMessage(const std::string& handler_name,
+                             const base::Value::List& args);
+  // TODO(crbug.com/1187062): Remove this HandleReceivedMessage() variant and
+  // switch to the one above.
+  void HandleReceivedMessage(const std::string& handler_name,
                              const base::ListValue* args);
   void set_web_contents(WebContents* web_contents) {
     web_contents_ = web_contents;
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 8e3d2fe..3d492ed6 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -876,16 +876,6 @@
       mojo::PendingRemote<mojom::FrameHTMLSerializerHandler> handler_remote)
       override;
 
-  // IPC message handlers ------------------------------------------------------
-  //
-  // The documentation for these functions should be in
-  // content/common/*_messages.h for the message that the function is handling.
-  void OnShowContextMenu(const gfx::Point& location);
-  void OnMoveCaret(const gfx::Point& point);
-  void OnScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect);
-  void OnSelectRange(const gfx::Point& base, const gfx::Point& extent);
-  void OnSuppressFurtherDialogs();
-
   // Callback scheduled from SerializeAsMHTML for when writing serialized
   // MHTML to the handle has been completed in the file thread.
   void OnWriteMHTMLComplete(
diff --git a/extensions/browser/api/printer_provider/printer_provider_internal_api.cc b/extensions/browser/api/printer_provider/printer_provider_internal_api.cc
index edfeff8..38998f8 100644
--- a/extensions/browser/api/printer_provider/printer_provider_internal_api.cc
+++ b/extensions/browser/api/printer_provider/printer_provider_internal_api.cc
@@ -151,7 +151,6 @@
       internal_api::ReportPrinters::Params::Create(args()));
   EXTENSION_FUNCTION_VALIDATE(params.get());
 
-  base::ListValue printers;
   if (params->printers) {
     PrinterProviderInternalAPI::GetFactoryInstance()
         ->Get(browser_context())
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index cb6a735a..3770e92 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -803,12 +803,6 @@
       GLsizei n,
       const volatile GLuint* paint_cache_ids);
   void DoClearPaintCacheINTERNAL();
-
-  // Generates a DDL, if necessary, and compiles shaders requires to raster it.
-  // Returns false each time a shader needed to be compiled and the decoder
-  // should yield. Returns true once all shaders in the DDL have been compiled.
-  bool EnsureDDLReadyForRaster();
-
   void FlushAndSubmitIfNecessary(
       SkSurface* surface,
       std::unique_ptr<GrBackendSurfaceMutableState> TakeEndState,
diff --git a/ios/chrome/app/strings/resources/ios_strings_bn.xtb b/ios/chrome/app/strings/resources/ios_strings_bn.xtb
index 2657104..bc1de3bf4c 100644
--- a/ios/chrome/app/strings/resources/ios_strings_bn.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_bn.xtb
@@ -250,6 +250,7 @@
 এক্ষেত্রে প্রযোজ্য হলে, আপনার সার্চ ইতিহাস মোছার জন্য সার্চ ইঞ্জিনের নির্দেশাবলী দেখুন।</translation>
 <translation id="3080525922482950719">পরে বা অফলাইনে পড়ার জন্য আপনি পৃষ্ঠা সেভ করে রাখতে পারেন</translation>
 <translation id="3081338492074632642">আপনি যে পাসওয়ার্ডটি সেভ করছেন, সেটি <ph name="WEBSITE" />-এ আপনার দেওয়া পাসওয়ার্ডের সাথে মিলছে কিনা ভাল করে দেখে নিন</translation>
+<translation id="3103603146121354983">পাসওয়ার্ড অটোফিল করা</translation>
 <translation id="3112556859945124369">চিহ্নিত করুন…</translation>
 <translation id="3122484138405575719"><ph name="BEGIN_LINK" />আপনি কী সিঙ্ক করতে পারবেন তা দেখুন<ph name="END_LINK" /></translation>
 <translation id="3131206671572504478">সব ব্লক করুন</translation>
@@ -662,6 +663,7 @@
 
 প্রতিটি সাইটের জন্য অনন্য পাসওয়ার্ড ব্যবহার করার চেষ্টা করুন।</translation>
 <translation id="650279896687777322">আরও জানুন...</translation>
+<translation id="6510072653668207258">আমাকে পরে মনে করাবেন</translation>
 <translation id="651505212789431520">সিঙ্ক বাতিল করতে চান? যেকোনও সময় সেটিংস থেকে আপনি সিঙ্ক চালু করতে পারবেন।</translation>
 <translation id="6524918542306337007">'ছদ্মবেশী মোড' উপলভ্য নেই</translation>
 <translation id="6530992499366869131">আপনার পাসওয়ার্ড কোনও ডেটা নিরাপত্তা লঙ্ঘনের কারণে সর্বজনীনভাবে প্রকাশিত হলে তা এটি আপনাকে জানায়</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_bs.xtb b/ios/chrome/app/strings/resources/ios_strings_bs.xtb
index 6d0dceb4..5326795 100644
--- a/ios/chrome/app/strings/resources/ios_strings_bs.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_bs.xtb
@@ -250,7 +250,7 @@
 Ako je primjenjivo, pogledajte uputstva pretraživača da saznate kako izbrisati historiju pretraživanja.</translation>
 <translation id="3080525922482950719">Možete sačuvati stranice da ih čitate kasnije ili van mreže</translation>
 <translation id="3081338492074632642">Provjerite podudara li se lozinka koju želite sačuvati s lozinkom za web lokaciju <ph name="WEBSITE" /></translation>
-<translation id="3103603146121354983">Automatski unos zaporki</translation>
+<translation id="3103603146121354983">Automatsko popunjavanje lozinki</translation>
 <translation id="3112556859945124369">Označi…</translation>
 <translation id="3122484138405575719"><ph name="BEGIN_LINK" />Pogledajte šta možete sinhronizirati<ph name="END_LINK" /></translation>
 <translation id="3131206671572504478">Blokiraj sve</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_el.xtb b/ios/chrome/app/strings/resources/ios_strings_el.xtb
index 9c4b48c..7fb4768 100644
--- a/ios/chrome/app/strings/resources/ios_strings_el.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_el.xtb
@@ -250,6 +250,7 @@
 Ανατρέξτε στις οδηγίες της μηχανής αναζήτησης σχετικά με τη διαγραφή του ιστορικού αναζήτησής σας, εφόσον υπάρχουν.</translation>
 <translation id="3080525922482950719">Μπορείτε να αποθηκεύετε σελίδες για ανάγνωση αργότερα ή εκτός σύνδεσης.</translation>
 <translation id="3081338492074632642">Βεβαιωθείτε ότι ο κωδικός πρόσβασης που αποθηκεύετε αντιστοιχεί στον κωδικό πρόσβασης για το <ph name="WEBSITE" />.</translation>
+<translation id="3103603146121354983">Αυτόματη συμπλήρωση κωδικών πρόσβασης</translation>
 <translation id="3112556859945124369">Επισήμανση…</translation>
 <translation id="3122484138405575719"><ph name="BEGIN_LINK" />Δείτε τι μπορείτε να συγχρονίσετε<ph name="END_LINK" /></translation>
 <translation id="3131206671572504478">Αποκλεισμός όλων</translation>
@@ -662,6 +663,7 @@
 
 Προσπαθήστε να χρησιμοποιείτε έναν μοναδικό κωδικό πρόσβασης για κάθε ιστότοπο.</translation>
 <translation id="650279896687777322">Μάθετε περισσότερα...</translation>
+<translation id="6510072653668207258">Υπενθύμιση αργότερα</translation>
 <translation id="651505212789431520">Ακύρωση συγχρονισμού; Μπορείτε να ενεργοποιήσετε τον συγχρονισμό ανά πάσα στιγμή στις Ρυθμίσεις.</translation>
 <translation id="6524918542306337007">Η κατάσταση ανώνυμης περιήγησης δεν είναι διαθέσιμη</translation>
 <translation id="6530992499366869131">Σας προειδοποιεί σε περίπτωση που οι κωδικοί πρόσβασής σας αποκαλυφθούν στο πλαίσιο μιας παραβίασης δεδομένων</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_mn.xtb b/ios/chrome/app/strings/resources/ios_strings_mn.xtb
index 6143cfaf..6a192d9 100644
--- a/ios/chrome/app/strings/resources/ios_strings_mn.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_mn.xtb
@@ -250,6 +250,7 @@
 Хэрэв боломжтой бол хайлтын түүхээ устгахын тулд хайлтын системийн зааварчилгаагаа харна уу.</translation>
 <translation id="3080525922482950719">Та хуудаснуудыг дараа, эсвэл офлайнаар уншихаар хадгалж болно</translation>
 <translation id="3081338492074632642">Таны хадгалж буй нууц үг <ph name="WEBSITE" />-н нууц үгтэй тохирч байгаа эсэхийг шалгана уу</translation>
+<translation id="3103603146121354983">Автоматаар бөглөх нууц үгнүүд</translation>
 <translation id="3112556859945124369">Тэмдэглэх...</translation>
 <translation id="3122484138405575719"><ph name="BEGIN_LINK" />Та юу синк хийх боломжтойгоо хараарай<ph name="END_LINK" /></translation>
 <translation id="3131206671572504478">Бүх күүкийг блоклосон</translation>
@@ -660,6 +661,7 @@
 
 Сайт бүрд өвөрмөц нууц үг ашиглахыг хичээгээрэй.</translation>
 <translation id="650279896687777322">Нэмэлт мэдээлэл авах...</translation>
+<translation id="6510072653668207258">Надад дараа сануулна уу</translation>
 <translation id="651505212789431520">Синк хийхийг цуцлах уу? Та синкийг хүссэн үедээ Тохиргоонд асааж болно.</translation>
 <translation id="6524918542306337007">Нууцлалын горим боломжгүй байна</translation>
 <translation id="6530992499366869131">Таны нууц үг өгөгдлийн зөрчилд өртсөн тохиолдолд танд сануулах</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_mr.xtb b/ios/chrome/app/strings/resources/ios_strings_mr.xtb
index 8e1602a..d24d3fd 100644
--- a/ios/chrome/app/strings/resources/ios_strings_mr.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_mr.xtb
@@ -250,6 +250,7 @@
 लागू असल्यास, तुमचा शोध इतिहास हटवण्यासाठी, तुमच्या शोध इंजीनच्या सूचना पहा.</translation>
 <translation id="3080525922482950719">तुम्‍ही नंतर किंवा ऑफलाइन वाचण्यासाठी पेज सेव्‍ह करू शकता</translation>
 <translation id="3081338492074632642">तुम्ही सेव्ह करत असलेला पासवर्ड तुमच्या <ph name="WEBSITE" /> च्या पासवर्डशी जुळत असल्याची खात्री करा</translation>
+<translation id="3103603146121354983">पासवर्ड ऑटोफिल करा</translation>
 <translation id="3112556859945124369">चिन्हांकित करा…</translation>
 <translation id="3122484138405575719"><ph name="BEGIN_LINK" />तुम्ही काय सिंक करू शकता ते पहा<ph name="END_LINK" /></translation>
 <translation id="3131206671572504478">सर्व ब्लॉक करा</translation>
@@ -663,6 +664,7 @@
 
 प्रत्येक साइटसाठी युनिक पासवर्ड वापरण्याचा प्रयत्न करा.</translation>
 <translation id="650279896687777322">अधिक जाणून घ्या…</translation>
+<translation id="6510072653668207258">मला नंतर आठवण करून द्या</translation>
 <translation id="651505212789431520">सिंक रद्द करायचे का? तुम्ही सेटिंग्ज मध्ये कधीही सिंक करणे सुरू करू शकता.</translation>
 <translation id="6524918542306337007">गुप्त मोड उपलब्ध नाही</translation>
 <translation id="6530992499366869131">डेटा भंग यामध्ये पासवर्ड उघड झाल्यास, तुम्हाला चेतावणी देणे</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_pl.xtb b/ios/chrome/app/strings/resources/ios_strings_pl.xtb
index e078f9c..860b0b77 100644
--- a/ios/chrome/app/strings/resources/ios_strings_pl.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_pl.xtb
@@ -250,6 +250,7 @@
 Jeśli chcesz usunąć historię wyszukiwania, zapoznaj się z instrukcjami wyszukiwarki.</translation>
 <translation id="3080525922482950719">Możesz zapisać strony, by przeczytać je później lub offline</translation>
 <translation id="3081338492074632642">Upewnij się, że zapisujesz hasło do witryny <ph name="WEBSITE" />.</translation>
+<translation id="3103603146121354983">Automatycznie uzupełniaj hasła</translation>
 <translation id="3112556859945124369">Oznacz…</translation>
 <translation id="3122484138405575719"><ph name="BEGIN_LINK" />Zobacz, co możesz synchronizować<ph name="END_LINK" /></translation>
 <translation id="3131206671572504478">Blokuj wszystkie</translation>
@@ -659,6 +660,7 @@
 
 Postaraj się używać innego hasła w każdej witrynie.</translation>
 <translation id="650279896687777322">Więcej informacji…</translation>
+<translation id="6510072653668207258">Przypomnij mi później</translation>
 <translation id="651505212789431520">Anulować synchronizację? W każdej chwili możesz włączyć synchronizację w Ustawieniach.</translation>
 <translation id="6524918542306337007">Tryb incognito jest niedostępny</translation>
 <translation id="6530992499366869131">Ostrzegaj, jeśli wskutek naruszenia bezpieczeństwa danych doszło do ujawnienia haseł</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_pt-BR.xtb b/ios/chrome/app/strings/resources/ios_strings_pt-BR.xtb
index 5b01192..21d0edc5 100644
--- a/ios/chrome/app/strings/resources/ios_strings_pt-BR.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_pt-BR.xtb
@@ -250,6 +250,7 @@
 Veja as instruções do seu mecanismo de pesquisa para excluir o histórico de pesquisa, se aplicável.</translation>
 <translation id="3080525922482950719">Você pode salvar páginas para ler depois ou off-line</translation>
 <translation id="3081338492074632642">A senha que você está salvando precisa corresponder à usada em <ph name="WEBSITE" /></translation>
+<translation id="3103603146121354983">Preenchimento automático de senhas</translation>
 <translation id="3112556859945124369">Marcar...</translation>
 <translation id="3122484138405575719"><ph name="BEGIN_LINK" />Veja o que pode ser sincronizado<ph name="END_LINK" /></translation>
 <translation id="3131206671572504478">Bloquear tudo</translation>
@@ -661,6 +662,7 @@
 
 Tente usar uma senha exclusiva para cada site.</translation>
 <translation id="650279896687777322">Saiba mais…</translation>
+<translation id="6510072653668207258">Lembrar mais tarde</translation>
 <translation id="651505212789431520">Cancelar sincronização? É possível ativar esse recurso a qualquer momento nas configurações.</translation>
 <translation id="6524918542306337007">O modo de navegação anônima está indisponível</translation>
 <translation id="6530992499366869131">Avisar se as suas senhas forem expostas em uma violação de dados</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_pt-PT.xtb b/ios/chrome/app/strings/resources/ios_strings_pt-PT.xtb
index 6d1cb3c..0ade33e 100644
--- a/ios/chrome/app/strings/resources/ios_strings_pt-PT.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_pt-PT.xtb
@@ -250,6 +250,7 @@
 Se aplicável, consulte as instruções do motor de pesquisa para eliminar o histórico de pesquisas.</translation>
 <translation id="3080525922482950719">Pode guardar páginas para ler mais tarde ou offline.</translation>
 <translation id="3081338492074632642">Certifique-se de que a palavra-passe que está a guardar corresponde à sua palavra-passe para <ph name="WEBSITE" />.</translation>
+<translation id="3103603146121354983">Preencha palavras-passe automaticamente</translation>
 <translation id="3112556859945124369">Marcar…</translation>
 <translation id="3122484138405575719"><ph name="BEGIN_LINK" />Veja o que pode sincronizar<ph name="END_LINK" /></translation>
 <translation id="3131206671572504478">Bloquear tudo</translation>
@@ -661,6 +662,7 @@
 
 Experimente utilizar uma palavra-passe exclusiva para cada site.</translation>
 <translation id="650279896687777322">Saber mais…</translation>
+<translation id="6510072653668207258">Lembrar-me mais tarde</translation>
 <translation id="651505212789431520">Pretende cancelar a sincronização? Pode ativar a sincronização em qualquer altura nas Definições.</translation>
 <translation id="6524918542306337007">O Modo de navegação anónima está indisponível</translation>
 <translation id="6530992499366869131">Enviar-lhe um aviso se as palavras-passe forem expostas numa violação de dados</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_sk.xtb b/ios/chrome/app/strings/resources/ios_strings_sk.xtb
index a6e89dd..03f7c46 100644
--- a/ios/chrome/app/strings/resources/ios_strings_sk.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_sk.xtb
@@ -250,6 +250,7 @@
 Prečítajte si pokyny vyhľadávača, ako odstrániť históriu vyhľadávania (ak je to možné).</translation>
 <translation id="3080525922482950719">Stránky si môžete uložiť a prečítať neskôr či offline</translation>
 <translation id="3081338492074632642">Ukladané heslo sa musí zhodovať s tým, ktoré používate pre web <ph name="WEBSITE" />.</translation>
+<translation id="3103603146121354983">Automatické dopĺňanie hesiel</translation>
 <translation id="3112556859945124369">Označiť…</translation>
 <translation id="3122484138405575719"><ph name="BEGIN_LINK" />Čo môžete synchronizovať<ph name="END_LINK" /></translation>
 <translation id="3131206671572504478">Blokovať všetky</translation>
@@ -661,6 +662,7 @@
 
 Pre každý web skúste použiť jedinečné heslo.</translation>
 <translation id="650279896687777322">Ďalšie informácie…</translation>
+<translation id="6510072653668207258">Pripomenúť neskôr</translation>
 <translation id="651505212789431520">Chcete zrušiť synchronizáciu? Môžete ju kedykoľvek zapnúť v Nastaveniach.</translation>
 <translation id="6524918542306337007">Režim inkognito nie je k dispozícii</translation>
 <translation id="6530992499366869131">Upozorňovať pri prezradení hesiel v rámci porušenia ochrany údajov</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_te.xtb b/ios/chrome/app/strings/resources/ios_strings_te.xtb
index 16e7965..e99304f 100644
--- a/ios/chrome/app/strings/resources/ios_strings_te.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_te.xtb
@@ -250,6 +250,7 @@
 వర్తిస్తే, మీ సెర్చ్ హిస్టరీని తొలగించడానికి మీ సెర్చ్ ఇంజిన్ సూచనలను చూడండి.</translation>
 <translation id="3080525922482950719">తర్వాత చదవడానికి లేదా ఆఫ్‌లైన్‌లో చదవడానికి మీరు పేజీలను సేవ్ చేయవచ్చు</translation>
 <translation id="3081338492074632642">మీరు సేవ్ చేస్తున్న పాస్‌వర్డ్ మీ <ph name="WEBSITE" /> పాస్‌వర్డ్‌తో మ్యాచ్ అవుతుందని నిర్ధారించుకోండి</translation>
+<translation id="3103603146121354983">పాస్‌వర్డ్‌లను ఆటోఫిల్ చేయండి</translation>
 <translation id="3112556859945124369">గుర్తు పెట్టు…</translation>
 <translation id="3122484138405575719"><ph name="BEGIN_LINK" />మీరు వేటిని సింక్ చేయగలరో చూడండి<ph name="END_LINK" /></translation>
 <translation id="3131206671572504478">అన్నీ బ్లాక్ చేయి</translation>
@@ -661,6 +662,7 @@
 
 ప్రతి సైట్‌కు ఒక విభిన్నమైన పాస్‌వర్డ్‌ను ఉపయోగించడానికి ట్రై చేయండి.</translation>
 <translation id="650279896687777322">మరింత తెలుసుకోండి...</translation>
+<translation id="6510072653668207258">తర్వాత గుర్తు చేయండి</translation>
 <translation id="651505212789431520">సింక్‌ను రద్దు చేయాలా? సెట్టింగ్‌లలో ఎప్పుడైనా మీరు సింక్‌ను ఆన్ చేయవచ్చు.</translation>
 <translation id="6524918542306337007">అజ్ఞాత మోడ్ అందుబాటులో లేదు</translation>
 <translation id="6530992499366869131">మీరు ఉపయోగించే పాస్‌వర్డ్‌లు, ఏదైనా డేటా ఉల్లంఘనలో బహిర్గతమైతే మిమ్మల్ని హెచ్చరిస్తుంది</translation>
diff --git a/ios/chrome/browser/translate/BUILD.gn b/ios/chrome/browser/translate/BUILD.gn
index 6495676..6eaaac5 100644
--- a/ios/chrome/browser/translate/BUILD.gn
+++ b/ios/chrome/browser/translate/BUILD.gn
@@ -86,7 +86,7 @@
     "//base/test:test_support",
     "//components/language/core/browser",
     "//components/language/ios/browser",
-    "//components/translate/core/browser:test_support",
+    "//components/translate/core/browser",
     "//components/translate/core/common",
     "//components/translate/ios/browser",
     "//ios/chrome/browser",
diff --git a/ios/chrome/browser/translate/chrome_ios_translate_client.h b/ios/chrome/browser/translate/chrome_ios_translate_client.h
index e34f915..2363abf8 100644
--- a/ios/chrome/browser/translate/chrome_ios_translate_client.h
+++ b/ios/chrome/browser/translate/chrome_ios_translate_client.h
@@ -26,6 +26,7 @@
 namespace translate {
 class TranslatePrefs;
 class TranslateManager;
+class TranslateMetricsLogger;
 }  // namespace translate
 
 namespace web {
@@ -72,10 +73,27 @@
  private:
   ChromeIOSTranslateClient(web::WebState* web_state);
   friend class web::WebStateUserData<ChromeIOSTranslateClient>;
+  FRIEND_TEST_ALL_PREFIXES(ChromeIOSTranslateClientTest,
+                           NewMetricsOnPageLoadCommits);
+  FRIEND_TEST_ALL_PREFIXES(ChromeIOSTranslateClientTest,
+                           NoNewMetricsOnErrorPage);
+  FRIEND_TEST_ALL_PREFIXES(ChromeIOSTranslateClientTest,
+                           PageTranslationCorrectlyUpdatesMetrics);
 
   // web::WebStateObserver implementation.
+  void DidStartNavigation(web::WebState* web_state,
+                          web::NavigationContext* navigation_context) override;
+  void DidFinishNavigation(web::WebState* web_state,
+                           web::NavigationContext* navigation_context) override;
+  void WasShown(web::WebState* web_state) override;
+  void WasHidden(web::WebState* web_state) override;
   void WebStateDestroyed(web::WebState* web_state) override;
 
+  // Triggered when the foreground page is changed by a new navigation (in
+  // DidStartNavigation) or is permanently closed (in WebStateDestroyed),
+  // similar to PageLoadMetricsObserver::OnComplete.
+  void DidPageLoadComplete();
+
   // The WebState this instance is observing. Will be null after
   // WebStateDestroyed has been called.
   web::WebState* web_state_ = nullptr;
@@ -83,6 +101,9 @@
   std::unique_ptr<translate::TranslateManager> translate_manager_;
   translate::IOSTranslateDriver translate_driver_;
 
+  // Metrics recorder for page load events.
+  std::unique_ptr<translate::TranslateMetricsLogger> translate_metrics_logger_;
+
   WEB_STATE_USER_DATA_KEY_DECL();
 };
 
diff --git a/ios/chrome/browser/translate/chrome_ios_translate_client.mm b/ios/chrome/browser/translate/chrome_ios_translate_client.mm
index cac593a..16ecb22 100644
--- a/ios/chrome/browser/translate/chrome_ios_translate_client.mm
+++ b/ios/chrome/browser/translate/chrome_ios_translate_client.mm
@@ -19,6 +19,7 @@
 #include "components/translate/core/browser/page_translated_details.h"
 #include "components/translate/core/browser/translate_infobar_delegate.h"
 #include "components/translate/core/browser/translate_manager.h"
+#include "components/translate/core/browser/translate_metrics_logger_impl.h"
 #include "components/translate/core/browser/translate_step.h"
 #include "components/translate/core/common/language_detection_details.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
@@ -32,6 +33,7 @@
 #include "ios/chrome/browser/translate/translate_service_ios.h"
 #include "ios/chrome/grit/ios_theme_resources.h"
 #include "ios/web/public/browser_state.h"
+#include "ios/web/public/navigation/navigation_context.h"
 #import "ios/web/public/web_state.h"
 #include "third_party/metrics_proto/translate_event.pb.h"
 #include "url/gurl.h"
@@ -154,15 +156,64 @@
   return false;
 }
 
+void ChromeIOSTranslateClient::DidStartNavigation(
+    web::WebState* web_state,
+    web::NavigationContext* navigation_context) {
+  if (navigation_context->IsSameDocument())
+    return;
+
+  DidPageLoadComplete();
+  // Lifetime of TranslateMetricsLogger should be each page load. So, we need to
+  // detect the page load completion, i.e. the tab was closed, new navigation
+  // replaced the page load, etc, and clear the logger.
+  translate_metrics_logger_ =
+      std::make_unique<translate::TranslateMetricsLoggerImpl>(
+          translate_manager_->GetWeakPtr());
+  translate_metrics_logger_->OnPageLoadStart(web_state->IsVisible());
+}
+
+void ChromeIOSTranslateClient::DidFinishNavigation(
+    web::WebState* web_state,
+    web::NavigationContext* navigation_context) {
+  if (navigation_context->GetError()) {
+    translate_metrics_logger_.reset();
+    return;
+  }
+
+  if (!navigation_context->IsSameDocument() && translate_metrics_logger_) {
+    translate_metrics_logger_->SetUkmSourceId(
+        translate_driver_.GetUkmSourceId());
+  }
+}
+
+void ChromeIOSTranslateClient::WasShown(web::WebState* web_state) {
+  if (translate_metrics_logger_)
+    translate_metrics_logger_->OnForegroundChange(true);
+};
+
+void ChromeIOSTranslateClient::WasHidden(web::WebState* web_state) {
+  if (translate_metrics_logger_)
+    translate_metrics_logger_->OnForegroundChange(false);
+};
+
 void ChromeIOSTranslateClient::WebStateDestroyed(web::WebState* web_state) {
   DCHECK_EQ(web_state_, web_state);
   web_state_->RemoveObserver(this);
   web_state_ = nullptr;
 
+  DidPageLoadComplete();
+
   // Translation process can be interrupted.
   // Destroying the TranslateManager now guarantees that it never has to deal
   // with nullptr WebState.
   translate_manager_.reset();
 }
 
+void ChromeIOSTranslateClient::DidPageLoadComplete() {
+  if (translate_metrics_logger_) {
+    translate_metrics_logger_->RecordMetrics(true);
+    translate_metrics_logger_.reset();
+  }
+}
+
 WEB_STATE_USER_DATA_KEY_IMPL(ChromeIOSTranslateClient)
diff --git a/ios/chrome/browser/translate/chrome_ios_translate_client_unittest.mm b/ios/chrome/browser/translate/chrome_ios_translate_client_unittest.mm
index 00fa7e7..5bafcb1 100644
--- a/ios/chrome/browser/translate/chrome_ios_translate_client_unittest.mm
+++ b/ios/chrome/browser/translate/chrome_ios_translate_client_unittest.mm
@@ -3,13 +3,15 @@
 // found in the LICENSE file.
 
 #include "ios/chrome/browser/translate/chrome_ios_translate_client.h"
+#import "base/metrics/metrics_hashes.h"
 #import "base/test/metrics/histogram_tester.h"
 #import "base/test/scoped_feature_list.h"
 #import "base/test/task_environment.h"
 #import "components/language/ios/browser/ios_language_detection_tab_helper.h"
+#import "components/translate/core/browser/translate_metrics_logger.h"
 #import "components/translate/core/common/translate_util.h"
 #import "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
-#import "ios/chrome/browser/infobars/infobar_manager_impl.h"
+#include "ios/chrome/browser/infobars/infobar_manager_impl.h"
 #import "ios/chrome/browser/language/language_model_manager_factory.h"
 #import "ios/chrome/browser/optimization_guide/optimization_guide_service.h"
 #import "ios/chrome/browser/optimization_guide/optimization_guide_service_factory.h"
@@ -20,6 +22,7 @@
 #import "ios/web/public/test/fakes/fake_navigation_manager.h"
 #import "ios/web/public/test/fakes/fake_web_state.h"
 #import "testing/platform_test.h"
+#import "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -64,3 +67,76 @@
                                     /*triggered_from_menu=*/false);
   EXPECT_EQ(1U, InfoBarManagerImpl::FromWebState(&web_state_)->infobar_count());
 }
+
+TEST_F(ChromeIOSTranslateClientTest, NewMetricsOnPageLoadCommits) {
+  ChromeIOSTranslateClient* translate_client =
+      ChromeIOSTranslateClient::FromWebState(&web_state_);
+
+  web::FakeNavigationContext context;
+  translate_client->DidStartNavigation(&web_state_, &context);
+  translate_client->DidFinishNavigation(&web_state_, &context);
+  base::RunLoop().RunUntilIdle();
+  histogram_tester_.ExpectTotalCount("Translate.PageLoad.NumTranslations", 0);
+
+  // Navigate to new URL within same tab (web state).
+  translate_client->DidStartNavigation(&web_state_, &context);
+  translate_client->DidFinishNavigation(&web_state_, &context);
+  base::RunLoop().RunUntilIdle();
+  histogram_tester_.ExpectUniqueSample("Translate.PageLoad.NumTranslations", 0,
+                                       1);
+
+  // Close tab (web state).
+  translate_client->WebStateDestroyed(&web_state_);
+  histogram_tester_.ExpectUniqueSample("Translate.PageLoad.NumTranslations", 0,
+                                       2);
+}
+
+TEST_F(ChromeIOSTranslateClientTest, NoNewMetricsOnErrorPage) {
+  ChromeIOSTranslateClient* translate_client =
+      ChromeIOSTranslateClient::FromWebState(&web_state_);
+
+  web::FakeNavigationContext context;
+  translate_client->DidStartNavigation(&web_state_, &context);  // needed?
+  context.SetError([NSError
+      errorWithDomain:@"commm"
+                 code:200
+             userInfo:@{@"Error reason" : @"Invalid Input"}]);
+  EXPECT_TRUE(context.GetError());
+  translate_client->DidFinishNavigation(&web_state_, &context);
+  translate_client->WebStateDestroyed(&web_state_);
+
+  histogram_tester_.ExpectTotalCount("Translate.PageLoad.NumTranslations", 0);
+}
+
+TEST_F(ChromeIOSTranslateClientTest, PageTranslationCorrectlyUpdatesMetrics) {
+  ChromeIOSTranslateClient* translate_client =
+      ChromeIOSTranslateClient::FromWebState(&web_state_);
+
+  histogram_tester_.ExpectTotalCount("Translate.PageLoad.InitialSourceLanguage",
+                                     0);
+  histogram_tester_.ExpectTotalCount("Translate.PageLoad.FinalTargetLanguage",
+                                     0);
+  histogram_tester_.ExpectTotalCount("Translate.PageLoad.NumTranslations", 0);
+
+  web::FakeNavigationContext context;
+  translate_client->DidStartNavigation(&web_state_, &context);
+  translate_client->DidFinishNavigation(&web_state_, &context);
+  translate_client->translate_metrics_logger_->LogInitialSourceLanguage(
+      "en", /*is_in_users_content_language=*/true);
+  translate_client->translate_metrics_logger_->LogTargetLanguage(
+      "ko", /*target_language_origin=*/translate::TranslateBrowserMetrics::
+          TargetLanguageOrigin::kUninitialized);
+  translate_client->translate_metrics_logger_->LogTranslationStarted(
+      translate::TranslationType::kUninitialized);
+  translate_client->translate_metrics_logger_->LogTranslationFinished(
+      true, translate::TranslateErrors::NONE);
+  translate_client->WebStateDestroyed(&web_state_);
+
+  histogram_tester_.ExpectUniqueSample(
+      "Translate.PageLoad.InitialSourceLanguage", base::HashMetricName("en"),
+      1);
+  histogram_tester_.ExpectUniqueSample("Translate.PageLoad.FinalTargetLanguage",
+                                       base::HashMetricName("ko"), 1);
+  histogram_tester_.ExpectUniqueSample("Translate.PageLoad.NumTranslations", 1,
+                                       1);
+}
diff --git a/ios/chrome/browser/web/web_performance_metrics/web_performance_metrics_java_script_feature.mm b/ios/chrome/browser/web/web_performance_metrics/web_performance_metrics_java_script_feature.mm
index 025a40d9a2..2afa580 100644
--- a/ios/chrome/browser/web/web_performance_metrics/web_performance_metrics_java_script_feature.mm
+++ b/ios/chrome/browser/web/web_performance_metrics/web_performance_metrics_java_script_feature.mm
@@ -122,7 +122,7 @@
   WebPerformanceMetricsTabHelper* tab_helper =
       WebPerformanceMetricsTabHelper::FromWebState(web_state);
 
-  if (!tab_helper) {
+  if (!tab_helper || tab_helper->HasBeenHiddenSinceNavigationStarted()) {
     return;
   }
 
@@ -195,7 +195,7 @@
   WebPerformanceMetricsTabHelper* tab_helper =
       WebPerformanceMetricsTabHelper::FromWebState(web_state);
 
-  if (!tab_helper) {
+  if (!tab_helper || tab_helper->HasBeenHiddenSinceNavigationStarted()) {
     return;
   }
 
diff --git a/ios/chrome/browser/web/web_performance_metrics/web_performance_metrics_tab_helper.h b/ios/chrome/browser/web/web_performance_metrics/web_performance_metrics_tab_helper.h
index e1a1752..1a6ce80 100644
--- a/ios/chrome/browser/web/web_performance_metrics/web_performance_metrics_tab_helper.h
+++ b/ios/chrome/browser/web/web_performance_metrics/web_performance_metrics_tab_helper.h
@@ -42,6 +42,10 @@
   // returns |true| otherwise it returns |false|
   bool GetFirstInputDelayLoggingStatus() const;
 
+  // Returns whether the WebState has been hidden at any point since the start
+  // of the most recent navigation.
+  bool HasBeenHiddenSinceNavigationStarted() const;
+
   // Sets the boolean variable that indicates whether the First Input Delay
   // has been logged in UMA for the current web page.
   void SetFirstInputDelayLoggingStatus(bool first_input_delay_logging_status);
@@ -56,6 +60,7 @@
 
   void DidStartNavigation(web::WebState* web_state,
                           web::NavigationContext* navigation_context) override;
+  void WasHidden(web::WebState* web_state) override;
 
   // Manages the tab helper's connection to the WebState
   base::ScopedObservation<web::WebState, web::WebStateObserver>
@@ -70,7 +75,11 @@
   // current web page
   bool first_input_delay_has_been_logged = false;
 
+  // Stores whether the WebState has been hidden at any point since the most
+  // recent navigation started.
+  bool has_been_hidden_since_navigation_started_ = false;
+
   WEB_STATE_USER_DATA_KEY_DECL();
 };
 
-#endif  // IOS_CHROME_BROWSER_WEB_WEB_PERFORMANCE_METRICS_WEB_PERFORMANCE_METRICS_TAB_HELPER_H_
\ No newline at end of file
+#endif  // IOS_CHROME_BROWSER_WEB_WEB_PERFORMANCE_METRICS_WEB_PERFORMANCE_METRICS_TAB_HELPER_H_
diff --git a/ios/chrome/browser/web/web_performance_metrics/web_performance_metrics_tab_helper.mm b/ios/chrome/browser/web/web_performance_metrics/web_performance_metrics_tab_helper.mm
index d9e7ab7..a9474f20 100644
--- a/ios/chrome/browser/web/web_performance_metrics/web_performance_metrics_tab_helper.mm
+++ b/ios/chrome/browser/web/web_performance_metrics/web_performance_metrics_tab_helper.mm
@@ -20,6 +20,11 @@
     web::NavigationContext* navigation_context) {
   SetAggregateAbsoluteFirstContentfulPaint(std::numeric_limits<double>::max());
   SetFirstInputDelayLoggingStatus(false);
+  has_been_hidden_since_navigation_started_ = !web_state->IsVisible();
+}
+
+void WebPerformanceMetricsTabHelper::WasHidden(web::WebState* web_state) {
+  has_been_hidden_since_navigation_started_ = true;
 }
 
 void WebPerformanceMetricsTabHelper::WebStateDestroyed(
@@ -42,9 +47,14 @@
   return first_input_delay_has_been_logged;
 }
 
+bool WebPerformanceMetricsTabHelper::HasBeenHiddenSinceNavigationStarted()
+    const {
+  return has_been_hidden_since_navigation_started_;
+}
+
 void WebPerformanceMetricsTabHelper::SetFirstInputDelayLoggingStatus(
     bool first_input_delay_logging_status) {
   first_input_delay_has_been_logged = first_input_delay_logging_status;
 }
 
-WEB_STATE_USER_DATA_KEY_IMPL(WebPerformanceMetricsTabHelper)
\ No newline at end of file
+WEB_STATE_USER_DATA_KEY_IMPL(WebPerformanceMetricsTabHelper)
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
index ce7b03af..d73c1e7 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-6dedb3e74f8ffc9430c3540089736fa6968cfa2f
\ No newline at end of file
+ab44cf1ff98006f57b4920cf2616f895c18f4c4e
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
index 1e3ea42..fe1738c7 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-24091cb273ec8775a2d6f35fd4ad85e1a2acbc9a
\ No newline at end of file
+1c8433ff373a896dbb1399f86340f2630fcd7a8d
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
index 95f9d1a9..26669b47 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-3313c844ef1b6ea25b609180bb52b7d16874de08
\ No newline at end of file
+6186a9f909bbc6bf3bc44d4bf9e6f1cf290905f1
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
index 9c00720..95938731 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-d3d718661c066491dd6975301600ae9ec930d35b
\ No newline at end of file
+ac36ebce7483ed4434dd181188531c76b0d360e0
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
index 4654599..9c36140 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-553d0de85469519c7d0b5beb54dfdc53184ddfbe
\ No newline at end of file
+19ca25ffd0ebc82035ded6f73162c2a643fdcd70
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
index 0c7bbdf..e0ac15f5 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-d3b854cd9f60a6801dc858a6faf04d485b95077d
\ No newline at end of file
+a4a6c0684095ee00f7e36863fe2abdea5f60f8f2
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
index 9294f50..e2b4620 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-9806e83e47abc8cbaa7d3daf8c0f220041b58698
\ No newline at end of file
+f6f4023250bfe97b0f858304197dad37a433f735
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
index f5e7c60f..9ebcc2f2 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-1df8de7c044505ccadfd044cb3a6e426fe25d129
\ No newline at end of file
+c173b14b0a89a9bc9db6cbb407880308244045b9
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
index db4f783..bbd9d88 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-f1fa0556e078d5c6b0117c44e53c7161b18a4eb4
\ No newline at end of file
+51f6ab9f56735daff38dd7a43a6b24a84498151c
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
index 89b7734..8f5033d 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-010ac88e03cb848472de012c67ba676dcbef1a4d
\ No newline at end of file
+a830df8732b7f202ddef3b36cec65c9017d45713
\ No newline at end of file
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index acbcf50..5c965b1e 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -8274,7 +8274,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.76"
+              "revision": "version:102.0.5005.88"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8359,7 +8359,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.27"
+              "revision": "version:103.0.5060.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8784,7 +8784,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.76"
+              "revision": "version:102.0.5005.88"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8869,7 +8869,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.27"
+              "revision": "version:103.0.5060.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 055d535..80a3ba06 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -46248,7 +46248,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.76"
+              "revision": "version:102.0.5005.88"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46333,7 +46333,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.27"
+              "revision": "version:103.0.5060.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46758,7 +46758,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.76"
+              "revision": "version:102.0.5005.88"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46843,7 +46843,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.27"
+              "revision": "version:103.0.5060.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47272,7 +47272,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.76"
+              "revision": "version:102.0.5005.88"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47357,7 +47357,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.27"
+              "revision": "version:103.0.5060.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47782,7 +47782,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.76"
+              "revision": "version:102.0.5005.88"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47867,7 +47867,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.27"
+              "revision": "version:103.0.5060.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48364,7 +48364,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.76"
+              "revision": "version:102.0.5005.88"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48449,7 +48449,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.27"
+              "revision": "version:103.0.5060.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48874,7 +48874,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.76"
+              "revision": "version:102.0.5005.88"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48959,7 +48959,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.27"
+              "revision": "version:103.0.5060.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49456,7 +49456,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.76"
+              "revision": "version:102.0.5005.88"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49541,7 +49541,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.27"
+              "revision": "version:103.0.5060.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49966,7 +49966,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.76"
+              "revision": "version:102.0.5005.88"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -50051,7 +50051,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.27"
+              "revision": "version:103.0.5060.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 9546fd0..5dda26c2 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -5769,21 +5769,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v101.0.4951.72/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.5005.75/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 101.0.4951.72",
+        "name": "interactive_ui_tests Lacros version skew testing ash 102.0.5005.75",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v101.0.4951.72",
-              "revision": "version:101.0.4951.72"
+              "location": "lacros_version_skew_tests_v102.0.5005.75",
+              "revision": "version:102.0.5005.75"
             }
           ],
           "dimension_sets": [
@@ -5796,7 +5796,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 101.0.4951.72"
+        "variant_id": "Lacros version skew testing ash 102.0.5005.75"
       },
       {
         "args": [
@@ -5865,21 +5865,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5087.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5088.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5087.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5088.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5087.0",
-              "revision": "version:104.0.5087.0"
+              "location": "lacros_version_skew_tests_v104.0.5088.0",
+              "revision": "version:104.0.5088.0"
             }
           ],
           "dimension_sets": [
@@ -5892,7 +5892,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5087.0"
+        "variant_id": "Lacros version skew testing ash 104.0.5088.0"
       },
       {
         "isolate_profile_data": true,
@@ -5937,21 +5937,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v101.0.4951.72/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.5005.75/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 101.0.4951.72",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 102.0.5005.75",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v101.0.4951.72",
-              "revision": "version:101.0.4951.72"
+              "location": "lacros_version_skew_tests_v102.0.5005.75",
+              "revision": "version:102.0.5005.75"
             }
           ],
           "dimension_sets": [
@@ -5963,7 +5963,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 101.0.4951.72"
+        "variant_id": "Lacros version skew testing ash 102.0.5005.75"
       },
       {
         "args": [
@@ -6030,21 +6030,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5087.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5088.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5087.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5088.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5087.0",
-              "revision": "version:104.0.5087.0"
+              "location": "lacros_version_skew_tests_v104.0.5088.0",
+              "revision": "version:104.0.5088.0"
             }
           ],
           "dimension_sets": [
@@ -6056,7 +6056,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5087.0"
+        "variant_id": "Lacros version skew testing ash 104.0.5088.0"
       },
       {
         "args": [
@@ -6083,21 +6083,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v101.0.4951.72/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.5005.75/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 101.0.4951.72",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 102.0.5005.75",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v101.0.4951.72",
-              "revision": "version:101.0.4951.72"
+              "location": "lacros_version_skew_tests_v102.0.5005.75",
+              "revision": "version:102.0.5005.75"
             }
           ],
           "dimension_sets": [
@@ -6109,7 +6109,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 101.0.4951.72"
+        "variant_id": "Lacros version skew testing ash 102.0.5005.75"
       },
       {
         "args": [
@@ -6176,21 +6176,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5087.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5088.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5087.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5088.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5087.0",
-              "revision": "version:104.0.5087.0"
+              "location": "lacros_version_skew_tests_v104.0.5088.0",
+              "revision": "version:104.0.5088.0"
             }
           ],
           "dimension_sets": [
@@ -6202,7 +6202,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 104.0.5087.0"
+        "variant_id": "Lacros version skew testing ash 104.0.5088.0"
       },
       {
         "isolate_profile_data": true,
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 82eb5e2..cf1a10c 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -87956,21 +87956,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v101.0.4951.72/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.5005.75/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 101.0.4951.72",
+        "name": "interactive_ui_tests Lacros version skew testing ash 102.0.5005.75",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v101.0.4951.72",
-              "revision": "version:101.0.4951.72"
+              "location": "lacros_version_skew_tests_v102.0.5005.75",
+              "revision": "version:102.0.5005.75"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -87978,7 +87978,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 101.0.4951.72"
+        "variant_id": "Lacros version skew testing ash 102.0.5005.75"
       },
       {
         "args": [
@@ -88037,21 +88037,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5087.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5088.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5087.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5088.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5087.0",
-              "revision": "version:104.0.5087.0"
+              "location": "lacros_version_skew_tests_v104.0.5088.0",
+              "revision": "version:104.0.5088.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -88059,7 +88059,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5087.0"
+        "variant_id": "Lacros version skew testing ash 104.0.5088.0"
       },
       {
         "isolate_profile_data": true,
@@ -88094,28 +88094,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v101.0.4951.72/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.5005.75/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 101.0.4951.72",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 102.0.5005.75",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v101.0.4951.72",
-              "revision": "version:101.0.4951.72"
+              "location": "lacros_version_skew_tests_v102.0.5005.75",
+              "revision": "version:102.0.5005.75"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 101.0.4951.72"
+        "variant_id": "Lacros version skew testing ash 102.0.5005.75"
       },
       {
         "args": [
@@ -88172,28 +88172,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5087.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5088.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5087.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5088.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5087.0",
-              "revision": "version:104.0.5087.0"
+              "location": "lacros_version_skew_tests_v104.0.5088.0",
+              "revision": "version:104.0.5088.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5087.0"
+        "variant_id": "Lacros version skew testing ash 104.0.5088.0"
       },
       {
         "args": [
@@ -88215,28 +88215,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v101.0.4951.72/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.5005.75/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 101.0.4951.72",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 102.0.5005.75",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v101.0.4951.72",
-              "revision": "version:101.0.4951.72"
+              "location": "lacros_version_skew_tests_v102.0.5005.75",
+              "revision": "version:102.0.5005.75"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 101.0.4951.72"
+        "variant_id": "Lacros version skew testing ash 102.0.5005.75"
       },
       {
         "args": [
@@ -88293,28 +88293,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5087.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5088.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5087.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5088.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5087.0",
-              "revision": "version:104.0.5087.0"
+              "location": "lacros_version_skew_tests_v104.0.5088.0",
+              "revision": "version:104.0.5088.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 104.0.5087.0"
+        "variant_id": "Lacros version skew testing ash 104.0.5088.0"
       },
       {
         "isolate_profile_data": true,
@@ -89556,20 +89556,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v101.0.4951.72/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.5005.75/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 101.0.4951.72",
+        "name": "interactive_ui_tests Lacros version skew testing ash 102.0.5005.75",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v101.0.4951.72",
-              "revision": "version:101.0.4951.72"
+              "location": "lacros_version_skew_tests_v102.0.5005.75",
+              "revision": "version:102.0.5005.75"
             }
           ],
           "dimension_sets": [
@@ -89583,7 +89583,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 101.0.4951.72"
+        "variant_id": "Lacros version skew testing ash 102.0.5005.75"
       },
       {
         "args": [
@@ -89652,20 +89652,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5087.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5088.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5087.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5088.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5087.0",
-              "revision": "version:104.0.5087.0"
+              "location": "lacros_version_skew_tests_v104.0.5088.0",
+              "revision": "version:104.0.5088.0"
             }
           ],
           "dimension_sets": [
@@ -89679,7 +89679,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5087.0"
+        "variant_id": "Lacros version skew testing ash 104.0.5088.0"
       },
       {
         "merge": {
@@ -89724,20 +89724,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v101.0.4951.72/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.5005.75/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 101.0.4951.72",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 102.0.5005.75",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v101.0.4951.72",
-              "revision": "version:101.0.4951.72"
+              "location": "lacros_version_skew_tests_v102.0.5005.75",
+              "revision": "version:102.0.5005.75"
             }
           ],
           "dimension_sets": [
@@ -89750,7 +89750,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 101.0.4951.72"
+        "variant_id": "Lacros version skew testing ash 102.0.5005.75"
       },
       {
         "args": [
@@ -89817,20 +89817,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5087.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5088.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5087.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5088.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5087.0",
-              "revision": "version:104.0.5087.0"
+              "location": "lacros_version_skew_tests_v104.0.5088.0",
+              "revision": "version:104.0.5088.0"
             }
           ],
           "dimension_sets": [
@@ -89843,7 +89843,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5087.0"
+        "variant_id": "Lacros version skew testing ash 104.0.5088.0"
       },
       {
         "args": [
@@ -89870,20 +89870,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v101.0.4951.72/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.5005.75/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 101.0.4951.72",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 102.0.5005.75",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v101.0.4951.72",
-              "revision": "version:101.0.4951.72"
+              "location": "lacros_version_skew_tests_v102.0.5005.75",
+              "revision": "version:102.0.5005.75"
             }
           ],
           "dimension_sets": [
@@ -89896,7 +89896,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 101.0.4951.72"
+        "variant_id": "Lacros version skew testing ash 102.0.5005.75"
       },
       {
         "args": [
@@ -89963,20 +89963,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5087.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5088.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5087.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5088.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5087.0",
-              "revision": "version:104.0.5087.0"
+              "location": "lacros_version_skew_tests_v104.0.5088.0",
+              "revision": "version:104.0.5088.0"
             }
           ],
           "dimension_sets": [
@@ -89989,7 +89989,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 104.0.5087.0"
+        "variant_id": "Lacros version skew testing ash 104.0.5088.0"
       },
       {
         "merge": {
@@ -91389,20 +91389,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v101.0.4951.72/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.5005.75/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 101.0.4951.72",
+        "name": "interactive_ui_tests Lacros version skew testing ash 102.0.5005.75",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v101.0.4951.72",
-              "revision": "version:101.0.4951.72"
+              "location": "lacros_version_skew_tests_v102.0.5005.75",
+              "revision": "version:102.0.5005.75"
             }
           ],
           "dimension_sets": [
@@ -91416,7 +91416,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 101.0.4951.72"
+        "variant_id": "Lacros version skew testing ash 102.0.5005.75"
       },
       {
         "args": [
@@ -91485,20 +91485,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5087.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5088.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5087.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5088.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5087.0",
-              "revision": "version:104.0.5087.0"
+              "location": "lacros_version_skew_tests_v104.0.5088.0",
+              "revision": "version:104.0.5088.0"
             }
           ],
           "dimension_sets": [
@@ -91512,7 +91512,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5087.0"
+        "variant_id": "Lacros version skew testing ash 104.0.5088.0"
       },
       {
         "merge": {
@@ -91557,20 +91557,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v101.0.4951.72/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.5005.75/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 101.0.4951.72",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 102.0.5005.75",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v101.0.4951.72",
-              "revision": "version:101.0.4951.72"
+              "location": "lacros_version_skew_tests_v102.0.5005.75",
+              "revision": "version:102.0.5005.75"
             }
           ],
           "dimension_sets": [
@@ -91583,7 +91583,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 101.0.4951.72"
+        "variant_id": "Lacros version skew testing ash 102.0.5005.75"
       },
       {
         "args": [
@@ -91650,20 +91650,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5087.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5088.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5087.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5088.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5087.0",
-              "revision": "version:104.0.5087.0"
+              "location": "lacros_version_skew_tests_v104.0.5088.0",
+              "revision": "version:104.0.5088.0"
             }
           ],
           "dimension_sets": [
@@ -91676,7 +91676,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5087.0"
+        "variant_id": "Lacros version skew testing ash 104.0.5088.0"
       },
       {
         "args": [
@@ -91703,20 +91703,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v101.0.4951.72/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.5005.75/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 101.0.4951.72",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 102.0.5005.75",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v101.0.4951.72",
-              "revision": "version:101.0.4951.72"
+              "location": "lacros_version_skew_tests_v102.0.5005.75",
+              "revision": "version:102.0.5005.75"
             }
           ],
           "dimension_sets": [
@@ -91729,7 +91729,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 101.0.4951.72"
+        "variant_id": "Lacros version skew testing ash 102.0.5005.75"
       },
       {
         "args": [
@@ -91796,20 +91796,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5087.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5088.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5087.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5088.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5087.0",
-              "revision": "version:104.0.5087.0"
+              "location": "lacros_version_skew_tests_v104.0.5088.0",
+              "revision": "version:104.0.5088.0"
             }
           ],
           "dimension_sets": [
@@ -91822,7 +91822,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 104.0.5087.0"
+        "variant_id": "Lacros version skew testing ash 104.0.5088.0"
       },
       {
         "merge": {
@@ -92464,20 +92464,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v101.0.4951.72/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.5005.75/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 101.0.4951.72",
+        "name": "interactive_ui_tests Lacros version skew testing ash 102.0.5005.75",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v101.0.4951.72",
-              "revision": "version:101.0.4951.72"
+              "location": "lacros_version_skew_tests_v102.0.5005.75",
+              "revision": "version:102.0.5005.75"
             }
           ],
           "dimension_sets": [
@@ -92490,7 +92490,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 101.0.4951.72"
+        "variant_id": "Lacros version skew testing ash 102.0.5005.75"
       },
       {
         "args": [
@@ -92557,20 +92557,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5087.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5088.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5087.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5088.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5087.0",
-              "revision": "version:104.0.5087.0"
+              "location": "lacros_version_skew_tests_v104.0.5088.0",
+              "revision": "version:104.0.5088.0"
             }
           ],
           "dimension_sets": [
@@ -92583,7 +92583,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5087.0"
+        "variant_id": "Lacros version skew testing ash 104.0.5088.0"
       }
     ]
   },
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index 607a71b0..8d934307 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -2057,6 +2057,11 @@
       }
     ]
   },
+  "Win Builder (dbg)": {
+    "additional_compile_targets": [
+      "all"
+    ]
+  },
   "Win x64 Builder": {
     "additional_compile_targets": [
       "pdf_fuzzers"
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json
index 7e886592..aa5bf20 100644
--- a/testing/buildbot/internal.chromeos.fyi.json
+++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1162,7 +1162,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R101-14588.123.0",
+        "cros_img": "octopus-release/R102-14695.85.0",
         "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_STABLE",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1207,7 +1207,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R101-14588.123.0",
+        "cros_img": "octopus-release/R102-14695.85.0",
         "name": "ozone_unittests OCTOPUS_RELEASE_STABLE",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1262,7 +1262,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R101-14588.123.0",
+        "cros_img": "strongbad-release/R102-14695.85.0",
         "name": "lacros_all_tast_tests STRONGBAD_RELEASE_STABLE",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1307,7 +1307,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R101-14588.123.0",
+        "cros_img": "strongbad-release/R102-14695.85.0",
         "name": "ozone_unittests STRONGBAD_RELEASE_STABLE",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1351,7 +1351,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R101-14588.123.0",
+        "cros_img": "strongbad-release/R102-14695.85.0",
         "name": "viz_unittests STRONGBAD_RELEASE_STABLE",
         "swarming": {},
         "test": "viz_unittests",
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index d319d40..c392bf6 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -22,15 +22,15 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5087.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5088.0/test_ash_chrome',
     ],
-    'identifier': 'Lacros version skew testing ash 104.0.5087.0',
+    'identifier': 'Lacros version skew testing ash 104.0.5088.0',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v104.0.5087.0',
-          'revision': 'version:104.0.5087.0',
+          'location': 'lacros_version_skew_tests_v104.0.5088.0',
+          'revision': 'version:104.0.5088.0',
         },
       ],
     },
@@ -67,15 +67,15 @@
   },
   'LACROS_VERSION_SKEW_STABLE': {
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v101.0.4951.72/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.5005.75/test_ash_chrome',
     ],
-    'identifier': 'Lacros version skew testing ash 101.0.4951.72',
+    'identifier': 'Lacros version skew testing ash 102.0.5005.75',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v101.0.4951.72',
-          'revision': 'version:101.0.4951.72',
+          'location': 'lacros_version_skew_tests_v102.0.5005.75',
+          'revision': 'version:102.0.5005.75',
         },
       ],
     },
@@ -479,7 +479,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.27'
+          'revision': 'version:103.0.5060.28'
         }
       ]
     }
@@ -503,7 +503,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M102',
-          'revision': 'version:102.0.5005.76'
+          'revision': 'version:102.0.5005.88'
         }
       ]
     }
@@ -623,7 +623,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.27'
+          'revision': 'version:103.0.5060.28'
         }
       ]
     }
@@ -647,7 +647,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M102',
-          'revision': 'version:102.0.5005.76'
+          'revision': 'version:102.0.5005.88'
         }
       ]
     }
@@ -767,7 +767,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.27'
+          'revision': 'version:103.0.5060.28'
         }
       ]
     }
@@ -791,7 +791,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M102',
-          'revision': 'version:102.0.5005.76'
+          'revision': 'version:102.0.5005.88'
         }
       ]
     }
@@ -1048,8 +1048,8 @@
   'CROS_OCTOPUS_RELEASE_STABLE': {
     'skylab': {
       'cros_board': 'octopus',
-      'cros_chrome_version': '101.0.4951.72',
-      'cros_img': 'octopus-release/R101-14588.123.0',
+      'cros_chrome_version': '102.0.5005.75',
+      'cros_img': 'octopus-release/R102-14695.85.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_RELEASE_STABLE',
@@ -1084,8 +1084,8 @@
   'CROS_STRONGBAD_RELEASE_STABLE': {
     'skylab': {
       'cros_board': 'strongbad',
-      'cros_chrome_version': '101.0.4951.72',
-      'cros_img': 'strongbad-release/R101-14588.123.0',
+      'cros_chrome_version': '102.0.5005.75',
+      'cros_img': 'strongbad-release/R102-14695.85.0',
     },
     'enabled': True,
     'identifier': 'STRONGBAD_RELEASE_STABLE',
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 6da23c0..470ffeb 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -5960,6 +5960,11 @@
           'scripts': 'chromium_win_scripts',
         },
       },
+      'Win Builder (dbg)': {
+        'additional_compile_targets': [
+          'all'
+        ],
+      },
       'Win x64 Builder': {
         'additional_compile_targets': [
           'pdf_fuzzers'
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 0a79b5c6..a87a0545 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -1472,6 +1472,9 @@
     "PrefetchFontLookupTables", base::FEATURE_DISABLED_BY_DEFAULT};
 #endif
 
+const base::Feature kPrecompileInlineScripts{"PrecompileInlineScripts",
+                                             base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kSimulateClickOnAXFocus {
   "SimulateClickOnAXFocus",
 #if BUILDFLAG(IS_WIN)
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index a5ee71e..c2a3d9f 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -766,6 +766,10 @@
 BLINK_COMMON_EXPORT extern const base::Feature kPrefetchFontLookupTables;
 #endif
 
+// If enabled, inline scripts will be stream compiled using a background HTML
+// scanner.
+BLINK_COMMON_EXPORT extern const base::Feature kPrecompileInlineScripts;
+
 // TODO(accessibility): This flag is set to accommodate JAWS on Windows so they
 // can adjust to us not simulating click events on a focus action. It should be
 // disabled by default (and removed) before 5/17/2023.
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
index 0ba66b7e..c915d812 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
@@ -46,7 +46,7 @@
 
 // ScriptDecoder decodes and hashes the script source on a worker thread, and
 // then forwards the data to the client on the loader thread.
-class ScriptStreamer::ScriptDecoder {
+class ResourceScriptStreamer::ScriptDecoder {
  public:
   ScriptDecoder(ResponseBodyLoaderClient* response_body_loader_client,
                 std::unique_ptr<TextResourceDecoder> decoder,
@@ -177,7 +177,7 @@
   scoped_refptr<base::SequencedTaskRunner> decoding_task_runner_;
 };
 
-void ScriptStreamer::ScriptDecoderDeleter::operator()(
+void ResourceScriptStreamer::ScriptDecoderDeleter::operator()(
     const ScriptDecoder* ptr) {
   if (ptr)
     ptr->Delete();
@@ -203,12 +203,12 @@
     DCHECK(!IsMainThread());
     CHECK(ready_to_run_.IsSet());
 
-    if (load_state_ != ScriptStreamer::LoadingState::kLoading) {
+    if (load_state_ != ResourceScriptStreamer::LoadingState::kLoading) {
       return 0;
     }
 
     if (cancelled_.IsSet()) {
-      SetFinished(ScriptStreamer::LoadingState::kCancelled);
+      SetFinished(ResourceScriptStreamer::LoadingState::kCancelled);
       return 0;
     }
 
@@ -286,13 +286,13 @@
           if (result != MOJO_RESULT_OK) {
             // If the producer handle was closed, then treat as EOF.
             CHECK_EQ(result, MOJO_RESULT_FAILED_PRECONDITION);
-            SetFinished(ScriptStreamer::LoadingState::kLoaded);
+            SetFinished(ResourceScriptStreamer::LoadingState::kLoaded);
             return 0;
           }
 
           // We were blocked, so check for cancelation again.
           if (cancelled_.IsSet()) {
-            SetFinished(ScriptStreamer::LoadingState::kCancelled);
+            SetFinished(ResourceScriptStreamer::LoadingState::kCancelled);
             return 0;
           }
 
@@ -302,12 +302,12 @@
 
         case MOJO_RESULT_FAILED_PRECONDITION:
           // If the producer handle was closed, then treat as EOF.
-          SetFinished(ScriptStreamer::LoadingState::kLoaded);
+          SetFinished(ResourceScriptStreamer::LoadingState::kLoaded);
           return 0;
 
         default:
           // Some other error occurred.
-          SetFinished(ScriptStreamer::LoadingState::kFailed);
+          SetFinished(ResourceScriptStreamer::LoadingState::kFailed);
           return 0;
       }
     }
@@ -315,13 +315,13 @@
 
   void DrainRemainingDataWithoutStreaming() {
     DCHECK(!IsMainThread());
-    if (load_state_ == ScriptStreamer::LoadingState::kLoading) {
+    if (load_state_ == ResourceScriptStreamer::LoadingState::kLoading) {
       // Keep reading data until we finish (returning 0). It won't be streaming
       // compiled any more, but it will continue being forwarded to the client.
       while (GetMoreData(nullptr) != 0) {
       }
     }
-    CHECK_NE(load_state_, ScriptStreamer::LoadingState::kLoading);
+    CHECK_NE(load_state_, ResourceScriptStreamer::LoadingState::kLoading);
   }
 
   void Cancel() {
@@ -329,16 +329,16 @@
     // The script is no longer needed by the upper layers. Stop streaming
     // it. The next time GetMoreData is called (or woken up), it will return
     // 0, which will be interpreted as EOS by V8 and the parsing will
-    // fail. ScriptStreamer::StreamingComplete will be called, and at that
-    // point we will release the references to SourceStream.
+    // fail. ResourceScriptStreamer::StreamingComplete will be called, and at
+    // that point we will release the references to SourceStream.
     cancelled_.Set();
   }
 
   void TakeDataAndPipeOnMainThread(
       ScriptResource* resource,
-      ScriptStreamer* streamer,
+      ResourceScriptStreamer* streamer,
       mojo::ScopedDataPipeConsumerHandle data_pipe,
-      ScriptStreamer::ScriptDecoder* script_decoder) {
+      ResourceScriptStreamer::ScriptDecoder* script_decoder) {
     DCHECK(IsMainThread());
     CHECK(data_pipe);
     CHECK(!ready_to_run_.IsSet());
@@ -374,18 +374,22 @@
     ready_to_run_.Set();
   }
 
-  ScriptStreamer::LoadingState LoadingState() const { return load_state_; }
+  ResourceScriptStreamer::LoadingState LoadingState() const {
+    return load_state_;
+  }
 
  private:
-  void SetFinished(ScriptStreamer::LoadingState state) { load_state_ = state; }
+  void SetFinished(ResourceScriptStreamer::LoadingState state) {
+    load_state_ = state;
+  }
 
   // TODO(leszeks): Make this a DCHECK-only flag.
   base::AtomicFlag ready_to_run_;
   base::AtomicFlag cancelled_;
 
   // Only used by background thread
-  ScriptStreamer::LoadingState load_state_ =
-      ScriptStreamer::LoadingState::kLoading;
+  ResourceScriptStreamer::LoadingState load_state_ =
+      ResourceScriptStreamer::LoadingState::kLoading;
 
   // The initial data that was already on the Resource, rather than being read
   // directly from the data pipe.
@@ -393,15 +397,15 @@
   size_t initial_data_len_ = 0;
 
   mojo::ScopedDataPipeConsumerHandle data_pipe_;
-  ScriptStreamer::ScriptDecoder* script_decoder_;
+  ResourceScriptStreamer::ScriptDecoder* script_decoder_;
 };
 
-std::tuple<ScriptStreamer*, ScriptStreamer::NotStreamingReason>
-ScriptStreamer::TakeFrom(ScriptResource* script_resource,
-                         mojom::blink::ScriptType expected_type) {
+std::tuple<ResourceScriptStreamer*, ScriptStreamer::NotStreamingReason>
+ResourceScriptStreamer::TakeFrom(ScriptResource* script_resource,
+                                 mojom::blink::ScriptType expected_type) {
   ScriptStreamer::NotStreamingReason not_streamed_reason =
       script_resource->NoStreamerReason();
-  ScriptStreamer* streamer = script_resource->TakeStreamer();
+  ResourceScriptStreamer* streamer = script_resource->TakeStreamer();
   if (streamer) {
     if (streamer->IsStreamingSuppressed()) {
       not_streamed_reason = streamer->StreamingSuppressedReason();
@@ -522,45 +526,46 @@
   return false;
 }
 
-bool ScriptStreamer::IsStreamingStarted() const {
+bool ResourceScriptStreamer::IsStreamingStarted() const {
   DCHECK(IsMainThread());
   return !!stream_;
 }
 
-bool ScriptStreamer::IsStreamingSuppressed() const {
+bool ResourceScriptStreamer::IsStreamingSuppressed() const {
   DCHECK(IsMainThread());
   return suppressed_reason_ != NotStreamingReason::kInvalid;
 }
 
-bool ScriptStreamer::IsLoaded() const {
+bool ResourceScriptStreamer::IsLoaded() const {
   DCHECK(IsMainThread());
   return loading_state_ != LoadingState::kLoading;
 }
 
-bool ScriptStreamer::CanStartStreaming() const {
+bool ResourceScriptStreamer::CanStartStreaming() const {
   DCHECK(IsMainThread());
   return !IsStreamingStarted() && !IsStreamingSuppressed();
 }
 
-bool ScriptStreamer::IsFinished() const {
+bool ResourceScriptStreamer::IsFinished() const {
   DCHECK(IsMainThread());
   // We are finished when we know that we won't start streaming later (either
   // because we are streaming already or streaming was suppressed).
   return IsLoaded() && !CanStartStreaming();
 }
 
-bool ScriptStreamer::IsClientDetached() const {
+bool ResourceScriptStreamer::IsClientDetached() const {
   DCHECK(IsMainThread());
   return !response_body_loader_client_;
 }
 
-void ScriptStreamer::StreamingCompleteOnBackgroundThread(LoadingState state) {
+void ResourceScriptStreamer::StreamingCompleteOnBackgroundThread(
+    LoadingState state) {
   DCHECK(!IsMainThread());
 
   // notifyFinished might already be called, or it might be called in the
   // future (if the parsing finishes earlier because of a parse error).
   script_decoder_->FinishDecode(
-      CrossThreadBindOnce(&ScriptStreamer::StreamingComplete,
+      CrossThreadBindOnce(&ResourceScriptStreamer::StreamingComplete,
                           WrapCrossThreadPersistent(this), state));
 
   // The task might be the only remaining reference to the ScriptStreamer, and
@@ -568,7 +573,7 @@
   // is ran, so we should not access the "this" object after posting the task.
 }
 
-void ScriptStreamer::Cancel() {
+void ResourceScriptStreamer::Cancel() {
   DCHECK(IsMainThread());
   // The upper layer doesn't need the script any more, but streaming might
   // still be ongoing. Tell SourceStream to try to cancel it whenever it gets
@@ -581,16 +586,16 @@
   CHECK(IsClientDetached());
 }
 
-void ScriptStreamer::SuppressStreaming(NotStreamingReason reason) {
+void ResourceScriptStreamer::SuppressStreaming(NotStreamingReason reason) {
   DCHECK(IsMainThread());
   CHECK_EQ(suppressed_reason_, NotStreamingReason::kInvalid);
   CHECK_NE(reason, NotStreamingReason::kInvalid);
   suppressed_reason_ = reason;
 }
 
-void ScriptStreamer::RunScriptStreamingTask(
+void ResourceScriptStreamer::RunScriptStreamingTask(
     std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask> task,
-    ScriptStreamer* streamer,
+    ResourceScriptStreamer* streamer,
     SourceStream* stream) {
   // TODO(leszeks): Add flow event data again
   TRACE_EVENT_BEGIN1(
@@ -636,7 +641,8 @@
       "v8.parseOnBackground2");
 }
 
-bool ScriptStreamer::HasEnoughDataForStreaming(size_t resource_buffer_size) {
+bool ResourceScriptStreamer::HasEnoughDataForStreaming(
+    size_t resource_buffer_size) {
   if (base::FeatureList::IsEnabled(features::kSmallScriptStreaming)) {
     return resource_buffer_size >= kMaximumLengthOfBOM;
   } else {
@@ -659,7 +665,7 @@
 // If this method returns true, the datapipe handle will be cleared and the
 // streaming task becomes responsible for draining the datapipe and forwarding
 // data to the client. Otherwise, we should continue as if this were a no-op.
-bool ScriptStreamer::TryStartStreamingTask() {
+bool ResourceScriptStreamer::TryStartStreamingTask() {
   DCHECK(IsMainThread());
   if (!CanStartStreaming())
     return false;
@@ -780,7 +786,7 @@
   return true;
 }
 
-v8::ScriptType ScriptStreamer::ScriptTypeForStreamingTask(
+v8::ScriptType ResourceScriptStreamer::ScriptTypeForStreamingTask(
     ScriptResource* script_resource) {
   switch (script_resource->GetInitialRequestScriptType()) {
     case mojom::blink::ScriptType::kModule:
@@ -800,11 +806,11 @@
   NOTREACHED();
 }
 
-v8::ScriptType ScriptStreamer::GetScriptType() const {
+v8::ScriptType ResourceScriptStreamer::GetScriptType() const {
   return script_type_;
 }
 
-ScriptStreamer::ScriptStreamer(
+ResourceScriptStreamer::ResourceScriptStreamer(
     ScriptResource* script_resource,
     mojo::ScopedDataPipeConsumerHandle data_pipe,
     ResponseBodyLoaderClient* response_body_loader_client,
@@ -826,10 +832,11 @@
       FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL,
       loading_task_runner);
 
-  watcher_->Watch(data_pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE,
-                  MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
-                  WTF::BindRepeating(&ScriptStreamer::OnDataPipeReadable,
-                                     WrapWeakPersistent(this)));
+  watcher_->Watch(
+      data_pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE,
+      MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+      WTF::BindRepeating(&ResourceScriptStreamer::OnDataPipeReadable,
+                         WrapWeakPersistent(this)));
 
   MojoResult ready_result;
   mojo::HandleSignalsState ready_state;
@@ -841,8 +848,9 @@
   OnDataPipeReadable(ready_result, ready_state);
 }
 
-void ScriptStreamer::OnDataPipeReadable(MojoResult result,
-                                        const mojo::HandleSignalsState& state) {
+void ResourceScriptStreamer::OnDataPipeReadable(
+    MojoResult result,
+    const mojo::HandleSignalsState& state) {
   if (IsClientDetached())
     return;
 
@@ -920,9 +928,9 @@
   watcher_->ArmOrNotify();
 }
 
-ScriptStreamer::~ScriptStreamer() = default;
+ResourceScriptStreamer::~ResourceScriptStreamer() = default;
 
-void ScriptStreamer::Prefinalize() {
+void ResourceScriptStreamer::Prefinalize() {
   // Reset and cancel the watcher. This has to be called in the prefinalizer,
   // rather than relying on the destructor, as accesses by the watcher of the
   // script resource between prefinalization and destruction are invalid. See
@@ -933,12 +941,13 @@
   Cancel();
 }
 
-void ScriptStreamer::Trace(Visitor* visitor) const {
+void ResourceScriptStreamer::Trace(Visitor* visitor) const {
   visitor->Trace(script_resource_);
   visitor->Trace(response_body_loader_client_);
+  ScriptStreamer::Trace(visitor);
 }
 
-void ScriptStreamer::StreamingComplete(LoadingState loading_state) {
+void ResourceScriptStreamer::StreamingComplete(LoadingState loading_state) {
   TRACE_EVENT_WITH_FLOW2(
       TRACE_DISABLED_BY_DEFAULT("v8.compile"), "v8.streamingCompile.complete",
       this, TRACE_EVENT_FLAG_FLOW_IN, "streaming_suppressed",
@@ -958,7 +967,7 @@
   SendClientLoadFinishedCallback();
 }
 
-void ScriptStreamer::LoadCompleteWithoutStreaming(
+void ResourceScriptStreamer::LoadCompleteWithoutStreaming(
     LoadingState state,
     NotStreamingReason no_streaming_reason) {
   // We might have previously suppressed streaming, in which case we want to
@@ -969,12 +978,12 @@
   AdvanceLoadingState(state);
 
   // Make sure decoding is finished before finishing the load.
-  script_decoder_->FinishDecode(
-      CrossThreadBindOnce(&ScriptStreamer::SendClientLoadFinishedCallback,
-                          WrapCrossThreadPersistent(this)));
+  script_decoder_->FinishDecode(CrossThreadBindOnce(
+      &ResourceScriptStreamer::SendClientLoadFinishedCallback,
+      WrapCrossThreadPersistent(this)));
 }
 
-void ScriptStreamer::SendClientLoadFinishedCallback() {
+void ResourceScriptStreamer::SendClientLoadFinishedCallback() {
   // Don't do anything if we're detached, there's no client to send signals to.
   if (IsClientDetached())
     return;
@@ -999,7 +1008,7 @@
   response_body_loader_client_.Release();
 }
 
-void ScriptStreamer::AdvanceLoadingState(LoadingState new_state) {
+void ResourceScriptStreamer::AdvanceLoadingState(LoadingState new_state) {
   switch (loading_state_) {
     case LoadingState::kLoading:
       CHECK(new_state == LoadingState::kLoaded ||
@@ -1017,7 +1026,7 @@
   CheckState();
 }
 
-void ScriptStreamer::CheckState() const {
+void ResourceScriptStreamer::CheckState() const {
   switch (loading_state_) {
     case LoadingState::kLoading:
       // If we are still loading, we either
@@ -1041,4 +1050,81 @@
   }
 }
 
+class InlineScriptStreamer::InlineSourceStream final
+    : public v8::ScriptCompiler::ExternalSourceStream {
+ public:
+  InlineSourceStream() = default;
+  ~InlineSourceStream() override = default;
+
+  void SetText(const String& text) {
+    // The text should always be 16 bit since it comes from the HTML parser
+    // which defaults to 16 bit.
+    DCHECK(!text.Is8Bit());
+    text_ = text;
+  }
+
+  size_t GetMoreData(const uint8_t** src) override {
+    if (!text_)
+      return 0;
+
+    size_t size = text_.CharactersSizeInBytes();
+    auto data_copy = std::make_unique<uint8_t[]>(size);
+    memcpy(data_copy.get(), text_.Bytes(), size);
+    text_ = String();
+
+    *src = data_copy.release();
+    return size;
+  }
+
+ private:
+  String text_;
+};
+
+InlineScriptStreamer::InlineScriptStreamer() {
+  DCHECK(IsMainThread());
+  auto stream = std::make_unique<InlineSourceStream>();
+  stream_ = stream.get();
+  // TODO(crbug.com/1328448): Use ONE_BYTE encoding when possible.
+  source_ = std::make_unique<v8::ScriptCompiler::StreamedSource>(
+      std::move(stream), v8::ScriptCompiler::StreamedSource::TWO_BYTE);
+
+  task_ = base::WrapUnique(v8::ScriptCompiler::StartStreaming(
+      V8PerIsolateData::MainThreadIsolate(), source_.get()));
+}
+
+void InlineScriptStreamer::Run(const String& text) {
+  TRACE_EVENT0("blink", "InlineScriptStreamer::Run");
+  if (cancelled_.IsSet())
+    return;
+
+  started_.Set();
+  stream_->SetText(text);
+  task_->Run();
+  task_.reset();
+
+  // We signal an event here instead of posting a task to the main thread
+  // because it's possible the task wouldn't be run by the time the script
+  // streamer is needed. This allows us to compile the inline script right up to
+  // when it is needed. If the script hasn't finished compiling, the main thread
+  // will block while it finishes on the worker thread. The worker thread should
+  // have already gotten a head start, so this should block the main thread for
+  // less time than the compile would have taken.
+  event_.Signal();
+}
+
+v8::ScriptCompiler::StreamedSource* InlineScriptStreamer::Source(
+    v8::ScriptType expected_type) {
+  TRACE_EVENT0("blink", "InlineScriptStreamer::Source");
+  DCHECK(IsMainThread());
+  DCHECK_EQ(expected_type, v8::ScriptType::kClassic);
+  // Make sure the script has finished compiling in the background. See comment
+  // above in Run().
+  event_.Wait();
+  return source_.get();
+}
+
+void InlineScriptStreamer::Trace(Visitor* visitor) const {
+  ScriptStreamer::Trace(visitor);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer.h b/third_party/blink/renderer/bindings/core/v8/script_streamer.h
index ae58ab8f..520633a8 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_streamer.h
+++ b/third_party/blink/renderer/bindings/core/v8/script_streamer.h
@@ -9,8 +9,10 @@
 #include <tuple>
 
 #include "base/check_op.h"
+#include "base/synchronization/waitable_event.h"
 #include "base/task/single_thread_task_runner.h"
 #include "mojo/public/cpp/system/data_pipe.h"
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink-forward.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
 #include "third_party/blink/renderer/core/script/script_scheduling_type.h"
@@ -20,7 +22,6 @@
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "v8/include/v8.h"
 
-#include "third_party/blink/public/mojom/script/script_type.mojom-blink-forward.h"
 namespace mojo {
 class SimpleWatcher;
 }
@@ -31,14 +32,9 @@
 class SourceStream;
 class ResponseBodyLoaderClient;
 
-// ScriptStreamer streams incomplete script data to V8 so that it can be parsed
-// while it's loaded. ScriptResource holds a reference to ScriptStreamer. If the
-// Document and the ClassicPendingScript are destroyed while the streaming is in
-// progress, and ScriptStreamer handles it gracefully.
-class CORE_EXPORT ScriptStreamer final
-    : public GarbageCollected<ScriptStreamer> {
-  USING_PRE_FINALIZER(ScriptStreamer, Prefinalize);
-
+// Base class for streaming scripts. Subclasses should expose streamed script
+// data by overriding the Source() method.
+class CORE_EXPORT ScriptStreamer : public GarbageCollected<ScriptStreamer> {
  public:
   // For tracking why some scripts are not streamed. Not streaming is part of
   // normal operation (e.g., script already loaded, script too small) and
@@ -73,18 +69,42 @@
     kInvalid = -1,
   };
 
-  ScriptStreamer(
+  virtual ~ScriptStreamer() = default;
+
+  virtual v8::ScriptCompiler::StreamedSource* Source(
+      v8::ScriptType expected_type) = 0;
+  virtual void Trace(Visitor*) const {}
+
+  static void RecordStreamingHistogram(ScriptSchedulingType type,
+                                       bool can_use_streamer,
+                                       ScriptStreamer::NotStreamingReason);
+
+  // Returns false if we cannot stream the given encoding.
+  static bool ConvertEncoding(const char* encoding_name,
+                              v8::ScriptCompiler::StreamedSource::Encoding*);
+};
+
+// ResourceScriptStreamer streams incomplete script data to V8 so that it can be
+// parsed while it's loaded. ScriptResource holds a reference to
+// ResourceScriptStreamer. If the Document and the ClassicPendingScript are
+// destroyed while the streaming is in progress, and ScriptStreamer handles it
+// gracefully.
+class CORE_EXPORT ResourceScriptStreamer final : public ScriptStreamer {
+  USING_PRE_FINALIZER(ResourceScriptStreamer, Prefinalize);
+
+ public:
+  ResourceScriptStreamer(
       ScriptResource* resource,
       mojo::ScopedDataPipeConsumerHandle data_pipe,
       ResponseBodyLoaderClient* response_body_loader_client,
       std::unique_ptr<TextResourceDecoder> decoder,
       scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner);
 
-  ScriptStreamer(const ScriptStreamer&) = delete;
-  ScriptStreamer& operator=(const ScriptStreamer&) = delete;
+  ResourceScriptStreamer(const ResourceScriptStreamer&) = delete;
+  ResourceScriptStreamer& operator=(const ResourceScriptStreamer&) = delete;
 
-  ~ScriptStreamer();
-  void Trace(Visitor*) const;
+  ~ResourceScriptStreamer() override;
+  void Trace(Visitor*) const override;
 
   // Get a successful ScriptStreamer for the given ScriptResource.
   // If
@@ -93,16 +113,9 @@
   // - or the expected_type does not match the one with which the ScripStramer
   //    was started,
   // nullptr instead of a valid ScriptStreamer is returned.
-  static std::tuple<ScriptStreamer*, NotStreamingReason> TakeFrom(
+  static std::tuple<ResourceScriptStreamer*, NotStreamingReason> TakeFrom(
       ScriptResource* resource,
       mojom::blink::ScriptType expected_type);
-  static void RecordStreamingHistogram(ScriptSchedulingType type,
-                                       bool can_use_streamer,
-                                       ScriptStreamer::NotStreamingReason);
-
-  // Returns false if we cannot stream the given encoding.
-  static bool ConvertEncoding(const char* encoding_name,
-                              v8::ScriptCompiler::StreamedSource::Encoding*);
 
   bool IsStreamingStarted() const;     // Have we actually started streaming?
   bool CanStartStreaming() const;      // Can we still start streaming later?
@@ -110,8 +123,12 @@
   bool IsFinished() const;             // Has loading & streaming finished?
   bool IsStreamingSuppressed() const;  // Has streaming been suppressed?
 
-  v8::ScriptCompiler::StreamedSource* Source(v8::ScriptType expected_type) {
+  // ScriptStreamer implementation:
+  v8::ScriptCompiler::StreamedSource* Source(
+      v8::ScriptType expected_type) override {
     DCHECK_EQ(expected_type, script_type_);
+    DCHECK(IsFinished());
+    DCHECK(!IsStreamingSuppressed());
     return source_.get();
   }
 
@@ -166,7 +183,7 @@
 
   static void RunScriptStreamingTask(
       std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask> task,
-      ScriptStreamer* streamer,
+      ResourceScriptStreamer* streamer,
       SourceStream* stream);
 
   void OnDataPipeReadable(MojoResult result,
@@ -250,6 +267,35 @@
   v8::ScriptType script_type_;
 };
 
+// InlineScriptStreamer allows parsing and compiling inline scripts in the
+// background before they have been parsed by the HTML parser.
+class CORE_EXPORT InlineScriptStreamer final : public ScriptStreamer {
+ public:
+  InlineScriptStreamer();
+
+  void Run(const String& text);
+  bool IsStarted() const { return started_.IsSet(); }
+  void Cancel() { cancelled_.Set(); }
+
+  // This may return false if V8 failed to create a background streaming task.
+  bool CanStream() const { return task_.get(); };
+
+  // ScriptStreamer implementation:
+  v8::ScriptCompiler::StreamedSource* Source(
+      v8::ScriptType expected_type) override;
+  void Trace(Visitor* visitor) const override;
+
+ private:
+  class InlineSourceStream;
+  InlineSourceStream* stream_ = nullptr;
+
+  std::unique_ptr<v8::ScriptCompiler::StreamedSource> source_;
+  std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask> task_;
+  base::WaitableEvent event_;
+  base::AtomicFlag started_;
+  base::AtomicFlag cancelled_;
+};
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCRIPT_STREAMER_H_
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc b/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc
index 8cf1e4ab..48aef6d 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc
@@ -19,10 +19,12 @@
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/public/platform/web_url_request_extra_data.h"
 #include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/script/classic_pending_script.h"
 #include "third_party/blink/renderer/core/script/classic_script.h"
@@ -39,9 +41,11 @@
 #include "third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h"
 #include "third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/worker_pool.h"
 #include "third_party/blink/renderer/platform/testing/mock_context_lifecycle_notifier.h"
 #include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
 #include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
 #include "v8/include/v8.h"
 
@@ -169,7 +173,7 @@
   }
 
   ClassicScript* CreateClassicScript() const {
-    ScriptStreamer* streamer = resource_->TakeStreamer();
+    ResourceScriptStreamer* streamer = resource_->TakeStreamer();
     ScriptCacheConsumer* cache_consumer = resource_->TakeCacheConsumer();
     if (streamer) {
       if (streamer->IsStreamingSuppressed()) {
@@ -186,10 +190,6 @@
         resource_->NoStreamerReason(), cache_consumer);
   }
 
-  Settings* GetSettings() const {
-    return &dummy_page_holder_->GetPage().GetSettings();
-  }
-
  protected:
   void AppendData(const char* data) {
     uint32_t data_len = base::checked_cast<uint32_t>(strlen(data));
@@ -239,8 +239,6 @@
   Persistent<ScriptResource> resource_;
   mojo::ScopedDataPipeProducerHandle producer_handle_;
   mojo::ScopedDataPipeConsumerHandle consumer_handle_;
-
-  std::unique_ptr<DummyPageHolder> dummy_page_holder_;
 };
 
 TEST_F(ScriptStreamingTest, CompilingStreamedScript) {
@@ -567,4 +565,32 @@
             ScriptStreamer::NotStreamingReason::kRevalidate);
 }
 
+TEST_F(ScriptStreamingTest, InlineScript) {
+  // Test that we can successfully compile an inline script.
+  V8TestingScope scope;
+
+  String source = u"function foo() {return 5;} foo();";
+  source.Ensure16Bit();
+  auto* streamer = MakeGarbageCollected<InlineScriptStreamer>();
+  worker_pool::PostTask(
+      FROM_HERE, {},
+      CrossThreadBindOnce(&InlineScriptStreamer::Run,
+                          WrapCrossThreadPersistent(streamer), source));
+
+  ClassicScript* classic_script = ClassicScript::Create(
+      source, KURL(), KURL(), ScriptFetchOptions(),
+      ScriptSourceLocationType::kUnknown, SanitizeScriptErrors::kSanitize,
+      nullptr, TextPosition::MinimumPosition(),
+      ScriptStreamer::NotStreamingReason::kInvalid, streamer);
+
+  DummyPageHolder holder;
+  ScriptEvaluationResult result = classic_script->RunScriptAndReturnValue(
+      holder.GetFrame().DomWindow(),
+      ExecuteScriptPolicy::kExecuteScriptWhenScriptsDisabled);
+  EXPECT_EQ(result.GetResultType(),
+            ScriptEvaluationResult::ResultType::kSuccess);
+  EXPECT_EQ(
+      5, result.GetSuccessValue()->Int32Value(scope.GetContext()).FromJust());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc
index 2ccfd313..fc112b9 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc
@@ -129,8 +129,6 @@
     // Final compile call for a streamed compilation.
     // Streaming compilation may involve use of code cache.
     // TODO(leszeks): Add compile timer to streaming compilation.
-    DCHECK(streamer->IsFinished());
-    DCHECK(!streamer->IsStreamingSuppressed());
     return v8::ScriptCompiler::Compile(
         script_state->GetContext(), streamer->Source(v8::ScriptType::kClassic),
         code, origin);
@@ -318,8 +316,6 @@
     // Final compile call for a streamed compilation.
     // Streaming compilation may involve use of code cache.
     // TODO(leszeks): Add compile timer to streaming compilation.
-    DCHECK(streamer->IsFinished());
-    DCHECK(!streamer->IsStreamingSuppressed());
     script = v8::ScriptCompiler::CompileModule(
         isolate->GetCurrentContext(), streamer->Source(v8::ScriptType::kModule),
         code, origin);
diff --git a/third_party/blink/renderer/core/dom/scriptable_document_parser.cc b/third_party/blink/renderer/core/dom/scriptable_document_parser.cc
index e8efc50..6c584851 100644
--- a/third_party/blink/renderer/core/dom/scriptable_document_parser.cc
+++ b/third_party/blink/renderer/core/dom/scriptable_document_parser.cc
@@ -25,6 +25,7 @@
 
 #include "third_party/blink/renderer/core/dom/scriptable_document_parser.h"
 
+#include "third_party/blink/renderer/bindings/core/v8/script_streamer.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.h"
@@ -47,4 +48,27 @@
   DecodedDataDocumentParser::Trace(visitor);
 }
 
+void ScriptableDocumentParser::AddInlineScriptStreamer(
+    const String& source,
+    InlineScriptStreamer* streamer) {
+  base::AutoLock lock(streamers_lock_);
+  inline_script_streamers_.insert(source, streamer);
+}
+
+InlineScriptStreamer* ScriptableDocumentParser::TakeInlineScriptStreamer(
+    const String& source) {
+  InlineScriptStreamer* streamer;
+  {
+    base::AutoLock lock(streamers_lock_);
+    streamer = inline_script_streamers_.Take(source).Get();
+  }
+  // If the streamer hasn't started yet, cancel and just compile on the main
+  // thread.
+  if (streamer && !streamer->IsStarted()) {
+    streamer->Cancel();
+    streamer = nullptr;
+  }
+  return streamer;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/scriptable_document_parser.h b/third_party/blink/renderer/core/dom/scriptable_document_parser.h
index 855791a..5dd05d8 100644
--- a/third_party/blink/renderer/core/dom/scriptable_document_parser.h
+++ b/third_party/blink/renderer/core/dom/scriptable_document_parser.h
@@ -26,9 +26,13 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SCRIPTABLE_DOCUMENT_PARSER_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SCRIPTABLE_DOCUMENT_PARSER_H_
 
+#include "base/synchronization/lock.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_streamer.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/decoded_data_document_parser.h"
 #include "third_party/blink/renderer/core/dom/parser_content_policy.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
 #include "third_party/blink/renderer/platform/wtf/text/text_position.h"
 
 namespace blink {
@@ -71,6 +75,16 @@
     return inline_script_cache_handler_;
   }
 
+  // Adds a script streamer for |source| which can be later retrieved with
+  // TakeInlineScriptStreamer(). This may be called on any thread.
+  void AddInlineScriptStreamer(const String& source,
+                               InlineScriptStreamer* streamer);
+
+  // Takes a script streamer previously added with AddInlineScriptStreamer().
+  // The returned streamer is guaranteed to be correct for script text that
+  // matches the passed in |source|.
+  InlineScriptStreamer* TakeInlineScriptStreamer(const String& source);
+
  protected:
   explicit ScriptableDocumentParser(
       Document&,
@@ -84,6 +98,10 @@
   // http://www.whatwg.org/specs/web-apps/current-work/#script-created-parser
   bool was_created_by_script_;
   ParserContentPolicy parser_content_policy_;
+
+  base::Lock streamers_lock_;
+  HashMap<String, CrossThreadPersistent<InlineScriptStreamer>>
+      inline_script_streamers_ GUARDED_BY(streamers_lock_);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/build.gni b/third_party/blink/renderer/core/html/build.gni
index 96db9b2..fff4491 100644
--- a/third_party/blink/renderer/core/html/build.gni
+++ b/third_party/blink/renderer/core/html/build.gni
@@ -598,6 +598,8 @@
   "parser/html_parser_reentry_permit.h",
   "parser/html_preload_scanner.cc",
   "parser/html_preload_scanner.h",
+  "parser/background_html_scanner.cc",
+  "parser/background_html_scanner.h",
   "parser/html_resource_preloader.cc",
   "parser/html_resource_preloader.h",
   "parser/html_srcset_parser.cc",
@@ -707,6 +709,7 @@
   "parser/html_parser_metrics_test.cc",
   "parser/html_preload_scanner_document_test.cc",
   "parser/html_preload_scanner_test.cc",
+  "parser/background_html_scanner_test.cc",
   "parser/html_resource_preloader_test.cc",
   "parser/html_srcset_parser_test.cc",
   "parser/html_tokenizer_test.cc",
diff --git a/third_party/blink/renderer/core/html/parser/atomic_html_token.h b/third_party/blink/renderer/core/html/parser/atomic_html_token.h
index f871c59..4558746 100644
--- a/third_party/blink/renderer/core/html/parser/atomic_html_token.h
+++ b/third_party/blink/renderer/core/html/parser/atomic_html_token.h
@@ -35,6 +35,8 @@
 #include "third_party/blink/renderer/core/html/parser/html_token.h"
 #include "third_party/blink/renderer/core/html_element_lookup_trie.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/hash_set.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
 
 namespace blink {
 
@@ -186,6 +188,11 @@
   if (!size)
     return;
 
+  // Track which attributes have already been inserted to avoid N^2
+  // behavior with repeated linear searches when populating `attributes_`.
+  HashSet<AtomicString> added_attributes;
+  added_attributes.ReserveCapacityForSize(size);
+
   attributes_.clear();
   attributes_.ReserveInitialCapacity(size);
   for (const auto& attribute : attributes) {
@@ -203,8 +210,7 @@
       value = g_empty_atom;
     }
     const QualifiedName& name = NameForAttribute(attribute);
-    // FIXME: This is N^2 for the number of attributes.
-    if (!FindAttributeInVector(attributes_, name)) {
+    if (added_attributes.insert(name.LocalName()).is_new_entry) {
       attributes_.push_back(Attribute(name, value));
     } else {
       duplicate_attribute_ = true;
diff --git a/third_party/blink/renderer/core/html/parser/background_html_scanner.cc b/third_party/blink/renderer/core/html/parser/background_html_scanner.cc
new file mode 100644
index 0000000..52975fcb
--- /dev/null
+++ b/third_party/blink/renderer/core/html/parser/background_html_scanner.cc
@@ -0,0 +1,140 @@
+// 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.
+
+#include "third_party/blink/renderer/core/html/parser/background_html_scanner.h"
+
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/renderer/core/dom/scriptable_document_parser.h"
+#include "third_party/blink/renderer/core/html/parser/html_preload_scanner.h"
+#include "third_party/blink/renderer/core/html/parser/html_tokenizer.h"
+#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/scheduler/public/worker_pool.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_copier_base.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_copier_std.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+
+namespace WTF {
+
+template <>
+struct CrossThreadCopier<
+    blink::BackgroundHTMLScanner::InlineScriptStreamerVector>
+    : public CrossThreadCopierPassThrough<
+          blink::BackgroundHTMLScanner::InlineScriptStreamerVector> {
+  STATIC_ONLY(CrossThreadCopier);
+};
+
+}  // namespace WTF
+
+namespace blink {
+namespace {
+
+// The maximum number of inline scripts that will be streamed per page.
+int GetMaxScriptsPerPage() {
+  static const base::FeatureParam<int> kMaxScriptsPerPage{
+      &features::kPrecompileInlineScripts, "max-scripts-per-page", 50};
+  return kMaxScriptsPerPage.Get();
+}
+
+}  // namespace
+
+// static
+WTF::SequenceBound<BackgroundHTMLScanner> BackgroundHTMLScanner::Create(
+    const HTMLParserOptions& options,
+    ScriptableDocumentParser* parser) {
+  TRACE_EVENT0("blink", "BackgroundHTMLScanner::Create");
+
+  // InlineScriptStreamer must be created on the main thread. We create as many
+  // streamers as a page is likely to need here so the background scanner
+  // doesn't have to go back to the main thread to create more.
+  // TODO(crbug.com/v8/12916): Create these on the background thread.
+  InlineScriptStreamerVector streamers;
+  int scripts_per_page = GetMaxScriptsPerPage();
+  streamers.ReserveInitialCapacity(scripts_per_page);
+  for (int i = 0; i < scripts_per_page; i++)
+    streamers.emplace_back(MakeGarbageCollected<InlineScriptStreamer>());
+
+  // The background scanner lives on one sequence, while the script streamers
+  // work on a second sequence. This allows us to continue scanning the HTML
+  // while scripts are compiling.
+  return WTF::SequenceBound<BackgroundHTMLScanner>(
+      worker_pool::CreateSequencedTaskRunner(
+          {base::TaskPriority::USER_BLOCKING}),
+      std::make_unique<HTMLTokenizer>(options), std::move(streamers),
+      WrapCrossThreadWeakPersistent(parser),
+      worker_pool::CreateSequencedTaskRunner(
+          {base::TaskPriority::USER_BLOCKING}));
+}
+
+BackgroundHTMLScanner::BackgroundHTMLScanner(
+    std::unique_ptr<HTMLTokenizer> tokenizer,
+    InlineScriptStreamerVector streamers,
+    ScriptableDocumentParser* parser,
+    scoped_refptr<base::SequencedTaskRunner> task_runner)
+    : tokenizer_(std::move(tokenizer)),
+      streamers_(std::move(streamers)),
+      parser_(parser),
+      task_runner_(std::move(task_runner)) {}
+
+BackgroundHTMLScanner::~BackgroundHTMLScanner() = default;
+
+void BackgroundHTMLScanner::Scan(const String& source) {
+  TRACE_EVENT0("blink", "BackgroundHTMLScanner::Scan");
+  source_.Append(source);
+  while (tokenizer_->NextToken(source_, token_) && !streamers_.IsEmpty()) {
+    if (token_.GetType() == HTMLToken::kStartTag) {
+      tokenizer_->UpdateStateFor(
+          AttemptStaticStringCreation(token_.GetName(), kLikely8Bit));
+    }
+    ScanToken(token_);
+    token_.Clear();
+  }
+}
+
+void BackgroundHTMLScanner::ScanToken(const HTMLToken& token) {
+  switch (token.GetType()) {
+    case HTMLToken::kCharacter: {
+      if (in_script_)
+        script_builder_.Append(token.Data().AsString());
+      return;
+    }
+    case HTMLToken::kStartTag: {
+      if (Match(TagImplFor(token.Data()), html_names::kScriptTag)) {
+        in_script_ = true;
+        script_builder_.Clear();
+      }
+      return;
+    }
+    case HTMLToken::kEndTag: {
+      if (Match(TagImplFor(token.Data()), html_names::kScriptTag)) {
+        in_script_ = false;
+        // The script was empty, do nothing.
+        if (script_builder_.IsEmpty())
+          return;
+
+        String script_text = script_builder_.ReleaseString();
+        script_builder_.Clear();
+
+        auto streamer = std::move(streamers_.back());
+        streamers_.pop_back();
+        auto parser_lock = parser_.Lock();
+        if (!parser_lock || !streamer->CanStream())
+          return;
+
+        parser_lock->AddInlineScriptStreamer(script_text, streamer.Get());
+        PostCrossThreadTask(
+            *task_runner_, FROM_HERE,
+            CrossThreadBindOnce(&InlineScriptStreamer::Run, std::move(streamer),
+                                script_text));
+      }
+      return;
+    }
+    default: {
+      return;
+    }
+  }
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/html/parser/background_html_scanner.h b/third_party/blink/renderer/core/html/parser/background_html_scanner.h
new file mode 100644
index 0000000..70536a9
--- /dev/null
+++ b/third_party/blink/renderer/core/html/parser/background_html_scanner.h
@@ -0,0 +1,80 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_BACKGROUND_HTML_SCANNER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_BACKGROUND_HTML_SCANNER_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/script_streamer.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/html/parser/html_token.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/text/segmented_string.h"
+#include "third_party/blink/renderer/platform/wtf/sequence_bound.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+class HTMLParserOptions;
+class HTMLTokenizer;
+class ScriptableDocumentParser;
+
+// Scans HTML on a worker thread looking for inline scripts which can be stream
+// compiled.
+//
+// Unlike HTMLPreloadScanner which runs on the main thread, this scanner runs in
+// a worker thread. In addition, HTMLPreloadScanner only scans the first chunk
+// of body data and won't scan more of the response body unless the parser is
+// paused. BackgroundHTMLScanner will scan all body data, since it does not tie
+// up the main thread with the scan. If you want to add logic for scanning the
+// response body which can be done off the main thread, this is the place to add
+// it.
+//
+// This is currently used to stream compile inline scripts. To do this
+// effectively we need to get the script text as early as possible so it can be
+// compiled by the time it is needed in the parser. BackgroundHTMLScanner will
+// immediately scan the HTML until it finds an inline script, then kick off a
+// stream compile task for that script. The parser will store these compile
+// tasks in a map which will then be checked and used whenever a matching inline
+// script is parsed.
+// TODO(crbug.com/1329535): Move HTMLPreloadScanner to a background thread and
+// combine these.
+class CORE_EXPORT BackgroundHTMLScanner {
+  USING_FAST_MALLOC(BackgroundHTMLScanner);
+
+ public:
+  using InlineScriptStreamerVector =
+      Vector<CrossThreadPersistent<InlineScriptStreamer>>;
+
+  static WTF::SequenceBound<BackgroundHTMLScanner> Create(
+      const HTMLParserOptions& options,
+      ScriptableDocumentParser* parser);
+  BackgroundHTMLScanner(std::unique_ptr<HTMLTokenizer> tokenizer,
+                        InlineScriptStreamerVector streamers,
+                        ScriptableDocumentParser* parser,
+                        scoped_refptr<base::SequencedTaskRunner> task_runner);
+  ~BackgroundHTMLScanner();
+
+  BackgroundHTMLScanner(const BackgroundHTMLScanner&) = delete;
+  BackgroundHTMLScanner& operator=(const BackgroundHTMLScanner&) = delete;
+
+  void Scan(const String& source);
+
+ private:
+  void ScanToken(const HTMLToken& token);
+
+  SegmentedString source_;
+  HTMLToken token_;
+  std::unique_ptr<HTMLTokenizer> tokenizer_;
+  InlineScriptStreamerVector streamers_;
+  CrossThreadWeakPersistent<ScriptableDocumentParser> parser_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+  StringBuilder script_builder_;
+
+  bool in_script_ = false;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_BACKGROUND_HTML_SCANNER_H_
diff --git a/third_party/blink/renderer/core/html/parser/background_html_scanner_test.cc b/third_party/blink/renderer/core/html/parser/background_html_scanner_test.cc
new file mode 100644
index 0000000..63c3e7a
--- /dev/null
+++ b/third_party/blink/renderer/core/html/parser/background_html_scanner_test.cc
@@ -0,0 +1,120 @@
+// 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.
+
+#include "third_party/blink/renderer/core/html/parser/background_html_scanner.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/dom/scriptable_document_parser.h"
+#include "third_party/blink/renderer/core/html/parser/html_tokenizer.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+#include "third_party/blink/renderer/platform/scheduler/public/worker_pool.h"
+
+namespace blink {
+namespace {
+
+class TestParser : public ScriptableDocumentParser {
+ public:
+  explicit TestParser(Document& document)
+      : ScriptableDocumentParser(document) {}
+
+  void Trace(Visitor* visitor) const override {
+    ScriptableDocumentParser::Trace(visitor);
+  }
+
+  void ExecuteScriptsWaitingForResources() override {}
+  bool IsWaitingForScripts() const override { return false; }
+  void DidAddPendingParserBlockingStylesheet() override {}
+  void DidLoadAllPendingParserBlockingStylesheets() override {}
+  OrdinalNumber LineNumber() const override { return OrdinalNumber::First(); }
+  TextPosition GetTextPosition() const override {
+    return TextPosition::MinimumPosition();
+  }
+  void insert(const String&) override {}
+  void Append(const String&) override {}
+  void Finish() override {}
+};
+
+class BackgroundHTMLScannerTest : public PageTestBase {
+ public:
+  BackgroundHTMLScannerTest()
+      : task_runner_(worker_pool::CreateSequencedTaskRunner(
+            {base::TaskPriority::USER_BLOCKING})) {}
+
+ protected:
+  std::unique_ptr<BackgroundHTMLScanner> CreateScanner(int num_streamers,
+                                                       TestParser* parser) {
+    BackgroundHTMLScanner::InlineScriptStreamerVector streamers;
+    for (int i = 0; i < num_streamers; i++)
+      streamers.emplace_back(MakeGarbageCollected<InlineScriptStreamer>());
+    return std::make_unique<BackgroundHTMLScanner>(
+        std::make_unique<HTMLTokenizer>(HTMLParserOptions()),
+        std::move(streamers), parser, task_runner_);
+  }
+
+  void FlushTaskRunner() {
+    base::RunLoop r;
+    task_runner_->PostTask(FROM_HERE, r.QuitClosure());
+    r.Run();
+  }
+
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+};
+
+TEST_F(BackgroundHTMLScannerTest, SimpleScript) {
+  auto* parser = MakeGarbageCollected<TestParser>(GetDocument());
+  auto scanner = CreateScanner(2, parser);
+  scanner->Scan("<script>foo</script>");
+  FlushTaskRunner();
+  EXPECT_NE(parser->TakeInlineScriptStreamer("foo"), nullptr);
+}
+
+TEST_F(BackgroundHTMLScannerTest, ScriptWithScriptTag) {
+  auto* parser = MakeGarbageCollected<TestParser>(GetDocument());
+  auto scanner = CreateScanner(2, parser);
+  scanner->Scan("<script>foo = '<script>'</script>");
+  FlushTaskRunner();
+  EXPECT_NE(parser->TakeInlineScriptStreamer("foo = '<script>'"), nullptr);
+}
+
+TEST_F(BackgroundHTMLScannerTest, TooManyScripts) {
+  auto* parser = MakeGarbageCollected<TestParser>(GetDocument());
+  auto scanner = CreateScanner(2, parser);
+  scanner->Scan("<script>foo</script><script>bar</script><script>baz</script>");
+  FlushTaskRunner();
+  EXPECT_NE(parser->TakeInlineScriptStreamer("foo"), nullptr);
+  EXPECT_NE(parser->TakeInlineScriptStreamer("bar"), nullptr);
+  EXPECT_EQ(parser->TakeInlineScriptStreamer("baz"), nullptr);
+}
+
+TEST_F(BackgroundHTMLScannerTest, ScriptAcrossMultipleScans) {
+  auto* parser = MakeGarbageCollected<TestParser>(GetDocument());
+  auto scanner = CreateScanner(2, parser);
+  scanner->Scan("Some stuff<div></div><script>f");
+  scanner->Scan("oo</script> and some other stuff");
+  FlushTaskRunner();
+  EXPECT_NE(parser->TakeInlineScriptStreamer("foo"), nullptr);
+}
+
+TEST_F(BackgroundHTMLScannerTest, String16Key) {
+  auto* parser = MakeGarbageCollected<TestParser>(GetDocument());
+  auto scanner = CreateScanner(2, parser);
+  scanner->Scan("<script>foo</script>");
+  FlushTaskRunner();
+  String key = "foo";
+  key.Ensure16Bit();
+  EXPECT_NE(parser->TakeInlineScriptStreamer(key), nullptr);
+}
+
+TEST_F(BackgroundHTMLScannerTest, String16Source) {
+  auto* parser = MakeGarbageCollected<TestParser>(GetDocument());
+  auto scanner = CreateScanner(2, parser);
+  String source = "<script>foo</script>";
+  source.Ensure16Bit();
+  scanner->Scan(source);
+  FlushTaskRunner();
+  EXPECT_NE(parser->TakeInlineScriptStreamer("foo"), nullptr);
+}
+
+}  // namespace
+}  // namespace blink
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 fcd6a99..eb335f3 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
@@ -44,6 +44,7 @@
 #include "third_party/blink/renderer/core/html/html_document.h"
 #include "third_party/blink/renderer/core/html/nesting_level_incrementer.h"
 #include "third_party/blink/renderer/core/html/parser/atomic_html_token.h"
+#include "third_party/blink/renderer/core/html/parser/background_html_scanner.h"
 #include "third_party/blink/renderer/core/html/parser/html_parser_metrics.h"
 #include "third_party/blink/renderer/core/html/parser/html_resource_preloader.h"
 #include "third_party/blink/renderer/core/html/parser/html_tree_builder.h"
@@ -456,6 +457,7 @@
   // fast/dom/HTMLScriptElement/script-load-events.html we do.
   preload_scanner_.reset();
   insertion_preload_scanner_.reset();
+  background_scanner_.Reset();
   // Oilpan: It is important to clear token_ to deallocate backing memory of
   // HTMLToken::data_ and let the allocator reuse the memory for
   // HTMLToken::data_ of a next HTMLDocumentParser. We need to clear
@@ -882,6 +884,8 @@
         CreatePreloadScanner(TokenPreloadScanner::ScannerType::kMainDocument);
   }
 
+  ScanInBackground(input_source);
+
   if (GetDocument()->IsPrefetchOnly()) {
     preload_scanner_->AppendToEnd(source);
     if (preloader_) {
@@ -1323,4 +1327,14 @@
                        have_seen_first_byte ? ".NonInitial" : ".Initial"});
 }
 
+void HTMLDocumentParser::ScanInBackground(const String& source) {
+  if (!base::FeatureList::IsEnabled(features::kPrecompileInlineScripts))
+    return;
+
+  if (!background_scanner_)
+    background_scanner_ = BackgroundHTMLScanner::Create(options_, this);
+
+  background_scanner_.AsyncCall(&BackgroundHTMLScanner::Scan).WithArgs(source);
+}
+
 }  // namespace blink
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 e604ffc6..259f9e5 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
@@ -47,10 +47,12 @@
 #include "third_party/blink/renderer/platform/heap/prefinalizer.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 #include "third_party/blink/renderer/platform/wtf/deque.h"
+#include "third_party/blink/renderer/platform/wtf/sequence_bound.h"
 #include "third_party/blink/renderer/platform/wtf/text/text_position.h"
 
 namespace blink {
 
+class BackgroundHTMLScanner;
 class Document;
 class DocumentFragment;
 class Element;
@@ -186,6 +188,7 @@
   void FetchQueuedPreloads();
   std::string GetPreloadHistogramSuffix();
   void FinishAppend();
+  void ScanInBackground(const String& source);
 
   HTMLToken& Token() { return *token_; }
 
@@ -202,6 +205,7 @@
   std::unique_ptr<HTMLPreloadScanner> preload_scanner_;
   // A scanner used only for input provided to the insert() method.
   std::unique_ptr<HTMLPreloadScanner> insertion_preload_scanner_;
+  WTF::SequenceBound<BackgroundHTMLScanner> background_scanner_;
 
   scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner_;
 
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
index 590871e7..cba4e7a4 100644
--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
@@ -76,23 +76,11 @@
 
 namespace {
 
-bool Match(const StringImpl* impl, const QualifiedName& q_name) {
-  return impl == q_name.LocalName().Impl();
-}
-
 bool Match(const AtomicString& name, const QualifiedName& q_name) {
   DCHECK(IsMainThread());
   return q_name.LocalName() == name;
 }
 
-const StringImpl* TagImplFor(const HTMLToken::DataVector& data) {
-  AtomicString tag_name = data.AsAtomicString();
-  const StringImpl* result = tag_name.Impl();
-  if (result->IsStatic())
-    return result;
-  return nullptr;
-}
-
 String InitiatorFor(const StringImpl* tag_impl) {
   DCHECK(tag_impl);
   if (Match(tag_impl, html_names::kImgTag))
@@ -154,6 +142,18 @@
 
 }  // namespace
 
+bool Match(const StringImpl* impl, const QualifiedName& q_name) {
+  return impl == q_name.LocalName().Impl();
+}
+
+const StringImpl* TagImplFor(const HTMLToken::DataVector& data) {
+  AtomicString tag_name = data.AsAtomicString();
+  const StringImpl* result = tag_name.Impl();
+  if (result->IsStatic())
+    return result;
+  return nullptr;
+}
+
 class TokenPreloadScanner::StartTagScanner {
   STACK_ALLOCATED();
 
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.h b/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
index 94753716..45c3ae9 100644
--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
@@ -54,6 +54,9 @@
 class SegmentedString;
 class SubresourceRedirectOriginsPreloader;
 
+bool Match(const StringImpl* impl, const QualifiedName& q_name);
+const StringImpl* TagImplFor(const HTMLToken::DataVector& data);
+
 struct CORE_EXPORT CachedDocumentParameters {
   USING_FAST_MALLOC(CachedDocumentParameters);
 
diff --git a/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc
index 4b1c65b..fe645f4 100644
--- a/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc
+++ b/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc
@@ -57,7 +57,7 @@
   // Check if we can use the script streamer.
   ScriptStreamer* streamer;
   ScriptStreamer::NotStreamingReason not_streamed_reason;
-  std::tie(streamer, not_streamed_reason) = ScriptStreamer::TakeFrom(
+  std::tie(streamer, not_streamed_reason) = ResourceScriptStreamer::TakeFrom(
       script_resource, mojom::blink::ScriptType::kModule);
 
   ScriptStreamer::RecordStreamingHistogram(ScriptSchedulingType::kAsync,
diff --git a/third_party/blink/renderer/core/loader/resource/script_resource.cc b/third_party/blink/renderer/core/loader/resource/script_resource.cc
index 1a24516..35c90a7 100644
--- a/third_party/blink/renderer/core/loader/resource/script_resource.cc
+++ b/third_party/blink/renderer/core/loader/resource/script_resource.cc
@@ -414,7 +414,7 @@
   CheckStreamingState();
   CHECK(!ErrorOccurred());
 
-  streamer_ = MakeGarbageCollected<ScriptStreamer>(
+  streamer_ = MakeGarbageCollected<ResourceScriptStreamer>(
       this, std::move(data_pipe), response_body_loader_client,
       std::move(stream_text_decoder_), loader_task_runner);
   CHECK_EQ(no_streamer_reason_, ScriptStreamer::NotStreamingReason::kInvalid);
@@ -484,12 +484,12 @@
   }
 }
 
-ScriptStreamer* ScriptResource::TakeStreamer() {
+ResourceScriptStreamer* ScriptResource::TakeStreamer() {
   CHECK(IsLoaded());
   if (!streamer_)
     return nullptr;
 
-  ScriptStreamer* streamer = streamer_;
+  ResourceScriptStreamer* streamer = streamer_;
   // A second use of the streamer is not possible, so we null it out and disable
   // streaming for subsequent uses.
   streamer_ = nullptr;
diff --git a/third_party/blink/renderer/core/loader/resource/script_resource.h b/third_party/blink/renderer/core/loader/resource/script_resource.h
index 1dd2ab1d..0786e02 100644
--- a/third_party/blink/renderer/core/loader/resource/script_resource.h
+++ b/third_party/blink/renderer/core/loader/resource/script_resource.h
@@ -118,7 +118,7 @@
 
   // Gets the script streamer from the ScriptResource, clearing the resource's
   // streamer so that it cannot be used twice.
-  ScriptStreamer* TakeStreamer();
+  ResourceScriptStreamer* TakeStreamer();
 
   ScriptStreamer::NotStreamingReason NoStreamerReason() const {
     return no_streamer_reason_;
@@ -241,7 +241,7 @@
 
   ParkableString source_text_;
 
-  Member<ScriptStreamer> streamer_;
+  Member<ResourceScriptStreamer> streamer_;
   ScriptStreamer::NotStreamingReason no_streamer_reason_ =
       ScriptStreamer::NotStreamingReason::kInvalid;
   StreamingState streaming_state_ = StreamingState::kWaitingForDataPipe;
diff --git a/third_party/blink/renderer/core/page/focusgroup_controller.cc b/third_party/blink/renderer/core/page/focusgroup_controller.cc
index bf77f70..97d0ed938 100644
--- a/third_party/blink/renderer/core/page/focusgroup_controller.cc
+++ b/third_party/blink/renderer/core/page/focusgroup_controller.cc
@@ -335,20 +335,31 @@
             wrap_result, parent, direction);
         parent = FlatTreeTraversal::ParentElement(*current);
       } else {
-        // Wrapping wasn't an option. Validate that we're still in a focusgroup
-        // even though we went up to the parent element.
-        Element* parent_focusgroup = utils::FindNearestFocusgroupAncestor(
-            current, FocusgroupType::kLinear);
-        if (!parent_focusgroup ||
-            !utils::IsAxisSupported(parent_focusgroup->GetFocusgroupFlags(),
-                                    direction)) {
-          // At this point, we moved from inside of a focusgroup to the
-          // focusgroup root and it can't wrap. Furthermore, if there's a
-          // parent focusgroup, it doesn't support the axis of the arrow
-          // key, so it doesn't make sense to move into that focusgroup.
+        // Wrapping wasn't an option. At this point, we can only attempt to
+        // ascend to the parent.
+
+        // We can't ascend out of a non-extending focusgroup.
+        FocusgroupFlags current_flags = current->GetFocusgroupFlags();
+        if (current_flags != FocusgroupFlags::kNone &&
+            !(current_flags & FocusgroupFlags::kExtend)) {
           return false;
         }
 
+        // We can't ascend if there is no focusgroup ancestor.
+        Element* parent_focusgroup = utils::FindNearestFocusgroupAncestor(
+            current, FocusgroupType::kLinear);
+        if (!parent_focusgroup)
+          return false;
+
+        // We can't ascend if the parent focusgroup doesn't support the axis of
+        // the arrow key pressed.
+        if (!utils::IsAxisSupported(parent_focusgroup->GetFocusgroupFlags(),
+                                    direction)) {
+          return false;
+        }
+
+        // At this point, we are certain that we can ascend to the parent
+        // element.
         ascended = true;
         parent = FlatTreeTraversal::ParentElement(*parent);
         // No need to check if the new |parent| is null or not because, if that
diff --git a/third_party/blink/renderer/core/script/classic_pending_script.cc b/third_party/blink/renderer/core/script/classic_pending_script.cc
index 8e2d70b..7454fdc6 100644
--- a/third_party/blink/renderer/core/script/classic_pending_script.cc
+++ b/third_party/blink/renderer/core/script/classic_pending_script.cc
@@ -34,6 +34,22 @@
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace blink {
+namespace {
+
+InlineScriptStreamer* GetInlineScriptStreamer(const String& source,
+                                              Document& document) {
+  ScriptableDocumentParser* scriptable_parser =
+      document.GetScriptableDocumentParser();
+  if (!scriptable_parser)
+    return nullptr;
+
+  // The inline script streamers are keyed by the full source text to make sure
+  // the script that was parsed in the background scanner exactly matches the
+  // script we want to compile here.
+  return scriptable_parser->TakeInlineScriptStreamer(source);
+}
+
+}  // namespace
 
 // <specdef href="https://html.spec.whatwg.org/C/#fetch-a-classic-script">
 ClassicPendingScript* ClassicPendingScript::Fetch(
@@ -329,6 +345,7 @@
 
   TRACE_EVENT0("blink", "ClassicPendingScript::GetSource");
   if (!is_external_) {
+    InlineScriptStreamer* streamer = nullptr;
     SingleCachedMetadataHandler* cache_handler = nullptr;
     // We only create an inline cache handler for html-embedded scripts, not
     // for scripts produced by document.write, or not parser-inserted. This is
@@ -341,19 +358,23 @@
     if (source_location_type_ == ScriptSourceLocationType::kInline) {
       cache_handler = GetInlineCacheHandler(source_text_for_inline_script_,
                                             GetElement()->GetDocument());
+      streamer = GetInlineScriptStreamer(source_text_for_inline_script_,
+                                         GetElement()->GetDocument());
     }
 
     DCHECK(!GetResource());
     ScriptStreamer::RecordStreamingHistogram(
-        GetSchedulingType(), false,
+        GetSchedulingType(), streamer,
         ScriptStreamer::NotStreamingReason::kInlineScript);
 
     return ClassicScript::Create(
         source_text_for_inline_script_,
         ClassicScript::StripFragmentIdentifier(document_url),
         base_url_for_inline_script_, options_, source_location_type_,
-        SanitizeScriptErrors::kDoNotSanitize, cache_handler,
-        StartingPosition());
+        SanitizeScriptErrors::kDoNotSanitize, cache_handler, StartingPosition(),
+        streamer ? ScriptStreamer::NotStreamingReason::kInvalid
+                 : ScriptStreamer::NotStreamingReason::kInlineScript,
+        streamer);
   }
 
   DCHECK(GetResource()->IsLoaded());
@@ -370,10 +391,10 @@
   }
 
   // Check if we can use the script streamer.
-  ScriptStreamer* streamer;
+  ResourceScriptStreamer* streamer;
   ScriptStreamer::NotStreamingReason not_streamed_reason;
-  std::tie(streamer, not_streamed_reason) =
-      ScriptStreamer::TakeFrom(resource, mojom::blink::ScriptType::kClassic);
+  std::tie(streamer, not_streamed_reason) = ResourceScriptStreamer::TakeFrom(
+      resource, mojom::blink::ScriptType::kClassic);
 
   if (ready_state_ == kErrorOccurred) {
     not_streamed_reason = ScriptStreamer::NotStreamingReason::kErrorOccurred;
diff --git a/third_party/blink/renderer/core/script/classic_script.cc b/third_party/blink/renderer/core/script/classic_script.cc
index 7120804..bb72079 100644
--- a/third_party/blink/renderer/core/script/classic_script.cc
+++ b/third_party/blink/renderer/core/script/classic_script.cc
@@ -79,21 +79,22 @@
     SanitizeScriptErrors sanitize_script_errors,
     SingleCachedMetadataHandler* cache_handler,
     const TextPosition& start_position,
-    ScriptStreamer::NotStreamingReason not_streaming_reason) {
+    ScriptStreamer::NotStreamingReason not_streaming_reason,
+    InlineScriptStreamer* streamer) {
   // External files should use CreateFromResource().
   DCHECK(source_location_type != ScriptSourceLocationType::kExternalFile);
 
   return MakeGarbageCollected<ClassicScript>(
       ParkableString(source_text.Impl()), source_url, base_url, fetch_options,
       source_location_type, sanitize_script_errors, cache_handler,
-      start_position, nullptr, not_streaming_reason);
+      start_position, streamer, not_streaming_reason);
 }
 
 ClassicScript* ClassicScript::CreateFromResource(
     ScriptResource* resource,
     const KURL& base_url,
     const ScriptFetchOptions& fetch_options,
-    ScriptStreamer* streamer,
+    ResourceScriptStreamer* streamer,
     ScriptStreamer::NotStreamingReason not_streamed_reason,
     ScriptCacheConsumer* cache_consumer) {
   DCHECK_EQ(!streamer, not_streamed_reason !=
diff --git a/third_party/blink/renderer/core/script/classic_script.h b/third_party/blink/renderer/core/script/classic_script.h
index 84a5ce28..cfe5214 100644
--- a/third_party/blink/renderer/core/script/classic_script.h
+++ b/third_party/blink/renderer/core/script/classic_script.h
@@ -34,11 +34,12 @@
       SingleCachedMetadataHandler* = nullptr,
       const TextPosition& start_position = TextPosition::MinimumPosition(),
       ScriptStreamer::NotStreamingReason =
-          ScriptStreamer::NotStreamingReason::kInlineScript);
+          ScriptStreamer::NotStreamingReason::kInlineScript,
+      InlineScriptStreamer* = nullptr);
   static ClassicScript* CreateFromResource(ScriptResource*,
                                            const KURL& base_url,
                                            const ScriptFetchOptions&,
-                                           ScriptStreamer*,
+                                           ResourceScriptStreamer*,
                                            ScriptStreamer::NotStreamingReason,
                                            ScriptCacheConsumer*);
 
diff --git a/third_party/blink/tools/blinkpy/common/checkout/baseline_optimizer.py b/third_party/blink/tools/blinkpy/common/checkout/baseline_optimizer.py
index 78daae0..f3569bdc 100644
--- a/third_party/blink/tools/blinkpy/common/checkout/baseline_optimizer.py
+++ b/third_party/blink/tools/blinkpy/common/checkout/baseline_optimizer.py
@@ -40,9 +40,7 @@
         self._filesystem = host.filesystem
         self._default_port = default_port
         # To ensure the flag-specific baselines join the fallback graph in the
-        # same location each time the optimizer runs, we create a separate port
-        # fixed to Linux. Flag-specific suites only run on Linux builders at
-        # this time.
+        # same location each time the optimizer runs, we create a separate port.
         self._flag_spec_port = self._make_flag_spec_port(host, default_port)
         self._ports = {}
         for port_name in port_names:
@@ -83,11 +81,15 @@
         # TODO(robertma): Investigate changing the CLI.
         assert not suffix.startswith('.')
         extension = '.' + suffix
+        succeeded = True
+
+        if self._flag_spec_port:
+            self._optimize_flag_specific_baselines(test_name, extension)
+            return True
 
         baseline_name = self._default_port.output_filename(
             test_name, self._default_port.BASELINE_SUFFIX, extension)
         non_virtual_baseline_name = self._virtual_base(baseline_name)
-        succeeded = True
         if non_virtual_baseline_name:
             # The baseline belongs to a virtual suite.
             _log.debug('Optimizing virtual fallback path.')
@@ -103,9 +105,6 @@
                                             non_virtual_baseline_name)
         self._remove_extra_result_at_root(test_name, non_virtual_baseline_name)
 
-        if self._flag_spec_port:
-            self._optimize_flag_specific_baselines(test_name, extension)
-
         if not succeeded:
             _log.error('Heuristics failed to optimize %s', baseline_name)
         return succeeded
diff --git a/third_party/blink/tools/blinkpy/common/checkout/baseline_optimizer_unittest.py b/third_party/blink/tools/blinkpy/common/checkout/baseline_optimizer_unittest.py
index 3c34d6d..7b317bb 100644
--- a/third_party/blink/tools/blinkpy/common/checkout/baseline_optimizer_unittest.py
+++ b/third_party/blink/tools/blinkpy/common/checkout/baseline_optimizer_unittest.py
@@ -75,7 +75,11 @@
             'Fake Test Linux HighDPI': {
                 'port_name': 'linux-trusty',
                 'specifiers': ['Trusty', 'Release'],
-                'flag_specific': 'highdpi',
+                'steps': {
+                    'high_dpi_blink_web_tests (with patch)': {
+                        'flag_specific': 'highdpi',
+                    },
+                },
             },
             'Fake Test Mac12.0': {
                 'port_name': 'mac-mac12',
diff --git a/third_party/blink/tools/blinkpy/common/config/builders.json b/third_party/blink/tools/blinkpy/common/config/builders.json
index 5c0d6745..93c5d56af 100644
--- a/third_party/blink/tools/blinkpy/common/config/builders.json
+++ b/third_party/blink/tools/blinkpy/common/config/builders.json
@@ -63,7 +63,9 @@
         "main": "tryserver.chromium.linux",
         "port_name": "fuchsia",
         "specifiers": ["Fuchsia", "Release"],
-        "step_name": "blink_web_tests (with patch)",
+        "steps": {
+            "blink_web_tests (with patch)": {}
+        },
         "is_try_builder": true
     },
     "linux-wpt-identity-fyi-rel": {
@@ -71,14 +73,18 @@
         "port_name": "linux-trusty",
         "specifiers": ["Trusty", "Release"],
         "is_try_builder": true,
-        "step_name": "wpt_tests_suite (with patch)"
+        "steps": {
+            "wpt_tests_suite (with patch)": {}
+        }
     },
     "linux-wpt-input-fyi-rel": {
         "main": "tryserver.chromium.linux",
         "port_name": "linux-trusty",
         "specifiers": ["Trusty", "Release"],
         "is_try_builder": true,
-        "step_name": "wpt_tests_suite (with patch, experimental)"
+        "steps": {
+            "wpt_tests_suite (with patch, experimental)": {}
+        }
     },
     "linux-blink-rel": {
         "main": "tryserver.blink",
@@ -152,7 +158,18 @@
         "port_name": "linux-trusty",
         "specifiers": ["Trusty", "Release"],
         "has_webdriver_tests": true,
-        "step_name": "blink_web_tests (with patch)",
+        "steps": {
+            "blink_web_tests (with patch)": {},
+            "high_dpi_blink_web_tests (with patch)": {
+                "flag_specific": "highdpi"
+            },
+            "vulkan_swiftshader_blink_web_tests (with patch)": {
+                "flag_specific": "skia-vulkan-swiftshader"
+            },
+            "not_site_per_process_blink_web_tests (with patch)": {
+                "flag_specific": "disable-site-isolation-trials"
+            }
+        },
         "is_try_builder": true,
         "is_cq_builder":true
     },
@@ -174,8 +191,11 @@
         "main": "tryserver.chromium.linux",
         "port_name": "linux-trusty",
         "specifiers": ["Trusty", "Release"],
-        "flag_specific": "disable-layout-ng",
-        "step_name": "blink_web_tests (with patch)",
+        "steps": {
+            "blink_web_tests (with patch)": {
+                "flag_specific": "disable-layout-ng"
+            }
+        },
         "is_try_builder": true,
         "is_cq_builder":true
     },
@@ -204,7 +224,11 @@
         "main": "tryserver.blink",
         "port_name": "linux-trusty",
         "specifiers": ["Trusty", "Release"],
-        "flag_specific": "highdpi",
+        "steps": {
+            "high_dpi_blink_web_tests (with patch)": {
+                "flag_specific": "highdpi"
+            }
+        },
         "is_try_builder": true
     }
 }
diff --git a/third_party/blink/tools/blinkpy/common/host_mock.py b/third_party/blink/tools/blinkpy/common/host_mock.py
index c5efb2f5..85f074a3 100644
--- a/third_party/blink/tools/blinkpy/common/host_mock.py
+++ b/third_party/blink/tools/blinkpy/common/host_mock.py
@@ -59,8 +59,6 @@
         self.web = web or MockWeb()
         self._git = git
 
-        self.results_fetcher = MockTestResultsFetcher()
-
         # Note: We're using a real PortFactory here. Tests which don't wish to depend
         # on the list of known ports should override this with a MockPortFactory.
         self.port_factory = PortFactory(self)
@@ -99,7 +97,24 @@
                 'specifiers': ['KitKat', 'Release'],
                 'is_try_builder': True,
             },
+            # For the try flag unit tests.
+            'linux-rel': {
+                'port_name': 'linux-trusty',
+                'specifiers': ['Trusty', 'Release'],
+                'is_try_builder': True,
+            },
+            'win7-rel': {
+                'port_name': 'win-win7',
+                'specifiers': ['Win7', 'Release'],
+                'is_try_builder': True,
+            },
+            'mac-rel': {
+                'port_name': 'mac-mac12',
+                'specifiers': ['Trusty', 'Release'],
+                'is_try_builder': True,
+            },
         })
+        self.results_fetcher = MockTestResultsFetcher(self.builders)
 
     def git(self, path=None):
         if path:
diff --git a/third_party/blink/tools/blinkpy/common/net/git_cl_mock.py b/third_party/blink/tools/blinkpy/common/net/git_cl_mock.py
index 4c1875f..7661697 100644
--- a/third_party/blink/tools/blinkpy/common/net/git_cl_mock.py
+++ b/third_party/blink/tools/blinkpy/common/net/git_cl_mock.py
@@ -66,7 +66,15 @@
         return 'closed'
 
     def latest_try_jobs(self, builder_names=None, **_):
-        return self.filter_latest(self._try_job_results)
+        if builder_names:
+            jobs = {
+                build: status
+                for build, status in self._try_job_results.items()
+                if build.builder_name in builder_names
+            }
+        else:
+            jobs = self._try_job_results
+        return self.filter_latest(jobs)
 
     @staticmethod
     def filter_latest(try_results):
diff --git a/third_party/blink/tools/blinkpy/common/net/results_fetcher.py b/third_party/blink/tools/blinkpy/common/net/results_fetcher.py
index fe8b8d1..bd62869 100644
--- a/third_party/blink/tools/blinkpy/common/net/results_fetcher.py
+++ b/third_party/blink/tools/blinkpy/common/net/results_fetcher.py
@@ -76,10 +76,10 @@
         https://www.chromium.org/developers/the-json-test-results-format
     """
 
-    def __init__(self):
+    def __init__(self, builders=None):
         self.web = Web()
-        self.builders = BuilderList.load_default_builder_list(FileSystem())
-        self._webtest_results_resultdb = None
+        self.builders = builders or BuilderList.load_default_builder_list(
+            FileSystem())
 
     def results_url(self, builder_name, build_number=None, step_name=None):
         """Returns a URL for one set of archived web test results.
@@ -92,9 +92,6 @@
             assert str(build_number).isdigit(), \
                 'expected numeric build number, got %s' % build_number
             url_base = self.builder_results_url_base(builder_name)
-            if step_name is None:
-                step_name = self.get_layout_test_step_name(
-                    Build(builder_name, build_number))
             if step_name:
                 return '%s/%s/%s/layout-test-results' % (
                     url_base, build_number,
@@ -200,15 +197,16 @@
     @memoized
     def fetch_results_from_resultdb_layout_tests(self, host, build,
                                                  unexpected_results):
-        rv = []
         if unexpected_results:
             predicate = PREDICATE_UNEXPECTED_RESULTS
         else:
             predicate = ""
         rv = self.fetch_results_from_resultdb(host, [build], predicate)
-        self._webtest_results_resultdb = WebTestResults.results_from_resultdb(
-            rv)
-        return self._webtest_results_resultdb
+        # Rebaselining should still work correctly on this object, even though
+        # it holds results for possibly multiple steps. ResultDB only exposes
+        # the test suite name (like 'blink_web_tests'), not the full step name
+        # with the '(with patch)' suffix.
+        return WebTestResults.results_from_resultdb(rv)
 
     def fetch_results_from_resultdb(self, host, builds, predicate):
         """Returns a list of test results from ResultDB
@@ -271,7 +269,6 @@
         if not build.builder_name or not build.build_number:
             _log.debug('Builder name or build number is None')
             return None
-        step_name = step_name or self.get_layout_test_step_name(build)
         return self.fetch_web_test_results(
             self.results_url(
                 build.builder_name,
@@ -279,16 +276,16 @@
                 step_name=step_name), full, step_name)
 
     @memoized
-    def get_layout_test_step_name(self, build):
+    def get_layout_test_step_names(self, build):
         if not build.builder_name or not build.build_number:
             _log.debug('Builder name or build number is None')
-            return None
+            return []
 
-        # We were not able to retrieve step name for some builders from
+        # We were not able to retrieve step names for some builders from
         # https://test-results.appspot.com. Read from config file instead
-        step_name = self.builders.step_name_for_builder(build.builder_name)
-        if step_name:
-            return step_name
+        step_names = self.builders.step_names_for_builder(build.builder_name)
+        if step_names:
+            return step_names
 
         url = '%s/testfile?%s' % (
             TEST_RESULTS_SERVER,
@@ -302,7 +299,7 @@
         data = self.web.get_binary(url, return_none_on_404=True)
         if not data:
             _log.debug('Got 404 response from:\n%s', url)
-            return None
+            return []
 
         # Strip out the callback
         data = json.loads(json_results_generator.strip_json_wrapper(data))
@@ -313,18 +310,18 @@
             # runs with a patch. This should be changed eventually to use actual
             # structured data from the test results server.
             if re.match(
-                r'(blink_web_tests|wpt_tests_suite|high_dpi_blink_web_tests).*\(with patch\)$',
+                r'([\w\-]*blink_web_tests|wpt_tests_suite).*\(with patch\)$',
                 entry['TestType'])
         ]
         # In manual testing, I sometimes saw results where the same suite was
         # repeated twice. De-duplicate here to try to catch this.
         suites = list(set(suites))
-        if len(suites) != 1:
+        if not suites:
             raise Exception(
-                'build %s on builder %s expected to only have one web test '
-                'step, instead has %s' % (build.build_number,
-                                          build.builder_name, suites))
-        return suites[0]
+                'build %s on builder %s expected to have at least one web test '
+                'step, instead has none' %
+                (build.builder_number, build.builder_name))
+        return suites
 
     @memoized
     def fetch_web_test_results(self, results_url, full=False, step_name=None):
diff --git a/third_party/blink/tools/blinkpy/common/net/results_fetcher_mock.py b/third_party/blink/tools/blinkpy/common/net/results_fetcher_mock.py
index 6efd260..514c923c 100644
--- a/third_party/blink/tools/blinkpy/common/net/results_fetcher_mock.py
+++ b/third_party/blink/tools/blinkpy/common/net/results_fetcher_mock.py
@@ -35,40 +35,42 @@
 # TODO(qyearsley): To be consistent with other fake ("mock") classes, this
 # could be changed so it's not a subclass of TestResultsFetcher.
 class MockTestResultsFetcher(TestResultsFetcher):
-    def __init__(self):
-        super(MockTestResultsFetcher, self).__init__()
+    def __init__(self, builders=None):
+        super(MockTestResultsFetcher, self).__init__(builders)
         self._canned_results = {}
         self._canned_artifacts_resultdb = {}
         self._canned_retry_summary_json = {}
         self._webdriver_results = {}
         self.fetched_builds = []
         self.fetched_webdriver_builds = []
-        self._layout_test_step_name = 'blink_web_tests (with patch)'
 
     def set_results(self, build, results, step_name=None):
-        step_name = step_name or self.get_layout_test_step_name(build)
+        step_name = step_name or results.step_name()
         step = BuilderStep(build=build, step_name=step_name)
         self._canned_results[step] = results
 
     def fetch_results(self, build, full=False, step_name=None):
-        step_name = step_name or self.get_layout_test_step_name(build)
         step = BuilderStep(build=build, step_name=step_name)
         self.fetched_builds.append(step)
         return self._canned_results.get(step)
 
     def set_results_to_resultdb(self, build, results):
-        self._canned_results[build.build_id] = results
+        # The step name is not relevant for ResultDB, so just set it to None.
+        step = BuilderStep(build, step_name=None)
+        self._canned_results[step] = results
 
     def fetch_results_from_resultdb(self, host, builds, predicate):
         rv = []
         for build in builds:
-            results = self._canned_results.get(build.build_id)
+            step = BuilderStep(build, step_name=None)
+            results = self._canned_results.get(step)
             if results:
                 rv.extend(results)
         return rv
 
     def fetch_results_from_resultdb_layout_tests(self, host, build, predicate):
-        return self._canned_results.get(build.build_id)
+        step = BuilderStep(build, step_name=None)
+        return self._canned_results.get(step)
 
     def get_artifact_list_for_test(self, host, result_id):
         return self._canned_artifacts_resultdb[result_id]
@@ -89,8 +91,8 @@
     def fetch_retry_summary_json(self, build):
         return self._canned_retry_summary_json.get(build)
 
-    def set_layout_test_step_name(self, name):
-        self._layout_test_step_name = name
-
-    def get_layout_test_step_name(self, build):
-        return self._layout_test_step_name
+    def get_layout_test_step_names(self, build):
+        return [
+            step.step_name for step in self._canned_results
+            if build == step.build
+        ]
diff --git a/third_party/blink/tools/blinkpy/common/net/results_fetcher_test.py b/third_party/blink/tools/blinkpy/common/net/results_fetcher_test.py
index 912c64e..d0ee3d76 100644
--- a/third_party/blink/tools/blinkpy/common/net/results_fetcher_test.py
+++ b/third_party/blink/tools/blinkpy/common/net/results_fetcher_test.py
@@ -90,7 +90,7 @@
 
     def test_fetch_results_with_weird_step_name(self):
         fetcher = TestResultsFetcher()
-        fetcher.builders.step_name_for_builder = lambda builder: None
+        fetcher.builders.step_names_for_builder = lambda builder: []
         fetcher.web = MockWeb(
             urls={
                 'https://test-results.appspot.com/testfile?buildnumber=123&'
@@ -108,7 +108,9 @@
                     'passed': True
                 }).encode('utf8', 'replace')
             })
-        results = fetcher.fetch_results(Build('builder', 123))
+        step_name = 'blink_web_tests on Intel GPU (with patch)'
+        results = fetcher.fetch_results(Build('builder', 123), False,
+                                        step_name)
         self.assertEqual(
             results._results,  # pylint: disable=protected-access
             {'passed': True})
@@ -118,9 +120,9 @@
         fetcher = TestResultsFetcher()
         self.assertIsNone(fetcher.fetch_results(Build('builder', None)))
 
-    def test_get_step_name(self):
+    def test_get_step_names(self):
         fetcher = TestResultsFetcher()
-        fetcher.builders.step_name_for_builder = lambda builder: None
+        fetcher.builders.step_names_for_builder = lambda builder: []
         fetcher.web = MockWeb(
             urls={
                 'https://test-results.appspot.com/testfile?buildnumber=5&'
@@ -137,13 +139,16 @@
                     "TestType": "base_unittests (with patch)"
                 }]).encode('utf8', 'replace') + b');'
             })
-        step_name = fetcher.get_layout_test_step_name(Build('foo', 5))
-        self.assertEqual(step_name, 'blink_web_tests (with patch)')
+        step_names = fetcher.get_layout_test_step_names(Build('foo', 5))
+        self.assertEqual(sorted(step_names), [
+            'blink_web_tests (with patch)',
+            'not_site_per_process_blink_web_tests (with patch)',
+        ])
         self.assertLog([])
 
-    def test_get_step_name_for_wpt(self):
+    def test_get_step_names_for_wpt(self):
         fetcher = TestResultsFetcher()
-        fetcher.builders.step_name_for_builder = lambda builder: None
+        fetcher.builders.step_names_for_builder = lambda builder: []
         fetcher.web = MockWeb(
             urls={
                 'https://test-results.appspot.com/testfile?buildnumber=5&'
@@ -157,14 +162,14 @@
                     "TestType": "base_unittests (with patch)"
                 }])).encode('utf8', 'replace') + b');'
             })
-        step_name = fetcher.get_layout_test_step_name(Build('foo', 5))
-        self.assertEqual(step_name, 'wpt_tests_suite (with patch)')
+        step_names = fetcher.get_layout_test_step_names(Build('foo', 5))
+        self.assertEqual(step_names, ['wpt_tests_suite (with patch)'])
         self.assertLog([])
 
-    def test_get_step_name_without_build_number(self):
+    def test_get_step_names_without_build_number(self):
         fetcher = TestResultsFetcher()
-        self.assertIsNone(
-            fetcher.get_layout_test_step_name(Build('builder', None)))
+        self.assertEqual(
+            fetcher.get_layout_test_step_names(Build('builder', None)), [])
 
     def test_fetch_webdriver_results_without_build_number(self):
         fetcher = TestResultsFetcher()
diff --git a/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py b/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py
index 6caf70f..5d787ee 100644
--- a/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py
+++ b/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py
@@ -93,7 +93,7 @@
               'should be used to retrieve results from.'))
     flag_specific_option = optparse.make_option(
         '--flag-specific',
-        # TODO: build the list from builders.json
+        # TODO(crbug/1291020): build the list from builders.json
         choices=[
             "disable-layout-ng", "disable-site-isolation-trials", "highdpi",
             "skia-vulkan-swiftshader"
@@ -214,7 +214,7 @@
         # Set self._port to None to avoid accidentally calling port.tests when
         # we are not in prefix mode.
         self._port = self._host.port_factory.get() if prefix_mode else None
-        self._builder_names = set()
+        self._build_steps = set()
         self._prefix_mode = prefix_mode
         self._test_prefix_map = collections.defaultdict(list)
 
@@ -225,22 +225,22 @@
         return bool(self._test_prefix_map)
 
     def _iter_combinations(self):
-        """Iterates through (test, build, port) combinations."""
-        for test_prefix, build_port_pairs in self._test_prefix_map.items():
+        """Iterates through (test, build, step, port) combinations."""
+        for test_prefix, build_steps in self._test_prefix_map.items():
             if not self._prefix_mode:
-                for build, port_name in build_port_pairs:
-                    yield (test_prefix, build, port_name)
+                for build_step in build_steps:
+                    yield (test_prefix, ) + build_step
                 continue
 
             for test in self._port.tests([test_prefix]):
-                for build, port_name in build_port_pairs:
-                    yield (test, build, port_name)
+                for build_step in build_steps:
+                    yield (test, ) + build_step
 
     def __str__(self):
         if not self._test_prefix_map:
             return '<Empty TestBaselineSet>'
         return '<TestBaselineSet with:\n  %s>' % '\n  '.join(
-            '%s: %s, %s' % triple for triple in self._iter_combinations())
+            '%s: %s, %s, %s' % combo for combo in self._iter_combinations())
 
     def test_prefixes(self):
         """Returns a sorted list of test prefixes (or tests) added thus far."""
@@ -258,26 +258,30 @@
 
     def build_port_pairs(self, test_prefix):
         # Return a copy in case the caller modifies the returned list.
-        return list(self._test_prefix_map[test_prefix])
+        return [(build, port)
+                for build, _, port in self._test_prefix_map[test_prefix]]
 
-    def add(self, test_prefix, build, port_name=None):
+    def add(self, test_prefix, build, step_name=None, port_name=None):
         """Adds an entry for baselines to download for some set of tests.
 
         Args:
             test_prefix: This can be a full test path; if the instance was
                 constructed in prefix mode (the default), this can also be a
                 directory of tests or a path with globs.
-            build: A Build object. This specifies where to fetch baselines from.
+            build: A Build object. Along with the step name, this specifies
+                where to fetch baselines from.
+            step_name: The name of the build step this test was run for.
             port_name: This specifies what platform the baseline is for.
         """
         port_name = port_name or self._host.builders.port_name_for_builder_name(
             build.builder_name)
-        self._builder_names.add(build.builder_name)
-        self._test_prefix_map[test_prefix].append((build, port_name))
+        self._build_steps.add((build.builder_name, step_name))
+        build_step = (build, step_name, port_name)
+        self._test_prefix_map[test_prefix].append(build_step)
 
-    def all_builders(self):
-        """Returns all builder names in in this collection."""
-        return self._builder_names
+    def all_build_steps(self):
+        """Returns all builder name, step name pairs in this collection."""
+        return self._build_steps
 
 
 class AbstractParallelRebaselineCommand(AbstractRebaseliningCommand):
@@ -301,42 +305,54 @@
                 release_builders.append(builder_name)
         return release_builders
 
-    def _builders_to_fetch_from(self, builders_to_check):
-        """Returns the subset of builders that will cover all of the baseline
-        search paths used in the input list.
+    def _filter_baseline_set_builders(self, test_baseline_set):
+        build_steps_to_fetch_from = self.build_steps_to_fetch_from(
+            test_baseline_set.all_build_steps())
+        for test_prefix, build, step_name, port_name in test_baseline_set:
+            if (build.builder_name, step_name) in build_steps_to_fetch_from:
+                yield (test_prefix, build, step_name, port_name)
+
+    def build_steps_to_fetch_from(self, build_steps_to_check):
+        """Returns the subset of builder-step pairs that will cover all of the
+        baseline search paths used in the input list.
 
         In particular, if the input list contains both Release and Debug
         versions of a configuration, we *only* return the Release version
         (since we don't save debug versions of baselines).
 
         Args:
-            builders_to_check: A collection of builder names.
+            build_steps_to_check: A collection of builder name, step name
+                tuples.
 
         Returns:
-            A set of builders that we may fetch from, which is a subset
-            of the input list.
+            A subset of the input list that we should fetch from.
         """
-        release_builders = set()
-        debug_builders = set()
-        for builder in builders_to_check:
+        release_build_steps = set()
+        debug_build_steps = set()
+        for builder, step in build_steps_to_check:
             port = self._tool.port_factory.get_from_builder_name(builder)
             if port.test_configuration().build_type == 'release':
-                release_builders.add(builder)
+                release_build_steps.add((builder, step))
             else:
-                debug_builders.add(builder)
+                debug_build_steps.add((builder, step))
 
-        builders_to_fallback_paths = {}
-        wpt_builders = set()
-        for builder in list(release_builders) + list(debug_builders):
+        build_steps_to_fallback_paths = {}
+        wpt_build_steps = set()
+        for builder, step in list(release_build_steps) + list(
+                debug_build_steps):
             if not self._tool.builders.is_wpt_builder(builder):
+                flag_spec_option = self._tool.builders.flag_specific_option(
+                    builder, step)
                 port = self._tool.port_factory.get_from_builder_name(builder)
+                port.set_option_default('flag_specific', flag_spec_option)
                 fallback_path = port.baseline_search_path()
                 if fallback_path not in list(
-                        builders_to_fallback_paths.values()):
-                    builders_to_fallback_paths[builder] = fallback_path
+                        build_steps_to_fallback_paths.values()):
+                    build_steps_to_fallback_paths[builder,
+                                                  step] = fallback_path
             else:
-                wpt_builders.add(builder)
-        return set(builders_to_fallback_paths) | wpt_builders
+                wpt_build_steps.add((builder, step))
+        return set(build_steps_to_fallback_paths) | wpt_build_steps
 
     def baseline_fetch_url_resultdb(self, test_name, build):
         # TODO(preethim): Consider doing QueryArtifacts do a walk of that list for
@@ -359,33 +375,66 @@
                         done = True
         return artifact_fetch_urls
 
+    def _can_optimize(self, builder_name):
+        # TODO(crbug.com/1154085): Undo this special case when we have WPT
+        # bots on more ports.
+        # We may be rebaselining only a subset of all platforms, in which
+        # case we need to copy any existing baselines first to avoid clobbering
+        # results from platforms that were not run. See
+        # https://chromium.googlesource.com/chromium/src/+/main/docs/testing/web_test_baseline_fallback.md#rebaseline
+        #
+        # However when running in modes that don't interact with the optimizer,
+        # we don't want to do this copying.
+        return not self._tool.builders.is_wpt_builder(builder_name)
+
+    def _rebaseline_args(self,
+                         test,
+                         suffixes,
+                         port_name=None,
+                         flag_specific=None,
+                         verbose=False):
+        args = []
+        if verbose:
+            args.append('--verbose')
+        args.extend([
+            '--test',
+            test,
+            # Sort suffixes so we can have a deterministic order for comparing
+            # commands in unit tests.
+            '--suffixes',
+            ','.join(sorted(suffixes)),
+        ])
+        if port_name:
+            args.extend(['--port-name', port_name])
+        if flag_specific:
+            args.extend(['--flag-specific', flag_specific])
+        return args
+
     def _rebaseline_commands(self, test_baseline_set, options):
+        test_port_pairs_to_suffixes = collections.defaultdict(set)
         path_to_blink_tool = self._tool.path()
         cwd = self._tool.git().checkout_root
-        copy_baseline_commands = []
         rebaseline_commands = []
         lines_to_remove = {}
         fetch_urls = []
-        suffixes = []
 
-        builders_to_fetch_from = self._builders_to_fetch_from(
-            test_baseline_set.all_builders())
-        for test, build, port_name in test_baseline_set:
-            if build.builder_name not in builders_to_fetch_from:
-                continue
-
+        # A test baseline set is a high-dimensional object, so we try to avoid
+        # iterating it.
+        baseline_subset = self._filter_baseline_set_builders(test_baseline_set)
+        for test, build, step_name, port_name in baseline_subset:
             if options.resultDB:
                 fetch_urls = self.baseline_fetch_url_resultdb(test, build)
                 suffixes = list(
                     self._suffixes_for_actual_failures_resultdb(test, build))
             else:
-                suffixes = list(self._suffixes_for_actual_failures(
-                    test, build))
+                suffixes = list(
+                    self._suffixes_for_actual_failures(test, build, step_name))
             if not suffixes:
                 # Only try to remove the expectation if the test
                 #   1. ran and passed ([ Skip ], [ WontFix ] should be kept)
                 #   2. passed unexpectedly (flaky expectations should be kept)
-                if self._test_passed_unexpectedly(test, build, port_name):
+                if self._test_passed_unexpectedly(test, build, port_name,
+                                                  step_name):
                     _log.debug(
                         'Test %s passed unexpectedly in %s. '
                         'Will try to remove it from TestExpectations.', test,
@@ -395,53 +444,18 @@
                     lines_to_remove[test].append(port_name)
                 continue
 
-            # Sorting it here so we can have a deterministic order for comparing
-            # the suffixes in unit tests.
-            suffixes.sort()
-            args = []
-            if options.verbose:
-                args.append('--verbose')
-            args.extend([
-                '--test',
-                test,
-                '--suffixes',
-                ','.join(suffixes),
-                '--port-name',
-                port_name,
-            ])
-            # TODO(crbug.com/1154085): Undo this special case when we have WPT
-            # bots on more ports.
-            # We may be rebaselining only a subset of all platforms, in which
-            # case we need to copy any existing baselines first to avoid clobbering
-            # results from platforms that were not run. See
-            # https://chromium.googlesource.com/chromium/src/+/main/docs/testing/web_test_baseline_fallback.md#rebaseline
-            #
-            # However when running in modes that don't interact with the optimizer,
-            # we don't want to do this copying.
-            if (not self._tool.builders.is_wpt_builder(build.builder_name)
-                    and not self._tool.builders.is_flag_specific_builder(
-                        build.builder_name)):
-                copy_command = [
-                    self._tool.executable, path_to_blink_tool,
-                    'copy-existing-baselines-internal'
-                ] + args
-                copy_baseline_commands.append(tuple([copy_command, cwd]))
+            if suffixes and self._can_optimize(build.builder_name):
+                test_port_pairs_to_suffixes[test, port_name].update(suffixes)
 
+            flag_spec_option = self._tool.builders.flag_specific_option(
+                build.builder_name, step_name)
+            args = self._rebaseline_args(test, suffixes, port_name,
+                                         flag_spec_option, options.verbose)
             args.extend(['--builder', build.builder_name])
             if build.build_number:
                 args.extend(['--build-number', str(build.build_number)])
             if options.results_directory:
                 args.extend(['--results-directory', options.results_directory])
-
-            if (options.flag_specific
-                    and self._tool.builders.is_flag_specific_builder(
-                        build.builder_name)):
-                args.extend(['--flag-specific', options.flag_specific])
-
-            step_name = ""
-            if not options.resultDB:
-                step_name = self._tool.results_fetcher.get_layout_test_step_name(
-                    build)
             if step_name:
                 args.extend(['--step-name', step_name])
 
@@ -453,7 +467,22 @@
                 self._tool.executable, path_to_blink_tool,
                 'rebaseline-test-internal'
             ] + args
-            rebaseline_commands.append(tuple([rebaseline_command, cwd]))
+            rebaseline_commands.append((rebaseline_command, cwd))
+
+        copy_baseline_commands = []
+        for (test, port_name), suffixes in sorted(
+                test_port_pairs_to_suffixes.items()):
+            copy_command = [
+                self._tool.executable,
+                path_to_blink_tool,
+                'copy-existing-baselines-internal',
+            ]
+            copy_command.extend(
+                self._rebaseline_args(test,
+                                      suffixes,
+                                      port_name,
+                                      verbose=options.verbose))
+            copy_baseline_commands.append((copy_command, cwd))
 
         return copy_baseline_commands, rebaseline_commands, lines_to_remove
 
@@ -477,56 +506,49 @@
                 _log.debug('Could not add file based off output "%s"', stdout)
         return change_set
 
-    def _optimize_baselines(self,
-                            test_baseline_set,
-                            verbose=False,
-                            resultDB=False):
+    def _optimize_commands(self,
+                           test_baseline_set,
+                           verbose=False,
+                           resultDB=False):
         """Returns a list of commands to run in parallel to de-duplicate baselines."""
-        tests_to_suffixes = collections.defaultdict(set)
-        builders_to_fetch_from = self._builders_to_fetch_from(
-            test_baseline_set.all_builders())
-        for test, build, _ in test_baseline_set:
-            if build.builder_name not in builders_to_fetch_from:
+        # Group suffixes together to invoke fewer commands.
+        test_flag_pairs_to_suffixes = collections.defaultdict(set)
+        baseline_subset = self._filter_baseline_set_builders(test_baseline_set)
+        for test, build, step_name, _ in baseline_subset:
+            if not self._can_optimize(build.builder_name):
                 continue
 
-            # TODO(crbug.com/1154085): Undo this special case when we have WPT
-            # bots on more ports.
-            if self._tool.builders.is_wpt_builder(build.builder_name):
-                continue
-
-            # For flag_specific we skip both 'copy existing baselines'
-            # and  optimizer.
-            if self._tool.builders.is_flag_specific_builder(
-                    build.builder_name):
-                continue
-
+            flag_spec = self._tool.builders.flag_specific_option(
+                build.builder_name, step_name)
             if resultDB:
-                tests_to_suffixes[test].update(
+                test_flag_pairs_to_suffixes[test, flag_spec].update(
                     self._suffixes_for_actual_failures_resultdb(test, build))
             else:
-                tests_to_suffixes[test].update(
-                    self._suffixes_for_actual_failures(test, build))
+                test_flag_pairs_to_suffixes[test, flag_spec].update(
+                    self._suffixes_for_actual_failures(test, build, step_name))
 
         optimize_commands = []
-        for test, suffixes in tests_to_suffixes.items():
+        for (test, flag_spec), suffixes in test_flag_pairs_to_suffixes.items():
             # No need to optimize baselines for a test with no failures.
             if not suffixes:
                 continue
-            # FIXME: We should propagate the platform options as well.
-            # Prevent multiple baseline optimizer to race updating the manifest.
-            # The manifest has already been updated when listing tests.
-            args = ['--no-manifest-update']
-            if verbose:
-                args.append('--verbose')
-            suffixes_list = list(suffixes)
-            suffixes_list.sort()
-            args.extend(['--suffixes', ','.join(suffixes_list), test])
             path_to_blink_tool = self._tool.path()
-            cwd = self._tool.git().checkout_root
             command = [
-                self._tool.executable, path_to_blink_tool, 'optimize-baselines'
-            ] + args
-            optimize_commands.append(tuple([command, cwd]))
+                self._tool.executable,
+                path_to_blink_tool,
+                'optimize-baselines',
+                # FIXME: We should propagate the platform options as well.
+                # Prevent multiple baseline optimizer to race updating the manifest.
+                # The manifest has already been updated when listing tests.
+                '--no-manifest-update',
+            ]
+            if verbose:
+                command.append('--verbose')
+            if flag_spec:
+                command.extend(['--flag-specific', flag_spec])
+            command.extend(['--suffixes', ','.join(sorted(suffixes)), test])
+            cwd = self._tool.git().checkout_root
+            optimize_commands.append((command, cwd))
 
         return optimize_commands
 
@@ -596,8 +618,7 @@
             )
             return
 
-        # TODO: Consider optimizing here, it takes about 2 minutes for 500 tests
-        for test in sorted({t for t, _, _ in test_baseline_set}):
+        for test in test_baseline_set.all_tests():
             _log.info('Rebaselining %s', test)
 
         # extra_lines_to_remove are unexpected passes, while lines_to_remove are
@@ -619,8 +640,8 @@
 
         if options.optimize:
             self._run_in_parallel(
-                self._optimize_baselines(test_baseline_set, options.verbose,
-                                         options.resultDB))
+                self._optimize_commands(test_baseline_set, options.verbose,
+                                        options.resultDB))
 
         self._tool.git().add_list(self.unstaged_baselines())
 
@@ -670,17 +691,18 @@
                 suffixes.add('txt')
         return suffixes
 
-    def _suffixes_for_actual_failures(self, test, build):
+    def _suffixes_for_actual_failures(self, test, build, step_name=None):
         """Gets the baseline suffixes for actual mismatch failures in some results.
 
         Args:
             test: A full test path string.
             build: A Build object.
+            step_name: The name of the build step the test ran in.
 
         Returns:
             A set of file suffix strings.
         """
-        test_result = self._result_for_test(test, build)
+        test_result = self._result_for_test(test, build, step_name)
         if not test_result:
             return set()
         # Regardless of the test type, we only need the text output (i.e. the
@@ -690,7 +712,8 @@
             return {'txt'}
         return test_result.suffixes_for_test_result()
 
-    def _test_passed_unexpectedly(self, test, build, port_name):
+    def _test_passed_unexpectedly(self, test, build, port_name,
+                                  step_name=None):
         """Determines if a test passed unexpectedly in a build.
 
         The routine also takes into account the port that is being rebaselined.
@@ -702,6 +725,7 @@
             test: A full test path string.
             build: A Build object.
             port_name: The name of port currently being rebaselined.
+            step_name: The name of the build step the test ran in.
 
         Returns:
             A boolean.
@@ -709,16 +733,17 @@
         if self._tool.builders.port_name_for_builder_name(
                 build.builder_name) != port_name:
             return False
-        test_result = self._result_for_test(test, build)
+        test_result = self._result_for_test(test, build, step_name)
         if not test_result:
             return False
         return test_result.did_pass() and not test_result.did_run_as_expected()
 
     @memoized
-    def _result_for_test(self, test, build):
+    def _result_for_test(self, test, build, step_name=None):
         # We need full results to know if a test passed or was skipped.
         # TODO(robertma): Make memoized support kwargs, and use full=True here.
-        results = self._tool.results_fetcher.fetch_results(build, True)
+        results = self._tool.results_fetcher.fetch_results(
+            build, True, step_name)
         if not results:
             _log.debug('No results found for build %s', build)
             return None
@@ -771,8 +796,12 @@
         test_baseline_set = TestBaselineSet(tool)
 
         for builder in builders_to_check:
-            for test_prefix in args:
-                test_baseline_set.add(test_prefix, Build(builder))
+            build = Build(builder)
+            step_names = self._tool.results_fetcher.get_layout_test_step_names(
+                build)
+            for step_name in step_names:
+                for test_prefix in args:
+                    test_baseline_set.add(test_prefix, build, step_name)
 
         _log.debug('Rebaselining: %s', test_baseline_set)
 
diff --git a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py
index 58bbf4752..4a8d991 100644
--- a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py
+++ b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py
@@ -3,6 +3,8 @@
 # found in the LICENSE file.
 """A command to fetch new baselines from try jobs for the current CL."""
 
+import collections
+import itertools
 import json
 import logging
 import optparse
@@ -81,8 +83,11 @@
             optparse.make_option(
                 '--flag-specific',
                 dest='flag_specific',
-                # TODO: try to get the list from builders.json
-                choices=["disable-layout-ng", "highdpi"],
+                # TODO(crbug/1291020): try to get the list from builders.json
+                choices=[
+                    "disable-layout-ng", "highdpi",
+                    "disable-site-isolation-trials", "skia-vulkan-swiftshader"
+                ],
                 default=None,
                 action='store',
                 help=('Name of a flag-specific configuration defined in '
@@ -194,11 +199,6 @@
         if options.fill_missing:
             self.fill_in_missing_results(test_baseline_set)
 
-        for builder in test_baseline_set.all_builders():
-            if self._tool.builders.is_flag_specific_builder(builder):
-                options.flag_specific = self._tool.builders.flag_specific_option(
-                    builder)
-
         if not options.dry_run:
             self.rebaseline(options, test_baseline_set)
         return 0
@@ -291,40 +291,56 @@
             jobs: A dict mapping Build objects to TryJobStatus objects.
 
         Returns:
-            A dict mapping Build to WebTestResults for all completed jobs.
+            A dict mapping Builds to lists of WebTestResults for all completed
+            jobs.
         """
         results_fetcher = self._tool.results_fetcher
-        results = {}
-        results_url = ''
+        builds_to_results = collections.defaultdict(list)
 
         for build, status in jobs.items():
             if status == TryJobStatus('COMPLETED', 'SUCCESS'):
-                # Builds with passing try jobs are mapped to None, to indicate
-                # that there are no baselines to download.
-                results[build] = None
+                _log.debug('No baselines to download for passing %r build %s.',
+                           build.builder_name, build.build_number
+                           or '(unknown)')
+                # This empty entry indicates the builder is not missing.
+                builds_to_results[build] = []
                 continue
             if status != TryJobStatus('COMPLETED', 'FAILURE'):
                 # Only completed failed builds will contain actual failed
                 # web tests to download baselines for.
                 continue
-            if self._resultdb_fetcher:
-                web_test_results = results_fetcher.fetch_results_from_resultdb_layout_tests(
-                    self._tool, build, True)
-            else:
-                results_url = results_fetcher.results_url(
-                    build.builder_name, build.build_number)
-                web_test_results = results_fetcher.fetch_results(build)
 
-            if web_test_results is None:
-                _log.info('Failed to fetch results for "%s".',
-                          build.builder_name)
-                _log.info('Results URL: %s/results.html', results_url)
-                continue
-            results[build] = web_test_results
-        return results
+            step_names = results_fetcher.get_layout_test_step_names(build)
+            unavailable_step_names = []
+            if self._resultdb_fetcher:
+                maybe_results = results_fetcher.fetch_results_from_resultdb_layout_tests(
+                    self._tool, build, True)
+                if maybe_results:
+                    builds_to_results[build].append(maybe_results)
+                else:
+                    # The results don't have step-level granularity, so just
+                    # log all of them.
+                    unavailable_step_names.extend(step_names)
+            else:
+                for step_name in step_names:
+                    maybe_result = results_fetcher.fetch_results(
+                        build, False, step_name)
+                    if maybe_result:
+                        builds_to_results[build].append(maybe_result)
+                    else:
+                        unavailable_step_names.append(step_name)
+
+            if unavailable_step_names:
+                _log.warning('Failed to fetch some results for "%s".',
+                             build.builder_name)
+                for step_name in unavailable_step_names:
+                    results_url = results_fetcher.results_url(
+                        build.builder_name, build.build_number, step_name)
+                    _log.warning('Results URL: %s/results.html', results_url)
+        return builds_to_results
 
     def _make_test_baseline_set_from_file(self, filename, builds_to_results):
-        test_baseline_set = TestBaselineSet(self._tool)
+        tests = []
         try:
             with self._tool.filesystem.open_text_file_for_reading(
                     filename) as fh:
@@ -334,38 +350,35 @@
                     test = test.strip()
                     if not test or test.startswith('#'):
                         continue
-                    for build, results in builds_to_results.items():
-                        if self._resultdb_fetcher:
-                            # In the current flow, similar check to check for the presence of
-                            # a result is done later in rebaseline by sending the request again.
-                            # This can be done here itself to get an optimal test_baseline_set.
-                            if results and results.fail_result_exists_resultdb(
-                                    test):
-                                test_baseline_set.add(test, build)
-                        else:
-                            test_baseline_set.add(test, build)
+                    tests.append(test)
         except IOError:
             _log.info('Could not read test names from %s', filename)
-        return test_baseline_set
+        return self._make_test_baseline_set_for_tests(tests, builds_to_results)
+
+    def _test_exists(self, results, test):
+        if self._resultdb_fetcher:
+            return results.fail_result_exists_resultdb(test)
+        return results.result_for_test(test)
 
     def _make_test_baseline_set_for_tests(self, tests, builds_to_results):
         """Determines the set of test baselines to fetch from a list of tests.
 
         Args:
             tests: A list of tests.
-            builds_to_results: A dict mapping Builds to WebTestResults.
+            builds_to_results: A dict mapping Builds to lists of WebTestResults.
 
         Returns:
             A TestBaselineSet object.
         """
         test_baseline_set = TestBaselineSet(self._tool)
-        for test in tests:
-            for build, results in builds_to_results.items():
-                if self._resultdb_fetcher:
-                    if results and results.fail_result_exists_resultdb(test):
-                        test_baseline_set.add(test, build)
-                else:
-                    test_baseline_set.add(test, build)
+        for test, (build, builder_results) in itertools.product(
+                tests, builds_to_results.items()):
+            for step_results in builder_results:
+                # Check for bad user-supplied test names early to create a
+                # smaller test baseline set and send fewer bad requests.
+                if self._test_exists(step_results, test):
+                    test_baseline_set.add(test, build,
+                                          step_results.step_name())
         return test_baseline_set
 
     def _make_test_baseline_set(self, builds_to_results, only_changed_tests):
@@ -375,7 +388,7 @@
         modified tests will be rebaselined (depending on only_changed_tests).
 
         Args:
-            builds_to_results: A dict mapping Builds to WebTestResults.
+            builds_to_results: A dict mapping Builds to lists of WebTestResults.
             only_changed_tests: Whether to only include baselines for tests that
                are changed in this CL. If False, all new baselines for failing
                tests will be downloaded, even for tests that were not modified.
@@ -383,31 +396,31 @@
         Returns:
             A TestBaselineSet object.
         """
-        builds_to_tests = {}
-        for build, results in builds_to_results.items():
-            if self._resultdb_fetcher:
-                builds_to_tests[build] = self._tests_to_rebaseline_resultDB(
-                    build, results)
-            else:
-                builds_to_tests[build] = self._tests_to_rebaseline(
-                    build, results)
         if only_changed_tests:
             files_in_cl = self._tool.git().changed_files(diff_filter='AM')
             # In the changed files list from Git, paths always use "/" as
             # the path separator, and they're always relative to repo root.
             test_base = self._test_base_path()
-            tests_in_cl = [
-                f[len(test_base):] for f in files_in_cl
-                if f.startswith(test_base)
-            ]
+            tests_in_cl = {
+                f[len(test_base):]
+                for f in files_in_cl if f.startswith(test_base)
+            }
 
-        # Here we have a concrete list of tests so we don't need prefix lookup.
         test_baseline_set = TestBaselineSet(self._tool, prefix_mode=False)
-        for build, tests in builds_to_tests.items():
-            for test in tests:
-                if only_changed_tests and test not in tests_in_cl:
-                    continue
-                test_baseline_set.add(test, build)
+        for build, builder_results in builds_to_results.items():
+            for step_results in builder_results:
+                if self._resultdb_fetcher:
+                    tests_to_rebaseline = self._tests_to_rebaseline_resultDB(
+                        build, step_results)
+                else:
+                    tests_to_rebaseline = self._tests_to_rebaseline(
+                        build, step_results)
+                # Here we have a concrete list of tests so we don't need prefix lookup.
+                for test in tests_to_rebaseline:
+                    if only_changed_tests and test not in tests_in_cl:
+                        continue
+                    test_baseline_set.add(test, build,
+                                          step_results.step_name())
         return test_baseline_set
 
     def _test_base_path(self):
@@ -450,14 +463,11 @@
 
         Args:
             build: A Build instance.
-            web_test_results: A WebTestResults instance or None.
+            web_test_results: A WebTestResults instance.
 
         Returns:
             A sorted list of tests to rebaseline for this build.
         """
-        if web_test_results is None:
-            return []
-
         unexpected_results = web_test_results.didnt_run_as_expected_results()
         tests = sorted(
             r.test_name() for r in unexpected_results
@@ -486,7 +496,7 @@
             return None
         try:
             retry_summary = json.loads(content)
-            return retry_summary['failures']
+            return set(retry_summary['failures'])
         except (ValueError, KeyError):
             _log.warning('Unexpected retry summary content:\n%s', content)
             return None
@@ -516,7 +526,7 @@
                 build = self._choose_fill_in_build(port, build_port_pairs)
                 _log.info('Using "%s" build %d for %s.', build.builder_name,
                           build.build_number, port)
-                test_baseline_set.add(test_prefix, build, port)
+                test_baseline_set.add(test_prefix, build, port_name=port)
         return test_baseline_set
 
     def _choose_fill_in_build(self, target_port, build_port_pairs):
diff --git a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl_unittest.py b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl_unittest.py
index ce5b9851..3e349f1 100644
--- a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl_unittest.py
+++ b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl_unittest.py
@@ -36,11 +36,12 @@
             TryJobStatus('COMPLETED', 'FAILURE'),
             Build('MOCK Try Linux', 6000, 'Build-3'):
             TryJobStatus('COMPLETED', 'FAILURE'),
-            # Test the special case for experimental builders
             # Highdpi is an experimental builder whose status
             # is returned as ('COMPLETED', 'SUCCESS') even with failures.
             Build('MOCK Try Highdpi', 8000, 'Build-4'):
             TryJobStatus('COMPLETED', 'SUCCESS'),
+            Build('MOCK Try Linux Multiple Steps', 9000, 'Build-5'):
+            TryJobStatus('COMPLETED', 'FAILURE'),
         }
 
         self.command.git_cl = MockGitCL(self.tool, self.builds)
@@ -71,10 +72,27 @@
             'MOCK Try Highdpi': {
                 'port_name': 'test-linux-trusty',
                 'specifiers': ['trusty', 'Release'],
-                "flag_specific": "highdpi",
+                'steps': {
+                    'high_dpi_blink_web_tests (with patch)': {
+                        'flag_specific': 'highdpi',
+                    },
+                },
+            },
+            'MOCK Try Linux Multiple Steps': {
+                'port_name': 'test-linux-trusty',
+                'specifiers': ['Trusty', 'Release'],
+                'steps': {
+                    'blink_web_tests (with patch)': {},
+                    'not_site_per_process_blink_web_tests (with patch)': {
+                        'flag_specific': 'disable-site-isolation-trials',
+                    },
+                    'layout_ng_disabled_blink_web_tests (with patch)': {
+                        'flag_specific': 'disable-layout-ng',
+                    },
+                },
             },
         })
-        web_test_results = WebTestResults({
+        raw_web_test_results = {
             'tests': {
                 'one': {
                     'crash.html': {
@@ -147,7 +165,7 @@
                     }
                 },
             },
-        })
+        }
         self.web_test_resultsdb = WebTestResults([{
             "name": "tests/two/image-fail.html/results/2",
             "testId": "ninja://:blink_web_tests/two/image-fail.html",
@@ -213,7 +231,10 @@
         }
 
         for build in self.builds:
-            self.tool.results_fetcher.set_results(build, web_test_results)
+            self.tool.results_fetcher.set_results(
+                build,
+                WebTestResults(raw_web_test_results,
+                               step_name='blink_web_tests (with patch)'))
             self.tool.results_fetcher.set_retry_sumary_json(
                 build,
                 json.dumps({
@@ -227,6 +248,20 @@
                     'ignored': [],
                 }))
 
+        # Add results for the other flag-specific steps on this builder.
+        multiple_step_build = Build('MOCK Try Linux Multiple Steps', 9000,
+                                    'Build-5')
+        self.tool.results_fetcher.set_results(
+            multiple_step_build,
+            WebTestResults(
+                raw_web_test_results,
+                step_name='layout_ng_disabled_blink_web_tests (with patch)'))
+        self.tool.results_fetcher.set_results(
+            multiple_step_build,
+            WebTestResults(
+                raw_web_test_results,
+                step_name='not_site_per_process_blink_web_tests (with patch)'))
+
         # Write to the mock filesystem so that these tests are considered to exist.
         tests = [
             'one/flaky-fail.html',
@@ -329,6 +364,7 @@
             # one/slow-fail.html
             #
 
+            one/does-not-exist.html
             one/text-fail.html
                 two/image-fail.html   '''))
         exit_code = self.command.execute(
@@ -355,6 +391,7 @@
             # one/slow-fail.html
             #
 
+            ones/does-not-exist.html
                 two/image-fail.html   '''))
         for build in self.builds:
             self.tool.results_fetcher.set_results_to_resultdb(
@@ -539,15 +576,7 @@
     def test_execute_with_test_that_fails_on_retry(self):
         # In this example, one test failed both with and without the patch
         # in the try job, so it is not rebaselined.
-        builds = {
-            Build('MOCK Try Win', 5000, 'Build-1'):
-            TryJobStatus('COMPLETED', 'FAILURE'),
-            Build('MOCK Try Mac', 4000, 'Build-2'):
-            TryJobStatus('COMPLETED', 'FAILURE'),
-            Build('MOCK Try Linux', 6000, 'Build-3'):
-            TryJobStatus('COMPLETED', 'FAILURE'),
-        }
-        for build in builds:
+        for build in self.builds:
             self.tool.results_fetcher.set_retry_sumary_json(
                 build,
                 json.dumps({
@@ -578,19 +607,6 @@
             'INFO: Rebaselining two/image-fail.html\n',
         ])
 
-    def test_execute_with_flag_specific_experimental(self):
-        exit_code = self.command.execute(
-            self.command_options(flag_specific='highdpi'), [], self.tool)
-        self.assertEqual(exit_code, 0)
-        self.assertLog([
-            'INFO: Finished try jobs found for all try bots.\n',
-            'INFO: Rebaselining one/flaky-fail.html\n',
-            'INFO: Rebaselining one/missing.html\n',
-            'INFO: Rebaselining one/slow-fail.html\n',
-            'INFO: Rebaselining one/text-fail.html\n',
-            'INFO: Rebaselining two/image-fail.html\n',
-        ])
-
     def test_rebaseline_command_invocations(self):
         """Tests the list of commands that are called for rebaselining."""
         # First write test contents to the mock filesystem so that
@@ -601,7 +617,8 @@
         self._write(path, 'contents')
         test_baseline_set = TestBaselineSet(self.tool)
         test_baseline_set.add('one/flaky-fail.html',
-                              Build('MOCK Try Win', 5000, 'Build-1'))
+                              Build('MOCK Try Win', 5000, 'Build-1'),
+                              'blink_web_tests (with patch)')
         self.command.rebaseline(self.command_options(), test_baseline_set)
         self.assertEqual(self.tool.executive.calls,
                          [[[
@@ -642,6 +659,64 @@
                               'one/flaky-fail.html',
                           ]]])
 
+    def test_rebaseline_command_invocations_multiple_steps(self):
+        """Test the rebaseline tool handles multiple steps on the same builder.
+
+        In this example, the builder runs one generic web test step and two
+        flag-specific ones.
+        """
+        exit_code = self.command.execute(
+            self.command_options(builders=['MOCK Try Linux Multiple Steps']),
+            ['one/text-fail.html', 'one/does-not-exist.html'], self.tool)
+        self.assertEqual(exit_code, 0)
+        self.assertEqual(self.tool.executive.calls[0], [[
+            'python', 'echo', 'copy-existing-baselines-internal', '--test',
+            'one/text-fail.html', '--suffixes', 'txt', '--port-name',
+            'test-linux-trusty'
+        ]])
+        self.assertEqual(sorted(self.tool.executive.calls[1]), [
+            [
+                'python', 'echo', 'rebaseline-test-internal', '--test',
+                'one/text-fail.html', '--suffixes', 'txt', '--port-name',
+                'test-linux-trusty', '--builder',
+                'MOCK Try Linux Multiple Steps', '--build-number', '9000',
+                '--step-name', 'blink_web_tests (with patch)'
+            ],
+            [
+                'python', 'echo', 'rebaseline-test-internal', '--test',
+                'one/text-fail.html', '--suffixes', 'txt', '--port-name',
+                'test-linux-trusty', '--flag-specific', 'disable-layout-ng',
+                '--builder', 'MOCK Try Linux Multiple Steps', '--build-number',
+                '9000', '--step-name',
+                'layout_ng_disabled_blink_web_tests (with patch)'
+            ],
+            [
+                'python', 'echo', 'rebaseline-test-internal', '--test',
+                'one/text-fail.html', '--suffixes', 'txt', '--port-name',
+                'test-linux-trusty', '--flag-specific',
+                'disable-site-isolation-trials', '--builder',
+                'MOCK Try Linux Multiple Steps', '--build-number', '9000',
+                '--step-name',
+                'not_site_per_process_blink_web_tests (with patch)'
+            ],
+        ])
+        self.assertEqual(sorted(self.tool.executive.calls[2]), [
+            [
+                'python', 'echo', 'optimize-baselines', '--no-manifest-update',
+                '--flag-specific', 'disable-layout-ng', '--suffixes', 'txt',
+                'one/text-fail.html'
+            ],
+            [
+                'python', 'echo', 'optimize-baselines', '--no-manifest-update',
+                '--flag-specific', 'disable-site-isolation-trials',
+                '--suffixes', 'txt', 'one/text-fail.html'
+            ],
+            [
+                'python', 'echo', 'optimize-baselines', '--no-manifest-update',
+                '--suffixes', 'txt', 'one/text-fail.html'
+            ]
+        ])
+
     def test_trigger_try_jobs(self):
         # The trigger_try_jobs method just uses git cl to trigger jobs for
         # the given builders.
@@ -660,13 +735,14 @@
 
     def test_execute_missing_results_with_no_fill_missing_prompts(self):
         self.tool.results_fetcher.set_results(
-            Build('MOCK Try Win', 5000, 'Build-1'), None)
+            Build('MOCK Try Win', 5000, 'Build-1'), None,
+            'blink_web_tests (with patch)')
         exit_code = self.command.execute(self.command_options(), [], self.tool)
         self.assertEqual(exit_code, 1)
         self.assertLog([
             'INFO: Finished try jobs found for all try bots.\n',
-            'INFO: Failed to fetch results for "MOCK Try Win".\n',
-            ('INFO: Results URL: https://test-results.appspot.com/data/layout_results/'
+            'WARNING: Failed to fetch some results for "MOCK Try Win".\n',
+            ('WARNING: Results URL: https://test-results.appspot.com/data/layout_results/'
              'MOCK_Try_Win/5000/blink_web_tests%20%28with%20patch%29/layout-test-results/results.html\n'
              ),
             'INFO: There are some builders with no results:\n',
@@ -677,28 +753,31 @@
 
     def test_execute_missing_results_with_fill_missing_continues(self):
         self.tool.results_fetcher.set_results(
-            Build('MOCK Try Win', 5000, 'Build-1'), None)
+            Build('MOCK Try Win', 5000, 'Build-1'), None,
+            'blink_web_tests (with patch)')
         exit_code = self.command.execute(
             self.command_options(fill_missing=True), ['one/flaky-fail.html'],
             self.tool)
         self.assertEqual(exit_code, 0)
         self.assertLog([
             'INFO: Finished try jobs found for all try bots.\n',
-            'INFO: Failed to fetch results for "MOCK Try Win".\n',
-            ('INFO: Results URL: https://test-results.appspot.com/data/layout_results/'
+            'WARNING: Failed to fetch some results for "MOCK Try Win".\n',
+            ('WARNING: Results URL: https://test-results.appspot.com/data/layout_results/'
              'MOCK_Try_Win/5000/blink_web_tests%20%28with%20patch%29/layout-test-results/results.html\n'
              ), 'INFO: There are some builders with no results:\n',
             'INFO:   MOCK Try Win\n', 'INFO: For one/flaky-fail.html:\n',
-            'INFO: Using "MOCK Try Highdpi" build 8000 for test-win-win7.\n',
+            'INFO: Using "MOCK Try Linux" build 6000 for test-win-win7.\n',
             'INFO: Rebaselining one/flaky-fail.html\n'
         ])
 
     def test_fill_in_missing_results(self):
         test_baseline_set = TestBaselineSet(self.tool)
         test_baseline_set.add('one/flaky-fail.html',
-                              Build('MOCK Try Linux', 100))
-        test_baseline_set.add('one/flaky-fail.html', Build(
-            'MOCK Try Win', 200))
+                              Build('MOCK Try Linux', 100),
+                              'blink_web_tests (with patch)')
+        test_baseline_set.add('one/flaky-fail.html',
+                              Build('MOCK Try Win',
+                                    200), 'blink_web_tests (with patch)')
         self.command.fill_in_missing_results(test_baseline_set)
         self.assertEqual(
             test_baseline_set.build_port_pairs('one/flaky-fail.html'), [
diff --git a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_unittest.py b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_unittest.py
index 838e24a..09350f30 100644
--- a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_unittest.py
+++ b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_unittest.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import json
 import optparse
 import unittest
 
@@ -57,6 +58,28 @@
                 'port_name': 'test-linux-trusty',
                 'specifiers': ['Trusty', 'Release']
             },
+            'MOCK Trusty Disable LayoutNG': {
+                'port_name': 'test-linux-trusty',
+                'specifiers': ['Trusty', 'Release'],
+                'steps': {
+                    'blink_web_tests (with patch)': {
+                        'flag_specific': 'disable-layout-ng',
+                    },
+                },
+            },
+            'MOCK Trusty Multiple Steps': {
+                'port_name': 'test-linux-trusty',
+                'specifiers': ['Trusty', 'Release'],
+                'steps': {
+                    'blink_web_tests (with patch)': {},
+                    'not_site_per_process_blink_web_tests (with patch)': {
+                        'flag_specific': 'disable-site-isolation-trials',
+                    },
+                    'layout_ng_disabled_blink_web_tests (with patch)': {
+                        'flag_specific': 'disable-layout-ng',
+                    },
+                },
+            },
             'MOCK Win10': {
                 'port_name': 'test-win-win10',
                 'specifiers': ['Win10', 'Release']
@@ -91,8 +114,24 @@
         self.test_expectations_path = self.mac_port.path_to_generic_test_expectations_file(
         )
 
-        # This file must exist for Port classes to function properly.
+        # These files must exist for Port classes to function properly.
         self._write('VirtualTestSuites', '[]')
+        self._write(
+            'FlagSpecificConfig',
+            json.dumps([
+                {
+                    'name':
+                    'disable-layout-ng',
+                    'args': [
+                        '--disable-blink-features=LayoutNG,'
+                        'LayoutNGBlockFragmentation'
+                    ],
+                },
+                {
+                    'name': 'disable-site-isolation-trials',
+                    'args': ['--disable-site-isolation-trials'],
+                },
+            ]))
         # Create some dummy tests (note _setup_mock_build_data uses the same test names).
         self._write('userscripts/first-test.html', 'Dummy test contents')
         self._write('userscripts/second-test.html', 'Dummy test contents')
@@ -137,37 +176,43 @@
         for builder in ['MOCK Win7', 'MOCK Win7 (dbg)', 'MOCK Mac10.11']:
             self.tool.results_fetcher.set_results(
                 Build(builder),
-                WebTestResults({
-                    'tests': {
-                        'userscripts': {
-                            'first-test.html': {
-                                'expected': 'PASS',
-                                'actual': 'FAIL',
-                                'is_unexpected': True,
-                                'artifacts': {
-                                    'actual_image': ['first-test-actual.png'],
-                                    'expected_image':
-                                    ['first-test-expected.png'],
-                                    'actual_text': ['first-test-actual.txt'],
-                                    'expected_text':
-                                    ['first-test-expected.txt']
-                                }
-                            },
-                            'second-test.html': {
-                                'expected': 'FAIL',
-                                'actual': 'FAIL',
-                                'artifacts': {
-                                    'actual_image': ['second-test-actual.png'],
-                                    'expected_image':
-                                    ['second-test-expected.png'],
-                                    'actual_audio': ['second-test-actual.wav'],
-                                    'expected_audio':
-                                    ['second-test-expected.wav']
+                WebTestResults(
+                    {
+                        'tests': {
+                            'userscripts': {
+                                'first-test.html': {
+                                    'expected': 'PASS',
+                                    'actual': 'FAIL',
+                                    'is_unexpected': True,
+                                    'artifacts': {
+                                        'actual_image':
+                                        ['first-test-actual.png'],
+                                        'expected_image':
+                                        ['first-test-expected.png'],
+                                        'actual_text':
+                                        ['first-test-actual.txt'],
+                                        'expected_text':
+                                        ['first-test-expected.txt']
+                                    }
+                                },
+                                'second-test.html': {
+                                    'expected': 'FAIL',
+                                    'actual': 'FAIL',
+                                    'artifacts': {
+                                        'actual_image':
+                                        ['second-test-actual.png'],
+                                        'expected_image':
+                                        ['second-test-expected.png'],
+                                        'actual_audio':
+                                        ['second-test-actual.wav'],
+                                        'expected_audio':
+                                        ['second-test-expected.wav']
+                                    }
                                 }
                             }
                         }
-                    }
-                }))
+                    },
+                    step_name='blink_web_tests (with patch)'))
 
 
 class TestAbstractRebaselineCommand(BaseTestCase):
@@ -199,17 +244,63 @@
     command_constructor = AbstractParallelRebaselineCommand
 
     def test_builders_to_fetch_from(self):
-        # pylint: disable=protected-access
-        builders_to_fetch = self.command._builders_to_fetch_from([
-            'MOCK Win10', 'MOCK Win7 (dbg)(1)', 'MOCK Win7 (dbg)(2)',
-            'MOCK Win7'
+        build_steps_to_fetch = self.command.build_steps_to_fetch_from([
+            ('MOCK Win10', 'blink_web_tests (with patch)'),
+            ('MOCK Win7 (dbg)(1)', 'blink_web_tests (with patch)'),
+            ('MOCK Win7 (dbg)(2)', 'blink_web_tests (with patch)'),
+            ('MOCK Win7', 'blink_web_tests (with patch)'),
         ])
-        self.assertEqual(builders_to_fetch, {'MOCK Win7', 'MOCK Win10'})
+        # Win7 debug builders are shadowed by release builder.
+        self.assertEqual(
+            build_steps_to_fetch, {
+                ('MOCK Win7', 'blink_web_tests (with patch)'),
+                ('MOCK Win10', 'blink_web_tests (with patch)'),
+            })
 
-        builders_to_fetch = self.command._builders_to_fetch_from([
-            'MOCK Trusty', 'MOCK wpt(1)', 'MOCK wpt(2)'
+        build_steps_to_fetch = self.command.build_steps_to_fetch_from([
+            ('MOCK Trusty', 'blink_web_tests (with patch)'),
+            ('MOCK wpt(1)', 'blink_web_tests (with patch)'),
+            ('MOCK wpt(2)', 'blink_web_tests (with patch)'),
         ])
-        self.assertEqual(builders_to_fetch, {'MOCK Trusty', 'MOCK wpt(1)', 'MOCK wpt(2)'})
+        # All ports are unique.
+        self.assertEqual(
+            build_steps_to_fetch, {
+                ('MOCK Trusty', 'blink_web_tests (with patch)'),
+                ('MOCK wpt(1)', 'blink_web_tests (with patch)'),
+                ('MOCK wpt(2)', 'blink_web_tests (with patch)'),
+            })
+
+    def test_builders_to_fetch_from_flag_specific(self):
+        build_steps_to_fetch = self.command.build_steps_to_fetch_from([
+            ('MOCK Trusty', 'blink_web_tests (with patch)'),
+            # On this dedicated flag-specific builder, there's no need to
+            # include the flag-specific option in the step name.
+            ('MOCK Trusty Disable LayoutNG', 'blink_web_tests (with patch)'),
+        ])
+        # Ports are the same, but the fallback paths differ.
+        self.assertEqual(
+            build_steps_to_fetch, {
+                ('MOCK Trusty', 'blink_web_tests (with patch)'),
+                ('MOCK Trusty Disable LayoutNG',
+                 'blink_web_tests (with patch)'),
+            })
+
+        build_steps_to_fetch = self.command.build_steps_to_fetch_from([
+            ('MOCK Trusty Disable LayoutNG', 'blink_web_tests (with patch)'),
+            ('MOCK Trusty Multiple Steps', 'blink_web_tests (with patch)'),
+            ('MOCK Trusty Multiple Steps',
+             'not_site_per_process_blink_web_tests (with patch)'),
+            ('MOCK Trusty Multiple Steps',
+             'layout_ng_disabled_blink_web_tests (with patch)'),
+        ])
+        # 'layout_ng_disabled_blink_web_tests' should not be rebaselined twice.
+        self.assertEqual(len(build_steps_to_fetch), 3)
+        self.assertIn(
+            ('MOCK Trusty Multiple Steps', 'blink_web_tests (with patch)'),
+            build_steps_to_fetch)
+        self.assertIn(('MOCK Trusty Multiple Steps',
+                       'not_site_per_process_blink_web_tests (with patch)'),
+                      build_steps_to_fetch)
 
     def test_generic_baseline_paths(self):
         test_baseline_set = TestBaselineSet(self.tool)
@@ -333,7 +424,8 @@
     def test_rebaseline_all(self):
         test_baseline_set = TestBaselineSet(self.tool)
         test_baseline_set.add('userscripts/first-test.html',
-                              Build('MOCK Win7'))
+                              Build('MOCK Win7'),
+                              'blink_web_tests (with patch)')
         self.command.rebaseline(self.options(), test_baseline_set)
 
         self.assertEqual(self.tool.executive.calls,
@@ -379,7 +471,8 @@
     def test_rebaseline_debug(self):
         test_baseline_set = TestBaselineSet(self.tool)
         test_baseline_set.add('userscripts/first-test.html',
-                              Build('MOCK Win7 (dbg)'))
+                              Build('MOCK Win7 (dbg)'),
+                              'blink_web_tests (with patch)')
 
         self.command.rebaseline(self.options(), test_baseline_set)
         self.assertEqual(self.tool.executive.calls,
@@ -425,7 +518,8 @@
     def test_no_optimize(self):
         test_baseline_set = TestBaselineSet(self.tool)
         test_baseline_set.add('userscripts/first-test.html',
-                              Build('MOCK Win7'))
+                              Build('MOCK Win7'),
+                              'blink_web_tests (with patch)')
         self.command.rebaseline(
             self.options(optimize=False), test_baseline_set)
 
@@ -462,7 +556,8 @@
     def test_results_directory(self):
         test_baseline_set = TestBaselineSet(self.tool)
         test_baseline_set.add('userscripts/first-test.html',
-                              Build('MOCK Win7'))
+                              Build('MOCK Win7'),
+                              'blink_web_tests (with patch)')
         self.command.rebaseline(
             self.options(optimize=False, results_directory='/tmp'),
             test_baseline_set)
@@ -503,7 +598,8 @@
     def test_rebaseline_with_different_port_name(self):
         test_baseline_set = TestBaselineSet(self.tool)
         test_baseline_set.add('userscripts/first-test.html',
-                              Build('MOCK Win7'), 'test-win-win10')
+                              Build('MOCK Win7'),
+                              'blink_web_tests (with patch)', 'test-win-win10')
         self.command.rebaseline(self.options(), test_baseline_set)
 
         self.assertEqual(self.tool.executive.calls,
@@ -584,7 +680,8 @@
         self._setup_mock_build_data()
         test_baseline_set = TestBaselineSet(self.tool)
         test_baseline_set.add('userscripts/first-test.html',
-                              Build('MOCK Mac10.11'))
+                              Build('MOCK Mac10.11'),
+                              'blink_web_tests (with patch)')
 
         self.command.rebaseline(self.options(), test_baseline_set)
 
@@ -603,7 +700,8 @@
         self._setup_mock_build_data()
         test_baseline_set = TestBaselineSet(self.tool)
         test_baseline_set.add('userscripts/first-test.html',
-                              Build('MOCK Mac10.11'))
+                              Build('MOCK Mac10.11'),
+                              'blink_web_tests (with patch)')
 
         self.command.rebaseline(self.options(), test_baseline_set)
 
@@ -630,7 +728,8 @@
         self._setup_mock_build_data()
         test_baseline_set = TestBaselineSet(self.tool)
         test_baseline_set.add('userscripts/first-test.html',
-                              Build('MOCK Mac10.11'))
+                              Build('MOCK Mac10.11'),
+                              'blink_web_tests (with patch)')
 
         self.command.rebaseline(self.options(), test_baseline_set)
 
@@ -658,7 +757,8 @@
         self._setup_mock_build_data()
         test_baseline_set = TestBaselineSet(self.tool)
         test_baseline_set.add('userscripts/first-test.html',
-                              Build('MOCK Mac10.11'))
+                              Build('MOCK Mac10.11'),
+                              'blink_web_tests (with patch)')
 
         self.command.rebaseline(self.options(), test_baseline_set)
 
@@ -681,7 +781,8 @@
         self._setup_mock_build_data()
         test_baseline_set = TestBaselineSet(self.tool)
         test_baseline_set.add('userscripts/first-test.html',
-                              Build('MOCK Mac10.11'))
+                              Build('MOCK Mac10.11'),
+                              'blink_web_tests (with patch)')
 
         self.command.rebaseline(self.options(), test_baseline_set)
 
@@ -707,7 +808,8 @@
         self._setup_mock_build_data()
         test_baseline_set = TestBaselineSet(self.tool)
         test_baseline_set.add('userscripts/first-test.html',
-                              Build('MOCK Mac10.11'))
+                              Build('MOCK Mac10.11'),
+                              'blink_web_tests (with patch)')
 
         self.command.rebaseline(self.options(), test_baseline_set)
 
@@ -1046,7 +1148,7 @@
             },
             'MOCK Trusty': {
                 'port_name': 'test-linux-trusty',
-                'specifiers': ['Trusty', 'Release']
+                'specifiers': ['Trusty', 'Release'],
             },
             'MOCK Win10': {
                 'port_name': 'test-win-win10',
@@ -1062,18 +1164,18 @@
     def test_add_and_iter_tests(self):
         test_baseline_set = TestBaselineSet(host=self.host)
         test_baseline_set.add('a', Build('MOCK Trusty'))
-        test_baseline_set.add('a/z.html', Build('MOCK Win10'))
-        self.assertEqual(
-            list(test_baseline_set), [
-                ('a/x.html', Build(builder_name='MOCK Trusty'),
-                 'test-linux-trusty'),
-                ('a/y.html', Build(builder_name='MOCK Trusty'),
-                 'test-linux-trusty'),
-                ('a/z.html', Build(builder_name='MOCK Trusty'),
-                 'test-linux-trusty'),
-                ('a/z.html', Build(builder_name='MOCK Win10'),
-                 'test-win-win10'),
-            ])
+        test_baseline_set.add('a/z.html', Build('MOCK Win10'),
+                              'blink_web_tests (with patch)')
+        self.assertEqual(list(test_baseline_set), [
+            ('a/x.html', Build(builder_name='MOCK Trusty'), None,
+             'test-linux-trusty'),
+            ('a/y.html', Build(builder_name='MOCK Trusty'), None,
+             'test-linux-trusty'),
+            ('a/z.html', Build(builder_name='MOCK Trusty'), None,
+             'test-linux-trusty'),
+            ('a/z.html', Build(builder_name='MOCK Win10'),
+             'blink_web_tests (with patch)', 'test-win-win10'),
+        ])
         self.assertEqual(test_baseline_set.all_tests(),
                          ['a/x.html', 'a/y.html', 'a/z.html'])
 
@@ -1084,11 +1186,12 @@
     def test_str_basic(self):
         test_baseline_set = TestBaselineSet(host=self.host)
         test_baseline_set.add('a/x.html', Build('MOCK Mac10.12'))
-        test_baseline_set.add('a/x.html', Build('MOCK Win10'))
+        test_baseline_set.add('a/x.html', Build('MOCK Win10'),
+                              'blink_web_tests (with patch)')
         self.assertEqual(str(test_baseline_set), (
             '<TestBaselineSet with:\n'
-            '  a/x.html: Build(builder_name=\'MOCK Mac10.12\', build_number=None, build_id=None), test-mac-mac10.12\n'
-            '  a/x.html: Build(builder_name=\'MOCK Win10\', build_number=None, build_id=None), test-win-win10>'
+            "  a/x.html: Build(builder_name='MOCK Mac10.12', build_number=None, build_id=None), None, test-mac-mac10.12\n"
+            "  a/x.html: Build(builder_name='MOCK Win10', build_number=None, build_id=None), blink_web_tests (with patch), test-win-win10>"
         ))
 
     def test_getters(self):
@@ -1109,7 +1212,7 @@
         # done when prefix_mode=False.
         self.assertEqual(
             list(test_baseline_set),
-            [('wpt/foo.html', Build('some-wpt-bot'), 'linux-trusty')])
+            [('wpt/foo.html', Build('some-wpt-bot'), None, 'linux-trusty')])
         self.assertEqual(test_baseline_set.all_tests(), ['wpt/foo.html'])
         self.assertEqual(test_baseline_set.test_prefixes(), ['wpt/foo.html'])
         self.assertEqual(test_baseline_set.build_port_pairs('wpt/foo.html'),
diff --git a/third_party/blink/tools/blinkpy/web_tests/builder_list.py b/third_party/blink/tools/blinkpy/web_tests/builder_list.py
index 769538d..0394cbf 100644
--- a/third_party/blink/tools/blinkpy/web_tests/builder_list.py
+++ b/third_party/blink/tools/blinkpy/web_tests/builder_list.py
@@ -66,16 +66,17 @@
     def _find_ports_for_flag_specific_options(self):
         flag_spec_to_port = {}
         for builder_name, builder in self._builders.items():
-            option = self.flag_specific_option(builder_name)
-            if not option:
-                continue
             port_name = self.port_name_for_builder_name(builder_name)
-            maybe_port_name = flag_spec_to_port.get(option)
-            if maybe_port_name and maybe_port_name != port_name:
-                raise ValueError(
-                    'Flag-specific suite %r can only run on one port, got: '
-                    '%r, %r' % (option, maybe_port_name, port_name))
-            flag_spec_to_port[option] = port_name
+            for step_name in self.step_names_for_builder(builder_name):
+                option = self.flag_specific_option(builder_name, step_name)
+                if not option:
+                    continue
+                maybe_port_name = flag_spec_to_port.get(option)
+                if maybe_port_name and maybe_port_name != port_name:
+                    raise ValueError(
+                        'Flag-specific suite %r can only run on one port, got: '
+                        '%r, %r' % (option, maybe_port_name, port_name))
+                flag_spec_to_port[option] = port_name
         return flag_spec_to_port
 
     @staticmethod
@@ -111,23 +112,27 @@
         exclude_specifiers = _lower_specifiers(exclude_specifiers or {})
         include_specifiers = _lower_specifiers(include_specifiers or {})
         builders = []
-        for b in self._builders:
+        for b, builder in self._builders.items():
             builder_specifiers = _lower_specifiers(
-                self._builders[b].get('specifiers', {}))
+                builder.get('specifiers', {}))
+            flag_specific_suites = {
+                step.get('flag_specific')
+                for step in builder.get('steps', {}).values()
+            }
             if flag_specific:
-                if (flag_specific == '*' and
-                        not self._builders[b].get('flag_specific', None)):
+                if flag_specific == '*' and not any(flag_specific_suites):
                     # Skip non flag_specific builders
                     continue
-                if (flag_specific != '*' and
-                        self._builders[b].get('flag_specific', None) != flag_specific):
-                    # Skip if not an exact match
+                if (flag_specific != '*'
+                        and flag_specific not in flag_specific_suites):
+                    # Skip if none of the steps has an exact match
                     continue
-            if is_try and self._builders[b].get('is_try_builder', False) != is_try:
+            if is_try and builder.get('is_try_builder', False) != is_try:
                 continue
-            if is_cq and self._builders[b].get('is_cq_builder', False) != is_cq:
+            if is_cq and builder.get('is_cq_builder', False) != is_cq:
                 continue
-            if ((not is_cq and not is_try) and self._builders[b].get('is_try_builder', False)):
+            if ((not is_cq and not is_try)
+                    and builder.get('is_try_builder', False)):
                 continue
             if builder_specifiers & exclude_specifiers:
                 continue
@@ -158,8 +163,11 @@
     def specifiers_for_builder(self, builder_name):
         return self._builders[builder_name]['specifiers']
 
-    def step_name_for_builder(self, builder_name):
-        return self._builders[builder_name].get('step_name', None)
+    def _steps(self, builder_name):
+        return self._builders[builder_name].get('steps', {})
+
+    def step_names_for_builder(self, builder_name):
+        return sorted(self._steps(builder_name))
 
     def is_try_server_builder(self, builder_name):
         return self._builders[builder_name].get('is_try_builder', False)
@@ -167,11 +175,13 @@
     def is_wpt_builder(self, builder_name):
         return 'wpt' in builder_name
 
-    def is_flag_specific_builder(self, builder_name):
-        return self._builders[builder_name].get('flag_specific', None) != None
-
-    def flag_specific_option(self, builder_name):
-        return self._builders[builder_name].get('flag_specific', None)
+    def flag_specific_option(self, builder_name, step_name):
+        steps = self._steps(builder_name)
+        # TODO(crbug/1291020): We cannot validate the step name here because
+        # some steps are retrieved from the results server instead of read from
+        # 'builders.json'. Once all the steps are in the config, we can allow
+        # bad step names to raise an exception.
+        return steps.get(step_name, {}).get('flag_specific')
 
     def flag_specific_options_for_port_name(self, port_name):
         return {
diff --git a/third_party/blink/tools/blinkpy/web_tests/builder_list_unittest.py b/third_party/blink/tools/blinkpy/web_tests/builder_list_unittest.py
index bc5d168..ece93d6 100644
--- a/third_party/blink/tools/blinkpy/web_tests/builder_list_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/builder_list_unittest.py
@@ -92,13 +92,21 @@
             'Flag Specific A': {
                 'port_name': 'port-c',
                 'specifiers': ['C', 'Release'],
-                'flag_specific': 'highdpi',
+                'steps': {
+                    'high_dpi_blink_web_tests (with patch)': {
+                        'flag_specific': 'highdpi'
+                    },
+                },
                 "is_try_builder": True
             },
             'Flag Specific B': {
                 'port_name': 'port-c',
                 'specifiers': ['C', 'Release'],
-                'flag_specific': 'disable-layout-ng',
+                'steps': {
+                    'layout_ng_disabled_blink_web_tests (with patch)': {
+                        'flag_specific': 'disable-layout-ng',
+                    },
+                },
                 "is_try_builder": True
             },
         })
@@ -208,15 +216,23 @@
             BuilderList({
                 'Flag Specific A': {
                     'port_name': 'port-a',
-                    'specifiers': ['C', 'Release'],
-                    'flag_specific': 'highdpi',
-                    "is_try_builder": True
+                    'specifiers': ['A', 'Release'],
+                    'steps': {
+                        'blink_web_tests (with patch)': {
+                            'flag_specific': 'highdpi',
+                        },
+                    },
+                    'is_try_builder': True
                 },
                 'Flag Specific B': {
                     'port_name': 'port-b',
-                    'specifiers': ['C', 'Release'],
-                    'flag_specific': 'highdpi',
-                    "is_try_builder": True
+                    'specifiers': ['B', 'Release'],
+                    'steps': {
+                        'blink_web_tests (with patch)': {
+                            'flag_specific': 'highdpi',
+                        },
+                    },
+                    'is_try_builder': True
                 },
             })
 
diff --git a/third_party/blink/tools/blinkpy/web_tests/try_flag.py b/third_party/blink/tools/blinkpy/web_tests/try_flag.py
index f61059b..8fd66a13 100644
--- a/third_party/blink/tools/blinkpy/web_tests/try_flag.py
+++ b/third_party/blink/tools/blinkpy/web_tests/try_flag.py
@@ -107,13 +107,27 @@
             builder_names=BUILDER_CONFIGS.keys())
         results_fetcher = self._host.results_fetcher
         for build in sorted(jobs):
-            self._host.print_('-- %s: %s/results.html' %
-                              (BUILDER_CONFIGS[build.builder_name].version,
-                               results_fetcher.results_url(
-                                   build.builder_name, build.build_number)))
-            results = results_fetcher.fetch_results(build, True)
-            results.for_each_test(
-                lambda result, b=build: self._process_result(b, result))
+            step_names = results_fetcher.get_layout_test_step_names(build)
+            generic_steps = [
+                step_name for step_name in step_names
+                if not results_fetcher.builders.flag_specific_option(
+                    build.builder_name, step_name)
+            ]
+            if len(generic_steps) != 1:
+                self._host.print_('Expected exactly one non-flag-specific '
+                                  'web test step for build %r, but found %d.' %
+                                  (build, len(generic_steps)))
+                continue
+            step_name = generic_steps[0]
+            results_url = results_fetcher.results_url(build.builder_name,
+                                                      build.build_number,
+                                                      step_name)
+            self._host.print_(
+                '-- %s: %s/results.html' %
+                (BUILDER_CONFIGS[build.builder_name].version, results_url))
+            results = results_fetcher.fetch_results(build, True, step_name)
+            results.for_each_test(lambda result, b=build: self._process_result(
+                b, result))
 
         # TODO: Write to flag expectations file. For now, stdout. :)
         unexpected_failures = []
diff --git a/third_party/blink/tools/blinkpy/web_tests/try_flag_unittest.py b/third_party/blink/tools/blinkpy/web_tests/try_flag_unittest.py
index a58b8be..71c4fe0 100644
--- a/third_party/blink/tools/blinkpy/web_tests/try_flag_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/try_flag_unittest.py
@@ -70,58 +70,64 @@
     def _setup_mock_results(self, results_fetcher):
         results_fetcher.set_results(
             self.linux_build,
-            WebTestResults({
-                'tests': {
-                    'something': {
-                        'fail-everywhere.html': {
-                            'expected': 'FAIL',
-                            'actual': 'FAIL',
-                            'is_unexpected': True
-                        },
-                        'fail-win-and-linux.html': {
-                            'expected': 'FAIL',
-                            'actual': 'FAIL',
-                            'is_unexpected': True
+            WebTestResults(
+                {
+                    'tests': {
+                        'something': {
+                            'fail-everywhere.html': {
+                                'expected': 'FAIL',
+                                'actual': 'FAIL',
+                                'is_unexpected': True
+                            },
+                            'fail-win-and-linux.html': {
+                                'expected': 'FAIL',
+                                'actual': 'FAIL',
+                                'is_unexpected': True
+                            }
                         }
                     }
-                }
-            }))
+                },
+                step_name='blink_web_tests (with patch)'))
         results_fetcher.set_results(
             self.win_build,
-            WebTestResults({
-                'tests': {
-                    'something': {
-                        'fail-everywhere.html': {
-                            'expected': 'FAIL',
-                            'actual': 'FAIL',
-                            'is_unexpected': True
-                        },
-                        'fail-win-and-linux.html': {
-                            'expected': 'FAIL',
-                            'actual': 'FAIL',
-                            'is_unexpected': True
+            WebTestResults(
+                {
+                    'tests': {
+                        'something': {
+                            'fail-everywhere.html': {
+                                'expected': 'FAIL',
+                                'actual': 'FAIL',
+                                'is_unexpected': True
+                            },
+                            'fail-win-and-linux.html': {
+                                'expected': 'FAIL',
+                                'actual': 'FAIL',
+                                'is_unexpected': True
+                            }
                         }
                     }
-                }
-            }))
+                },
+                step_name='blink_web_tests (with patch)'))
         results_fetcher.set_results(
             self.mac_build,
-            WebTestResults({
-                'tests': {
-                    'something': {
-                        'pass-unexpectedly-mac.html': {
-                            'expected': 'FAIL',
-                            'actual': 'PASS',
-                            'is_unexpected': True
-                        },
-                        'fail-everywhere.html': {
-                            'expected': 'FAIL',
-                            'actual': 'FAIL',
-                            'is_unexpected': True
+            WebTestResults(
+                {
+                    'tests': {
+                        'something': {
+                            'pass-unexpectedly-mac.html': {
+                                'expected': 'FAIL',
+                                'actual': 'PASS',
+                                'is_unexpected': True
+                            },
+                            'fail-everywhere.html': {
+                                'expected': 'FAIL',
+                                'actual': 'FAIL',
+                                'is_unexpected': True
+                            }
                         }
                     }
-                }
-            }))
+                },
+                step_name='blink_web_tests (with patch)'))
 
     def test_update(self):
         host = MockHost()
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 708c48f..9216b9b 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -3279,6 +3279,7 @@
 crbug.com/626703 [ Win ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Mac10.15 ] external/wpt/pointerevents/pointerevent_pointercapture_in_frame.html?pen [ Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/css/css-lists/counter-list-item-slot-order.html [ Failure ]
 crbug.com/626703 [ Mac10.15 ] external/wpt/css/css-lists/counter-list-item-slot-order.html [ Failure ]
 crbug.com/626703 [ Mac11 ] external/wpt/css/css-lists/counter-list-item-slot-order.html [ Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 50f075bd..23142801 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -1270,5 +1270,14 @@
     "args": [
       "--disable-blink-features=RestrictBatteryStatusToSecureContexts"
     ]
+  },
+  {
+    "prefix": "precompile-inline-scripts",
+    "platforms": ["Linux", "Mac", "Win"],
+    "bases": [
+      "external/wpt/html/semantics/scripting-1",
+      "fast/dom/HTMLScriptElement"
+    ],
+    "args": ["--enable-features=PrecompileInlineScripts"]
   }
 ]
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version
index d7c6e684d..8c69cb0 100644
--- a/third_party/blink/web_tests/external/Version
+++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@
-Version: b45b46ee55aaf2ed2a3bc78845d71cf08da316a2
+Version: 8fadb381209a215280dc3ad96d0f135b6005f176
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 f65a496..d601bff 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
@@ -2958,6 +2958,13 @@
         {}
        ]
       ],
+      "unicode-bidi-select-crash.html": [
+       "b36a37616b646e41ba75e56e699d21aacd2eb70d",
+       [
+        null,
+        {}
+       ]
+      ],
       "wm-body-propagation-crash.html": [
        "a4a24712f4570f661917b0911567ea5bddc7c485",
        [
@@ -3107,6 +3114,17 @@
     ]
    },
    "dom": {
+    "abort": {
+     "crashtests": {
+      "timeout-close.html": [
+       "ee8544a7f57edb8cac05e94dbd836eac20a37b85",
+       [
+        null,
+        {}
+       ]
+      ]
+     }
+    },
     "events": {
      "keypress-dispatch-crash.html": [
       "3207adbd8c891903b1c6edd65edc41de9b9e7312",
@@ -87074,6 +87092,45 @@
         {}
        ]
       ],
+      "table-grid-paint-htb-ltr.html": [
+       "e2be9ce16c2cd1808fb32c9c48935a983519e705",
+       [
+        null,
+        [
+         [
+          "/css/css-break/table/table-grid-paint-htb-ltr-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "table-grid-paint-vlr-rtl.html": [
+       "b26363056be2fb5fcb961c49872051446a7d692f",
+       [
+        null,
+        [
+         [
+          "/css/css-break/table/table-grid-paint-vlr-rtl-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "table-grid-paint-vrl-rtl.html": [
+       "0d83c6c402a82c604cb928a6c43dd5dc5cc9fc7c",
+       [
+        null,
+        [
+         [
+          "/css/css-break/table/table-grid-paint-vrl-rtl-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "table-row-paint-htb-ltr.html": [
        "ecc156bd38bcc414b8d66abf84d355c040f0782d",
        [
@@ -151729,7 +151786,7 @@
       ]
      ],
      "target-text-text-decoration-001.html": [
-      "d90d5d96630d05ab88430b88fe4a4ad8985a6fac",
+      "1709ce70816a9f384b2ad86d74e03284aea7b50e",
       [
        null,
        [
@@ -236193,7 +236250,7 @@
        ]
       ],
       "popup-inside-display-none.tentative.html": [
-       "d72f0aa50a523a5a5da0776bc94a2c3927d4f920",
+       "2230d77a3d9c4a815b313685dd3d5073f5041cea",
        [
         null,
         [
@@ -246755,6 +246812,10 @@
      "dde8aa232e3e45e1a19aacd73cc8911604560089",
      []
     ],
+    "fedcm.json": [
+     "54175a71061cb971c6cf4b5fc29051b2711e4b4c",
+     []
+    ],
     "idp-proxy": {
      "META.yml": [
       "9901aed94e7d018fc877c768f902d2570484518c",
@@ -251214,6 +251275,10 @@
       "child_window_location_navigate.sub.html": [
        "3068822f377da0ea3840d641874fb3eb7756f2e4",
        []
+      ],
+      "helper.js": [
+       "26db3289ea3fb29e2b551b8ecce4e8c02394b23c",
+       []
       ]
      }
     },
@@ -261359,6 +261424,18 @@
        "2721bc0af0b11cddb17087d988990379cc48ebc5",
        []
       ],
+      "table-grid-paint-htb-ltr-ref.html": [
+       "5830aa5fd51585120e86e4579ecee85bb5b84628",
+       []
+      ],
+      "table-grid-paint-vlr-rtl-ref.html": [
+       "5f069ea05363c78df1ee4f896cb8f61b274a6b72",
+       []
+      ],
+      "table-grid-paint-vrl-rtl-ref.html": [
+       "2080a4e4501846c23e73660df8dfbee252f4d5e5",
+       []
+      ],
       "table-row-paint-htb-ltr-ref.html": [
        "74e99b0143aa89b641b06297a282b2d46c868e06",
        []
@@ -280467,7 +280544,7 @@
       []
      ],
      "target-text-text-decoration-001-ref.html": [
-      "0ee37b1e8aadfed3945bfecc6dbe77e783def5a1",
+      "b15f74c1dac7da3000f9f9fcc71ba86d5336a072",
       []
      ],
      "target-text-two-words-ref.html": [
@@ -301278,13 +301355,17 @@
          []
         ],
         "helper.sub.js": [
-         "ff446f5ee9d3c884f9867f05d2f736d3c752b100",
+         "4b42d91670252f929306fcda2e34dd4e61ea3265",
          []
         ],
         "inflight-fetch-helper.js": [
          "7832003b76b9518d5f3588bb5e9f6e0dbd8cea07",
          []
         ],
+        "service-worker.js": [
+         "60dceb0a6a6f5f2cf882610e3bd19e15e9533458",
+         []
+        ],
         "slow.py": [
          "01bb3309b103d5bba772bdbf1d0d0b8bc28c8e99",
          []
@@ -317711,7 +317792,7 @@
     ]
    },
    "lint.ignore": [
-    "33aafc900aa9302bba611822dfc002ca5722d03d",
+    "fdba97deda7a6eb41a7209caae79371b2dd10917",
     []
    ],
    "loading": {
@@ -342333,6 +342414,20 @@
     ]
    },
    "WebCryptoAPI": {
+    "algorithm-discards-context.https.window.js": [
+     "e648bc2f230f0c6f0b84ae629d96853b3cb8cd58",
+     [
+      "WebCryptoAPI/algorithm-discards-context.https.window.html",
+      {
+       "script_metadata": [
+        [
+         "title",
+         "WebCryptoAPI: Properties discard the context in algorithm normalization"
+        ]
+       ]
+      }
+     ]
+    ],
     "derive_bits_keys": {
      "ecdh_bits.https.any.js": [
       "37e3eb4324200c85cb65ee9f077ea7433bff7783",
@@ -362475,6 +362570,13 @@
        {}
       ]
      ],
+     "iframe-srcdoc-history-inheritance.html": [
+      "91592252e2efc64614d8a1b90290d3ec07a6e49a",
+      [
+       null,
+       {}
+      ]
+     ],
      "iframe-srcdoc-inheritance.html": [
       "e05150762faa6affa644876961f004723ab2806a",
       [
@@ -364664,14 +364766,28 @@
     },
     "unsafe-hashes": {
      "javascript_src_allowed-href.html": [
-      "76e9576e8b11856695b12bd2516fa8507940c57e",
+      "0c2a43a6e653b78601be729bc5bf79560c7e5578",
+      [
+       null,
+       {}
+      ]
+     ],
+     "javascript_src_allowed-href_blank-script-src-attr.html": [
+      "f2b3e1ff72c4d2f4bd88aa214eb4c7f59bc59801",
+      [
+       null,
+       {}
+      ]
+     ],
+     "javascript_src_allowed-href_blank-script-src-elem.html": [
+      "642d9768a5135447363be510dd049ed7b9f3ee6e",
       [
        null,
        {}
       ]
      ],
      "javascript_src_allowed-href_blank.html": [
-      "007338bc45eb8eb019a71eb138a5465b482f06fa",
+      "a321521e04315c3ef345aa859340f3b30b638999",
       [
        null,
        {}
@@ -364692,14 +364808,28 @@
       ]
      ],
      "javascript_src_denied_missing_unsafe_hashes-href.html": [
-      "991200ac0daaa047a7637753b31d38ca7d99320b",
+      "0f0dc67aa317641e84e34c329eb279c1248c8226",
+      [
+       null,
+       {}
+      ]
+     ],
+     "javascript_src_denied_missing_unsafe_hashes-href_blank-script-src-attr.html": [
+      "6b863e7a99d0b36c3a43e49f41897772231d44cb",
+      [
+       null,
+       {}
+      ]
+     ],
+     "javascript_src_denied_missing_unsafe_hashes-href_blank-script-src-elem.html": [
+      "23e9bdc1875efdf34c6a88a6285c111bc350c621",
       [
        null,
        {}
       ]
      ],
      "javascript_src_denied_missing_unsafe_hashes-href_blank.html": [
-      "66ec9e1678c6ac5dc34f962bee2830d67853d763",
+      "81805a1f870cde832c7f0bc0699b4bdb2a4b67cd",
       [
        null,
        {}
@@ -364720,14 +364850,28 @@
       ]
      ],
      "javascript_src_denied_wrong_hash-href.html": [
-      "944b72774c8b15870f403941a38c705075046c16",
+      "6558a03aeddde9348c2a0ffb3097046605ef8c06",
+      [
+       null,
+       {}
+      ]
+     ],
+     "javascript_src_denied_wrong_hash-href_blank-script-src-attr.html": [
+      "fa394b1d0ae7db4685ce989f7f8dcb0670eeaac4",
+      [
+       null,
+       {}
+      ]
+     ],
+     "javascript_src_denied_wrong_hash-href_blank-script-src-elem.html": [
+      "8ca49da7754d6d8daf7b0b70b8476a4ff5806228",
       [
        null,
        {}
       ]
      ],
      "javascript_src_denied_wrong_hash-href_blank.html": [
-      "84491f83fbb1f3f5908fce22afad6a6370379ac5",
+      "257899af29cab223255bed94517425abc978670b",
       [
        null,
        {}
@@ -369121,6 +369265,13 @@
         null,
         {}
        ]
+      ],
+      "keyframes-allowed-properties.html": [
+       "f682920b35769e7a6479dad625510b9f163e56fd",
+       [
+        null,
+        {}
+       ]
       ]
      },
      "pending-style-changes-001.html": [
@@ -393295,6 +393446,13 @@
        {}
       ]
      ],
+     "viewport-units-modify.html": [
+      "8ce5d9871280c6781b5bde177ac73363198f2954",
+      [
+       null,
+       {}
+      ]
+     ],
      "viewport-units-parsing.html": [
       "4373b2a9f0844456c00904a3d90e159c78362c28",
       [
@@ -433472,6 +433630,42 @@
          }
         ]
        ],
+       "service-worker-clients-claim.https.html": [
+        "d9540c221bdf21e8e4256f30548aedbfee46e218",
+        [
+         null,
+         {
+          "timeout": "long"
+         }
+        ]
+       ],
+       "service-worker-clients-matchall.https.html": [
+        "069529dbe477c642e7396b0cd021d2f43d5e1e08",
+        [
+         null,
+         {
+          "timeout": "long"
+         }
+        ]
+       ],
+       "service-worker-controlled-after-restore.https.html": [
+        "5a63b6e677af2020bb5c414d289379c86e7b5dba",
+        [
+         null,
+         {
+          "timeout": "long"
+         }
+        ]
+       ],
+       "service-worker-unregister.https.html": [
+        "1c3f81153c2a17a3dfc719d2cccca2079525b630",
+        [
+         null,
+         {
+          "timeout": "long"
+         }
+        ]
+       ],
        "timers.html": [
         "aab650f36e5f58d064f1dd8b08d98e1bf7b010e8",
         [
@@ -461679,6 +461873,15 @@
             }
            ]
           ],
+          "does-not-ascend-out-of-non-extending-focusgroup.html": [
+           "b00958719d5a2d9ef32b93188347b6f7a65b08c1",
+           [
+            null,
+            {
+             "testdriver": true
+            }
+           ]
+          ],
           "does-not-move-when-axis-not-supported.html": [
            "e671a2584434289e8188f4615e49ec1fac991b88",
            [
@@ -461798,6 +462001,15 @@
             }
            ]
           ],
+          "does-not-ascend-out-of-non-extending-focusgroup.html": [
+           "08dc46660335471445c520a67be67555bdda4b06",
+           [
+            null,
+            {
+             "testdriver": true
+            }
+           ]
+          ],
           "does-not-move-when-axis-not-supported.html": [
            "0cf6ad3be23ec477b0786bc64d2833401426885e",
            [
@@ -468845,7 +469057,7 @@
         ]
        ],
        "select-event.html": [
-        "cb54b64592e191619d0543cd923d18e97994e518",
+        "c3a65f7302a9dd2f811eb9bd019fb153152c65ba",
         [
          null,
          {
@@ -470256,7 +470468,7 @@
         ]
        ],
        "selectmenu-parts-structure.tentative.html": [
-        "927b45cdc15b35cfc727644f3203c283cf2e21ac",
+        "7a11b57fcb786e78c190ccd39635311b73069ed6",
         [
          null,
          {
@@ -471245,7 +471457,7 @@
        ]
       ],
       "popup-anchor-nesting.tentative.html": [
-       "d7e5784ba4d6aecfc32ad3f68ddd40f69f2c93f5",
+       "c7ebe58ec7c466a89d66a6bcc082a9172bfa3af8",
        [
         null,
         {
@@ -471254,7 +471466,7 @@
        ]
       ],
       "popup-attribute-basic.tentative.html": [
-       "9d74476d4e1b88c528a3a049fc978487203762ce",
+       "661c63fec446b6fdce2327fdec452a4e5576c6d7",
        [
         null,
         {}
@@ -471268,28 +471480,28 @@
        ]
       ],
       "popup-defaultopen-2.tentative.html": [
-       "1e54e469ae8410cdc204437ec929eac84ce2d0ad",
+       "bf44092c09c8dc14e59a2272737ae80402ba6598",
        [
         null,
         {}
        ]
       ],
       "popup-defaultopen.tentative.html": [
-       "50bf825d8f2672754f0a409bd8c7d42af5be4e57",
+       "12cf5452fac9c42c21edd30ebe428967f0a267dc",
        [
         null,
         {}
        ]
       ],
       "popup-events.tentative.html": [
-       "9390ea3c40b585b2c0a8161765b305f4927f492b",
+       "7be1dae00bca10153b63e6af322f785d86207424",
        [
         null,
         {}
        ]
       ],
       "popup-focus.tentative.html": [
-       "6fccb0f13bdb489ee8b535267147e6d7a41f5bec",
+       "0612313ec904a4177e4079da59d1d3ee95427dcc",
        [
         null,
         {
@@ -471299,7 +471511,7 @@
        ]
       ],
       "popup-invoking-attribute.tentative.html": [
-       "49056f8b77ff9ca7c76f9555a7afbedb1382bd7a",
+       "2cac8d15abbd5c2885b8507138b9f9ef6d3e9227",
        [
         null,
         {
@@ -471309,14 +471521,14 @@
        ]
       ],
       "popup-light-dismiss-on-scroll.tentative.html": [
-       "bafa50dae36330fd24d9e5681693e307c1d4a0c0",
+       "10276edbb338445bcaf75143400cb7f378a44b38",
        [
         null,
         {}
        ]
       ],
       "popup-light-dismiss.tentative.html": [
-       "e3c05fa530d3f69198771c34fb0d92ad9f5417db",
+       "568a515a9d53f15f86886a92d6bed57793d52f16",
        [
         null,
         {
@@ -471325,7 +471537,7 @@
        ]
       ],
       "popup-not-keyboard-focusable.tentative.html": [
-       "39d98396c89409e7ce12c311713412f0ec51d1ec",
+       "4deb76d0d76911dd726ee13c80f343e07f82470e",
        [
         null,
         {
@@ -471334,35 +471546,35 @@
        ]
       ],
       "popup-removal-2.tentative.html": [
-       "0204c3c913412d83133bf528ec5b12bf7c1c8037",
+       "02e74297eeca211a73be6d61ad1476d8caa9a757",
        [
         null,
         {}
        ]
       ],
       "popup-removal.tentative.html": [
-       "02201dc2af8386eec05ae8b5771a94b30a8ebffe",
+       "525448eed1c71ab5f7a710901ef3b92c234f813c",
        [
         null,
         {}
        ]
       ],
       "popup-shadow-dom.tentative.html": [
-       "922bf1630f4a0c940f5e90dbe06e7d2b1bb55cb2",
+       "8df874def480aa6c1ff0295d53d15c7bd439adf7",
        [
         null,
         {}
        ]
       ],
       "popup-stacking.tentative.html": [
-       "160a4a573b75171a2d09a48efe2916ffcab28d41",
+       "2cf540c96d238065d9c89e59bb7292ddcd185eee",
        [
         null,
         {}
        ]
       ],
       "popup-top-layer-interactions.tentative.html": [
-       "53ded3ed0eba3c4175fb5e0719e6ea3850b23a6d",
+       "69cc436a3d1f8d3ce68106c835ba8765e9688596",
        [
         null,
         {
@@ -471371,7 +471583,7 @@
        ]
       ],
       "popup-types.tentative.html": [
-       "74a1b916440d0373279c069c78b47035a240b8dc",
+       "e3d24acfd9955da7d902f158adda1590eb229ca7",
        [
         null,
         {}
diff --git a/third_party/blink/web_tests/external/wpt/dom/abort/crashtests/timeout-close.html b/third_party/blink/web_tests/external/wpt/dom/abort/crashtests/timeout-close.html
new file mode 100644
index 0000000..ee8544a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/abort/crashtests/timeout-close.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="test-wait">
+<meta charset="utf-8">
+<iframe id="iframe"></iframe>
+<script>
+  const srcdoc = `
+    <!DOCTYPE html>
+    <meta charset="utf-8">
+    <script>
+      const xhr = new XMLHttpRequest()
+      setTimeout(() => {
+        xhr.open('GET', '/', false)
+        xhr.send()
+        AbortSignal.timeout(41.62684667994843)
+      }, 1)
+      setTimeout(() => {
+        location.href = "about:blank"
+        parent.document.documentElement.classList.remove("test-wait")
+      }, 0)
+    </` + "script>";
+  iframe.srcdoc = srcdoc;
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/horizontal/does-not-ascend-out-of-non-extending-focusgroup.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/horizontal/does-not-ascend-out-of-non-extending-focusgroup.html
new file mode 100644
index 0000000..b0095871
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/horizontal/does-not-ascend-out-of-non-extending-focusgroup.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focusgroup - Focus does not ascend out of current focusgroup if it does not extend the parent focusgroup.</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Focusgroup/explainer.md">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="../../resources/focusgroup-utils.js"></script>
+
+<ul focusgroup=horizontal>
+  <li id=item1 tabindex="-1">
+    <ul focusgroup=vertical>
+      <li id=item2 tabindex="-1">item2</li>
+    </ul>
+  </li>
+</ul>
+
+<script>
+
+  promise_test(async t => {
+    var item2 = document.getElementById("item2");
+
+    await focusAndKeyPress(item2, kArrowLeft);
+    assert_equals(document.activeElement, item2);
+  }, "When the focus is set on the first element of a non-extending focusgroup located inside another focusgroup, we should be able to ascend to that other focusgroup.");
+
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/vertical/does-not-ascend-out-of-non-extending-focusgroup.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/vertical/does-not-ascend-out-of-non-extending-focusgroup.html
new file mode 100644
index 0000000..08dc4666
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/vertical/does-not-ascend-out-of-non-extending-focusgroup.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focusgroup - Focus does not ascend out of current focusgroup if it does not extend the parent focusgroup.</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Focusgroup/explainer.md">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="../../resources/focusgroup-utils.js"></script>
+
+<ul focusgroup=vertical>
+  <li id=item1 tabindex="-1">
+    <ul focusgroup=horizontal>
+      <li id=item2 tabindex="-1">item2</li>
+    </ul>
+  </li>
+</ul>
+
+<script>
+
+  promise_test(async t => {
+    var item2 = document.getElementById("item2");
+
+    await focusAndKeyPress(item2, kArrowUp);
+    assert_equals(document.activeElement, item2);
+  }, "When the focus is set on the first element of a non-extending focusgroup located inside another focusgroup, we should be able to ascend to that other focusgroup.");
+
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/lint.ignore b/third_party/blink/web_tests/external/wpt/lint.ignore
index e6e755b..fdba97d 100644
--- a/third_party/blink/web_tests/external/wpt/lint.ignore
+++ b/third_party/blink/web_tests/external/wpt/lint.ignore
@@ -341,6 +341,7 @@
 SET TIMEOUT: speculation-rules/prerender/resources/deferred-promise-utils.js
 SET TIMEOUT: speculation-rules/prerender/resources/utils.js
 SET TIMEOUT: html/browsers/browsing-the-web/back-forward-cache/timers.html
+SET TIMEOUT: dom/abort/crashtests/timeout-close.html
 
 # setTimeout use in reftests
 SET TIMEOUT: acid/acid3/test.html
diff --git a/third_party/blink/web_tests/virtual/precompile-inline-scripts/external/wpt/html/semantics/scripting-1/README.txt b/third_party/blink/web_tests/virtual/precompile-inline-scripts/external/wpt/html/semantics/scripting-1/README.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/precompile-inline-scripts/external/wpt/html/semantics/scripting-1/README.txt
diff --git a/third_party/blink/web_tests/virtual/precompile-inline-scripts/fast/dom/HTMLScriptElement/README.txt b/third_party/blink/web_tests/virtual/precompile-inline-scripts/fast/dom/HTMLScriptElement/README.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/precompile-inline-scripts/fast/dom/HTMLScriptElement/README.txt
diff --git a/third_party/cpuinfo/BUILD.gn b/third_party/cpuinfo/BUILD.gn
index 565609f..10fe3d2 100644
--- a/third_party/cpuinfo/BUILD.gn
+++ b/third_party/cpuinfo/BUILD.gn
@@ -2,30 +2,16 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-config("cpuinfo_include") {
+config("cpuinfo_config") {
   include_dirs = [
     "src/include",
     "src/src",
     "src/deps/clog/include",
   ]
-}
-
-config("cpuinfo_config") {
-  cflags = [
-    # For chipset.c and utils.h.
-    "-Wno-implicit-function-declaration",
-
-    # For clog.c.
-    "-Wno-unused-result",
-
-    # A lot of locations.
-    "-Wno-unused-function",
-  ]
 
   defines = [
-    "_GNU_SOURCE=1",  # Required for CPU_SETSIZE to be available.
-    "CPUINFO_INTERNAL=",
-    "CPUINFO_PRIVATE=",
+    # Required for CPU_SETSIZE to be available.
+    "_GNU_SOURCE",
   ]
 }
 
@@ -37,184 +23,82 @@
     "src/include/cpuinfo.h",
     "src/src/api.c",
     "src/src/cache.c",
+    "src/src/cpuinfo/common.h",
+    "src/src/cpuinfo/internal-api.h",
+    "src/src/cpuinfo/log.h",
+    "src/src/cpuinfo/utils.h",
     "src/src/init.c",
   ]
 
   deps = [
-    ":cpu_and_os_specific",
-    ":cpu_specific",
-    ":os_specific",
+    ":cache_x86",
+    ":linux",
+    ":linux_x86",
+    ":x86",
   ]
 
-  configs -= [
-    "//build/config/compiler:chromium_code",
-    "//build/config/sanitizers:default_sanitizer_flags",
-  ]
-  configs += [
-    "//build/config/compiler:no_chromium_code",
-    ":cpuinfo_config",
-  ]
-
-  public_configs = [ ":cpuinfo_include" ]
-}
-
-source_set("os_specific") {
-  if (is_chromeos || is_linux || is_android) {
-    sources = [
-      "src/src/linux/cpulist.c",
-      "src/src/linux/multiline.c",
-      "src/src/linux/processors.c",
-      "src/src/linux/smallfile.c",
-    ]
-  }
-
-  if (is_mac || is_ios) {
-    sources = [ "src/src/mach/topology.c" ]
-  }
-
-  configs -= [
-    "//build/config/compiler:chromium_code",
-    "//build/config/sanitizers:default_sanitizer_flags",
-  ]
-  configs += [
-    "//build/config/compiler:no_chromium_code",
-    ":cpuinfo_include",
-    ":cpuinfo_config",
-  ]
-}
-
-source_set("cpu_specific") {
-  if (current_cpu == "x86" || current_cpu == "x64") {
-    sources = [
-      "src/src/x86/info.c",
-      "src/src/x86/init.c",
-      "src/src/x86/isa.c",
-      "src/src/x86/name.c",
-      "src/src/x86/topology.c",
-      "src/src/x86/uarch.c",
-      "src/src/x86/vendor.c",
-    ]
-  }
-
-  if (current_cpu == "arm" || current_cpu == "arm64") {
-    sources = [
-      "src/src/arm/cache.c",
-      "src/src/arm/uarch.c",
-    ]
-  }
-
-  # Because "init.c" is reused again, but only has sources in the corresponding
-  # build config.
-  deps = [ ":x86_cache" ]
-
   configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [
-    "//build/config/compiler:no_chromium_code",
-    ":cpuinfo_config",
-    ":cpuinfo_include",
-  ]
+  configs += [ "//build/config/compiler:no_chromium_code" ]
+
+  public_configs = [ ":cpuinfo_config" ]
 }
 
-source_set("x86_cache") {
-  if (current_cpu == "x86" || current_cpu == "x64") {
-    sources = [
-      "src/src/x86/cache/descriptor.c",
-      "src/src/x86/cache/deterministic.c",
-      "src/src/x86/cache/init.c",
-    ]
-  }
+source_set("x86") {
+  sources = [
+    "src/src/x86/api.h",
+    "src/src/x86/cpuid.h",
+    "src/src/x86/info.c",
+    "src/src/x86/init.c",
+    "src/src/x86/isa.c",
+    "src/src/x86/name.c",
+    "src/src/x86/topology.c",
+    "src/src/x86/uarch.c",
+    "src/src/x86/vendor.c",
+  ]
 
-  configs -= [
-    "//build/config/compiler:chromium_code",
-    "//build/config/sanitizers:default_sanitizer_flags",
-  ]
-  configs += [
-    "//build/config/compiler:no_chromium_code",
-    ":cpuinfo_include",
-    ":cpuinfo_config",
-  ]
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [ "//build/config/compiler:no_chromium_code" ]
+
+  public_configs = [ ":cpuinfo_config" ]
 }
 
-source_set("cpu_and_os_specific") {
-  if ((is_linux || is_chromeos) &&
-      (current_cpu == "x86" || current_cpu == "x64")) {
-    sources = [
-      "src/src/x86/linux/cpuinfo.c",
-      "src/src/x86/linux/init.c",
-    ]
-  }
-
-  if ((is_linux || is_chromeos) && current_cpu == "arm") {
-    sources = [
-      "src/src/arm/linux/aarch32-isa.c",
-      "src/src/arm/linux/api.h",
-      "src/src/arm/linux/chipset.c",
-      "src/src/arm/linux/clusters.c",
-      "src/src/arm/linux/cpuinfo.c",
-      "src/src/arm/linux/hwcap.c",
-      "src/src/arm/linux/init.c",
-      "src/src/arm/linux/midr.c",
-    ]
-  }
-
-  if ((is_linux || is_chromeos) && current_cpu == "arm64") {
-    sources = [
-      "src/src/arm/linux/aarch64-isa.c",
-      "src/src/arm/linux/api.h",
-      "src/src/arm/linux/chipset.c",
-      "src/src/arm/linux/clusters.c",
-      "src/src/arm/linux/cpuinfo.c",
-      "src/src/arm/linux/hwcap.c",
-      "src/src/arm/linux/init.c",
-      "src/src/arm/linux/midr.c",
-    ]
-  }
-
-  if (is_android && (current_cpu == "arm" || current_cpu == "arm64")) {
-    sources = [
-      "src/src/arm/android/properties.c",
-      "src/src/arm/linux/api.h",
-      "src/src/arm/linux/chipset.c",
-      "src/src/arm/linux/clusters.c",
-      "src/src/arm/linux/cpuinfo.c",
-      "src/src/arm/linux/hwcap.c",
-      "src/src/arm/linux/init.c",
-      "src/src/arm/linux/midr.c",
-    ]
-
-    if (current_cpu == "arm64") {
-      sources += [ "src/src/arm/linux/aarch64-isa.c" ]
-    } else {
-      sources += [ "src/src/arm/linux/aarch32-isa.c" ]
-    }
-  }
-
-  if (is_android && (current_cpu == "x86" || current_cpu == "x64")) {
-    sources = [
-      "src/src/x86/linux/cpuinfo.c",
-      "src/src/x86/linux/init.c",
-    ]
-  }
-
-  if (is_win && (current_cpu == "x86" || current_cpu == "x64")) {
-    sources = [ "src/src/x86/windows/init.c" ]
-  }
-
-  if ((is_mac || is_ios) && (current_cpu == "x86" || current_cpu == "x64")) {
-    sources = [ "src/src/x86/mach/init.c" ]
-  }
-
-  if ((is_mac || is_ios) && (current_cpu == "arm" || current_cpu == "arm64")) {
-    sources = [ "src/src/arm/mach/init.c" ]
-  }
-
-  configs -= [
-    "//build/config/compiler:chromium_code",
-    "//build/config/sanitizers:default_sanitizer_flags",
+source_set("linux") {
+  sources = [
+    "src/src/linux/cpulist.c",
+    "src/src/linux/multiline.c",
+    "src/src/linux/processors.c",
+    "src/src/linux/smallfile.c",
   ]
-  configs += [
-    "//build/config/compiler:no_chromium_code",
-    ":cpuinfo_include",
-    ":cpuinfo_config",
+
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [ "//build/config/compiler:no_chromium_code" ]
+  configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ]
+
+  public_configs = [ ":cpuinfo_config" ]
+}
+
+source_set("linux_x86") {
+  sources = [
+    "src/src/x86/linux/api.h",
+    "src/src/x86/linux/cpuinfo.c",
+    "src/src/x86/linux/init.c",
   ]
+
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [ "//build/config/compiler:no_chromium_code" ]
+
+  public_configs = [ ":cpuinfo_config" ]
+}
+
+source_set("cache_x86") {
+  sources = [
+    "src/src/x86/cache/descriptor.c",
+    "src/src/x86/cache/deterministic.c",
+    "src/src/x86/cache/init.c",
+  ]
+
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [ "//build/config/compiler:no_chromium_code" ]
+
+  public_configs = [ ":cpuinfo_config" ]
 }
diff --git a/third_party/polymer/v3_0/components-chromium/iron-overlay-behavior/iron-overlay-backdrop.js b/third_party/polymer/v3_0/components-chromium/iron-overlay-behavior/iron-overlay-backdrop.js
index fca79f0..d32f1cc3 100644
--- a/third_party/polymer/v3_0/components-chromium/iron-overlay-behavior/iron-overlay-backdrop.js
+++ b/third_party/polymer/v3_0/components-chromium/iron-overlay-behavior/iron-overlay-backdrop.js
@@ -26,8 +26,6 @@
 -------------------------------------------|------------------------|---------
 `--iron-overlay-backdrop-background-color` | Backdrop background color | #000
 `--iron-overlay-backdrop-opacity`          | Backdrop opacity | 0.6
-`--iron-overlay-backdrop`                  | Mixin applied to `iron-overlay-backdrop`.                      | {}
-`--iron-overlay-backdrop-opened`           | Mixin applied to `iron-overlay-backdrop` when it is displayed | {}
 */
 Polymer({
   _template: html`
@@ -42,13 +40,11 @@
         opacity: 0;
         transition: opacity 0.2s;
         pointer-events: none;
-        @apply --iron-overlay-backdrop;
       }
 
       :host(.opened) {
         opacity: var(--iron-overlay-backdrop-opacity, 0.6);
         pointer-events: auto;
-        @apply --iron-overlay-backdrop-opened;
       }
     </style>
 
diff --git a/third_party/polymer/v3_0/iron_overlay_backdrop.patch b/third_party/polymer/v3_0/iron_overlay_backdrop.patch
new file mode 100644
index 0000000..b1101d7
--- /dev/null
+++ b/third_party/polymer/v3_0/iron_overlay_backdrop.patch
@@ -0,0 +1,27 @@
+diff --git a/components-chromium/iron-overlay-behavior/iron-overlay-backdrop.js b/components-chromium/iron-overlay-behavior/iron-overlay-backdrop.js
+index fca79f0d2cd25..d32f1cc38325f 100644
+--- a/components-chromium/iron-overlay-behavior/iron-overlay-backdrop.js
++++ b/components-chromium/iron-overlay-behavior/iron-overlay-backdrop.js
+@@ -26,8 +26,6 @@ Custom property | Description | Default
+ -------------------------------------------|------------------------|---------
+ `--iron-overlay-backdrop-background-color` | Backdrop background color | #000
+ `--iron-overlay-backdrop-opacity`          | Backdrop opacity | 0.6
+-`--iron-overlay-backdrop`                  | Mixin applied to `iron-overlay-backdrop`.                      | {}
+-`--iron-overlay-backdrop-opened`           | Mixin applied to `iron-overlay-backdrop` when it is displayed | {}
+ */
+ Polymer({
+   _template: html`
+@@ -42,13 +40,11 @@ Polymer({
+         opacity: 0;
+         transition: opacity 0.2s;
+         pointer-events: none;
+-        @apply --iron-overlay-backdrop;
+       }
+ 
+       :host(.opened) {
+         opacity: var(--iron-overlay-backdrop-opacity, 0.6);
+         pointer-events: auto;
+-        @apply --iron-overlay-backdrop-opened;
+       }
+     </style>
+ 
diff --git a/third_party/polymer/v3_0/reproduce.sh b/third_party/polymer/v3_0/reproduce.sh
index 1578e71..a9af73b0 100755
--- a/third_party/polymer/v3_0/reproduce.sh
+++ b/third_party/polymer/v3_0/reproduce.sh
@@ -55,6 +55,7 @@
 patch -p1 --forward < chromium.patch
 patch -p1 --forward < iron_icon.patch
 patch -p1 --forward < iron_list.patch
+patch -p1 --forward < iron_overlay_backdrop.patch
 patch -p1 --forward < paper_progress.patch
 patch -p1 --forward < paper_tooltip.patch
 
diff --git a/third_party/ruy/BUILD.gn b/third_party/ruy/BUILD.gn
index d468465..54a0e61 100644
--- a/third_party/ruy/BUILD.gn
+++ b/third_party/ruy/BUILD.gn
@@ -2,827 +2,106 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/arm.gni")
-
-use_cpuinfo =
-    # cpuinfo is not supported on these chips.
-    current_cpu != "ppc64" && current_cpu != "ppc64le" &&
-    current_cpu != "s390" && current_cpu != "s390x" &&
-    # cpuinfo is not supported on fuchsia.
-    !is_fuchsia &&
-    # There's a few arm architectures that are not supported by cpuinfo,
-    # especially amongst ChromeOS devices.
-    # See //third_party/cpuinfo/src/src/arm/linux/cp.h.
-    (!defined(arm_arch) ||
-     (arm_arch != "armv7-a+crc" && arm_arch != "armv8-a+crc"))
-
-config("ruy_include") {
+config("ruy_includes") {
   include_dirs = [ "src" ]
 }
 
-config("ruy_shared_config") {
-  include_dirs = [ "src" ]
-
-  if (current_cpu == "arm" || current_cpu == "arm64") {
-    # Disables a warning about the assembly instructions that are used.
+config("ruy_flags") {
+  if (target_cpu == "arm" || target_cpu == "arm64") {
     cflags = [ "-Wno-inline-asm" ]
   }
 }
 
-# We skip cmake's |ruy_0_Wall_Wcxx14_compat_Wextra_Wundef|, |ruy_1_mfpu_neon|,
-# |ruy_2_O3|, |ruy_3_pthread|, and |ruy_no_undef| rules since those flags are
-# covered by Chromium's build system..
-
-# Analogous to cmake's |ruy_5_DRUY_HAVE_CPUINFO|.
-config("ruy_cpuinfo_config") {
-  if (use_cpuinfo) {
-    defines = [ "RUY_HAVE_CPUINFO" ]
-  }
-}
-
-# We skip cmake's
-# |ruy_7_mavx512bw_mavx512cd_mavx512dq_mavx512f_mavx512vl_arch_AVX512| rule
-# since there's too few consumer machines that it would apply to, while still
-# eating the binary size for everybody.
-
-# Analogous to cmake's |ruy_8_mavx2_mfma_arch_AVX2|.
-config("ruy_avx2_flags") {
-  if ((current_cpu == "x86_64" || current_cpu == "amd64") && !is_win) {
-    cflags = [
-      "-mavx2",
-      "-mfma",
-    ]
-  } else if (is_win) {
-    cflags = [ "/arch:AVX2" ]
-  }
-}
-
-# Analogous to cmake's |ruy_9_mavx_arch_AVX|.
-config("ruy_avx_flags") {
-  if ((current_cpu == "x86_64" || current_cpu == "amd64") && !is_win) {
-    cflags = [ "-mavx" ]
-  } else if (is_win) {
-    cflags = [ "/arch:AVX" ]
-  }
-}
-
-# We skip cmake's |ruy_10_lm| rule since those flags are covered by Chromium's
-# build system.
-
-source_set("ruy_trace") {
-  sources = [ "src/ruy/trace.h" ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_mat",
-    ":ruy_matrix",
-    ":ruy_path",
-    ":ruy_platform",
-    ":ruy_side_pair",
-  ]
-}
-
-source_set("ruy_platform") {
-  sources = [ "src/ruy/platform.h" ]
-  configs += [ ":ruy_shared_config" ]
-}
-
-source_set("ruy_check_macros") {
-  sources = [ "src/ruy/check_macros.h" ]
-  configs += [ ":ruy_shared_config" ]
-}
-
-source_set("ruy_opt_set") {
-  sources = [ "src/ruy/opt_set.h" ]
-  configs += [ ":ruy_shared_config" ]
-}
-
-source_set("ruy_time") {
-  sources = [ "src/ruy/time.h" ]
-  configs += [ ":ruy_shared_config" ]
-}
-
-source_set("ruy_wait") {
-  sources = [
-    "src/ruy/wait.cc",
-    "src/ruy/wait.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [ ":ruy_time" ]
-}
-
-source_set("ruy_size_util") {
-  sources = [ "src/ruy/size_util.h" ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [ ":ruy_check_macros" ]
-}
-
-source_set("ruy_tune") {
-  sources = [
-    "src/ruy/tune.cc",
-    "src/ruy/tune.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_cpu_cache_params",
-    ":ruy_cpuinfo",
-    ":ruy_opt_set",
-    ":ruy_platform",
-    ":ruy_time",
-  ]
-}
-
-source_set("ruy_system_aligned_alloc") {
-  sources = [
-    "src/ruy/system_aligned_alloc.cc",
-    "src/ruy/system_aligned_alloc.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-}
-
-source_set("ruy_prepacked_cache") {
-  sources = [
-    "src/ruy/prepacked_cache.cc",
-    "src/ruy/prepacked_cache.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_mat",
-    ":ruy_profiler_instrumentation",
-    ":ruy_system_aligned_alloc",
-  ]
-}
-
-source_set("ruy_allocator") {
+source_set("ruy") {
   sources = [
     "src/ruy/allocator.cc",
     "src/ruy/allocator.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_opt_set",
-    ":ruy_size_util",
-    ":ruy_system_aligned_alloc",
-  ]
-}
-
-source_set("ruy_side_pair") {
-  sources = [ "src/ruy/side_pair.h" ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [ ":ruy_check_macros" ]
-}
-
-source_set("ruy_block_map") {
-  sources = [
-    "src/ruy/block_map.cc",
-    "src/ruy/block_map.h",
-  ]
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [
-    "//build/config/compiler:no_chromium_code",
-    ":ruy_shared_config",
-  ]
-  deps = [
-    ":ruy_check_macros",
-    ":ruy_cpu_cache_params",
-    ":ruy_opt_set",
-    ":ruy_profiler_instrumentation",
-    ":ruy_side_pair",
-    ":ruy_size_util",
-    ":ruy_trace",
-  ]
-}
-
-source_set("ruy_blocking_counter") {
-  sources = [
-    "src/ruy/blocking_counter.cc",
-    "src/ruy/blocking_counter.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_check_macros",
-    ":ruy_time",
-    ":ruy_wait",
-  ]
-}
-
-source_set("ruy_thread_pool") {
-  sources = [
-    "src/ruy/thread_pool.cc",
-    "src/ruy/thread_pool.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_blocking_counter",
-    ":ruy_check_macros",
-    ":ruy_denormal",
-    ":ruy_time",
-    ":ruy_trace",
-    ":ruy_wait",
-  ]
-}
-
-source_set("ruy_cpu_cache_params") {
-  sources = [ "src/ruy/cpu_cache_params.h" ]
-  configs += [ ":ruy_shared_config" ]
-}
-
-source_set("ruy_cpuinfo") {
-  sources = [
-    "src/ruy/cpuinfo.cc",
-    "src/ruy/cpuinfo.h",
-  ]
-  configs += [
-    ":ruy_shared_config",
-    ":ruy_cpuinfo_config",
-  ]
-  deps = [
-    ":ruy_check_macros",
-    ":ruy_cpu_cache_params",
-    ":ruy_platform",
-  ]
-
-  if (use_cpuinfo) {
-    deps += [ "//third_party/cpuinfo" ]
-  }
-}
-
-source_set("ruy_path") {
-  sources = [ "src/ruy/path.h" ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_platform",
-    ":ruy_size_util",
-  ]
-}
-
-source_set("ruy_denormal") {
-  sources = [
-    "src/ruy/denormal.cc",
-    "src/ruy/denormal.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-}
-
-source_set("ruy_performance_advisory") {
-  sources = [ "src/ruy/performance_advisory.h" ]
-  configs += [ ":ruy_shared_config" ]
-}
-
-source_set("ruy_matrix") {
-  sources = [ "src/ruy/matrix.h" ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [ ":ruy_check_macros" ]
-}
-
-source_set("ruy_mul_params") {
-  sources = [ "src/ruy/mul_params.h" ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_check_macros",
-    ":ruy_size_util",
-  ]
-}
-
-source_set("ruy_mat") {
-  sources = [ "src/ruy/mat.h" ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_check_macros",
-    ":ruy_matrix",
-    ":ruy_size_util",
-  ]
-}
-
-source_set("ruy_asm_helpers") {
-  sources = [ "src/ruy/asm_helpers.h" ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [ ":ruy_opt_set" ]
-}
-
-source_set("ruy_apply_multiplier") {
-  sources = [
     "src/ruy/apply_multiplier.cc",
     "src/ruy/apply_multiplier.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_check_macros",
-    ":ruy_mul_params",
-  ]
-}
-
-source_set("ruy_kernel_common") {
-  sources = [ "src/ruy/kernel_common.h" ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_apply_multiplier",
-    ":ruy_check_macros",
-    ":ruy_instrumentation",
-    ":ruy_mat",
-    ":ruy_matrix",
-    ":ruy_mul_params",
-    ":ruy_opt_set",
-    ":ruy_path",
-    ":ruy_platform",
-    ":ruy_profiler_instrumentation",
-    ":ruy_side_pair",
-    ":ruy_size_util",
-    ":ruy_tune",
-  ]
-}
-
-source_set("ruy_pack_common") {
-  sources = [ "src/ruy/pack_common.h" ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_check_macros",
-    ":ruy_mat",
-    ":ruy_matrix",
-    ":ruy_opt_set",
-    ":ruy_path",
-    ":ruy_platform",
-    ":ruy_profiler_instrumentation",
-    ":ruy_tune",
-  ]
-}
-
-source_set("ruy_kernel_arm") {
-  sources = [
-    "src/ruy/kernel_arm.h",
-    "src/ruy/kernel_arm32.cc",
-    "src/ruy/kernel_arm64.cc",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_asm_helpers",
-    ":ruy_check_macros",
-    ":ruy_kernel_common",
-    ":ruy_mat",
-    ":ruy_mul_params",
-    ":ruy_opt_set",
-    ":ruy_path",
-    ":ruy_platform",
-    ":ruy_profiler_instrumentation",
-    ":ruy_side_pair",
-    ":ruy_size_util",
-    ":ruy_tune",
-  ]
-}
-
-source_set("ruy_pack_arm") {
-  sources = [
-    "src/ruy/pack_arm.cc",
-    "src/ruy/pack_arm.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_asm_helpers",
-    ":ruy_check_macros",
-    ":ruy_mat",
-    ":ruy_opt_set",
-    ":ruy_pack_common",
-    ":ruy_path",
-    ":ruy_platform",
-    ":ruy_profiler_instrumentation",
-    ":ruy_tune",
-  ]
-}
-
-source_set("ruy_kernel_avx512") {
-  sources = [
-    "src/ruy/kernel_avx512.cc",
-    "src/ruy/kernel_x86.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_check_macros",
-    ":ruy_instrumentation",
-    ":ruy_kernel_common",
-    ":ruy_mat",
-    ":ruy_mul_params",
-    ":ruy_opt_set",
-    ":ruy_path",
-    ":ruy_platform",
-    ":ruy_profiler_instrumentation",
-    ":ruy_tune",
-  ]
-}
-
-source_set("ruy_pack_avx512") {
-  sources = [
-    "src/ruy/pack_avx512.cc",
-    "src/ruy/pack_x86.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_check_macros",
-    ":ruy_mat",
-    ":ruy_opt_set",
-    ":ruy_pack_common",
-    ":ruy_path",
-    ":ruy_platform",
-    ":ruy_profiler_instrumentation",
-    ":ruy_tune",
-  ]
-}
-
-source_set("ruy_have_built_path_for_avx512") {
-  sources = [
-    "src/ruy/have_built_path_for.h",
-    "src/ruy/have_built_path_for_avx512.cc",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_opt_set",
-    ":ruy_platform",
-  ]
-}
-
-source_set("ruy_kernel_avx2_fma") {
-  sources = [
-    "src/ruy/kernel_avx2_fma.cc",
-    "src/ruy/kernel_x86.h",
-  ]
-  configs += [
-    ":ruy_shared_config",
-    ":ruy_avx2_flags",
-  ]
-  deps = [
-    ":ruy_check_macros",
-    ":ruy_kernel_common",
-    ":ruy_mat",
-    ":ruy_mul_params",
-    ":ruy_opt_set",
-    ":ruy_path",
-    ":ruy_platform",
-    ":ruy_profiler_instrumentation",
-    ":ruy_tune",
-  ]
-}
-
-source_set("ruy_pack_avx2_fma") {
-  sources = [
-    "src/ruy/pack_avx2_fma.cc",
-    "src/ruy/pack_x86.h",
-  ]
-  configs += [
-    ":ruy_shared_config",
-    ":ruy_avx2_flags",
-  ]
-  deps = [
-    ":ruy_check_macros",
-    ":ruy_mat",
-    ":ruy_opt_set",
-    ":ruy_pack_common",
-    ":ruy_path",
-    ":ruy_platform",
-    ":ruy_profiler_instrumentation",
-    ":ruy_tune",
-  ]
-}
-
-source_set("ruy_have_built_path_for_avx2_fma") {
-  sources = [
-    "src/ruy/have_built_path_for.h",
-    "src/ruy/have_built_path_for_avx2_fma.cc",
-  ]
-  configs += [
-    ":ruy_shared_config",
-    ":ruy_avx2_flags",
-  ]
-  deps = [
-    ":ruy_opt_set",
-    ":ruy_platform",
-  ]
-}
-
-source_set("ruy_kernel_avx") {
-  sources = [
-    "src/ruy/kernel_avx.cc",
-    "src/ruy/kernel_x86.h",
-  ]
-  configs += [
-    ":ruy_shared_config",
-    ":ruy_avx_flags",
-  ]
-  deps = [
-    ":ruy_check_macros",
-    ":ruy_kernel_common",
-    ":ruy_mat",
-    ":ruy_mul_params",
-    ":ruy_opt_set",
-    ":ruy_path",
-    ":ruy_platform",
-    ":ruy_profiler_instrumentation",
-    ":ruy_tune",
-  ]
-}
-
-source_set("ruy_pack_avx") {
-  sources = [
-    "src/ruy/pack_avx.cc",
-    "src/ruy/pack_x86.h",
-  ]
-  configs += [
-    ":ruy_shared_config",
-    ":ruy_avx_flags",
-  ]
-  deps = [
-    ":ruy_check_macros",
-    ":ruy_mat",
-    ":ruy_opt_set",
-    ":ruy_pack_common",
-    ":ruy_path",
-    ":ruy_platform",
-    ":ruy_profiler_instrumentation",
-    ":ruy_tune",
-  ]
-}
-
-source_set("ruy_have_built_path_for_avx") {
-  sources = [
-    "src/ruy/have_built_path_for.h",
-    "src/ruy/have_built_path_for_avx.cc",
-  ]
-  configs += [
-    ":ruy_shared_config",
-    ":ruy_avx_flags",
-  ]
-  deps = [
-    ":ruy_opt_set",
-    ":ruy_platform",
-  ]
-}
-
-source_set("ruy_kernel") {
-  sources = [ "src/ruy/kernel.h" ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_apply_multiplier",
-    ":ruy_check_macros",
-    ":ruy_kernel_arm",
-    ":ruy_kernel_avx",
-    ":ruy_kernel_avx2_fma",
-    ":ruy_kernel_avx512",
-    ":ruy_kernel_common",
-    ":ruy_mat",
-    ":ruy_matrix",
-    ":ruy_mul_params",
-    ":ruy_opt_set",
-    ":ruy_path",
-    ":ruy_platform",
-    ":ruy_profiler_instrumentation",
-    ":ruy_side_pair",
-    ":ruy_size_util",
-    ":ruy_trace",
-    ":ruy_tune",
-  ]
-}
-
-source_set("ruy_pack") {
-  sources = [ "src/ruy/pack.h" ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_check_macros",
-    ":ruy_mat",
-    ":ruy_matrix",
-    ":ruy_opt_set",
-    ":ruy_pack_arm",
-    ":ruy_pack_avx",
-    ":ruy_pack_avx2_fma",
-    ":ruy_pack_avx512",
-    ":ruy_pack_common",
-    ":ruy_path",
-    ":ruy_platform",
-    ":ruy_profiler_instrumentation",
-    ":ruy_trace",
-    ":ruy_tune",
-  ]
-}
-
-source_set("ruy_have_built_path_for") {
-  sources = [ "src/ruy/have_built_path_for.h" ]
-  deps = [
-    ":ruy_have_built_path_for_avx",
-    ":ruy_have_built_path_for_avx2_fma",
-    ":ruy_have_built_path_for_avx512",
-    ":ruy_platform",
-  ]
-}
-
-source_set("ruy_context") {
-  sources = [
+    "src/ruy/asm_helpers.h",
+    "src/ruy/block_map.cc",
+    "src/ruy/block_map.h",
+    "src/ruy/blocking_counter.cc",
+    "src/ruy/blocking_counter.h",
+    "src/ruy/check_macros.h",
     "src/ruy/context.cc",
     "src/ruy/context.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_allocator",
-    ":ruy_check_macros",
-    ":ruy_ctx",
-    ":ruy_path",
-    ":ruy_performance_advisory",
-    ":ruy_platform",
-    ":ruy_prepacked_cache",
-    ":ruy_thread_pool",
-    ":ruy_tune",
-  ]
-}
-
-source_set("ruy_ctx") {
-  sources = [
+    "src/ruy/context_get_ctx.cc",
+    "src/ruy/context_get_ctx.h",
+    "src/ruy/cpu_cache_params.h",
+    "src/ruy/cpuinfo.cc",
+    "src/ruy/cpuinfo.h",
+    "src/ruy/create_trmul_params.h",
     "src/ruy/ctx.cc",
     "src/ruy/ctx.h",
     "src/ruy/ctx_impl.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_allocator",
-    ":ruy_check_macros",
-    ":ruy_cpuinfo",
-    ":ruy_have_built_path_for",
-    ":ruy_path",
-    ":ruy_performance_advisory",
-    ":ruy_platform",
-    ":ruy_prepacked_cache",
-    ":ruy_thread_pool",
-    ":ruy_trace",
-    ":ruy_tune",
-  ]
-}
-
-source_set("ruy_context_get_ctx") {
-  sources = [
-    "src/ruy/context_get_ctx.cc",
-    "src/ruy/context_get_ctx.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_context",
-    ":ruy_ctx",
-  ]
-}
-
-source_set("ruy_trmul_params") {
-  sources = [ "src/ruy/trmul_params.h" ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_instrumentation",
-    ":ruy_mat",
-    ":ruy_mul_params",
-    ":ruy_path",
-    ":ruy_side_pair",
-    ":ruy_tune",
-  ]
-}
-
-source_set("ruy_trmul") {
-  sources = [
-    "src/ruy/trmul.cc",
-    "src/ruy/trmul.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_allocator",
-    ":ruy_block_map",
-    ":ruy_check_macros",
-    ":ruy_cpu_cache_params",
-    ":ruy_cpuinfo",
-    ":ruy_ctx",
-    ":ruy_denormal",
-    ":ruy_mat",
-    ":ruy_matrix",
-    ":ruy_mul_params",
-    ":ruy_opt_set",
-    ":ruy_profiler_instrumentation",
-    ":ruy_side_pair",
-    ":ruy_size_util",
-    ":ruy_thread_pool",
-    ":ruy_trace",
-    ":ruy_trmul_params",
-    ":ruy_tune",
-  ]
-}
-
-source_set("ruy_prepare_packed_matrices") {
-  sources = [
-    "src/ruy/prepare_packed_matrices.cc",
-    "src/ruy/prepare_packed_matrices.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_allocator",
-    ":ruy_ctx",
-    ":ruy_matrix",
-    ":ruy_prepacked_cache",
-    ":ruy_side_pair",
-    ":ruy_trace",
-    ":ruy_trmul_params",
-  ]
-}
-
-source_set("ruy_create_trmul_params") {
-  sources = [ "src/ruy/create_trmul_params.h" ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_allocator",
-    ":ruy_check_macros",
-    ":ruy_ctx",
-    ":ruy_kernel",
-    ":ruy_mat",
-    ":ruy_mul_params",
-    ":ruy_pack",
-    ":ruy_path",
-    ":ruy_performance_advisory",
-    ":ruy_platform",
-    ":ruy_side_pair",
-    ":ruy_trace",
-    ":ruy_trmul_params",
-  ]
-}
-
-source_set("ruy_validate") {
-  sources = [ "src/ruy/validate.h" ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_check_macros",
-    ":ruy_mat",
-    ":ruy_mul_params",
-    ":ruy_side_pair",
-  ]
-}
-
-source_set("ruy_frontend") {
-  sources = [
+    "src/ruy/denormal.cc",
     "src/ruy/frontend.cc",
     "src/ruy/frontend.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  deps = [
-    ":ruy_allocator",
-    ":ruy_create_trmul_params",
-    ":ruy_ctx",
-    ":ruy_mat",
-    ":ruy_mul_params",
-    ":ruy_prepare_packed_matrices",
-    ":ruy_profiler_instrumentation",
-    ":ruy_trace",
-    ":ruy_trmul",
-    ":ruy_trmul_params",
-    ":ruy_validate",
-  ]
-}
-
-source_set("ruy_instrumentation") {
-  sources = [
+    "src/ruy/have_built_path_for.h",
+    "src/ruy/have_built_path_for_avx.cc",
+    "src/ruy/have_built_path_for_avx2_fma.cc",
+    "src/ruy/have_built_path_for_avx512.cc",
+    "src/ruy/kernel.h",
+    "src/ruy/kernel_arm.h",
+    "src/ruy/kernel_arm32.cc",
+    "src/ruy/kernel_arm64.cc",
+    "src/ruy/kernel_avx.cc",
+    "src/ruy/kernel_avx2_fma.cc",
+    "src/ruy/kernel_avx512.cc",
+    "src/ruy/kernel_common.h",
+    "src/ruy/kernel_x86.h",
+    "src/ruy/mat.h",
+    "src/ruy/matrix.h",
+    "src/ruy/mul_params.h",
+    "src/ruy/opt_set.h",
+    "src/ruy/pack.h",
+    "src/ruy/pack_arm.cc",
+    "src/ruy/pack_arm.h",
+    "src/ruy/pack_avx.cc",
+    "src/ruy/pack_avx2_fma.cc",
+    "src/ruy/pack_avx512.cc",
+    "src/ruy/pack_common.h",
+    "src/ruy/pack_x86.h",
+    "src/ruy/path.h",
+    "src/ruy/performance_advisory.h",
+    "src/ruy/platform.h",
+    "src/ruy/pmu.cc",
+    "src/ruy/pmu.h",
+    "src/ruy/prepacked_cache.cc",
+    "src/ruy/prepacked_cache.h",
+    "src/ruy/prepare_packed_matrices.cc",
+    "src/ruy/prepare_packed_matrices.h",
     "src/ruy/profiler/instrumentation.cc",
     "src/ruy/profiler/instrumentation.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-  defines = [ "RUY_PROFILER" ]
-}
-
-source_set("ruy_profiler_instrumentation") {
-  sources = [
     "src/ruy/profiler/profiler.cc",
     "src/ruy/profiler/profiler.h",
     "src/ruy/profiler/treeview.cc",
     "src/ruy/profiler/treeview.h",
-  ]
-  public_deps = [ ":ruy_instrumentation" ]
-  configs += [ ":ruy_shared_config" ]
-}
-
-source_set("ruy") {
-  sources = [
-    "src/ruy/context.h",
-    "src/ruy/matrix.h",
-    "src/ruy/mul_params.h",
-    "src/ruy/path.h",
+    "src/ruy/reference_mul.h",
     "src/ruy/ruy.h",
-  ]
-  configs += [ ":ruy_shared_config" ]
-
-  # All the deps are public so that tflite can refer to the headers without
-  # failing `gn check`.
-  public_deps = [
-    ":ruy_check_macros",
-    ":ruy_context",
-    ":ruy_context_get_ctx",
-    ":ruy_denormal",
-    ":ruy_frontend",
-    ":ruy_instrumentation",
-    ":ruy_mat",
-    ":ruy_matrix",
-    ":ruy_mul_params",
-    ":ruy_path",
-    ":ruy_platform",
-    ":ruy_size_util",
-    ":ruy_trace",
+    "src/ruy/side_pair.h",
+    "src/ruy/size_util.h",
+    "src/ruy/system_aligned_alloc.cc",
+    "src/ruy/system_aligned_alloc.h",
+    "src/ruy/thread_pool.cc",
+    "src/ruy/thread_pool.h",
+    "src/ruy/time.h",
+    "src/ruy/trmul.cc",
+    "src/ruy/trmul.h",
+    "src/ruy/trmul_params.h",
+    "src/ruy/tune.cc",
+    "src/ruy/tune.h",
+    "src/ruy/validate.h",
+    "src/ruy/wait.cc",
+    "src/ruy/wait.h",
   ]
 
   configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
+  configs += [
+    ":ruy_flags",
+    "//build/config/compiler:no_chromium_code",
+  ]
 
-  public_configs = [ ":ruy_include" ]
+  public_configs = [ ":ruy_includes" ]
 }
diff --git a/third_party/tflite/BUILD.gn b/third_party/tflite/BUILD.gn
index e564906..935b974 100644
--- a/third_party/tflite/BUILD.gn
+++ b/third_party/tflite/BUILD.gn
@@ -66,9 +66,11 @@
     ]
   }
 
-  if (build_tflite_with_ruy) {
+  if (is_android) {
     defines += [ "TFLITE_WITH_RUY" ]
-  } else if (is_linux || is_chromeos_lacros) {
+  }
+
+  if (is_linux || is_chromeos_lacros) {
     defines += [ "GEMMLOWP_ALLOW_SLOW_SCALAR_FALLBACK" ]
   }
 
@@ -287,6 +289,7 @@
     "src/tensorflow/lite/kernels/cpu_backend_gemm_custom_gemv.h",
     "src/tensorflow/lite/kernels/cpu_backend_gemm_eigen.cc",
     "src/tensorflow/lite/kernels/cpu_backend_gemm_eigen.h",
+    "src/tensorflow/lite/kernels/cpu_backend_gemm_gemmlowp.h",
     "src/tensorflow/lite/kernels/cpu_backend_gemm_ruy.h",
     "src/tensorflow/lite/kernels/cumsum.cc",
     "src/tensorflow/lite/kernels/densify.cc",
@@ -377,10 +380,6 @@
     "src/tensorflow/lite/kernels/zeros_like.cc",
   ]
 
-  if (!build_tflite_with_ruy) {
-    sources += [ "src/tensorflow/lite/kernels/cpu_backend_gemm_gemmlowp.h" ]
-  }
-
   deps = [
     ":fft2d_deps",
     ":tflite_kernel_common_headers",
diff --git a/third_party/tflite/features.gni b/third_party/tflite/features.gni
index f11cb57c..f27df9c5 100644
--- a/third_party/tflite/features.gni
+++ b/third_party/tflite/features.gni
@@ -7,8 +7,5 @@
 declare_args() {
   # This enables building TFLite with XNNPACK. Currently only available for
   # Linux x64.
-  build_tflite_with_xnnpack = is_linux && current_cpu == "x64"
-
-  # Turns on TFLITE_WITH_RUY, using ruy as the gemm backend instead of gemmlowp.
-  build_tflite_with_ruy = true
+  build_tflite_with_xnnpack = is_linux && target_cpu == "x64"
 }
diff --git a/third_party/wpt_tools/README.chromium b/third_party/wpt_tools/README.chromium
index 9c931b7..e8f44a42 100644
--- a/third_party/wpt_tools/README.chromium
+++ b/third_party/wpt_tools/README.chromium
@@ -1,7 +1,7 @@
 Name: web-platform-tests - Test Suites for Web Platform specifications
 Short Name: wpt
 URL: https://github.com/web-platform-tests/wpt/
-Version: 2385ce5e8bca0be2251dded899877e3265fe0c44
+Version: 622b9a0c1e58e302816947cac22d34eccf3624d1
 License: LICENSES FOR W3C TEST SUITES (https://www.w3.org/Consortium/Legal/2008/03-bsd-license.html)
 License File: NOT_SHIPPED
 Security Critical: no
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_firefox.txt b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_firefox.txt
index 76936b1..e385f471 100644
--- a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_firefox.txt
+++ b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_firefox.txt
@@ -7,4 +7,4 @@
 mozprofile==2.5.0
 mozrunner==8.2.1
 mozversion==2.3.0
-psutil==5.9.0
+psutil==5.9.1
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_safari.txt b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_safari.txt
index f371e20..8d303aa 100644
--- a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_safari.txt
+++ b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_safari.txt
@@ -1 +1 @@
-psutil==5.9.0
+psutil==5.9.1
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 30ece6d7..fc5dbc6d 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -374,7 +374,6 @@
       'fuchsia-fyi-x64-rel': 'release_bot_fuchsia',
       'fuchsia-fyi-x64-reviver': 'release_bot_fuchsia',
       'fuchsia-fyi-x64-wst': 'fuchsia_workstation_bot',
-      'ios-asan': 'ios_simulator_release_static_asan_bot_xctest',
       'ios-fieldtrial-rel': 'ios_simulator_debug_static_bot_xctest_arm64',
       'ios-m1-simulator': 'ios_simulator_debug_static_bot_xctest_arm64',
       'ios-m1-simulator-cronet': 'ios_cronet_xctest_arm64',
@@ -605,6 +604,7 @@
       'WebKit Linux Leak': 'release_bot_blink_reclient',
       'WebKit Linux MSAN': 'msan_release_bot_blink_reclient',
       'android-asan': 'android_clang_asan_release_bot_reclient',
+      'ios-asan': 'ios_simulator_release_static_asan_bot_xctest',
       'linux-ubsan-vptr': 'ubsan_vptr_release_bot_reclient',
       'win-asan': 'asan_clang_fuzzer_static_v8_heap_minimal_symbols_release_reclient',
     },
diff --git a/tools/mb/mb_config_expectations/chromium.fyi.json b/tools/mb/mb_config_expectations/chromium.fyi.json
index b136204..634c33ccb 100644
--- a/tools/mb/mb_config_expectations/chromium.fyi.json
+++ b/tools/mb/mb_config_expectations/chromium.fyi.json
@@ -686,20 +686,6 @@
       "use_goma": true
     }
   },
-  "ios-asan": {
-    "gn_args": {
-      "dcheck_always_on": false,
-      "enable_run_ios_unittests_with_xctest": true,
-      "ios_set_attributes_for_xcode_project_generation": false,
-      "is_asan": true,
-      "is_component_build": false,
-      "is_debug": false,
-      "target_cpu": "x64",
-      "target_environment": "simulator",
-      "target_os": "ios",
-      "use_goma": true
-    }
-  },
   "ios-fieldtrial-rel": {
     "gn_args": {
       "enable_run_ios_unittests_with_xctest": true,
diff --git a/tools/mb/mb_config_expectations/chromium.memory.json b/tools/mb/mb_config_expectations/chromium.memory.json
index 7d2a81a1..e304000 100644
--- a/tools/mb/mb_config_expectations/chromium.memory.json
+++ b/tools/mb/mb_config_expectations/chromium.memory.json
@@ -136,6 +136,20 @@
       "use_remoteexec": true
     }
   },
+  "ios-asan": {
+    "gn_args": {
+      "dcheck_always_on": false,
+      "enable_run_ios_unittests_with_xctest": true,
+      "ios_set_attributes_for_xcode_project_generation": false,
+      "is_asan": true,
+      "is_component_build": false,
+      "is_debug": false,
+      "target_cpu": "x64",
+      "target_environment": "simulator",
+      "target_os": "ios",
+      "use_goma": true
+    }
+  },
   "linux-ubsan-vptr": {
     "gn_args": {
       "dcheck_always_on": false,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 7e6dc49a..4741c27b 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -55870,6 +55870,7 @@
   <int value="-1308389775" label="PermissionChipGestureSensitive:enabled"/>
   <int value="-1308184869" label="MediaFeedsBackgroundFetching:enabled"/>
   <int value="-1306581260" label="AutofillParsingPatternProvider:enabled"/>
+  <int value="-1305690805" label="PrecompileInlineScripts:enabled"/>
   <int value="-1304957199" label="OfflinePagesShowAlternateDinoPage:enabled"/>
   <int value="-1304758527" label="SyncSendTabToSelf:disabled"/>
   <int value="-1304401930" label="CSSContainerQueries:enabled"/>
@@ -58409,6 +58410,7 @@
   <int value="375785554" label="UserActivationV2:disabled"/>
   <int value="375934458" label="PortalsCrossOrigin:enabled"/>
   <int value="377093001" label="WebRtcHWH264Encoding:disabled"/>
+  <int value="378093891" label="PrecompileInlineScripts:disabled"/>
   <int value="378948081"
       label="AutofillEnableInfoBarAccountIndicationFooter:disabled"/>
   <int value="378994579" label="Previews:enabled"/>
diff --git a/tools/metrics/histograms/print_expanded_histograms.py b/tools/metrics/histograms/print_expanded_histograms.py
index 3afb8a2..8fc6faf 100755
--- a/tools/metrics/histograms/print_expanded_histograms.py
+++ b/tools/metrics/histograms/print_expanded_histograms.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright 2020 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 0b3281a..50365b1 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,24 +5,24 @@
             "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "win": {
-            "hash": "7318b13e41d1be2d8329f70f152b28444c8b37e5",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/26f1ca3b42a13a5dc179334f972ad8847aded023/trace_processor_shell.exe"
+            "hash": "b63f94357b0f34298abd3a9b83112bde117301d9",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/6214d0c954d720a3c87cf7673903d679d2ae7413/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893",
             "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "mac": {
-            "hash": "143c4ce23f9389069250ea96f424eb19989cf325",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/26f1ca3b42a13a5dc179334f972ad8847aded023/trace_processor_shell"
+            "hash": "264c11ffef682d8a1f737bec52098694092919a4",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/6214d0c954d720a3c87cf7673903d679d2ae7413/trace_processor_shell"
         },
         "mac_arm64": {
             "hash": "e1ad4861384b06d911a65f035317914b8cc975c6",
             "full_remote_path": "perfetto-luci-artifacts/v25.0/mac-arm64/trace_processor_shell"
         },
         "linux": {
-            "hash": "6af362a53a155fdc10bfd52b59057fcfc75a5428",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/26f1ca3b42a13a5dc179334f972ad8847aded023/trace_processor_shell"
+            "hash": "2706843ca63f4105b3660df895afbafde6ca4ec7",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/6214d0c954d720a3c87cf7673903d679d2ae7413/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/polymer/html_to_wrapper.gni b/tools/polymer/html_to_wrapper.gni
index 6727993..6a902fe 100644
--- a/tools/polymer/html_to_wrapper.gni
+++ b/tools/polymer/html_to_wrapper.gni
@@ -29,5 +29,12 @@
              rebase_path(target_gen_dir, root_build_dir),
              "--in_files",
            ] + invoker.in_files
+
+    if (defined(invoker.template)) {
+      args += [
+        "--template",
+        invoker.template,
+      ]
+    }
   }
 }
diff --git a/tools/polymer/html_to_wrapper.py b/tools/polymer/html_to_wrapper.py
index 55e7e05..0b4559c 100644
--- a/tools/polymer/html_to_wrapper.py
+++ b/tools/polymer/html_to_wrapper.py
@@ -25,6 +25,13 @@
 
 _CWD = getcwd()
 
+# Template for non-Polymer elements.
+_NON_POLYMER_ELEMENT_TEMPLATE = """import {getTrustedHTML} from \'chrome://resources/js/static_types.js\';
+export function getTemplate() {
+  return getTrustedHTML`<!--_html_template_start_-->%s<!--_html_template_end_-->`;
+}"""
+
+# Template for Polymer elements.
 _ELEMENT_TEMPLATE = """import {html} from \'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js\';
 export function getTemplate() {
   return html`<!--_html_template_start_-->%s<!--_html_template_end_-->`;
@@ -43,6 +50,10 @@
   parser.add_argument('--in_folder', required=True)
   parser.add_argument('--out_folder', required=True)
   parser.add_argument('--in_files', required=True, nargs="*")
+  parser.add_argument('--template',
+                      choices=['polymer', 'native'],
+                      default='polymer')
+
   args = parser.parse_args(argv)
 
   in_folder = path.normpath(path.join(_CWD, args.in_folder))
@@ -57,7 +68,8 @@
       html_content = f.read()
 
       wrapper = None
-      template = _ELEMENT_TEMPLATE
+      template = _ELEMENT_TEMPLATE \
+          if args.template == 'polymer' else _NON_POLYMER_ELEMENT_TEMPLATE
 
       filename = path.basename(in_file)
       if filename == 'icons.html' or filename.endswith('_icons.html'):
diff --git a/tools/polymer/html_to_wrapper_test.py b/tools/polymer/html_to_wrapper_test.py
index 2f30b0f..d461a6b 100755
--- a/tools/polymer/html_to_wrapper_test.py
+++ b/tools/polymer/html_to_wrapper_test.py
@@ -25,14 +25,23 @@
     with open(os.path.join(self._out_folder, file_name), 'rb') as f:
       return f.read()
 
-  def _run_test(self, html_file, wrapper_file, wrapper_file_expected):
+  def _run_test(self,
+                html_file,
+                wrapper_file,
+                wrapper_file_expected,
+                template=None):
     assert not self._out_folder
     self._out_folder = tempfile.mkdtemp(dir=_HERE_DIR)
-    html_to_wrapper.main([
+    args = [
         '--in_folder',
         os.path.join(_HERE_DIR, 'tests'), '--out_folder', self._out_folder,
         '--in_files', html_file
-    ])
+    ]
+
+    if template:
+      args += ['--template', template]
+
+    html_to_wrapper.main(args)
 
     actual_wrapper = self._read_out_file(wrapper_file)
     with open(os.path.join(_HERE_DIR, 'tests', wrapper_file_expected),
@@ -40,10 +49,15 @@
       expected_wrapper = f.read()
     self.assertMultiLineEqual(str(expected_wrapper), str(actual_wrapper))
 
-  def testHtmlToWrapperElement(self):
+  def testHtmlToWrapperPolymerElement(self):
     self._run_test('html_to_wrapper/foo.html', 'html_to_wrapper/foo.html.ts',
                    'html_to_wrapper/foo_expected.html.ts')
 
+  def testHtmlToWrapperNativeElement(self):
+    self._run_test('html_to_wrapper/foo_native.html',
+                   'html_to_wrapper/foo_native.html.ts',
+                   'html_to_wrapper/foo_native_expected.html.ts', 'native')
+
   def testHtmlToWrapperIcons(self):
     self._run_test('html_to_wrapper/icons.html',
                    'html_to_wrapper/icons.html.ts',
diff --git a/tools/polymer/tests/html_to_wrapper/foo_native.html b/tools/polymer/tests/html_to_wrapper/foo_native.html
new file mode 100644
index 0000000..1521f59
--- /dev/null
+++ b/tools/polymer/tests/html_to_wrapper/foo_native.html
@@ -0,0 +1,6 @@
+<style>
+  div {
+    font-size: 2rem;
+  }
+</style>
+<div>Hello world</div>
diff --git a/tools/polymer/tests/html_to_wrapper/foo_native_expected.html.ts b/tools/polymer/tests/html_to_wrapper/foo_native_expected.html.ts
new file mode 100644
index 0000000..d7f4c9f
--- /dev/null
+++ b/tools/polymer/tests/html_to_wrapper/foo_native_expected.html.ts
@@ -0,0 +1,10 @@
+import {getTrustedHTML} from 'chrome://resources/js/static_types.js';
+export function getTemplate() {
+  return getTrustedHTML`<!--_html_template_start_--><style>
+  div {
+    font-size: 2rem;
+  }
+</style>
+<div>Hello world</div>
+<!--_html_template_end_-->`;
+}
\ No newline at end of file
diff --git a/ui/webui/resources/BUILD.gn b/ui/webui/resources/BUILD.gn
index 7468e5a..fecb06a7 100644
--- a/ui/webui/resources/BUILD.gn
+++ b/ui/webui/resources/BUILD.gn
@@ -307,6 +307,9 @@
 
   in_files = [
     "cr_elements/cr_tab_box/cr_tab_box.ts",
+    "cr_elements/cr_tree/cr_tree.ts",
+    "cr_elements/cr_tree/cr_tree_base.ts",
+    "cr_elements/cr_tree/cr_tree_item.ts",
     "js/assert_ts.ts",
     "js/custom_element.ts",
   ]
diff --git a/ui/webui/resources/cr_components/history_clusters/clusters.ts b/ui/webui/resources/cr_components/history_clusters/clusters.ts
index 9bfb42d..3504abe 100644
--- a/ui/webui/resources/cr_components/history_clusters/clusters.ts
+++ b/ui/webui/resources/cr_components/history_clusters/clusters.ts
@@ -44,7 +44,7 @@
   }
 }
 
-interface HistoryClustersElement {
+export interface HistoryClustersElement {
   $: {
     clusters: IronListElement,
     confirmationDialog: CrLazyRenderElement<CrDialogElement>,
@@ -53,7 +53,7 @@
   };
 }
 
-class HistoryClustersElement extends PolymerElement {
+export class HistoryClustersElement extends PolymerElement {
   static get is() {
     return 'history-clusters';
   }
diff --git a/ui/webui/resources/cr_elements/BUILD.gn b/ui/webui/resources/cr_elements/BUILD.gn
index 4de81aa..1c7bc71b 100644
--- a/ui/webui/resources/cr_elements/BUILD.gn
+++ b/ui/webui/resources/cr_elements/BUILD.gn
@@ -42,13 +42,13 @@
 }
 
 group("preprocess") {
-  public_deps = [ ":preprocess_generated_ts" ]
+  public_deps = [
+    ":preprocess_generated_ts",
+    ":preprocess_src_ts",
+  ]
 
   if (include_polymer) {
-    public_deps += [
-      ":preprocess_generated",
-      ":preprocess_src_ts",
-    ]
+    public_deps += [ ":preprocess_generated" ]
   }
 
   if (is_chromeos_ash) {
@@ -76,11 +76,12 @@
 
 # TS files are passed to a separate target so that they are not listed in the
 # |out_manifest|.
-if (include_polymer) {
-  preprocess_if_expr("preprocess_src_ts") {
-    in_folder = "."
-    out_folder = preprocess_folder
-    in_files = [
+preprocess_if_expr("preprocess_src_ts") {
+  in_folder = "."
+  out_folder = preprocess_folder
+  in_files = [ "cr_tree/cr_tree_base.ts" ]
+  if (include_polymer) {
+    in_files += [
       "cr_a11y_announcer/cr_a11y_announcer.ts",
       "cr_action_menu/cr_action_menu.ts",
       "cr_auto_img/cr_auto_img.ts",
@@ -233,7 +234,11 @@
   deps = [ ":custom_elements" ]
   in_folder = target_gen_dir
   out_folder = preprocess_folder
-  in_files = [ "cr_tab_box/cr_tab_box.ts" ]
+  in_files = [
+    "cr_tab_box/cr_tab_box.ts",
+    "cr_tree/cr_tree.ts",
+    "cr_tree/cr_tree_item.ts",
+  ]
   if (include_polymer) {
     deps += [
       ":css_wrapper_files",
@@ -398,7 +403,6 @@
       ":modulize",
       ":shared_style_css_module",
       ":shared_vars_css_module",
-      ":web_components",
       "cr_button:cr_button_module",
       "cr_checkbox:cr_checkbox_module",
       "cr_dialog:cr_dialog_module",
@@ -502,5 +506,9 @@
 }
 
 html_to_js("web_components") {
-  js_files = [ "cr_tab_box/cr_tab_box.ts" ]
+  js_files = [
+    "cr_tab_box/cr_tab_box.ts",
+    "cr_tree/cr_tree.ts",
+    "cr_tree/cr_tree_item.ts",
+  ]
 }
diff --git a/ui/webui/resources/cr_elements/cr_tab_box/cr_tab_box.html b/ui/webui/resources/cr_elements/cr_tab_box/cr_tab_box.html
index c587467..dd17fbe 100644
--- a/ui/webui/resources/cr_elements/cr_tab_box/cr_tab_box.html
+++ b/ui/webui/resources/cr_elements/cr_tab_box/cr_tab_box.html
@@ -62,6 +62,7 @@
     box-shadow: none;
     display: flex;
     flex: 1;
+    overflow: hidden;
     padding: 0 20px;
   }
 
diff --git a/ui/webui/resources/cr_elements/cr_tree/cr_tree.html b/ui/webui/resources/cr_elements/cr_tree/cr_tree.html
new file mode 100644
index 0000000..f9351f5
--- /dev/null
+++ b/ui/webui/resources/cr_elements/cr_tree/cr_tree.html
@@ -0,0 +1,7 @@
+<style>
+  :host {
+    display: block;
+    outline: none;
+    overflow: auto;
+  }
+</style>
diff --git a/ui/webui/resources/cr_elements/cr_tree/cr_tree.ts b/ui/webui/resources/cr_elements/cr_tree/cr_tree.ts
new file mode 100644
index 0000000..6c530f6
--- /dev/null
+++ b/ui/webui/resources/cr_elements/cr_tree/cr_tree.ts
@@ -0,0 +1,235 @@
+// 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.
+
+import {assert, assertNotReached} from '../../js/assert_ts.js';
+import {isMac} from '../../js/cr.m.js';
+import {getTrustedHTML} from '../../js/static_types.js';
+
+import {CrTreeBaseElement} from './cr_tree_base.js';
+import {SELECTED_ATTR} from './cr_tree_item.js';
+
+/**
+ * @fileoverview cr-tree is a container for a tree structure. Items can be added
+ * or removed from the tree using the add/addAt/removeItem methods. Adding items
+ * declaratively is not currently supported, as this class is primarily intended
+ * to replace cr.ui.Tree, which is used for cases of creating trees at runtime
+ * (e.g. from backend data).
+ */
+
+/**
+ * Helper function that returns the next visible tree item.
+ */
+function getNext(item: CrTreeBaseElement): CrTreeBaseElement|null {
+  if (item.expanded) {
+    const firstChild = item.items[0];
+    if (firstChild) {
+      return firstChild;
+    }
+  }
+
+  return getNextHelper(item);
+}
+
+/**
+ * Another helper function that returns the next visible tree item.
+ */
+function getNextHelper(item: CrTreeBaseElement|null): CrTreeBaseElement|null {
+  if (!item) {
+    return null;
+  }
+
+  const nextSibling = item.nextElementSibling;
+  if (nextSibling) {
+    assert(nextSibling.tagName === 'CR-TREE-ITEM');
+    return nextSibling as CrTreeBaseElement;
+  }
+  const parent = item.parentItem;
+  if (!parent || parent.tagName === 'CR-TREE') {
+    return null;
+  }
+  return getNextHelper(item.parentItem);
+}
+
+/**
+ * Helper function that returns the previous visible tree item.
+ */
+function getPrevious(item: CrTreeBaseElement): CrTreeBaseElement|null {
+  const previousSibling = item.previousElementSibling;
+  if (previousSibling && previousSibling.tagName === 'CR-TREE-ITEM') {
+    return getLastHelper(previousSibling as CrTreeBaseElement);
+  }
+  return item.parentItem;
+}
+
+/**
+ * Helper function that returns the last visible tree item in the subtree.
+ */
+function getLastHelper(item: CrTreeBaseElement): CrTreeBaseElement|null {
+  if (item.expanded && item.hasChildren) {
+    const lastChild = item.items[item.items.length - 1]!;
+    return getLastHelper(lastChild);
+  }
+  return item;
+}
+
+export class CrTreeElement extends CrTreeBaseElement {
+  static override get template() {
+    return getTrustedHTML`{__html_template__}`;
+  }
+
+  private selectedItem_: CrTreeBaseElement|null = null;
+
+  /**
+   * Initializes the element.
+   */
+  connectedCallback() {
+    // Make list focusable
+    if (!this.hasAttribute('tabindex')) {
+      this.tabIndex = 0;
+    }
+
+    if (!this.hasAttribute('role')) {
+      this.setAttribute('role', 'tree');
+    }
+
+    this.addEventListener('keydown', this.handleKeyDown.bind(this));
+    this.addEventListener('focus', this.onFocus.bind(this));
+    this.addEventListener('blur', this.onBlur.bind(this));
+  }
+
+  // CrTreeBase implementation:
+  /**
+   * The depth of the node. This is 0 for the tree itself.
+   */
+  override get depth(): number {
+    return 0;
+  }
+
+  override get itemsRoot(): DocumentFragment|HTMLElement {
+    return this.shadowRoot!;
+  }
+
+  // These two methods should never be called for the tree itself.
+  override set depth(_depth: number) {
+    assertNotReached();
+  }
+
+  override setParent(_parent: CrTreeBaseElement) {
+    assertNotReached();
+  }
+
+  /**
+   * The selected tree item or null if none.
+   */
+  override get selectedItem(): CrTreeBaseElement|null {
+    return this.selectedItem_ || null;
+  }
+
+  override set selectedItem(item: CrTreeBaseElement|null) {
+    const oldSelectedItem = this.selectedItem_;
+    if (oldSelectedItem !== item) {
+      // Set the selectedItem_ before deselecting the old item since we only
+      // want one change when moving between items.
+      this.selectedItem_ = item;
+
+      if (oldSelectedItem) {
+        oldSelectedItem.toggleAttribute(SELECTED_ATTR, false);
+      }
+
+      if (item) {
+        item.toggleAttribute(SELECTED_ATTR, true);
+        if (item.id) {
+          this.setAttribute('aria-activedescendant', item.id);
+        }
+      } else {
+        this.removeAttribute('aria-activedescendant');
+      }
+
+      this.dispatchEvent(
+          new CustomEvent('cr-tree-change', {bubbles: true, composed: true}));
+    }
+  }
+
+  // Event handlers:
+  // TODO(rbpotter): Figure out if there is a better way to handle tree:focus
+  // and tree[icon-visibility] styles from tree.css.
+  onFocus() {
+    this.setAttribute('tree-focused', 'true');
+  }
+
+  onBlur() {
+    this.setAttribute('tree-focused', 'false');
+  }
+
+  /**
+   * Handles keydown events on the tree and updates selection and exanding
+   * of tree items.
+   */
+  handleKeyDown(e: KeyboardEvent) {
+    let itemToSelect: CrTreeBaseElement|null = null;
+    if (e.ctrlKey) {
+      return;
+    }
+
+    const item = this.selectedItem;
+    if (!item) {
+      return;
+    }
+
+    const rtl = getComputedStyle(item).direction === 'rtl';
+
+    switch (e.key) {
+      case 'ArrowUp':
+        itemToSelect = getPrevious(item);
+        break;
+      case 'ArrowDown':
+        itemToSelect = getNext(item);
+        break;
+      case 'ArrowLeft':
+      case 'ArrowRight':
+        // Don't let back/forward keyboard shortcuts be used.
+        if (!isMac && e.altKey || isMac && e.metaKey) {
+          break;
+        }
+
+        if (e.key === 'ArrowLeft' && !rtl || e.key === 'ArrowRight' && rtl) {
+          if (item.expanded) {
+            item.expanded = false;
+          } else {
+            itemToSelect = item.parentItem;
+          }
+        } else {
+          if (!item.expanded) {
+            item.expanded = true;
+          } else {
+            itemToSelect = item.items[0] || null;
+          }
+        }
+        break;
+      case 'Home':
+        itemToSelect = this.items[0] || null;
+        break;
+      case 'End':
+        itemToSelect = this.items[this.items.length - 1] || null;
+        break;
+    }
+
+    if (itemToSelect) {
+      itemToSelect.toggleAttribute(SELECTED_ATTR, true);
+      e.preventDefault();
+    }
+  }
+
+  setIconVisibility(visibility: string) {
+    this.setAttribute('icon-visibility', visibility);
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'cr-tree': CrTreeElement;
+  }
+}
+
+customElements.define('cr-tree', CrTreeElement);
diff --git a/ui/webui/resources/cr_elements/cr_tree/cr_tree_base.ts b/ui/webui/resources/cr_elements/cr_tree/cr_tree_base.ts
new file mode 100644
index 0000000..4edce25
--- /dev/null
+++ b/ui/webui/resources/cr_elements/cr_tree/cr_tree_base.ts
@@ -0,0 +1,114 @@
+// 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.
+
+import {assert} from '../../js/assert_ts.js';
+import {CustomElement} from '../../js/custom_element.js';
+
+export const EXPANDED_ATTR: string = 'expanded';
+
+// Encapuslates shared behavior of cr-trees and the cr-tree-items that they
+// contain. This reduces code duplication for e.g. adding/removing children and
+// facilitates writing methods navigating the full tree structure (cr-tree and
+// all cr-tree-item descendants), without introducing circular dependencies.
+export abstract class CrTreeBaseElement extends CustomElement {
+  static override get template() {
+    return window.trustedTypes ? window.trustedTypes.emptyHTML : ('' as string);
+  }
+
+  static get observedAttributes() {
+    return ['icon-visibility', 'tree-focused'];
+  }
+
+  detail: object = {};
+  private parent_: CrTreeBaseElement|null = null;
+
+  attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
+    assert(name === 'icon-visibility' || name === 'tree-focused');
+    this.items.forEach(item => item.setAttribute(name, newValue));
+  }
+
+  setParent(parent: CrTreeBaseElement) {
+    this.parent_ = parent;
+  }
+
+  get items(): CrTreeBaseElement[] {
+    return Array.from(this.itemsRoot.querySelectorAll('cr-tree-item')) as
+        CrTreeBaseElement[];
+  }
+
+  abstract get depth(): number;
+  abstract set depth(depth: number);
+  abstract get itemsRoot(): DocumentFragment|HTMLElement;
+  abstract get selectedItem(): CrTreeBaseElement|null;
+  abstract set selectedItem(item: CrTreeBaseElement|null);
+
+  /**
+   * Adds a tree item as a child.
+   */
+  add(child: CrTreeBaseElement) {
+    this.addAt(child, -1);
+  }
+
+  /**
+   * Adds a tree item as a child at a given index.
+   */
+  addAt(child: CrTreeBaseElement, index: number) {
+    assert(child.tagName === 'CR-TREE-ITEM');
+    child.setParent(this);
+
+    if (index === -1 || index >= this.items.length) {
+      this.itemsRoot.appendChild(child);
+    } else {
+      this.itemsRoot.insertBefore(child, this.items[index] || null);
+    }
+    if (this.items.length === 1) {
+      this.setHasChildren(true);
+    }
+    child.depth = this.depth + 1;
+    child.setAttribute(
+        'icon-visibility', this.getAttribute('icon-visibility') || '');
+  }
+
+  removeTreeItem(child: CrTreeBaseElement) {
+    this.itemsRoot.removeChild(child);
+    if (this.items.length === 0) {
+      this.setHasChildren(false);
+    }
+  }
+
+  get parentItem(): CrTreeBaseElement|null {
+    return this.parent_;
+  }
+
+  /**
+   * The tree that the tree item belongs to or null of no added to a tree.
+   */
+  get tree(): CrTreeBaseElement|null {
+    if (this.tagName === 'CR-TREE') {
+      return this;
+    }
+
+    if (!this.parent_) {
+      return null;
+    }
+
+    return this.parent_.tree;
+  }
+
+  get hasChildren(): boolean {
+    return !!this.items[0];
+  }
+
+  setHasChildren(b: boolean) {
+    this.toggleAttribute('has-children', b);
+  }
+
+  get expanded() {
+    return this.hasAttribute(EXPANDED_ATTR);
+  }
+
+  set expanded(expanded: boolean) {
+    this.toggleAttribute(EXPANDED_ATTR, expanded);
+  }
+}
diff --git a/ui/webui/resources/cr_elements/cr_tree/cr_tree_item.html b/ui/webui/resources/cr_elements/cr_tree/cr_tree_item.html
new file mode 100644
index 0000000..d118773
--- /dev/null
+++ b/ui/webui/resources/cr_elements/cr_tree/cr_tree_item.html
@@ -0,0 +1,158 @@
+<style>
+  :host {
+    --white-100: rgba(255, 255, 255, 0);
+    --white-80: rgba(255, 255, 255, .8);
+  }
+
+  :host .tree-row {
+    align-items: center;
+    background-color: var(--white-100);
+    /* transparent white */
+    border: var(--cr-tree-row-border, 1px solid var(--white-100));
+    border-radius: var(--cr-tree-row-border-radius, 2px);
+    color: black;
+    cursor: default;
+    display: flex;
+    line-height: var(--cr-tree-row-line-height, 28px);
+    padding: 0 3px;
+    position: relative;
+    user-select: none;
+    white-space: nowrap;
+  }
+
+  .expand-icon {
+    background: url(chrome://resources/images/tree_triangle.svg) no-repeat center center;
+    background-size: 8px 5.5px;
+    height: 16px;
+    min-width: 16px;
+    opacity: .6;
+    transform: rotate(-90deg);
+    transition: all 150ms;
+    width: 16px;
+  }
+
+  :host-context([dir=rtl]) .expand-icon {
+    transform: rotate(90deg);
+  }
+
+  :host([expanded]) .expand-icon {
+    background-image: url(chrome://resources/images/tree_triangle.svg);
+    opacity: .5;
+    transform: rotate(0);
+  }
+
+  .tree-row .expand-icon {
+    visibility: hidden;
+  }
+
+  :host([may-have-children]) .tree-row .expand-icon {
+    visibility: visible;
+  }
+
+  :host(:not([has-children])) .tree-row .expand-icon {
+    visibility: hidden;
+  }
+
+  .tree-row:hover {
+    background-color: hsl(214, 91%, 97%);
+    border-color: hsl(214, 91%, 85%);
+    z-index: 1;
+  }
+
+  :host([selected]) .tree-row {
+    background-color: var(--cr-tree-row-selected-color, hsl(0, 0%, 90%));
+    background-image: var(--cr-tree-row-selected-image,
+                          linear-gradient(var(--white-80), var(--white-100)));
+    border-color: hsl(0, 0%, 85%);
+    z-index: 2;
+  }
+
+  :host([selected]) .tree-row:hover,
+  :host([selected][tree-focused=true]) .tree-row {
+    background-color: hsl(214, 91%, 89%);
+    border-color: rgb(125, 162, 206);
+  }
+
+  :host([expanded]) .tree-children {
+    display: block;
+  }
+
+  .tree-children {
+    display: none;
+  }
+
+  :host .tree-row > * {
+    box-sizing: border-box;
+    display: inline-block;
+  }
+
+  .tree-label-icon {
+    background-position: 0 50%;
+    background-repeat: no-repeat;
+    height: 20px;
+    min-width: 20px;
+    width: 20px;
+  }
+
+  .tree-label {
+    white-space: pre;
+  }
+
+  .tree-label-icon,
+  :host([may-have-children]) .tree-row > .tree-label-icon {
+    background-image: url(chrome://theme/IDR_FOLDER_CLOSED);
+  }
+
+  <if expr="is_macosx or is_ios">
+  @media (prefers-color-scheme: dark) {
+    .tree-label-icon,
+    :host([may-have-children]) .tree-row > .tree-label-icon {
+      background-image: url(chrome://theme/IDR_FOLDER_CLOSED_WHITE);
+    }
+  }
+  </if>
+
+  <if expr="not is_macosx and not is_ios">
+  :host([expanded]) > .tree-row > .tree-label-icon {
+    background-image: url(chrome://theme/IDR_FOLDER_OPEN);
+  }
+  </if>
+
+  :host-context([dir=rtl]) .tree-label-icon,
+  :host-context([dir=rtl]) :host([may-have-children]) .tree-row > .tree-label-icon,
+  :host-context([dir=rtl]) :host([expanded]) > .tree-row > .tree-label-icon {
+    transform: scaleX(-1);
+  }
+
+  :host([icon-visibility=hidden]) .tree-label-icon {
+    display: none;
+  }
+
+  :host([icon-visibility=parent]) .tree-label-icon,
+  :host([icon-visibility=parent]) .tree-row:not([has-children]) > .tree-label-icon {
+    background-image: none;
+  }
+
+  /* We need to ensure that even empty labels take up space */
+  .tree-label:empty::after {
+    content: ' ';
+    white-space: pre;
+  }
+
+  @media(forced-colors) {
+    :host([selected]) .tree-row,
+    .tree-row:hover,
+    :host([selected]) .tree-row:hover {
+      background-color: Highlight;
+      background-image: none;
+      color: HighlightText;
+      forced-color-adjust: none;
+    }
+  }
+</style>
+<div class="tree-row" part="row">
+  <span class="expand-icon"></span>
+  <span class="tree-label-icon"></span>
+  <span class="tree-label"></span>
+</div>
+<div class="tree-children" role="group"></div>
diff --git a/ui/webui/resources/cr_elements/cr_tree/cr_tree_item.ts b/ui/webui/resources/cr_elements/cr_tree/cr_tree_item.ts
new file mode 100644
index 0000000..5f3e8f8a
--- /dev/null
+++ b/ui/webui/resources/cr_elements/cr_tree/cr_tree_item.ts
@@ -0,0 +1,241 @@
+// 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.
+
+import {assert, assertNotReached} from '../../js/assert_ts.js';
+import {getTrustedHTML} from '../../js/static_types.js';
+
+import {CrTreeBaseElement, EXPANDED_ATTR} from './cr_tree_base.js';
+
+/**
+ * @fileoverview cr-tree-item represents a node in a tree structure. Child items
+ * can be added or removed using the add/addAt/removeItem methods. A parent can
+ * be set using the setParent() method; the parent may be a cr-tree or
+ * cr-tree-item. Adding items declaratively is not currently supported, as this
+ * class is primarily intended to replace cr.ui.TreeItem, which is used for
+ * cases of creating trees at runtime (e.g. from backend data).
+ */
+
+export const SELECTED_ATTR: string = 'selected';
+const MAY_HAVE_CHILDREN_ATTR: string = 'may-have-children';
+const INDENT_PX: number = 20;
+let treeItemAutoGeneratedIdCounter: number = 0;
+
+// Returns true if |root| has |el| as a descendant.
+function hasDescendant(
+    root: CrTreeBaseElement, el: CrTreeBaseElement): boolean {
+  const itemsToCheck = [root];
+  while (itemsToCheck.length > 0) {
+    const item = itemsToCheck.shift()!;
+    if (item === el) {
+      return true;
+    }
+    if (item.items.includes(el)) {
+      return true;
+    }
+    itemsToCheck.push(...item.items);
+  }
+  return false;
+}
+
+export class CrTreeItemElement extends CrTreeBaseElement {
+  static override get template() {
+    return getTrustedHTML`{__html_template__}`;
+  }
+
+  static override get observedAttributes() {
+    return super.observedAttributes.concat([SELECTED_ATTR, EXPANDED_ATTR]);
+  }
+
+  private label_: string = '';
+  private depth_: number = 0;
+
+  connectedCallback() {
+    const labelId =
+        'tree-item-label-autogen-id-' + treeItemAutoGeneratedIdCounter++;
+    this.labelElement.id = labelId;
+    this.setAttribute('aria-labelledby', labelId);
+    this.labelElement.textContent = this.label_;
+    this.toggleAttribute(SELECTED_ATTR, false);
+    this.addEventListener('click', this.handleClick.bind(this));
+    this.addEventListener('mousedown', this.handleMouseDown.bind(this));
+    this.addEventListener('dblclick', this.handleDblClick.bind(this));
+  }
+
+  override attributeChangedCallback(
+      name: string, oldValue: string, newValue: string) {
+    if (name === SELECTED_ATTR) {
+      this.onSelectedChange_(newValue === '');
+      return;
+    }
+    if (name === EXPANDED_ATTR) {
+      this.onExpandedChange_(newValue === '');
+      return;
+    }
+    super.attributeChangedCallback(name, oldValue, newValue);
+  }
+
+  private onSelectedChange_(selected: boolean) {
+    if (selected) {
+      this.reveal();
+      this.labelElement.scrollIntoViewIfNeeded();
+      if (this.tree) {
+        this.tree.selectedItem = this;
+      }
+    } else if (this.tree && this.tree.selectedItem === this) {
+      this.tree.selectedItem = null;
+    }
+  }
+
+  private onExpandedChange_(expanded: boolean) {
+    if (expanded) {
+      if (this.hasAttribute(MAY_HAVE_CHILDREN_ATTR)) {
+        this.setAttribute('aria-expanded', 'true');
+        this.dispatchEvent(new CustomEvent(
+            'cr-tree-item-expand',
+            {bubbles: true, composed: true, detail: true}));
+        this.scrollIntoViewIfNeeded();
+      }
+      return;
+    }
+    if (this.tree && !this.hasAttribute(SELECTED_ATTR)) {
+      const oldSelected = this.tree.selectedItem;
+      if (oldSelected && hasDescendant(this, oldSelected)) {
+        this.toggleAttribute(SELECTED_ATTR, true);
+      }
+    }
+    if (this.hasAttribute(MAY_HAVE_CHILDREN_ATTR)) {
+      this.setAttribute('aria-expanded', 'false');
+    } else {
+      this.removeAttribute('aria-expanded');
+    }
+    this.dispatchEvent(new CustomEvent(
+        'cr-tree-item-collapse',
+        {bubbles: true, composed: true, detail: true}));
+  }
+
+  // CrTreeBaseElement implementation:
+  override get depth(): number {
+    return this.depth_;
+  }
+
+  override set depth(depth: number) {
+    if (depth !== this.depth_) {
+      const rowDepth = Math.max(0, depth - 1);
+      const row = this.shadowRoot!.querySelector<HTMLElement>('.tree-row');
+      assert(row);
+      row.style.paddingInlineStart = rowDepth * INDENT_PX + 'px';
+      this.depth_ = depth;
+      this.items.forEach(item => item.depth = depth + 1);
+    }
+  }
+
+  override get itemsRoot(): DocumentFragment|HTMLElement {
+    const root = this.shadowRoot!.querySelector<HTMLElement>('.tree-children');
+    assert(root);
+    return root;
+  }
+
+  override removeTreeItem(child: CrTreeItemElement) {
+    // If we removed the selected item we should become selected.
+    const tree = this.tree;
+    assert(tree);
+    const selectedItem = tree.selectedItem;
+    if (selectedItem && hasDescendant(child, selectedItem)) {
+      this.toggleAttribute(SELECTED_ATTR, true);
+    }
+
+    super.removeTreeItem(child);
+  }
+
+  /**
+   * Whether the tree item has children.
+   */
+  override setHasChildren(hasChildren: boolean) {
+    super.setHasChildren(hasChildren);
+    if (hasChildren) {
+      this.toggleAttribute(MAY_HAVE_CHILDREN_ATTR, true);
+      this.toggleAttribute('aria-expanded', this.expanded);
+    }
+  }
+
+  // These methods shouldn't be called on a tree item.
+  override set selectedItem(_item: CrTreeBaseElement|null) {
+    assertNotReached();
+  }
+
+  override get selectedItem() {
+    return null;
+  }
+
+  // Mouse event handlers
+  handleMouseDown(e: MouseEvent) {
+    if (e.button === 2) {  // right
+      this.handleClick(e);
+    }
+  }
+
+  /**
+   * Handles double click events on the tree item.
+   */
+  handleDblClick(e: Event) {
+    const expanded = this.expanded;
+    this.expanded = !expanded;
+    e.stopPropagation();
+  }
+
+  /**
+   * Called when the user clicks on a tree item.
+   */
+  handleClick(e: Event) {
+    if ((e.target as HTMLElement).classList.contains('expand-icon')) {
+      this.expanded = !this.expanded;
+    } else {
+      this.toggleAttribute(SELECTED_ATTR, true);
+    }
+    e.stopPropagation();
+  }
+
+  // Additional methods unique to CrTreeItem:
+  /**
+   * Expands all parent items.
+   */
+  reveal() {
+    let pi = this.parentItem;
+    while (pi) {
+      pi.expanded = true;
+      pi = pi.parentItem;
+    }
+  }
+
+  /**
+   * The element containing the label text.
+   */
+  get labelElement(): HTMLElement {
+    const labelEl = this.shadowRoot!.querySelector<HTMLElement>('.tree-label');
+    assert(labelEl);
+    return labelEl as HTMLElement;
+  }
+
+  /**
+   * The label text.
+   */
+  get label(): string {
+    return this.label_;
+  }
+
+  set label(s: string) {
+    this.label_ = s;
+    if (this.shadowRoot && this.shadowRoot.querySelector('.tree-label')) {
+      this.labelElement.textContent = s;
+    }
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'cr-tree-item': CrTreeItemElement;
+  }
+}
+
+customElements.define('cr-tree-item', CrTreeItemElement);