diff --git a/DEPS b/DEPS
index c1785f58..fab3de5 100644
--- a/DEPS
+++ b/DEPS
@@ -245,11 +245,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': '6bebf036a5027da0faefbb8d822ebfc7b8f6d3c9',
+  'skia_revision': '735ff421bb53a26ff7e2a89fc394a44b4f973bbd',
   # 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': '11559b4461ac0c3328354229e03c2a989b104ff9',
+  'v8_revision': 'aaef5e2e1e317afbcabdb5f67f6e20f227f52bd4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
@@ -257,7 +257,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '433b1bf9bff2cb385f9cdfcb9be1d7f5489f357f',
+  'swiftshader_revision': 'd0de9dcaaa4420103a5363a571e71298b6827dd8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -320,7 +320,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '7f47d6b217a68889748aeb8af9bfa62304162d97',
+  'devtools_frontend_revision': '805c1e9f351c42b9a0dbc07b328e9b441105aefe',
   # 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.
@@ -360,7 +360,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': '433b116d39eb99e79cd2d4e0ae5682bb5ca7bef9',
+  'dawn_revision': 'ab02767bf28ab9dd3162d39cc8ad3153262cb6b4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -722,7 +722,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/linux-amd64',
-          'version': 'gwW_nuIBbaSJs-T9SqZ8p-n9n8PeBeGCIpIT4sa1Yk4C',
+          'version': 'DikwzN-GSg5bbYa2yySgEHRgLxoFYwKyLZ0R4ZSnaWwC',
         },
       ],
       'dep_type': 'cipd',
@@ -733,7 +733,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/mac-amd64',
-          'version': 'lI01ErixADKVyf--6jyS6PIJOFVfe1tgu5b6DQMwTW4C',
+          'version': 'BjV-CrQm6SeTrTBp7eZvbSH7Xv2ZVNsjnqJfSCQkLBQC',
         },
       ],
       'dep_type': 'cipd',
@@ -744,7 +744,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/windows-amd64',
-          'version': 'AlGjJ-CejY4CeQg-uhxG0Gput00l4TBgsuXn5IhegKQC',
+          'version': 'NZptHgrl727DXopAp3OesaDNxk0hPaZEnLNT1tunup4C',
         },
       ],
       'dep_type': 'cipd',
@@ -805,7 +805,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'fIyF1fpX--9wg5UiZuEc0h9PjgDcvDk5sEvymVaje2IC',
+          'version': 'auifkWa894Hu2TGfbC-0qFprVHM2Lwfx4dnvSIbn3ZIC',
       },
     ],
     'condition': 'checkout_android',
@@ -1044,7 +1044,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '30ae637731b459f3849867c43a0226d57d25133e',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '92c05b07e4c46c03cdaccbaa6216c70f834210ae',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1184,7 +1184,7 @@
     Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + '18e09b9197a3b1d771c077c530d1a4ebad04c167',
 
   'src/third_party/icu':
-    Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'fbc6faf1c2c429cd27fabe615a89f0b217aa4213',
+    Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'b9f6d0a5c5375dc4643f35360d257dba37c1d3e1',
 
   'src/third_party/icu4j': {
       'packages': [
@@ -1246,7 +1246,7 @@
   },
 
   'src/third_party/leveldatabase/src':
-    Var('chromium_git') + '/external/leveldb.git' + '@' + '335876a1335c765f818ae10d9c4d18f563cdfce5',
+    Var('chromium_git') + '/external/leveldb.git' + '@' + '8f464e7f68fd9d50ed39b2866ef8dac9c837439d',
 
   'src/third_party/libFuzzer/src':
     Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git' + '@' +  Var('libfuzzer_revision'),
@@ -1427,7 +1427,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'e780c370b9272c36eab718bacaa100537fd8d215',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '6303738528d33d2ac5ed455564eb8f08e14c931b',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1609,7 +1609,7 @@
   'src/third_party/usrsctp/usrsctplib':
     Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '62d7d0c928c9a040dce96aa2f16c00e7e67d59cb',
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@5d16a1ce9e6d04ad2fcd25bc65308eed82eb20c6',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@00957032e9fb062035557492b74ab3b09fe935cc',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '5e49f57a6e71a026a54eb42e366de09a4142d24e',
@@ -1648,7 +1648,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'fca7b339442bd70c5dc49bb33ee7f9466b560a97',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '94f0194d5a24c31ea80aeff7c8ff0c05668418e9',
+    Var('webrtc_git') + '/src.git' + '@' + 'de6e1b4ffde48b8f646e7449a0bcabb2c77db76b',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1730,7 +1730,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@c7922c204221d2f56cc19110e71533391dc20ee9',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@d69667bf39d4cb1cd27bd85e435644663b6ad006',
     'condition': 'checkout_src_internal',
   },
 
@@ -1760,7 +1760,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 's6Go8OsrWbDSOUjCZoIwEBFoFIcvFiqHIsvZ9YYb_hoC',
+        'version': 'u_Fv6v2Geu2wAIpdFw_5DMsaNf0h8KMx9H3CLGVt3ZcC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1771,7 +1771,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'DWF-TUAi0-Q1_W6lNqTQQheD7Yai15vasU1wxDwJWsgC',
+        'version': 'sXs5SWPhJ7kAbHETKs4m-ZHITYSXiJjF4lMiFbU1q4IC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1782,7 +1782,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': '0apBJfzJkpDurPSAH4Ov522ZP09ROz15tKsFCGouaMYC',
+        'version': '4DoYPLgzBi8J8lxcLZzBzF_Nb3xRN-iWgOwCC4j13hAC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/WATCHLISTS b/WATCHLISTS
index 0ecfd4ff..b87edd37 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -634,6 +634,16 @@
     'browsing_data': {
       'filepath': 'browsing_data|BrowsingData',
     },
+    'cast_2_class': {
+      'filepath':  '/access_code/' \
+                   '|access_code_cast' \
+                   '|ash/public/cpp/cast' \
+                   '|ash/system/cast' \
+                   '|chrome/browser/media/router/providers' \
+                   '|chrome/browser/ui/ash/cast' \
+                   '|media_router/cast_dialog_view' \
+                   '|media/router/discovery',
+    },
     'cast_certificate': {
       'filepath': 'components/cast_certificate/'\
                   '|components/test/data/cast_certificate/',
@@ -2351,6 +2361,7 @@
     'browser_scheduler': ['scheduler-bugs+browser@chromium.org'],
     'browsing_data': ['dullweber+watch@chromium.org',
                       'msramek+watch@chromium.org'],
+    'cast_2_class': ['cros-edu-eng+cl@google.com'],
     'cast_certificate': ['dougsteed+watch@chromium.org',
                          'mfoltz+watch@chromium.org',
                          'ryanchung+watch@chromium.org'],
diff --git a/ash/accelerators/key_hold_detector.cc b/ash/accelerators/key_hold_detector.cc
index 912cf36..5d9ae6a 100644
--- a/ash/accelerators/key_hold_detector.cc
+++ b/ash/accelerators/key_hold_detector.cc
@@ -69,7 +69,7 @@
         break;
       case PRESSED:
         state_ = HOLD;
-        FALLTHROUGH;
+        [[fallthrough]];
       case HOLD:
         delegate_->OnKeyHold(event);
         if (delegate_->ShouldStopEventPropagation())
diff --git a/ash/components/device_activity/device_activity_client.cc b/ash/components/device_activity/device_activity_client.cc
index aab8f30..c8ee027 100644
--- a/ash/components/device_activity/device_activity_client.cc
+++ b/ash/components/device_activity/device_activity_client.cc
@@ -293,7 +293,7 @@
       replacements.SetPathStr(kFresnelHealthCheckEndpoint);
       break;
     case State::kIdle:  // Fallthrough to |kUnknown| case.
-      FALLTHROUGH;
+      [[fallthrough]];
     case State::kUnknown:
       NOTREACHED();
       break;
diff --git a/ash/components/phonehub/connection_scheduler_impl.cc b/ash/components/phonehub/connection_scheduler_impl.cc
index 3c3699c..3083e7a0 100644
--- a/ash/components/phonehub/connection_scheduler_impl.cc
+++ b/ash/components/phonehub/connection_scheduler_impl.cc
@@ -63,15 +63,15 @@
     // from initiating a connection. Disconnect the existing connection, reset
     // backoffs, and return early.
     case FeatureStatus::kNotEligibleForFeature:
-      FALLTHROUGH;
+      [[fallthrough]];
     case FeatureStatus::kEligiblePhoneButNotSetUp:
-      FALLTHROUGH;
+      [[fallthrough]];
     case FeatureStatus::kPhoneSelectedAndPendingSetup:
-      FALLTHROUGH;
+      [[fallthrough]];
     case FeatureStatus::kDisabled:
-      FALLTHROUGH;
+      [[fallthrough]];
     case FeatureStatus::kUnavailableBluetoothOff:
-      FALLTHROUGH;
+      [[fallthrough]];
     case FeatureStatus::kLockOrSuspended:
       DisconnectAndClearBackoffAttempts();
       return;
diff --git a/ash/components/phonehub/multidevice_setup_state_updater.cc b/ash/components/phonehub/multidevice_setup_state_updater.cc
index 29f8113..3cf22ff 100644
--- a/ash/components/phonehub/multidevice_setup_state_updater.cc
+++ b/ash/components/phonehub/multidevice_setup_state_updater.cc
@@ -57,7 +57,7 @@
       break;
 
     case NotificationAccessManager::AccessStatus::kAvailableButNotGranted:
-      FALLTHROUGH;
+      [[fallthrough]];
     case NotificationAccessManager::AccessStatus::kProhibited:
       // Disable kPhoneHubNotifications if notification access has been revoked
       // by the phone.
diff --git a/ash/components/phonehub/tether_controller_impl.cc b/ash/components/phonehub/tether_controller_impl.cc
index 486e39a..ca6acd7 100644
--- a/ash/components/phonehub/tether_controller_impl.cc
+++ b/ash/components/phonehub/tether_controller_impl.cc
@@ -448,9 +448,9 @@
 
   switch (connection_state) {
     case ConnectionStateType::kOnline:
-      FALLTHROUGH;
+      [[fallthrough]];
     case ConnectionStateType::kConnected:
-      FALLTHROUGH;
+      [[fallthrough]];
     case ConnectionStateType::kPortal:
       return Status::kConnected;
 
diff --git a/ash/components/phonehub/util/histogram_util.cc b/ash/components/phonehub/util/histogram_util.cc
index 578277e3..e9145255 100644
--- a/ash/components/phonehub/util/histogram_util.cc
+++ b/ash/components/phonehub/util/histogram_util.cc
@@ -18,42 +18,42 @@
 std::string GetMessageResultHistogramName(proto::MessageType message_type) {
   switch (message_type) {
     case proto::MessageType::DISMISS_NOTIFICATION_REQUEST:
-      FALLTHROUGH;
+      [[fallthrough]];
     case proto::MessageType::DISMISS_NOTIFICATION_RESPONSE:
       return "PhoneHub.TaskCompletion.NotificationDismissal.Result";
 
     case proto::MessageType::NOTIFICATION_INLINE_REPLY_REQUEST:
-      FALLTHROUGH;
+      [[fallthrough]];
     case proto::MessageType::NOTIFICATION_INLINE_REPLY_RESPONSE:
       return "PhoneHub.TaskCompletion.NotificationInlineReply.Result";
 
     case proto::MessageType::UPDATE_NOTIFICATION_MODE_REQUEST:
-      FALLTHROUGH;
+      [[fallthrough]];
     case proto::MessageType::UPDATE_NOTIFICATION_MODE_RESPONSE:
       return "PhoneHub.TaskCompletion.SilencePhone.Result";
 
     case proto::MessageType::RING_DEVICE_REQUEST:
-      FALLTHROUGH;
+      [[fallthrough]];
     case proto::MessageType::RING_DEVICE_RESPONSE:
       return "PhoneHub.TaskCompletion.LocatePhone.Result";
 
     case proto::MessageType::SHOW_NOTIFICATION_ACCESS_SETUP_REQUEST:
-      FALLTHROUGH;
+      [[fallthrough]];
     case proto::MessageType::SHOW_NOTIFICATION_ACCESS_SETUP_RESPONSE:
       return "PhoneHub.TaskCompletion.ShowNotificationAccessSetup.Result";
 
     case proto::MessageType::UPDATE_BATTERY_MODE_REQUEST:
-      FALLTHROUGH;
+      [[fallthrough]];
     case proto::MessageType::UPDATE_BATTERY_MODE_RESPONSE:
       return "PhoneHub.TaskCompletion.UpdateBatteryMode.Result";
 
     case proto::MessageType::FETCH_CAMERA_ROLL_ITEMS_REQUEST:
-      FALLTHROUGH;
+      [[fallthrough]];
     case proto::MessageType::FETCH_CAMERA_ROLL_ITEMS_RESPONSE:
       return "PhoneHub.TaskCompletion.FetchCameraRollItems.Result";
 
     case proto::MessageType::FETCH_CAMERA_ROLL_ITEM_DATA_REQUEST:
-      FALLTHROUGH;
+      [[fallthrough]];
     case proto::MessageType::FETCH_CAMERA_ROLL_ITEM_DATA_RESPONSE:
       return "PhoneHub.TaskCompletion.FetchCameraRollItemData.Result";
 
diff --git a/ash/components/proximity_auth/proximity_auth_profile_pref_manager.cc b/ash/components/proximity_auth/proximity_auth_profile_pref_manager.cc
index 9af9b30..a6b0fbf 100644
--- a/ash/components/proximity_auth/proximity_auth_profile_pref_manager.cc
+++ b/ash/components/proximity_auth/proximity_auth_profile_pref_manager.cc
@@ -138,26 +138,26 @@
 bool ProximityAuthProfilePrefManager::IsSmartLockEligible() const {
   switch (multidevice_setup_client_->GetFeatureState(Feature::kSmartLock)) {
     case FeatureState::kUnavailableNoVerifiedHost:
-      FALLTHROUGH;
+      [[fallthrough]];
     case FeatureState::kUnavailableNoVerifiedHost_ClientNotReady:
-      FALLTHROUGH;
+      [[fallthrough]];
     case FeatureState::kNotSupportedByChromebook:
-      FALLTHROUGH;
+      [[fallthrough]];
     case FeatureState::kNotSupportedByPhone:
       return false;
 
     case FeatureState::kProhibitedByPolicy:
-      FALLTHROUGH;
+      [[fallthrough]];
     case FeatureState::kDisabledByUser:
-      FALLTHROUGH;
+      [[fallthrough]];
     case FeatureState::kEnabledByUser:
-      FALLTHROUGH;
+      [[fallthrough]];
     case FeatureState::kUnavailableInsufficientSecurity:
-      FALLTHROUGH;
+      [[fallthrough]];
     case FeatureState::kUnavailableSuiteDisabled:
-      FALLTHROUGH;
+      [[fallthrough]];
     case FeatureState::kFurtherSetupRequired:
-      FALLTHROUGH;
+      [[fallthrough]];
     case FeatureState::kUnavailableTopLevelFeatureDisabled:
       return true;
   }
diff --git a/ash/multi_device_setup/multi_device_notification_presenter.cc b/ash/multi_device_setup/multi_device_notification_presenter.cc
index 69e3cf33..4319bc2 100644
--- a/ash/multi_device_setup/multi_device_notification_presenter.cc
+++ b/ash/multi_device_setup/multi_device_notification_presenter.cc
@@ -234,7 +234,7 @@
     case Status::kExistingUserHostSwitchedNotificationVisible:
       // Clicks on the 'host switched' and 'Chromebook added' notifications have
       // the same effect, i.e. opening the Settings subpage.
-      FALLTHROUGH;
+      [[fallthrough]];
     case Status::kExistingUserNewChromebookNotificationVisible:
       Shell::Get()
           ->system_tray_model()
diff --git a/ash/public/cpp/shelf_prefs.cc b/ash/public/cpp/shelf_prefs.cc
index 6fef0204..0eddbbc5 100644
--- a/ash/public/cpp/shelf_prefs.cc
+++ b/ash/public/cpp/shelf_prefs.cc
@@ -55,22 +55,20 @@
   std::string pref_key = base::NumberToString(display_id);
   bool has_per_display_prefs = false;
   if (!pref_key.empty()) {
-    const base::DictionaryValue* shelf_prefs = &base::Value::AsDictionaryValue(
-        *prefs->GetDictionary(prefs::kShelfPreferences));
-    const base::DictionaryValue* display_pref = nullptr;
-    std::string per_display_value;
-    if (shelf_prefs->GetDictionary(pref_key, &display_pref) &&
-        display_pref->GetString(path, &per_display_value))
-      return per_display_value;
+    const base::Value* shelf_prefs =
+        prefs->GetDictionary(prefs::kShelfPreferences);
+    const base::Value* display_pref = shelf_prefs->FindDictKey(pref_key);
+    if (display_pref) {
+      const std::string* per_display_value = display_pref->FindStringPath(path);
+      if (per_display_value)
+        return *per_display_value;
+    }
 
     // If the pref for the specified display is not found, scan the whole prefs
     // and check if the prefs for other display is already specified.
     std::string unused_value;
-    for (base::DictionaryValue::Iterator iter(*shelf_prefs); !iter.IsAtEnd();
-         iter.Advance()) {
-      const base::DictionaryValue* display_pref = nullptr;
-      if (iter.value().GetAsDictionary(&display_pref) &&
-          display_pref->GetString(path, &unused_value)) {
+    for (const auto iter : shelf_prefs->DictItems()) {
+      if (iter.second.is_dict() && iter.second.FindStringPath(path)) {
         has_per_display_prefs = true;
         break;
       }
@@ -94,19 +92,20 @@
     return;
 
   // Avoid DictionaryPrefUpdate's notifications for read but unmodified prefs.
-  const base::DictionaryValue* current_shelf_prefs =
-      &base::Value::AsDictionaryValue(
-          *prefs->GetDictionary(prefs::kShelfPreferences));
+  const base::Value* current_shelf_prefs =
+      prefs->GetDictionary(prefs::kShelfPreferences);
   DCHECK(current_shelf_prefs);
   std::string display_key = base::NumberToString(display_id);
-  const base::DictionaryValue* current_display_prefs = nullptr;
-  std::string current_value;
-  if (current_shelf_prefs->GetDictionary(display_key, &current_display_prefs) &&
-      current_display_prefs->GetString(pref_key, &current_value) &&
-      current_value == value) {
-    return;
+  const base::Value* current_display_prefs =
+      current_shelf_prefs->FindDictKey(display_key);
+  if (current_display_prefs) {
+    const std::string* current_value =
+        current_display_prefs->FindStringPath(pref_key);
+    if (current_value && *current_value == value)
+      return;
   }
 
+  // TODO(crbug.com/1187061): Refactor this to remove base::DictionaryValue.
   DictionaryPrefUpdate update(prefs, prefs::kShelfPreferences);
   base::DictionaryValue* shelf_prefs = update.Get();
   base::DictionaryValue* display_prefs_weak = nullptr;
diff --git a/ash/rotator/screen_rotation_animator.cc b/ash/rotator/screen_rotation_animator.cc
index a0f6756..53dbf20f 100644
--- a/ash/rotator/screen_rotation_animator.cc
+++ b/ash/rotator/screen_rotation_animator.cc
@@ -492,7 +492,7 @@
   switch (screen_rotation_state_) {
     case IDLE:
       DCHECK(!current_async_rotation_request_);
-      FALLTHROUGH;
+      [[fallthrough]];
     case COPY_REQUESTED:
       if (current_async_rotation_request_ &&
           !RootWindowChangedForDisplayId(
diff --git a/ash/shelf/scrollable_shelf_view.cc b/ash/shelf/scrollable_shelf_view.cc
index 8dd118c..1a50cae3 100644
--- a/ash/shelf/scrollable_shelf_view.cc
+++ b/ash/shelf/scrollable_shelf_view.cc
@@ -793,6 +793,7 @@
 void ScrollableShelfView::ChildPreferredSizeChanged(views::View* child) {
   // Add/remove a shelf icon may change the layout strategy.
   UpdateAvailableSpaceAndScroll();
+  shelf_container_view_->TranslateShelfView(scroll_offset_);
   Layout();
 }
 
diff --git a/ash/shelf/shelf_app_button.cc b/ash/shelf/shelf_app_button.cc
index eb27d2b..b7519d8 100644
--- a/ash/shelf/shelf_app_button.cc
+++ b/ash/shelf/shelf_app_button.cc
@@ -753,7 +753,7 @@
       }
       break;
     case ui::ET_GESTURE_TAP:
-      FALLTHROUGH;  // Ensure tapped items are not enlarged for drag.
+      [[fallthrough]];  // Ensure tapped items are not enlarged for drag.
     case ui::ET_GESTURE_END:
       // If the button is being dragged, or there is an active context menu,
       // for this ShelfAppButton, don't deactivate the ink drop.
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc
index bf2aa2d..ab5af4a 100644
--- a/ash/shelf/shelf_layout_manager.cc
+++ b/ash/shelf/shelf_layout_manager.cc
@@ -1416,7 +1416,7 @@
                    ? HotseatState::kExtended
                    : HotseatState::kHidden;
       }
-      FALLTHROUGH;
+      [[fallthrough]];
     case kDragCancelInProgress: {
       // If the drag being completed is not a Hotseat drag, don't change the
       // state.
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc
index 207b7b1f..aabdc78 100644
--- a/ash/shelf/shelf_view.cc
+++ b/ash/shelf/shelf_view.cc
@@ -658,7 +658,7 @@
         return;
       }
 
-      FALLTHROUGH;
+      [[fallthrough]];
     case ui::ET_MOUSE_DRAGGED:
     case ui::ET_MOUSE_RELEASED:
       // Convert the event location from current view to screen, since dragging
diff --git a/ash/strings/ash_strings_am.xtb b/ash/strings/ash_strings_am.xtb
index 8f5d7c6..98a05778 100644
--- a/ash/strings/ash_strings_am.xtb
+++ b/ash/strings/ash_strings_am.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">የቀጥታ ስርጭት መግለጫ ጽሑፍ በርቷል።</translation>
 <translation id="1720011244392820496">የWi-Fi ስምረትን ያብሩ</translation>
+<translation id="1736898441010944794">«<ph name="NAME" />» ለብሉቱዝ መሳሪያዎች ይታያል።</translation>
 <translation id="1743570585616704562">አልታወቀም</translation>
 <translation id="1746730358044914197">የግቤት ስልቶች በእርስዎ አስተዳዳሪ ይዋቀራሉ።</translation>
 <translation id="1747827819627189109">በማያ ገጽ ላይ የቁልፍ ሰሌዳ ነቅቷል</translation>
@@ -831,6 +832,7 @@
 <translation id="6578407462441924264">ያልተሰየመ</translation>
 <translation id="6585808820553845416">ክፍለ-ጊዜ በ<ph name="SESSION_TIME_REMAINING" /> ውስጥ ያበቃል።</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />፣ <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">የእርስዎ ግንኙነት ደህንነቱ ይበልጥ ወደተጠበቀ አውታረ መረብ ቀይሯል</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />፣ የሲግናል ጥንካሬ <ph name="SIGNAL_STRENGTH" />፣ በአስተዳዳሪዎ የሚቀናበር</translation>
 <translation id="6612802754306526077">የማያ ገጽ ቀረጻ ሁነታ ተመርጧል</translation>
 <translation id="6614169507485700968">የግላዊነት ማያ ገጽ በርቷል</translation>
diff --git a/ash/strings/ash_strings_bn.xtb b/ash/strings/ash_strings_bn.xtb
index 1dfade5..4da32e1 100644
--- a/ash/strings/ash_strings_bn.xtb
+++ b/ash/strings/ash_strings_bn.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">"লাইভ ক্যাপশন" চালু আছে।</translation>
 <translation id="1720011244392820496">ওয়াই-ফাই সিঙ্ক করার সুবিধা চালু করুন</translation>
+<translation id="1736898441010944794">ব্লুটুথ ডিভাইসে "<ph name="NAME" />" দেখা যায়।</translation>
 <translation id="1743570585616704562">শনাক্ত করা যায়নি</translation>
 <translation id="1746730358044914197">আপনার প্রশাসক ইনপুটের পদ্ধতিগুলি কনফিগার করে।</translation>
 <translation id="1747827819627189109">অন-স্ক্রিন কীবোর্ড সক্ষম করা রয়েছে</translation>
@@ -831,6 +832,7 @@
 <translation id="6578407462441924264">নামবিহীন</translation>
 <translation id="6585808820553845416"><ph name="SESSION_TIME_REMAINING" /> এর মধ্যে সেশন শেষ হয়ে যাবে৷</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">আপনার নেটওয়ার্ক কানেকশনটি আরও সুরক্ষিত নেটওয়ার্কে পরিবর্তিত হয়েছে</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, সিগন্যাল: <ph name="SIGNAL_STRENGTH" />, আপনার অ্যাডমিনিস্ট্রেটর ম্যানেজ করে</translation>
 <translation id="6612802754306526077">স্ক্রিন রেকর্ডিং মোড বেছে নেওয়া হয়েছে</translation>
 <translation id="6614169507485700968">গোপনীয়তা স্ক্রিন চালু করা আছে</translation>
diff --git a/ash/strings/ash_strings_bs.xtb b/ash/strings/ash_strings_bs.xtb
index 924f9d10..3c579e65 100644
--- a/ash/strings/ash_strings_bs.xtb
+++ b/ash/strings/ash_strings_bs.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">Automatski titlovi su uključeni.</translation>
 <translation id="1720011244392820496">Uključite sinhronizaciju putem WiFi mreže</translation>
+<translation id="1736898441010944794">"<ph name="NAME" />" je vidljiv Bluetooth uređajima.</translation>
 <translation id="1743570585616704562">Nije prepoznato</translation>
 <translation id="1746730358044914197">Načine unosa konfigurira vaš administrator.</translation>
 <translation id="1747827819627189109">Tastatura na ekranu je omogućena</translation>
@@ -831,6 +832,7 @@
 <translation id="6578407462441924264">Neimenovano</translation>
 <translation id="6585808820553845416">Sesija će se završiti za <ph name="SESSION_TIME_REMAINING" />.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">Vaša veza je prebačena na sigurniju mrežu</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, jačina signala <ph name="SIGNAL_STRENGTH" />, upravlja vaš administrator</translation>
 <translation id="6612802754306526077">Odabran je način rada za snimanje ekrana</translation>
 <translation id="6614169507485700968">Ekran za privatnost je uključen</translation>
diff --git a/ash/strings/ash_strings_cs.xtb b/ash/strings/ash_strings_cs.xtb
index 88c0dba8..fee27a1 100644
--- a/ash/strings/ash_strings_cs.xtb
+++ b/ash/strings/ash_strings_cs.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">Živý přepis je zapnutý</translation>
 <translation id="1720011244392820496">Zapnutí Synchronizace Wi-Fi</translation>
+<translation id="1736898441010944794">Adaptér <ph name="NAME" /> je viditelný pro zařízení Bluetooth.</translation>
 <translation id="1743570585616704562">Nerozpoznáno</translation>
 <translation id="1746730358044914197">Metody zadávání nastavuje váš administrátor.</translation>
 <translation id="1747827819627189109">Softwarová klávesnice je aktivována</translation>
@@ -831,6 +832,7 @@
 <translation id="6578407462441924264">Bez názvu</translation>
 <translation id="6585808820553845416">Relace skončí za <ph name="SESSION_TIME_REMAINING" />.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">Vaše připojení se přepnulo na bezpečnější síť</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, síla signálu: <ph name="SIGNAL_STRENGTH" />, spravováno administrátorem</translation>
 <translation id="6612802754306526077">Je vybrán režim nahrávání obrazovky</translation>
 <translation id="6614169507485700968">Obrazovka ochrany soukromí je zapnutá</translation>
diff --git a/ash/strings/ash_strings_de.xtb b/ash/strings/ash_strings_de.xtb
index 055ae8d..b45c816 100644
--- a/ash/strings/ash_strings_de.xtb
+++ b/ash/strings/ash_strings_de.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">Automatische Untertitel sind an.</translation>
 <translation id="1720011244392820496">WLAN-Synchronisation aktivieren</translation>
+<translation id="1736898441010944794">„<ph name="NAME" />“ ist für Bluetooth-Geräte sichtbar.</translation>
 <translation id="1743570585616704562">Nicht erkannt</translation>
 <translation id="1746730358044914197">Die Eingabemethoden werden von Ihrem Administrator konfiguriert.</translation>
 <translation id="1747827819627189109">Bildschirmtastatur aktiviert</translation>
@@ -831,6 +832,7 @@
 <translation id="6578407462441924264">Unbenannt</translation>
 <translation id="6585808820553845416">Sitzung endet in <ph name="SESSION_TIME_REMAINING" />.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">Deine Verbindung wurde auf ein sichereres Netzwerk umgestellt</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, Signalstärke bei <ph name="SIGNAL_STRENGTH" />, von Ihrem Administrator verwaltet</translation>
 <translation id="6612802754306526077">Modus für Aufzeichnung des Bildschirms ausgewählt</translation>
 <translation id="6614169507485700968">Der Datenschutzbildschirm ist momentan aktiviert</translation>
diff --git a/ash/strings/ash_strings_el.xtb b/ash/strings/ash_strings_el.xtb
index 6ce1084..217c3e0 100644
--- a/ash/strings/ash_strings_el.xtb
+++ b/ash/strings/ash_strings_el.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">Οι Ζωντανοί υπότιτλοι είναι ενεργοποιημένοι.</translation>
 <translation id="1720011244392820496">Ενεργοποίηση του Συγχρονισμού Wi-Fi</translation>
+<translation id="1736898441010944794">Το "<ph name="NAME" />" είναι ορατό σε συσκευές Bluetooth.</translation>
 <translation id="1743570585616704562">Δεν αναγνωρίστηκε</translation>
 <translation id="1746730358044914197">Οι μέθοδοι εισαγωγής έχουν διαμορφωθεί από τον διαχειριστή σας.</translation>
 <translation id="1747827819627189109">Το πληκτρολόγιο οθόνης είναι ενεργοποιημένο</translation>
@@ -831,6 +832,7 @@
 <translation id="6578407462441924264">Χωρίς όνομα</translation>
 <translation id="6585808820553845416">Η περίοδος σύνδεσης λήγει σε <ph name="SESSION_TIME_REMAINING" />.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">Έγινε εναλλαγή της σύνδεσής σας σε ένα πιο ασφαλές δίκτυο.</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, Ισχύς σήματος <ph name="SIGNAL_STRENGTH" />, Διαχειριζόμενο από τον διαχειριστή σας</translation>
 <translation id="6612802754306526077">Επιλέχτηκε η λειτουργία εγγραφής οθόνης.</translation>
 <translation id="6614169507485700968">Η οθόνη απορρήτου είναι ενεργοποιημένη.</translation>
diff --git a/ash/strings/ash_strings_es.xtb b/ash/strings/ash_strings_es.xtb
index 4070f3c..036e9d9 100644
--- a/ash/strings/ash_strings_es.xtb
+++ b/ash/strings/ash_strings_es.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">Subtítulos automáticos activados.</translation>
 <translation id="1720011244392820496">Activar Sincronización Wi‑Fi</translation>
+<translation id="1736898441010944794">"<ph name="NAME" />" es visible para los dispositivos Bluetooth.</translation>
 <translation id="1743570585616704562">No se ha reconocido</translation>
 <translation id="1746730358044914197">El administrador configura los métodos de introducción.</translation>
 <translation id="1747827819627189109">Teclado en pantalla habilitado</translation>
@@ -832,6 +833,7 @@
 <translation id="6578407462441924264">Sin nombre</translation>
 <translation id="6585808820553845416">La sesión finalizará dentro de <ph name="SESSION_TIME_REMAINING" />.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">La conexión ha cambiado a una red más segura</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, intensidad de la señal: <ph name="SIGNAL_STRENGTH" />, gestionada por el administrador</translation>
 <translation id="6612802754306526077">Modo de grabación de pantalla seleccionado</translation>
 <translation id="6614169507485700968">La pantalla de privacidad está activada</translation>
diff --git a/ash/strings/ash_strings_eu.xtb b/ash/strings/ash_strings_eu.xtb
index 99a1ab67..8afc2adb 100644
--- a/ash/strings/ash_strings_eu.xtb
+++ b/ash/strings/ash_strings_eu.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">Istanteko azpitituluak aktibatuta daude.</translation>
 <translation id="1720011244392820496">Aktibatu Wifi-sinkronizazioa</translation>
+<translation id="1736898441010944794">Ezarri da ikusgai "<ph name="NAME" />" Bluetooth bidezko gailuetarako.</translation>
 <translation id="1743570585616704562">Ez da ezagutu</translation>
 <translation id="1746730358044914197">Administratzaileak konfiguratzen ditu idazketa-metodoak.</translation>
 <translation id="1747827819627189109">Pantailako teklatua gaitu egin da</translation>
@@ -832,6 +833,7 @@
 <translation id="6578407462441924264">Izengabea</translation>
 <translation id="6585808820553845416">Saioa <ph name="SESSION_TIME_REMAINING" /> barru amaituko da.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">Sare seguruago batera konektatuta zaude orain</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />. Seinalearen indarra: <ph name="SIGNAL_STRENGTH" />. Administratzaileak kudeatua.</translation>
 <translation id="6612802754306526077">Pantaila grabatzeko modua hautatu da</translation>
 <translation id="6614169507485700968">Aktibatuta dago pribatutasun-pantaila</translation>
diff --git a/ash/strings/ash_strings_gl.xtb b/ash/strings/ash_strings_gl.xtb
index 829c9df..e9b5987 100644
--- a/ash/strings/ash_strings_gl.xtb
+++ b/ash/strings/ash_strings_gl.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">A función Subtítulos instantáneos está activada.</translation>
 <translation id="1720011244392820496">Activar Sincronización wifi</translation>
+<translation id="1736898441010944794">"<ph name="NAME" />" detectable por dispositivos Bluetooth.</translation>
 <translation id="1743570585616704562">Non se recoñece</translation>
 <translation id="1746730358044914197">O teu administrador configura os métodos de entrada.</translation>
 <translation id="1747827819627189109">Teclado en pantalla activado</translation>
@@ -832,6 +833,7 @@
 <translation id="6578407462441924264">Sen nome</translation>
 <translation id="6585808820553845416">A sesión finaliza dentro de <ph name="SESSION_TIME_REMAINING" /> .</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">A conexión cambiouse a unha rede máis segura</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, intensidade do sinal do <ph name="SIGNAL_STRENGTH" />, xestionada polo teu administrador</translation>
 <translation id="6612802754306526077">Seleccionouse o modo de gravación da pantalla</translation>
 <translation id="6614169507485700968">A pantalla de privacidade está activada</translation>
diff --git a/ash/strings/ash_strings_hi.xtb b/ash/strings/ash_strings_hi.xtb
index f9ab9b6..f356d63 100644
--- a/ash/strings/ash_strings_hi.xtb
+++ b/ash/strings/ash_strings_hi.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">एफ़</translation>
 <translation id="1719094688023114093">लाइव कैप्शन की सुविधा चालू है.</translation>
 <translation id="1720011244392820496">'वाई-फ़ाई सिंक' चालू करें</translation>
+<translation id="1736898441010944794">"<ph name="NAME" />" ब्लूटूथ डिवाइसों को दिख रहा है.</translation>
 <translation id="1743570585616704562">उंगली की पहचान नहीं हो सकी</translation>
 <translation id="1746730358044914197">इनपुट विधियों को आपका व्यवस्थापक कॉन्फ़िगर करता है.</translation>
 <translation id="1747827819627189109">ऑन-स्‍क्रीन कीबोर्ड सक्षम है</translation>
@@ -832,6 +833,7 @@
 <translation id="6578407462441924264">कोई नाम नहीं</translation>
 <translation id="6585808820553845416">सत्र <ph name="SESSION_TIME_REMAINING" /> में खत्म होने वाला है.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">आपका कनेक्शन ज़्यादा सुरक्षित नेटवर्क पर स्विच कर दिया गया है</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, सिग्नल की क्षमता <ph name="SIGNAL_STRENGTH" />, आपका एडमिन प्रबंधित करता है</translation>
 <translation id="6612802754306526077">स्क्रीन रिकॉर्डिंग मोड चुना गया</translation>
 <translation id="6614169507485700968">निजता स्क्रीन चालू है</translation>
diff --git a/ash/strings/ash_strings_hr.xtb b/ash/strings/ash_strings_hr.xtb
index ca29185..6a28487 100644
--- a/ash/strings/ash_strings_hr.xtb
+++ b/ash/strings/ash_strings_hr.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">Uključeni su automatski titlovi.</translation>
 <translation id="1720011244392820496">Uključivanje Wi-Fi sinkronizacije</translation>
+<translation id="1736898441010944794">"<ph name="NAME" />" je vidljiv Bluetooth uređajima.</translation>
 <translation id="1743570585616704562">Nije prepoznat</translation>
 <translation id="1746730358044914197">Načine unosa konfigurira administrator.</translation>
 <translation id="1747827819627189109">Tipkovnica na zaslonu omogućena je</translation>
@@ -831,6 +832,7 @@
 <translation id="6578407462441924264">Bez naziva</translation>
 <translation id="6585808820553845416">Sesija će završiti za <ph name="SESSION_TIME_REMAINING" />.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">Prebacili ste se na vezu sa sigurnijom mrežom.</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, jačina signala <ph name="SIGNAL_STRENGTH" />, upravlja administrator</translation>
 <translation id="6612802754306526077">Odabran je način snimanja zaslona</translation>
 <translation id="6614169507485700968">Uključen je zaslon privatnosti</translation>
diff --git a/ash/strings/ash_strings_hu.xtb b/ash/strings/ash_strings_hu.xtb
index fd78d3d..b16342d 100644
--- a/ash/strings/ash_strings_hu.xtb
+++ b/ash/strings/ash_strings_hu.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">Az Élő feliratozás be van kapcsolva.</translation>
 <translation id="1720011244392820496">Wi-Fi szinkronizálásának bekapcsolása</translation>
+<translation id="1736898441010944794">A(z) „<ph name="NAME" />” látható a Bluetooth-eszközök számára.</translation>
 <translation id="1743570585616704562">Nem sikerült felismerni</translation>
 <translation id="1746730358044914197">A rendszergazda állította be a beviteli módszereket.</translation>
 <translation id="1747827819627189109">Képernyő-billentyűzet bekapcsolva</translation>
@@ -832,6 +833,7 @@
 <translation id="6578407462441924264">Név nélküli</translation>
 <translation id="6585808820553845416">A munkamenet <ph name="SESSION_TIME_REMAINING" /> múlva véget ér.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">A rendszer biztonságosabb hálózati kapcsolatra váltott</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, jelerősség: <ph name="SIGNAL_STRENGTH" />, a rendszergazdája kezeli</translation>
 <translation id="6612802754306526077">Képernyőrögzítés mód kiválasztva</translation>
 <translation id="6614169507485700968">Az adatvédelmi képernyő be van kapcsolva</translation>
diff --git a/ash/strings/ash_strings_it.xtb b/ash/strings/ash_strings_it.xtb
index 2d8c4dc3..032ad3cf 100644
--- a/ash/strings/ash_strings_it.xtb
+++ b/ash/strings/ash_strings_it.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">La funzionalità Sottotitoli in tempo reale è attiva.</translation>
 <translation id="1720011244392820496">Attiva Sync Wi-Fi</translation>
+<translation id="1736898441010944794">"<ph name="NAME" />" visibile ai dispositivi Bluetooth.</translation>
 <translation id="1743570585616704562">Non riconosciuta</translation>
 <translation id="1746730358044914197">I metodi di immissione vengono configurati dall'amministratore.</translation>
 <translation id="1747827819627189109">Tastiera sullo schermo attiva</translation>
@@ -832,6 +833,7 @@
 <translation id="6578407462441924264">Senza nome</translation>
 <translation id="6585808820553845416">La sessione terminerà tra <ph name="SESSION_TIME_REMAINING" />.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">La tua connessione è passata a una rete più sicura</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, intensità del segnale <ph name="SIGNAL_STRENGTH" />, gestita dall'amministratore</translation>
 <translation id="6612802754306526077">Modalità Registrazione dello schermo selezionata</translation>
 <translation id="6614169507485700968">Schermata sulla privacy attiva</translation>
diff --git a/ash/strings/ash_strings_iw.xtb b/ash/strings/ash_strings_iw.xtb
index c8ab1ae..7ae7283 100644
--- a/ash/strings/ash_strings_iw.xtb
+++ b/ash/strings/ash_strings_iw.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">התכונה 'כתוביות מיידיות' מופעלת.</translation>
 <translation id="1720011244392820496">‏הפעלה של סנכרון Wi-Fi</translation>
+<translation id="1736898441010944794">‏"<ph name="NAME" />" זמין למכשירי Bluetooth.</translation>
 <translation id="1743570585616704562">לא מזוהה</translation>
 <translation id="1746730358044914197">מנהל המערכת שלך מגדיר את שיטות הקלט.</translation>
 <translation id="1747827819627189109">המקלדת שמופיעה במסך מופעלת</translation>
@@ -831,6 +832,7 @@
 <translation id="6578407462441924264">ללא שם</translation>
 <translation id="6585808820553845416">הפעילות באתר תסתיים בעוד <ph name="SESSION_TIME_REMAINING" />.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">החיבור שלך הועבר לרשת מאובטחת יותר</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, עוצמת האות: <ph name="SIGNAL_STRENGTH" />, הרשת מנוהלת על ידי מנהל המערכת</translation>
 <translation id="6612802754306526077">נבחר מצב של הקלטת מסך</translation>
 <translation id="6614169507485700968">מסך הפרטיות פועל</translation>
diff --git a/ash/strings/ash_strings_kk.xtb b/ash/strings/ash_strings_kk.xtb
index afa007ec..ee94cdd 100644
--- a/ash/strings/ash_strings_kk.xtb
+++ b/ash/strings/ash_strings_kk.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">Live Caption қосулы.</translation>
 <translation id="1720011244392820496">Wi-Fi деректерін синхрондауды қосу</translation>
+<translation id="1736898441010944794">"<ph name="NAME" />" Bluetooth құрылғыларына көрінеді.</translation>
 <translation id="1743570585616704562">Анықталмады</translation>
 <translation id="1746730358044914197">Енгізу әдістерін әкімші конфигурациялайды.</translation>
 <translation id="1747827819627189109">Экрандық пернетақта қосылды</translation>
@@ -831,6 +832,7 @@
 <translation id="6578407462441924264">Атауы жоқ</translation>
 <translation id="6585808820553845416">Сеанс <ph name="SESSION_TIME_REMAINING" /> уақыттан кейін аяқталады.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">Байланысыңыз әлдеқайда қауіпсіз желіге ауысты.</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, сигнал күші: <ph name="SIGNAL_STRENGTH" />, әкімші басқарады</translation>
 <translation id="6612802754306526077">Экранды жазу режимі таңдалды.</translation>
 <translation id="6614169507485700968">Құпиялылық экраны қосулы.</translation>
diff --git a/ash/strings/ash_strings_ky.xtb b/ash/strings/ash_strings_ky.xtb
index c532562..3f809f7a 100644
--- a/ash/strings/ash_strings_ky.xtb
+++ b/ash/strings/ash_strings_ky.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">Ыкчам коштомо жазуулар күйүк.</translation>
 <translation id="1720011244392820496">Wi-Fi Sync'ти күйгүзүү</translation>
+<translation id="1736898441010944794">"<ph name="NAME" />" Bluetooth түзмөктөрүнө көрүнөт.</translation>
 <translation id="1743570585616704562">Таанылган жок</translation>
 <translation id="1746730358044914197">Киргизүү ыкмасы администратор тарабынан конфигурацияланат.</translation>
 <translation id="1747827819627189109">Экрандагы баскычтоп күйгүзүлдү</translation>
@@ -831,6 +832,7 @@
 <translation id="6578407462441924264">Аталышы жок</translation>
 <translation id="6585808820553845416">Сессия <ph name="SESSION_TIME_REMAINING" /> кийиничинде бүтөт.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">Туташууңуз коопсузураак тармакка которулду</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, Сигналдын күчү <ph name="SIGNAL_STRENGTH" />, Администраторуңуз башкарат</translation>
 <translation id="6612802754306526077">Экрандан видео жаздырып алуу режими тандалды</translation>
 <translation id="6614169507485700968">Купуялык экраны күйүк</translation>
diff --git a/ash/strings/ash_strings_ml.xtb b/ash/strings/ash_strings_ml.xtb
index 0727b51..bd07f558 100644
--- a/ash/strings/ash_strings_ml.xtb
+++ b/ash/strings/ash_strings_ml.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">തത്സമയ ക്യാപ്ഷൻ ഓണാണ്.</translation>
 <translation id="1720011244392820496">വൈഫൈ സമന്വയം ഓണാക്കുക</translation>
+<translation id="1736898441010944794">Bluetooth ഉപകരണങ്ങൾക്ക് "<ph name="NAME" />" ദൃശ്യമാണ്.</translation>
 <translation id="1743570585616704562">തിരിച്ചറിഞ്ഞില്ല</translation>
 <translation id="1746730358044914197">ഇൻപുട്ട് രീതികൾ കോൺഫിഗർ ചെയ്യുന്നത് നിങ്ങളുടെ അഡ്‌മിനിസ്‌ട്രേറ്ററാണ്.</translation>
 <translation id="1747827819627189109">ഓൺ‌ സ്‌ക്രീൻ കീ‌ബോർഡ് പ്രവർത്തനക്ഷമമാക്കി</translation>
@@ -831,6 +832,7 @@
 <translation id="6578407462441924264">പേരില്ലാത്തത്</translation>
 <translation id="6585808820553845416"><ph name="SESSION_TIME_REMAINING" />-നുള്ളിൽ സെഷൻ അവസാനിക്കുന്നു.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">കൂടുതൽ സുരക്ഷിതമായൊരു നെറ്റ്‌വർക്കിലേക്ക് നിങ്ങളുടെ കണക്ഷൻ മാറ്റിയിരിക്കുന്നു</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, സിഗ്‌നൽ ശക്തി <ph name="SIGNAL_STRENGTH" />, നിങ്ങളുടെ അഡ്‌മിൻ മാനേജ് ചെയ്യുന്നത്</translation>
 <translation id="6612802754306526077">സ്ക്രീൻ റെക്കോർഡിംഗ് മോഡ് തിരഞ്ഞെടുത്തു</translation>
 <translation id="6614169507485700968">സ്വകാര്യതാ സ്‌ക്രീൻ ഓണാണ്</translation>
diff --git a/ash/strings/ash_strings_mn.xtb b/ash/strings/ash_strings_mn.xtb
index 9fad62fd..ba4af08 100644
--- a/ash/strings/ash_strings_mn.xtb
+++ b/ash/strings/ash_strings_mn.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">Шууд тайлбар асаалттай байна.</translation>
 <translation id="1720011244392820496">Wi-Fi синкийг асаана уу</translation>
+<translation id="1736898441010944794">"<ph name="NAME" />" нь Bluetooth төхөөрөмжүүдэд харагдана.</translation>
 <translation id="1743570585616704562">Танихгүй байна</translation>
 <translation id="1746730358044914197">Оролтын аргыг таны админ тохируулсан.</translation>
 <translation id="1747827819627189109">Дэлгэцэн дээрх гарыг идэвхжүүлсэн байна</translation>
@@ -832,6 +833,7 @@
 <translation id="6578407462441924264">Нэргүй</translation>
 <translation id="6585808820553845416"><ph name="SESSION_TIME_REMAINING" /> хугацааны дараа таны цаг дуусна.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">Таны холболтыг илүү аюулгүй сүлжээ рүү сэлгэсэн</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, дохионы хүч <ph name="SIGNAL_STRENGTH" />, таны администратор удирддаг</translation>
 <translation id="6612802754306526077">Дэлгэцийн үйлдэл бичих горимыг сонгосон</translation>
 <translation id="6614169507485700968">Нууцлалын дэлгэц асаалттай байна</translation>
diff --git a/ash/strings/ash_strings_mr.xtb b/ash/strings/ash_strings_mr.xtb
index 3be00f4..4cb1703f 100644
--- a/ash/strings/ash_strings_mr.xtb
+++ b/ash/strings/ash_strings_mr.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">लाइव्ह कॅप्शन सुरू आहे.</translation>
 <translation id="1720011244392820496">वाय-फाय सिंक सुरू करा</translation>
+<translation id="1736898441010944794">ब्लूटूथ डिव्‍हाइसना "<ph name="NAME" />" दृश्यमान आहे.</translation>
 <translation id="1743570585616704562">ओळखले नाही</translation>
 <translation id="1746730358044914197">तुमच्या ॲडमिनिस्ट्रेटरद्वारे कॉंफिगर केलेल्या इनपुट पद्धती.</translation>
 <translation id="1747827819627189109">ऑन-स्क्रीन कीबोर्ड सक्षम</translation>
@@ -831,6 +832,7 @@
 <translation id="6578407462441924264">नाव नसलेले</translation>
 <translation id="6585808820553845416"><ph name="SESSION_TIME_REMAINING" /> मध्ये सेशन समाप्त होते.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">तुमचे कनेक्शन अधिक सुरक्षित नेटवर्कवर स्विच केले आहे</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, सिग्नल क्षमता <ph name="SIGNAL_STRENGTH" />, तुमच्या अ‍ॅडमिनिस्ट्रेटरने व्यवस्थापित केलेले</translation>
 <translation id="6612802754306526077">स्क्रीन रेकॉर्डिंग मोड निवडला आहे</translation>
 <translation id="6614169507485700968">गोपनीयता स्क्रीन सुरू आहे</translation>
diff --git a/ash/strings/ash_strings_pa.xtb b/ash/strings/ash_strings_pa.xtb
index 88fb442..e7c8ff37 100644
--- a/ash/strings/ash_strings_pa.xtb
+++ b/ash/strings/ash_strings_pa.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">ਲਾਈਵ ਸੁਰਖੀਆਂ ਚਾਲੂ ਹਨ।</translation>
 <translation id="1720011244392820496">ਵਾਈ-ਫਾਈ ਸਿੰਕ ਚਾਲੂ ਕਰੋ</translation>
+<translation id="1736898441010944794">"<ph name="NAME" />" ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਨੂੰ ਦਿਸ ਰਿਹਾ ਹੈ।</translation>
 <translation id="1743570585616704562">ਪਛਾਣ ਨਹੀਂ ਹੋਈ</translation>
 <translation id="1746730358044914197">ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਇਨਪੁੱਟ ਵਿਧੀਆਂ ਦਾ ਸੰਰੂਪਣ ਕੀਤਾ ਗਿਆ ਹੈ।</translation>
 <translation id="1747827819627189109">ਔਨ-ਸਕ੍ਰੀਨ ਕੀ-ਬੋਰਡ ਸਮਰਥਿਤ</translation>
@@ -832,6 +833,7 @@
 <translation id="6578407462441924264">ਬੇਨਾਮ</translation>
 <translation id="6585808820553845416">ਸੈਸ਼ਨ <ph name="SESSION_TIME_REMAINING" /> ਵਿੱਚ ਖ਼ਤਮ ਹੋਵੇਗਾ।</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">ਤੁਹਾਡਾ ਕਨੈਕਸ਼ਨ ਹੋਰ ਸੁਰੱਖਿਅਤ ਨੈੱਟਵਰਕ 'ਤੇ ਸਵਿੱਚ ਕੀਤਾ ਗਿਆ ਹੈ</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, ਸਿਗਨਲ ਦੀ ਤੀਬਰਤਾ <ph name="SIGNAL_STRENGTH" />, ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ</translation>
 <translation id="6612802754306526077">ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਮੋਡ ਨੂੰ ਚੁਣਿਆ ਗਿਆ</translation>
 <translation id="6614169507485700968">ਪਰਦੇਦਾਰੀ ਸਕ੍ਰੀਨ ਚਾਲੂ ਹੈ</translation>
diff --git a/ash/strings/ash_strings_sr-Latn.xtb b/ash/strings/ash_strings_sr-Latn.xtb
index c6d88ac..218e8b0 100644
--- a/ash/strings/ash_strings_sr-Latn.xtb
+++ b/ash/strings/ash_strings_sr-Latn.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">Titl uživo je uključen.</translation>
 <translation id="1720011244392820496">Uključite WiFi sinhronizaciju</translation>
+<translation id="1736898441010944794">Stavka „<ph name="NAME" />“ je vidljiva za Bluetooth uređaje.</translation>
 <translation id="1743570585616704562">Nije prepoznat</translation>
 <translation id="1746730358044914197">Metode unosa konfiguriše administrator.</translation>
 <translation id="1747827819627189109">Tastatura na ekranu je omogućena</translation>
@@ -831,6 +832,7 @@
 <translation id="6578407462441924264">Bez imena</translation>
 <translation id="6585808820553845416">Sesija se završava za <ph name="SESSION_TIME_REMAINING" />.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">Sada ste povezani na bezbedniju mrežu</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, jačina signala <ph name="SIGNAL_STRENGTH" />, upravlja administrator</translation>
 <translation id="6612802754306526077">Režim snimanja ekrana je izabran</translation>
 <translation id="6614169507485700968">Ekran za privatnost je uključen</translation>
diff --git a/ash/strings/ash_strings_sr.xtb b/ash/strings/ash_strings_sr.xtb
index 19a8d0a..a53c95f 100644
--- a/ash/strings/ash_strings_sr.xtb
+++ b/ash/strings/ash_strings_sr.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">Титл уживо је укључен.</translation>
 <translation id="1720011244392820496">Укључите WiFi синхронизацију</translation>
+<translation id="1736898441010944794">Ставка „<ph name="NAME" />“ је видљива за Bluetooth уређаје.</translation>
 <translation id="1743570585616704562">Није препознат</translation>
 <translation id="1746730358044914197">Методе уноса конфигурише администратор.</translation>
 <translation id="1747827819627189109">Тастатура на екрану је омогућена</translation>
@@ -831,6 +832,7 @@
 <translation id="6578407462441924264">Без имена</translation>
 <translation id="6585808820553845416">Сесија се завршава за <ph name="SESSION_TIME_REMAINING" />.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">Сада сте повезани на безбеднију мрежу</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, јачина сигнала <ph name="SIGNAL_STRENGTH" />, управља администратор</translation>
 <translation id="6612802754306526077">Режим снимања екрана је изабран</translation>
 <translation id="6614169507485700968">Екран за приватност је укључен</translation>
diff --git a/ash/strings/ash_strings_ta.xtb b/ash/strings/ash_strings_ta.xtb
index 3ada065b..28c476b9 100644
--- a/ash/strings/ash_strings_ta.xtb
+++ b/ash/strings/ash_strings_ta.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">'உடனடி வசனம்' இயக்கப்பட்டது.</translation>
 <translation id="1720011244392820496">வைஃபை ஒத்திசைவை இயக்குங்கள்</translation>
+<translation id="1736898441010944794">புளூடூத் சாதனங்களுக்கு "<ph name="NAME" />" காட்டப்படும்.</translation>
 <translation id="1743570585616704562">அடையாளங்காண முடியவில்லை</translation>
 <translation id="1746730358044914197">உள்ளீட்டு முறைகளை உங்கள் நிர்வாகி உள்ளமைத்துள்ளார்.</translation>
 <translation id="1747827819627189109">ஆன்ஸ்க்ரீன் கீபோர்டு இயக்கப்பட்டது</translation>
@@ -831,6 +832,7 @@
 <translation id="6578407462441924264">பெயரிடப்படாதது</translation>
 <translation id="6585808820553845416"><ph name="SESSION_TIME_REMAINING" /> இல் அமர்வு முடிந்துவிடும்.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">உங்கள் இணைப்பு மிகவும் பாதுகாப்பான நெட்வொர்க்கிற்கு மாற்றப்பட்டது</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, சிக்னல் வலிமை: <ph name="SIGNAL_STRENGTH" />, உங்கள் நிர்வாகி நிர்வகிக்கிறார்</translation>
 <translation id="6612802754306526077">ஸ்கிரீன் ரெக்கார்டிங் பயன்முறை தேர்ந்தெடுக்கப்பட்டது</translation>
 <translation id="6614169507485700968">தனிப்பட்ட திரை இயக்கப்பட்டுள்ளது</translation>
diff --git a/ash/strings/ash_strings_uk.xtb b/ash/strings/ash_strings_uk.xtb
index ef42aa9..69305f60 100644
--- a/ash/strings/ash_strings_uk.xtb
+++ b/ash/strings/ash_strings_uk.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">Живі субтитри ввімкнено.</translation>
 <translation id="1720011244392820496">Увімкніть синхронізацію Wi-Fi</translation>
+<translation id="1736898441010944794">Пристрої з Bluetooth можуть бачити <ph name="NAME" />.</translation>
 <translation id="1743570585616704562">Не розпізнано</translation>
 <translation id="1746730358044914197">Адміністратор налаштував методи введення.</translation>
 <translation id="1747827819627189109">Екранну клавіатуру ввімкнено</translation>
@@ -831,6 +832,7 @@
 <translation id="6578407462441924264">Без назви</translation>
 <translation id="6585808820553845416">Сеанс закінчиться через <ph name="SESSION_TIME_REMAINING" />.</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />, <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">Вас під’єднано до більш захищеної мережі</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />, рівень сигналу – <ph name="SIGNAL_STRENGTH" />. Мережею керує адміністратор</translation>
 <translation id="6612802754306526077">Вибрано режим запису екрана</translation>
 <translation id="6614169507485700968">Екран конфіденційності ввімкнено</translation>
diff --git a/ash/strings/ash_strings_ur.xtb b/ash/strings/ash_strings_ur.xtb
index 9ad0b5c..b060dcb5 100644
--- a/ash/strings/ash_strings_ur.xtb
+++ b/ash/strings/ash_strings_ur.xtb
@@ -122,6 +122,7 @@
 <translation id="1715874602234207">F</translation>
 <translation id="1719094688023114093">لائیو کیپشن آن ہے۔</translation>
 <translation id="1720011244392820496">‏Wi-Fi سِنک آن کریں</translation>
+<translation id="1736898441010944794">"<ph name="NAME" />" بلوٹوتھ آلات کے لیے مرئی ہے۔</translation>
 <translation id="1743570585616704562">تسلیم شدہ نہیں ہے</translation>
 <translation id="1746730358044914197">ان پٹ کے طریقے آپ کے منتظم کے ذریعے کنفیگر کئے جاتے ہیں۔</translation>
 <translation id="1747827819627189109">آن اسکرین کی بورڈ فعال ہے</translation>
@@ -830,6 +831,7 @@
 <translation id="6578407462441924264">بغیر نام والا</translation>
 <translation id="6585808820553845416">سیشن <ph name="SESSION_TIME_REMAINING" /> میں ختم ہو جائے گا۔</translation>
 <translation id="6593850935013518327"><ph name="PRIMARY_TEXT" />، <ph name="SECONDARY_TEXT" /></translation>
+<translation id="6602800870584047641">آپ کا کنکشن ایک مزید محفوظ نیٹ ورک پر سوئچ کر دیا گیا ہے</translation>
 <translation id="661203523074512333"><ph name="SECURITY_STATUS" />، سگنل کی مضبوطی <ph name="SIGNAL_STRENGTH" />، آپ کے منتظم کے زیر انتظام ہے</translation>
 <translation id="6612802754306526077">اسکرین ریکارڈنگ موڈ کا انتخاب کیا گیا</translation>
 <translation id="6614169507485700968">رازداری کی اسکرین آن ہے</translation>
diff --git a/ash/system/accessibility/select_to_speak/select_to_speak_menu_view.cc b/ash/system/accessibility/select_to_speak/select_to_speak_menu_view.cc
index 8e8d177..0e45b71 100644
--- a/ash/system/accessibility/select_to_speak/select_to_speak_menu_view.cc
+++ b/ash/system/accessibility/select_to_speak/select_to_speak_menu_view.cc
@@ -273,14 +273,14 @@
 
   switch (action) {
     case SelectToSpeakPanelAction::kPreviousParagraph:
-      FALLTHROUGH;
+      [[fallthrough]];
     case SelectToSpeakPanelAction::kNextParagraph:
       base::UmaHistogramEnumeration(
           kParagraphNavigationMethodHistogramName,
           CrosSelectToSpeakActivationMethod::kMenuButton);
       break;
     case SelectToSpeakPanelAction::kPreviousSentence:
-      FALLTHROUGH;
+      [[fallthrough]];
     case SelectToSpeakPanelAction::kNextSentence:
       base::UmaHistogramEnumeration(
           kSentenceNavigationMethodHistogramName,
diff --git a/ash/system/audio/audio_detailed_view.cc b/ash/system/audio/audio_detailed_view.cc
index d439af0c..cd71276 100644
--- a/ash/system/audio/audio_detailed_view.cc
+++ b/ash/system/audio/audio_detailed_view.cc
@@ -59,7 +59,7 @@
       return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_AUDIO_USB_DEVICE,
                                         base::UTF8ToUTF16(device.display_name));
     case AudioDeviceType::kBluetooth:
-      FALLTHROUGH;
+      [[fallthrough]];
     case AudioDeviceType::kBluetoothNbMic:
       return l10n_util::GetStringFUTF16(
           IDS_ASH_STATUS_TRAY_AUDIO_BLUETOOTH_DEVICE,
diff --git a/ash/system/message_center/ash_notification_view.cc b/ash/system/message_center/ash_notification_view.cc
index aca3bb1..f14b7f04 100644
--- a/ash/system/message_center/ash_notification_view.cc
+++ b/ash/system/message_center/ash_notification_view.cc
@@ -31,6 +31,7 @@
 #include "ui/gfx/font.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/rounded_corners_f.h"
+#include "ui/gfx/geometry/transform.h"
 #include "ui/gfx/image/image_skia_operations.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/gfx/scoped_canvas.h"
@@ -43,6 +44,7 @@
 #include "ui/message_center/views/notification_control_buttons_view.h"
 #include "ui/message_center/views/notification_header_view.h"
 #include "ui/message_center/views/notification_view_base.h"
+#include "ui/message_center/views/proportional_image_view.h"
 #include "ui/message_center/views/relative_time_formatter.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/background.h"
@@ -161,6 +163,30 @@
                     .SetTextStyle(views::style::STYLE_SECONDARY));
 }
 
+// Perform a scale and translate animation by scale from (scale_value_x,
+// scalue_value_y) and translate from (translate_value_x, translate_value_y) to
+// its correct scale and position.
+void ScaleAndTranslateView(views::View* view,
+                           SkScalar scale_value_x,
+                           SkScalar scale_value_y,
+                           SkScalar translate_value_x,
+                           SkScalar translate_value_y) {
+  gfx::Transform transform;
+  transform.Translate(translate_value_x, translate_value_y);
+  transform.Scale(scale_value_x, scale_value_y);
+
+  views::AnimationBuilder()
+      .SetPreemptionStrategy(
+          ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET)
+      .Once()
+      .SetDuration(base::TimeDelta())
+      .SetTransform(view, transform)
+      .Then()
+      .SetDuration(
+          base::Milliseconds(ash::kLargeImageScaleAndTranslateDurationMs))
+      .SetTransform(view, gfx::Transform(), gfx::Tween::ACCEL_0_100_DECEL_80);
+}
+
 }  // namespace
 
 namespace ash {
@@ -1026,11 +1052,6 @@
 }
 
 void AshNotificationView::PerformExpandCollapseAnimation() {
-  // Ensure layout is up-to-date before animating views.
-  if (needs_layout())
-    Layout();
-  DCHECK(!needs_layout());
-
   if (title_row_)
     title_row_->PerformExpandCollapseAnimation();
 
@@ -1041,28 +1062,129 @@
                                      kHeaderRowFadeInAnimationDurationMs);
   }
 
-  // Fade in `message_view()`.
-  if (message_view()) {
+  // Fade in `message_view()`. We only do fade in for both message view in
+  // expanded and collapsed mode if there's a difference between them (a.k.a
+  // when `message_view()` is truncated).
+  if (message_view()->GetVisible() &&
+      message_view()->IsDisplayTextTruncated()) {
     message_center_utils::FadeInView(message_view(),
                                      kMessageViewFadeInAnimationDelayMs,
                                      kMessageViewFadeInAnimationDurationMs);
   }
 
   // Fade in `message_view_in_expanded_state_`.
-  if (message_view_in_expanded_state_->GetVisible()) {
+  if (message_view_in_expanded_state_->GetVisible() &&
+      message_view()->IsDisplayTextTruncated()) {
     message_center_utils::FadeInView(
         message_view_in_expanded_state_,
         kMessageViewInExpandedStateFadeInAnimationDelayMs,
         kMessageViewInExpandedStateFadeInAnimationDurationMs);
   }
 
-  expand_button_->PerformExpandCollapseAnimation();
+  if (!image_container_view()->children().empty()) {
+    PerformLargeImageAnimation();
+  }
 
   if (actions_row()->GetVisible()) {
     message_center_utils::FadeInView(actions_row(),
                                      kActionsRowFadeInAnimationDelayMs,
                                      kActionsRowFadeInAnimationDurationMs);
   }
+
+  if (total_grouped_notifications_) {
+    // Ensure layout is up-to-date before animating expand button. This is used
+    // for its bounds animation.
+    if (needs_layout())
+      Layout();
+    DCHECK(!needs_layout());
+
+    expand_button_->PerformExpandCollapseAnimation();
+  }
+}
+
+void AshNotificationView::PerformLargeImageAnimation() {
+  message_center_utils::InitLayerForAnimations(image_container_view());
+  message_center_utils::InitLayerForAnimations(icon_view());
+  auto icon_view_bounds = icon_view()->GetBoundsInScreen();
+  auto large_image_bounds = image_container_view()->GetBoundsInScreen();
+
+  if (IsExpanded()) {
+    // In expanded state, do a scale and translate from `icon_view()` to
+    // `image_container_view()`.
+    message_center_utils::InitLayerForAnimations(image_container_view());
+    ScaleAndTranslateView(image_container_view(),
+                          static_cast<double>(icon_view()->width()) /
+                              image_container_view()->width(),
+                          static_cast<double>(icon_view()->height()) /
+                              image_container_view()->height(),
+                          icon_view_bounds.x() - large_image_bounds.x(),
+                          icon_view_bounds.y() - large_image_bounds.y());
+
+    // If we a different image for `icon_view()` and `image_container_view()`
+    // (a.k.a hide_icon_on_expanded() is false), fade in
+    // `image_container_view()`.
+    if (!hide_icon_on_expanded()) {
+      message_center_utils::FadeInView(image_container_view(),
+                                       kLargeImageFadeInAnimationDelayMs,
+                                       kLargeImageFadeInAnimationDurationMs);
+    }
+    return;
+  }
+
+  if (hide_icon_on_expanded()) {
+    // In collapsed state, if we use a same image for `icon_view()` and
+    // `image_container_view()`, perform a scale and translate from
+    // `image_container_view()` to `icon_view()`.
+    ScaleAndTranslateView(
+        icon_view(),
+        static_cast<double>(image_container_view()->width()) /
+            icon_view()->width(),
+        static_cast<double>(image_container_view()->height()) /
+            icon_view()->height(),
+        large_image_bounds.x() - icon_view_bounds.x(),
+        large_image_bounds.y() - icon_view_bounds.y());
+    return;
+  }
+
+  // In collapsed state, if we use a different image for `icon_view()` and
+  // `image_container_view()`, fade out and scale down `image_container_view()`.
+  message_center_utils::FadeOutView(
+      image_container_view(),
+      base::BindRepeating(
+          [](base::WeakPtr<ash::AshNotificationView> parent,
+             views::View* image_container_view) {
+            if (parent) {
+              image_container_view->layer()->SetOpacity(1.0f);
+              //
+              image_container_view->layer()->SetTransform(gfx::Transform());
+              image_container_view->SetVisible(false);
+            }
+          },
+          weak_factory_.GetWeakPtr(), image_container_view()),
+      kLargeImageFadeOutAnimationDelayMs, kLargeImageFadeOutAnimationDurationMs,
+      gfx::Tween::ACCEL_20_DECEL_100);
+
+  gfx::Transform transform;
+  // Translate y further down so that it would not interfere with the currently
+  // shown `icon_view()`.
+  transform.Translate((icon_view_bounds.x() - large_image_bounds.x()),
+                      (icon_view_bounds.y() - large_image_bounds.y() +
+                       large_image_bounds.height()));
+  transform.Scale(static_cast<double>(icon_view()->width()) /
+                      image_container_view()->width(),
+                  static_cast<double>(icon_view()->height()) /
+                      image_container_view()->height());
+
+  views::AnimationBuilder()
+      .SetPreemptionStrategy(
+          ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET)
+      .Once()
+      .At(base::TimeDelta())
+      .SetTransform(image_container_view(), gfx::Transform())
+      .Then()
+      .SetDuration(base::Milliseconds(kLargeImageScaleDownDurationMs))
+      .SetTransform(image_container_view(), transform,
+                    gfx::Tween::ACCEL_20_DECEL_100);
 }
 
 }  // namespace ash
diff --git a/ash/system/message_center/ash_notification_view.h b/ash/system/message_center/ash_notification_view.h
index 3597dfe8..7a4dd33 100644
--- a/ash/system/message_center/ash_notification_view.h
+++ b/ash/system/message_center/ash_notification_view.h
@@ -164,6 +164,9 @@
   // ChildPreferredSizeChange(). Child views are animated here.
   void PerformExpandCollapseAnimation();
 
+  // Expand/collapse animation for large image within `image_container_view()`.
+  void PerformLargeImageAnimation();
+
   // Owned by views hierarchy.
   RoundedImageView* app_icon_view_ = nullptr;
   AshNotificationExpandButton* expand_button_ = nullptr;
diff --git a/ash/system/message_center/message_center_constants.h b/ash/system/message_center/message_center_constants.h
index 72c19a78..266a199 100644
--- a/ash/system/message_center/message_center_constants.h
+++ b/ash/system/message_center/message_center_constants.h
@@ -68,6 +68,12 @@
 constexpr int kActionButtonsFadeOutAnimationDurationMs = 100;
 constexpr int kInlineReplyFadeInAnimationDurationMs = 100;
 constexpr int kInlineReplyFadeOutAnimationDurationMs = 50;
+constexpr int kLargeImageFadeInAnimationDelayMs = 50;
+constexpr int kLargeImageFadeInAnimationDurationMs = 50;
+constexpr int kLargeImageFadeOutAnimationDelayMs = 50;
+constexpr int kLargeImageFadeOutAnimationDurationMs = 100;
+constexpr int kLargeImageScaleAndTranslateDurationMs = 250;
+constexpr int kLargeImageScaleDownDurationMs = 150;
 
 constexpr int kCollapsedSummaryViewAnimationDurationMs = 50;
 constexpr int kChildMainViewFadeInAnimationDurationMs = 100;
diff --git a/ash/system/phonehub/enable_hotspot_quick_action_controller.cc b/ash/system/phonehub/enable_hotspot_quick_action_controller.cc
index 763c1140..de170f3 100644
--- a/ash/system/phonehub/enable_hotspot_quick_action_controller.cc
+++ b/ash/system/phonehub/enable_hotspot_quick_action_controller.cc
@@ -50,7 +50,7 @@
       item_->SetVisible(false);
       return;
     case Status::kConnectionUnavailable:
-      FALLTHROUGH;
+      [[fallthrough]];
     case Status::kConnectionAvailable:
       SetState(ActionState::kOff);
       break;
diff --git a/ash/system/phonehub/phone_hub_ui_controller.cc b/ash/system/phonehub/phone_hub_ui_controller.cc
index 519f5495..8ebd7083 100644
--- a/ash/system/phonehub/phone_hub_ui_controller.cc
+++ b/ash/system/phonehub/phone_hub_ui_controller.cc
@@ -183,7 +183,7 @@
 
   switch (feature_status) {
     case FeatureStatus::kPhoneSelectedAndPendingSetup:
-      FALLTHROUGH;
+      [[fallthrough]];
     case FeatureStatus::kNotEligibleForFeature:
       return UiState::kHidden;
 
diff --git a/ash/webui/camera_app_ui/resources/js/device/stream_constraints.js b/ash/webui/camera_app_ui/resources/js/device/stream_constraints.js
deleted file mode 100644
index 4976c9e6..0000000
--- a/ash/webui/camera_app_ui/resources/js/device/stream_constraints.js
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2021 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.
-
-/**
- * Stream constraints for audio and video.
- * @record
- */
-export class StreamConstraints {
-  /**
-   * @public
-   */
-  constructor() {
-    /**
-     * @type {string} Target device id.
-     */
-    this.deviceId;
-
-    /**
-     * @type {!MediaTrackConstraints} Extra video constraints.
-     */
-    this.video;
-
-    /**
-     * @type {boolean} Whether to enable audio.
-     */
-    this.audio;
-  }
-}
-
-/**
- * Convert this to MediaStreamConstraints that is suitable to be used in
- * getUserMedia.
- *
- * @param {!StreamConstraints} constraints
- * @return {!MediaStreamConstraints}
- */
-export function toMediaStreamConstraints(constraints) {
-  return {
-    audio: constraints.audio ? {echoCancellation: false} : false,
-    video: {...constraints.video, deviceId: {exact: constraints.deviceId}},
-  };
-}
diff --git a/ash/webui/camera_app_ui/resources/js/device/stream_constraints.ts b/ash/webui/camera_app_ui/resources/js/device/stream_constraints.ts
new file mode 100644
index 0000000..9afe6aef
--- /dev/null
+++ b/ash/webui/camera_app_ui/resources/js/device/stream_constraints.ts
@@ -0,0 +1,35 @@
+// Copyright 2021 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.
+
+/**
+ * Stream constraints for audio and video.
+ */
+export interface StreamConstraints {
+  /**
+   * Target device id.
+   */
+  deviceId: string;
+
+  /**
+   * Extra video constraints.
+   */
+  video: MediaTrackConstraints;
+
+  /**
+   * Whether to enable audio.
+   */
+  audio: boolean;
+}
+
+/**
+ * Convert this to MediaStreamConstraints that is suitable to be used in
+ * getUserMedia.
+ */
+export function toMediaStreamConstraints(constraints: StreamConstraints):
+    MediaStreamConstraints {
+  return {
+    audio: constraints.audio ? {echoCancellation: false} : false,
+    video: {...constraints.video, deviceId: {exact: constraints.deviceId}},
+  };
+}
diff --git a/ash/webui/camera_app_ui/resources/js/device/stream_manager.js b/ash/webui/camera_app_ui/resources/js/device/stream_manager.js
deleted file mode 100644
index 7cc9576c..0000000
--- a/ash/webui/camera_app_ui/resources/js/device/stream_manager.js
+++ /dev/null
@@ -1,336 +0,0 @@
-// Copyright 2021 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 '../assert.js';
-import {reportError} from '../error.js';
-import {I18nString} from '../i18n_string.js';
-import * as loadTimeData from '../models/load_time_data.js';
-import {DeviceOperator} from '../mojo/device_operator.js';
-import * as toast from '../toast.js';
-// eslint-disable-next-line no-unused-vars
-import {ErrorLevel, ErrorType, Facing, VideoConfig} from '../type.js';
-import {WaitableEvent} from '../waitable_event.js';
-
-import {Camera3DeviceInfo} from './camera3_device_info.js';
-import {
-  StreamConstraints,  // eslint-disable-line no-unused-vars
-  toMediaStreamConstraints,
-} from './stream_constraints.js';
-
-/**
- * The singleton instance of StreamManager. Initialized by the first
- * invocation of getInstance().
- * @type {?StreamManager}
- */
-let instance = null;
-
-/**
- * Device information includs MediaDeviceInfo and Camera3DeviceInfo.
- * @typedef {{
- *   v1Info: !MediaDeviceInfo,
- *   v3Info: ?Camera3DeviceInfo
- * }}
- */
-export let DeviceInfo;
-
-/**
- * Real and virtual device mapping.
- * @typedef {{
- *   realId: string,
- *   virtualId: string
- * }}
- */
-// eslint-disable-next-line no-unused-vars
-let VirtualMap;
-
-/**
- * Monitors device change and provides different listener callbacks for
- * device changes. It also provides streams for different modes.
- */
-export class StreamManager {
-  /**
-   * @private
-   */
-  constructor() {
-    /**
-     * MediaDeviceInfo of all available video devices.
-     * @type {?Promise<!Array<!MediaDeviceInfo>>}
-     * @private
-     */
-    this.devicesInfo_ = null;
-
-    /**
-     * Camera3DeviceInfo of all available video devices. Is null on HALv1 device
-     * without mojo api support.
-     * @type {?Promise<?Array<!DeviceInfo>>}
-     * @private
-     */
-    this.camera3DevicesInfo_ = null;
-
-    /**
-     * Listeners for real device change event.
-     * @type {!Array<function(!Array<!DeviceInfo>): !Promise>}
-     * @private
-     */
-    this.realListeners_ = [];
-
-    /**
-     * Latest result of Camera3DeviceInfo of all real video devices.
-     * @type {!Array<!DeviceInfo>}
-     * @private
-     */
-    this.realDevices_ = [];
-
-    /**
-     * real device id and corresponding virtual devices id mapping and it is
-     * only available on HALv3.
-     * @type {?VirtualMap}
-     * @private
-     */
-    this.virtualMap_ = null;
-
-    /**
-     * Signal it to indicate that the virtual device is ready.
-     * @type {?WaitableEvent<string>}
-     * @private
-     */
-    this.waitVirtual_ = null;
-
-    /**
-     * Signal to indicate that the virtual device is successfully removed.
-     * @type {?WaitableEvent}
-     * @private
-     */
-    this.waitVirtualRemoved_ = null;
-
-    /**
-     * Filter out lagging 720p on grunt. See https://crbug.com/1122852.
-     * @const {!Promise<function(!VideoConfig): boolean>}
-     * @private
-     */
-    this.videoConfigFilter_ = (async () => {
-      const board = await loadTimeData.getBoard();
-      return board === 'grunt' ? ({height}) => height < 720 : () => true;
-    })();
-
-    navigator.mediaDevices.addEventListener(
-        'devicechange', () => this.deviceUpdate());
-  }
-
-  /**
-   * Creates a new instance of StreamManager if it is not set. Returns the
-   *     exist instance.
-   * @return {!StreamManager} The singleton instance.
-   */
-  static getInstance() {
-    if (instance === null) {
-      instance = new StreamManager();
-    }
-    return instance;
-  }
-
-  /**
-   * Registers listener to be called when state of available real devices
-   * changes.
-   * @param {function(!Array<!DeviceInfo>): !Promise} listener
-   */
-  addRealDeviceChangeListener(listener) {
-    this.realListeners_.push(listener);
-  }
-
-  /**
-   * Creates extra stream according to the constraints.
-   * @param {!StreamConstraints} constraints
-   * @return {!Promise<!MediaStream>}
-   */
-  async openCaptureStream(constraints) {
-    const realDeviceId = constraints.deviceId;
-    if (await DeviceOperator.isSupported()) {
-      try {
-        await this.setMultipleStreamsEnabled(realDeviceId, true);
-        constraints.deviceId = this.virtualMap_.virtualId;
-      } catch (e) {
-        reportError(ErrorType.MULTIPLE_STREAMS_FAILURE, ErrorLevel.ERROR, e);
-      }
-    }
-
-    const stream = await navigator.mediaDevices.getUserMedia(
-        toMediaStreamConstraints(constraints));
-    return stream;
-  }
-
-  /**
-   * Closes the given capture stream.
-   * @param {!MediaStream} captureStream
-   * @return {!Promise}
-   */
-  async closeCaptureStream(captureStream) {
-    captureStream.getVideoTracks()[0].stop();
-    const deviceOperator = await DeviceOperator.getInstance();
-    if (deviceOperator !== null) {
-      // We need to cache |virtualId| first since it will be wiped out after
-      // disabling multi-stream.
-      const virtualId = this.virtualMap_.virtualId;
-      try {
-        await this.setMultipleStreamsEnabled(this.virtualMap_.realId, false);
-      } catch (e) {
-        reportError(ErrorType.MULTIPLE_STREAMS_FAILURE, ErrorLevel.ERROR, e);
-      }
-      await deviceOperator.dropConnection(virtualId);
-    }
-  }
-
-  /**
-   * Handling function for device changing.
-   */
-  async deviceUpdate() {
-    const devices = await this.doDeviceInfoUpdate_();
-    if (devices === null) {
-      return;
-    }
-    await this.doDeviceNotify_(devices);
-  }
-
-  /**
-   * Gets devices information via mojo IPC.
-   * @return {?Promise<?Array<!DeviceInfo>>}
-   * @private
-   */
-  async doDeviceInfoUpdate_() {
-    this.devicesInfo_ = this.enumerateDevices_();
-    this.camera3DevicesInfo_ = this.queryMojoDevicesInfo_();
-    try {
-      return await this.camera3DevicesInfo_;
-    } catch (e) {
-      reportError(ErrorType.DEVICE_INFO_UPDATE_FAILURE, ErrorLevel.ERROR, e);
-    }
-    return null;
-  }
-
-  /**
-   * Notifies device changes to listeners and create a mapping for real and
-   * virtual device.
-   * @param {!Array<!DeviceInfo>} devices
-   * @private
-   */
-  async doDeviceNotify_(devices) {
-    const isVirtual = (d) => d.v3Info !== null &&
-        (d.v3Info.facing === Facing.VIRTUAL_USER ||
-         d.v3Info.facing === Facing.VIRTUAL_ENV ||
-         d.v3Info.facing === Facing.VIRTUAL_EXT);
-    const realDevices = devices.filter((d) => !isVirtual(d));
-    const virtualDevices = devices.filter(isVirtual);
-    // We currently only support one virtual device.
-    assert(virtualDevices.length <= 1);
-
-    if (virtualDevices.length === 1 && this.waitVirtual_ !== null) {
-      this.waitVirtual_.signal(virtualDevices[0].v1Info.deviceId);
-      this.waitVirtual_ = null;
-    }
-
-    if (virtualDevices.length === 0 && this.waitVirtualRemoved_ !== null) {
-      this.waitVirtualRemoved_.signal();
-      this.waitVirtualRemoved_ = null;
-    }
-
-    let isRealDeviceChange = false;
-    for (const added of this.getDifference_(realDevices, this.realDevices_)) {
-      toast.speak(I18nString.STATUS_MSG_CAMERA_PLUGGED, added.v1Info.label);
-      isRealDeviceChange = true;
-    }
-    for (const removed of this.getDifference_(this.realDevices_, realDevices)) {
-      toast.speak(I18nString.STATUS_MSG_CAMERA_UNPLUGGED, removed.v1Info.label);
-      isRealDeviceChange = true;
-    }
-    if (isRealDeviceChange) {
-      this.realListeners_.map((l) => l(realDevices));
-    }
-    this.realDevices_ = realDevices;
-  }
-
-  /**
-   * Computes |devices| - |devices2|.
-   * @param {!Array<!DeviceInfo>} devices
-   * @param {!Array<!DeviceInfo>} devices2
-   * @return {!Array<!DeviceInfo>}
-   */
-  getDifference_(devices, devices2) {
-    const ids = new Set(devices2.map((d) => d.v1Info.deviceId));
-    return devices.filter((d) => !ids.has(d.v1Info.deviceId));
-  }
-
-  /**
-   * Enumerates all available devices and gets their MediaDeviceInfo.
-   * @return {!Promise<!Array<!MediaDeviceInfo>>}
-   * @throws {!Error}
-   * @private
-   */
-  async enumerateDevices_() {
-    const devices = (await navigator.mediaDevices.enumerateDevices())
-                        .filter((device) => device.kind === 'videoinput');
-
-    const deviceType = loadTimeData.getDeviceType();
-    const shouldHaveBuiltinCamera =
-        deviceType === 'chromebook' || deviceType === 'chromebase';
-    if (devices.length === 0 && shouldHaveBuiltinCamera) {
-      throw new Error('Device list empty.');
-    }
-    return devices;
-  }
-
-  /**
-   * Queries Camera3DeviceInfo of available devices through private mojo API.
-   * @return {!Promise<?Array<!DeviceInfo>>} Camera3DeviceInfo of available
-   *     devices. Maybe null on HALv1 devices without supporting private mojo
-   *     api.
-   * @throws {!Error} Thrown when camera unplugging happens between enumerating
-   *     devices and querying mojo APIs with current device info results.
-   * @private
-   */
-  async queryMojoDevicesInfo_() {
-    const deviceInfos = await this.devicesInfo_;
-    const videoConfigFilter = await this.videoConfigFilter_;
-    const isV3Supported = await DeviceOperator.isSupported();
-    return Promise.all(deviceInfos.map(
-        async (d) => ({
-          v1Info: d,
-          v3Info: isV3Supported ?
-              (await Camera3DeviceInfo.create(d, videoConfigFilter)) :
-              null,
-        })));
-  }
-
-  /**
-   * Enables/Disables multiple streams on target camera device. The extra
-   * stream will be reported as virtual video device from
-   * navigator.mediaDevices.enumerateDevices().
-   * @param {string} deviceId The id of target camera device.
-   * @param {boolean} enabled True for eanbling multiple streams.
-   */
-  async setMultipleStreamsEnabled(deviceId, enabled) {
-    assert(await DeviceOperator.isSupported());
-    const deviceOperator = await DeviceOperator.getInstance();
-
-    if (enabled) {
-      /** @type {WaitableEvent<string>} */
-      const waitEvent = new WaitableEvent();
-      this.waitVirtual_ = waitEvent;
-
-      await deviceOperator.setMultipleStreamsEnabled(deviceId, enabled);
-      await this.deviceUpdate();
-
-      const virtualId = await waitEvent.timedWait(3000);
-      this.virtualMap_ = {realId: deviceId, virtualId};
-    } else {
-      const waitEvent = new WaitableEvent();
-      this.waitVirtualRemoved_ = waitEvent;
-
-      await deviceOperator.setMultipleStreamsEnabled(deviceId, enabled);
-      await this.deviceUpdate();
-
-      await waitEvent.timedWait(3000);
-      this.virtualMap_ = null;
-    }
-  }
-}
diff --git a/ash/webui/camera_app_ui/resources/js/device/stream_manager.ts b/ash/webui/camera_app_ui/resources/js/device/stream_manager.ts
new file mode 100644
index 0000000..7896538
--- /dev/null
+++ b/ash/webui/camera_app_ui/resources/js/device/stream_manager.ts
@@ -0,0 +1,300 @@
+// Copyright 2021 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 '../assert.js';
+import {reportError} from '../error.js';
+import {I18nString} from '../i18n_string.js';
+import * as loadTimeData from '../models/load_time_data.js';
+import {DeviceOperator} from '../mojo/device_operator.js';
+import * as toast from '../toast.js';
+import {ErrorLevel, ErrorType, Facing, VideoConfig} from '../type.js';
+import {WaitableEvent} from '../waitable_event.js';
+
+import {Camera3DeviceInfo} from './camera3_device_info.js';
+import {
+  StreamConstraints,
+  toMediaStreamConstraints,
+} from './stream_constraints.js';
+
+/**
+ * The singleton instance of StreamManager. Initialized by the first
+ * invocation of getInstance().
+ */
+let instance: StreamManager|null = null;
+
+/**
+ * Device information includs MediaDeviceInfo and Camera3DeviceInfo.
+ */
+export interface DeviceInfo {
+  v1Info: MediaDeviceInfo;
+  v3Info: Camera3DeviceInfo|null;
+}
+
+/**
+ * Real and virtual device mapping.
+ */
+interface VirtualMap {
+  realId: string;
+  virtualId: string;
+}
+
+/**
+ * Monitors device change and provides different listener callbacks for
+ * device changes. It also provides streams for different modes.
+ */
+export class StreamManager {
+  /**
+   * MediaDeviceInfo of all available video devices.
+   */
+  private devicesInfo: Promise<MediaDeviceInfo[]>|null = null;
+
+  /**
+   * Camera3DeviceInfo of all available video devices. Is null on HALv1 device
+   * without mojo api support.
+   */
+  private camera3DevicesInfo: Promise<DeviceInfo[]|null>|null = null;
+
+  /**
+   * Listeners for real device change event.
+   */
+  private readonly realListeners:
+      Array<(devices: DeviceInfo[]) => Promise<void>> = [];
+
+  /**
+   * Latest result of Camera3DeviceInfo of all real video devices.
+   */
+  private realDevices: DeviceInfo[] = [];
+
+  /**
+   * real device id and corresponding virtual devices id mapping and it is
+   * only available on HALv3.
+   */
+  private virtualMap: VirtualMap|null = null;
+
+  /**
+   * Signal it to indicate that the virtual device is ready.
+   */
+  private waitVirtual: WaitableEvent<string>|null = null;
+
+  /**
+   * Signal to indicate that the virtual device is successfully removed.
+   */
+  private waitVirtualRemoved: WaitableEvent|null = null;
+
+  /**
+   * Filter out lagging 720p on grunt. See https://crbug.com/1122852.
+   */
+  private videoConfigFilter: (config: VideoConfig) => boolean;
+
+  private constructor() {
+    this.videoConfigFilter = (() => {
+      const board = loadTimeData.getBoard();
+      return board === 'grunt' ? ({height}) => height < 720 : () => true;
+    })();
+
+    navigator.mediaDevices.addEventListener(
+        'devicechange', () => this.deviceUpdate());
+  }
+
+  /**
+   * Creates a new instance of StreamManager if it is not set. Returns the
+   *     exist instance.
+   * @return The singleton instance.
+   */
+  static getInstance(): StreamManager {
+    if (instance === null) {
+      instance = new StreamManager();
+    }
+    return instance;
+  }
+
+  /**
+   * Registers listener to be called when state of available real devices
+   * changes.
+   */
+  addRealDeviceChangeListener(
+      listener: (devices: DeviceInfo[]) => Promise<void>): void {
+    this.realListeners.push(listener);
+  }
+
+  /**
+   * Creates extra stream according to the constraints.
+   */
+  async openCaptureStream(constraints: StreamConstraints):
+      Promise<MediaStream> {
+    const realDeviceId = constraints.deviceId;
+    if (await DeviceOperator.isSupported()) {
+      try {
+        await this.setMultipleStreamsEnabled(realDeviceId, true);
+        constraints.deviceId = this.virtualMap.virtualId;
+      } catch (e) {
+        reportError(ErrorType.MULTIPLE_STREAMS_FAILURE, ErrorLevel.ERROR, e);
+      }
+    }
+
+    const stream = await navigator.mediaDevices.getUserMedia(
+        toMediaStreamConstraints(constraints));
+    return stream;
+  }
+
+  /**
+   * Closes the given capture stream.
+   */
+  async closeCaptureStream(captureStream: MediaStream): Promise<void> {
+    captureStream.getVideoTracks()[0].stop();
+    const deviceOperator = await DeviceOperator.getInstance();
+    if (deviceOperator !== null) {
+      // We need to cache |virtualId| first since it will be wiped out after
+      // disabling multi-stream.
+      const virtualId = this.virtualMap.virtualId;
+      try {
+        await this.setMultipleStreamsEnabled(this.virtualMap.realId, false);
+      } catch (e) {
+        reportError(ErrorType.MULTIPLE_STREAMS_FAILURE, ErrorLevel.ERROR, e);
+      }
+      await deviceOperator.dropConnection(virtualId);
+    }
+  }
+
+  /**
+   * Handling function for device changing.
+   */
+  async deviceUpdate(): Promise<void> {
+    const devices = await this.doDeviceInfoUpdate();
+    if (devices === null) {
+      return;
+    }
+    await this.doDeviceNotify(devices);
+  }
+
+  /**
+   * Gets devices information via mojo IPC.
+   */
+  private async doDeviceInfoUpdate(): Promise<DeviceInfo[]|null>|null {
+    this.devicesInfo = this.enumerateDevices();
+    this.camera3DevicesInfo = this.queryMojoDevicesInfo();
+    try {
+      return await this.camera3DevicesInfo;
+    } catch (e) {
+      reportError(ErrorType.DEVICE_INFO_UPDATE_FAILURE, ErrorLevel.ERROR, e);
+    }
+    return null;
+  }
+
+  /**
+   * Notifies device changes to listeners and create a mapping for real and
+   * virtual device.
+   */
+  private async doDeviceNotify(devices: DeviceInfo[]) {
+    const isVirtual = (d) => d.v3Info !== null &&
+        (d.v3Info.facing === Facing.VIRTUAL_USER ||
+         d.v3Info.facing === Facing.VIRTUAL_ENV ||
+         d.v3Info.facing === Facing.VIRTUAL_EXT);
+    const realDevices = devices.filter((d) => !isVirtual(d));
+    const virtualDevices = devices.filter(isVirtual);
+    // We currently only support one virtual device.
+    assert(virtualDevices.length <= 1);
+
+    if (virtualDevices.length === 1 && this.waitVirtual !== null) {
+      this.waitVirtual.signal(virtualDevices[0].v1Info.deviceId);
+      this.waitVirtual = null;
+    }
+
+    if (virtualDevices.length === 0 && this.waitVirtualRemoved !== null) {
+      this.waitVirtualRemoved.signal();
+      this.waitVirtualRemoved = null;
+    }
+
+    let isRealDeviceChange = false;
+    for (const added of this.getDifference(realDevices, this.realDevices)) {
+      toast.speak(I18nString.STATUS_MSG_CAMERA_PLUGGED, added.v1Info.label);
+      isRealDeviceChange = true;
+    }
+    for (const removed of this.getDifference(this.realDevices, realDevices)) {
+      toast.speak(I18nString.STATUS_MSG_CAMERA_UNPLUGGED, removed.v1Info.label);
+      isRealDeviceChange = true;
+    }
+    if (isRealDeviceChange) {
+      this.realListeners.map((l) => l(realDevices));
+    }
+    this.realDevices = realDevices;
+  }
+
+  /**
+   * Computes |devices| - |devices2|.
+   */
+  private getDifference(devices: DeviceInfo[], devices2: DeviceInfo[]):
+      DeviceInfo[] {
+    const ids = new Set(devices2.map((d) => d.v1Info.deviceId));
+    return devices.filter((d) => !ids.has(d.v1Info.deviceId));
+  }
+
+  /**
+   * Enumerates all available devices and gets their MediaDeviceInfo.
+   */
+  private async enumerateDevices(): Promise<MediaDeviceInfo[]> {
+    const devices = (await navigator.mediaDevices.enumerateDevices())
+                        .filter((device) => device.kind === 'videoinput');
+
+    const deviceType = loadTimeData.getDeviceType();
+    const shouldHaveBuiltinCamera =
+        deviceType === 'chromebook' || deviceType === 'chromebase';
+    if (devices.length === 0 && shouldHaveBuiltinCamera) {
+      throw new Error('Device list empty.');
+    }
+    return devices;
+  }
+
+  /**
+   * Queries Camera3DeviceInfo of available devices through private mojo API.
+   * @return Camera3DeviceInfo of available devices. Maybe null on HALv1
+   *     devices without supporting private mojo api.
+   * @throws Thrown when camera unplugging happens between enumerating devices
+   *     and querying mojo APIs with current device info results.
+   */
+  private async queryMojoDevicesInfo(): Promise<DeviceInfo[]|null> {
+    const deviceInfos = await this.devicesInfo;
+    const isV3Supported = await DeviceOperator.isSupported();
+    return Promise.all(deviceInfos.map(
+        async (d) => ({
+          v1Info: d,
+          v3Info: isV3Supported ?
+              (await Camera3DeviceInfo.create(d, this.videoConfigFilter)) :
+              null,
+        })));
+  }
+
+  /**
+   * Enables/Disables multiple streams on target camera device. The extra
+   * stream will be reported as virtual video device from
+   * navigator.mediaDevices.enumerateDevices().
+   * @param deviceId The id of target camera device.
+   * @param enabled True for eanbling multiple streams.
+   */
+  async setMultipleStreamsEnabled(deviceId: string, enabled: boolean):
+      Promise<void> {
+    assert(await DeviceOperator.isSupported());
+    const deviceOperator = await DeviceOperator.getInstance();
+
+    if (enabled) {
+      const waitEvent = new WaitableEvent<string>();
+      this.waitVirtual = waitEvent;
+
+      await deviceOperator.setMultipleStreamsEnabled(deviceId, enabled);
+      await this.deviceUpdate();
+
+      const virtualId = await waitEvent.timedWait(3000);
+      this.virtualMap = {realId: deviceId, virtualId};
+    } else {
+      const waitEvent = new WaitableEvent();
+      this.waitVirtualRemoved = waitEvent;
+
+      await deviceOperator.setMultipleStreamsEnabled(deviceId, enabled);
+      await this.deviceUpdate();
+
+      await waitEvent.timedWait(3000);
+      this.virtualMap = null;
+    }
+  }
+}
diff --git a/ash/webui/camera_app_ui/resources/js/js.gni b/ash/webui/camera_app_ui/resources/js/js.gni
index d336b5d..123e9e0 100644
--- a/ash/webui/camera_app_ui/resources/js/js.gni
+++ b/ash/webui/camera_app_ui/resources/js/js.gni
@@ -12,8 +12,8 @@
   "device/camera3_device_info.ts",
   "device/constraints_preferrer.js",
   "device/device_info_updater.ts",
-  "device/stream_constraints.js",
-  "device/stream_manager.js",
+  "device/stream_constraints.ts",
+  "device/stream_manager.ts",
   "dom.ts",
   "error.ts",
   "expert.ts",
diff --git a/ash/webui/shimless_rma/backend/shimless_rma_service.cc b/ash/webui/shimless_rma/backend/shimless_rma_service.cc
index 4cb853a75..c61903a 100644
--- a/ash/webui/shimless_rma/backend/shimless_rma_service.cc
+++ b/ash/webui/shimless_rma/backend/shimless_rma_service.cc
@@ -592,6 +592,7 @@
     const std::string& serial_number,
     uint8_t region_index,
     uint8_t sku_index,
+    uint8_t white_label_index,
     SetDeviceInformationCallback callback) {
   if (state_proto_.state_case() != rmad::RmadState::kUpdateDeviceInfo) {
     LOG(ERROR) << "SetDeviceInformation called from incorrect state "
@@ -604,6 +605,8 @@
   state_proto_.mutable_update_device_info()->set_serial_number(serial_number);
   state_proto_.mutable_update_device_info()->set_region_index(region_index);
   state_proto_.mutable_update_device_info()->set_sku_index(sku_index);
+  state_proto_.mutable_update_device_info()->set_whitelabel_index(
+      white_label_index);
   TransitionNextStateGeneric(std::move(callback));
 }
 
@@ -727,6 +730,20 @@
   TransitionNextStateGeneric(std::move(callback));
 }
 
+void ShimlessRmaService::RetryFinalization(RetryFinalizationCallback callback) {
+  if (state_proto_.state_case() != rmad::RmadState::kFinalize) {
+    LOG(ERROR) << "RetryFinalization called from incorrect state "
+               << state_proto_.state_case();
+    std::move(callback).Run(RmadStateToMojo(state_proto_.state_case()),
+                            can_abort_, can_go_back_,
+                            rmad::RmadErrorCode::RMAD_ERROR_REQUEST_INVALID);
+    return;
+  }
+  state_proto_.mutable_finalize()->set_choice(
+      rmad::FinalizeState::RMAD_FINALIZE_CHOICE_RETRY);
+  TransitionNextStateGeneric(std::move(callback));
+}
+
 void ShimlessRmaService::FinalizationComplete(
     FinalizationCompleteCallback callback) {
   if (state_proto_.state_case() != rmad::RmadState::kFinalize) {
diff --git a/ash/webui/shimless_rma/backend/shimless_rma_service.h b/ash/webui/shimless_rma/backend/shimless_rma_service.h
index cd3a9c0..890e4ce6 100644
--- a/ash/webui/shimless_rma/backend/shimless_rma_service.h
+++ b/ash/webui/shimless_rma/backend/shimless_rma_service.h
@@ -101,6 +101,7 @@
   void SetDeviceInformation(const std::string& serial_number,
                             uint8_t region_index,
                             uint8_t sku_index,
+                            uint8_t white_label_index,
                             SetDeviceInformationCallback callback) override;
 
   void GetCalibrationComponentList(
@@ -117,6 +118,7 @@
   void RetryProvisioning(RetryProvisioningCallback callback) override;
   void ProvisioningComplete(ProvisioningCompleteCallback callback) override;
 
+  void RetryFinalization(RetryFinalizationCallback callback) override;
   void FinalizationComplete(FinalizationCompleteCallback callback) override;
 
   void WriteProtectManuallyEnabled(
diff --git a/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc b/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc
index cd4613c..62ec3e9 100644
--- a/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc
+++ b/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc
@@ -1867,6 +1867,7 @@
         EXPECT_EQ(state.update_device_info().serial_number(), "serial number");
         EXPECT_EQ(state.update_device_info().region_index(), 1UL);
         EXPECT_EQ(state.update_device_info().sku_index(), 2UL);
+        EXPECT_EQ(state.update_device_info().whitelabel_index(), 3UL);
       });
   base::RunLoop run_loop;
   shimless_rma_provider_->GetCurrentState(base::BindLambdaForTesting(
@@ -1878,7 +1879,7 @@
   run_loop.RunUntilIdle();
 
   shimless_rma_provider_->SetDeviceInformation(
-      "serial number", 1, 2,
+      "serial number", 1, 2, 3,
       base::BindLambdaForTesting([&](mojom::State state, bool can_cancel,
                                      bool can_go_back,
                                      rmad::RmadErrorCode error) {
@@ -1903,7 +1904,7 @@
   run_loop.RunUntilIdle();
 
   shimless_rma_provider_->SetDeviceInformation(
-      "serial number", 1, 2,
+      "serial number", 1, 2, 3,
       base::BindLambdaForTesting([&](mojom::State state, bool can_cancel,
                                      bool can_go_back,
                                      rmad::RmadErrorCode error) {
@@ -2337,7 +2338,7 @@
   run_loop.Run();
 }
 
-TEST_F(ShimlessRmaServiceTest, kFinalize) {
+TEST_F(ShimlessRmaServiceTest, Finalization) {
   const std::vector<rmad::GetStateReply> fake_states = {
       CreateStateReply(rmad::RmadState::kFinalize, rmad::RMAD_ERROR_OK),
       CreateStateReply(rmad::RmadState::kDeviceDestination,
@@ -2362,6 +2363,37 @@
   run_loop.Run();
 }
 
+TEST_F(ShimlessRmaServiceTest, RetryFinalization) {
+  const std::vector<rmad::GetStateReply> fake_states = {
+      CreateStateReply(rmad::RmadState::kFinalize, rmad::RMAD_ERROR_OK),
+      CreateStateReply(rmad::RmadState::kDeviceDestination,
+                       rmad::RMAD_ERROR_OK)};
+  fake_rmad_client_()->SetFakeStateReplies(std::move(fake_states));
+  fake_rmad_client_()->check_state_callback =
+      base::BindRepeating([](const rmad::RmadState& state) {
+        EXPECT_EQ(state.state_case(), rmad::RmadState::kFinalize);
+        EXPECT_EQ(state.finalize().choice(),
+                  rmad::FinalizeState::RMAD_FINALIZE_CHOICE_RETRY);
+      });
+  base::RunLoop run_loop;
+  shimless_rma_provider_->GetCurrentState(base::BindLambdaForTesting(
+      [&](mojom::State state, bool can_cancel, bool can_go_back,
+          rmad::RmadErrorCode error) {
+        EXPECT_EQ(state, mojom::State::kFinalize);
+        EXPECT_EQ(error, rmad::RmadErrorCode::RMAD_ERROR_OK);
+      }));
+  run_loop.RunUntilIdle();
+
+  shimless_rma_provider_->RetryFinalization(base::BindLambdaForTesting(
+      [&](mojom::State state, bool can_cancel, bool can_go_back,
+          rmad::RmadErrorCode error) {
+        EXPECT_EQ(state, mojom::State::kChooseDestination);
+        EXPECT_EQ(error, rmad::RmadErrorCode::RMAD_ERROR_OK);
+        run_loop.Quit();
+      }));
+  run_loop.Run();
+}
+
 TEST_F(ShimlessRmaServiceTest, FinalizationCompleteFromWrongStateFails) {
   const std::vector<rmad::GetStateReply> fake_states = {CreateStateReply(
       rmad::RmadState::kDeviceDestination, rmad::RMAD_ERROR_OK)};
diff --git a/ash/webui/shimless_rma/mojom/shimless_rma.mojom b/ash/webui/shimless_rma/mojom/shimless_rma.mojom
index 30fa6dc..ffa9e86 100644
--- a/ash/webui/shimless_rma/mojom/shimless_rma.mojom
+++ b/ash/webui/shimless_rma/mojom/shimless_rma.mojom
@@ -600,11 +600,12 @@
   // Get the device SKU index at RMA start.
   GetOriginalSku() => (uint8 sku_index);
   // Get the device white-label index at RMA start.
-  GetOriginalWhiteLabel() => (uint8 whiteLabel_index);
+  GetOriginalWhiteLabel() => (uint8 white_label_index);
   // Attempt to set device info and transition to the next state.
   // Returns the next state to display and an error code.
   SetDeviceInformation(
-      string serial_number, uint8 region_index, uint8 sku_index)
+      string serial_number, uint8 region_index, uint8 sku_index,
+      uint8 white_label_index)
           => (State state, bool can_cancel, bool can_go_back,
               RmadErrorCode error);
 
@@ -661,6 +662,10 @@
   ///////////////////////////////////////
   // Methods for kFinalize state
   //
+  // Retries provisioning after a failure.
+  RetryFinalization()
+      => (State state, bool can_cancel, bool can_go_back,
+          RmadErrorCode error);
   FinalizationComplete()
       => (State state, bool can_cancel, bool can_go_back,
           RmadErrorCode error);
diff --git a/ash/webui/shimless_rma/resources/fake_data.js b/ash/webui/shimless_rma/resources/fake_data.js
index 88da8935..470edc0f 100644
--- a/ash/webui/shimless_rma/resources/fake_data.js
+++ b/ash/webui/shimless_rma/resources/fake_data.js
@@ -206,7 +206,7 @@
 
 /** @type {!Array<string>} */
 export const fakeDeviceWhiteLabels =
-    ['White-label 1', 'White-label 2', 'White-label 3'];
+    ['White-label 1', 'White-label 2', 'White-label 3', ''];
 
 /** @type {string} */
 export const fakeLog =
diff --git a/ash/webui/shimless_rma/resources/fake_shimless_rma_service.js b/ash/webui/shimless_rma/resources/fake_shimless_rma_service.js
index 53d445b..d7f4e106 100644
--- a/ash/webui/shimless_rma/resources/fake_shimless_rma_service.js
+++ b/ash/webui/shimless_rma/resources/fake_shimless_rma_service.js
@@ -569,9 +569,10 @@
    * @param {string} serialNumber
    * @param {number} regionIndex
    * @param {number} skuIndex
+   * @param {number} whiteLabelIndex
    * @return {!Promise<!StateResult>}
    */
-  setDeviceInformation(serialNumber, regionIndex, skuIndex) {
+  setDeviceInformation(serialNumber, regionIndex, skuIndex, whiteLabelIndex) {
     // TODO(gavindodd): Validate range of region and sku.
     return this.getNextStateForMethod_(
         'setDeviceInformation', State.kUpdateDeviceInformation);
@@ -668,6 +669,13 @@
   /**
    * @return {!Promise<!StateResult>}
    */
+  retryFinalization() {
+    return this.getNextStateForMethod_('retryFinalization', State.kFinalize);
+  }
+
+  /**
+   * @return {!Promise<!StateResult>}
+   */
   writeProtectManuallyEnabled() {
     return this.getNextStateForMethod_(
         'writeProtectManuallyEnabled', State.kWaitForManualWPEnable);
@@ -1228,6 +1236,7 @@
     this.methods_.register('retryProvisioning');
     this.methods_.register('provisioningComplete');
 
+    this.methods_.register('retryFinalization');
     this.methods_.register('finalizationComplete');
 
     this.methods_.register('writeProtectManuallyEnabled');
diff --git a/ash/webui/shimless_rma/resources/reimaging_device_information_page.html b/ash/webui/shimless_rma/resources/reimaging_device_information_page.html
index 9ca99b8f..76aac589 100644
--- a/ash/webui/shimless_rma/resources/reimaging_device_information_page.html
+++ b/ash/webui/shimless_rma/resources/reimaging_device_information_page.html
@@ -73,6 +73,25 @@
         </cr-button>
       </div>
     </div>
+    <div class="input-row">
+      <label id="whiteLabelLabel" class="cr-form-field-label">
+        [[i18n('confirmDeviceInfoWhiteLabelLabel')]]
+      </label>
+      <div class="input-holder">
+        <select id="whiteLabelSelect" class="md-select"
+            on-change="onSelectedWhiteLabelChange_" aria-labelledby="whiteLabelLabel">
+          <template is="dom-repeat" items="[[whiteLabels_]]" as="whiteLabel">
+            <option value="[[whiteLabel]]">
+              [[whiteLabel]]
+            </option>
+          </template>
+        </select>
+        <cr-button id="resetWhiteLabel" on-click="onResetWhiteLabelButtonClicked_"
+            disabled="[[disableResetWhiteLabel_]]">
+          [[i18n('confirmDeviceInfoResetButtonLabel')]]
+        </cr-button>
+      </div>
+    </div>
     <div>
       <label id="skuLabel" class="cr-form-field-label">
         [[i18n('confirmDeviceInfoSkuLabel')]]
@@ -95,6 +114,6 @@
     <div class="sku-warning">
       <iron-icon icon="shimless-icon:warning"></iron-icon>
       [[i18n('confirmDeviceInfoSkuWarning')]]
-    </p>
+    </div>
   </div>
 </base-page>
diff --git a/ash/webui/shimless_rma/resources/reimaging_device_information_page.js b/ash/webui/shimless_rma/resources/reimaging_device_information_page.js
index b3425a5..d89cc44 100644
--- a/ash/webui/shimless_rma/resources/reimaging_device_information_page.js
+++ b/ash/webui/shimless_rma/resources/reimaging_device_information_page.js
@@ -61,6 +61,13 @@
       },
 
       /** @protected */
+      disableResetWhiteLabel_: {
+        type: Boolean,
+        computed: 'getDisableResetWhiteLabel_(' +
+            'originalWhiteLabelIndex_, whiteLabelIndex_)',
+      },
+
+      /** @protected */
       originalSerialNumber_: {
         type: String,
         value: '',
@@ -108,6 +115,23 @@
         value: 0,
       },
 
+      /** @protected {!Array<string>} */
+      whiteLabels_: {
+        type: Array,
+        value: () => [],
+      },
+
+      /** @protected */
+      originalWhiteLabelIndex_: {
+        type: Number,
+        value: 0,
+      },
+
+      /** @protected */
+      whiteLabelIndex_: {
+        type: Number,
+        value: 0,
+      },
     };
   }
 
@@ -123,6 +147,7 @@
     this.getOriginalSerialNumber_();
     this.getOriginalRegionAndRegionList_();
     this.getOriginalSkuAndSkuList_();
+    this.getOriginalWhiteLabelAndWhiteLabelList_();
     this.dispatchEvent(new CustomEvent(
         'disable-next-button',
         {bubbles: true, composed: true, detail: false},
@@ -177,6 +202,34 @@
         });
   }
 
+  /** @private */
+  getOriginalWhiteLabelAndWhiteLabelList_() {
+    this.shimlessRmaService_.getOriginalWhiteLabel()
+        .then((result) => {
+          this.originalWhiteLabelIndex_ = result.whiteLabelIndex;
+          return this.shimlessRmaService_.getWhiteLabelList();
+        })
+        .then((result) => {
+          this.whiteLabels_ = result.whiteLabels;
+          const blankIndex = this.whiteLabels_.indexOf('');
+          if (blankIndex >= 0) {
+            this.whiteLabels_[blankIndex] =
+                this.i18n('confirmDeviceInfoEmptyWhiteLabelLabel');
+            if (this.originalWhiteLabelIndex_ < 0) {
+              this.originalWhiteLabelIndex_ = blankIndex;
+            }
+          }
+          this.whiteLabelIndex_ = this.originalWhiteLabelIndex_;
+
+          // Need to wait for the select options to render before setting the
+          // selected index.
+          afterNextRender(this, () => {
+            this.shadowRoot.querySelector('#whiteLabelSelect').selectedIndex =
+                this.whiteLabelIndex_;
+          });
+        });
+  }
+
   /** @protected */
   getDisableResetSerialNumber_() {
     return this.originalSerialNumber_ === this.serialNumber_;
@@ -193,6 +246,11 @@
   }
 
   /** @protected */
+  getDisableResetWhiteLabel_() {
+    return this.originalWhiteLabelIndex_ === this.whiteLabelIndex_;
+  }
+
+  /** @protected */
   onSelectedRegionChange_(event) {
     this.regionIndex_ =
         this.shadowRoot.querySelector('#regionSelect').selectedIndex;
@@ -204,6 +262,12 @@
   }
 
   /** @protected */
+  onSelectedWhiteLabelChange_(event) {
+    this.whiteLabelIndex_ =
+        this.shadowRoot.querySelector('#whiteLabelSelect').selectedIndex;
+  }
+
+  /** @protected */
   onResetSerialNumberButtonClicked_(event) {
     this.serialNumber_ = this.originalSerialNumber_;
   }
@@ -221,13 +285,21 @@
     this.shadowRoot.querySelector('#skuSelect').selectedIndex = this.skuIndex_;
   }
 
+  /** @protected */
+  onResetWhiteLabelButtonClicked_(event) {
+    this.whiteLabelIndex_ = this.originalWhiteLabelIndex_;
+    this.shadowRoot.querySelector('#whiteLabelSelect').selectedIndex =
+        this.whiteLabelIndex_;
+  }
+
   /** @return {!Promise<!StateResult>} */
   onNextButtonClick() {
     if (this.serialNumber_ === '') {
       return Promise.reject(new Error('Serial number not set'));
     } else {
       return this.shimlessRmaService_.setDeviceInformation(
-          this.serialNumber_, this.regionIndex_, this.skuIndex_);
+          this.serialNumber_, this.regionIndex_, this.skuIndex_,
+          this.whiteLabelIndex_);
     }
   }
 }
diff --git a/ash/webui/shimless_rma/shimless_rma.cc b/ash/webui/shimless_rma/shimless_rma.cc
index 0d47855..579630d9 100644
--- a/ash/webui/shimless_rma/shimless_rma.cc
+++ b/ash/webui/shimless_rma/shimless_rma.cc
@@ -239,6 +239,10 @@
        IDS_SHIMLESS_RMA_CONFIRM_DEVICE_INFO_SERIAL_NUMBER_LABEL},
       {"confirmDeviceInfoRegionLabel",
        IDS_SHIMLESS_RMA_CONFIRM_DEVICE_INFO_REGION_LABEL},
+      {"confirmDeviceInfoWhiteLabelLabel",
+       IDS_SHIMLESS_RMA_CONFIRM_DEVICE_INFO_WHITE_LABEL_LABEL},
+      {"confirmDeviceInfoEmptyWhiteLabelLabel",
+       IDS_SHIMLESS_RMA_CONFIRM_DEVICE_INFO_EMPTY_WHITE_LABEL_LABEL},
       {"confirmDeviceInfoSkuLabel",
        IDS_SHIMLESS_RMA_CONFIRM_DEVICE_INFO_SKU_LABEL},
       {"confirmDeviceInfoResetButtonLabel",
diff --git a/ash/wm/desks/desk_preview_view.cc b/ash/wm/desks/desk_preview_view.cc
index 0a2756a..32877942 100644
--- a/ash/wm/desks/desk_preview_view.cc
+++ b/ash/wm/desks/desk_preview_view.cc
@@ -466,7 +466,7 @@
       event->SetHandled();
       break;
     case ui::ET_GESTURE_SCROLL_BEGIN:
-      FALLTHROUGH;
+      [[fallthrough]];
     case ui::ET_GESTURE_SCROLL_UPDATE:
       owner_bar->HandleDragEvent(mini_view_, *event);
       event->SetHandled();
diff --git a/ash/wm/desks/desks_unittests.cc b/ash/wm/desks/desks_unittests.cc
index 1281f82..de5c2cad 100644
--- a/ash/wm/desks/desks_unittests.cc
+++ b/ash/wm/desks/desks_unittests.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <memory>
 #include <vector>
 
 #include "ash/accessibility/accessibility_controller_impl.h"
@@ -27,9 +28,13 @@
 #include "ash/screen_util.h"
 #include "ash/session/session_controller_impl.h"
 #include "ash/shelf/hotseat_widget.h"
+#include "ash/shelf/scroll_arrow_view.h"
+#include "ash/shelf/scrollable_shelf_view.h"
 #include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_layout_manager.h"
 #include "ash/shelf/shelf_view.h"
+#include "ash/shelf/shelf_view_test_api.h"
+#include "ash/shelf/shelf_widget.h"
 #include "ash/shell.h"
 #include "ash/style/ash_color_provider.h"
 #include "ash/style/close_button.h"
@@ -79,6 +84,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_clock.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/prefs/testing_pref_service.h"
@@ -107,6 +113,7 @@
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/point_conversions.h"
 #include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/transform.h"
 #include "ui/views/background.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/widget/widget.h"
@@ -4159,6 +4166,39 @@
   VerifyViewVisibility(app2, true);
 }
 
+TEST_P(PerDeskShelfTest, ShelfViewTransformUpdatedForScrollWhenSwitchingDesks) {
+  ScrollableShelfView* scrollable_shelf_view = GetPrimaryShelf()
+                                                   ->shelf_widget()
+                                                   ->hotseat_widget()
+                                                   ->scrollable_shelf_view();
+  ShelfView* shelf_view = scrollable_shelf_view->shelf_view();
+  ShelfViewTestAPI shelf_view_test_api(shelf_view);
+  shelf_view_test_api.SetAnimationDuration(base::Milliseconds(1));
+
+  // Create apps running on the active desk, and not pinned to the shelf, until
+  // the right or bottom scroll arrow appears.
+  ScrollArrowView* right_arrow = scrollable_shelf_view->right_arrow();
+  std::vector<std::unique_ptr<aura::Window>> windows;
+  while (!right_arrow->GetVisible()) {
+    windows.push_back(CreateAppWithShelfItem(ShelfItemType::TYPE_APP));
+    shelf_view_test_api.RunMessageLoopUntilAnimationsDone();
+  }
+
+  // Scroll the shelf.
+  ClickOnView(right_arrow, GetEventGenerator());
+  shelf_view_test_api.RunMessageLoopUntilAnimationsDone();
+  const gfx::Transform scrolled_transform = shelf_view->GetTransform();
+  EXPECT_FALSE(scrolled_transform.IsIdentity());
+
+  // Switch desks.
+  NewDesk();
+  ActivateDesk(DesksController::Get()->desks()[1].get());
+  if (IsPerDeskShelfEnabled())
+    EXPECT_TRUE(shelf_view->GetTransform().IsIdentity());
+  else
+    EXPECT_EQ(scrolled_transform, shelf_view->GetTransform());
+}
+
 // Tests desks name nudges, i.e. when a user creates a new desk, focus + clear
 // the new desk's renaming textfield.
 TEST_F(DesksTest, NameNudges) {
diff --git a/ash/wm/toplevel_window_event_handler.cc b/ash/wm/toplevel_window_event_handler.cc
index 05561e8..a2781f2c 100644
--- a/ash/wm/toplevel_window_event_handler.cc
+++ b/ash/wm/toplevel_window_event_handler.cc
@@ -456,7 +456,7 @@
       event->StopPropagation();
       return;
     case ui::ET_SCROLL_FLING_START:
-      FALLTHROUGH;
+      [[fallthrough]];
     case ui::ET_GESTURE_SWIPE:
       HandleFlingOrSwipe(event);
       return;
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 0e3a8ef..0732e8a 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -3089,6 +3089,7 @@
     "i18n/string_search_unittest.cc",
     "i18n/time_formatting_unittest.cc",
     "i18n/timezone_unittest.cc",
+    "i18n/transliterator_unittest.cc",
     "immediate_crash_unittest.cc",
     "json/json_parser_unittest.cc",
     "json/json_reader_unittest.cc",
diff --git a/base/allocator/partition_allocator/memory_reclaimer.cc b/base/allocator/partition_allocator/memory_reclaimer.cc
index 5b609b5..741e969 100644
--- a/base/allocator/partition_allocator/memory_reclaimer.cc
+++ b/base/allocator/partition_allocator/memory_reclaimer.cc
@@ -16,26 +16,6 @@
 
 namespace base {
 
-namespace {
-
-template <bool thread_safe>
-void Insert(std::set<PartitionRoot<thread_safe>*>* partitions,
-            PartitionRoot<thread_safe>* partition) {
-  PA_DCHECK(partition);
-  auto it_and_whether_inserted = partitions->insert(partition);
-  PA_DCHECK(it_and_whether_inserted.second);
-}
-
-template <bool thread_safe>
-void Remove(std::set<PartitionRoot<thread_safe>*>* partitions,
-            PartitionRoot<thread_safe>* partition) {
-  PA_DCHECK(partition);
-  size_t erased_count = partitions->erase(partition);
-  PA_DCHECK(erased_count == 1u);
-}
-
-}  // namespace
-
 // static
 PartitionAllocMemoryReclaimer* PartitionAllocMemoryReclaimer::Instance() {
   static NoDestructor<PartitionAllocMemoryReclaimer> instance;
@@ -45,25 +25,17 @@
 void PartitionAllocMemoryReclaimer::RegisterPartition(
     PartitionRoot<internal::ThreadSafe>* partition) {
   internal::PartitionAutoLock lock(lock_);
-  Insert(&thread_safe_partitions_, partition);
-}
-
-void PartitionAllocMemoryReclaimer::RegisterPartition(
-    PartitionRoot<internal::NotThreadSafe>* partition) {
-  internal::PartitionAutoLock lock(lock_);
-  Insert(&thread_unsafe_partitions_, partition);
+  PA_DCHECK(partition);
+  auto it_and_whether_inserted = partitions_.insert(partition);
+  PA_DCHECK(it_and_whether_inserted.second);
 }
 
 void PartitionAllocMemoryReclaimer::UnregisterPartition(
     PartitionRoot<internal::ThreadSafe>* partition) {
   internal::PartitionAutoLock lock(lock_);
-  Remove(&thread_safe_partitions_, partition);
-}
-
-void PartitionAllocMemoryReclaimer::UnregisterPartition(
-    PartitionRoot<internal::NotThreadSafe>* partition) {
-  internal::PartitionAutoLock lock(lock_);
-  Remove(&thread_unsafe_partitions_, partition);
+  PA_DCHECK(partition);
+  size_t erased_count = partitions_.erase(partition);
+  PA_DCHECK(erased_count == 1u);
 }
 
 PartitionAllocMemoryReclaimer::PartitionAllocMemoryReclaimer() = default;
@@ -113,17 +85,13 @@
     internal::ThreadCacheRegistry::Instance().PurgeAll();
 #endif
 
-  for (auto* partition : thread_safe_partitions_)
-    partition->PurgeMemory(flags);
-  for (auto* partition : thread_unsafe_partitions_)
+  for (auto* partition : partitions_)
     partition->PurgeMemory(flags);
 }
 
 void PartitionAllocMemoryReclaimer::ResetForTesting() {
   internal::PartitionAutoLock lock(lock_);
-
-  thread_safe_partitions_.clear();
-  thread_unsafe_partitions_.clear();
+  partitions_.clear();
 }
 
 }  // namespace base
diff --git a/base/allocator/partition_allocator/memory_reclaimer.h b/base/allocator/partition_allocator/memory_reclaimer.h
index bd0972c7..dde12a3 100644
--- a/base/allocator/partition_allocator/memory_reclaimer.h
+++ b/base/allocator/partition_allocator/memory_reclaimer.h
@@ -35,11 +35,9 @@
   // Internal. Do not use.
   // Registers a partition to be tracked by the reclaimer.
   void RegisterPartition(PartitionRoot<internal::ThreadSafe>* partition);
-  void RegisterPartition(PartitionRoot<internal::NotThreadSafe>* partition);
   // Internal. Do not use.
   // Unregisters a partition to be tracked by the reclaimer.
   void UnregisterPartition(PartitionRoot<internal::ThreadSafe>* partition);
-  void UnregisterPartition(PartitionRoot<internal::NotThreadSafe>* partition);
 
   // Triggers an explicit reclaim now to reclaim as much free memory as
   // possible. The API callers need to invoke this method periodically
@@ -64,10 +62,7 @@
   void ResetForTesting();
 
   internal::PartitionLock lock_;
-  std::set<PartitionRoot<internal::ThreadSafe>*> thread_safe_partitions_
-      GUARDED_BY(lock_);
-  std::set<PartitionRoot<internal::NotThreadSafe>*> thread_unsafe_partitions_
-      GUARDED_BY(lock_);
+  std::set<PartitionRoot<internal::ThreadSafe>*> partitions_ GUARDED_BY(lock_);
 
   friend class NoDestructor<PartitionAllocMemoryReclaimer>;
   friend class PartitionAllocMemoryReclaimerTest;
diff --git a/base/allocator/partition_allocator/partition_alloc.cc b/base/allocator/partition_allocator/partition_alloc.cc
index 5d89318..5b0982c 100644
--- a/base/allocator/partition_allocator/partition_alloc.cc
+++ b/base/allocator/partition_allocator/partition_alloc.cc
@@ -99,9 +99,6 @@
 
 template PartitionAllocator<internal::ThreadSafe>::~PartitionAllocator();
 template void PartitionAllocator<internal::ThreadSafe>::init(PartitionOptions);
-template PartitionAllocator<internal::NotThreadSafe>::~PartitionAllocator();
-template void PartitionAllocator<internal::NotThreadSafe>::init(
-    PartitionOptions);
 
 #if (DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)) && \
     BUILDFLAG(USE_BACKUP_REF_PTR)
diff --git a/base/allocator/partition_allocator/partition_bucket.cc b/base/allocator/partition_allocator/partition_bucket.cc
index 443ff923..5000b77 100644
--- a/base/allocator/partition_allocator/partition_bucket.cc
+++ b/base/allocator/partition_allocator/partition_bucket.cc
@@ -1042,7 +1042,6 @@
 }
 
 template struct PartitionBucket<ThreadSafe>;
-template struct PartitionBucket<NotThreadSafe>;
 
 }  // namespace internal
 }  // namespace base
diff --git a/base/allocator/partition_allocator/partition_page.cc b/base/allocator/partition_allocator/partition_page.cc
index 19d8251..fcc404e 100644
--- a/base/allocator/partition_allocator/partition_page.cc
+++ b/base/allocator/partition_allocator/partition_page.cc
@@ -357,7 +357,6 @@
 }  // namespace
 
 template struct SlotSpanMetadata<ThreadSafe>;
-template struct SlotSpanMetadata<NotThreadSafe>;
 
 }  // namespace internal
 }  // namespace base
diff --git a/base/allocator/partition_allocator/partition_root.cc b/base/allocator/partition_allocator/partition_root.cc
index 40fb496c..132057d 100644
--- a/base/allocator/partition_allocator/partition_root.cc
+++ b/base/allocator/partition_allocator/partition_root.cc
@@ -1159,7 +1159,6 @@
 }
 
 template struct BASE_EXPORT PartitionRoot<internal::ThreadSafe>;
-template struct BASE_EXPORT PartitionRoot<internal::NotThreadSafe>;
 
 static_assert(sizeof(PartitionRoot<internal::ThreadSafe>) ==
                   sizeof(PartitionRoot<internal::NotThreadSafe>),
diff --git a/base/barrier_callback.h b/base/barrier_callback.h
index fee95987..85402cf 100644
--- a/base/barrier_callback.h
+++ b/base/barrier_callback.h
@@ -83,8 +83,13 @@
 // Run() on the returned callbacks, or the thread that constructed the
 // BarrierCallback (in the case where `num_callbacks` is 0).
 //
+// BarrierCallback is copyable. Copies share state.
+//
 // `done_callback` is also cleared on the thread that runs it (by virtue of
 // being a OnceCallback).
+//
+// See also
+// https://chromium.googlesource.com/chromium/src/+/HEAD/docs/callback.md
 template <typename T,
           typename RawArg = base::remove_cvref_t<T>,
           typename DoneArg = std::vector<RawArg>,
diff --git a/base/barrier_callback_unittest.cc b/base/barrier_callback_unittest.cc
index 127cc1e..7b6db8632 100644
--- a/base/barrier_callback_unittest.cc
+++ b/base/barrier_callback_unittest.cc
@@ -51,6 +51,29 @@
   EXPECT_TRUE(done);
 }
 
+TEST(BarrierCallbackTest, CopiesShareState) {
+  bool done = false;
+  const auto barrier_callback = base::BarrierCallback<int>(
+      3, base::BindLambdaForTesting([&done](std::vector<int> results) {
+        EXPECT_THAT(results, testing::ElementsAre(1, 3, 2));
+        done = true;
+      }));
+  EXPECT_FALSE(done);
+
+  const auto barrier_copy1 = barrier_callback;
+  const auto barrier_copy2 = barrier_callback;
+  const auto barrier_copy3 = barrier_callback;
+
+  barrier_copy1.Run(1);
+  EXPECT_FALSE(done);
+
+  barrier_copy2.Run(3);
+  EXPECT_FALSE(done);
+
+  barrier_copy3.Run(2);
+  EXPECT_TRUE(done);
+}
+
 template <typename... Args>
 class DestructionIndicator {
  public:
diff --git a/base/base_paths_win.cc b/base/base_paths_win.cc
index 759e67f..65eb5a8 100644
--- a/base/base_paths_win.cc
+++ b/base/base_paths_win.cc
@@ -61,7 +61,7 @@
         break;
       }
       // Fall through to base::DIR_PROGRAM_FILES if we're on an X86 machine.
-      FALLTHROUGH;
+      [[fallthrough]];
     case base::DIR_PROGRAM_FILES:
       if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL,
                                  SHGFP_TYPE_CURRENT, system_buffer)))
diff --git a/base/files/memory_mapped_file.cc b/base/files/memory_mapped_file.cc
index 646f3dfc..643128d 100644
--- a/base/files/memory_mapped_file.cc
+++ b/base/files/memory_mapped_file.cc
@@ -89,7 +89,7 @@
           return false;
         }
       }
-      FALLTHROUGH;
+      [[fallthrough]];
     case READ_ONLY:
     case READ_WRITE:
       // Ensure that the region values are valid.
diff --git a/base/i18n/transliterator_unittest.cc b/base/i18n/transliterator_unittest.cc
new file mode 100644
index 0000000..e23d2c6
--- /dev/null
+++ b/base/i18n/transliterator_unittest.cc
@@ -0,0 +1,51 @@
+// Copyright (c) 2021 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 "build/build_config.h"
+#include "base/i18n/unicodestring.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/icu/source/common/unicode/ustring.h"
+#include "third_party/icu/source/i18n/unicode/translit.h"
+
+namespace base {
+namespace i18n {
+
+TEST(TransliteratorTest, LowerCorrect) {
+  UParseError parseErr;
+  UErrorCode err;
+  std::unique_ptr<icu::Transliterator> transliterator(
+      icu::Transliterator::createInstance("Lower", UTRANS_FORWARD,
+                                          parseErr, err));
+  ASSERT_TRUE(U_SUCCESS(err));
+  icu::UnicodeString text(u"ÎÑŢÉRÑÅŢÎÖÑÅĻÎŽÅŢÎÖÑ");
+  transliterator->transliterate(text);
+  EXPECT_EQ(base::i18n::UnicodeStringToString16(text), u"îñţérñåţîöñåļîžåţîöñ");
+}
+
+TEST(TransliteratorTest, LatinASCIICorrect) {
+  UParseError parseErr;
+  UErrorCode err;
+  std::unique_ptr<icu::Transliterator> transliterator(
+      icu::Transliterator::createInstance("Latin-ASCII", UTRANS_FORWARD,
+                                          parseErr, err));
+  ASSERT_TRUE(U_SUCCESS(err));
+  icu::UnicodeString text(u"ÎÑŢÉRÑÅŢÎÖÑÅĻÎŽÅŢÎÖÑ");
+  transliterator->transliterate(text);
+  EXPECT_EQ(base::i18n::UnicodeStringToString16(text), u"INTERNATIONALIZATION");
+}
+
+TEST(TransliteratorTest, LowerLatinASCIICorrect) {
+  UParseError parseErr;
+  UErrorCode err;
+  std::unique_ptr<icu::Transliterator> transliterator(
+      icu::Transliterator::createInstance("Lower;Latin-ASCII", UTRANS_FORWARD,
+                                          parseErr, err));
+  ASSERT_TRUE(U_SUCCESS(err));
+  icu::UnicodeString text(u"ÎÑŢÉRÑÅŢÎÖÑÅĻÎŽÅŢÎÖÑ");
+  transliterator->transliterate(text);
+  EXPECT_EQ(base::i18n::UnicodeStringToString16(text), u"internationalization");
+}
+
+}  // namespace i18n
+}  // namespace base
diff --git a/base/strings/sys_string_conversions_posix.cc b/base/strings/sys_string_conversions_posix.cc
index 07ee947..71251c7d 100644
--- a/base/strings/sys_string_conversions_posix.cc
+++ b/base/strings/sys_string_conversions_posix.cc
@@ -116,7 +116,7 @@
       case 0:
         // We hit an embedded null byte, keep going.
         i += 1;
-        FALLTHROUGH;
+        [[fallthrough]];
       default:
         i += res;
         ++num_out_chars;
diff --git a/base/threading/platform_thread_linux.cc b/base/threading/platform_thread_linux.cc
index a8c1d3f9..a887cd5a 100644
--- a/base/threading/platform_thread_linux.cc
+++ b/base/threading/platform_thread_linux.cc
@@ -144,7 +144,7 @@
     case ThreadPriority::BACKGROUND:
       return cgroup_filepath.Append(FILE_PATH_LITERAL("non-urgent"));
     case ThreadPriority::DISPLAY:
-      FALLTHROUGH;
+      [[fallthrough]];
     case ThreadPriority::REALTIME_AUDIO:
       return cgroup_filepath.Append(FILE_PATH_LITERAL("urgent"));
   }
@@ -228,12 +228,12 @@
 
   switch (priority) {
     case ThreadPriority::NORMAL:
-      FALLTHROUGH;
+      [[fallthrough]];
     case ThreadPriority::BACKGROUND:
       break;
     case ThreadPriority::DISPLAY:
       // Display needs a boost for consistent 60 fps compositing.
-      FALLTHROUGH;
+      [[fallthrough]];
     case ThreadPriority::REALTIME_AUDIO:
       is_urgent = true;
       break;
diff --git a/base/threading/platform_thread_win.cc b/base/threading/platform_thread_win.cc
index 047114ee..5aee160 100644
--- a/base/threading/platform_thread_win.cc
+++ b/base/threading/platform_thread_win.cc
@@ -465,11 +465,11 @@
       return ThreadPriority::BACKGROUND;
     case kWin7NormalPriority:
       DCHECK_EQ(win::GetVersion(), win::Version::WIN7);
-      FALLTHROUGH;
+      [[fallthrough]];
     case THREAD_PRIORITY_NORMAL:
       return ThreadPriority::NORMAL;
     case kWinNormalPriority1:
-      FALLTHROUGH;
+      [[fallthrough]];
     case kWinNormalPriority2:
       return ThreadPriority::NORMAL;
     case THREAD_PRIORITY_ABOVE_NORMAL:
diff --git a/base/values.h b/base/values.h
index 6e8ecb8..168f8c9 100644
--- a/base/values.h
+++ b/base/values.h
@@ -632,6 +632,8 @@
 // DictionaryValue provides a key-value dictionary with (optional) "path"
 // parsing for recursive access; see the comment at the top of the file. Keys
 // are std::string's and should be UTF-8 encoded.
+// DEPRECATED: Use DictStorage or base::Value(base::Value::Type::DICTIONARY)
+// instead.
 class BASE_EXPORT DictionaryValue : public Value {
  public:
   // Returns `value` if it is a dictionary, nullptr otherwise.
diff --git a/build/config/compiler/pgo/BUILD.gn b/build/config/compiler/pgo/BUILD.gn
index 3e8502ed..637436b 100644
--- a/build/config/compiler/pgo/BUILD.gn
+++ b/build/config/compiler/pgo/BUILD.gn
@@ -56,19 +56,18 @@
     }
 
     if (pgo_data_path == "" && _pgo_target != "") {
-      pgo_data_path = rebase_path(exec_script("//tools/update_pgo_profiles.py",
-                                              [
-                                                "--target",
-                                                _pgo_target,
-                                                "get_profile_path",
-                                              ],
-                                              "value"),
-                                  root_build_dir)
+      pgo_data_path = exec_script("//tools/update_pgo_profiles.py",
+                                  [
+                                    "--target",
+                                    _pgo_target,
+                                    "get_profile_path",
+                                  ],
+                                  "value")
     }
     assert(pgo_data_path != "",
            "Please set pgo_data_path to point at the profile data")
     cflags = [
-      "-fprofile-instr-use=$pgo_data_path",
+      "-fprofile-instr-use=" + rebase_path(pgo_data_path, root_build_dir),
 
       # It's possible to have some profile data legitimately missing,
       # and at least some profile data always ends up being considered
diff --git a/build/fuchsia/PRESUBMIT.py b/build/fuchsia/PRESUBMIT.py
index 5538bfc..9af9c00 100644
--- a/build/fuchsia/PRESUBMIT.py
+++ b/build/fuchsia/PRESUBMIT.py
@@ -27,7 +27,11 @@
                                            ],
                                            run_on_python2=False,
                                            run_on_python3=True))
-  return input_api.RunTests(tests)
+  results = []
+  results.extend(input_api.RunTests(tests))
+  results.extend(
+      input_api.canned_checks.RunPylint(input_api, output_api, version='2.7'))
+  return results
 
 
 def CheckChangeOnUpload(input_api, output_api):
diff --git a/build/fuchsia/__init__.py b/build/fuchsia/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/build/fuchsia/__init__.py
+++ /dev/null
diff --git a/build/fuchsia/aemu_target.py b/build/fuchsia/aemu_target.py
index 9f86c77..8f83124 100644
--- a/build/fuchsia/aemu_target.py
+++ b/build/fuchsia/aemu_target.py
@@ -18,12 +18,10 @@
 
 
 class AemuTarget(qemu_target.QemuTarget):
-  EMULATOR_NAME = 'aemu'
-
   def __init__(self, out_dir, target_cpu, cpu_cores, require_kvm, ram_size_mb,
                enable_graphics, hardware_gpu, logs_dir):
-    super(AemuTarget, self).__init__(out_dir, target_cpu, cpu_cores,
-                                     require_kvm, ram_size_mb, logs_dir)
+    super().__init__(out_dir, target_cpu, cpu_cores, require_kvm, ram_size_mb,
+                     logs_dir)
 
     self._enable_graphics = enable_graphics
     self._hardware_gpu = hardware_gpu
@@ -48,12 +46,15 @@
                            help='Use local GPU hardware instead of '\
                                 'Swiftshader.')
 
+  def _GetEmulatorName(self):
+    return 'aemu'
+
   def _EnsureEmulatorExists(self, path):
     assert os.path.exists(path), \
-          'This checkout is missing %s.' % (self.EMULATOR_NAME)
+          'This checkout is missing %s.' % (self._GetEmulatorName())
 
   def _BuildCommand(self):
-    aemu_folder = GetEmuRootForPlatform(self.EMULATOR_NAME)
+    aemu_folder = GetEmuRootForPlatform(self._GetEmulatorName())
 
     self._EnsureEmulatorExists(aemu_folder)
     aemu_path = os.path.join(aemu_folder, 'emulator')
@@ -100,7 +101,7 @@
     return aemu_command
 
   def _GetVulkanIcdFile(self):
-    return os.path.join(GetEmuRootForPlatform(self.EMULATOR_NAME), 'lib64',
+    return os.path.join(GetEmuRootForPlatform(self._GetEmulatorName()), 'lib64',
                         'vulkan', 'vk_swiftshader_icd.json')
 
   def _SetEnv(self):
diff --git a/build/fuchsia/binary_size_differ.py b/build/fuchsia/binary_size_differ.py
index 2a72e43..8d2f2d99 100755
--- a/build/fuchsia/binary_size_differ.py
+++ b/build/fuchsia/binary_size_differ.py
@@ -126,12 +126,12 @@
     test_completed = True
     with open(args.results_path, 'wt') as results_file:
       json.dump(growth, results_file)
-  except:
+  except:  # pylint: disable=bare-except
     _, value, trace = sys.exc_info()
     traceback.print_tb(trace)
     print(str(value))
-  finally:
-    return 0 if test_completed else 1
+
+  return 0 if test_completed else 1
 
 
 if __name__ == '__main__':
diff --git a/build/fuchsia/binary_sizes.py b/build/fuchsia/binary_sizes.py
index de5d0b0..342f1da 100755
--- a/build/fuchsia/binary_sizes.py
+++ b/build/fuchsia/binary_sizes.py
@@ -321,8 +321,6 @@
   sdk_arch_dir = os.path.join(SDK_ROOT, 'arch')
   # Leaf subdirectories containing shared object files.
   sdk_so_leaf_dirs = ['dist', 'lib']
-  # Match a shared object file name.
-  sdk_so_filename_re = r'\.so(\.\d+)?$'
 
   lib_names = set()
   for dirpath, _, file_names in os.walk(sdk_arch_dir):
@@ -551,30 +549,30 @@
     package_sizes, package_blobs = GetBinarySizesAndBlobs(args, sizes_config)
     sizes_histogram = CreateSizesHistogram(package_sizes)
     test_completed = True
-  except:
+  except:  # pylint: disable=bare-except
     _, value, trace = sys.exc_info()
     traceback.print_tb(trace)
     print(str(value))
-  finally:
-    all_tests_passed, test_status = GetTestStatus(package_sizes, sizes_config,
-                                                  test_completed)
 
-    if results_directory:
-      WriteTestResults(os.path.join(results_directory, 'test_results.json'),
-                       test_completed, test_status, timestamp)
-      with open(os.path.join(results_directory, 'perf_results.json'), 'w') as f:
-        json.dump(sizes_histogram, f)
-      WritePackageBlobsJson(os.path.join(results_directory, PACKAGES_SIZE_FILE),
-                            package_blobs)
+  all_tests_passed, test_status = GetTestStatus(package_sizes, sizes_config,
+                                                test_completed)
 
-    if args.isolated_script_test_output:
-      WriteTestResults(args.isolated_script_test_output, test_completed,
-                       test_status, timestamp)
+  if results_directory:
+    WriteTestResults(os.path.join(results_directory, 'test_results.json'),
+                     test_completed, test_status, timestamp)
+    with open(os.path.join(results_directory, 'perf_results.json'), 'w') as f:
+      json.dump(sizes_histogram, f)
+    WritePackageBlobsJson(os.path.join(results_directory, PACKAGES_SIZE_FILE),
+                          package_blobs)
 
-    if args.size_plugin_json_path:
-      WriteGerritPluginSizeData(args.size_plugin_json_path, package_sizes)
+  if args.isolated_script_test_output:
+    WriteTestResults(args.isolated_script_test_output, test_completed,
+                     test_status, timestamp)
 
-    return 0 if all_tests_passed else 1
+  if args.size_plugin_json_path:
+    WriteGerritPluginSizeData(args.size_plugin_json_path, package_sizes)
+
+  return 0 if all_tests_passed else 1
 
 
 if __name__ == '__main__':
diff --git a/build/fuchsia/common.py b/build/fuchsia/common.py
index abe82c4a..501f21d 100644
--- a/build/fuchsia/common.py
+++ b/build/fuchsia/common.py
@@ -31,7 +31,7 @@
   host_platform = sys.platform
   if host_platform.startswith('linux'):
     return 'linux'
-  elif host_platform.startswith('darwin'):
+  if host_platform.startswith('darwin'):
     return 'mac'
   raise Exception('Unsupported host platform: %s' % host_platform)
 
@@ -39,12 +39,11 @@
   host_arch = platform.machine()
   if host_arch == 'x86_64':
     return 'x64'
-  elif host_arch == 'aarch64':
+  if host_arch == 'aarch64':
     return 'arm64'
   raise Exception('Unsupported host architecture: %s' % host_arch)
 
 def GetHostToolPathFromPlatform(tool):
-  host_arch = platform.machine()
   return os.path.join(SDK_ROOT, 'tools', GetHostArchFromPlatform(), tool)
 
 
@@ -54,23 +53,20 @@
           emulator, GetHostOsFromPlatform(), GetHostArchFromPlatform()))
 
 
-def ConnectPortForwardingTask(target, local_port, remote_port = 0):
+def ConnectPortForwardingTask(target, local_port):
   """Establishes a port forwarding SSH task to a localhost TCP endpoint hosted
   at port |local_port|. Blocks until port forwarding is established.
 
   Returns the remote port number."""
 
-  forwarding_flags = ['-O', 'forward',  # Send SSH mux control signal.
-                      '-R', '%d:localhost:%d' % (remote_port, local_port),
-                      '-v',   # Get forwarded port info from stderr.
-                      '-NT']  # Don't execute command; don't allocate terminal.
-
-  if remote_port != 0:
-    # Forward to a known remote port.
-    task = target.RunCommand([], ssh_args=forwarding_flags)
-    if task.returncode != 0:
-      raise Exception('Could not establish a port forwarding connection.')
-    return
+  forwarding_flags = [
+      '-O',
+      'forward',  # Send SSH mux control signal.
+      '-R',
+      '0:localhost:%d' % local_port,
+      '-v',  # Get forwarded port info from stderr.
+      '-NT'
+  ]  # Don't execute command; don't allocate terminal.
 
   task = target.RunCommandPiped([],
                                 ssh_args=forwarding_flags,
diff --git a/build/fuchsia/common_args.py b/build/fuchsia/common_args.py
index b55f447..2a61e68 100644
--- a/build/fuchsia/common_args.py
+++ b/build/fuchsia/common_args.py
@@ -124,7 +124,7 @@
   emu_args.add_argument('--ram-size-mb',
                         type=int,
                         default=8192,
-                        help='Sets the emulated RAM size (MB).'),
+                        help='Sets the emulated RAM size (MB).')
   emu_args.add_argument('--allow-no-kvm',
                         action='store_false',
                         dest='require_kvm',
diff --git a/build/fuchsia/device_target.py b/build/fuchsia/device_target.py
index 1ccb0493a..93d4c99b 100644
--- a/build/fuchsia/device_target.py
+++ b/build/fuchsia/device_target.py
@@ -81,7 +81,7 @@
     system_image_dir: The directory which contains the files used to pave the
                       device."""
 
-    super(DeviceTarget, self).__init__(out_dir, target_cpu, logs_dir)
+    super().__init__(out_dir, target_cpu, logs_dir)
 
     self._host = host
     self._port = port
@@ -345,8 +345,8 @@
     if self._node_name:
       pave_command.extend(['-n', self._node_name, '-1'])
     logging.info(' '.join(pave_command))
-    return_code, stdout, stderr = SubprocessCallWithTimeout(pave_command,
-                                                            timeout_secs=300)
+    return_code, _, stderr = SubprocessCallWithTimeout(pave_command,
+                                                       timeout_secs=300)
     if return_code != 0:
       raise Exception('Could not pave device.')
     self._ParseNodename(stderr)
@@ -360,7 +360,7 @@
 
   def Stop(self):
     try:
-      super(DeviceTarget, self).Stop()
+      super().Stop()
     finally:
       # End multiplexed ssh connection, ensure that ssh logging stops before
       # tests/scripts return.
diff --git a/build/fuchsia/device_target_test.py b/build/fuchsia/device_target_test.py
index 93fa150..8cf364f 100755
--- a/build/fuchsia/device_target_test.py
+++ b/build/fuchsia/device_target_test.py
@@ -103,7 +103,7 @@
     self.args.system_image_dir = 'mockdir'
     with DeviceTarget.CreateFromArgs(self.args) as device_target_instance, \
          mock.patch.object(DeviceTarget, '_Discover') as mock_discover, \
-         mock.patch.object(DeviceTarget, '_WaitUntilReady') as mock_ready, \
+         mock.patch.object(DeviceTarget, '_WaitUntilReady'), \
          mock.patch.object(DeviceTarget, '_GetSdkHash') as mock_hash, \
          mock.patch.object(
             DeviceTarget, '_GetInstalledSdkVersion') as mock_version, \
@@ -119,12 +119,12 @@
     self.args.system_image_dir = 'mockdir'
     with DeviceTarget.CreateFromArgs(self.args) as device_target_instance, \
          mock.patch.object(DeviceTarget, '_Discover') as mock_discover, \
-         mock.patch.object(DeviceTarget, '_WaitUntilReady') as mock_ready, \
+         mock.patch.object(DeviceTarget, '_WaitUntilReady'), \
          mock.patch.object(DeviceTarget, '_GetSdkHash') as mock_hash, \
          mock.patch.object(
             DeviceTarget, '_GetInstalledSdkVersion') as mock_version, \
          mock.patch.object(
-            DeviceTarget, '_ProvisionDevice') as mock_provision, \
+            DeviceTarget, '_ProvisionDevice'), \
          self.assertRaisesRegex(Exception, 'Image and Fuchsia version'):
       mock_discover.return_value = True
       mock_hash.return_value = '2.0'
diff --git a/build/fuchsia/emu_target.py b/build/fuchsia/emu_target.py
index e4b330d..63e2e8b 100644
--- a/build/fuchsia/emu_target.py
+++ b/build/fuchsia/emu_target.py
@@ -26,7 +26,7 @@
     target_cpu: The emulated target CPU architecture.
                 Can be 'x64' or 'arm64'."""
 
-    super(EmuTarget, self).__init__(out_dir, target_cpu, logs_dir)
+    super().__init__(out_dir, target_cpu, logs_dir)
     self._emu_process = None
     self._pkg_repo = None
     self._target_added = False
@@ -34,9 +34,13 @@
   def __enter__(self):
     return self
 
+  def _GetEmulatorName(self):
+    """Returns the name of this emulator."""
+    raise NotImplementedError()
+
   def _BuildCommand(self):
     """Build the command that will be run to start Fuchsia in the emulator."""
-    pass
+    raise NotImplementedError()
 
   def _SetEnv(self):
     return os.environ.copy()
@@ -80,13 +84,13 @@
       self._AddFfxTarget()
     except target.FuchsiaTargetException:
       if temporary_log_file:
-        logging.info('Kernel logs:\n' +
+        logging.info('Kernel logs:\n%s',
                      open(temporary_log_file.name, 'r').read())
       raise
 
   def Stop(self):
     try:
-      super(EmuTarget, self).Stop()
+      super().Stop()
     finally:
       self.Shutdown()
 
@@ -98,23 +102,24 @@
 
   def Shutdown(self):
     if not self._emu_process:
-      logging.error('%s did not start' % (self.EMULATOR_NAME))
+      logging.error('%s did not start', self._GetEmulatorName())
       return
     self._RemoveFfxTarget()
     if common.IsRunningUnattended():
       self._StopFfxDaemon()
     returncode = self._emu_process.poll()
     if returncode == None:
-      logging.info('Shutting down %s' % (self.EMULATOR_NAME))
+      logging.info('Shutting down %s', self._GetEmulatorName())
       self._emu_process.kill()
     elif returncode == 0:
-      logging.info('%s quit unexpectedly without errors' % self.EMULATOR_NAME)
+      logging.info('%s quit unexpectedly without errors',
+                   self._GetEmulatorName())
     elif returncode < 0:
-      logging.error('%s was terminated by signal %d' %
-                    (self.EMULATOR_NAME, -returncode))
+      logging.error('%s was terminated by signal %d', self._GetEmulatorName(),
+                    -returncode)
     else:
-      logging.error('%s quit unexpectedly with exit code %d' %
-                    (self.EMULATOR_NAME, returncode))
+      logging.error('%s quit unexpectedly with exit code %d',
+                    self._GetEmulatorName(), returncode)
 
     self.LogProcessStatistics('proc_stat_end_log')
     self.LogSystemStatistics('system_statistics_end_log')
@@ -125,11 +130,6 @@
       return False
     return os.waitpid(self._emu_process.pid, os.WNOHANG)[0] == 0
 
-  def _GetEndpoint(self):
-    if not self._IsEmuStillRunning():
-      raise Exception('%s quit unexpectedly.' % (self.EMULATOR_NAME))
-    return (self.LOCAL_ADDRESS, self._host_ssh_port)
-
   def _GetSshConfigPath(self):
     return boot_data.GetSSHConfigPath()
 
@@ -159,18 +159,17 @@
                                          stderr=subprocess.STDOUT,
                                          encoding='utf-8')
       if completed_process.stdout:
-        logging.debug('ffx succeeded with output\n%s' %
-                      completed_process.stdout)
+        logging.debug('ffx succeeded with output\n%s', completed_process.stdout)
       return completed_process.stdout
     except subprocess.CalledProcessError as cpe:
-      logging.exception('ffx failed with output\n%s' % cpe.stdout)
+      logging.exception('ffx failed with output\n%s', cpe.stdout)
       raise
 
   def _StopFfxDaemon(self):
     try:
       self._RunFfxCommand(['daemon', 'stop'])
       return
-    except subprocess.CalledProcessError as cpe:
+    except subprocess.CalledProcessError:
       pass
     logging.error('Failed to stop the damon. Attempting to restart it via ffx' +
                   ' doctor')
@@ -187,11 +186,11 @@
       return
     try:
       targets = json.loads(json_targets)
-    except json.JSONDecodeError as e:
-      logging.debug('ffx target list returned non-json text: %s' % json_targets)
+    except json.JSONDecodeError:
+      logging.debug('ffx target list returned non-json text: %s', json_targets)
       return
-    for target in targets:
-      if target['rcs_state'] == 'N' and address in target['addresses']:
+    for a_target in targets:
+      if a_target['rcs_state'] == 'N' and address in a_target['addresses']:
         self._RunFfxCommand(['target', 'remove', address])
 
   def _SetDefaultFfxTarget(self, address):
@@ -201,11 +200,11 @@
       address: A string representation of the target's ip address.
     """
     targets = json.loads(self._RunFfxCommand(['target', 'list', '-f', 'j']))
-    for target in targets:
-      if (target['rcs_state'] == 'N' or target['nodename'] == '<unknown>'
-          or address not in target['addresses']):
+    for a_target in targets:
+      if (a_target['rcs_state'] == 'N' or a_target['nodename'] == '<unknown>'
+          or address not in a_target['addresses']):
         continue
-      self._RunFfxCommand(['target', 'default', 'set', target['nodename']])
+      self._RunFfxCommand(['target', 'default', 'set', a_target['nodename']])
       break
 
   def _AddFfxTarget(self):
diff --git a/build/fuchsia/fvdl_target.py b/build/fuchsia/fvdl_target.py
index 058ded0..bb250bee 100644
--- a/build/fuchsia/fvdl_target.py
+++ b/build/fuchsia/fvdl_target.py
@@ -32,17 +32,15 @@
 
 class EmulatorNetworkNotFoundError(Exception):
   """Raised when emulator's address cannot be found"""
-  pass
 
 
 class FvdlTarget(emu_target.EmuTarget):
-  EMULATOR_NAME = 'aemu'
   _FVDL_PATH = os.path.join(common.SDK_ROOT, 'tools', 'x64', 'fvdl')
 
   def __init__(self, out_dir, target_cpu, require_kvm, enable_graphics,
                hardware_gpu, with_network, cpu_cores, ram_size_mb, logs_dir,
                custom_image):
-    super(FvdlTarget, self).__init__(out_dir, target_cpu, logs_dir)
+    super().__init__(out_dir, target_cpu, logs_dir)
     self._require_kvm = require_kvm
     self._enable_graphics = enable_graphics
     self._hardware_gpu = hardware_gpu
@@ -53,6 +51,7 @@
 
     self._host = None
     self._pid = None
+    self._host_ssh_port = None
 
     if custom_image:
       components = custom_image.split('.')
@@ -89,6 +88,9 @@
                            help='Specify an image used for booting up the '
                            'emulator.')
 
+  def _GetEmulatorName(self):
+    return 'aemu'
+
   def _BuildCommand(self):
     boot_data.ProvisionSSH()
     self._host_ssh_port = common.GetAvailableTcpPort()
@@ -102,7 +104,7 @@
         boot_data.GetTargetFile('storage-full.blk', self._image_arch,
                                 self._image_type))
     aemu_path = common.EnsurePathExists(
-        os.path.join(common.GetEmuRootForPlatform(self.EMULATOR_NAME),
+        os.path.join(common.GetEmuRootForPlatform(self._GetEmulatorName()),
                      'emulator'))
 
     emu_command = [
@@ -168,8 +170,8 @@
       ]
       if self._hardware_gpu:
         vulkan_icd_file = os.path.join(
-            common.GetEmuRootForPlatform(self.EMULATOR_NAME), 'lib64', 'vulkan',
-            'vk_swiftshader_icd.json')
+            common.GetEmuRootForPlatform(self._GetEmulatorName()), 'lib64',
+            'vulkan', 'vk_swiftshader_icd.json')
         env_flags.append('VK_ICD_FILENAMES=%s' % vulkan_icd_file)
       for flag in env_flags:
         emu_command.extend(['--envs', flag])
@@ -177,7 +179,7 @@
   def _WaitUntilReady(self):
     # Indicates the FVDL command finished running.
     self._emu_process.communicate()
-    super(FvdlTarget, self)._WaitUntilReady()
+    super()._WaitUntilReady()
 
   def _IsEmuStillRunning(self):
     if not self._pid:
@@ -215,14 +217,14 @@
               return (self._host, _DEFAULT_SSH_PORT)
         logging.error('Network address not found.')
         raise EmulatorNetworkNotFoundError()
-    except IOError as e:
+    except IOError:
       logging.error('vdl_output file not found. Cannot get network address.')
       raise
 
   def Shutdown(self):
     if not self._emu_process:
-      logging.error('%s did not start' % (self.EMULATOR_NAME))
-      super(FvdlTarget, self).Shutdown()
+      logging.error('%s did not start', self._GetEmulatorName())
+      super().Shutdown()
       return
     femu_command = [
         self._FVDL_PATH, '--sdk', 'kill', '--launched-proto',
@@ -233,12 +235,12 @@
     if returncode == 0:
       logging.info('FVDL shutdown successfully')
     else:
-      logging.info('FVDL kill returned error status {}'.format(returncode))
+      logging.info('FVDL kill returned error status %s', returncode)
     self.LogProcessStatistics('proc_stat_end_log')
     self.LogSystemStatistics('system_statistics_end_log')
     self._vdl_output_file.close()
     self._device_proto_file.close()
-    super(FvdlTarget, self).Shutdown()
+    super().Shutdown()
 
   def _GetSshConfigPath(self):
     return boot_data.GetSSHConfigPath()
diff --git a/build/fuchsia/fvdl_target_test.py b/build/fuchsia/fvdl_target_test.py
index 42383680..eabc73b 100755
--- a/build/fuchsia/fvdl_target_test.py
+++ b/build/fuchsia/fvdl_target_test.py
@@ -81,7 +81,6 @@
     with FvdlTarget.CreateFromArgs(self.args) as target:
       self.assertIn('--device-proto', target._BuildCommand())
       self.assertTrue(os.path.exists(target._device_proto_file.name))
-      correct_ram_amount = False
       with open(target._device_proto_file.name, 'r') as f:
         self.assertTrue('  ram:  {}\n'.format(custom_ram_size) in f.readlines())
 
diff --git a/build/fuchsia/generic_x64_target.py b/build/fuchsia/generic_x64_target.py
index 439aff7..d69aae17 100644
--- a/build/fuchsia/generic_x64_target.py
+++ b/build/fuchsia/generic_x64_target.py
@@ -89,9 +89,9 @@
     bootserver_command += boot_data.GetKernelArgs()
 
     logging.debug(' '.join(bootserver_command))
-    _, stdout = SubprocessCallWithTimeout(bootserver_command,
-                                          silent=False,
-                                          timeout_secs=300)
+    _, stdout, _ = SubprocessCallWithTimeout(bootserver_command,
+                                             silent=False,
+                                             timeout_secs=300)
 
     self._ParseNodename(stdout)
 
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 8200cbe..2d9e5602 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-7.20220103.3.1
+7.20220104.1.1
diff --git a/build/fuchsia/log_manager.py b/build/fuchsia/log_manager.py
index 91f202ea..39e060e7 100644
--- a/build/fuchsia/log_manager.py
+++ b/build/fuchsia/log_manager.py
@@ -10,7 +10,7 @@
 import os
 
 
-class LogManager(object):
+class LogManager():
   def __init__(self, logs_dir):
 
     # A dictionary with the log file path as the key and a file stream as value.
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 38bfdfb..2d9e5602 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-7.20220103.2.1
+7.20220104.1.1
diff --git a/build/fuchsia/net_test_server.py b/build/fuchsia/net_test_server.py
index 26cc978c..36fcca4 100644
--- a/build/fuchsia/net_test_server.py
+++ b/build/fuchsia/net_test_server.py
@@ -56,7 +56,7 @@
     raise Exception('Unmap called for unknown port: %d' % device_port)
 
 
-def SetupTestServer(target, test_concurrency, for_package, for_realms=[]):
+def SetupTestServer(target, test_concurrency, for_package, for_realms=()):
   """Provisions a forwarding test server and configures |target| to use it.
 
   Returns a Popen object for the test server process."""
diff --git a/build/fuchsia/pkg_repo.py b/build/fuchsia/pkg_repo.py
index 837149b..2037303 100644
--- a/build/fuchsia/pkg_repo.py
+++ b/build/fuchsia/pkg_repo.py
@@ -22,7 +22,7 @@
 _MANAGED_REPO_NAME = 'chromium-test-package-server'
 
 
-class PkgRepo(object):
+class PkgRepo():
   """Abstract interface for a repository used to serve packages to devices."""
 
   def __init__(self):
@@ -52,53 +52,60 @@
   """Creates and serves packages from an ephemeral repository."""
 
   def __init__(self, target):
-    super(ManagedPkgRepo, self).__init__()
+    super().__init__()
     self._with_count = 0
     self._target = target
 
     self._pkg_root = tempfile.mkdtemp()
     pm_tool = common.GetHostToolPathFromPlatform('pm')
     subprocess.check_call([pm_tool, 'newrepo', '-repo', self._pkg_root])
-    logging.debug('Creating and serving temporary package root: {}.'.format(
-        self._pkg_root))
+    logging.debug('Creating and serving temporary package root: %s.',
+                  self._pkg_root)
 
     with tempfile.NamedTemporaryFile() as pm_port_file:
-        # Flags for `pm serve`:
-        # https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/src/sys/pkg/bin/pm/cmd/pm/serve/serve.go
-        self._pm_serve_task = subprocess.Popen([
-            pm_tool, 'serve',
-            '-d', os.path.join(self._pkg_root, 'repository'),
-            '-c', '2',  # Use config.json format v2, the default for pkgctl.
-            '-q',  # Don't log transfer activity.
-            '-l', ':0',  # Bind to ephemeral port.
-            '-f', pm_port_file.name  # Publish port number to |pm_port_file|.
-        ])
+      # Flags for `pm serve`:
+      # https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/src/sys/pkg/bin/pm/cmd/pm/serve/serve.go
+      self._pm_serve_task = subprocess.Popen([
+          pm_tool,
+          'serve',
+          '-d',
+          os.path.join(self._pkg_root, 'repository'),
+          '-c',
+          '2',  # Use config.json format v2, the default for pkgctl.
+          '-q',  # Don't log transfer activity.
+          '-l',
+          ':0',  # Bind to ephemeral port.
+          '-f',
+          pm_port_file.name  # Publish port number to |pm_port_file|.
+      ])
 
-        # Busywait until 'pm serve' starts the server and publishes its port to
-        # a temporary file.
-        timeout = time.time() + _PM_SERVE_LISTEN_TIMEOUT_SECS
-        serve_port = None
-        while not serve_port:
-          if time.time() > timeout:
-            raise Exception('Timeout waiting for \'pm serve\' to publish its port.')
+      # Busywait until 'pm serve' starts the server and publishes its port to
+      # a temporary file.
+      timeout = time.time() + _PM_SERVE_LISTEN_TIMEOUT_SECS
+      serve_port = None
+      while not serve_port:
+        if time.time() > timeout:
+          raise Exception(
+              'Timeout waiting for \'pm serve\' to publish its port.')
 
-          with open(pm_port_file.name, 'r', encoding='utf8') as serve_port_file:
-            serve_port = serve_port_file.read()
+        with open(pm_port_file.name, 'r', encoding='utf8') as serve_port_file:
+          serve_port = serve_port_file.read()
 
-          time.sleep(_PM_SERVE_POLL_INTERVAL)
+        time.sleep(_PM_SERVE_POLL_INTERVAL)
 
-        serve_port = int(serve_port)
-        logging.debug('pm serve is active on port {}.'.format(serve_port))
+      serve_port = int(serve_port)
+      logging.debug('pm serve is active on port %s.', serve_port)
 
-    remote_port = common.ConnectPortForwardingTask(target, serve_port, 0)
+    remote_port = common.ConnectPortForwardingTask(target, serve_port)
     self._RegisterPkgRepository(self._pkg_root, remote_port)
 
   def __enter__(self):
     self._with_count += 1
     return self
 
-  def __exit__(self, type, value, tb):
-    # Allows the repository to delete itself when it leaves the scope of a 'with' block.
+  def __exit__(self, exc_type, exc_value, traceback):
+    # Allows the repository to delete itself when it leaves the scope of a
+    # 'with' block.
     self._with_count -= 1
     if self._with_count > 0:
       return
@@ -107,7 +114,7 @@
     self._pm_serve_task.kill()
     self._pm_serve_task = None
 
-    logging.info('Cleaning up package root: ' + self._pkg_root)
+    logging.info('Cleaning up package root: %s', self._pkg_root)
     shutil.rmtree(self._pkg_root)
     self._pkg_root = None
 
@@ -167,7 +174,10 @@
       raise Exception('Error code %d when running pkgctl repo add.' %
                       return_code)
 
-    rule_template = """'{"version":"1","content":[{"host_match":"fuchsia.com","host_replacement":"%s","path_prefix_match":"/","path_prefix_replacement":"/"}]}'"""
+    rule_template = \
+      """'{"version":"1","content":[{"host_match":"fuchsia.com",""" \
+      """"host_replacement":"%s","path_prefix_match":"/",""" \
+      """"path_prefix_replacement":"/"}]}'"""
     return_code = self._target.RunCommand([
         ('pkgctl rule replace json %s') % (rule_template % (_MANAGED_REPO_NAME))
     ])
@@ -187,7 +197,9 @@
     # were booted with 'fx serve'.
     self._target.RunCommand([
         'pkgctl', 'rule', 'replace', 'json',
-        """'{"version":"1","content":[{"host_match":"fuchsia.com","host_replacement":"devhost","path_prefix_match":"/","path_prefix_replacement":"/"}]}'"""
+        """'{"version":"1","content":[{"host_match":"fuchsia.com",""" \
+        """"host_replacement":"devhost","path_prefix_match":"/",""" \
+        """"path_prefix_replacement":"/"}]}'"""
     ],
                             silent=True)
 
@@ -197,28 +209,27 @@
   (ie. located under a Fuchsia build directory and served by "fx serve"."""
 
   def __init__(self, pkg_root, symbol_root):
-    super(PkgRepo, self).__init__()
+    super().__init__()
 
     self._pkg_root = pkg_root
     self._symbol_root = symbol_root
 
-    logging.info('Using existing package root: {}'.format(pkg_root))
-    logging.info(
-        'ATTENTION: This will not start a package server. Please run "fx serve" manually.'
-    )
+    logging.info('Using existing package root: %s', pkg_root)
+    logging.info('ATTENTION: This will not start a package server. Please run '
+                 '"fx serve" manually.')
 
   def GetPath(self):
     return self._pkg_root
 
   def PublishPackage(self, package_path):
-    super(ExternalPkgRepo, self).PublishPackage(package_path)
+    super().PublishPackage(package_path)
 
     self._InstallSymbols(os.path.join(os.path.dirname(package_path), 'ids.txt'))
 
   def __enter__(self):
     return self
 
-  def __exit__(self, type, value, tb):
+  def __exit__(self, exc_type, exc_value, traceback):
     pass
 
   def _InstallSymbols(self, package_path):
diff --git a/build/fuchsia/qemu_target.py b/build/fuchsia/qemu_target.py
index 16bbe416..3e3e2ca 100644
--- a/build/fuchsia/qemu_target.py
+++ b/build/fuchsia/qemu_target.py
@@ -36,20 +36,22 @@
 
 
 class QemuTarget(emu_target.EmuTarget):
-  EMULATOR_NAME = 'qemu'
-
   def __init__(self, out_dir, target_cpu, cpu_cores, require_kvm, ram_size_mb,
                logs_dir):
-    super(QemuTarget, self).__init__(out_dir, target_cpu, logs_dir)
+    super().__init__(out_dir, target_cpu, logs_dir)
     self._cpu_cores=cpu_cores
     self._require_kvm=require_kvm
     self._ram_size_mb=ram_size_mb
+    self._host_ssh_port = None
 
   @staticmethod
   def CreateFromArgs(args):
     return QemuTarget(args.out_dir, args.target_cpu, args.cpu_cores,
                       args.require_kvm, args.ram_size_mb, args.logs_dir)
 
+  def _GetEmulatorName(self):
+    return 'qemu'
+
   def _IsKvmEnabled(self):
     kvm_supported = sys.platform.startswith('linux') and \
                     os.access('/dev/kvm', os.R_OK | os.W_OK)
@@ -58,7 +60,7 @@
         (self._target_cpu == 'x64' and platform.machine() == 'x86_64')
     if kvm_supported and same_arch:
       return True
-    elif self._require_kvm:
+    if self._require_kvm:
       if same_arch:
         if not os.path.exists('/dev/kvm'):
           kvm_error = 'File /dev/kvm does not exist. Please install KVM first.'
@@ -67,12 +69,10 @@
                       'with "sudo usermod -a -G kvm $USER". Log out and back '\
                       'in for the change to take effect.'
         raise FuchsiaTargetException(kvm_error)
-      else:
-        raise FuchsiaTargetException('KVM unavailable when CPU architecture '\
-                                     'of host is different from that of'\
-                                     ' target. See --allow-no-kvm.')
-    else:
-      return False
+      raise FuchsiaTargetException('KVM unavailable when CPU architecture '
+                                   'of host is different from that of'
+                                   ' target. See --allow-no-kvm.')
+    return False
 
   def _BuildQemuConfig(self):
     boot_data.AssertBootImagesExist(self._GetTargetSdkArch(), 'qemu')
@@ -143,8 +143,9 @@
       else:
         kvm_command.append('host,migratable=no,+invtsc')
     else:
-      logging.warning('Unable to launch %s with KVM acceleration. '
-                      'The guest VM will be slow.' % (self.EMULATOR_NAME))
+      logging.warning(
+          'Unable to launch %s with KVM acceleration. '
+          'The guest VM will be slow.', self._GetEmulatorName())
       if self._target_cpu == 'arm64':
         kvm_command = ['-cpu', 'cortex-a53']
       else:
@@ -177,13 +178,19 @@
       raise Exception('Unknown target_cpu %s:' % self._target_cpu)
 
     qemu_command = [
-        os.path.join(GetEmuRootForPlatform(self.EMULATOR_NAME), 'bin',
+        os.path.join(GetEmuRootForPlatform(self._GetEmulatorName()), 'bin',
                      qemu_exec)
     ]
     qemu_command.extend(self._BuildQemuConfig())
     qemu_command.append('-nographic')
     return qemu_command
 
+  def _GetEndpoint(self):
+    if not self._IsEmuStillRunning():
+      raise Exception('%s quit unexpectedly.' % (self._GetEmulatorName()))
+    return (self.LOCAL_ADDRESS, self._host_ssh_port)
+
+
 def _ComputeFileHash(filename):
   hasher = hashlib.md5()
   with open(filename, 'rb') as f:
diff --git a/build/fuchsia/qemu_target_test.py b/build/fuchsia/qemu_target_test.py
index 21006ffc..fc666d1f 100755
--- a/build/fuchsia/qemu_target_test.py
+++ b/build/fuchsia/qemu_target_test.py
@@ -17,7 +17,8 @@
 # Register the target with the context manager so that it always gets
 # torn down on process exit. Otherwise there might be lingering QEMU instances
 # if Python crashes or is interrupted.
-with qemu_target.QemuTarget(tmpdir, 'x64') as target:
+with qemu_target.QemuTarget(tmpdir, 'x64', 2, True, 8192, None) as target:
+
   class TestQemuTarget(unittest.TestCase):
     @classmethod
     def setUpClass(cls):
diff --git a/build/fuchsia/remote_cmd.py b/build/fuchsia/remote_cmd.py
index dd9804e5..9080131 100644
--- a/build/fuchsia/remote_cmd.py
+++ b/build/fuchsia/remote_cmd.py
@@ -23,10 +23,10 @@
 def _EscapeIfIPv6Address(address):
   if ':' in address:
     return '[' + address + ']'
-  else:
-    return address
+  return address
 
-class CommandRunner(object):
+
+class CommandRunner():
   """Helper class used to execute commands on a remote host over SSH."""
 
   def __init__(self, config_path, host, port):
@@ -124,8 +124,7 @@
 
     _SSH_LOGGER.debug(' '.join(scp_command))
     try:
-      scp_output = subprocess.check_output(scp_command,
-                                           stderr=subprocess.STDOUT)
+      subprocess.check_output(scp_command, stderr=subprocess.STDOUT)
     except subprocess.CalledProcessError as error:
       _SSH_LOGGER.info(error.output)
       raise
diff --git a/build/fuchsia/run_ffx_command.py b/build/fuchsia/run_ffx_command.py
index 02f07459..0202a07 100755
--- a/build/fuchsia/run_ffx_command.py
+++ b/build/fuchsia/run_ffx_command.py
@@ -48,23 +48,24 @@
     target.Start()
     target.StartSystemLog(args.package)
 
-    # Extend the lifetime of |pkg_repo| beyond InstallPackage so that the
-    # package can be instantiated after resolution.
-    with target.GetPkgRepo() as pkg_repo:
+    # Extend the lifetime of the package repository beyond InstallPackage so
+    # that the package can be instantiated after resolution.
+    with target.GetPkgRepo():
       target.InstallPackage(args.package)
       process = target.RunFFXCommand(ffx_args)
 
       # It's possible that components installed by this script may be
-      # instantiated at arbitrary points in the future.
-      # This script (specifically |pkg_repo|) must be kept alive until it
-      # is explicitly terminated by the user, otherwise pkgsvr will
-      # throw an error when launching components.
+      # instantiated at arbitrary points in the future. This script
+      # (specifically, the package repository) must be kept alive until it is
+      # explicitly terminated by the user, otherwise pkgsvr will throw an error
+      # when launching components.
       logging.info('Command is now running. Press CTRL-C to exit.')
       try:
         while True:
           time.sleep(1)
       except KeyboardInterrupt:
         pass
+      del process
 
   return 0
 
diff --git a/build/fuchsia/run_test_package.py b/build/fuchsia/run_test_package.py
index aa4e99e..ec00952 100644
--- a/build/fuchsia/run_test_package.py
+++ b/build/fuchsia/run_test_package.py
@@ -42,7 +42,7 @@
                                 stderr=subprocess.STDOUT)
 
 
-class MergedInputStream(object):
+class MergedInputStream():
   """Merges a number of input streams into a UTF-8 encoded UNIX pipe on a
   dedicated thread. Terminates when the file descriptor of the primary stream
   (the first in the sequence) is closed."""
@@ -167,12 +167,11 @@
   return RunSymbolizer(input_fd, subprocess.PIPE, ids_txt_files)
 
 
-def RunTestPackage(output_dir, target, package_paths, package_name,
+def RunTestPackage(target, package_paths, package_name,
                    package_component_version, package_args, args):
   """Installs the Fuchsia package at |package_path| on the target,
   executes it with |package_args|, and symbolizes its output.
 
-  output_dir: The path containing the build output files.
   target: The deployment Target object that will run the package.
   package_paths: The paths to the .far packages to be installed.
   package_name: The name of the primary package to run.
diff --git a/build/fuchsia/runner_exceptions.py b/build/fuchsia/runner_exceptions.py
index 03f872e..d011db9 100644
--- a/build/fuchsia/runner_exceptions.py
+++ b/build/fuchsia/runner_exceptions.py
@@ -51,22 +51,22 @@
 
   Returns the mapped return code."""
 
-  (type, value, trace) = sys.exc_info()
+  (ex_type, value, trace) = sys.exc_info()
   _PrintException(value, trace)
 
-  if type is FuchsiaTargetException:
+  if ex_type is FuchsiaTargetException:
     if 'ssh' in str(value).lower():
       print('Error: FuchsiaTargetException: SSH to Fuchsia target failed.')
       return 65
     return 64
-  elif type is IOError:
+  if ex_type is IOError:
     if value.errno == errno.EAGAIN:
       logging.info('Python print to sys.stdout probably failed')
       if not IsStdoutBlocking():
         logging.warn('sys.stdout is non-blocking')
       return 73
     return 72
-  elif type is subprocess.CalledProcessError:
+  if ex_type is subprocess.CalledProcessError:
     if os.path.basename(value.cmd[0]) == 'scp':
       print('Error: scp operation failed - %s' % str(value))
       return 81
@@ -74,5 +74,4 @@
       print('Error: qemu-img fuchsia image generation failed.')
       return 82
     return 80
-  else:
-    return 1
+  return 1
diff --git a/build/fuchsia/start_emulator.py b/build/fuchsia/start_emulator.py
index 2b6db18a9..c39993e 100755
--- a/build/fuchsia/start_emulator.py
+++ b/build/fuchsia/start_emulator.py
@@ -42,7 +42,6 @@
                    'Chrome Fuchsia tests to target this emulator.')
     while fvdl_target._IsEmuStillRunning():
       time.sleep(10)
-      pass
 
 
 def AddLongRunningArgs(arg_parser):
diff --git a/build/fuchsia/target.py b/build/fuchsia/target.py
index e723e7c..fe7c9154 100644
--- a/build/fuchsia/target.py
+++ b/build/fuchsia/target.py
@@ -35,7 +35,7 @@
   # Query the metadata file which resides next to the package file.
   package_info = json.load(
       open(os.path.join(os.path.dirname(package_path), 'package')))
-  return package_info['name'], package_info['version'],
+  return package_info['name'], package_info['version']
 
 
 class _MapIsolatedPathsForPackage:
@@ -57,12 +57,11 @@
 
 
 class FuchsiaTargetException(Exception):
-  def __init__(self, message):
-    super(FuchsiaTargetException, self).__init__(message)
+  pass
 
 
 # TODO(crbug.com/1250803): Factor high level commands out of target.
-class Target(object):
+class Target():
   """Base class representing a Fuchsia deployment target."""
 
   def __init__(self, out_dir, target_cpu, logs_dir):
@@ -191,7 +190,7 @@
     for_realms: If specified, identifies the sub-realm of 'sys' under which
                 isolated paths (see |for_package|) are stored.
     """
-    assert type(source) is str
+    assert isinstance(source, str)
     self.PutFiles([source], dest, recursive, for_package, for_realms)
 
   def PutFiles(self,
@@ -210,7 +209,7 @@
     for_realms: If specified, identifies the sub-realm of 'sys' under which
                 isolated paths (see |for_package|) are stored.
     """
-    assert type(sources) is tuple or type(sources) is list
+    assert isinstance(sources, (tuple, list))
     if for_package:
       self.EnsureIsolatedPathsExist(for_package, for_realms)
       dest = _MapIsolatedPathsForPackage(for_package, 0, for_realms)(dest)
@@ -234,7 +233,7 @@
                 isolated paths (see |for_package|) are stored.
     recursive: If true, performs a recursive copy.
     """
-    assert type(source) is str
+    assert isinstance(source, str)
     self.GetFiles([source], dest, for_package, for_realms, recursive)
 
   def GetFiles(self,
@@ -253,7 +252,7 @@
                 isolated paths (see |for_package|) are stored.
     recursive: If true, performs a recursive copy.
     """
-    assert type(sources) is tuple or type(sources) is list
+    assert isinstance(sources, (tuple, list))
     self._AssertIsStarted()
     if for_package:
       sources = map(_MapIsolatedPathsForPackage(for_package, 0, for_realms),
@@ -273,7 +272,7 @@
                                     stderr=subprocess.STDOUT)
     stdout, _ = cat_proc.communicate()
     if cat_proc.returncode != 0:
-      raise Exception('Could not read file %s on device.', source)
+      raise Exception('Could not read file %s on device.' % source)
     return stdout.decode('utf-8')
 
   def _GetEndpoint(self):
@@ -312,7 +311,7 @@
 
     raise FuchsiaTargetException('Couldn\'t connect using SSH.')
 
-  def _GetSshConfigPath(self, path):
+  def _GetSshConfigPath(self):
     raise NotImplementedError()
 
   def GetPkgRepo(self):
@@ -336,7 +335,7 @@
 
       # Resolve all packages, to have them pulled into the device/VM cache.
       for package_path in package_paths:
-        package_name, package_version = _GetPackageInfo(package_path)
+        package_name, _ = _GetPackageInfo(package_path)
         logging.info('Installing %s...', package_name)
         return_code = self.RunCommand(
             ['pkgctl', 'resolve',
@@ -349,13 +348,13 @@
       # Verify that the newly resolved versions of packages are reported.
       for package_path in package_paths:
         # Use pkgctl get-hash to determine which version will be resolved.
-        package_name, package_version = _GetPackageInfo(package_path)
+        package_name, _ = _GetPackageInfo(package_path)
         pkgctl = self.RunCommandPiped(
             ['pkgctl', 'get-hash',
              _GetPackageUri(package_name)],
             stdout=subprocess.PIPE,
             stderr=subprocess.PIPE)
-        pkgctl_out, pkgctl_err = pkgctl.communicate()
+        pkgctl_out, _ = pkgctl.communicate()
 
         # Read the expected version from the meta.far Merkel hash file alongside
         # the package's FAR.
diff --git a/build/fuchsia/test_runner.py b/build/fuchsia/test_runner.py
index d01966a..abcd1cc 100755
--- a/build/fuchsia/test_runner.py
+++ b/build/fuchsia/test_runner.py
@@ -29,7 +29,7 @@
 TEST_REALM_NAME = 'chromium_tests'
 
 
-class TestOutputs(object):
+class TestOutputs():
   """An abstract base class for extracting outputs generated by a test."""
 
   def __init__(self):
@@ -43,11 +43,11 @@
 
   def GetDevicePath(self, path):
     """Returns an absolute device-local variant of a path."""
-    return ''
+    raise NotImplementedError()
 
   def GetFile(self, glob, destination):
     """Places all files/directories matched by a glob into a destination."""
-    pass
+    raise NotImplementedError()
 
 
 class TargetTestOutputs(TestOutputs):
@@ -55,7 +55,7 @@
   /tmp that are retrieved from the device via ssh."""
 
   def __init__(self, target, package_name, test_realms):
-    super(TargetTestOutputs, self).__init__()
+    super().__init__()
     self._target = target
     self._package_name = package_name
     self._test_realms = test_realms
@@ -76,7 +76,7 @@
   /custom_artifacts that are retrieved from the device automatically via ffx."""
 
   def __init__(self):
-    super(CustomArtifactsTestOutputs, self).__init__()
+    super().__init__()
     self._directory_manager = tempfile.TemporaryDirectory()
 
   def __enter__(self):
@@ -320,9 +320,9 @@
         run_package_args.use_run_test_component = True
       if args.component_version == "2":
         run_package_args.output_directory = test_outputs.GetOutputDirectory()
-      returncode = RunTestPackage(args.out_dir, target, args.package,
-                                  args.package_name, args.component_version,
-                                  child_args, run_package_args)
+      returncode = RunTestPackage(target, args.package, args.package_name,
+                                  args.component_version, child_args,
+                                  run_package_args)
 
       if test_server:
         test_server.Stop()
@@ -346,7 +346,7 @@
 
       return returncode
 
-  except:
+  except:  # pylint: disable=bare-except
     return HandleExceptionAndReturnExitCode()
 
 
diff --git a/build/fuchsia/update_images.py b/build/fuchsia/update_images.py
index c18726d..edcacb137 100755
--- a/build/fuchsia/update_images.py
+++ b/build/fuchsia/update_images.py
@@ -28,14 +28,14 @@
 
 
 def GetAllImages(boot_image_names):
+  images_to_download = set()
+
   if not boot_image_names:
-    return
+    return images_to_download
 
   all_device_types = ['generic', 'qemu']
   all_archs = ['x64', 'arm64']
 
-  images_to_download = set()
-
   for boot_image in boot_image_names.split(','):
     components = boot_image.split('.')
     if len(components) != 2:
diff --git a/build/fuchsia/update_sdk.py b/build/fuchsia/update_sdk.py
index 6bdb9d8..9d83f4a1 100755
--- a/build/fuchsia/update_sdk.py
+++ b/build/fuchsia/update_sdk.py
@@ -26,11 +26,11 @@
     'gs://{bucket}/development/{sdk_hash}/sdk/{platform}-amd64/gn.tar.gz')
 
 
-def _GetSdkGeneration(bucket, hash):
-  if not hash:
+def _GetSdkGeneration(bucket, sdk_hash):
+  if not sdk_hash:
     return None
 
-  sdk_path = _GetSdkTarballPath(bucket, hash)
+  sdk_path = _GetSdkTarballPath(bucket, sdk_hash)
   cmd = [
       os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gsutil.py'), 'ls', '-L',
       sdk_path
@@ -92,12 +92,13 @@
   task = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
   try:
     tarfile.open(mode='r|gz', fileobj=task.stdout).extractall(path=output_dir)
-  except tarfile.ReadError:
+  except tarfile.ReadError as read_error:
     task.wait()
     stderr = task.stderr.read()
-    raise subprocess.CalledProcessError(task.returncode, cmd,
-      "Failed to read a tarfile from gsutil.py.{}".format(
-        stderr if stderr else ""))
+    raise subprocess.CalledProcessError(
+        task.returncode, cmd,
+        "Failed to read a tarfile from gsutil.py.{}".format(
+            stderr if stderr else "")) from read_error
   task.wait()
   if task.returncode:
     raise subprocess.CalledProcessError(task.returncode, cmd,
@@ -142,7 +143,7 @@
   # Quietly exit if there's no SDK support for this platform.
   try:
     GetHostOsFromPlatform()
-  except:
+  except:  # pylint: disable=bare-except
     return 0
 
   # Use the bucket in sdk-bucket.txt if an entry exists.
diff --git a/chrome/VERSION b/chrome/VERSION
index c1948c23..d050e1ec 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=99
 MINOR=0
-BUILD=4807
+BUILD=4808
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
index fb9676a8..8fa181d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
@@ -658,10 +658,11 @@
                 profile = Profile.fromWebContents(webContents);
             } else {
                 profile = Profile.getLastUsedRegularProfile();
+                webContents = null;
             }
 
-            WebContentsDarkModeMessageController.attemptToSendMessage(
-                    mActivity, profile, new SettingsLauncherImpl(), mMessageDispatcher);
+            WebContentsDarkModeMessageController.attemptToSendMessage(mActivity, profile,
+                    webContents, new SettingsLauncherImpl(), mMessageDispatcher);
         }
 
         if (ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_FEED)) {
diff --git a/chrome/app/resources/generated_resources_am.xtb b/chrome/app/resources/generated_resources_am.xtb
index 2900dae..40d8b3a 100644
--- a/chrome/app/resources/generated_resources_am.xtb
+++ b/chrome/app/resources/generated_resources_am.xtb
@@ -2895,6 +2895,7 @@
 <translation id="3916445069167113093">የዚህ አይነት ፋይል ኮምፒውተርዎን ሊጎዳ ይችላል። <ph name="FILE_NAME" />ን ለማንኛውም ማስቀመጥ ይፈልጋሉ?</translation>
 <translation id="3918972485393593704">ዝርዝሮችን ለGoogle ሪፖርት አድርግ</translation>
 <translation id="3919145445993746351">በሁሉም ኮምፒውተሮችዎ ላይ ቅጥያዎችዎን ለማግኘት ስምረትን ያብሩ</translation>
+<translation id="3919229493046408863">መሳሪያዎች በአቅራቢያ ሲሆኑ ማሳወቂያን አጥፋ</translation>
 <translation id="3919798653937160644">በዚህ መስኮት ውስጥ የሚመለከቷቸውን ገጾች በአሰሳ ታሪክዎ ላይ የማይታዩ ሲሆን ሁሉንም የተከፈቱ የእንግዳ መስኮቶችን ከዘጉ በኋላ እንደ ኩኪዎች ያሉ ሌሎች መከታተያዎች በእርስዎ ኮምፒውተር ላይ አይተዉም። ይሁንና ማንኛውም የሚያወርዷቸው ፋይሎች ይቀመጣሉ።</translation>
 <translation id="3920504717067627103">የሰርቲፊኬት መምሪያዎች</translation>
 <translation id="392089482157167418">ChromeVoxን (የሚነገር ግብረመልስ) አንቃ</translation>
@@ -5926,6 +5927,7 @@
 <translation id="7167486101654761064">&amp;ሁልጊዜ እንዲህ አይነት ፋይሎችን ክፈት</translation>
 <translation id="716810439572026343"><ph name="FILE_NAME" />ን በማውረድ ላይ</translation>
 <translation id="7168109975831002660">አነስተኛ የቅርፀ ቁምፊ መጠን</translation>
+<translation id="7169122689956315694">መሣሪያዎች በአቅራቢያ ሲሆኑ ማሳወቂያን አብራ</translation>
 <translation id="7170236477717446850">የመገለጫ ስዕል</translation>
 <translation id="7171000599584840888">መገለጫ አክል...</translation>
 <translation id="7171259390164035663">አትመዝገብ</translation>
diff --git a/chrome/app/resources/generated_resources_bn.xtb b/chrome/app/resources/generated_resources_bn.xtb
index 7acc7837..db235021 100644
--- a/chrome/app/resources/generated_resources_bn.xtb
+++ b/chrome/app/resources/generated_resources_bn.xtb
@@ -2901,6 +2901,7 @@
 <translation id="3916445069167113093"> এই প্রকারের ফাইল আপনার কম্পিউটারের ক্ষতি করতে পারে৷ আপনি কি যেকোনো ভাবে <ph name="FILE_NAME" /> রাখতে চান?</translation>
 <translation id="3918972485393593704">Google এ বিশদে অভিযোগ করুন</translation>
 <translation id="3919145445993746351">আপনার সব কম্পিউটারে এক্সটেনশন পেতে, সিঙ্ক চালু করুন</translation>
+<translation id="3919229493046408863">আশেপাশে ডিভাইস থাকলে বিজ্ঞপ্তি বন্ধ করুন</translation>
 <translation id="3919798653937160644">এই উইন্ডোতে আপনি যে পৃষ্ঠাগুলি দেখেন তা ব্রাউজার ইতিহাসে দেখা যাবে না এবং আপনি সব খোলা গেস্ট উইন্ডো বন্ধ করে দেওয়ার পরে এগুলি কম্পিউটারে কুকির মতো অন্যান্য ট্রেস রেখে যাবে না। তবে, আপনার ডাউনলোড করা যেকোনও ফাইল সেভ করা হবে।</translation>
 <translation id="3920504717067627103">সার্টিফিকেটের নীতিসমূহ</translation>
 <translation id="392089482157167418">ChromeVox (কথ্য প্রতিবার্তা) চালু করুন</translation>
@@ -5935,6 +5936,7 @@
 <translation id="7167486101654761064">&amp;সবসময় এই ধরনের ফাইল খুলুন</translation>
 <translation id="716810439572026343"><ph name="FILE_NAME" /> ডাউনলোড করা হচ্ছে</translation>
 <translation id="7168109975831002660">ন্যূনতম হরফ আকার</translation>
+<translation id="7169122689956315694">আশেপাশে ডিভাইস থাকলে বিজ্ঞপ্তি চালু করুন</translation>
 <translation id="7170236477717446850">প্রোফাইল ছবি</translation>
 <translation id="7171000599584840888">প্রোফাইল যোগ করুন...</translation>
 <translation id="7171259390164035663">এনরোল করবেন না</translation>
diff --git a/chrome/app/resources/generated_resources_bs.xtb b/chrome/app/resources/generated_resources_bs.xtb
index 4d3e814..f14226a 100644
--- a/chrome/app/resources/generated_resources_bs.xtb
+++ b/chrome/app/resources/generated_resources_bs.xtb
@@ -2899,6 +2899,7 @@
 <translation id="3916445069167113093">Ova vrsta datoteke može oštetiti vaše računalo. Želite li ipak zadržati datoteku <ph name="FILE_NAME" />?</translation>
 <translation id="3918972485393593704">Prijavite detalje u Google</translation>
 <translation id="3919145445993746351">Da dobijete ekstenzije na svim svojim računarima, uključite sinhronizaciju</translation>
+<translation id="3919229493046408863">Isključite obavještenja kada su uređaji u blizini</translation>
 <translation id="3919798653937160644">Stranice koje prikazujete u ovom prozoru se neće prikazivati u historiji preglednika i neće ostaviti na računaru druge tragove, kao što su kolačići, nakon što zatvorite sve otvorene prozore u načinu rada za gosta. Međutim, zadržat će se svi fajlovi koje preuzmete.</translation>
 <translation id="3920504717067627103">Pravila za potvrde</translation>
 <translation id="392089482157167418">Omogući ChromeVox (izgovorene povratne informacije)</translation>
@@ -5933,6 +5934,7 @@
 <translation id="7167486101654761064">&amp;Uvijek otvori ovu vrstu datoteka</translation>
 <translation id="716810439572026343">Preuzimanje fajla <ph name="FILE_NAME" /></translation>
 <translation id="7168109975831002660">Najmanja veličina fonta</translation>
+<translation id="7169122689956315694">Uključite obavještenja kada su uređaji u blizini</translation>
 <translation id="7170236477717446850">Slika profila</translation>
 <translation id="7171000599584840888">Dodaj profil…</translation>
 <translation id="7171259390164035663">Nemoj prijaviti</translation>
diff --git a/chrome/app/resources/generated_resources_cs.xtb b/chrome/app/resources/generated_resources_cs.xtb
index 0ee7768..a72cd8a 100644
--- a/chrome/app/resources/generated_resources_cs.xtb
+++ b/chrome/app/resources/generated_resources_cs.xtb
@@ -2887,6 +2887,7 @@
 <translation id="3916445069167113093">Tento typ souboru může poškodit počítač. Chcete soubor <ph name="FILE_NAME" /> i přesto uložit?</translation>
 <translation id="3918972485393593704">Nahlásit podrobnosti do Googlu</translation>
 <translation id="3919145445993746351">Chcete-li svá rozšíření mít na všech svých počítačích, zapněte synchronizaci</translation>
+<translation id="3919229493046408863">Vypnout oznámení o zařízeních v okolí</translation>
 <translation id="3919798653937160644">Stránky, které otevřete v tomto okně, nebudou uvedeny v historii prohlížeče a nezanechají v počítači po zavření všech oken hosta žádné stopy, např. soubory cookie. Všechny stažené soubory však budou zachovány.</translation>
 <translation id="3920504717067627103">Zásady certifikátů</translation>
 <translation id="392089482157167418">Zapnout funkci ChromeVox (hlasovou odezvu)</translation>
@@ -5919,6 +5920,7 @@
 <translation id="7167486101654761064">Vždy otevírat soubory tohoto typu</translation>
 <translation id="716810439572026343">Stahování souboru <ph name="FILE_NAME" /></translation>
 <translation id="7168109975831002660">Minimální velikost písma</translation>
+<translation id="7169122689956315694">Zapnout oznámení o zařízeních v okolí</translation>
 <translation id="7170236477717446850">Profilová fotka</translation>
 <translation id="7171000599584840888">Přidat profil…</translation>
 <translation id="7171259390164035663">Neregistrovat</translation>
diff --git a/chrome/app/resources/generated_resources_de.xtb b/chrome/app/resources/generated_resources_de.xtb
index 895ce779..444ddb8 100644
--- a/chrome/app/resources/generated_resources_de.xtb
+++ b/chrome/app/resources/generated_resources_de.xtb
@@ -2883,6 +2883,7 @@
 <translation id="3916445069167113093">Dateien dieses Typs können Schäden an Ihrem Computer verursachen. Möchten Sie <ph name="FILE_NAME" /> trotzdem behalten?</translation>
 <translation id="3918972485393593704">Details an Google senden</translation>
 <translation id="3919145445993746351">Wenn Ihre Erweiterungen auf allen Computern verfügbar sein sollen, aktivieren Sie die Synchronisierung</translation>
+<translation id="3919229493046408863">Benachrichtigungen deaktivieren, wenn sich Geräte in der Nähe befinden</translation>
 <translation id="3919798653937160644">In diesem Fenster aufgerufene Seiten erscheinen nicht im Browserverlauf und hinterlassen auch keine anderweitigen Spuren wie Cookies auf dem Computer, nachdem Sie alle geöffneten Gastmodus-Fenster geschlossen haben. Heruntergeladene Dateien bleiben jedoch erhalten.</translation>
 <translation id="3920504717067627103">Zertifikatrichtlinien</translation>
 <translation id="392089482157167418">ChromeVox aktivieren (gesprochenes Feedback)</translation>
@@ -5914,6 +5915,7 @@
 <translation id="7167486101654761064">Dateien dieses Typs &amp;immer öffnen</translation>
 <translation id="716810439572026343"><ph name="FILE_NAME" /> wird heruntergeladen.</translation>
 <translation id="7168109975831002660">Mindestgröße</translation>
+<translation id="7169122689956315694">Benachrichtigungen aktivieren, wenn sich Geräte in der Nähe befinden</translation>
 <translation id="7170236477717446850">Profilbild</translation>
 <translation id="7171000599584840888">Profil hinzufügen…</translation>
 <translation id="7171259390164035663">Nicht anmelden</translation>
diff --git a/chrome/app/resources/generated_resources_el.xtb b/chrome/app/resources/generated_resources_el.xtb
index b3b4621a6..b38c2c8 100644
--- a/chrome/app/resources/generated_resources_el.xtb
+++ b/chrome/app/resources/generated_resources_el.xtb
@@ -2901,6 +2901,7 @@
 <translation id="3916445069167113093">Αυτός ο τύπος αρχείου ενδέχεται να βλάψει τον υπολογιστή σας. Θέλετε να διατηρήσετε το αρχείο <ph name="FILE_NAME" /> ούτως ή άλλως;</translation>
 <translation id="3918972485393593704">Αναφορά λεπτομερειών στην Google</translation>
 <translation id="3919145445993746351">Για τη λήψη των επεκτάσεων σε όλους τους υπολογιστές σας, ενεργοποιήστε τον συγχρονισμό.</translation>
+<translation id="3919229493046408863">Απενεργοποίηση της ειδοποίησης όταν υπάρχουν συσκευές κοντά σας.</translation>
 <translation id="3919798653937160644">Οι σελίδες που βλέπετε σε αυτό το παράθυρο δεν θα εμφανίζονται στο ιστορικό του προγράμματος περιήγησης και δεν θα αφήνουν άλλα ίχνη στον υπολογιστή, όπως cookie, αφού κλείσετε όλα τα ανοιχτά παράθυρα Επισκέπτη. Ωστόσο, τυχόν αρχεία τα οποία έχετε κατεβάσει θα διατηρηθούν.</translation>
 <translation id="3920504717067627103">Πολιτικές πιστοποιητικού</translation>
 <translation id="392089482157167418">Ενεργοποίηση του ChromeVox (προφορικά σχόλια)</translation>
@@ -5936,6 +5937,7 @@
 <translation id="7167486101654761064">&amp;Πάντα άνοιγμα αρχείων αυτού του τύπου</translation>
 <translation id="716810439572026343">Γίνεται λήψη του αρχείου <ph name="FILE_NAME" /></translation>
 <translation id="7168109975831002660">Ελάχιστο μέγεθος γραμματοσειράς</translation>
+<translation id="7169122689956315694">Ενεργοποίηση της ειδοποίησης όταν υπάρχουν συσκευές κοντά σας.</translation>
 <translation id="7170236477717446850">Φωτογραφία προφίλ</translation>
 <translation id="7171000599584840888">Προσθήκη προφίλ…</translation>
 <translation id="7171259390164035663">Να μην γίνει εγγραφή</translation>
diff --git a/chrome/app/resources/generated_resources_es.xtb b/chrome/app/resources/generated_resources_es.xtb
index e438ce1..45f9d10 100644
--- a/chrome/app/resources/generated_resources_es.xtb
+++ b/chrome/app/resources/generated_resources_es.xtb
@@ -2886,6 +2886,7 @@
 <translation id="3916445069167113093">Este tipo de archivo puede dañar tu ordenador. ¿Quieres descargar <ph name="FILE_NAME" /> de todos modos?</translation>
 <translation id="3918972485393593704">Enviar informe detallado a Google</translation>
 <translation id="3919145445993746351">Para obtener las extensiones en todos tus ordenadores, activa la sincronización</translation>
+<translation id="3919229493046408863">Desactivar notificación cuando haya dispositivos cerca</translation>
 <translation id="3919798653937160644">Las páginas que aparezcan en esta ventana no se mostrarán en el historial del navegador y no dejarán otros rastros, como cookies, en el ordenador después de cerrar todas las ventanas abiertas de la sesión de invitado. No obstante, se conservará cualquier archivo que descargues.</translation>
 <translation id="3920504717067627103">Políticas de certificados</translation>
 <translation id="392089482157167418">Habilitar ChromeVox (mensajes de voz)</translation>
@@ -5918,6 +5919,7 @@
 <translation id="7167486101654761064">&amp;Abrir siempre archivos de este tipo</translation>
 <translation id="716810439572026343">Descargando <ph name="FILE_NAME" /></translation>
 <translation id="7168109975831002660">Tamaño mínimo de fuente</translation>
+<translation id="7169122689956315694">Activar notificación cuando haya dispositivos cerca</translation>
 <translation id="7170236477717446850">Imagen de perfil</translation>
 <translation id="7171000599584840888">Añadir perfil...</translation>
 <translation id="7171259390164035663">No registrar</translation>
diff --git a/chrome/app/resources/generated_resources_eu.xtb b/chrome/app/resources/generated_resources_eu.xtb
index 74ed171..320915e 100644
--- a/chrome/app/resources/generated_resources_eu.xtb
+++ b/chrome/app/resources/generated_resources_eu.xtb
@@ -2885,6 +2885,7 @@
 <translation id="3916445069167113093">Fitxategi mota honek ordenagailuari kalte egin diezaioke. <ph name="FILE_NAME" /> mantendu nahi duzu halere?</translation>
 <translation id="3918972485393593704">Eman xehetasunen berri Google-ri</translation>
 <translation id="3919145445993746351">Luzapenak ordenagailu guztietan izateko, aktibatu sinkronizazioa</translation>
+<translation id="3919229493046408863">Gailuak inguruan daudenean, desaktibatu jakinarazpenak</translation>
 <translation id="3919798653937160644">Leiho honetan ikusten dituzun orriak ez dira arakatze-historian agertuko eta ez dute ordenagailuan beste inolako aztarnarik utziko (adibidez, cookieak) gonbidatu moduko leiho guztiak itxi ondoren. Hala ere, deskargatutako fitxategiak mantendu egingo dira.</translation>
 <translation id="3920504717067627103">Ziurtagiri-gidalerroak</translation>
 <translation id="392089482157167418">Gaitu ChromeVox (ahozko argibideak)</translation>
@@ -5918,6 +5919,7 @@
 <translation id="7167486101654761064">Ireki &amp;beti mota honetako fitxategiak</translation>
 <translation id="716810439572026343"><ph name="FILE_NAME" /> deskargatzen</translation>
 <translation id="7168109975831002660">Letra-tamaina minimoa</translation>
+<translation id="7169122689956315694">Gailuak inguruan daudenean, aktibatu jakinarazpenak</translation>
 <translation id="7170236477717446850">Profileko argazkia</translation>
 <translation id="7171000599584840888">Gehitu profil bat…</translation>
 <translation id="7171259390164035663">Ez erregistratu</translation>
diff --git a/chrome/app/resources/generated_resources_gl.xtb b/chrome/app/resources/generated_resources_gl.xtb
index d33623d..ce861c4 100644
--- a/chrome/app/resources/generated_resources_gl.xtb
+++ b/chrome/app/resources/generated_resources_gl.xtb
@@ -2884,6 +2884,7 @@
 <translation id="3916445069167113093">Este tipo de ficheiro pode danar o teu ordenador. Queres descargar <ph name="FILE_NAME" /> igualmente?</translation>
 <translation id="3918972485393593704">Informar dos detalles a Google</translation>
 <translation id="3919145445993746351">Para dispoñer das túas extensións en todos os ordenadores, activa a sincronización</translation>
+<translation id="3919229493046408863">Desactivar notificacións cando haxa dispositivos nas proximidades</translation>
 <translation id="3919798653937160644">As páxinas que visites nesta ventá non aparecerán no historial do navegador nin deixarán outros rastros (por exemplo, cookies) no ordenador unha vez peches todas as ventás abertas da sesión de convidado. Non obstante, conservaranse todos os ficheiros que descargues.</translation>
 <translation id="3920504717067627103">Políticas de certificados</translation>
 <translation id="392089482157167418">Activar ChromeVox (mensaxes de voz)</translation>
@@ -5917,6 +5918,7 @@
 <translation id="7167486101654761064">&amp;Abrir sempre ficheiros deste tipo</translation>
 <translation id="716810439572026343">Descargando <ph name="FILE_NAME" /></translation>
 <translation id="7168109975831002660">Tamaño mínimo do tipo de letra</translation>
+<translation id="7169122689956315694">Activar notificacións cando haxa dispositivos nas proximidades</translation>
 <translation id="7170236477717446850">Imaxe do perfil</translation>
 <translation id="7171000599584840888">Engadir perfil…</translation>
 <translation id="7171259390164035663">Non inscribirse</translation>
diff --git a/chrome/app/resources/generated_resources_hi.xtb b/chrome/app/resources/generated_resources_hi.xtb
index a6681c4..9bc47db 100644
--- a/chrome/app/resources/generated_resources_hi.xtb
+++ b/chrome/app/resources/generated_resources_hi.xtb
@@ -2901,6 +2901,7 @@
 <translation id="3916445069167113093">इस प्रकार की फ़ाइल आपके कंप्‍यूटर को नुकसान पहुंचा सकती है. क्‍या फिर भी आप <ph name="FILE_NAME" /> को रखना चाहते हैं?</translation>
 <translation id="3918972485393593704">Google को जानकारी भेजें</translation>
 <translation id="3919145445993746351">अपने सभी कंप्यूटर पर अपने एक्सटेंशन पाने के लिए, सिंक चालू करें</translation>
+<translation id="3919229493046408863">डिवाइसों के आस-पास होने पर सूचना मिलने की सुविधा बंद करें</translation>
 <translation id="3919798653937160644">जब आप अपने कंप्यूटर पर सभी मेहमान विंडो बंद कर देंगे, तो इस विंडो में देखे गए पेजों की जानकारी आपके ब्राउज़र इतिहास में सेव नहीं होगी. साथ ही, इन पेजों से जुड़ा किसी भी तरह का डेटा मिट जाएगा, जैसे कि कुकी. हालांकि, आपकी डाउनलोड की गई सभी फ़ाइलें सेव रहेंगी.</translation>
 <translation id="3920504717067627103">प्रमाणपत्र नीतियां</translation>
 <translation id="392089482157167418">ChromeVox (कंप्यूटर का बोलकर दिया गया जवाब) चालू करें</translation>
@@ -5934,6 +5935,7 @@
 <translation id="7167486101654761064">इस प्रकार की फ़ाइलें &amp;हमेशा खोलें</translation>
 <translation id="716810439572026343"><ph name="FILE_NAME" /> डाउनलोड हो रही है</translation>
 <translation id="7168109975831002660">कम से कम अक्षरों का आकार</translation>
+<translation id="7169122689956315694">डिवाइसों के आस-पास होने पर सूचना मिलने की सुविधा चालू करें</translation>
 <translation id="7170236477717446850">प्रोफ़ाइल फ़ोटो</translation>
 <translation id="7171000599584840888">प्रोफ़ाइल जोड़ें...</translation>
 <translation id="7171259390164035663">रजिस्टर न करें</translation>
diff --git a/chrome/app/resources/generated_resources_hr.xtb b/chrome/app/resources/generated_resources_hr.xtb
index 3dfcb36..dfa3548 100644
--- a/chrome/app/resources/generated_resources_hr.xtb
+++ b/chrome/app/resources/generated_resources_hr.xtb
@@ -2889,6 +2889,7 @@
 <translation id="3916445069167113093">Ova vrsta datoteke može oštetiti vaše računalo. Želite li ipak zadržati datoteku <ph name="FILE_NAME" />?</translation>
 <translation id="3918972485393593704">Prijavi pojedinosti Googleu</translation>
 <translation id="3919145445993746351">Da biste imali svoja proširenja na svim svojim računalima, uključite sinkronizaciju</translation>
+<translation id="3919229493046408863">Isključite obavijest kad je uređaj u blizini</translation>
 <translation id="3919798653937160644">Stranice koje gledate u ovom prozoru neće se pojaviti u povijesti preglednika niti će ostaviti druge tragove, na primjer kolačiće, na računalu nakon što zatvorite sve otvorene gostujuće prozore. Međutim, ako preuzmete datoteke, one će se sačuvati.</translation>
 <translation id="3920504717067627103">Pravila certifikata</translation>
 <translation id="392089482157167418">Omogući ChromeVox (govorne povratne informacije)</translation>
@@ -5922,6 +5923,7 @@
 <translation id="7167486101654761064">&amp;Uvijek otvori ovu vrstu datoteka</translation>
 <translation id="716810439572026343">Preuzimanje datoteke <ph name="FILE_NAME" /></translation>
 <translation id="7168109975831002660">Najmanja veličina fonta</translation>
+<translation id="7169122689956315694">Uključite obavijest kad je uređaj u blizini</translation>
 <translation id="7170236477717446850">Profilna slika</translation>
 <translation id="7171000599584840888">Dodaj profil...</translation>
 <translation id="7171259390164035663">Bez registracije</translation>
diff --git a/chrome/app/resources/generated_resources_hu.xtb b/chrome/app/resources/generated_resources_hu.xtb
index 04c9f83..ac7532c 100644
--- a/chrome/app/resources/generated_resources_hu.xtb
+++ b/chrome/app/resources/generated_resources_hu.xtb
@@ -2899,6 +2899,7 @@
 <translation id="3916445069167113093">Az ilyen fájlok kárt okozhatnak számítógépében. Ennek ellenére is szeretné megtartani a(z) <ph name="FILE_NAME" /> fájlt?</translation>
 <translation id="3918972485393593704">Részletek jelentése a Google-nak</translation>
 <translation id="3919145445993746351">Ha az összes számítógépén szeretné elérni bővítményeit, kapcsolja be a szinkronizálást.</translation>
+<translation id="3919229493046408863">Közeli eszközökre vonatkozó értesítések kikapcsolása</translation>
 <translation id="3919798653937160644">Az ebben az ablakban megtekintett oldalak a vendég módban megnyitott ablakok bezárását követően nem fognak megjelenni a böngészési előzmények között, és nem hagynak egyéb nyomokat, például cookie-kat a számítógépen. Az Ön által letöltött fájlokat azonban megőrzi a rendszer.</translation>
 <translation id="3920504717067627103">Tanúsítvány-irányelvek</translation>
 <translation id="392089482157167418">A ChromeVox (beszélt visszajelzés) engedélyezése</translation>
@@ -5934,6 +5935,7 @@
 <translation id="7167486101654761064">&amp;Az ilyen típusú fájlokat mindig nyissa meg</translation>
 <translation id="716810439572026343"><ph name="FILE_NAME" /> letöltése</translation>
 <translation id="7168109975831002660">Minimális betűméret</translation>
+<translation id="7169122689956315694">Közeli eszközökre vonatkozó értesítések bekapcsolása</translation>
 <translation id="7170236477717446850">Profilkép</translation>
 <translation id="7171000599584840888">Profil hozzáadása…</translation>
 <translation id="7171259390164035663">Nem regisztrálok</translation>
diff --git a/chrome/app/resources/generated_resources_it.xtb b/chrome/app/resources/generated_resources_it.xtb
index e0523b7..621292b1 100644
--- a/chrome/app/resources/generated_resources_it.xtb
+++ b/chrome/app/resources/generated_resources_it.xtb
@@ -2887,6 +2887,7 @@
 <translation id="3916445069167113093">Questo tipo di file può danneggiare il computer. Conservare comunque <ph name="FILE_NAME" />?</translation>
 <translation id="3918972485393593704">Segnala i dettagli a Google</translation>
 <translation id="3919145445993746351">Attiva la sincronizzazione per avere a disposizione le estensioni su tutti i tuoi computer</translation>
+<translation id="3919229493046408863">Disattiva la notifica quando ci sono dispositivi nelle vicinanze</translation>
 <translation id="3919798653937160644">Le pagine visualizzate in questa finestra non verranno memorizzate nella cronologia del browser e non lasceranno altre tracce, ad esempio cookie, sul computer dopo la chiusura di tutte le finestre Ospite aperte. Tutti i file scaricati verranno comunque conservati.</translation>
 <translation id="3920504717067627103">Criteri dei certificati</translation>
 <translation id="392089482157167418">Attiva ChromeVox (lettura vocale)</translation>
@@ -5920,6 +5921,7 @@
 <translation id="7167486101654761064">&amp;Apri sempre file di questo tipo</translation>
 <translation id="716810439572026343">Download di <ph name="FILE_NAME" /> in corso</translation>
 <translation id="7168109975831002660">Dimensioni minime dei caratteri</translation>
+<translation id="7169122689956315694">Attiva la notifica quando ci sono dispositivi nelle vicinanze</translation>
 <translation id="7170236477717446850">Immagine del profilo</translation>
 <translation id="7171000599584840888">Aggiungi profilo…</translation>
 <translation id="7171259390164035663">Non registrare</translation>
diff --git a/chrome/app/resources/generated_resources_iw.xtb b/chrome/app/resources/generated_resources_iw.xtb
index 901b01d..5fb69bd 100644
--- a/chrome/app/resources/generated_resources_iw.xtb
+++ b/chrome/app/resources/generated_resources_iw.xtb
@@ -2901,6 +2901,7 @@
 <translation id="3916445069167113093">סוג קובץ זה עלול לגרום נזק למחשב שלך. האם ברצונך לשמור את <ph name="FILE_NAME" /> בכל מקרה?</translation>
 <translation id="3918972485393593704">‏שליחת הפרטים אל Google</translation>
 <translation id="3919145445993746351">כדי לקבל גישה אל התוספים שלך בכל המחשבים שברשותך, יש להפעיל את הסנכרון</translation>
+<translation id="3919229493046408863">השבתת ההתראה כשמזוהים מכשירים בקרבת מקום</translation>
 <translation id="3919798653937160644">‏הדפים המוצגים בחלון זה לא יופיעו בהיסטוריית הדפדפן, ולאחר סגירת כל חלונות האורח הפתוחים, לא יותירו במחשב עקבות, כמו קובצי Cookie. עם זאת, כל הקבצים שיורדו יישמרו.</translation>
 <translation id="3920504717067627103">מדיניות אישורים </translation>
 <translation id="392089482157167418">‏הפעלת ChromeVox (משוב קולי)</translation>
@@ -5935,6 +5936,7 @@
 <translation id="7167486101654761064">&amp;פתיחה תמיד של קבצים מסוג זה</translation>
 <translation id="716810439572026343">הורדת <ph name="FILE_NAME" /> מתבצעת</translation>
 <translation id="7168109975831002660">גודל גופן מינימלי</translation>
+<translation id="7169122689956315694">הפעלת ההתראה כשמזוהים מכשירים בקרבת מקום</translation>
 <translation id="7170236477717446850">תמונת פרופיל</translation>
 <translation id="7171000599584840888">הוספת פרופיל...</translation>
 <translation id="7171259390164035663">אני לא רוצה להירשם</translation>
diff --git a/chrome/app/resources/generated_resources_kk.xtb b/chrome/app/resources/generated_resources_kk.xtb
index 6f2d7cbb..cfd713e4 100644
--- a/chrome/app/resources/generated_resources_kk.xtb
+++ b/chrome/app/resources/generated_resources_kk.xtb
@@ -2882,6 +2882,7 @@
 <translation id="3916445069167113093">Файлдың бұл түрі компьютеріңізге зиян келтіруі мүмкін. Бәрібір <ph name="FILE_NAME" /> сақтауды қалайсыз ба?</translation>
 <translation id="3918972485393593704">Толық мәліметтерді Google қызметіне беріңіз</translation>
 <translation id="3919145445993746351">Барлық компьютерде кеңейтімдер орнатылуы үшін, синхрондауды іске қосыңыз.</translation>
+<translation id="3919229493046408863">Маңайда құрылғылар пайда болғанда хабарландыруды өшіру</translation>
 <translation id="3919798653937160644">Сіз осы терезеде қарайтын беттер браузерді қолдану тарихында көрсетілмейді және ашық Қонақ терезелерінің барлығын жапқаннан кейін, олар компьютерде cookie файлдары сияқты іздер қалдырмайды. Дегенмен сіз жүктеп алған файлдардың барлығы сақталады.</translation>
 <translation id="3920504717067627103">Сертификат саясаттары</translation>
 <translation id="392089482157167418">ChromeVox құралын (дыбысты көмек) қосу</translation>
@@ -5915,6 +5916,7 @@
 <translation id="7167486101654761064">&amp;Түрі осындай файлдарды әрқашан ашу</translation>
 <translation id="716810439572026343"><ph name="FILE_NAME" /> жүктеу</translation>
 <translation id="7168109975831002660">Ең кіші қаріп өлшемі</translation>
+<translation id="7169122689956315694">Маңайда құрылғылар пайда болғанда хабарландыруды қосу</translation>
 <translation id="7170236477717446850">Профиль суреті</translation>
 <translation id="7171000599584840888">Профиль қосу…</translation>
 <translation id="7171259390164035663">Тіркелмеу</translation>
diff --git a/chrome/app/resources/generated_resources_ky.xtb b/chrome/app/resources/generated_resources_ky.xtb
index 1414691..dd9eac71 100644
--- a/chrome/app/resources/generated_resources_ky.xtb
+++ b/chrome/app/resources/generated_resources_ky.xtb
@@ -2901,6 +2901,7 @@
 <translation id="3916445069167113093">Файлдын мындай түрү компьютериңизге зыян келтириши мүмкүн. <ph name="FILE_NAME" /> баары бир кала берсинби?</translation>
 <translation id="3918972485393593704">Чоо-жайы тууралуу Google'га кабар бериңиз</translation>
 <translation id="3919145445993746351">Бардык компьютерлериңизден кеңейтүүлөрүңүздү алуу үчүн, шайкештирүүнү күйгүзүңүз</translation>
+<translation id="3919229493046408863">Түзмөктөр жакын болгондо билдирмени өчүрүү</translation>
 <translation id="3919798653937160644">Ачылып турган Конок терезелери жабылгандан кийин, бул терезеде каралган баракчалар серепчи таржымалында көрүнбөйт жана компьютерде cookie файлдары сыяктуу башка издерди калтырбайт. Бирок бардык жүктөлүп алынган файлдар сакталып кала берет.</translation>
 <translation id="3920504717067627103">Тастыктама саясаттары</translation>
 <translation id="392089482157167418">ChromeVox иштетүү (айтылуучу жооп пикир)</translation>
@@ -5935,6 +5936,7 @@
 <translation id="7167486101654761064">Мындай түрдөгү файлдар &amp;ар дайым ачылсын</translation>
 <translation id="716810439572026343"><ph name="FILE_NAME" /> жүктөлүп алынууда</translation>
 <translation id="7168109975831002660">Эң кичине арип өлчөмү</translation>
+<translation id="7169122689956315694">Түзмөктөр жакын болгондо билдирмени күйгүзүү</translation>
 <translation id="7170236477717446850">Профилдин сүрөтү</translation>
 <translation id="7171000599584840888">Профиль кошуу...</translation>
 <translation id="7171259390164035663">Катталбасын</translation>
diff --git a/chrome/app/resources/generated_resources_ml.xtb b/chrome/app/resources/generated_resources_ml.xtb
index 33a41bb..228e4e8 100644
--- a/chrome/app/resources/generated_resources_ml.xtb
+++ b/chrome/app/resources/generated_resources_ml.xtb
@@ -2885,6 +2885,7 @@
 <translation id="3916445069167113093">നിങ്ങളുടെ കമ്പ്യൂട്ടറിനെ ഇത്തരത്തിലുള്ള ഫയൽ ദ്രോഹിച്ചേക്കാം. <ph name="FILE_NAME" /> എന്നത് എന്തായാലും സൂക്ഷിക്കണമെന്നത് തീർച്ചയാണോ?</translation>
 <translation id="3918972485393593704">വിശദാംശങ്ങൾ Google-ന് റിപ്പോർട്ട് ചെയ്യുക</translation>
 <translation id="3919145445993746351">എല്ലാ കമ്പ്യൂട്ടറുകളിലും നിങ്ങളുടെ വിപുലീകരണങ്ങൾ ലഭിക്കാൻ, സമന്വയം ഓണാക്കുക</translation>
+<translation id="3919229493046408863">ഉപകരണങ്ങൾ സമീപത്തുള്ളപ്പോൾ അറിയിപ്പ് ഓഫാക്കുക</translation>
 <translation id="3919798653937160644">ഈ വിൻഡോയിൽ കാണുന്ന പേജുകൾ, നിങ്ങൾ തുറന്ന എല്ലാ അതിഥി വിൻഡോകളും അടച്ച ശേഷം ബ്രൗസർ ചരിത്രത്തിൽ ദൃശ്യമാകില്ല, അവ കുക്കികൾ പോലുള്ള മറ്റ് അടയാളങ്ങൾ കമ്പ്യൂട്ടറിൽ അവശേഷിപ്പിക്കുകയുമില്ല. എന്നിരുന്നാലും നിങ്ങൾ ഡൗൺലോഡ് ചെയ്യുന്ന എല്ലാ ഫയലുകളും സംരക്ഷിക്കും.</translation>
 <translation id="3920504717067627103">സര്‍‌ട്ടിഫിക്കറ്റ് നയങ്ങള്‍‌</translation>
 <translation id="392089482157167418">ChromeVox (സ്‌പോക്കൺ ഫീഡ്‌ബാക്ക്) പ്രവർത്തനക്ഷമമാക്കുക</translation>
@@ -5919,6 +5920,7 @@
 <translation id="7167486101654761064">&amp;എപ്പോഴും ഈ തരത്തിലുള്ള ഫയലുകള്‍ തുറക്കുക</translation>
 <translation id="716810439572026343"><ph name="FILE_NAME" /> ഡൗൺലോഡുചെയ്യുന്നു</translation>
 <translation id="7168109975831002660">കുറഞ്ഞ ഫോണ്ട് വലിപ്പം</translation>
+<translation id="7169122689956315694">ഉപകരണങ്ങൾ സമീപത്തുള്ളപ്പോൾ അറിയിപ്പ് ഓണാക്കുക</translation>
 <translation id="7170236477717446850">പ്രൊഫൈൽ ചിത്രം</translation>
 <translation id="7171000599584840888">പ്രൊഫൈൽ ചേർക്കുക...</translation>
 <translation id="7171259390164035663">എൻറോൾ ചെയ്യരുത്</translation>
diff --git a/chrome/app/resources/generated_resources_mn.xtb b/chrome/app/resources/generated_resources_mn.xtb
index 1f2866b..9b00f6a 100644
--- a/chrome/app/resources/generated_resources_mn.xtb
+++ b/chrome/app/resources/generated_resources_mn.xtb
@@ -2897,6 +2897,7 @@
 <translation id="3916445069167113093">Энэ төрлийн файл таны компьютерийг гэмтээж болно. Та ямар ч байсан <ph name="FILE_NAME" />-ийг хадгалахыг хүсч байна уу?</translation>
 <translation id="3918972485393593704">Google-д дэлгэрэнгүйг мэдээллэх</translation>
 <translation id="3919145445993746351">Өргөтгөлөө бүх компьютер дээрээ авахын тулд синкийг асаана уу</translation>
+<translation id="3919229493046408863">Төхөөрөмжүүд ойролцоо байх үед мэдэгдлийг унтраах</translation>
 <translation id="3919798653937160644">Таны энэ цонхонд үзсэн хуудаснууд хөтчийн түүхэд гарч ирэхгүй бөгөөд тэдгээр нь таныг Зочны нээлттэй бүх цонхыг хаасны дараа компьютер дээр күүки зэрэг бусад ул мөр үлдээхгүй. Гэсэн хэдий ч таны татсан аливаа файлыг хадгална.</translation>
 <translation id="3920504717067627103">Гэрчилгээний бодлого</translation>
 <translation id="392089482157167418">ChromeVox-ыг идэвхжүүлнэ (ярьсан санал хүсэлт)</translation>
@@ -5930,6 +5931,7 @@
 <translation id="7167486101654761064">&amp; Үргэлж энэ төрлийн файлыг нээх</translation>
 <translation id="716810439572026343"><ph name="FILE_NAME" />-ыг татаж авч байна</translation>
 <translation id="7168109975831002660">Үсгийн хамгийн бага хэмжээ</translation>
+<translation id="7169122689956315694">Төхөөрөмжүүд ойролцоо байх үед мэдэгдлийг асаах</translation>
 <translation id="7170236477717446850">Профайлын зураг</translation>
 <translation id="7171000599584840888">Профайл нэмэх...</translation>
 <translation id="7171259390164035663">Битгий бүртгүүл</translation>
diff --git a/chrome/app/resources/generated_resources_mr.xtb b/chrome/app/resources/generated_resources_mr.xtb
index 4878324..7f7fea1 100644
--- a/chrome/app/resources/generated_resources_mr.xtb
+++ b/chrome/app/resources/generated_resources_mr.xtb
@@ -2900,6 +2900,7 @@
 <translation id="3916445069167113093">या प्रकारची फाइल तुमच्या कॉंप्युटरला हानी पोहचवू शकते. तुम्ही तरीसुद्धा <ph name="FILE_NAME" /> ठेवू इच्छिता?</translation>
 <translation id="3918972485393593704">Google ला तपशील द्या</translation>
 <translation id="3919145445993746351">तुमच्या सर्व कॉंप्युटरवर एक्स्टेंशन मिळवण्यासाठी, सिंक सुरू करा</translation>
+<translation id="3919229493046408863">डिव्‍हाइस जवळपास असतात, तेव्हा सूचना बंद करा</translation>
 <translation id="3919798653937160644">या विंडोमध्ये तुम्ही पाहत असलेली पेज ही ब्राउझर इतिहासामध्ये दिसणार नाहीत आणि तुम्ही सर्व उघड्या अतिथी विंडो बंद केल्यानंतर ती काँप्युटरवर कुकीसारखे इतर माग सोडणार नाहीत. मात्र, तुम्ही डाउनलोड करत असलेल्या कोणत्याही फाइलचे जतन केले जाईल.</translation>
 <translation id="3920504717067627103">सर्टिफिकेट धोरणे</translation>
 <translation id="392089482157167418">ChromeVox (वाचिक अभिप्राय) सुरू करा</translation>
@@ -5933,6 +5934,7 @@
 <translation id="7167486101654761064">&amp;नेहमी या प्रकारच्या फाइल्स उघडा</translation>
 <translation id="716810439572026343"><ph name="FILE_NAME" /> डाउनलोड करीत आहे</translation>
 <translation id="7168109975831002660">किमान फॉंट आकार</translation>
+<translation id="7169122689956315694">डिव्‍हाइस जवळपास असतात, तेव्हा सूचना सुरू करा</translation>
 <translation id="7170236477717446850">प्रोफाइल फोटो</translation>
 <translation id="7171000599584840888">प्रोफाइल जोडा…</translation>
 <translation id="7171259390164035663">नोंदणी करू नका</translation>
diff --git a/chrome/app/resources/generated_resources_pa.xtb b/chrome/app/resources/generated_resources_pa.xtb
index 94f9b3b..fc5b126 100644
--- a/chrome/app/resources/generated_resources_pa.xtb
+++ b/chrome/app/resources/generated_resources_pa.xtb
@@ -2901,6 +2901,7 @@
 <translation id="3916445069167113093">ਇਸ ਕਿਸਮ ਦੀ ਫ਼ਾਈਲ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਨੂੰ ਨੁਕਸਾਨ ਪਹੁੰਚਾ ਸਕਦੀ ਹੈ। ਕੀ ਤੁਸੀਂ ਫੇਰ ਵੀ <ph name="FILE_NAME" /> ਨੂੰ ਰੱਖਣਾ ਚਾਹੁੰਦੇ ਹੋ?</translation>
 <translation id="3918972485393593704">Google ਨੂੰ ਵੇਰਵਿਆਂ ਦੀ ਰਿਪੋਰਟ ਕਰੋ</translation>
 <translation id="3919145445993746351">ਆਪਣੇ ਸਾਰੇ ਕੰਪਿਊਟਰਾਂ 'ਤੇ ਆਪਣੀਆਂ ਐਕਸਟੈਂਸ਼ਨਾਂ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ, ਸਮਕਾਲੀਕਰਨ ਚਾਲੂ ਕਰੋ</translation>
+<translation id="3919229493046408863">ਡੀਵਾਈਸਾਂ ਦੇ ਨਜ਼ਦੀਕ ਹੋਣ 'ਤੇ ਸੂਚਨਾ ਬੰਦ ਕਰੋ</translation>
 <translation id="3919798653937160644">ਜੋ ਪੰਨੇ ਤੁਸੀਂ ਇਸ ਵਿੰਡੋ ਵਿੱਚ ਦੇਖਦੇ ਹੋ, ਉਹ ਬ੍ਰਾਊਜ਼ਿੰਗ ਇਤਿਹਾਸ ਵਿੱਚ ਦਿਖਾਈ ਨਹੀਂ ਦੇਣਗੇ ਅਤੇ ਉਹ ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਾਰੀਆਂ ਖੁੱਲ੍ਹੀਆਂ ਮਹਿਮਾਨ ਵਿੰਡੋਆਂ ਨੂੰ ਬੰਦ ਕੀਤੇ ਜਾਣ ਤੋਂ ਬਾਅਦ ਕੰਪਿਊਟਰ 'ਤੇ ਹੋਰ ਟ੍ਰੇਸ ਨਹੀਂ ਛੱਡਣਗੇ, ਜਿਵੇਂ ਕੁਕੀਜ਼। ਹਾਲਾਂਕਿ ਜੋ ਫ਼ਾਈਲਾਂ ਤੁਸੀਂ ਡਾਊਨਲੋਡ ਕਰਦੇ ਹੋ, ਸੁਰੱਖਿਅਤ ਰੱਖੀਆਂ ਜਾਣਗੀਆਂ।</translation>
 <translation id="3920504717067627103">ਪ੍ਰਮਾਣ-ਪੱਤਰ ਨੀਤੀਆਂ</translation>
 <translation id="392089482157167418">ChromeVox ਨੂੰ ਚਾਲੂ ਕਰੋ (ਬੋਲੀ ਪ੍ਰਤੀਕਰਮ)</translation>
@@ -5936,6 +5937,7 @@
 <translation id="7167486101654761064">&amp;ਹਮੇਸ਼ਾਂ ਇਸ ਪ੍ਰਕਾਰ ਦੀਆਂ ਫਾਈਲਾਂ ਖੋਲ੍ਹੋ</translation>
 <translation id="716810439572026343"><ph name="FILE_NAME" /> ਨੂੰ ਡਾਊਨਲੋਡ ਕਰ ਰਿਹਾ ਹੈ</translation>
 <translation id="7168109975831002660">ਨਿਊਨਤਮ ਫੌਂਟ ਆਕਾਰ</translation>
+<translation id="7169122689956315694">ਡੀਵਾਈਸਾਂ ਦੇ ਨਜ਼ਦੀਕ ਹੋਣ 'ਤੇ ਸੂਚਨਾ ਚਾਲੂ ਕਰੋ</translation>
 <translation id="7170236477717446850">ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ</translation>
 <translation id="7171000599584840888">ਪ੍ਰੋਫਾਈਲ ਸ਼ਾਮਲ ਕਰੋ...</translation>
 <translation id="7171259390164035663">ਦਰਜ ਨਾ ਹੋਵੋ</translation>
diff --git a/chrome/app/resources/generated_resources_sr-Latn.xtb b/chrome/app/resources/generated_resources_sr-Latn.xtb
index 01a8581..a1b70d2d 100644
--- a/chrome/app/resources/generated_resources_sr-Latn.xtb
+++ b/chrome/app/resources/generated_resources_sr-Latn.xtb
@@ -2885,6 +2885,7 @@
 <translation id="3916445069167113093">Ovaj tip datoteke može da naškodi računaru. Da li ipak želite da zadržite datoteku <ph name="FILE_NAME" />?</translation>
 <translation id="3918972485393593704">Šalji detalje Google-u</translation>
 <translation id="3919145445993746351">Da bi vam dodaci bili dostupni na svim računarima, uključite sinhronizaciju</translation>
+<translation id="3919229493046408863">Isključite obaveštenja kada su uređaji u blizini</translation>
 <translation id="3919798653937160644">Stranice koje vidite u ovom prozoru se neće pojavljivati u istoriji pregledača i neće ostavljati druge tragove, poput kolačića, na računaru kada zatvorite sve otvorene prozore režima gosta. Međutim, svi fajlovi koje preuzmete će biti sačuvani.</translation>
 <translation id="3920504717067627103">Smernice sertifikata</translation>
 <translation id="392089482157167418">Omogući ChromeVox (govorne povratne informacije)</translation>
@@ -5918,6 +5919,7 @@
 <translation id="7167486101654761064">&amp;Uvek otvori datoteke ovog tipa</translation>
 <translation id="716810439572026343">Preuzimate <ph name="FILE_NAME" /></translation>
 <translation id="7168109975831002660">Minimalna veličina fonta</translation>
+<translation id="7169122689956315694">Uključite obaveštenja kada su uređaji u blizini</translation>
 <translation id="7170236477717446850">Slika profila</translation>
 <translation id="7171000599584840888">Dodaj profil…</translation>
 <translation id="7171259390164035663">Bez registracije</translation>
diff --git a/chrome/app/resources/generated_resources_sr.xtb b/chrome/app/resources/generated_resources_sr.xtb
index e924d18..18310f8 100644
--- a/chrome/app/resources/generated_resources_sr.xtb
+++ b/chrome/app/resources/generated_resources_sr.xtb
@@ -2885,6 +2885,7 @@
 <translation id="3916445069167113093">Овај тип датотеке може да нашкоди рачунару. Да ли ипак желите да задржите датотеку <ph name="FILE_NAME" />?</translation>
 <translation id="3918972485393593704">Шаљи детаље Google-у</translation>
 <translation id="3919145445993746351">Да би вам додаци били доступни на свим рачунарима, укључите синхронизацију</translation>
+<translation id="3919229493046408863">Искључите обавештења када су уређаји у близини</translation>
 <translation id="3919798653937160644">Странице које видите у овом прозору се неће појављивати у историји прегледача и неће остављати друге трагове, попут колачића, на рачунару када затворите све отворене прозоре режима госта. Међутим, сви фајлови које преузмете ће бити сачувани.</translation>
 <translation id="3920504717067627103">Смернице сертификата</translation>
 <translation id="392089482157167418">Омогући ChromeVox (говорне повратне информације)</translation>
@@ -5918,6 +5919,7 @@
 <translation id="7167486101654761064">&amp;Увек отвори датотеке овог типа</translation>
 <translation id="716810439572026343">Преузимате <ph name="FILE_NAME" /></translation>
 <translation id="7168109975831002660">Минимална величина фонта</translation>
+<translation id="7169122689956315694">Укључите обавештења када су уређаји у близини</translation>
 <translation id="7170236477717446850">Слика профила</translation>
 <translation id="7171000599584840888">Додај профил…</translation>
 <translation id="7171259390164035663">Без регистрације</translation>
diff --git a/chrome/app/resources/generated_resources_ta.xtb b/chrome/app/resources/generated_resources_ta.xtb
index 5d62c80..4ed2c99 100644
--- a/chrome/app/resources/generated_resources_ta.xtb
+++ b/chrome/app/resources/generated_resources_ta.xtb
@@ -2901,6 +2901,7 @@
 <translation id="3916445069167113093">இவ்வகையான ஃபைல் உங்கள் கம்ப்யூட்டரைப் பாதிக்கக்கூடும். இருப்பினும் <ph name="FILE_NAME" /> ஐ வைத்திருக்க வேண்டுமா?</translation>
 <translation id="3918972485393593704">Googleளுக்கு விவரங்களை அனுப்பு</translation>
 <translation id="3919145445993746351">உங்கள் அனைத்துக் கணிணிகளிலும் நீட்டிப்புகளைப் பெற, ஒத்திசைவை இயக்கவும்</translation>
+<translation id="3919229493046408863">சாதனங்கள் அருகில் இருக்கும்போது அறிவிப்பை முடக்கு</translation>
 <translation id="3919798653937160644">இந்தச் சாளரத்தில் நீங்கள் பார்க்கும் பக்கங்கள் உலாவியின் இதுவரையான செயல்பாடுகளில் தோன்றாது. திறக்கப்பட்டிருக்கும் கெஸ்ட் சாளரங்கள் அனைத்தையும் மூடியபிறகு அவை குக்கீகள் போன்ற பிற தடங்களைக் கம்ப்யூட்டரில் விட்டுச் செல்லாது. இருப்பினும், நீங்கள் பதிவிறக்கிய ஃபைல்கள்  அனைத்தும் பாதுகாக்கப்படும்.</translation>
 <translation id="3920504717067627103">சான்றிதழ் கொள்கைகள்</translation>
 <translation id="392089482157167418">ChromeVox (பேச்சுவடிவ கருத்து) ஐ இயக்கு</translation>
@@ -5936,6 +5937,7 @@
 <translation id="7167486101654761064">&amp;எப்போதும் இந்த வகை ஃபைல்களைத் திற</translation>
 <translation id="716810439572026343"><ph name="FILE_NAME" />ஐப் பதிவிறக்குகிறது</translation>
 <translation id="7168109975831002660">குறைந்தபட்ச எழுத்து வடிவ அளவு</translation>
+<translation id="7169122689956315694">சாதனங்கள் அருகில் இருக்கும்போது அறிவிப்பை இயக்கு</translation>
 <translation id="7170236477717446850">சுயவிவரப் படம்</translation>
 <translation id="7171000599584840888">சுயவிவரத்தைச் சேர்...</translation>
 <translation id="7171259390164035663">பதிவுசெய்ய வேண்டாம்</translation>
diff --git a/chrome/app/resources/generated_resources_uk.xtb b/chrome/app/resources/generated_resources_uk.xtb
index d6ed883d..afa7666 100644
--- a/chrome/app/resources/generated_resources_uk.xtb
+++ b/chrome/app/resources/generated_resources_uk.xtb
@@ -2904,6 +2904,7 @@
 <translation id="3916445069167113093">Цей тип файлу може зашкодити вашому комп’ютеру. Усе одно зберегти <ph name="FILE_NAME" />?</translation>
 <translation id="3918972485393593704">Надішліть у Google докладнішу інформацію</translation>
 <translation id="3919145445993746351">Щоб користуватися розширеннями на всіх комп’ютерах, увімкніть синхронізацію</translation>
+<translation id="3919229493046408863">Вимкнути сповіщення, якщо буде знайдено пристрої поблизу</translation>
 <translation id="3919798653937160644">Сторінки, які ви переглядаєте в цьому вікні, не записуватимуться в історію веб-перегляду, а також не залишать на комп'ютері інших слідів (на зразок файлів cookie), коли ви закриєте всі вікна, відкриті в гостьовому режимі. Однак завантажені файли зберігатимуться.</translation>
 <translation id="3920504717067627103">Політика сертифікатів</translation>
 <translation id="392089482157167418">Увімкнути ChromeVox (голосові підказки)</translation>
@@ -5938,6 +5939,7 @@
 <translation id="7167486101654761064">&amp;Завжди відкривати файли цього типу</translation>
 <translation id="716810439572026343">Завантаження файлу "<ph name="FILE_NAME" />"</translation>
 <translation id="7168109975831002660">Мінімальний розмір шрифту</translation>
+<translation id="7169122689956315694">Увімкнути сповіщення, якщо буде знайдено пристрої поблизу</translation>
 <translation id="7170236477717446850">Зображення профілю</translation>
 <translation id="7171000599584840888">Додати профіль…</translation>
 <translation id="7171259390164035663">Пропустити реєстрацію</translation>
diff --git a/chrome/app/resources/generated_resources_ur.xtb b/chrome/app/resources/generated_resources_ur.xtb
index ad9566dc..55fd3d26 100644
--- a/chrome/app/resources/generated_resources_ur.xtb
+++ b/chrome/app/resources/generated_resources_ur.xtb
@@ -2885,6 +2885,7 @@
 <translation id="3916445069167113093">اس قسم کی فائل سے آپ کے کمپیوٹر کو نقصان پہنچ سکتا ہے۔ کیا آپ <ph name="FILE_NAME" /> کو بہر صورت رکھنا چاہتے ہیں؟</translation>
 <translation id="3918972485393593704">‏Google کو تفصیلات کی اطلاع دیں</translation>
 <translation id="3919145445993746351">اپنے سبھی کمپیوٹرز پر اپنی ایکسٹینشنز حاصل کرنے کے لیے، مطابقت پذیری کو آن کریں</translation>
+<translation id="3919229493046408863">آلات کے قریب ہونے پر اطلاع کو آف کریں</translation>
 <translation id="3919798653937160644">جو صفحات آپ اس ونڈو میں دیکھتے ہیں وہ براؤزر کی سرگزشت میں ظاہر نہیں ہوں گے اور جب آپ سبھی کھلی ہوئی مہمان ونڈوز بند کر دیں گے تو وہ آپ کے کمپیوٹر پر کوکیز جیسے دیگر نشانات نہیں چھوڑیں گے۔ تاہم، جو بھی فائلیں آپ ڈاؤن لوڈ کریں گے انہیں برقرار رکھا جائے گا۔</translation>
 <translation id="3920504717067627103">سرٹیفکیٹ کی پالیسیاں</translation>
 <translation id="392089482157167418">‏ChromeVox فعال کریں (بولے جانے والے تاثرات)</translation>
@@ -5917,6 +5918,7 @@
 <translation id="7167486101654761064">اس قسم کی فائلیں &amp;ہمیشہ کھولیں</translation>
 <translation id="716810439572026343"><ph name="FILE_NAME" /> ڈاؤن لوڈ لو رہی ہے</translation>
 <translation id="7168109975831002660">کم از کم فونٹ سائز</translation>
+<translation id="7169122689956315694">آلات کے قریب ہونے پر اطلاع کو آن کریں</translation>
 <translation id="7170236477717446850">پروفائل تصویر</translation>
 <translation id="7171000599584840888">پروفائل شامل کریں...</translation>
 <translation id="7171259390164035663">اندراج نہ کریں</translation>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 0c4c7cebb..bd251c1 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1127,8 +1127,6 @@
     "permissions/permission_manager_factory.h",
     "permissions/prediction_based_permission_ui_selector.cc",
     "permissions/prediction_based_permission_ui_selector.h",
-    "permissions/prediction_model_handler_factory.cc",
-    "permissions/prediction_model_handler_factory.h",
     "permissions/prediction_service_factory.cc",
     "permissions/prediction_service_factory.h",
     "permissions/prediction_service_request.cc",
@@ -7256,6 +7254,13 @@
       "component_updater/file_type_policies_component_installer.h",
     ]
   }
+
+  if (build_with_tflite_lib) {
+    sources += [
+      "permissions/prediction_model_handler_factory.cc",
+      "permissions/prediction_model_handler_factory.h",
+    ]
+  }
 }
 
 if (is_android) {
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index ef82a164..d3f0e6b1 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3880,6 +3880,12 @@
     {"ozone-platform-hint", flag_descriptions::kOzonePlatformHintName,
      flag_descriptions::kOzonePlatformHintDescription, kOsLinux,
      MULTI_VALUE_TYPE(kOzonePlatformHintRuntimeChoices)},
+
+    {"clean-undecryptable-passwords",
+     flag_descriptions::kCleanUndecryptablePasswordsLinuxName,
+     flag_descriptions::kCleanUndecryptablePasswordsLinuxDescription, kOsLinux,
+     FEATURE_VALUE_TYPE(
+         password_manager::features::kSyncUndecryptablePasswordsLinux)},
 #endif
 
 #if BUILDFLAG(ENABLE_VR)
diff --git a/chrome/browser/ash/cert_provisioning/cert_provisioning_worker.cc b/chrome/browser/ash/cert_provisioning/cert_provisioning_worker.cc
index 1f1abf2..ff84fc9 100644
--- a/chrome/browser/ash/cert_provisioning/cert_provisioning_worker.cc
+++ b/chrome/browser/ash/cert_provisioning/cert_provisioning_worker.cc
@@ -99,28 +99,28 @@
   switch (state) {
     case CertProvisioningWorkerState::kInitState:
       res -= 1;
-      FALLTHROUGH;
+      [[fallthrough]];
     case CertProvisioningWorkerState::kKeypairGenerated:
       res -= 1;
-      FALLTHROUGH;
+      [[fallthrough]];
     case CertProvisioningWorkerState::kStartCsrResponseReceived:
       res -= 1;
-      FALLTHROUGH;
+      [[fallthrough]];
     case CertProvisioningWorkerState::kVaChallengeFinished:
       res -= 1;
-      FALLTHROUGH;
+      [[fallthrough]];
     case CertProvisioningWorkerState::kKeyRegistered:
       res -= 1;
-      FALLTHROUGH;
+      [[fallthrough]];
     case CertProvisioningWorkerState::kKeypairMarked:
       res -= 1;
-      FALLTHROUGH;
+      [[fallthrough]];
     case CertProvisioningWorkerState::kSignCsrFinished:
       res -= 1;
-      FALLTHROUGH;
+      [[fallthrough]];
     case CertProvisioningWorkerState::kFinishCsrResponseReceived:
       res -= 1;
-      FALLTHROUGH;
+      [[fallthrough]];
     case CertProvisioningWorkerState::kSucceeded:
     case CertProvisioningWorkerState::kInconsistentDataError:
     case CertProvisioningWorkerState::kFailed:
diff --git a/chrome/browser/ash/child_accounts/time_limits/web_time_limit_enforcer.cc b/chrome/browser/ash/child_accounts/time_limits/web_time_limit_enforcer.cc
index f33cbef1..0b08b989 100644
--- a/chrome/browser/ash/child_accounts/time_limits/web_time_limit_enforcer.cc
+++ b/chrome/browser/ash/child_accounts/time_limits/web_time_limit_enforcer.cc
@@ -16,8 +16,8 @@
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_features.h"
-#include "components/policy/core/browser/url_util.h"
 #include "components/url_matcher/url_matcher.h"
+#include "components/url_matcher/url_util.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/reload_type.h"
 #include "content/public/browser/web_contents.h"
@@ -87,7 +87,7 @@
   if (!url_matcher_)
     return false;
 
-  GURL effective_url = policy::url_util::Normalize(url);
+  GURL effective_url = url_matcher::util::Normalize(url);
   if (!effective_url.is_valid())
     effective_url = url;
 
diff --git a/chrome/browser/ash/customization/customization_document.cc b/chrome/browser/ash/customization/customization_document.cc
index c4a5a3bb0..0b24ee89 100644
--- a/chrome/browser/ash/customization/customization_document.cc
+++ b/chrome/browser/ash/customization/customization_document.cc
@@ -782,8 +782,7 @@
   } else {
     const base::DictionaryValue* root = &base::Value::AsDictionaryValue(
         *profile->GetPrefs()->GetDictionary(kServicesCustomizationKey));
-    std::string version;
-    if (root && root->GetString(kVersionAttr, &version)) {
+    if (root && root->FindStringKey(kVersionAttr)) {
       // If version exists, profile has cached version of customization.
       loader->SetCurrentApps(GetDefaultAppsInProviderFormat(*root));
       SetOemFolderName(profile, *root);
diff --git a/chrome/browser/ash/customization/customization_document.h b/chrome/browser/ash/customization/customization_document.h
index 36283ee..23069cf4 100644
--- a/chrome/browser/ash/customization/customization_document.h
+++ b/chrome/browser/ash/customization/customization_document.h
@@ -22,6 +22,7 @@
 class Profile;
 
 namespace base {
+// TODO(crbug.com/1187061): Refactor this to remove base::DictionaryValue.
 class DictionaryValue;
 class FilePath;
 }  // namespace base
diff --git a/chrome/browser/ash/device_name/device_name_store_impl.cc b/chrome/browser/ash/device_name/device_name_store_impl.cc
index be5465f0..59fd3f37 100644
--- a/chrome/browser/ash/device_name/device_name_store_impl.cc
+++ b/chrome/browser/ash/device_name/device_name_store_impl.cc
@@ -93,14 +93,14 @@
   switch (handler_->GetDeviceNamePolicy()) {
     case policy::DeviceNamePolicyHandler::DeviceNamePolicy::
         kPolicyHostnameNotConfigurable:
-      FALLTHROUGH;
+      [[fallthrough]];
     case policy::DeviceNamePolicyHandler::DeviceNamePolicy::
         kPolicyHostnameChosenByAdmin:
       return true;
 
     case policy::DeviceNamePolicyHandler::DeviceNamePolicy::
         kPolicyHostnameConfigurableByManagedUser:
-      FALLTHROUGH;
+      [[fallthrough]];
     case policy::DeviceNamePolicyHandler::DeviceNamePolicy::kNoPolicy:
       return false;
   }
diff --git a/chrome/browser/ash/login/easy_unlock/easy_unlock_service_regular.cc b/chrome/browser/ash/login/easy_unlock/easy_unlock_service_regular.cc
index cbf5776f..ec09ead 100644
--- a/chrome/browser/ash/login/easy_unlock/easy_unlock_service_regular.cc
+++ b/chrome/browser/ash/login/easy_unlock/easy_unlock_service_regular.cc
@@ -306,11 +306,13 @@
 }
 
 const base::ListValue* EasyUnlockServiceRegular::GetRemoteDevices() const {
-  const base::DictionaryValue* pairing_dict = &base::Value::AsDictionaryValue(
-      *profile()->GetPrefs()->GetDictionary(prefs::kEasyUnlockPairing));
-  const base::ListValue* devices = NULL;
-  if (pairing_dict && pairing_dict->GetList(kKeyDevices, &devices))
-    return devices;
+  const base::Value* pairing_dict =
+      profile()->GetPrefs()->GetDictionary(prefs::kEasyUnlockPairing);
+  if (pairing_dict) {
+    const base::Value* devices = pairing_dict->FindListKey(kKeyDevices);
+    if (devices)
+      return &base::Value::AsListValue(*devices);
+  }
   return NULL;
 }
 
diff --git a/chrome/browser/ash/login/easy_unlock/smartlock_state_handler.cc b/chrome/browser/ash/login/easy_unlock/smartlock_state_handler.cc
index 50cac945..df009b47 100644
--- a/chrome/browser/ash/login/easy_unlock/smartlock_state_handler.cc
+++ b/chrome/browser/ash/login/easy_unlock/smartlock_state_handler.cc
@@ -34,7 +34,7 @@
         return proximity_auth::ScreenlockBridge::
             USER_POD_CUSTOM_ICON_LOCKED_TO_BE_ACTIVATED;
       }
-      FALLTHROUGH;
+      [[fallthrough]];
     case SmartLockState::kBluetoothDisabled:
     case SmartLockState::kPhoneNotFound:
     case SmartLockState::kPhoneNotAuthenticated:
diff --git a/chrome/browser/ash/login/enrollment/auto_enrollment_check_screen.cc b/chrome/browser/ash/login/enrollment/auto_enrollment_check_screen.cc
index 30daadf..d607a5d 100644
--- a/chrome/browser/ash/login/enrollment/auto_enrollment_check_screen.cc
+++ b/chrome/browser/ash/login/enrollment/auto_enrollment_check_screen.cc
@@ -216,7 +216,7 @@
 
       // Fall to the same behavior like any connection error if the device is
       // enrolled.
-      FALLTHROUGH;
+      [[fallthrough]];
     case policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR:
       ShowErrorScreen(NetworkError::ERROR_STATE_OFFLINE);
       return true;
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_controller.cc b/chrome/browser/ash/policy/dlp/dlp_files_controller.cc
new file mode 100644
index 0000000..41a2b66
--- /dev/null
+++ b/chrome/browser/ash/policy/dlp/dlp_files_controller.cc
@@ -0,0 +1,108 @@
+// Copyright 2021 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/policy/dlp/dlp_files_controller.h"
+
+#include "base/bind.h"
+#include "base/check.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h"
+#include "chromeos/dbus/dlp/dlp_client.h"
+#include "storage/browser/file_system/file_system_url.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace policy {
+
+namespace {
+
+absl::optional<ino_t> GetInodeValue(const base::FilePath& path) {
+  struct stat file_stats;
+  if (stat(path.value().c_str(), &file_stats) != 0)
+    return absl::nullopt;
+  return file_stats.st_ino;
+}
+
+base::flat_map<ino_t, storage::FileSystemURL> GetFilesInodes(
+    const std::vector<storage::FileSystemURL>& transferred_files) {
+  base::flat_map<ino_t, storage::FileSystemURL> files_map;
+  dlp::GetFilesSourcesRequest request;
+  for (const auto& file : transferred_files) {
+    absl::optional<ino_t> inode = GetInodeValue(file.path());
+    if (inode.has_value())
+      files_map[inode.value()] = file;
+  }
+  return files_map;
+}
+
+}  // namespace
+
+DlpFilesController::DlpFilesController(DlpRulesManager* dlp_rules_manager)
+    : dlp_rules_manager_(dlp_rules_manager) {
+  DCHECK(dlp_rules_manager);
+}
+
+DlpFilesController::~DlpFilesController() = default;
+
+void DlpFilesController::GetDisallowedTransfers(
+    const std::vector<storage::FileSystemURL>& transferred_files,
+    storage::FileSystemURL destination,
+    GetDisallowedTransfersCallback result_callback) {
+  if (!chromeos::DlpClient::Get() || !chromeos::DlpClient::Get()->IsAlive()) {
+    std::move(result_callback).Run(std::vector<storage::FileSystemURL>());
+    return;
+  }
+
+  base::ThreadPool::PostTaskAndReplyWithResult(
+      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+      base::BindOnce(&GetFilesInodes, transferred_files),
+      base::BindOnce(&DlpFilesController::GetFilesSources,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(destination),
+                     std::move(result_callback)));
+}
+
+void DlpFilesController::GetFilesSources(
+    storage::FileSystemURL destination,
+    GetDisallowedTransfersCallback result_callback,
+    base::flat_map<ino_t, storage::FileSystemURL> files_map) {
+  dlp::GetFilesSourcesRequest request;
+  for (const auto& file_inode_url : files_map) {
+    request.add_files_inodes(file_inode_url.first);
+  }
+
+  chromeos::DlpClient::Get()->GetFilesSources(
+      request,
+      base::BindOnce(&DlpFilesController::OnGetFilesSourcesReply,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(files_map),
+                     std::move(destination), std::move(result_callback)));
+}
+
+void DlpFilesController::OnGetFilesSourcesReply(
+    base::flat_map<ino_t, storage::FileSystemURL> files_map,
+    storage::FileSystemURL destination,
+    GetDisallowedTransfersCallback result_callback,
+    const dlp::GetFilesSourcesResponse response) {
+  if (response.has_error_message()) {
+    LOG(ERROR) << "Failed to get files sources, error: "
+               << response.error_message();
+  }
+  // TODO(crbug.com/1273793): Change to handle VMs, external drive, ...etc.
+  std::vector<storage::FileSystemURL> restricted_files;
+  for (const auto& file : response.files_metadata()) {
+    DlpRulesManager::Level level = dlp_rules_manager_->IsRestrictedDestination(
+        GURL(file.source_url()), destination.ToGURL(),
+        DlpRulesManager::Restriction::kFiles, nullptr, nullptr);
+    if (level == DlpRulesManager::Level::kBlock) {
+      auto blocked_file_itr = files_map.find(file.inode());
+      DCHECK(blocked_file_itr != files_map.end());
+      restricted_files.push_back(blocked_file_itr->second);
+    }
+  }
+  std::move(result_callback).Run(std::move(restricted_files));
+}
+
+}  // namespace policy
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_controller.h b/chrome/browser/ash/policy/dlp/dlp_files_controller.h
new file mode 100644
index 0000000..0cba034e
--- /dev/null
+++ b/chrome/browser/ash/policy/dlp/dlp_files_controller.h
@@ -0,0 +1,62 @@
+// Copyright 2021 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_POLICY_DLP_DLP_FILES_CONTROLLER_H_
+#define CHROME_BROWSER_ASH_POLICY_DLP_DLP_FILES_CONTROLLER_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/containers/flat_map.h"
+#include "base/memory/weak_ptr.h"
+#include "chromeos/dbus/dlp/dlp_service.pb.h"
+
+namespace storage {
+class FileSystemURL;
+}  // namespace storage
+
+namespace policy {
+
+class DlpRulesManager;
+
+// DlpFilesController is responsible for deciding whether file transfers are
+// allowed according to the files sources saved in the DLP daemon and the rules
+// of the Data leak prevention policy set by the admin.
+class DlpFilesController {
+ public:
+  using GetDisallowedTransfersCallback =
+      base::OnceCallback<void(std::vector<storage::FileSystemURL>)>;
+
+  // `dlp_rules_manager` must outlive this class.
+  explicit DlpFilesController(DlpRulesManager* dlp_rules_manager);
+
+  DlpFilesController(const DlpFilesController& other) = delete;
+  DlpFilesController& operator=(const DlpFilesController& other) = delete;
+
+  ~DlpFilesController();
+
+  // Returns a list of files disallowed to be transferred in |result_callback|.
+  void GetDisallowedTransfers(
+      const std::vector<storage::FileSystemURL>& transferred_files,
+      storage::FileSystemURL destination,
+      GetDisallowedTransfersCallback result_callback);
+
+ private:
+  void GetFilesSources(storage::FileSystemURL destination,
+                       GetDisallowedTransfersCallback result_callback,
+                       base::flat_map<ino_t, storage::FileSystemURL> files_map);
+  void OnGetFilesSourcesReply(
+      base::flat_map<ino_t, storage::FileSystemURL> files_map,
+      storage::FileSystemURL destination,
+      GetDisallowedTransfersCallback result_callback,
+      const dlp::GetFilesSourcesResponse response);
+
+  DlpRulesManager* dlp_rules_manager_;  // Unowned.
+
+  base::WeakPtrFactory<DlpFilesController> weak_ptr_factory_{this};
+};
+
+}  // namespace policy
+
+#endif  // CHROME_BROWSER_ASH_POLICY_DLP_DLP_FILES_CONTROLLER_H_
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_controller_unittest.cc b/chrome/browser/ash/policy/dlp/dlp_files_controller_unittest.cc
new file mode 100644
index 0000000..899b70699
--- /dev/null
+++ b/chrome/browser/ash/policy/dlp/dlp_files_controller_unittest.cc
@@ -0,0 +1,132 @@
+// Copyright 2021 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/policy/dlp/dlp_files_controller.h"
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/check.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "base/test/mock_callback.h"
+#include "chrome/browser/chromeos/policy/dlp/mock_dlp_rules_manager.h"
+#include "chromeos/dbus/dlp/dlp_client.h"
+#include "chromeos/dbus/dlp/dlp_service.pb.h"
+#include "content/public/test/browser_task_environment.h"
+#include "storage/browser/file_system/file_system_url.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/browser/test/test_file_system_context.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace policy {
+
+namespace {
+
+ino_t GetInodeValue(const base::FilePath& path) {
+  struct stat file_stats;
+  if (stat(path.value().c_str(), &file_stats) != 0)
+    return 0;
+  return file_stats.st_ino;
+}
+
+bool CreateDummyFile(const base::FilePath& path) {
+  return WriteFile(path, "42", sizeof("42")) == sizeof("42");
+}
+
+}  // namespace
+
+class DlpFilesControllerTest : public testing::Test {
+ protected:
+  DlpFilesControllerTest() : files_controller_(&rules_manager_) {}
+
+  DlpFilesControllerTest(const DlpFilesControllerTest&) = delete;
+  DlpFilesControllerTest& operator=(const DlpFilesControllerTest&) = delete;
+
+  ~DlpFilesControllerTest() override = default;
+
+  void SetUp() override {
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+    file_system_context_ = storage::CreateFileSystemContextForTesting(
+        nullptr, temp_dir_.GetPath());
+  }
+
+  storage::FileSystemURL CreateFileSystemURL(const std::string& path) {
+    return file_system_context_->CreateCrackedFileSystemURL(
+        kTestStorageKey, storage::kFileSystemTypeTest,
+        base::FilePath::FromUTF8Unsafe(path));
+  }
+
+  content::BrowserTaskEnvironment task_environment_;
+
+  const blink::StorageKey kTestStorageKey =
+      blink::StorageKey::CreateFromStringForTesting("https://example.com/test");
+
+  base::ScopedTempDir temp_dir_;
+  scoped_refptr<storage::FileSystemContext> file_system_context_;
+  testing::StrictMock<MockDlpRulesManager> rules_manager_;
+  DlpFilesController files_controller_;
+};
+
+TEST_F(DlpFilesControllerTest, GetDisallowedTransfers) {
+  chromeos::DlpClient::InitializeFake();
+  base::MockCallback<chromeos::DlpClient::AddFileCallback> add_file_cb;
+
+  EXPECT_CALL(add_file_cb, Run(testing::_)).Times(3);
+
+  const base::FilePath path = temp_dir_.GetPath();
+
+  const base::FilePath file1 = path.AppendASCII("test1.txt");
+  ASSERT_TRUE(CreateDummyFile(file1));
+  dlp::AddFileRequest add_file_req1;
+  add_file_req1.set_file_path(file1.value());
+  add_file_req1.set_source_url("example1.com");
+  chromeos::DlpClient::Get()->AddFile(add_file_req1, add_file_cb.Get());
+
+  const base::FilePath file2 = path.AppendASCII("test2.txt");
+  ASSERT_TRUE(CreateDummyFile(file2));
+  dlp::AddFileRequest add_file_req2;
+  add_file_req2.set_file_path(file2.value());
+  add_file_req2.set_source_url("example2.com");
+  chromeos::DlpClient::Get()->AddFile(add_file_req2, add_file_cb.Get());
+
+  const base::FilePath file3 = path.AppendASCII("test3.txt");
+  ASSERT_TRUE(CreateDummyFile(file3));
+  dlp::AddFileRequest add_file_req3;
+  add_file_req3.set_file_path(file3.value());
+  add_file_req3.set_source_url("example3.com");
+  chromeos::DlpClient::Get()->AddFile(add_file_req3, add_file_cb.Get());
+
+  testing::Mock::VerifyAndClearExpectations(&add_file_cb);
+
+  storage::FileSystemURL file_url1 = CreateFileSystemURL(file1.value());
+  storage::FileSystemURL file_url2 = CreateFileSystemURL(file2.value());
+  storage::FileSystemURL file_url3 = CreateFileSystemURL(file3.value());
+  std::vector<storage::FileSystemURL> transferred_files(
+      {file_url1, file_url2, file_url3});
+  std::vector<storage::FileSystemURL> disallowed_files({file_url1, file_url3});
+  base::MockCallback<DlpFilesController::GetDisallowedTransfersCallback>
+      disallowed_transfers_cb;
+
+  EXPECT_CALL(disallowed_transfers_cb, Run(disallowed_files));
+  EXPECT_CALL(rules_manager_, IsRestrictedDestination)
+      .WillOnce(testing::Return(DlpRulesManager::Level::kBlock))
+      .WillOnce(testing::Return(DlpRulesManager::Level::kAllow))
+      .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
+
+  base::RunLoop run_loop;
+  base::RepeatingClosure quit_closure = run_loop.QuitClosure();
+
+  files_controller_.GetDisallowedTransfers(
+      transferred_files, CreateFileSystemURL("Downloads"),
+      disallowed_transfers_cb.Get().Then(std::move(quit_closure)));
+
+  run_loop.Run();
+}
+
+}  // namespace policy
diff --git a/chrome/browser/ash/scanning/scan_service.cc b/chrome/browser/ash/scanning/scan_service.cc
index 84eda79..b59bb89 100644
--- a/chrome/browser/ash/scanning/scan_service.cc
+++ b/chrome/browser/ash/scanning/scan_service.cc
@@ -56,7 +56,7 @@
           chromeos::features::kScanAppSearchablePdf));
       // Temporarily set searchable pdfs to follow png pipeline while
       // implementing.
-      FALLTHROUGH;
+      [[fallthrough]];
     case mojo_ipc::FileType::kPng:
       file_ext = "png";
       break;
diff --git a/chrome/browser/ash/system/device_disabling_manager.cc b/chrome/browser/ash/system/device_disabling_manager.cc
index b795bd9..331994d0 100644
--- a/chrome/browser/ash/system/device_disabling_manager.cc
+++ b/chrome/browser/ash/system/device_disabling_manager.cc
@@ -126,21 +126,24 @@
 
   // Update the enrollment domain.
   enrollment_domain_.clear();
-  base::Value::AsDictionaryValue(
-      *g_browser_process->local_state()->GetDictionary(
-          prefs::kServerBackedDeviceState))
-      .GetString(policy::kDeviceStateManagementDomain, &enrollment_domain_);
+  const std::string* maybe_enrollment_domain =
+      g_browser_process->local_state()
+          ->GetDictionary(prefs::kServerBackedDeviceState)
+          ->FindStringKey(policy::kDeviceStateManagementDomain);
+  enrollment_domain_ =
+      maybe_enrollment_domain ? *maybe_enrollment_domain : std::string();
 
   // Update the serial number.
   serial_number_ = chromeos::system::StatisticsProvider::GetInstance()
                        ->GetEnterpriseMachineID();
 
   // Update the disabled message.
-  std::string disabled_message;
-  base::Value::AsDictionaryValue(
-      *g_browser_process->local_state()->GetDictionary(
-          prefs::kServerBackedDeviceState))
-      .GetString(policy::kDeviceStateDisabledMessage, &disabled_message);
+  const std::string* maybe_disabled_message =
+      g_browser_process->local_state()
+          ->GetDictionary(prefs::kServerBackedDeviceState)
+          ->FindStringKey(policy::kDeviceStateDisabledMessage);
+  std::string disabled_message =
+      maybe_disabled_message ? *maybe_disabled_message : std::string();
   CacheDisabledMessageAndNotify(disabled_message);
 
   // Indicate that the device is disabled.
diff --git a/chrome/browser/ash/tether/tether_service.cc b/chrome/browser/ash/tether/tether_service.cc
index 6e6ed09..b5af1be 100644
--- a/chrome/browser/ash/tether/tether_service.cc
+++ b/chrome/browser/ash/tether/tether_service.cc
@@ -545,10 +545,10 @@
       // Note that because of the early return above after
       // !HasSyncedTetherHosts, if this point is hit, there are synced tether
       // hosts available, but the multidevice state is unverified.
-      FALLTHROUGH;
+      [[fallthrough]];
     case chromeos::multidevice_setup::mojom::FeatureState::
         kUnavailableNoVerifiedHost_ClientNotReady:
-      FALLTHROUGH;
+      [[fallthrough]];
     case chromeos::multidevice_setup::mojom::FeatureState::
         kNotSupportedByChromebook:
       // CryptAuth may not yet know that this device supports
@@ -556,7 +556,7 @@
       // that). This should be resolved shortly once DeviceReenroller realizes
       // reconciles the discrepancy. For now, fall through to mark as
       // unavailable.
-      FALLTHROUGH;
+      [[fallthrough]];
     case chromeos::multidevice_setup::mojom::FeatureState::kNotSupportedByPhone:
       return NO_AVAILABLE_HOSTS;
     default:
diff --git a/chrome/browser/autofill/form_structure_browsertest.cc b/chrome/browser/autofill/form_structure_browsertest.cc
index 354bfaa..07b0dea 100644
--- a/chrome/browser/autofill/form_structure_browsertest.cc
+++ b/chrome/browser/autofill/form_structure_browsertest.cc
@@ -193,7 +193,8 @@
        // TODO(crbug.com/1157405) Remove once launched.
        features::kAutofillEnableDependentLocalityParsing,
        // TODO(crbug.com/1150895) Remove once launched.
-       features::kAutofillParsingPatternsLanguageDetection,
+       features::kAutofillParsingPatternProvider,
+       features::kAutofillPageLanguageDetection,
        // TODO(crbug/1165780): Remove once shared labels are launched.
        features::kAutofillEnableSupportForParsingWithSharedLabels,
        // TODO(crbug.com/1277480): Remove once launched.
diff --git a/chrome/browser/background_fetch/background_fetch_permission_context.cc b/chrome/browser/background_fetch/background_fetch_permission_context.cc
index 7f7a134..63c9427 100644
--- a/chrome/browser/background_fetch/background_fetch_permission_context.cc
+++ b/chrome/browser/background_fetch/background_fetch_permission_context.cc
@@ -29,6 +29,18 @@
     const GURL& embedding_origin) const {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
+  auto* host_content_settings_map =
+      HostContentSettingsMapFactory::GetForProfile(browser_context());
+  DCHECK(host_content_settings_map);
+
+  // The set of valid settings for automatic downloads is defined as
+  // {CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK, CONTENT_SETTING_BLOCK}.
+  const ContentSetting setting = host_content_settings_map->GetContentSetting(
+      requesting_origin, requesting_origin,
+      ContentSettingsType::AUTOMATIC_DOWNLOADS);
+  if (setting == CONTENT_SETTING_BLOCK)
+    return setting;
+
   if (render_frame_host && !render_frame_host->GetParent()) {
     DownloadRequestLimiter* limiter =
         g_browser_process->download_request_limiter();
@@ -50,26 +62,13 @@
   }
 
   // |render_frame_host| is either a nullptr, which means we're being called
-  // from a worker context, or it's not a top level frame. In either case, use
-  // content settings.
-  auto* host_content_settings_map =
-      HostContentSettingsMapFactory::GetForProfile(browser_context());
-  DCHECK(host_content_settings_map);
-
-  // The set of valid settings for automatic downloads is defined as
-  // {CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK, CONTENT_SETTING_BLOCK}.
-  ContentSetting setting = host_content_settings_map->GetContentSetting(
-      requesting_origin, requesting_origin,
-      ContentSettingsType::AUTOMATIC_DOWNLOADS);
-
-  // Due to privacy concerns as outlined in https://crbug.com/896311 the most
-  // permissive state BGF can be in for non top level frames or service workers
-  // is ASK. This causes background fetches that do not originate in a main
-  // frame to start paused.
-  if (setting == CONTENT_SETTING_ALLOW)
-    setting = CONTENT_SETTING_ASK;
-
-  return setting;
+  // from a worker context, or it's not a top level frame. Due to privacy
+  // concerns as outlined in https://crbug.com/896311 the most permissive state
+  // BGF can be in for non top level frames or service workers is ASK. This
+  // causes background fetches that do not originate in a main frame to start
+  // paused.
+  DCHECK(setting == CONTENT_SETTING_ASK || setting == CONTENT_SETTING_ALLOW);
+  return CONTENT_SETTING_ASK;
 }
 
 void BackgroundFetchPermissionContext::DecidePermission(
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index e90e16c..0e3423c 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -2464,6 +2464,8 @@
     "../ash/policy/display/display_settings_handler.h",
     "../ash/policy/dlp/dlp_content_manager_ash.cc",
     "../ash/policy/dlp/dlp_content_manager_ash.h",
+    "../ash/policy/dlp/dlp_files_controller.cc",
+    "../ash/policy/dlp/dlp_files_controller.h",
     "../ash/policy/dlp/dlp_window_observer.cc",
     "../ash/policy/dlp/dlp_window_observer.h",
     "../ash/policy/enrollment/account_status_check_fetcher.cc",
@@ -4369,6 +4371,7 @@
     "../ash/policy/core/user_cloud_policy_store_ash_unittest.cc",
     "../ash/policy/core/user_cloud_policy_token_forwarder_unittest.cc",
     "../ash/policy/dlp/dlp_content_manager_ash_unittest.cc",
+    "../ash/policy/dlp/dlp_files_controller_unittest.cc",
     "../ash/policy/dlp/mock_dlp_content_manager_ash.cc",
     "../ash/policy/dlp/mock_dlp_content_manager_ash.h",
     "../ash/policy/enrollment/account_status_check_fetcher_unittest.cc",
diff --git a/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.cc b/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.cc
index 5edfdc8..27d419ff 100644
--- a/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.cc
+++ b/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.cc
@@ -353,7 +353,7 @@
       break;
 
     case DlpRulesManager::Level::kAllow:
-      FALLTHROUGH;
+      [[fallthrough]];
     case DlpRulesManager::Level::kReport:
       std::move(drop_cb).Run();
       break;
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h
index c9d4260..e41d554f 100644
--- a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h
+++ b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h
@@ -137,12 +137,6 @@
   // Returns the admin-configured limit for the minimal size of data in the
   // clipboard to be checked against DLP rules.
   virtual size_t GetClipboardCheckSizeLimitInBytes() const = 0;
-
-  // Returns a list of files inodes disallowed to be transferred to
-  // |destination|.
-  virtual std::vector<uint64_t> GetDisallowedFileTransfers(
-      const std::vector<FileMetadata>& transferred_files,
-      const GURL& destination) const = 0;
 };
 
 }  // namespace policy
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.cc b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.cc
index ce2151b..752880f 100644
--- a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.cc
+++ b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.cc
@@ -24,10 +24,10 @@
 #include "chrome/common/chrome_features.h"
 #include "chromeos/dbus/dlp/dlp_client.h"
 #include "chromeos/dbus/dlp/dlp_service.pb.h"
-#include "components/policy/core/browser/url_util.h"
 #include "components/policy/core/common/policy_pref_names.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
+#include "components/url_matcher/url_util.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace policy {
@@ -103,12 +103,12 @@
   bool match_subdomains = true;
   for (const auto& list_entry : urls->GetList()) {
     std::string url = list_entry.GetString();
-    if (!url_util::FilterToComponents(url, &scheme, &host, &match_subdomains,
-                                      &port, &path, &query)) {
+    if (!url_matcher::util::FilterToComponents(
+            url, &scheme, &host, &match_subdomains, &port, &path, &query)) {
       LOG(ERROR) << "Invalid pattern " << url;
       continue;
     }
-    auto condition_set = url_util::CreateConditionSet(
+    auto condition_set = url_matcher::util::CreateConditionSet(
         matcher, ++condition_id, scheme, host, match_subdomains, port, path,
         query, /*allow=*/true);
 
@@ -396,20 +396,6 @@
       policy_prefs::kDlpClipboardCheckSizeLimit);
 }
 
-std::vector<uint64_t> DlpRulesManagerImpl::GetDisallowedFileTransfers(
-    const std::vector<FileMetadata>& transferred_files,
-    const GURL& destination) const {
-  // TODO(crbug.com/1273793): Change to handle VMs, external drive, ...etc.
-  std::vector<uint64_t> restricted_files;
-  for (const auto& file : transferred_files) {
-    Level level = IsRestrictedDestination(
-        file.source, destination, Restriction::kFiles, nullptr, nullptr);
-    if (level == Level::kBlock)
-      restricted_files.push_back(file.inode);
-  }
-  return restricted_files;
-}
-
 void DlpRulesManagerImpl::OnPolicyUpdate() {
   components_rules_.clear();
   restrictions_map_.clear();
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.h b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.h
index 5d333bb9..d4ec987 100644
--- a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.h
+++ b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.h
@@ -52,9 +52,6 @@
                                   Restriction restriction,
                                   Level level) const override;
   size_t GetClipboardCheckSizeLimitInBytes() const override;
-  std::vector<uint64_t> GetDisallowedFileTransfers(
-      const std::vector<FileMetadata>& transferred_files,
-      const GURL& destination) const override;
 
  protected:
   friend class DlpRulesManagerFactory;
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc
index 0c2b4a5..8938a23 100644
--- a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc
+++ b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc
@@ -847,41 +847,4 @@
                 DlpRulesManager::Restriction::kScreenShare));
 }
 
-TEST_F(DlpRulesManagerImplTest, GetDisallowedFileTransfers) {
-  base::Value rules(base::Value::Type::LIST);
-
-  base::Value src_urls_1(base::Value::Type::LIST);
-  src_urls_1.Append(kDrivePattern);
-  src_urls_1.Append(kCompanyPattern);
-
-  base::Value dst_urls_1(base::Value::Type::LIST);
-  dst_urls_1.Append(kWildCardMatching);
-
-  base::Value restrictions_1(base::Value::Type::LIST);
-  restrictions_1.Append(dlp_test_util::CreateRestrictionWithLevel(
-      dlp::kFilesRestriction, dlp::kBlockLevel));
-
-  rules.Append(dlp_test_util::CreateRule(
-      "Block files", "Block files of work urls", std::move(src_urls_1),
-      std::move(dst_urls_1),
-      /*dst_components=*/base::Value(base::Value::Type::LIST),
-      std::move(restrictions_1)));
-
-  UpdatePolicyPref(std::move(rules));
-
-  uint64_t inode_1 = 12345;
-  uint64_t inode_2 = 67890;
-  uint64_t inode_3 = 13679;
-  std::vector<DlpRulesManager::FileMetadata> transferred_files;
-  transferred_files.push_back({inode_1, kCompanyUrl});
-  transferred_files.push_back(
-      {inode_2, base::StrCat({kHttpsPrefix, kDrivePattern})});
-  transferred_files.push_back({inode_3, kGoogleUrl});
-
-  std::vector<uint64_t> expected_output = {inode_1, inode_2};
-
-  EXPECT_EQ(expected_output, dlp_rules_manager_.GetDisallowedFileTransfers(
-                                 transferred_files, GURL(kExampleUrl)));
-}
-
 }  // namespace policy
diff --git a/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.cc b/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.cc
index 0cae203..402094f 100644
--- a/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.cc
+++ b/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.cc
@@ -6,7 +6,7 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/enterprise/connectors/service_provider_config.h"
-#include "components/policy/core/browser/url_util.h"
+#include "components/url_matcher/url_util.h"
 
 namespace enterprise_connectors {
 
@@ -205,8 +205,8 @@
   if (!url_list)
     return;
 
-  policy::url_util::AddFilters(matcher_.get(), enabled, id,
-                               &base::Value::AsListValue(*url_list));
+  url_matcher::util::AddFilters(matcher_.get(), enabled, id,
+                                &base::Value::AsListValue(*url_list));
 
   if (enabled)
     enabled_patterns_settings_[*id] = std::move(setting);
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc
index de5230cc..b4a25ef 100644
--- a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc
+++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc
@@ -35,7 +35,6 @@
 #include "chrome/browser/safe_browsing/download_protection/check_client_download_request.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/enterprise/common/proto/connectors.pb.h"
-#include "components/policy/core/browser/url_util.h"
 #include "components/policy/core/common/chrome_schema.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/core/common/features.h"
diff --git a/chrome/browser/enterprise/connectors/connectors_manager.cc b/chrome/browser/enterprise/connectors/connectors_manager.cc
index b38a27d4..f3fc199 100644
--- a/chrome/browser/enterprise/connectors/connectors_manager.cc
+++ b/chrome/browser/enterprise/connectors/connectors_manager.cc
@@ -10,7 +10,6 @@
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/enterprise/connectors/connectors_prefs.h"
-#include "components/policy/core/browser/url_util.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
 #include "components/url_matcher/url_matcher.h"
diff --git a/chrome/browser/enterprise/connectors/device_trust/device_trust_connector_service.cc b/chrome/browser/enterprise/connectors/device_trust/device_trust_connector_service.cc
index 56651cb8..5630fe9a 100644
--- a/chrome/browser/enterprise/connectors/device_trust/device_trust_connector_service.cc
+++ b/chrome/browser/enterprise/connectors/device_trust/device_trust_connector_service.cc
@@ -7,9 +7,9 @@
 #include "base/check.h"
 #include "chrome/browser/enterprise/connectors/connectors_prefs.h"
 #include "chrome/browser/enterprise/connectors/device_trust/device_trust_features.h"
-#include "components/policy/core/browser/url_util.h"
 #include "components/prefs/pref_service.h"
 #include "components/url_matcher/url_matcher.h"
+#include "components/url_matcher/url_util.h"
 #include "url/gurl.h"
 
 namespace enterprise_connectors {
@@ -89,7 +89,7 @@
 
   if (url_patterns && !url_patterns->GetList().empty()) {
     // Add the new endpoints to the conditions.
-    policy::url_util::AddAllowFilters(matcher_.get(), url_patterns);
+    url_matcher::util::AddAllowFilters(matcher_.get(), url_patterns);
 
     // Call the hook which signals that the connector has been enabled.
     OnConnectorEnabled();
diff --git a/chrome/browser/enterprise/connectors/file_system/service_settings.cc b/chrome/browser/enterprise/connectors/file_system/service_settings.cc
index dfd94f2..61ac81bd1 100644
--- a/chrome/browser/enterprise/connectors/file_system/service_settings.cc
+++ b/chrome/browser/enterprise/connectors/file_system/service_settings.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/enterprise/connectors/file_system/service_settings.h"
 
 #include "chrome/browser/enterprise/connectors/service_provider_config.h"
-#include "components/policy/core/browser/url_util.h"
+#include "components/url_matcher/url_util.h"
 
 namespace enterprise_connectors {
 
@@ -211,8 +211,8 @@
 
   // This pre-increments the id by size of url_list_value.
   URLMatchingID pre_id = *id;
-  policy::url_util::AddFilters(url_matcher_.get(), enabled, id,
-                               &base::Value::AsListValue(*url_list));
+  url_matcher::util::AddFilters(url_matcher_.get(), enabled, id,
+                                &base::Value::AsListValue(*url_list));
 
   const base::Value* mime_types = url_settings_value.FindListKey(kKeyMimeTypes);
   if (!mime_types)
diff --git a/chrome/browser/enterprise/connectors/reporting/reporting_service_settings.cc b/chrome/browser/enterprise/connectors/reporting/reporting_service_settings.cc
index 6bcbc3d..22e24ae 100644
--- a/chrome/browser/enterprise/connectors/reporting/reporting_service_settings.cc
+++ b/chrome/browser/enterprise/connectors/reporting/reporting_service_settings.cc
@@ -9,7 +9,6 @@
 #include "chrome/browser/enterprise/connectors/service_provider_config.h"
 #include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h"
 #include "chrome/browser/policy/chrome_browser_policy_connector.h"
-#include "components/policy/core/browser/url_util.h"
 
 namespace enterprise_connectors {
 
diff --git a/chrome/browser/extensions/api/commands/command_service.cc b/chrome/browser/extensions/api/commands/command_service.cc
index e5cd076..896c92f 100644
--- a/chrome/browser/extensions/api/commands/command_service.cc
+++ b/chrome/browser/extensions/api/commands/command_service.cc
@@ -193,20 +193,18 @@
   std::string key = GetPlatformKeybindingKeyForAccelerator(accelerator,
                                                            extension_id);
 
-  if (bindings->HasKey(key)) {
+  if (bindings->FindKey(key)) {
     if (!allow_overrides)
       return false;  // Already taken.
 
     // If the shortcut has been assigned to another command, it should be
     // removed before overriding, so that |ExtensionKeybindingRegistry| can get
     // a chance to do clean-up.
-    const base::DictionaryValue* item = NULL;
-    bindings->GetDictionary(key, &item);
-    std::string old_extension_id;
-    std::string old_command_name;
-    item->GetString(kExtension, &old_extension_id);
-    item->GetString(kCommandName, &old_command_name);
-    RemoveKeybindingPrefs(old_extension_id, old_command_name);
+    const base::Value* item = bindings->FindDictKey(key);
+    const std::string* old_extension_id = item->FindStringKey(kExtension);
+    const std::string* old_command_name = item->FindStringKey(kCommandName);
+    RemoveKeybindingPrefs(old_extension_id ? *old_extension_id : std::string(),
+                          old_command_name ? *old_command_name : std::string());
   }
 
   // If the command that is taking a new shortcut already has a shortcut, remove
diff --git a/chrome/browser/extensions/api/commands/command_service_browsertest.cc b/chrome/browser/extensions/api/commands/command_service_browsertest.cc
index 3ec2298..df92388 100644
--- a/chrome/browser/extensions/api/commands/command_service_browsertest.cc
+++ b/chrome/browser/extensions/api/commands/command_service_browsertest.cc
@@ -128,7 +128,7 @@
 
   // Removal of keybinding preference should be platform-specific, so the key on
   // another platform should always remained.
-  EXPECT_TRUE(bindings->HasKey(anotherPlatformKey));
+  EXPECT_TRUE(bindings->FindKey(anotherPlatformKey));
 }
 
 IN_PROC_BROWSER_TEST_F(CommandServiceTest,
diff --git a/chrome/browser/extensions/api/declarative_content/content_action.cc b/chrome/browser/extensions/api/declarative_content/content_action.cc
index e71e5fdb..bca2ffe 100644
--- a/chrome/browser/extensions/api/declarative_content/content_action.cc
+++ b/chrome/browser/extensions/api/declarative_content/content_action.cc
@@ -176,9 +176,10 @@
 };
 
 // Helper for getting JS collections into C++.
-static bool AppendJSStringsToCPPStrings(const base::ListValue& append_strings,
-                                        std::vector<std::string>* append_to) {
-  for (const auto& entry : append_strings.GetList()) {
+static bool AppendJSStringsToCPPStrings(
+    const base::Value::ConstListView& append_strings,
+    std::vector<std::string>* append_to) {
+  for (const auto& entry : append_strings) {
     if (entry.is_string()) {
       append_to->push_back(entry.GetString());
     } else {
@@ -255,42 +256,38 @@
 bool RequestContentScript::InitScriptData(const base::DictionaryValue* dict,
                                           std::string* error,
                                           ScriptData* script_data) {
-  const base::ListValue* list_value = NULL;
+  const base::Value* css = dict->FindKey(declarative_content_constants::kCss);
+  const base::Value* js = dict->FindKey(declarative_content_constants::kJs);
 
-  if (!dict->HasKey(declarative_content_constants::kCss) &&
-      !dict->HasKey(declarative_content_constants::kJs)) {
+  if (!css && !js) {
     *error = base::StringPrintf(kMissingParameter, "css or js");
     return false;
   }
-  if (dict->HasKey(declarative_content_constants::kCss)) {
-    if (!dict->GetList(declarative_content_constants::kCss, &list_value) ||
-        !AppendJSStringsToCPPStrings(*list_value,
-                                     &script_data->css_file_names)) {
+  if (css) {
+    if (!css->is_list() || !AppendJSStringsToCPPStrings(
+                               css->GetList(), &script_data->css_file_names)) {
       return false;
     }
   }
-  if (dict->HasKey(declarative_content_constants::kJs)) {
-    if (!dict->GetList(declarative_content_constants::kJs, &list_value) ||
-        !AppendJSStringsToCPPStrings(*list_value,
-                                     &script_data->js_file_names)) {
+  if (js) {
+    if (!js->is_list() || !AppendJSStringsToCPPStrings(
+                              js->GetList(), &script_data->js_file_names)) {
       return false;
     }
   }
-  if (dict->HasKey(declarative_content_constants::kAllFrames)) {
-    absl::optional<bool> all_frames =
-        dict->FindBoolKey(declarative_content_constants::kAllFrames);
-    if (!all_frames.has_value())
+  if (const base::Value* all_frames_val =
+          dict->FindKey(declarative_content_constants::kAllFrames)) {
+    if (!all_frames_val->is_bool())
       return false;
 
-    script_data->all_frames = all_frames.value();
+    script_data->all_frames = all_frames_val->GetBool();
   }
-  if (dict->HasKey(declarative_content_constants::kMatchAboutBlank)) {
-    absl::optional<bool> match_about_blank =
-        dict->FindBoolKey(declarative_content_constants::kMatchAboutBlank);
-    if (!match_about_blank.has_value())
+  if (const base::Value* match_about_blank_val =
+          dict->FindKey(declarative_content_constants::kMatchAboutBlank)) {
+    if (!match_about_blank_val->is_bool())
       return false;
 
-    script_data->match_about_blank = match_about_blank.value();
+    script_data->match_about_blank = match_about_blank_val->GetBool();
   }
 
   return true;
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc
index 535137af..43249c5 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -1859,17 +1859,14 @@
     // the bytesReceived field, if the field has changed from the previous old
     // json, set the differences in the |delta| object and remember that
     // something significant changed.
-    for (base::DictionaryValue::Iterator iter(*new_json); !iter.IsAtEnd();
-         iter.Advance()) {
-      new_fields.insert(iter.key());
-      if (IsDownloadDeltaField(iter.key())) {
-        const base::Value* old_value = NULL;
-        if (!data->json().HasKey(iter.key()) ||
-            (data->json().Get(iter.key(), &old_value) &&
-             iter.value() != *old_value)) {
-          delta->SetPath(iter.key() + ".current", iter.value().Clone());
+    for (auto kv : new_json->DictItems()) {
+      new_fields.insert(kv.first);
+      if (IsDownloadDeltaField(kv.first)) {
+        const base::Value* old_value = data->json().FindKey(kv.first);
+        if (!old_value || kv.second != *old_value) {
+          delta->SetPath(kv.first + ".current", kv.second.Clone());
           if (old_value) {
-            delta->SetPath(iter.key() + ".previous", old_value->Clone());
+            delta->SetPath(kv.first + ".previous", old_value->Clone());
           }
           changed = true;
         }
diff --git a/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc b/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
index 3b89604a..fd4e2e9 100644
--- a/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
+++ b/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
@@ -84,25 +84,23 @@
                                       bool* out,
                                       std::string* error,
                                       bool* bad_message) {
-  const base::DictionaryValue* pac_dict = NULL;
-  proxy_config->GetDictionary(proxy_api_constants::kProxyConfigPacScript,
-                              &pac_dict);
+  const base::Value* pac_dict =
+      proxy_config->FindDictKey(proxy_api_constants::kProxyConfigPacScript);
   if (!pac_dict) {
     *out = false;
     return true;
   }
 
-  absl::optional<bool> mandatory_pac;
-  if (pac_dict->HasKey(proxy_api_constants::kProxyConfigPacScriptMandatory)) {
-    mandatory_pac = pac_dict->FindBoolKey(
-        proxy_api_constants::kProxyConfigPacScriptMandatory);
-    if (!mandatory_pac.has_value()) {
+  const base::Value* mandatory_pac =
+      pac_dict->FindKey(proxy_api_constants::kProxyConfigPacScriptMandatory);
+  if (mandatory_pac) {
+    if (!mandatory_pac->is_bool()) {
       LOG(ERROR) << "'pacScript.mandatory' could not be parsed.";
       *bad_message = true;
       return false;
     }
   }
-  *out = mandatory_pac.value_or(false);
+  *out = mandatory_pac ? mandatory_pac->GetBool() : false;
   return true;
 }
 
@@ -110,27 +108,29 @@
                                 std::string* out,
                                 std::string* error,
                                 bool* bad_message) {
-  const base::DictionaryValue* pac_dict = NULL;
-  proxy_config->GetDictionary(proxy_api_constants::kProxyConfigPacScript,
-                              &pac_dict);
+  const base::Value* pac_dict =
+      proxy_config->FindDictKey(proxy_api_constants::kProxyConfigPacScript);
   if (!pac_dict)
     return true;
 
   // TODO(battre): Handle UTF-8 URLs (http://crbug.com/72692).
-  std::u16string pac_url16;
-  if (pac_dict->HasKey(proxy_api_constants::kProxyConfigPacScriptUrl) &&
-      !pac_dict->GetString(proxy_api_constants::kProxyConfigPacScriptUrl,
-                           &pac_url16)) {
-    LOG(ERROR) << "'pacScript.url' could not be parsed.";
-    *bad_message = true;
-    return false;
+  std::string pac_url;
+  const base::Value* pac_url_val =
+      pac_dict->FindKey(proxy_api_constants::kProxyConfigPacScriptUrl);
+  if (pac_url_val) {
+    if (!pac_url_val->is_string()) {
+      LOG(ERROR) << "'pacScript.url' could not be parsed.";
+      *bad_message = true;
+      return false;
+    }
+    pac_url = pac_url_val->GetString();
   }
-  if (!base::IsStringASCII(pac_url16)) {
+  if (!base::IsStringASCII(pac_url)) {
     *error = "'pacScript.url' supports only ASCII URLs "
              "(encode URLs in Punycode format).";
     return false;
   }
-  *out = base::UTF16ToASCII(pac_url16);
+  *out = std::move(pac_url);
   return true;
 }
 
@@ -138,26 +138,29 @@
                                  std::string* out,
                                  std::string* error,
                                  bool* bad_message) {
-  const base::DictionaryValue* pac_dict = NULL;
-  proxy_config->GetDictionary(proxy_api_constants::kProxyConfigPacScript,
-                              &pac_dict);
+  const base::Value* pac_dict =
+      proxy_config->FindDictKey(proxy_api_constants::kProxyConfigPacScript);
   if (!pac_dict)
     return true;
 
-  std::u16string pac_data16;
-  if (pac_dict->HasKey(proxy_api_constants::kProxyConfigPacScriptData) &&
-      !pac_dict->GetString(proxy_api_constants::kProxyConfigPacScriptData,
-                           &pac_data16)) {
-    LOG(ERROR) << "'pacScript.data' could not be parsed.";
-    *bad_message = true;
-    return false;
+  std::string pac_data;
+  const base::Value* pac_val =
+      pac_dict->FindKey(proxy_api_constants::kProxyConfigPacScriptData);
+  if (pac_val) {
+    if (!pac_val->is_string()) {
+      LOG(ERROR) << "'pacScript.data' could not be parsed.";
+      *bad_message = true;
+      return false;
+    }
+    pac_data = pac_val->GetString();
   }
-  if (!base::IsStringASCII(pac_data16)) {
+
+  if (!base::IsStringASCII(pac_data)) {
     *error = "'pacScript.data' supports only ASCII code"
              "(encode URLs in Punycode format).";
     return false;
   }
-  *out = base::UTF16ToASCII(pac_data16);
+  *out = std::move(pac_data);
   return true;
 }
 
@@ -275,13 +278,13 @@
   return true;
 }
 
-bool JoinUrlList(const base::ListValue* list,
+bool JoinUrlList(base::Value::ConstListView list,
                  const std::string& joiner,
                  std::string* out,
                  std::string* error,
                  bool* bad_message) {
   std::string result;
-  for (const auto& val : list->GetList()) {
+  for (const auto& val : list) {
     if (!result.empty())
       result.append(joiner);
 
@@ -307,25 +310,25 @@
                                     std::string* out,
                                     std::string* error,
                                     bool* bad_message) {
-  const base::DictionaryValue* proxy_rules = NULL;
-  proxy_config->GetDictionary(proxy_api_constants::kProxyConfigRules,
-                              &proxy_rules);
+  const base::Value* proxy_rules =
+      proxy_config->FindDictKey(proxy_api_constants::kProxyConfigRules);
   if (!proxy_rules)
     return true;
 
-  if (!proxy_rules->HasKey(proxy_api_constants::kProxyConfigBypassList)) {
+  const base::Value* bypass_list =
+      proxy_rules->FindKey(proxy_api_constants::kProxyConfigBypassList);
+  if (!bypass_list) {
     *out = "";
     return true;
   }
-  const base::ListValue* bypass_list = NULL;
-  if (!proxy_rules->GetList(proxy_api_constants::kProxyConfigBypassList,
-                            &bypass_list)) {
+
+  if (!bypass_list->is_list()) {
     LOG(ERROR) << "'rules.bypassList' could not be parsed.";
     *bad_message = true;
     return false;
   }
 
-  return JoinUrlList(bypass_list, ",", out, error, bad_message);
+  return JoinUrlList(bypass_list->GetList(), ",", out, error, bad_message);
 }
 
 std::unique_ptr<base::Value> CreateProxyConfigDict(
diff --git a/chrome/browser/extensions/api/proxy/proxy_api_helpers.h b/chrome/browser/extensions/api/proxy/proxy_api_helpers.h
index 00da9381..7a8fbce6 100644
--- a/chrome/browser/extensions/api/proxy/proxy_api_helpers.h
+++ b/chrome/browser/extensions/api/proxy/proxy_api_helpers.h
@@ -10,17 +10,12 @@
 #include <memory>
 #include <string>
 
+#include "base/values.h"
 #include "components/proxy_config/proxy_prefs.h"
 #include "net/proxy_resolution/proxy_config.h"
 
 class ProxyConfigDictionary;
 
-namespace base {
-class DictionaryValue;
-class ListValue;
-class Value;
-}
-
 namespace extensions {
 namespace proxy_api_helpers {
 
@@ -104,13 +99,12 @@
 
 // Joins a list of URLs (stored as StringValues) in |list| with |joiner|
 // to |out|. Returns true if successful and sets |error| otherwise.
-bool JoinUrlList(const base::ListValue* list,
+bool JoinUrlList(base::Value::ConstListView list,
                  const std::string& joiner,
                  std::string* out,
                  std::string* error,
                  bool* bad_message);
 
-
 // Helper functions for browser->extension pref transformation:
 
 // Creates and returns a ProxyRules dictionary as defined in the extension API
diff --git a/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc b/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc
index 7b708a16..b7e3b73 100644
--- a/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc
+++ b/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc
@@ -299,14 +299,14 @@
 
 TEST(ExtensionProxyApiHelpers, JoinUrlList) {
   bool bad_message = false;
-  base::ListValue list;
+  base::Value list(base::Value::Type::LIST);
   list.Append("s1");
   list.Append("s2");
   list.Append("s3");
 
   std::string out;
   std::string error;
-  ASSERT_TRUE(JoinUrlList(&list, ";", &out, &error, &bad_message));
+  ASSERT_TRUE(JoinUrlList(list.GetList(), ";", &out, &error, &bad_message));
   EXPECT_EQ("s1;s2;s3", out);
   EXPECT_FALSE(bad_message);
 }
diff --git a/chrome/browser/extensions/api/storage/policy_value_store.cc b/chrome/browser/extensions/api/storage/policy_value_store.cc
index 4965996f..a38d2be 100644
--- a/chrome/browser/extensions/api/storage/policy_value_store.cc
+++ b/chrome/browser/extensions/api/storage/policy_value_store.cc
@@ -68,10 +68,9 @@
   // and changes after removing old policies that aren't in |current_policy|
   // anymore.
   std::vector<std::string> removed_keys;
-  for (base::DictionaryValue::Iterator it(previous_policy);
-       !it.IsAtEnd(); it.Advance()) {
-    if (!current_policy.HasKey(it.key()))
-      removed_keys.push_back(it.key());
+  for (auto kv : previous_policy.DictItems()) {
+    if (!current_policy.FindKey(kv.first))
+      removed_keys.push_back(kv.first);
   }
 
   value_store::ValueStoreChangeList changes;
diff --git a/chrome/browser/extensions/api/storage/sync_storage_backend.cc b/chrome/browser/extensions/api/storage/sync_storage_backend.cc
index 9abc1a8..4919a65 100644
--- a/chrome/browser/extensions/api/storage/sync_storage_backend.cc
+++ b/chrome/browser/extensions/api/storage/sync_storage_backend.cc
@@ -177,7 +177,7 @@
     base::DictionaryValue*& settings = grouped_sync_data[data.extension_id()];
     if (!settings)
       settings = new base::DictionaryValue();
-    DCHECK(!settings->HasKey(data.key()))
+    DCHECK(!settings->FindKey(data.key()))
         << "Duplicate settings for " << data.extension_id() << "/"
         << data.key();
     settings->SetKey(data.key(),
diff --git a/chrome/browser/extensions/api/tabs/tabs_interactive_test.cc b/chrome/browser/extensions/api/tabs/tabs_interactive_test.cc
index 48e14e6..c980871a 100644
--- a/chrome/browser/extensions/api/tabs/tabs_interactive_test.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_interactive_test.cc
@@ -109,11 +109,12 @@
   base::ListValue* result_tabs = result.get();
   // We should have one initial tab and one added tab.
   EXPECT_EQ(2u, result_tabs->GetList().size());
-  for (size_t i = 0; i < result_tabs->GetList().size(); ++i) {
-    base::DictionaryValue* result_tab = NULL;
-    EXPECT_TRUE(result_tabs->GetDictionary(i, &result_tab));
-    EXPECT_EQ(focused_window_id,
-              api_test_utils::GetInteger(result_tab, keys::kWindowIdKey));
+  for (const base::Value& result_tab : result_tabs->GetList()) {
+    EXPECT_TRUE(result_tab.is_dict());
+    EXPECT_EQ(
+        focused_window_id,
+        api_test_utils::GetInteger(&base::Value::AsDictionaryValue(result_tab),
+                                   keys::kWindowIdKey));
   }
 
   // Get tabs NOT in the 'last focused' window called from the focused browser.
@@ -125,11 +126,12 @@
   result_tabs = result.get();
   // We should get one tab for each extra window and one for the initial window.
   EXPECT_EQ(kExtraWindows + 1, result_tabs->GetList().size());
-  for (size_t i = 0; i < result_tabs->GetList().size(); ++i) {
-    base::DictionaryValue* result_tab = NULL;
-    EXPECT_TRUE(result_tabs->GetDictionary(i, &result_tab));
-    EXPECT_NE(focused_window_id,
-              api_test_utils::GetInteger(result_tab, keys::kWindowIdKey));
+  for (const base::Value& result_tab : result_tabs->GetList()) {
+    EXPECT_TRUE(result_tab.is_dict());
+    EXPECT_NE(
+        focused_window_id,
+        api_test_utils::GetInteger(&base::Value::AsDictionaryValue(result_tab),
+                                   keys::kWindowIdKey));
   }
 }
 
diff --git a/chrome/browser/extensions/api/tabs/tabs_test.cc b/chrome/browser/extensions/api/tabs/tabs_test.cc
index 8da21c6..d0e3115f 100644
--- a/chrome/browser/extensions/api/tabs/tabs_test.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_test.cc
@@ -114,19 +114,19 @@
 const ExtensionTabUtil::ScrubTabBehavior kDontScrubBehavior = {
     ExtensionTabUtil::kDontScrubTab, ExtensionTabUtil::kDontScrubTab};
 
-int GetTabId(base::DictionaryValue* tab) {
+int GetTabId(const base::Value* tab) {
   if (!tab)
     return kUndefinedId;
   return tab->FindIntKey(keys::kIdKey).value_or(kUndefinedId);
 }
 
-int GetTabWindowId(base::DictionaryValue* tab) {
+int GetTabWindowId(const base::Value* tab) {
   if (!tab)
     return kUndefinedId;
   return tab->FindIntKey(keys::kWindowIdKey).value_or(kUndefinedId);
 }
 
-int GetWindowId(base::DictionaryValue* window) {
+int GetWindowId(const base::Value* window) {
   if (!window)
     return kUndefinedId;
   return window->FindIntKey(keys::kIdKey).value_or(kUndefinedId);
@@ -299,14 +299,13 @@
 
   base::ListValue* windows = result.get();
   EXPECT_EQ(window_ids.size(), windows->GetList().size());
-  for (size_t i = 0; i < windows->GetList().size(); ++i) {
-    base::DictionaryValue* result_window = nullptr;
-    EXPECT_TRUE(windows->GetDictionary(i, &result_window));
-    result_ids.insert(GetWindowId(result_window));
+  for (const base::Value& result_window : windows->GetList()) {
+    EXPECT_TRUE(result_window.is_dict());
+    result_ids.insert(GetWindowId(&result_window));
 
     // "populate" was not passed in so tabs are not populated.
-    base::ListValue* tabs = nullptr;
-    EXPECT_FALSE(result_window->GetList(keys::kTabsKey, &tabs));
+    const base::Value* tabs = result_window.FindListKey(keys::kTabsKey);
+    EXPECT_FALSE(tabs);
   }
   // The returned ids should contain all the current browser instance ids.
   EXPECT_EQ(window_ids, result_ids);
@@ -319,14 +318,13 @@
 
   windows = result.get();
   EXPECT_EQ(window_ids.size(), windows->GetList().size());
-  for (size_t i = 0; i < windows->GetList().size(); ++i) {
-    base::DictionaryValue* result_window = nullptr;
-    EXPECT_TRUE(windows->GetDictionary(i, &result_window));
-    result_ids.insert(GetWindowId(result_window));
+  for (const base::Value& result_window : windows->GetList()) {
+    EXPECT_TRUE(result_window.is_dict());
+    result_ids.insert(GetWindowId(&result_window));
 
     // "populate" was enabled so tabs should be populated.
-    base::ListValue* tabs = nullptr;
-    EXPECT_TRUE(result_window->GetList(keys::kTabsKey, &tabs));
+    const base::Value* tabs = result_window.FindListKey(keys::kTabsKey);
+    EXPECT_TRUE(tabs);
   }
   // The returned ids should contain all the current app, browser and
   // devtools instance ids.
@@ -371,14 +369,13 @@
 
   base::ListValue* windows = result.get();
   EXPECT_EQ(window_ids.size(), windows->GetList().size());
-  for (size_t i = 0; i < windows->GetList().size(); ++i) {
-    base::DictionaryValue* result_window = nullptr;
-    EXPECT_TRUE(windows->GetDictionary(i, &result_window));
-    result_ids.insert(GetWindowId(result_window));
+  for (const base::Value& result_window : windows->GetList()) {
+    EXPECT_TRUE(result_window.is_dict());
+    result_ids.insert(GetWindowId(&result_window));
 
     // "populate" was not passed in so tabs are not populated.
-    base::ListValue* tabs = nullptr;
-    EXPECT_FALSE(result_window->GetList(keys::kTabsKey, &tabs));
+    const base::Value* tabs = result_window.FindListKey(keys::kTabsKey);
+    EXPECT_FALSE(tabs);
   }
   // The returned ids should contain all the browser and devtools instance ids.
   EXPECT_EQ(window_ids, result_ids);
@@ -394,14 +391,13 @@
 
   windows = result.get();
   EXPECT_EQ(window_ids.size(), windows->GetList().size());
-  for (size_t i = 0; i < windows->GetList().size(); ++i) {
-    base::DictionaryValue* result_window = nullptr;
-    EXPECT_TRUE(windows->GetDictionary(i, &result_window));
-    result_ids.insert(GetWindowId(result_window));
+  for (const base::Value& result_window : windows->GetList()) {
+    EXPECT_TRUE(result_window.is_dict());
+    result_ids.insert(GetWindowId(&result_window));
 
     // "populate" was enabled so tabs should be populated.
-    base::ListValue* tabs = nullptr;
-    EXPECT_TRUE(result_window->GetList(keys::kTabsKey, &tabs));
+    const base::Value* tabs = result_window.FindListKey(keys::kTabsKey);
+    EXPECT_TRUE(tabs);
   }
   // The returned ids should contain all the browser and devtools instance ids.
   EXPECT_EQ(window_ids, result_ids);
@@ -612,10 +608,9 @@
   base::ListValue* result_tabs = result.get();
   // We should have one initial tab and one added tab.
   EXPECT_EQ(2u, result_tabs->GetList().size());
-  for (size_t i = 0; i < result_tabs->GetList().size(); ++i) {
-    base::DictionaryValue* result_tab = nullptr;
-    EXPECT_TRUE(result_tabs->GetDictionary(i, &result_tab));
-    EXPECT_EQ(window_id, GetTabWindowId(result_tab));
+  for (const base::Value& result_tab : result_tabs->GetList()) {
+    EXPECT_TRUE(result_tab.is_dict());
+    EXPECT_EQ(window_id, GetTabWindowId(&result_tab));
   }
 
   // Get tabs NOT in the 'current' window called from non-focused browser.
@@ -627,10 +622,9 @@
   result_tabs = result.get();
   // We should have one tab for each extra window.
   EXPECT_EQ(kExtraWindows, result_tabs->GetList().size());
-  for (size_t i = 0; i < kExtraWindows; ++i) {
-    base::DictionaryValue* result_tab = nullptr;
-    EXPECT_TRUE(result_tabs->GetDictionary(i, &result_tab));
-    EXPECT_NE(window_id, GetTabWindowId(result_tab));
+  for (const base::Value& result_tab : result_tabs->GetList()) {
+    EXPECT_TRUE(result_tab.is_dict());
+    EXPECT_NE(window_id, GetTabWindowId(&result_tab));
   }
 }
 
@@ -658,10 +652,9 @@
   base::ListValue* result_tabs = result.get();
   // We should have one tab per browser except for DevTools.
   EXPECT_EQ(kNumWindows, result_tabs->GetList().size());
-  for (size_t i = 0; i < result_tabs->GetList().size(); ++i) {
-    base::DictionaryValue* result_tab = nullptr;
-    EXPECT_TRUE(result_tabs->GetDictionary(i, &result_tab));
-    result_ids.insert(GetTabWindowId(result_tab));
+  for (const base::Value& result_tab : result_tabs->GetList()) {
+    EXPECT_TRUE(result_tab.is_dict());
+    result_ids.insert(GetTabWindowId(&result_tab));
   }
   EXPECT_EQ(window_ids, result_ids);
 
diff --git a/chrome/browser/extensions/api/tabs/windows_event_router.cc b/chrome/browser/extensions/api/tabs/windows_event_router.cc
index ff5a7c864..72b54668 100644
--- a/chrome/browser/extensions/api/tabs/windows_event_router.cc
+++ b/chrome/browser/extensions/api/tabs/windows_event_router.cc
@@ -67,7 +67,7 @@
                              const base::DictionaryValue* listener_filter) {
   bool has_filter =
       listener_filter &&
-      listener_filter->HasKey(extensions::tabs_constants::kWindowTypesKey);
+      listener_filter->FindKey(extensions::tabs_constants::kWindowTypesKey);
   // TODO(https://crbug.com/807313): Remove this.
   bool allow_dev_tools_windows = has_filter;
   if (!window_controller->IsVisibleToTabsAPIForExtension(
@@ -99,7 +99,7 @@
   Profile* new_active_context = nullptr;
   bool has_filter =
       listener_filter &&
-      listener_filter->HasKey(extensions::tabs_constants::kWindowTypesKey);
+      listener_filter->FindKey(extensions::tabs_constants::kWindowTypesKey);
 
   // We might not have a window controller if the focus moves away
   // from chromium's windows.
diff --git a/chrome/browser/extensions/extension_web_ui.cc b/chrome/browser/extensions/extension_web_ui.cc
index b8b7e28b..f54843f9 100644
--- a/chrome/browser/extensions/extension_web_ui.cc
+++ b/chrome/browser/extensions/extension_web_ui.cc
@@ -218,7 +218,7 @@
           break;
         }
         // Else fall through and erase the broken pref.
-        FALLTHROUGH;
+        [[fallthrough]];
       }
       case UPDATE_REMOVE:
         overrides_list->EraseListIter(iter);
diff --git a/chrome/browser/extensions/forced_extensions/force_installed_tracker.cc b/chrome/browser/extensions/forced_extensions/force_installed_tracker.cc
index 468981e..6a2aa18 100644
--- a/chrome/browser/extensions/forced_extensions/force_installed_tracker.cc
+++ b/chrome/browser/extensions/forced_extensions/force_installed_tracker.cc
@@ -54,7 +54,7 @@
   switch (status) {
     case ExtensionStatus::kPending:
       load_pending_count_ += delta;
-      FALLTHROUGH;
+      [[fallthrough]];
     case ExtensionStatus::kLoaded:
       ready_pending_count_ += delta;
       break;
diff --git a/chrome/browser/extensions/lazy_background_page_apitest.cc b/chrome/browser/extensions/lazy_background_page_apitest.cc
index dc42d059..efcdf53 100644
--- a/chrome/browser/extensions/lazy_background_page_apitest.cc
+++ b/chrome/browser/extensions/lazy_background_page_apitest.cc
@@ -798,8 +798,16 @@
 
 // Tests that an extension can not fetch a file scheme URL from the lazy
 // background page, if it does not have file access.
+// Flaky on Linux: crbug.com/1284362.
+#if defined(OS_LINUX)
+#define MAYBE_FetchFileSchemeURLWithNoFileAccess \
+  DISABLED_FetchFileSchemeURLWithNoFileAccess
+#else
+#define MAYBE_FetchFileSchemeURLWithNoFileAccess \
+  FetchFileSchemeURLWithNoFileAccess
+#endif
 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,
-                       FetchFileSchemeURLWithNoFileAccess) {
+                       MAYBE_FetchFileSchemeURLWithNoFileAccess) {
   ASSERT_TRUE(RunExtensionTest(
       "lazy_background_page/fetch_file_scheme_url_with_no_file_access", {}))
       << message_;
diff --git a/chrome/browser/extensions/menu_manager_unittest.cc b/chrome/browser/extensions/menu_manager_unittest.cc
index be0141d..86e5473 100644
--- a/chrome/browser/extensions/menu_manager_unittest.cc
+++ b/chrome/browser/extensions/menu_manager_unittest.cc
@@ -622,25 +622,26 @@
 
   ASSERT_EQ(2u, list->GetList().size());
 
-  base::DictionaryValue* info;
-  ASSERT_TRUE(list->GetDictionary(0, &info));
+  const base::Value& info = list->GetList()[0];
+  ASSERT_TRUE(info.is_dict());
 
-  ASSERT_EQ(id.uid, info->FindIntKey("menuItemId"));
-  ASSERT_EQ(parent_id.uid, info->FindIntKey("parentMenuItemId"));
+  ASSERT_EQ(id.uid, info.FindIntKey("menuItemId"));
+  ASSERT_EQ(parent_id.uid, info.FindIntKey("parentMenuItemId"));
 
-  std::string tmp;
-  ASSERT_TRUE(info->GetString("mediaType", &tmp));
-  ASSERT_EQ("image", tmp);
-  ASSERT_TRUE(info->GetString("srcUrl", &tmp));
-  ASSERT_EQ(params.src_url.spec(), tmp);
-  ASSERT_TRUE(info->GetString("pageUrl", &tmp));
-  ASSERT_EQ(params.page_url.spec(), tmp);
+  const std::string* tmp = info.FindStringKey("mediaType");
+  ASSERT_TRUE(tmp);
+  ASSERT_EQ("image", *tmp);
+  tmp = info.FindStringKey("srcUrl");
+  ASSERT_TRUE(tmp);
+  ASSERT_EQ(params.src_url.spec(), *tmp);
+  tmp = info.FindStringKey("pageUrl");
+  ASSERT_TRUE(tmp);
+  ASSERT_EQ(params.page_url.spec(), *tmp);
+  tmp = info.FindStringKey("selectionText");
+  ASSERT_TRUE(tmp);
+  ASSERT_EQ(params.selection_text, base::UTF8ToUTF16(*tmp));
 
-  std::u16string tmp16;
-  ASSERT_TRUE(info->GetString("selectionText", &tmp16));
-  ASSERT_EQ(params.selection_text, tmp16);
-
-  absl::optional<bool> editable = info->FindBoolKey("editable");
+  absl::optional<bool> editable = info.FindBoolKey("editable");
   ASSERT_TRUE(editable.has_value());
   ASSERT_EQ(params.is_editable, editable.value());
 
diff --git a/chrome/browser/extensions/page_action_browsertest.cc b/chrome/browser/extensions/page_action_browsertest.cc
index 2cadb64..7b8ef728 100644
--- a/chrome/browser/extensions/page_action_browsertest.cc
+++ b/chrome/browser/extensions/page_action_browsertest.cc
@@ -5,6 +5,7 @@
 #include <stddef.h>
 
 #include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
 #include "chrome/browser/extensions/extension_action_test_util.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/extensions/extension_tab_util.h"
@@ -116,7 +117,13 @@
 }
 
 // Tests that the location bar forgets about unloaded page actions.
-IN_PROC_BROWSER_TEST_P(PageActionBrowserTest, UnloadPageAction) {
+// Flaky on Linux: https://crbug.com/1283900
+#if defined(OS_LINUX)
+#define MAYBE_UnloadPageAction DISABLED_UnloadPageAction
+#else
+#define MAYBE_UnloadPageAction UnloadPageAction
+#endif
+IN_PROC_BROWSER_TEST_P(PageActionBrowserTest, MAYBE_UnloadPageAction) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
   base::FilePath extension_path(
diff --git a/chrome/browser/extensions/webstore_standalone_installer.cc b/chrome/browser/extensions/webstore_standalone_installer.cc
index ee41907..254faa3 100644
--- a/chrome/browser/extensions/webstore_standalone_installer.cc
+++ b/chrome/browser/extensions/webstore_standalone_installer.cc
@@ -276,11 +276,24 @@
   }
 
   // Localized name and description are optional.
-  if ((webstore_data->HasKey(kLocalizedNameKey) &&
-      !webstore_data->GetString(kLocalizedNameKey, &localized_name_)) ||
-      (webstore_data->HasKey(kLocalizedDescriptionKey) &&
-      !webstore_data->GetString(
-          kLocalizedDescriptionKey, &localized_description_))) {
+  bool ok = true;
+  if (const base::Value* localized_name_in =
+          webstore_data->FindKey(kLocalizedNameKey)) {
+    if (localized_name_in->is_string())
+      localized_name_ = localized_name_in->GetString();
+    else
+      ok = false;
+  }
+
+  if (const base::Value* localized_description_in =
+          webstore_data->FindKey(kLocalizedDescriptionKey)) {
+    if (localized_description_in->is_string())
+      localized_description_ = localized_description_in->GetString();
+    else
+      ok = false;
+  }
+
+  if (!ok) {
     CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
                     webstore_install::kInvalidWebstoreResponseError);
     return;
@@ -288,14 +301,14 @@
 
   // Icon URL is optional.
   GURL icon_url;
-  if (webstore_data->HasKey(kIconUrlKey)) {
-    std::string icon_url_string;
-    if (!webstore_data->GetString(kIconUrlKey, &icon_url_string)) {
+  if (const base::Value* icon_url_val = webstore_data->FindKey(kIconUrlKey)) {
+    const std::string* icon_url_string = icon_url_val->GetIfString();
+    if (!icon_url_string) {
       CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
                       webstore_install::kInvalidWebstoreResponseError);
       return;
     }
-    icon_url = extension_urls::GetWebstoreLaunchURL().Resolve(icon_url_string);
+    icon_url = extension_urls::GetWebstoreLaunchURL().Resolve(*icon_url_string);
     if (!icon_url.is_valid()) {
       CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
                       webstore_install::kInvalidWebstoreResponseError);
diff --git a/chrome/browser/external_protocol/external_protocol_handler.cc b/chrome/browser/external_protocol/external_protocol_handler.cc
index 1681c8e..3bf366dd 100644
--- a/chrome/browser/external_protocol/external_protocol_handler.cc
+++ b/chrome/browser/external_protocol/external_protocol_handler.cc
@@ -19,11 +19,11 @@
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
-#include "components/policy/core/browser/url_util.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/url_matcher/url_matcher.h"
+#include "components/url_matcher/url_util.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/weak_document_ptr.h"
 #include "net/base/escape.h"
@@ -276,8 +276,8 @@
 
   url_matcher::URLMatcher matcher;
   url_matcher::URLMatcherConditionSet::ID id(0);
-  policy::url_util::AddFilters(&matcher, true /* allowed */, &id,
-                               &base::Value::AsListValue(*origin_patterns));
+  url_matcher::util::AddFilters(&matcher, true /* allowed */, &id,
+                                &base::Value::AsListValue(*origin_patterns));
 
   auto matching_set = matcher.MatchURL(initiating_origin->GetURL());
   return !matching_set.empty();
diff --git a/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc b/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc
index 13813ce..42ecb638 100644
--- a/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc
+++ b/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc
@@ -865,7 +865,7 @@
           // Open and Save dialog only grant read access for individual files.
           if (handle_type == HandleType::kDirectory)
             break;
-          FALLTHROUGH;
+          [[fallthrough]];
         case UserAction::kDragAndDrop:
           // Drag&drop grants read access for all handles.
           existing_grant->SetStatus(
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 7595a97..e84dd8d 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -763,6 +763,11 @@
     "expiry_milestone": 98
   },
   {
+    "name": "clean-undecryptable-passwords",
+    "owners": [ "derinel@google.com", "mamir" ],
+    "expiry_milestone": 99
+  },
+  {
     "name": "clear-cross-site-cross-browsing-context-group-window-name",
     "owners": [ "shuuran", "kaustubhag" ],
     "expiry_milestone": 94
@@ -1784,7 +1789,7 @@
   {
     "name": "enable-debug-for-secure-payment-confirmation",
     "owners": [ "rouslan", "web-payments-team@google.com" ],
-    "expiry_milestone": 102
+    "expiry_milestone": 112
   },
   {
     "name": "enable-debug-for-store-billing",
@@ -2203,7 +2208,7 @@
   {
     "name": "enable-jxl",
     "owners": [ "deymo", "firsching", "lode" ],
-    "expiry_milestone": 100
+    "expiry_milestone": 105
   },
   {
     "name": "enable-lacros-in-web-kiosk",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 18f969b..06422771 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -5417,6 +5417,14 @@
     "\"X11\". \"Auto\" selects Wayland if possible, X11 otherwise. ";
 #endif  // defined(OS_LINUX) && !defined(OS_CHROMEOS)
 
+#if defined(OS_LINUX)
+const char kCleanUndecryptablePasswordsLinuxName[] =
+    "Cleanup local undecryptable passwords during initial sync flow";
+const char kCleanUndecryptablePasswordsLinuxDescription[] =
+    "Deletes the undecryptable passwords from the local database to enable "
+    "syncing all passwords during the initial sync.";
+#endif  // defined(OS_LINUX)
+
 // Feature flags --------------------------------------------------------------
 
 #if defined(DCHECK_IS_CONFIGURABLE)
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 7c95e7e1..dc4f2da2 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -3145,6 +3145,9 @@
 
 extern const char kOzonePlatformHintName[];
 extern const char kOzonePlatformHintDescription[];
+
+extern const char kCleanUndecryptablePasswordsLinuxName[];
+extern const char kCleanUndecryptablePasswordsLinuxDescription[];
 #endif  // defined(OS_LINUX)
 
 // Feature flags --------------------------------------------------------------
diff --git a/chrome/browser/lifetime/browser_close_manager_browsertest.cc b/chrome/browser/lifetime/browser_close_manager_browsertest.cc
index 9de4974..9227e01 100644
--- a/chrome/browser/lifetime/browser_close_manager_browsertest.cc
+++ b/chrome/browser/lifetime/browser_close_manager_browsertest.cc
@@ -408,10 +408,12 @@
                        MAYBE_TestSessionRestore) {
   // The testing framework launches Chrome with about:blank as args.
   EXPECT_EQ(2, browser()->tab_strip_model()->count());
-  EXPECT_EQ(GURL(chrome::kChromeUIVersionURL),
-            browser()->tab_strip_model()->GetWebContentsAt(0)->GetURL());
-  EXPECT_EQ(GURL("about:blank"),
-            browser()->tab_strip_model()->GetWebContentsAt(1)->GetURL());
+  EXPECT_EQ(
+      GURL(chrome::kChromeUIVersionURL),
+      browser()->tab_strip_model()->GetWebContentsAt(0)->GetLastCommittedURL());
+  EXPECT_EQ(
+      GURL("about:blank"),
+      browser()->tab_strip_model()->GetWebContentsAt(1)->GetLastCommittedURL());
 }
 
 // Test that browser windows are only closed if all browsers are ready to close
@@ -819,10 +821,12 @@
 
   // Check the restored browser contents.
   EXPECT_EQ(2, browser2->tab_strip_model()->count());
-  EXPECT_EQ(embedded_test_server()->GetURL("/beforeunload.html"),
-            browser2->tab_strip_model()->GetWebContentsAt(0)->GetURL());
-  EXPECT_EQ(embedded_test_server()->GetURL("/title2.html"),
-            browser2->tab_strip_model()->GetWebContentsAt(1)->GetURL());
+  EXPECT_EQ(
+      embedded_test_server()->GetURL("/beforeunload.html"),
+      browser2->tab_strip_model()->GetWebContentsAt(0)->GetLastCommittedURL());
+  EXPECT_EQ(
+      embedded_test_server()->GetURL("/title2.html"),
+      browser2->tab_strip_model()->GetWebContentsAt(1)->GetLastCommittedURL());
 }
 
 IN_PROC_BROWSER_TEST_F(BrowserCloseManagerBrowserTest,
@@ -983,8 +987,10 @@
       TestBrowserCloseManager::USER_CHOICE_USER_CANCELS_CLOSE);
   EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
   navigation_observer.Wait();
-  EXPECT_EQ(GURL(chrome::kChromeUIDownloadsURL),
-            browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
+  EXPECT_EQ(GURL(chrome::kChromeUIDownloadsURL), browser()
+                                                     ->tab_strip_model()
+                                                     ->GetActiveWebContents()
+                                                     ->GetLastCommittedURL());
 
   TestBrowserCloseManager::AttemptClose(
       TestBrowserCloseManager::USER_CHOICE_USER_ALLOWS_CLOSE);
@@ -1014,8 +1020,9 @@
       TestBrowserCloseManager::USER_CHOICE_USER_CANCELS_CLOSE);
   EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
   navigation_observer.Wait();
-  EXPECT_EQ(GURL(chrome::kChromeUIDownloadsURL),
-            otr_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
+  EXPECT_EQ(GURL(chrome::kChromeUIDownloadsURL), otr_browser->tab_strip_model()
+                                                     ->GetActiveWebContents()
+                                                     ->GetLastCommittedURL());
 
   TestBrowserCloseManager::AttemptClose(
       TestBrowserCloseManager::USER_CHOICE_USER_ALLOWS_CLOSE);
@@ -1107,12 +1114,13 @@
   Browser* opened_browser = BrowserList::GetInstance()->GetLastActive();
   ASSERT_TRUE(opened_browser);
   EXPECT_NE(other_profile_ptr, opened_browser->profile());
-  EXPECT_EQ(
-      GURL(chrome::kChromeUIDownloadsURL),
-      opened_browser->tab_strip_model()->GetActiveWebContents()->GetURL());
-  EXPECT_EQ(GURL("about:blank"),
-            other_profile_browser->tab_strip_model()->GetActiveWebContents()
-                ->GetURL());
+  EXPECT_EQ(GURL(chrome::kChromeUIDownloadsURL),
+            opened_browser->tab_strip_model()
+                ->GetActiveWebContents()
+                ->GetVisibleURL());
+  EXPECT_EQ(GURL("about:blank"), other_profile_browser->tab_strip_model()
+                                     ->GetActiveWebContents()
+                                     ->GetLastCommittedURL());
 
   TestBrowserCloseManager::AttemptClose(
       TestBrowserCloseManager::USER_CHOICE_USER_ALLOWS_CLOSE);
diff --git a/chrome/browser/media/webrtc/media_stream_capture_indicator.cc b/chrome/browser/media/webrtc/media_stream_capture_indicator.cc
index 90e658df..9e6e9b4 100644
--- a/chrome/browser/media/webrtc/media_stream_capture_indicator.cc
+++ b/chrome/browser/media/webrtc/media_stream_capture_indicator.cc
@@ -66,7 +66,7 @@
   extensions::ExtensionRegistry* registry =
       extensions::ExtensionRegistry::Get(web_contents->GetBrowserContext());
   return registry->enabled_extensions().GetExtensionOrAppByURL(
-      web_contents->GetURL());
+      web_contents->GetLastCommittedURL());
 }
 
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
@@ -83,7 +83,8 @@
     return base::UTF8ToUTF16(extension->name());
 #endif
 
-  return url_formatter::FormatUrlForSecurityDisplay(web_contents->GetURL());
+  return url_formatter::FormatUrlForSecurityDisplay(
+      web_contents->GetLastCommittedURL());
 }
 
 // Returns if the passed |device| is capturing the whole display. This is
diff --git a/chrome/browser/metrics/plugin_metrics_provider.cc b/chrome/browser/metrics/plugin_metrics_provider.cc
index 48cdbd6a..d1eeff2 100644
--- a/chrome/browser/metrics/plugin_metrics_provider.cc
+++ b/chrome/browser/metrics/plugin_metrics_provider.cc
@@ -172,24 +172,24 @@
         stability->add_plugin_stability();
     *plugin_stability->mutable_plugin() = *system_profile_plugin;
 
-    int launches = 0;
-    plugin_dict->GetInteger(prefs::kStabilityPluginLaunches, &launches);
+    int launches =
+        plugin_dict->FindIntKey(prefs::kStabilityPluginLaunches).value_or(0);
     if (launches > 0)
       plugin_stability->set_launch_count(launches);
 
-    int instances = 0;
-    plugin_dict->GetInteger(prefs::kStabilityPluginInstances, &instances);
+    int instances =
+        plugin_dict->FindIntKey(prefs::kStabilityPluginInstances).value_or(0);
     if (instances > 0)
       plugin_stability->set_instance_count(instances);
 
-    int crashes = 0;
-    plugin_dict->GetInteger(prefs::kStabilityPluginCrashes, &crashes);
+    int crashes =
+        plugin_dict->FindIntKey(prefs::kStabilityPluginCrashes).value_or(0);
     if (crashes > 0)
       plugin_stability->set_crash_count(crashes);
 
-    int loading_errors = 0;
-    plugin_dict->GetInteger(prefs::kStabilityPluginLoadingErrors,
-                            &loading_errors);
+    int loading_errors =
+        plugin_dict->FindIntKey(prefs::kStabilityPluginLoadingErrors)
+            .value_or(0);
     if (loading_errors > 0)
       plugin_stability->set_loading_error_count(loading_errors);
   }
@@ -229,30 +229,30 @@
 
     ChildProcessStats stats = child_process_stats_buffer_[plugin_name];
     if (stats.process_launches) {
-      int launches = 0;
-      plugin_dict->GetInteger(prefs::kStabilityPluginLaunches, &launches);
+      int launches =
+          plugin_dict->FindIntKey(prefs::kStabilityPluginLaunches).value_or(0);
       launches += stats.process_launches;
-      plugin_dict->SetInteger(prefs::kStabilityPluginLaunches, launches);
+      plugin_dict->SetIntKey(prefs::kStabilityPluginLaunches, launches);
     }
     if (stats.process_crashes) {
-      int crashes = 0;
-      plugin_dict->GetInteger(prefs::kStabilityPluginCrashes, &crashes);
+      int crashes =
+          plugin_dict->FindIntKey(prefs::kStabilityPluginCrashes).value_or(0);
       crashes += stats.process_crashes;
-      plugin_dict->SetInteger(prefs::kStabilityPluginCrashes, crashes);
+      plugin_dict->SetIntKey(prefs::kStabilityPluginCrashes, crashes);
     }
     if (stats.instances) {
-      int instances = 0;
-      plugin_dict->GetInteger(prefs::kStabilityPluginInstances, &instances);
+      int instances =
+          plugin_dict->FindIntKey(prefs::kStabilityPluginInstances).value_or(0);
       instances += stats.instances;
-      plugin_dict->SetInteger(prefs::kStabilityPluginInstances, instances);
+      plugin_dict->SetIntKey(prefs::kStabilityPluginInstances, instances);
     }
     if (stats.loading_errors) {
-      int loading_errors = 0;
-      plugin_dict->GetInteger(prefs::kStabilityPluginLoadingErrors,
-                              &loading_errors);
+      int loading_errors =
+          plugin_dict->FindIntKey(prefs::kStabilityPluginLoadingErrors)
+              .value_or(0);
       loading_errors += stats.loading_errors;
-      plugin_dict->SetInteger(prefs::kStabilityPluginLoadingErrors,
-                              loading_errors);
+      plugin_dict->SetIntKey(prefs::kStabilityPluginLoadingErrors,
+                             loading_errors);
     }
 
     child_process_stats_buffer_.erase(plugin_name);
@@ -272,14 +272,13 @@
         new base::DictionaryValue);
 
     plugin_dict->SetString(prefs::kStabilityPluginName, cache_iter->first);
-    plugin_dict->SetInteger(prefs::kStabilityPluginLaunches,
-                            stats.process_launches);
-    plugin_dict->SetInteger(prefs::kStabilityPluginCrashes,
-                            stats.process_crashes);
-    plugin_dict->SetInteger(prefs::kStabilityPluginInstances,
-                            stats.instances);
-    plugin_dict->SetInteger(prefs::kStabilityPluginLoadingErrors,
-                            stats.loading_errors);
+    plugin_dict->SetIntKey(prefs::kStabilityPluginLaunches,
+                           stats.process_launches);
+    plugin_dict->SetIntKey(prefs::kStabilityPluginCrashes,
+                           stats.process_crashes);
+    plugin_dict->SetIntKey(prefs::kStabilityPluginInstances, stats.instances);
+    plugin_dict->SetIntKey(prefs::kStabilityPluginLoadingErrors,
+                           stats.loading_errors);
     plugins->Append(std::move(plugin_dict));
   }
   child_process_stats_buffer_.clear();
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
index 5989bcc..03a753b 100644
--- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
+++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
@@ -81,6 +81,10 @@
 constexpr base::TimeDelta kProcessShutdownPendingTimerDelay = base::Seconds(15);
 constexpr base::TimeDelta kProcessNetworkChangeTimerDelay = base::Seconds(1);
 
+// Cooldown period after a successful incoming share before we allow the "Device
+// nearby is sharing" notification to appear again.
+constexpr base::TimeDelta kFastInitiationScannerCooldown = base::Seconds(8);
+
 // The maximum number of certificate downloads that can be performed during a
 // discovery session.
 constexpr size_t kMaxCertificateDownloadsDuringDiscovery = 3u;
@@ -406,6 +410,7 @@
 
   net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
   on_network_changed_delay_timer_.Stop();
+  fast_initiation_scanner_cooldown_timer_.Stop();
 }
 
 void NearbySharingServiceImpl::AddObserver(
@@ -2131,6 +2136,14 @@
   if (!profile_)
     return;
 
+  if (fast_initiation_scanner_cooldown_timer_.IsRunning()) {
+    NS_LOG(VERBOSE) << __func__
+                    << ": Stopping background scanning due to post-transfer "
+                       "cooldown period";
+    StopFastInitiationScanning();
+    return;
+  }
+
   if (settings_.GetFastInitiationNotificationState() !=
       FastInitiationNotificationState::kEnabled) {
     NS_LOG(VERBOSE) << __func__
@@ -3748,18 +3761,26 @@
   }
 
   if (metadata.status() == TransferMetadata::Status::kComplete &&
-      share_target.is_incoming && !OnIncomingPayloadsComplete(share_target)) {
-    metadata = TransferMetadataBuilder()
-                   .set_status(TransferMetadata::Status::kIncompletePayloads)
-                   .build();
+      share_target.is_incoming) {
+    if (!OnIncomingPayloadsComplete(share_target)) {
+      metadata = TransferMetadataBuilder()
+                     .set_status(TransferMetadata::Status::kIncompletePayloads)
+                     .build();
 
-    // Reset file paths for file attachments.
-    for (auto& file : share_target.file_attachments)
-      file.set_file_path(absl::nullopt);
+      // Reset file paths for file attachments.
+      for (auto& file : share_target.file_attachments)
+        file.set_file_path(absl::nullopt);
 
-    // Reset body of text attachments.
-    for (auto& text : share_target.text_attachments)
-      text.set_text_body(std::string());
+      // Reset body of text attachments.
+      for (auto& text : share_target.text_attachments)
+        text.set_text_body(std::string());
+    }
+
+    fast_initiation_scanner_cooldown_timer_.Start(
+        FROM_HERE, kFastInitiationScannerCooldown,
+        base::BindRepeating(
+            &NearbySharingServiceImpl::InvalidateFastInitiationScanning,
+            base::Unretained(this)));
   }
 
   // Make sure to call this before calling Disconnect or we risk loosing some
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
index d99cffc..bfc440b 100644
--- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
+++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
@@ -542,6 +542,10 @@
   // Used to debounce OnNetworkChanged processing.
   base::RetainingOneShotTimer on_network_changed_delay_timer_;
 
+  // Used to prevent the "Device nearby is sharing" notification from appearing
+  // immediately after a completed share.
+  base::OneShotTimer fast_initiation_scanner_cooldown_timer_;
+
   // Available free disk space for testing. Using real disk space can introduce
   // flakiness in tests.
   absl::optional<int64_t> free_disk_space_for_testing_;
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
index b545dd70..c2cdee3 100644
--- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
+++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
@@ -1116,6 +1116,128 @@
     fake_nearby_connections_manager_->OnEndpointLost(endpoint_id);
   }
 
+  // This method sets up an incoming connection and performs the steps required
+  // to simulate a successful incoming transfter.
+  void SuccessfullyReceiveTransfer() {
+    for (int64_t payload_id : kValidIntroductionFramePayloadIds) {
+      fake_nearby_connections_manager_->SetPayloadPathStatus(
+          payload_id, location::nearby::connections::mojom::Status::kSuccess);
+    }
+
+    NiceMock<MockTransferUpdateCallback> callback;
+    ShareTarget share_target = SetUpIncomingConnection(callback);
+
+    base::RunLoop run_loop_accept;
+    EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_))
+        .WillOnce(testing::Invoke(
+            [](const ShareTarget& share_target, TransferMetadata metadata) {
+              EXPECT_FALSE(metadata.is_final_status());
+              EXPECT_EQ(TransferMetadata::Status::kAwaitingRemoteAcceptance,
+                        metadata.status());
+            }));
+
+    service_->Accept(
+        share_target,
+        base::BindLambdaForTesting(
+            [&](NearbySharingServiceImpl::StatusCodes status_code) {
+              EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kOk,
+                        status_code);
+              run_loop_accept.Quit();
+            }));
+
+    run_loop_accept.Run();
+
+    fake_nearby_connections_manager_->SetIncomingPayload(
+        kFilePayloadId, GetFilePayloadPtr(kFilePayloadId));
+
+    for (int64_t id : kValidIntroductionFramePayloadIds) {
+      // Update file payload at the end.
+      if (id == kFilePayloadId)
+        continue;
+
+      fake_nearby_connections_manager_->SetIncomingPayload(
+          id, GetTextPayloadPtr(id, kTextPayload));
+
+      base::WeakPtr<NearbyConnectionsManager::PayloadStatusListener> listener =
+          fake_nearby_connections_manager_->GetRegisteredPayloadStatusListener(
+              id);
+      ASSERT_TRUE(listener);
+
+      base::RunLoop run_loop_progress;
+      EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_))
+          .WillOnce(testing::Invoke([&](const ShareTarget& share_target,
+                                        TransferMetadata metadata) {
+            EXPECT_FALSE(metadata.is_final_status());
+            EXPECT_EQ(TransferMetadata::Status::kInProgress, metadata.status());
+            run_loop_progress.Quit();
+          }));
+
+      location::nearby::connections::mojom::PayloadTransferUpdatePtr payload =
+          location::nearby::connections::mojom::PayloadTransferUpdate::New(
+              id, location::nearby::connections::mojom::PayloadStatus::kSuccess,
+              /*total_bytes=*/kPayloadSize,
+              /*bytes_transferred=*/kPayloadSize);
+      listener->OnStatusUpdate(std::move(payload),
+                               /*upgraded_medium=*/absl::nullopt);
+      run_loop_progress.Run();
+
+      task_environment_.FastForwardBy(kMinProgressUpdateFrequency);
+    }
+
+    base::FilePath file_path;
+    base::RunLoop run_loop_success;
+    EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_))
+        .WillOnce(testing::Invoke(
+            [&](const ShareTarget& share_target, TransferMetadata metadata) {
+              EXPECT_TRUE(metadata.is_final_status());
+              EXPECT_EQ(TransferMetadata::Status::kComplete, metadata.status());
+
+              ASSERT_TRUE(share_target.has_attachments());
+              EXPECT_EQ(1u, share_target.file_attachments.size());
+              for (const FileAttachment& file : share_target.file_attachments) {
+                EXPECT_TRUE(file.file_path());
+                file_path = *file.file_path();
+              }
+
+              EXPECT_EQ(3u, share_target.text_attachments.size());
+              for (const TextAttachment& text : share_target.text_attachments) {
+                EXPECT_EQ(kTextPayload, text.text_body());
+              }
+              run_loop_success.Quit();
+            }));
+
+    base::WeakPtr<NearbyConnectionsManager::PayloadStatusListener> listener =
+        fake_nearby_connections_manager_->GetRegisteredPayloadStatusListener(
+            kFilePayloadId);
+    ASSERT_TRUE(listener);
+
+    location::nearby::connections::mojom::PayloadTransferUpdatePtr payload =
+        location::nearby::connections::mojom::PayloadTransferUpdate::New(
+            kFilePayloadId,
+            location::nearby::connections::mojom::PayloadStatus::kSuccess,
+            /*total_bytes=*/kPayloadSize,
+            /*bytes_transferred=*/kPayloadSize);
+    listener->OnStatusUpdate(std::move(payload),
+                             /*upgraded_medium=*/absl::nullopt);
+    run_loop_success.Run();
+
+    EXPECT_FALSE(fake_nearby_connections_manager_->connection_endpoint_info(
+        kEndpointId));
+    EXPECT_FALSE(fake_nearby_connections_manager_->has_incoming_payloads());
+
+    // TODO(crbug.com/1123022): This check is flaky, should be investigated.
+    // EXPECT_TRUE(FileExists(file_path));
+
+    // To avoid UAF in OnIncomingTransferUpdate().
+    service_->UnregisterReceiveSurface(&callback);
+
+    // Remove test file.
+    {
+      base::ScopedAllowBlockingForTesting allow_blocking;
+      base::DeleteFile(file_path);
+    }
+  }
+
  protected:
   FakeNearbyShareLocalDeviceDataManager* local_device_data_manager() {
     EXPECT_EQ(1u, local_device_data_manager_factory_.instances().size());
@@ -2828,122 +2950,7 @@
 }
 
 TEST_F(NearbySharingServiceImplTest, AcceptValidShareTarget_PayloadSuccessful) {
-  for (int64_t payload_id : kValidIntroductionFramePayloadIds) {
-    fake_nearby_connections_manager_->SetPayloadPathStatus(
-        payload_id, location::nearby::connections::mojom::Status::kSuccess);
-  }
-
-  NiceMock<MockTransferUpdateCallback> callback;
-  ShareTarget share_target = SetUpIncomingConnection(callback);
-
-  base::RunLoop run_loop_accept;
-  EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_))
-      .WillOnce(testing::Invoke(
-          [](const ShareTarget& share_target, TransferMetadata metadata) {
-            EXPECT_FALSE(metadata.is_final_status());
-            EXPECT_EQ(TransferMetadata::Status::kAwaitingRemoteAcceptance,
-                      metadata.status());
-          }));
-
-  service_->Accept(share_target,
-                   base::BindLambdaForTesting(
-                       [&](NearbySharingServiceImpl::StatusCodes status_code) {
-                         EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kOk,
-                                   status_code);
-                         run_loop_accept.Quit();
-                       }));
-
-  run_loop_accept.Run();
-
-  fake_nearby_connections_manager_->SetIncomingPayload(
-      kFilePayloadId, GetFilePayloadPtr(kFilePayloadId));
-
-  for (int64_t id : kValidIntroductionFramePayloadIds) {
-    // Update file payload at the end.
-    if (id == kFilePayloadId)
-      continue;
-
-    fake_nearby_connections_manager_->SetIncomingPayload(
-        id, GetTextPayloadPtr(id, kTextPayload));
-
-    base::WeakPtr<NearbyConnectionsManager::PayloadStatusListener> listener =
-        fake_nearby_connections_manager_->GetRegisteredPayloadStatusListener(
-            id);
-    ASSERT_TRUE(listener);
-
-    base::RunLoop run_loop_progress;
-    EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_))
-        .WillOnce(testing::Invoke([&](const ShareTarget& share_target,
-                                      TransferMetadata metadata) {
-          EXPECT_FALSE(metadata.is_final_status());
-          EXPECT_EQ(TransferMetadata::Status::kInProgress, metadata.status());
-          run_loop_progress.Quit();
-        }));
-
-    location::nearby::connections::mojom::PayloadTransferUpdatePtr payload =
-        location::nearby::connections::mojom::PayloadTransferUpdate::New(
-            id, location::nearby::connections::mojom::PayloadStatus::kSuccess,
-            /*total_bytes=*/kPayloadSize,
-            /*bytes_transferred=*/kPayloadSize);
-    listener->OnStatusUpdate(std::move(payload),
-                             /*upgraded_medium=*/absl::nullopt);
-    run_loop_progress.Run();
-
-    task_environment_.FastForwardBy(kMinProgressUpdateFrequency);
-  }
-
-  base::FilePath file_path;
-  base::RunLoop run_loop_success;
-  EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_))
-      .WillOnce(testing::Invoke(
-          [&](const ShareTarget& share_target, TransferMetadata metadata) {
-            EXPECT_TRUE(metadata.is_final_status());
-            EXPECT_EQ(TransferMetadata::Status::kComplete, metadata.status());
-
-            ASSERT_TRUE(share_target.has_attachments());
-            EXPECT_EQ(1u, share_target.file_attachments.size());
-            for (const FileAttachment& file : share_target.file_attachments) {
-              EXPECT_TRUE(file.file_path());
-              file_path = *file.file_path();
-            }
-
-            EXPECT_EQ(3u, share_target.text_attachments.size());
-            for (const TextAttachment& text : share_target.text_attachments) {
-              EXPECT_EQ(kTextPayload, text.text_body());
-            }
-            run_loop_success.Quit();
-          }));
-
-  base::WeakPtr<NearbyConnectionsManager::PayloadStatusListener> listener =
-      fake_nearby_connections_manager_->GetRegisteredPayloadStatusListener(
-          kFilePayloadId);
-  ASSERT_TRUE(listener);
-
-  location::nearby::connections::mojom::PayloadTransferUpdatePtr payload =
-      location::nearby::connections::mojom::PayloadTransferUpdate::New(
-          kFilePayloadId,
-          location::nearby::connections::mojom::PayloadStatus::kSuccess,
-          /*total_bytes=*/kPayloadSize,
-          /*bytes_transferred=*/kPayloadSize);
-  listener->OnStatusUpdate(std::move(payload),
-                           /*upgraded_medium=*/absl::nullopt);
-  run_loop_success.Run();
-
-  EXPECT_FALSE(
-      fake_nearby_connections_manager_->connection_endpoint_info(kEndpointId));
-  EXPECT_FALSE(fake_nearby_connections_manager_->has_incoming_payloads());
-
-  // TODO(crbug.com/1123022): This check is flaky, should be investigated.
-  // EXPECT_TRUE(FileExists(file_path));
-
-  // To avoid UAF in OnIncomingTransferUpdate().
-  service_->UnregisterReceiveSurface(&callback);
-
-  // Remove test file.
-  {
-    base::ScopedAllowBlockingForTesting allow_blocking;
-    base::DeleteFile(file_path);
-  }
+  SuccessfullyReceiveTransfer();
 }
 
 TEST_F(NearbySharingServiceImplTest,
@@ -4745,4 +4752,25 @@
   EXPECT_EQ(1u, fast_initiation_scanner_factory_->scanner_destroyed_count());
 }
 
+TEST_F(NearbySharingServiceImplTest,
+       FastInitiationScanning_PostTransferCooldown) {
+  // Make sure we started scanning once
+  SetConnectionType(net::NetworkChangeNotifier::CONNECTION_BLUETOOTH);
+  EXPECT_EQ(1u, fast_initiation_scanner_factory_->scanner_created_count());
+  EXPECT_EQ(0u, fast_initiation_scanner_factory_->scanner_destroyed_count());
+
+  SuccessfullyReceiveTransfer();
+
+  // Make sure we stopped scanning and didn't restart... yet.
+  EXPECT_EQ(1u, fast_initiation_scanner_factory_->scanner_created_count());
+  EXPECT_EQ(1u, fast_initiation_scanner_factory_->scanner_destroyed_count());
+
+  // Fast forward 10s to pass through the cooldown period.
+  task_environment_.FastForwardBy(base::Seconds(10));
+
+  // Make sure we restarted Fast Initiation scanning.
+  EXPECT_EQ(2u, fast_initiation_scanner_factory_->scanner_created_count());
+  EXPECT_EQ(1u, fast_initiation_scanner_factory_->scanner_destroyed_count());
+}
+
 }  // namespace NearbySharingServiceUnitTests
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc
index 00fe55f0..31800e10 100644
--- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc
+++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc
@@ -24,6 +24,7 @@
 #include "components/leveldb_proto/public/proto_database_provider.h"
 #include "components/optimization_guide/core/command_line_top_host_provider.h"
 #include "components/optimization_guide/core/hints_processing_util.h"
+#include "components/optimization_guide/core/model_util.h"
 #include "components/optimization_guide/core/optimization_guide_constants.h"
 #include "components/optimization_guide/core/optimization_guide_features.h"
 #include "components/optimization_guide/core/optimization_guide_navigation_data.h"
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager.cc b/chrome/browser/optimization_guide/prediction/prediction_manager.cc
index 2edf107..02913d2d 100644
--- a/chrome/browser/optimization_guide/prediction/prediction_manager.cc
+++ b/chrome/browser/optimization_guide/prediction/prediction_manager.cc
@@ -28,6 +28,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "components/optimization_guide/content/browser/optimization_guide_decider.h"
 #include "components/optimization_guide/core/model_info.h"
+#include "components/optimization_guide/core/model_util.h"
 #include "components/optimization_guide/core/optimization_guide_constants.h"
 #include "components/optimization_guide/core/optimization_guide_enums.h"
 #include "components/optimization_guide/core/optimization_guide_features.h"
@@ -35,7 +36,6 @@
 #include "components/optimization_guide/core/optimization_guide_prefs.h"
 #include "components/optimization_guide/core/optimization_guide_store.h"
 #include "components/optimization_guide/core/optimization_guide_switches.h"
-#include "components/optimization_guide/core/optimization_guide_util.h"
 #include "components/optimization_guide/core/optimization_target_model_observer.h"
 #include "components/optimization_guide/core/prediction_model.h"
 #include "components/optimization_guide/core/prediction_model_fetcher_impl.h"
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager.h b/chrome/browser/optimization_guide/prediction/prediction_manager.h
index b3ad4cb..507935e 100644
--- a/chrome/browser/optimization_guide/prediction/prediction_manager.h
+++ b/chrome/browser/optimization_guide/prediction/prediction_manager.h
@@ -19,6 +19,7 @@
 #include "base/time/clock.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/optimization_guide/prediction/prediction_model_download_observer.h"
+#include "components/optimization_guide/core/model_enums.h"
 #include "components/optimization_guide/core/optimization_guide_enums.h"
 #include "components/optimization_guide/proto/models.pb.h"
 #include "url/origin.h"
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc b/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc
index 693c9bc..51e15d7 100644
--- a/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc
+++ b/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/optimization_guide/prediction/prediction_model_download_manager.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/leveldb_proto/testing/fake_db.h"
+#include "components/optimization_guide/core/model_util.h"
 #include "components/optimization_guide/core/optimization_guide_features.h"
 #include "components/optimization_guide/core/optimization_guide_prefs.h"
 #include "components/optimization_guide/core/optimization_guide_store.h"
diff --git a/chrome/browser/optimization_guide/prediction/prediction_model_download_manager.cc b/chrome/browser/optimization_guide/prediction/prediction_model_download_manager.cc
index f586747..75cffaf 100644
--- a/chrome/browser/optimization_guide/prediction/prediction_model_download_manager.cc
+++ b/chrome/browser/optimization_guide/prediction/prediction_model_download_manager.cc
@@ -21,6 +21,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "components/crx_file/crx_verifier.h"
 #include "components/download/public/background_service/background_download_service.h"
+#include "components/optimization_guide/core/model_util.h"
 #include "components/optimization_guide/core/optimization_guide_enums.h"
 #include "components/optimization_guide/core/optimization_guide_features.h"
 #include "components/optimization_guide/core/optimization_guide_switches.h"
diff --git a/chrome/browser/optimization_guide/prediction/prediction_model_download_manager_unittest.cc b/chrome/browser/optimization_guide/prediction/prediction_model_download_manager_unittest.cc
index 3f0730f..207c2b5 100644
--- a/chrome/browser/optimization_guide/prediction/prediction_model_download_manager_unittest.cc
+++ b/chrome/browser/optimization_guide/prediction/prediction_model_download_manager_unittest.cc
@@ -16,6 +16,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/optimization_guide/prediction/prediction_model_download_observer.h"
 #include "components/download/public/background_service/test/mock_download_service.h"
+#include "components/optimization_guide/core/model_util.h"
 #include "components/optimization_guide/core/optimization_guide_enums.h"
 #include "components/optimization_guide/core/optimization_guide_features.h"
 #include "components/optimization_guide/core/optimization_guide_switches.h"
diff --git a/chrome/browser/permissions/prediction_based_permission_ui_selector.cc b/chrome/browser/permissions/prediction_based_permission_ui_selector.cc
index 26ad1456..2997a14 100644
--- a/chrome/browser/permissions/prediction_based_permission_ui_selector.cc
+++ b/chrome/browser/permissions/prediction_based_permission_ui_selector.cc
@@ -11,24 +11,28 @@
 #include "base/rand_util.h"
 #include "base/time/default_clock.h"
 #include "chrome/browser/permissions/permission_actions_history_factory.h"
-#include "chrome/browser/permissions/prediction_model_handler_factory.h"
 #include "chrome/browser/permissions/prediction_service_factory.h"
 #include "chrome/browser/permissions/prediction_service_request.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
+#include "components/optimization_guide/machine_learning_tflite_buildflags.h"
 #include "components/permissions/features.h"
 #include "components/permissions/permission_actions_history.h"
 #include "components/permissions/permission_uma_util.h"
 #include "components/permissions/permission_util.h"
 #include "components/permissions/prediction_service/prediction_common.h"
-#include "components/permissions/prediction_service/prediction_model_handler.h"
 #include "components/permissions/prediction_service/prediction_service.h"
 #include "components/permissions/prediction_service/prediction_service_messages.pb.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
 
+#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
+#include "chrome/browser/permissions/prediction_model_handler_factory.h"
+#include "components/permissions/prediction_service/prediction_model_handler.h"
+#endif  // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
+
 namespace {
 
 using QuietUiReason = PredictionBasedPermissionUiSelector::QuietUiReason;
@@ -86,10 +90,13 @@
     if (mock_likelihood.has_value())
       set_likelihood_override(mock_likelihood.value());
   }
+
+#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
   if (base::FeatureList::IsEnabled(
           permissions::features::kPermissionOnDevicePredictions)) {
     PredictionModelHandlerFactory::GetForBrowserContext(profile);
   }
+#endif  // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
 }
 
 PredictionBasedPermissionUiSelector::~PredictionBasedPermissionUiSelector() =
@@ -136,6 +143,7 @@
 
   DCHECK(!request_);
 
+#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
   if (base::FeatureList::IsEnabled(
           permissions::features::kPermissionOnDevicePredictions)) {
     permissions::PredictionModelHandler* prediction_model_handler =
@@ -152,6 +160,7 @@
       return;
     }
   }
+#endif  // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
 
   permissions::PredictionService* service =
       PredictionServiceFactory::GetForProfile(profile_);
diff --git a/chrome/browser/prefs/tracked/pref_hash_browsertest.cc b/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
index 72ea1ac..a80f5f8 100644
--- a/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
+++ b/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
@@ -858,9 +858,9 @@
     // Tamper with any installed setting for good.crx
     base::DictionaryValue* good_crx_dict;
     EXPECT_TRUE(extensions_dict->GetDictionary(kGoodCrxId, &good_crx_dict));
-    int good_crx_state;
-    EXPECT_TRUE(good_crx_dict->GetInteger("state", &good_crx_state));
-    EXPECT_EQ(extensions::Extension::ENABLED, good_crx_state);
+    absl::optional<int> good_crx_state = good_crx_dict->FindIntKey("state");
+    ASSERT_TRUE(good_crx_state);
+    EXPECT_EQ(extensions::Extension::ENABLED, *good_crx_state);
     good_crx_dict->SetInteger("state", extensions::Extension::DISABLED);
 
     // Drop a fake extension (for the purpose of this test, dropped settings
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc
index 7f2eaef3..fcd52b01 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc
@@ -123,7 +123,6 @@
   DCHECK(pref_service_);
   DCHECK(cookie_settings_);
   DCHECK(policy_service_);
-  DCHECK(identity_manager_);
 
   // Register observers for the Privacy Sandbox & FLoC preferences.
   user_prefs_registrar_.Init(pref_service_);
@@ -345,6 +344,7 @@
   // If there is a persistent auth error associated with the primary account's
   // refresh token, then sync will not be able to run and then outcome B has
   // been reached.
+  DCHECK(identity_manager_);
   GoogleServiceAuthError auth_error =
       identity_manager_->GetErrorStateOfRefreshTokenForAccount(
           identity_manager_->GetPrimaryAccountId(signin::ConsentLevel::kSync));
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.cc
index 997128d..4e15dec 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.cc
@@ -42,9 +42,6 @@
 KeyedService* PrivacySandboxServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
   Profile* profile = Profile::FromBrowserContext(context);
-  if (!profile->IsRegularProfile())
-    return nullptr;
-
   return new PrivacySandboxService(
       PrivacySandboxSettingsFactory::GetForProfile(profile),
       CookieSettingsFactory::GetForProfile(profile).get(), profile->GetPrefs(),
@@ -53,3 +50,10 @@
       IdentityManagerFactory::GetForProfile(profile),
       federated_learning::FlocIdProviderFactory::GetForProfile(profile));
 }
+
+content::BrowserContext* PrivacySandboxServiceFactory::GetBrowserContextToUse(
+    content::BrowserContext* context) const {
+  // TODO(crbug.com/1284295): Determine whether this actually needs to be
+  // created, or whether all usage in OTR contexts can be removed.
+  return chrome::GetBrowserContextOwnInstanceInIncognito(context);
+}
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.h b/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.h
index 17aba87..36a8f75 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.h
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.h
@@ -24,6 +24,8 @@
   // BrowserContextKeyedServiceFactory:
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
+  content::BrowserContext* GetBrowserContextToUse(
+      content::BrowserContext* context) const override;
 };
 
 #endif  // CHROME_BROWSER_PRIVACY_SANDBOX_PRIVACY_SANDBOX_SERVICE_FACTORY_H_
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
index aadf17a..074ea8a 100644
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -63,7 +63,6 @@
 #include "chrome/browser/permissions/adaptive_quiet_notification_permission_ui_enabler.h"
 #include "chrome/browser/permissions/last_tab_standing_tracker_factory.h"
 #include "chrome/browser/permissions/permission_auditing_service_factory.h"
-#include "chrome/browser/permissions/prediction_model_handler_factory.h"
 #include "chrome/browser/persisted_state_db/persisted_state_db_content.pb.h"
 #include "chrome/browser/persisted_state_db/profile_proto_db_factory.h"
 #include "chrome/browser/plugins/plugin_prefs_factory.h"
@@ -116,6 +115,7 @@
 #include "chrome/common/chrome_features.h"
 #include "components/captive_portal/core/buildflags.h"
 #include "components/optimization_guide/core/optimization_guide_switches.h"
+#include "components/optimization_guide/machine_learning_tflite_buildflags.h"
 #include "components/permissions/features.h"
 #include "components/reading_list/features/reading_list_switches.h"
 #include "components/safe_browsing/buildflags.h"
@@ -223,6 +223,10 @@
 #include "chrome/browser/lacros/cert_db_initializer_factory.h"
 #endif
 
+#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
+#include "chrome/browser/permissions/prediction_model_handler_factory.h"
+#endif
+
 #if defined(OS_MAC)
 #include "chrome/browser/ui/cocoa/screentime/history_bridge_factory.h"
 #include "chrome/browser/ui/cocoa/screentime/screentime_features.h"
@@ -433,10 +437,12 @@
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
   policy::UserPolicySigninServiceFactory::GetInstance();
 #endif
+#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
   if (base::FeatureList::IsEnabled(
           permissions::features::kPermissionOnDevicePredictions)) {
     PredictionModelHandlerFactory::GetInstance();
   }
+#endif  // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
   predictors::AutocompleteActionPredictorFactory::GetInstance();
   predictors::LoadingPredictorFactory::GetInstance();
   predictors::PredictorDatabaseFactory::GetInstance();
diff --git a/chrome/browser/profiles/profile_manager.h b/chrome/browser/profiles/profile_manager.h
index 6b23be2..3eedbe8d 100644
--- a/chrome/browser/profiles/profile_manager.h
+++ b/chrome/browser/profiles/profile_manager.h
@@ -102,10 +102,20 @@
   // the last one).
   static std::vector<Profile*> GetLastOpenedProfiles();
 
+  // WARNING: do not use this function on Desktop platforms (Windows, Mac,
+  // Linux). See https://crbug.com/1264436 for more info.
+  // TODO(https://crbug.com/1264436): restrict this function to Android and
+  // ChromeOS.
+  //
   // Get the profile for the user which created the current session.
   // Note that in case of a guest account this will return a 'suitable' profile.
   static Profile* GetPrimaryUserProfile();
 
+  // WARNING: do not use this function on Desktop platforms (Windows, Mac,
+  // Linux). See https://crbug.com/1264436 for more info.
+  // TODO(https://crbug.com/1264436): restrict this function to Android and
+  // ChromeOS.
+  //
   // Get the profile for the currently active user.
   // Note that in case of a guest account this will return a 'suitable' profile.
   static Profile* GetActiveUserProfile();
diff --git a/chrome/browser/resources/chromeos/login/BUILD.gn b/chrome/browser/resources/chromeos/login/BUILD.gn
index b2e894e..63f54b2 100644
--- a/chrome/browser/resources/chromeos/login/BUILD.gn
+++ b/chrome/browser/resources/chromeos/login/BUILD.gn
@@ -123,6 +123,7 @@
   in_files = [
     "cr_ui.html",
     "i18n_setup.js",
+    "keyboard_utils.html",
     "oobe.css",
     "oobe_polymer3.js",
     "oobe_popup_overlay.css",
@@ -249,6 +250,8 @@
     "screens/common/parental_handoff.js",
     "screens/common/pin_setup.html",
     "screens/common/pin_setup.js",
+    "screens/common/saml_confirm_password.html",
+    "screens/common/saml_confirm_password.js",
     "screens/common/signin_fatal_error.html",
     "screens/common/signin_fatal_error.js",
     "screens/common/sync_consent.html",
@@ -287,6 +290,8 @@
     "screens/oobe/hid_detection.js",
     "screens/oobe/update.html",
     "screens/oobe/update.js",
+    "screens/oobe/oobe_network.html",
+    "screens/oobe/oobe_network.js",
     "screens/oobe/packaged_license.html",
     "screens/oobe/packaged_license.js",
     "screens/oobe/quick_start.html",
@@ -395,6 +400,7 @@
     "screens/common/os_install.m.js",
     "screens/common/parental_handoff.m.js",
     "screens/common/pin_setup.m.js",
+    "screens/common/saml_confirm_password.m.js",
     "screens/common/signin_fatal_error.m.js",
     "screens/common/sync_consent.m.js",
     "screens/common/tpm_error.m.js",
@@ -414,6 +420,7 @@
     "screens/oobe/enable_debugging.m.js",
     "screens/oobe/hid_detection.m.js",
     "screens/oobe/oobe_eula.m.js",
+    "screens/oobe/oobe_network.m.js",
     "screens/oobe/update.m.js",
     "screens/oobe/packaged_license.m.js",
     "screens/oobe/quick_start.m.js",
@@ -444,7 +451,6 @@
     ":closure_compile_local",
     "components:closure_compile",
     "screens/common:closure_compile",
-    "screens/oobe:closure_compile",
     "test_api:closure_compile",
   ]
 }
@@ -483,7 +489,6 @@
     ":multidevice_setup_first_run",
     ":oobe_screen_assistant_optin_flow",
     ":recommend_apps",
-    ":saml_confirm_password",
   ]
 }
 
@@ -543,18 +548,6 @@
   ]
 }
 
-js_library("saml_confirm_password") {
-  deps = [
-    ":login_ui_tools",
-    "components/behaviors:oobe_i18n_behavior",
-    "components/buttons:oobe_next_button",
-    "components/buttons:oobe_text_button",
-    "components/dialogs:oobe_adaptive_dialog",
-    "components/dialogs:oobe_loading_dialog",
-    "components/dialogs:oobe_modal_dialog",
-  ]
-}
-
 js_library("i18n_setup") {
   deps = [ "//ui/webui/resources/js:load_time_data.m" ]
 }
diff --git a/chrome/browser/resources/chromeos/login/components/BUILD.gn b/chrome/browser/resources/chromeos/login/components/BUILD.gn
index a0bec8d2..6141d42 100644
--- a/chrome/browser/resources/chromeos/login/components/BUILD.gn
+++ b/chrome/browser/resources/chromeos/login/components/BUILD.gn
@@ -25,6 +25,7 @@
     ":fake_oobe",
     ":hd_iron_icon",
     ":html_echo",
+    ":keyboard_utils_for_injection",
     ":long_touch_detector",
     ":oobe_select",
     ":oobe_types",
@@ -134,6 +135,9 @@
 js_library("html_echo") {
 }
 
+js_library("keyboard_utils_for_injection") {
+}
+
 js_library("long_touch_detector") {
 }
 
diff --git a/chrome/browser/resources/chromeos/login/components/keyboard_utils_for_injection.html b/chrome/browser/resources/chromeos/login/components/keyboard_utils_for_injection.html
new file mode 100644
index 0000000..b3b5c83
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/components/keyboard_utils_for_injection.html
@@ -0,0 +1,9 @@
+<!-- Copyright 2021 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. -->
+
+<!-- This is just a dummy file to assist with the Polymer3 migration.
+     Adding this file as an import will force the Polymer3 version of
+     the file to add the directive:
+     - `import {INJECTED_WEBVIEW_SCRIPT} from '.../keyboard_utils_for_injection.m.js';`
+-->
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/login/components/keyboard_utils_for_injection.js b/chrome/browser/resources/chromeos/login/components/keyboard_utils_for_injection.js
new file mode 100644
index 0000000..de3c43f
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/components/keyboard_utils_for_injection.js
@@ -0,0 +1,17 @@
+// Copyright 2021 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.
+
+/**
+ * TODO(crbug.com/1229130) - Find a better way to do this.
+ *
+ * Code which is embedded inside of the enterprise enrollment webview.
+ * See /screens/oobe/enterprise_enrollment.js for details.
+ */
+const INJECTED_WEBVIEW_SCRIPT = String.raw`
+                    (function() {
+                       // <include src="../../keyboard/keyboard_utils.js">
+                       keyboard.initializeKeyboardFlow(true);
+                     })();`;
+
+window.INJECTED_WEBVIEW_SCRIPT = INJECTED_WEBVIEW_SCRIPT;
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/login/components/network_select_login.js b/chrome/browser/resources/chromeos/login/components/network_select_login.js
index c3bf941..37d1b424 100644
--- a/chrome/browser/resources/chromeos/login/components/network_select_login.js
+++ b/chrome/browser/resources/chromeos/login/components/network_select_login.js
@@ -14,7 +14,7 @@
  */
 let networkCustomItemCustomData;
 
-class NetworkSelectLogin extends Polymer.Element {
+/* #export */ class NetworkSelectLogin extends Polymer.Element {
   static get is() {
     return 'network-select-login';
   }
diff --git a/chrome/browser/resources/chromeos/login/enterprise_enrollment.js b/chrome/browser/resources/chromeos/login/enterprise_enrollment.js
index f20e0ec..0080a36e 100644
--- a/chrome/browser/resources/chromeos/login/enterprise_enrollment.js
+++ b/chrome/browser/resources/chromeos/login/enterprise_enrollment.js
@@ -42,7 +42,7 @@
 /**
  * The same steps as in offline-ad-login-element.
  */
-const adLoginStep = {
+const ADLoginStep = {
   UNLOCK: 'unlock',
   CREDS: 'creds',
 };
@@ -399,7 +399,7 @@
    * Sets Active Directory join screen params.
    * @param {string} machineName
    * @param {string} userName
-   * @param {ACTIVE_DIRECTORY_ERROR_STATE} errorState
+   * @param {ActiveDirectoryErrorState} errorState
    * @param {boolean} showUnlockConfig true if there is an encrypted
    * configuration (and not unlocked yet).
    */
@@ -409,9 +409,9 @@
     this.$["step-ad-join"].userName = userName;
     this.$["step-ad-join"].errorState = errorState;
     if (showUnlockConfig) {
-      this.$["step-ad-join"].setUIStep(adLoginStep.UNLOCK);
+      this.$["step-ad-join"].setUIStep(ADLoginStep.UNLOCK);
     } else {
-      this.$["step-ad-join"].setUIStep(adLoginStep.CREDS);
+      this.$["step-ad-join"].setUIStep(ADLoginStep.CREDS);
     }
   },
 
@@ -422,7 +422,7 @@
   setAdJoinConfiguration(options) {
     this.$["step-ad-join"].disabled = false;
     this.$["step-ad-join"].setJoinConfigurationOptions(options);
-    this.$["step-ad-join"].setUIStep(adLoginStep.CREDS);
+    this.$["step-ad-join"].setUIStep(ADLoginStep.CREDS);
     this.$["step-ad-join"].focus();
   },
 
diff --git a/chrome/browser/resources/chromeos/login/keyboard_utils.html b/chrome/browser/resources/chromeos/login/keyboard_utils.html
new file mode 100644
index 0000000..7c3db492
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/keyboard_utils.html
@@ -0,0 +1,9 @@
+<!-- Copyright 2021 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. -->
+
+<!-- This is just a dummy file to assist with the Polymer3 migration.
+     Adding this file as an import will force the Polymer3 version of
+     the file to add the directive:
+     - `import {keyboard} from '.../keyboard_utils.m.js';`
+-->
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/login/oobe_auto_imports.gni b/chrome/browser/resources/chromeos/login/oobe_auto_imports.gni
index 6b61e8c..54e8ee0 100644
--- a/chrome/browser/resources/chromeos/login/oobe_auto_imports.gni
+++ b/chrome/browser/resources/chromeos/login/oobe_auto_imports.gni
@@ -41,14 +41,18 @@
   "chrome/browser/resources/chromeos/login/components/behaviors/multi_step_behavior.html|MultiStepBehavior,MultiStepBehaviorInterface",
   "chrome/browser/resources/chromeos/login/components/display_manager_types.html|OOBE_UI_STATE",
   "chrome/browser/resources/chromeos/login/components/long_touch_detector.html|LongTouchDetector",
+  "chrome/browser/resources/chromeos/login/components/network_select_login.html|NetworkSelectLogin",
   "chrome/browser/resources/chromeos/login/components/oobe_select.html|getSelectedValue,getSelectedTitle,SelectListType,setupSelect",
   "chrome/browser/resources/chromeos/login/components/oobe_types.html|OobeTypes",
   "chrome/browser/resources/chromeos/login/components/oobe_a11y_option.html|OobeA11yOption",
   "chrome/browser/resources/chromeos/login/components/web_view_helper.html|WebViewHelper",
   "chrome/browser/resources/chromeos/login/screens/oobe/welcome_dialog.html|OobeWelcomeDialog",
   "chrome/browser/resources/chromeos/login/components/web_view_loader.html|WebViewLoader",
+  "chrome/browser/resources/chromeos/login/screens/common/offline_ad_login.html|ActiveDirectoryErrorState,ADLoginStep,JoinConfigType",
   "chrome/browser/resources/chromeos/login/screens/login/checking_downloading_update.html|CheckingDownloadingUpdate",
+  "chrome/browser/resources/chromeos/login/screens/oobe/welcome_dialog.html|OobeWelcomeDialog",
   "chrome/browser/resources/chromeos/login/cr_ui.html|Oobe",
+  "chrome/browser/resources/chromeos/login/keyboard_utils.html|keyboard",
   "chrome/browser/resources/chromeos/login/login_ui_tools.html|addSubmitListener",
   "ui/webui/resources/cr_components/chromeos/network/mojo_interface_provider.html|MojoInterfaceProviderImpl",
   "ui/webui/resources/cr_components/chromeos/network/network_list_types.html|NetworkList",
diff --git a/chrome/browser/resources/chromeos/login/oobe_conditional_resources.grd b/chrome/browser/resources/chromeos/login/oobe_conditional_resources.grd
index 577c3591..19a5592 100644
--- a/chrome/browser/resources/chromeos/login/oobe_conditional_resources.grd
+++ b/chrome/browser/resources/chromeos/login/oobe_conditional_resources.grd
@@ -24,6 +24,8 @@
 
       <structure name="IDR_OOBE_DEBUGGER_JS" file="debug\debug.js" flattenhtml="true" type="chrome_html" />
       <structure name="IDR_OOBE_DEBUGGER_STUB_JS" file="debug\no_debug.js" flattenhtml="true" type="chrome_html" />
+
+      <structure name="IDR_KEYBOARD_UTILS_FOR_INJECTION_JS" file="components/keyboard_utils_for_injection.js" flattenhtml="true" type="chrome_html" />
     </structures>
     <includes>
       <!-- Resources that are served under fixed paths -->
diff --git a/chrome/browser/resources/chromeos/login/oobe_polymer3.html b/chrome/browser/resources/chromeos/login/oobe_polymer3.html
index b555196..9223ef6d 100644
--- a/chrome/browser/resources/chromeos/login/oobe_polymer3.html
+++ b/chrome/browser/resources/chromeos/login/oobe_polymer3.html
@@ -38,6 +38,8 @@
           </demo-preferences-element>
           <demo-setup-element id="demo-setup" class="step hidden" hidden>
           </demo-setup-element>
+          <oobe-network-element id="network-selection" class="step hidden" hidden>
+          </oobe-network-element>
           <packaged-license-element id="packaged-license" class="step hidden" hidden>
           </packaged-license-element>
           <autolaunch-element id="autolaunch" class="step hidden" hidden>
@@ -78,6 +80,8 @@
           </user-creation-element>
           <oobe-reset-element id="reset" class="step hidden" hidden>
           </oobe-reset-element>
+          <saml-confirm-password-element id="saml-confirm-password" class="step hidden" hidden>
+          </saml-confirm-password-element>
           <consolidated-consent-element id="consolidated-consent" class="step hidden" hidden>
           </consolidated-consent-element>
           <guest-tos-element id="guest-tos" class="step hidden" hidden>
diff --git a/chrome/browser/resources/chromeos/login/oobe_polymer3.js b/chrome/browser/resources/chromeos/login/oobe_polymer3.js
index d5faaeb..f0f0c12 100644
--- a/chrome/browser/resources/chromeos/login/oobe_polymer3.js
+++ b/chrome/browser/resources/chromeos/login/oobe_polymer3.js
@@ -30,6 +30,7 @@
 import 'chrome://oobe/screens/common/os_trial.m.js';
 import 'chrome://oobe/screens/common/parental_handoff.m.js';
 import 'chrome://oobe/screens/common/pin_setup.m.js';
+import 'chrome://oobe/screens/common/saml_confirm_password.m.js';
 import 'chrome://oobe/screens/common/signin_fatal_error.m.js';
 import 'chrome://oobe/screens/common/sync_consent.m.js';
 import 'chrome://oobe/screens/common/tpm_error.m.js';
@@ -48,6 +49,7 @@
 import 'chrome://oobe/screens/oobe/enable_debugging.m.js';
 import 'chrome://oobe/screens/oobe/hid_detection.m.js';
 import 'chrome://oobe/screens/oobe/oobe_eula.m.js';
+import 'chrome://oobe/screens/oobe/oobe_network.m.js';
 import 'chrome://oobe/screens/oobe/welcome.m.js';
 import 'chrome://oobe/screens/oobe/packaged_license.m.js';
 import 'chrome://oobe/screens/oobe/update.m.js';
diff --git a/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn b/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn
index a85c95c5..4cbea955 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn
+++ b/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn
@@ -34,6 +34,7 @@
     ":os_trial_module",
     ":parental_handoff_module",
     ":pin_setup_module",
+    ":saml_confirm_password_module",
     ":signin_fatal_error_module",
     ":sync_consent_module",
     ":tpm_error_module",
@@ -72,6 +73,7 @@
     ":os_trial.m",
     ":parental_handoff.m",
     ":pin_setup.m",
+    ":saml_confirm_password.m",
     ":signin_fatal_error.m",
     ":sync_consent.m",
     ":tpm_error.m",
@@ -333,6 +335,7 @@
     "../../components/buttons:oobe_text_button.m",
     "../../components/dialogs:oobe_adaptive_dialog.m",
     "//ui/webui/resources/cr_elements/cr_input:cr_input.m",
+    "//ui/webui/resources/cr_elements/cr_toggle:cr_toggle.m",
     "//ui/webui/resources/js:load_time_data.m",
   ]
   extra_deps = [ ":offline_ad_login_module" ]
@@ -425,6 +428,20 @@
   extra_deps = [ ":pin_setup_module" ]
 }
 
+js_library("saml_confirm_password.m") {
+  sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/common/saml_confirm_password.m.js" ]
+  deps = [
+    "../../:login_ui_tools.m",
+    "../../components/behaviors:oobe_i18n_behavior.m",
+    "../../components/buttons:oobe_next_button.m",
+    "../../components/buttons:oobe_text_button.m",
+    "../../components/dialogs:oobe_adaptive_dialog.m",
+    "../../components/dialogs:oobe_loading_dialog.m",
+    "../../components/dialogs:oobe_modal_dialog.m",
+  ]
+  extra_deps = [ ":saml_confirm_password_module" ]
+}
+
 js_library("signin_fatal_error.m") {
   sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/common/signin_fatal_error.m.js" ]
   deps = [
@@ -686,6 +703,14 @@
   namespace_rewrites = oobe_namespace_rewrites
 }
 
+polymer_modulizer("saml_confirm_password") {
+  js_file = "saml_confirm_password.js"
+  html_file = "saml_confirm_password.html"
+  html_type = "dom-module"
+  auto_imports = oobe_auto_imports
+  namespace_rewrites = oobe_namespace_rewrites
+}
+
 polymer_modulizer("signin_fatal_error") {
   js_file = "signin_fatal_error.js"
   html_file = "signin_fatal_error.html"
diff --git a/chrome/browser/resources/chromeos/login/screens/common/offline_ad_login.html b/chrome/browser/resources/chromeos/login/screens/common/offline_ad_login.html
index 196583d..0060066 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/offline_ad_login.html
+++ b/chrome/browser/resources/chromeos/login/screens/common/offline_ad_login.html
@@ -5,8 +5,9 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/cr_elements/md_select_css.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/cr_elements/md_select_css.html">
 <link rel="import" href="chrome://resources/html/load_time_data.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 
diff --git a/chrome/browser/resources/chromeos/login/screens/common/offline_ad_login.js b/chrome/browser/resources/chromeos/login/screens/common/offline_ad_login.js
index d1c72672..1f999bdba 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/offline_ad_login.js
+++ b/chrome/browser/resources/chromeos/login/screens/common/offline_ad_login.js
@@ -9,7 +9,7 @@
 
 /* #js_imports_placeholder */
 
-// The definitions below (JoinConfigType, ACTIVE_DIRECTORY_ERROR_STATE) are
+// The definitions below (JoinConfigType, ActiveDirectoryErrorState) are
 // used in enterprise_enrollment.js as well.
 
 /**
@@ -17,11 +17,14 @@
  *             computer_ou: ?string, encryption_types: ?string,
  *             computer_name_validation_regex: ?string}}
  */
-var JoinConfigType;
+/* #export */ var JoinConfigType;
 
 // Possible error states of the screen. Must be in the same order as
 // ActiveDirectoryErrorState enum values. Used in enterprise_enrollment
-/** @enum {number} */ var ACTIVE_DIRECTORY_ERROR_STATE = {
+/**
+ * @enum {number}
+ */
+/* #export */ const ActiveDirectoryErrorState = {
   NONE: 0,
   MACHINE_NAME_INVALID: 1,
   MACHINE_NAME_TOO_LONG: 2,
@@ -30,7 +33,8 @@
   BAD_UNLOCK_PASSWORD: 5,
 };
 
-const adLoginStep = {
+// Used by enterprise_enrollment.js
+/* #export */ const ADLoginStep = {
   UNLOCK: 'unlock',
   CREDS: 'creds',
 };
@@ -120,7 +124,7 @@
        */
       errorState: {
         type: Number,
-        value: ACTIVE_DIRECTORY_ERROR_STATE.NONE,
+        value: ActiveDirectoryErrorState.NONE,
         observer: 'errorStateObserver_'
       },
       /**
@@ -241,11 +245,11 @@
   }
 
   get UI_STEPS() {
-    return adLoginStep;
+    return ADLoginStep;
   }
 
   defaultUIStep() {
-    return adLoginStep.CREDS;
+    return ADLoginStep.CREDS;
   }
 
   /** @override */
@@ -273,7 +277,7 @@
 
   /**
    * @param {string} username
-   * @param {ACTIVE_DIRECTORY_ERROR_STATE} errorState
+   * @param {ActiveDirectoryErrorState} errorState
    */
   setErrorState(username, errorState) {
     this.userName = username;
@@ -284,7 +288,7 @@
   reset() {
     this.$.userInput.value = '';
     this.$.passwordInput.value = '';
-    this.errorState = ACTIVE_DIRECTORY_ERROR_STATE.NONE;
+    this.errorState = ActiveDirectoryErrorState.NONE;
   }
 
   setupEncList() {
@@ -304,7 +308,7 @@
   }
 
   focus() {
-    if (this.uiStep === adLoginStep.UNLOCK) {
+    if (this.uiStep === ADLoginStep.UNLOCK) {
       this.$.unlockPasswordInput.focus();
     } else if (this.isDomainJoin && !this.$.machineNameInput.value) {
       this.$.machineNameInput.focus();
@@ -322,17 +326,17 @@
     // errorState.
     this.errorStateLocked_ = true;
     this.machineNameInvalid =
-        this.errorState == ACTIVE_DIRECTORY_ERROR_STATE.MACHINE_NAME_INVALID ||
-        this.errorState == ACTIVE_DIRECTORY_ERROR_STATE.MACHINE_NAME_TOO_LONG;
+        this.errorState == ActiveDirectoryErrorState.MACHINE_NAME_INVALID ||
+        this.errorState == ActiveDirectoryErrorState.MACHINE_NAME_TOO_LONG;
     this.userInvalid =
-        this.errorState == ACTIVE_DIRECTORY_ERROR_STATE.BAD_USERNAME;
+        this.errorState == ActiveDirectoryErrorState.BAD_USERNAME;
     this.authPasswordInvalid =
-        this.errorState == ACTIVE_DIRECTORY_ERROR_STATE.BAD_AUTH_PASSWORD;
+        this.errorState == ActiveDirectoryErrorState.BAD_AUTH_PASSWORD;
     this.unlockPasswordInvalid =
-        this.errorState == ACTIVE_DIRECTORY_ERROR_STATE.BAD_UNLOCK_PASSWORD;
+        this.errorState == ActiveDirectoryErrorState.BAD_UNLOCK_PASSWORD;
 
     // Clear password.
-    if (this.errorState == ACTIVE_DIRECTORY_ERROR_STATE.NONE)
+    if (this.errorState == ActiveDirectoryErrorState.NONE)
       this.$.passwordInput.value = '';
     this.errorStateLocked_ = false;
   }
@@ -455,7 +459,7 @@
   /** @private */
   onSkipClicked_() {
     this.backToUnlockButtonVisible_ = true;
-    this.setUIStep(adLoginStep.CREDS);
+    this.setUIStep(ADLoginStep.CREDS);
     this.focus();
   }
 
@@ -463,7 +467,7 @@
   onBackToUnlock_() {
     if (this.disabled)
       return;
-    this.setUIStep(adLoginStep.UNLOCK);
+    this.setUIStep(ADLoginStep.UNLOCK);
     this.focus();
   }
 
@@ -479,7 +483,7 @@
   onJoinConfigSelected_(value) {
     if (this.selectedConfigOption_ == this.joinConfigOptions_[value])
       return;
-    this.errorState = ACTIVE_DIRECTORY_ERROR_STATE.NONE;
+    this.errorState = ActiveDirectoryErrorState.NONE;
     this.previousSelectedConfigOption_ = this.selectedConfigOption_;
     this.selectedConfigOption_ = this.joinConfigOptions_[value];
     var option = this.selectedConfigOption_;
@@ -547,16 +551,16 @@
 
   /**
    * Returns true if "Machine name is invalid" error should be displayed.
-   * @param {ACTIVE_DIRECTORY_ERROR_STATE} errorState
+   * @param {ActiveDirectoryErrorState} errorState
    */
   isMachineNameInvalid_(errorState) {
-    return errorState != ACTIVE_DIRECTORY_ERROR_STATE.MACHINE_NAME_TOO_LONG;
+    return errorState != ActiveDirectoryErrorState.MACHINE_NAME_TOO_LONG;
   }
 
   getMachineNameError_(locale, errorState) {
-    if (errorState == ACTIVE_DIRECTORY_ERROR_STATE.MACHINE_NAME_TOO_LONG)
+    if (errorState == ActiveDirectoryErrorState.MACHINE_NAME_TOO_LONG)
       return this.i18nDynamic(locale, 'adJoinErrorMachineNameTooLong');
-    if (errorState == ACTIVE_DIRECTORY_ERROR_STATE.MACHINE_NAME_INVALID) {
+    if (errorState == ActiveDirectoryErrorState.MACHINE_NAME_INVALID) {
       if (this.machineNameInputPattern_) {
         return this.i18nDynamic(locale, 'adJoinErrorMachineNameInvalidFormat');
       }
@@ -571,11 +575,11 @@
       else
         this.onUnlockPasswordEntered_();
     }
-    this.errorState = ACTIVE_DIRECTORY_ERROR_STATE.NONE;
+    this.errorState = ActiveDirectoryErrorState.NONE;
   }
 
   onKeydownMachineNameInput_(e) {
-    this.errorState = ACTIVE_DIRECTORY_ERROR_STATE.NONE;
+    this.errorState = ActiveDirectoryErrorState.NONE;
     if (e.key == 'Enter') {
       this.switchTo_('userInput') || this.switchTo_('passwordInput') ||
           this.onSubmit_();
@@ -583,7 +587,7 @@
   }
 
   onKeydownUserInput_(e) {
-    this.errorState = ACTIVE_DIRECTORY_ERROR_STATE.NONE;
+    this.errorState = ActiveDirectoryErrorState.NONE;
     if (e.key == 'Enter')
       this.switchTo_('passwordInput') || this.onSubmit_();
   }
@@ -600,7 +604,7 @@
   }
 
   onKeydownAuthPasswordInput_(e) {
-    this.errorState = ACTIVE_DIRECTORY_ERROR_STATE.NONE;
+    this.errorState = ActiveDirectoryErrorState.NONE;
     if (e.key == 'Enter')
       this.onSubmit_();
   }
@@ -615,21 +619,21 @@
 
   machineNameInvalidObserver_(isInvalid) {
     this.setErrorState_(
-        isInvalid, ACTIVE_DIRECTORY_ERROR_STATE.MACHINE_NAME_INVALID);
+        isInvalid, ActiveDirectoryErrorState.MACHINE_NAME_INVALID);
   }
 
   userInvalidObserver_(isInvalid) {
-    this.setErrorState_(isInvalid, ACTIVE_DIRECTORY_ERROR_STATE.BAD_USERNAME);
+    this.setErrorState_(isInvalid, ActiveDirectoryErrorState.BAD_USERNAME);
   }
 
   authPasswordInvalidObserver_(isInvalid) {
     this.setErrorState_(
-        isInvalid, ACTIVE_DIRECTORY_ERROR_STATE.BAD_AUTH_PASSWORD);
+        isInvalid, ActiveDirectoryErrorState.BAD_AUTH_PASSWORD);
   }
 
   unlockPasswordInvalidObserver_(isInvalid) {
     this.setErrorState_(
-        isInvalid, ACTIVE_DIRECTORY_ERROR_STATE.BAD_UNLOCK_PASSWORD);
+        isInvalid, ActiveDirectoryErrorState.BAD_UNLOCK_PASSWORD);
   }
 
   setErrorState_(isInvalid, error) {
@@ -639,7 +643,7 @@
     if (isInvalid)
       this.errorState = error;
     else
-      this.errorState = ACTIVE_DIRECTORY_ERROR_STATE.NONE;
+      this.errorState = ActiveDirectoryErrorState.NONE;
     this.errorStateLocked_ = false;
   }
 
diff --git a/chrome/browser/resources/chromeos/login/saml_confirm_password.html b/chrome/browser/resources/chromeos/login/screens/common/saml_confirm_password.html
similarity index 74%
rename from chrome/browser/resources/chromeos/login/saml_confirm_password.html
rename to chrome/browser/resources/chromeos/login/screens/common/saml_confirm_password.html
index fadb8df..008b0bba 100644
--- a/chrome/browser/resources/chromeos/login/saml_confirm_password.html
+++ b/chrome/browser/resources/chromeos/login/screens/common/saml_confirm_password.html
@@ -9,17 +9,20 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 
-<link rel="import" href="/components/oobe_icons.html">
-<link rel="import" href="/components/behaviors/login_screen_behavior.html">
-<link rel="import" href="/components/behaviors/multi_step_behavior.html">
-<link rel="import" href="/components/behaviors/oobe_i18n_behavior.html">
-<link rel="import" href="/components/buttons/oobe_next_button.html">
-<link rel="import" href="/components/buttons/oobe_text_button.html">
-<link rel="import" href="/components/common_styles/common_styles.html">
-<link rel="import" href="/components/common_styles/oobe_dialog_host_styles.html">
-<link rel="import" href="/components/dialogs/oobe_adaptive_dialog.html">
-<link rel="import" href="/components/dialogs/oobe_loading_dialog.html">
-<link rel="import" href="/components/dialogs/oobe_modal_dialog.html">
+<link rel="import" href="../../cr_ui.html">
+<link rel="import" href="../../login_ui_tools.html">
+<link rel="import" href="../../components/display_manager_types.html">
+<link rel="import" href="../../components/oobe_icons.html">
+<link rel="import" href="../../components/behaviors/login_screen_behavior.html">
+<link rel="import" href="../../components/behaviors/multi_step_behavior.html">
+<link rel="import" href="../../components/behaviors/oobe_i18n_behavior.html">
+<link rel="import" href="../../components/buttons/oobe_next_button.html">
+<link rel="import" href="../../components/buttons/oobe_text_button.html">
+<link rel="import" href="../../components/common_styles/common_styles.html">
+<link rel="import" href="../../components/common_styles/oobe_dialog_host_styles.html">
+<link rel="import" href="../../components/dialogs/oobe_adaptive_dialog.html">
+<link rel="import" href="../../components/dialogs/oobe_loading_dialog.html">
+<link rel="import" href="../../components/dialogs/oobe_modal_dialog.html">
 
 <!--
   SAML password confirmation UI for the Gaia flow.
@@ -79,8 +82,7 @@
       <iron-icon slot="icon" icon="oobe-32:googleg"></iron-icon>
     </oobe-loading-dialog>
 
-    <oobe-modal-dialog id="cancelConfirmDlg"
-        on-close="onDialogOverlayClosed_">
+    <oobe-modal-dialog id="cancelConfirmDlg">
       <div slot="title">
         [[i18nDynamic(locale, 'accountSetupCancelDialogTitle')]]
       </div>
@@ -95,4 +97,5 @@
     </oobe-modal-dialog>
 
   </template>
+  <script src="saml_confirm_password.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/chromeos/login/saml_confirm_password.js b/chrome/browser/resources/chromeos/login/screens/common/saml_confirm_password.js
similarity index 64%
rename from chrome/browser/resources/chromeos/login/saml_confirm_password.js
rename to chrome/browser/resources/chromeos/login/screens/common/saml_confirm_password.js
index 2f3e5d1..8b74f51b 100644
--- a/chrome/browser/resources/chromeos/login/saml_confirm_password.js
+++ b/chrome/browser/resources/chromeos/login/screens/common/saml_confirm_password.js
@@ -2,52 +2,83 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-'use strict';
-
-(function() {
+/* #js_imports_placeholder */
 
 /**
  * UI mode for the dialog.
  * @enum {string}
  */
-const UIState = {
+const SamlConfirmPasswordState = {
   PASSWORD: 'password',
   PROGRESS: 'progress',
 };
 
-Polymer({
-  is: 'saml-confirm-password-element',
+/**
+ * @constructor
+ * @extends {PolymerElement}
+ * @implements {LoginScreenBehaviorInterface}
+ * @implements {MultiStepBehaviorInterface}
+ * @implements {OobeI18nBehaviorInterface}
+ */
+ const SamlConfirmPasswordBase = Polymer.mixinBehaviors(
+  [OobeI18nBehavior, LoginScreenBehavior, MultiStepBehavior],
+  Polymer.Element);
 
-  behaviors: [
-    OobeI18nBehavior,
-    LoginScreenBehavior,
-    MultiStepBehavior,
-  ],
+/**
+ * @typedef {{
+ *   passwordInput:  CrInputElement,
+ *   confirmPasswordInput: CrInputElement,
+ *   cancelConfirmDlg: OobeModalDialogElement
+ * }}
+ */
+SamlConfirmPasswordBase.$;
 
-  properties: {
-    email: String,
+/**
+ * @polymer
+ */
+class SamlConfirmPassword extends SamlConfirmPasswordBase {
 
-    isManualInput: {
-      type: Boolean,
-      value: false,
-    }
-  },
+  static get is() { return 'saml-confirm-password-element'; }
 
-  EXTERNAL_API: ['show'],
+  /* #html_template_placeholder */
+
+  static get properties() {
+    return {
+      email: {
+        type: String,
+        value: '',
+      },
+
+      isManualInput: {
+        type: Boolean,
+        value: false,
+      }
+    };
+  }
+
+  constructor() {
+    super();
+    /**
+     * Callback to run when the screen is dismissed.
+     * @type {?function(string)}
+     */
+    this.callback_ = null;
+  }
+
+  get EXTERNAL_API() {
+    return ['show'];
+  }
 
   defaultUIStep() {
-    return UIState.PASSWORD;
-  },
+    return SamlConfirmPasswordState.PASSWORD;
+  }
 
-  UI_STEPS: UIState,
-
-  /**
-   * Callback to run when the screen is dismissed.
-   * @type {?function(string)}
-   */
-  callback_: null,
+  get UI_STEPS() {
+    return SamlConfirmPasswordState;
+  }
 
   ready() {
+    super.ready();
     this.initializeLoginScreen('ConfirmSamlPasswordScreen', {
       resetAllowed: true,
     });
@@ -56,12 +87,12 @@
         this.$.passwordInput, this.submit_.bind(this));
     cr.ui.LoginUITools.addSubmitListener(
         this.$.confirmPasswordInput, this.submit_.bind(this));
-  },
+  }
 
   /** Initial UI State for screen */
   getOobeUIInitialState() {
     return OOBE_UI_STATE.SAML_PASSWORD_CONFIRM;
-  },
+  }
 
   /**
    * Shows the confirm password screen.
@@ -79,8 +110,8 @@
     this.isManualInput = manualPasswordInput;
     if (attemptCount > 0)
       this.$.passwordInput.invalid = true;
-    cr.ui.Oobe.showScreen({id: 'saml-confirm-password'});
-  },
+    Oobe.getInstance().showScreen({id: 'saml-confirm-password'});
+  }
 
   resetFields() {
     this.$.passwordInput.invalid = false;
@@ -89,30 +120,30 @@
       this.shadowRoot.querySelector('#confirmPasswordInput').invalid = false;
       this.shadowRoot.querySelector('#confirmPasswordInput').value = '';
     }
-  },
+  }
 
   reset() {
     if (this.$.cancelConfirmDlg.open)
       this.$.cancelConfirmDlg.hideDialog();
-    this.setUIStep(UIState.PASSWORD);
+    this.setUIStep(SamlConfirmPasswordState.PASSWORD);
     this.resetFields();
-  },
+  }
 
 
   onCancel_() {
     this.$.cancelConfirmDlg.showDialog();
-  },
+  }
 
   onCancelNo_() {
     this.$.cancelConfirmDlg.hideDialog();
-  },
+  }
 
   onCancelYes_() {
     this.$.cancelConfirmDlg.hideDialog();
 
-    cr.ui.Oobe.showScreen({id: 'gaia-signin'});
-    cr.ui.Oobe.resetSigninUI(true);
-  },
+    Oobe.getInstance().showScreen({id: 'gaia-signin'});
+    Oobe.getInstance().resetSigninUI(true);
+  }
 
   submit_() {
     if (!this.$.passwordInput.validate())
@@ -129,29 +160,26 @@
         return;
       }
     }
-    this.setUIStep(UIState.PROGRESS);
+    this.setUIStep(SamlConfirmPasswordState.PROGRESS);
     this.callback_(this.$.passwordInput.value);
     this.resetFields();
-  },
-
-  onDialogOverlayClosed_() {
-    this.disabled = false;
-  },
+  }
 
   subtitleText_(locale, manual) {
     const key = manual ? 'manualPasswordTitle' : 'confirmPasswordTitle';
     return this.i18n(key);
-  },
+  }
 
   passwordPlaceholder_(locale, manual) {
     const key = manual ? 'manualPasswordInputLabel' : 'confirmPasswordLabel';
     return this.i18n(key);
-  },
+  }
 
   passwordErrorText_(locale, manual) {
     const key =
         manual ? 'manualPasswordMismatch' : 'confirmPasswordIncorrectPassword';
     return this.i18n(key);
-  },
-});
-})();
+  }
+}
+
+customElements.define(SamlConfirmPassword.is, SamlConfirmPassword);
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/login/screens/oobe/BUILD.gn b/chrome/browser/resources/chromeos/login/screens/oobe/BUILD.gn
index 5ab1c295..51bdcf3d 100644
--- a/chrome/browser/resources/chromeos/login/screens/oobe/BUILD.gn
+++ b/chrome/browser/resources/chromeos/login/screens/oobe/BUILD.gn
@@ -15,6 +15,7 @@
     ":enable_debugging_module",
     ":hid_detection_module",
     ":oobe_eula_module",
+    ":oobe_network_module",
     ":packaged_license_module",
     ":quick_start_module",
     ":update_module",
@@ -23,15 +24,6 @@
   ]
 }
 
-group("closure_compile") {
-  deps = [ ":closure_compile_local" ]
-}
-
-js_type_check("closure_compile_local") {
-  uses_legacy_modules = true
-  deps = [ ":oobe_network" ]
-}
-
 js_type_check("closure_compile_module") {
   is_polymer3 = true
   closure_flags = default_closure_args
@@ -42,6 +34,7 @@
     ":enable_debugging.m",
     ":hid_detection.m",
     ":oobe_eula.m",
+    ":oobe_network.m",
     ":packaged_license.m",
     ":quick_start.m",
     ":update.m",
@@ -53,18 +46,6 @@
 ###############################
 # Closure compiler libraries below
 
-js_library("oobe_network") {
-  deps = [
-    # TODO(crbug.com/251576): Restore when migrate to Polymer 3.
-    # "../../components:network_select_login",
-    "../../components/behaviors:login_screen_behavior",
-    "../../components/behaviors:oobe_dialog_host_behavior",
-    "../../components/behaviors:oobe_i18n_behavior",
-    "../../components/dialogs:oobe_adaptive_dialog",
-    "//ui/webui/resources/cr_components/chromeos/network:network_select",
-  ]
-}
-
 js_library("auto_enrollment_check.m") {
   sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/oobe/auto_enrollment_check.m.js" ]
   deps = [
@@ -163,6 +144,20 @@
   extra_deps = [ ":oobe_eula_module" ]
 }
 
+js_library("oobe_network.m") {
+  sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/oobe/oobe_network.m.js" ]
+  deps = [
+    "../../components:network_select_login.m",
+    "../../components/behaviors:login_screen_behavior.m",
+    "../../components/behaviors:oobe_dialog_host_behavior.m",
+    "../../components/behaviors:oobe_i18n_behavior.m",
+    "../../components/dialogs:oobe_adaptive_dialog.m",
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/js:assert.m",
+  ]
+  extra_deps = [ ":oobe_network_module" ]
+}
+
 js_library("packaged_license.m") {
   sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/oobe/packaged_license.m.js" ]
   deps = [
@@ -205,7 +200,7 @@
     "../../components/dialogs:oobe_adaptive_dialog.m",
     "../../components/dialogs:oobe_modal_dialog.m",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-    "//ui/webui/resources/cr_elements/cr_input:cr_input",
+    "//ui/webui/resources/cr_elements/cr_input:cr_input.m",
   ]
   extra_deps = [ ":welcome_module" ]
   externs_list = [ "$externs_path/tts.js" ]
@@ -281,6 +276,14 @@
   namespace_rewrites = oobe_namespace_rewrites
 }
 
+polymer_modulizer("oobe_network") {
+  js_file = "oobe_network.js"
+  html_file = "oobe_network.html"
+  html_type = "dom-module"
+  auto_imports = oobe_auto_imports
+  namespace_rewrites = oobe_namespace_rewrites
+}
+
 polymer_modulizer("packaged_license") {
   js_file = "packaged_license.js"
   html_file = "packaged_license.html"
diff --git a/chrome/browser/resources/chromeos/login/screens/oobe/oobe_network.html b/chrome/browser/resources/chromeos/login/screens/oobe/oobe_network.html
index c4270c8..538e6794 100644
--- a/chrome/browser/resources/chromeos/login/screens/oobe/oobe_network.html
+++ b/chrome/browser/resources/chromeos/login/screens/oobe/oobe_network.html
@@ -1,18 +1,22 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 
-<link rel="import" href="/components/behaviors/login_screen_behavior.html">
-<link rel="import" href="/components/behaviors/oobe_dialog_host_behavior.html">
-<link rel="import" href="/components/behaviors/oobe_i18n_behavior.html">
-<link rel="import" href="/components/buttons/oobe_back_button.html">
-<link rel="import" href="/components/buttons/oobe_next_button.html">
-<link rel="import" href="/components/common_styles/common_styles.html">
-<link rel="import" href="/components/common_styles/oobe_dialog_host_styles.html">
-<link rel="import" href="/components/dialogs/oobe_adaptive_dialog.html">
-<link rel="import" href="/components/network_select_login.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/network/network_list.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/network/network_list_types.html">
+
+<link rel="import" href="../../components/behaviors/login_screen_behavior.html">
+<link rel="import" href="../../components/behaviors/oobe_dialog_host_behavior.html">
+<link rel="import" href="../../components/behaviors/oobe_i18n_behavior.html">
+<link rel="import" href="../../components/buttons/oobe_back_button.html">
+<link rel="import" href="../../components/buttons/oobe_next_button.html">
+<link rel="import" href="../../components/common_styles/common_styles.html">
+<link rel="import" href="../../components/common_styles/oobe_dialog_host_styles.html">
+<link rel="import" href="../../components/dialogs/oobe_adaptive_dialog.html">
+<link rel="import" href="../../components/network_select_login.html">
 
 <dom-module id="oobe-network-element">
   <template>
@@ -52,4 +56,5 @@
       </div>
     </oobe-adaptive-dialog>
   </template>
+  <script src="oobe_network.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/chromeos/login/screens/oobe/oobe_network.js b/chrome/browser/resources/chromeos/login/screens/oobe/oobe_network.js
index 083a82b3..562f8f7 100644
--- a/chrome/browser/resources/chromeos/login/screens/oobe/oobe_network.js
+++ b/chrome/browser/resources/chromeos/login/screens/oobe/oobe_network.js
@@ -6,73 +6,100 @@
  * @fileoverview Polymer element for displaying network selection OOBE dialog.
  */
 
-Polymer({
-  is: 'oobe-network-element',
+/* #js_imports_placeholder */
 
-  behaviors: [OobeI18nBehavior, OobeDialogHostBehavior, LoginScreenBehavior],
+/**
+ * @constructor
+ * @extends {PolymerElement}
+ * @implements {LoginScreenBehaviorInterface}
+ * @implements {OobeI18nBehaviorInterface}
+ */
+const NetworkScreenBase = Polymer.mixinBehaviors(
+    [OobeI18nBehavior, OobeDialogHostBehavior, LoginScreenBehavior],
+    Polymer.Element);
+/**
+ * @typedef {{
+ *   networkSelectLogin:  NetworkSelectLogin,
+ *   networkDialog:  HTMLElement,
+ *   nextButton:  HTMLElement,
+ * }}
+ */
+NetworkScreenBase.$;
 
-  EXTERNAL_API: [
-    'setOfflineDemoModeEnabled',
-    'setError',
-  ],
+/**
+ * @polymer
+ */
+class NetworkScreen extends NetworkScreenBase {
+  static get is() {
+    return 'oobe-network-element';
+  }
 
-  properties: {
-    /**
-     * Whether network dialog is shown as a part of demo mode setup flow.
-     * Additional custom elements can be displayed on network list in demo mode
-     * setup.
-     * @type {boolean}
-     */
-    isDemoModeSetup: {
-      type: Boolean,
-      value: false,
-    },
+  /* #html_template_placeholder */
 
-    /**
-     * Whether offline demo mode is enabled. If it is enabled offline setup
-     * option will be shown in UI.
-     * @type {boolean}
-     */
-    offlineDemoModeEnabled: {
-      type: Boolean,
-      value: false,
-    },
+  static get properties() {
+    return {
+      /**
+       * Whether network dialog is shown as a part of demo mode setup flow.
+       * Additional custom elements can be displayed on network list in demo
+       * mode setup.
+       * @type {boolean}
+       */
+      isDemoModeSetup: {
+        type: Boolean,
+        value: false,
+      },
 
-    /**
-     * Network error message.
-     * @type {string}
-     * @private
-     */
-    errorMessage_: {
-      type: String,
-      value: '',
-    },
+      /**
+       * Whether offline demo mode is enabled. If it is enabled offline setup
+       * option will be shown in UI.
+       * @type {boolean}
+       */
+      offlineDemoModeEnabled: {
+        type: Boolean,
+        value: false,
+      },
 
-    /**
-     * Whether device is connected to the network.
-     * @type {boolean}
-     * @private
-     */
-    isConnected_: {
-      type: Boolean,
-      value: false,
-    },
+      /**
+       * Network error message.
+       * @type {string}
+       * @private
+       */
+      errorMessage_: {
+        type: String,
+        value: '',
+      },
 
-    /**
-     * Controls if periodic background Wi-Fi scans are enabled to update the
-     * list of available networks. It is enabled by default so that when user
-     * gets to screen networks are already listed, but should be off when user
-     * leaves the screen, as scanning can reduce effective bandwidth.
-     * @private
-     */
-    enableWifiScans_: {
-      type: Boolean,
-      value: true,
-    },
-  },
+      /**
+       * Whether device is connected to the network.
+       * @type {boolean}
+       * @private
+       */
+      isConnected_: {
+        type: Boolean,
+        value: false,
+      },
 
-  observers:
-      ['onDemoModeSetupChanged_(isDemoModeSetup, offlineDemoModeEnabled)'],
+      /**
+       * Controls if periodic background Wi-Fi scans are enabled to update the
+       * list of available networks. It is enabled by default so that when user
+       * gets to screen networks are already listed, but should be off when user
+       * leaves the screen, as scanning can reduce effective bandwidth.
+       * @private
+       */
+      enableWifiScans_: {
+        type: Boolean,
+        value: true,
+      },
+    };
+  }
+
+  static get observers() {
+    return ['onDemoModeSetupChanged_(isDemoModeSetup, offlineDemoModeEnabled)'];
+  }
+
+  get EXTERNAL_API() {
+    return ['setOfflineDemoModeEnabled', 'setError'];
+  }
 
   /** Called when dialog is shown. */
   onBeforeShow(data) {
@@ -84,35 +111,36 @@
     this.errorMessage_ = '';
     this.$.networkSelectLogin.onBeforeShow();
     this.show();
-  },
+  }
 
   /** Called when dialog is hidden. */
   onBeforeHide() {
-    cr.ui.login.invokePolymerMethod(this.$.networkSelectLogin, 'onBeforeHide');
+    this.$.networkSelectLogin.onBeforeHide();
     this.enableWifiScans_ = false;
-  },
+  }
 
   /** @override */
   ready() {
+    super.ready();
     this.initializeLoginScreen('NetworkScreen', {
       resetAllowed: true,
     });
     this.updateLocalizedContent();
-  },
+  }
 
   /** Shows the dialog. */
   show() {
     this.$.networkDialog.show();
-  },
+  }
 
   focus() {
     this.$.networkDialog.focus();
-  },
+  }
 
   /** Updates localized elements of the UI. */
   updateLocalizedContent() {
     this.i18nUpdateLocale();
-  },
+  }
 
   /**
    * Sets the network error message.
@@ -120,7 +148,7 @@
    */
   setError(message) {
     this.errorMessage_ = message;
-  },
+  }
 
   /**
    * Enables or disables the offline Demo Mode option.
@@ -128,7 +156,7 @@
    */
   setOfflineDemoModeEnabled(enabled) {
     this.offlineDemoModeEnabled = enabled;
-  },
+  }
 
   /**
    * Returns element of the network list selected by the query.
@@ -141,7 +169,7 @@
         this.$.networkSelectLogin.shadowRoot.querySelector('#networkSelect').getNetworkListForTest();
     assert(networkList);
     return networkList.querySelector(query);
-  },
+  }
 
   /**
    * Returns element of the network list with the given name.
@@ -152,7 +180,7 @@
   getNetworkListItemByNameForTest(name) {
     return this.$.networkSelectLogin.shadowRoot.querySelector('#networkSelect')
         .getNetworkListItemByNameForTest(name);
-  },
+  }
 
   /**
    * Called after dialog is shown. Refreshes the list of the networks.
@@ -160,15 +188,15 @@
    */
   onShown_() {
     this.$.networkSelectLogin.refresh();
-    this.async(function() {
+    setTimeout(() => {
       if (this.isConnected_)
         this.$.nextButton.focus();
       else
         this.$.networkSelectLogin.focus();
-    }.bind(this), 300);
+    }, 300);
     // Timeout is a workaround to correctly propagate focus to
     // RendererFrameHostImpl see https://crbug.com/955129 for details.
-  },
+  }
 
   /**
    * Next button click handler.
@@ -176,7 +204,7 @@
    */
   onNextClicked_() {
     chrome.send('login.NetworkScreen.userActed', ['continue']);
-  },
+  }
 
   /**
    * Back button click handler.
@@ -184,7 +212,7 @@
    */
   onBackClicked_() {
     chrome.send('login.NetworkScreen.userActed', ['back']);
-  },
+  }
 
   /**
    * Updates custom elements on network list when demo mode setup properties
@@ -194,7 +222,7 @@
   onDemoModeSetupChanged_() {
     this.$.networkSelectLogin.isOfflineDemoModeSetup =
         this.isDemoModeSetup && this.offlineDemoModeEnabled;
-  },
+  }
 
   /**
    * This is called when network setup is done.
@@ -202,5 +230,7 @@
    */
   onNetworkConnected_() {
     chrome.send('login.NetworkScreen.userActed', ['continue']);
-  },
-});
+  }
+}
+
+customElements.define(NetworkScreen.is, NetworkScreen);
diff --git a/chrome/browser/resources/chromeos/login/screens/oobe/welcome_dialog.html b/chrome/browser/resources/chromeos/login/screens/oobe/welcome_dialog.html
index c3c1455..c347857 100644
--- a/chrome/browser/resources/chromeos/login/screens/oobe/welcome_dialog.html
+++ b/chrome/browser/resources/chromeos/login/screens/oobe/welcome_dialog.html
@@ -6,6 +6,7 @@
 
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
 <link rel="import" href="chrome://resources/html/action_link.html">
+<link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/load_time_data.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
diff --git a/chrome/browser/resources/chromeos/login/structure/components_common.html b/chrome/browser/resources/chromeos/login/structure/components_common.html
index fe65590..6d1978b 100644
--- a/chrome/browser/resources/chromeos/login/structure/components_common.html
+++ b/chrome/browser/resources/chromeos/login/structure/components_common.html
@@ -34,6 +34,7 @@
 <link rel="import" href="/screens/common/oobe_reset.html">
 <link rel="import" href="/screens/common/parental_handoff.html">
 <link rel="import" href="/screens/common/pin_setup.html">
+<link rel="import" href="/screens/common/saml_confirm_password.html">
 <link rel="import" href="/screens/common/signin_fatal_error.html">
 <link rel="import" href="/screens/common/sync_consent.html">
 <link rel="import" href="/screens/common/tpm_error.html">
@@ -46,7 +47,6 @@
 <include src="../components/oobe_network_icons.html">
 
 <include src="../screen_gaia_signin.html">
-<include src="../saml_confirm_password.html">
 <include src="../recommend_apps.html">
 <include src="../oobe_screen_assistant_optin_flow.html">
 <include src="../multidevice_setup_first_run.html">
diff --git a/chrome/browser/resources/chromeos/login/structure/components_common.js b/chrome/browser/resources/chromeos/login/structure/components_common.js
index ee6dcda..4cc98a8 100644
--- a/chrome/browser/resources/chromeos/login/structure/components_common.js
+++ b/chrome/browser/resources/chromeos/login/structure/components_common.js
@@ -10,7 +10,6 @@
 // This inclusion is types-only. No actual code to execute.
 
 // <include src="../screen_gaia_signin.js">
-// <include src="../saml_confirm_password.js">
 // <include src="../recommend_apps.js">
 // <include src="../oobe_screen_assistant_optin_flow.js">
 // <include src="../multidevice_setup_first_run.js">
diff --git a/chrome/browser/resources/chromeos/login/structure/components_oobe.html b/chrome/browser/resources/chromeos/login/structure/components_oobe.html
index 05c1f72..1a0970b 100644
--- a/chrome/browser/resources/chromeos/login/structure/components_oobe.html
+++ b/chrome/browser/resources/chromeos/login/structure/components_oobe.html
@@ -9,10 +9,10 @@
 <link rel="import" href="/screens/oobe/enable_debugging.html">
 <link rel="import" href="/screens/oobe/hid_detection.html">
 <link rel="import" href="/screens/oobe/oobe_eula.html">
+<link rel="import" href="/screens/oobe/oobe_network.html">
 <link rel="import" href="/screens/oobe/packaged_license.html">
 <link rel="import" href="/screens/oobe/quick_start.html">
 <link rel="import" href="/screens/oobe/update.html">
 <link rel="import" href="/screens/oobe/welcome.html">
 
-<include src="../screens/oobe/oobe_network.html">
 <include src="../enterprise_enrollment.html">
diff --git a/chrome/browser/resources/chromeos/login/structure/components_oobe.js b/chrome/browser/resources/chromeos/login/structure/components_oobe.js
index 535cb048..7a92f03 100644
--- a/chrome/browser/resources/chromeos/login/structure/components_oobe.js
+++ b/chrome/browser/resources/chromeos/login/structure/components_oobe.js
@@ -4,5 +4,4 @@
 
 // clang-format off
 
-// <include src="../screens/oobe/oobe_network.js">
 // <include src="../enterprise_enrollment.js">
diff --git a/chrome/browser/resources/new_tab_page_third_party/BUILD.gn b/chrome/browser/resources/new_tab_page_third_party/BUILD.gn
index 9fc838a..e486177 100644
--- a/chrome/browser/resources/new_tab_page_third_party/BUILD.gn
+++ b/chrome/browser/resources/new_tab_page_third_party/BUILD.gn
@@ -11,7 +11,15 @@
 
 js_type_check("closure_compile") {
   is_polymer3 = true
-  closure_flags = default_closure_args + mojom_js_args
+  closure_flags = default_closure_args + mojom_js_args + [
+                    "js_module_root=" + rebase_path(".", root_build_dir),
+                    "js_module_root=" + rebase_path(
+                            "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/new_tab_page_third_party",
+                            root_build_dir),
+                    "hide_warnings_for=" + rebase_path(
+                            "$root_gen_dir/mojom-webui/ui/webui/resources/cr_components/most_visited",
+                            root_build_dir),
+                  ]
   deps = [ ":new_tab_page_third_party" ]
 }
 
@@ -21,8 +29,9 @@
 
 js_library("browser_proxy") {
   deps = [
-    "//chrome/browser/ui/webui/new_tab_page_third_party:mojo_bindings_js_library_for_compile",
+    "//chrome/browser/ui/webui/new_tab_page_third_party:mojo_bindings_webui_js",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/cr_components/most_visited:mojom_webui_js",
     "//ui/webui/resources/js:cr.m",
   ]
 }
@@ -44,10 +53,10 @@
 generate_grd("build_new_tab_page_third_party_mojo_grdp") {
   grd_prefix = grd_prefix
   out_grd = "$target_gen_dir/new_tab_page_third_party_mojo_resources.grdp"
-  input_files = [ "new_tab_page_third_party.mojom-lite.js" ]
-  input_files_base_dir =
-      rebase_path(
-          "$root_gen_dir/chrome/browser/ui/webui/new_tab_page_third_party",
+  deps = [ "//chrome/browser/ui/webui/read_later:mojo_bindings_webui_js" ]
+  input_files = [ "new_tab_page_third_party.mojom-webui.js" ]
+  input_files_base_dir = rebase_path(
+          "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/new_tab_page_third_party/",
           root_build_dir)
 }
 
diff --git a/chrome/browser/resources/new_tab_page_third_party/browser_proxy.js b/chrome/browser/resources/new_tab_page_third_party/browser_proxy.js
index 67f6986..62258ce 100644
--- a/chrome/browser/resources/new_tab_page_third_party/browser_proxy.js
+++ b/chrome/browser/resources/new_tab_page_third_party/browser_proxy.js
@@ -2,28 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// TODO(crbug.com/1179821): Migrate to JS module Mojo bindings.
-import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
-import 'chrome://resources/mojo/mojo/public/mojom/base/text_direction.mojom-lite.js';
-import 'chrome://resources/mojo/mojo/public/mojom/base/time.mojom-lite.js';
-import 'chrome://resources/mojo/skia/public/mojom/skcolor.mojom-lite.js';
-import 'chrome://resources/mojo/url/mojom/url.mojom-lite.js';
-
-import 'chrome://resources/cr_components/most_visited/most_visited.mojom-lite.js';
-
-import './new_tab_page_third_party.mojom-lite.js';
-
 import {addSingletonGetter} from 'chrome://resources/js/cr.m.js';
 
+import {PageCallbackRouter, PageHandlerFactory, PageHandlerRemote} from './new_tab_page_third_party.mojom-webui.js';
+
 export class BrowserProxy {
   constructor() {
-    /** @type {newTabPageThirdParty.mojom.PageCallbackRouter} */
-    this.callbackRouter = new newTabPageThirdParty.mojom.PageCallbackRouter();
+    /** @type {!PageCallbackRouter} */
+    this.callbackRouter = new PageCallbackRouter();
 
-    /** @type {newTabPageThirdParty.mojom.PageHandlerRemote} */
-    this.handler = new newTabPageThirdParty.mojom.PageHandlerRemote();
+    /** @type {!PageHandlerRemote} */
+    this.handler = new PageHandlerRemote();
 
-    const factory = newTabPageThirdParty.mojom.PageHandlerFactory.getRemote();
+    const factory = PageHandlerFactory.getRemote();
     factory.createPageHandler(
         this.callbackRouter.$.bindNewPipeAndPassRemote(),
         this.handler.$.bindNewPipeAndPassReceiver());
diff --git a/chrome/browser/resources/tab_strip/tab_list.ts b/chrome/browser/resources/tab_strip/tab_list.ts
index 8487eb9..0ad2b6b 100644
--- a/chrome/browser/resources/tab_strip/tab_list.ts
+++ b/chrome/browser/resources/tab_strip/tab_list.ts
@@ -474,6 +474,20 @@
     this.$<TabElement>('tabstrip-tab')!.focus();
   }
 
+  private updatePreviouslyActiveTabs(activeTabId: number) {
+    // There may be more than 1 TabElement marked as active if other events
+    // have updated a Tab to have an active state. For example, if a
+    // tab is created with an already active state, there may be 2 active
+    // TabElements: the newly created tab and the previously active tab.
+    this.$all<TabElement>('tabstrip-tab[active]')
+        .forEach((previouslyActiveTab) => {
+          if (previouslyActiveTab.tab.id !== activeTabId) {
+            previouslyActiveTab.tab = /** @type {!Tab} */ (
+                Object.assign({}, previouslyActiveTab.tab, {active: false}));
+          }
+        });
+  }
+
   private onTabActivated_(tabId: number) {
     if (this.activatingTabId_ === tabId) {
       this.tabsApi_.reportTabActivationDuration(
@@ -482,18 +496,7 @@
     this.activatingTabId_ = undefined;
     this.activatingTabIdTimestamp_ = undefined;
 
-    // There may be more than 1 TabElement marked as active if other events
-    // have updated a Tab to have an active state. For example, if a
-    // tab is created with an already active state, there may be 2 active
-    // TabElements: the newly created tab and the previously active tab.
-    this.$all<TabElement>('tabstrip-tab[active]')
-        .forEach((previouslyActiveTab) => {
-          if (previouslyActiveTab.tab.id !== tabId) {
-            previouslyActiveTab.tab = /** @type {!Tab} */ (
-                Object.assign({}, previouslyActiveTab.tab, {active: false}));
-          }
-        });
-
+    this.updatePreviouslyActiveTabs(tabId);
     const newlyActiveTab = this.findTabElement_(tabId);
     if (newlyActiveTab) {
       newlyActiveTab.tab =
@@ -552,6 +555,7 @@
     this.placeTabElement(tabElement, tab.index, tab.pinned, tab.groupId);
     this.addAnimationPromise_(tabElement.slideIn());
     if (tab.active) {
+      this.updatePreviouslyActiveTabs(tab.id);
       this.scrollToTab_(tabElement);
     }
   }
diff --git a/chrome/browser/safe_browsing/download_protection/check_client_download_request.cc b/chrome/browser/safe_browsing/download_protection/check_client_download_request.cc
index 3287c439..4570c7c 100644
--- a/chrome/browser/safe_browsing/download_protection/check_client_download_request.cc
+++ b/chrome/browser/safe_browsing/download_protection/check_client_download_request.cc
@@ -32,7 +32,6 @@
 #include "chrome/browser/safe_browsing/download_protection/download_protection_util.h"
 #include "chrome/common/safe_browsing/download_type_util.h"
 #include "components/download/public/common/download_danger_type.h"
-#include "components/policy/core/browser/url_util.h"
 #include "components/policy/core/common/policy_pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/content/common/file_type_policies.h"
diff --git a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
index b1e0700..1df821f0 100644
--- a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
+++ b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
@@ -33,7 +33,6 @@
 #include "chrome/common/pref_names.h"
 #include "components/download/public/common/download_item.h"
 #include "components/enterprise/common/proto/connectors.pb.h"
-#include "components/policy/core/browser/url_util.h"
 #include "components/policy/core/common/cloud/dm_token.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/core/common/features.h"
diff --git a/chrome/browser/sharing/sharing_ui_controller.cc b/chrome/browser/sharing/sharing_ui_controller.cc
index d28ca64..db4cdb0 100644
--- a/chrome/browser/sharing/sharing_ui_controller.cc
+++ b/chrome/browser/sharing/sharing_ui_controller.cc
@@ -67,7 +67,7 @@
     case SharingSendMessageResult::kSuccessful:
     case SharingSendMessageResult::kCancelled:
       NOTREACHED();
-      FALLTHROUGH;
+      [[fallthrough]];
 
     case SharingSendMessageResult::kPayloadTooLarge:
     case SharingSendMessageResult::kInternalError:
diff --git a/chrome/browser/ssl/security_state_tab_helper.cc b/chrome/browser/ssl/security_state_tab_helper.cc
index c9853a0..2530a10 100644
--- a/chrome/browser/ssl/security_state_tab_helper.cc
+++ b/chrome/browser/ssl/security_state_tab_helper.cc
@@ -216,7 +216,7 @@
               MALICIOUS_CONTENT_STATUS_SIGNED_IN_SYNC_PASSWORD_REUSE;
         }
 #endif
-        FALLTHROUGH;
+        [[fallthrough]];
       case safe_browsing::SB_THREAT_TYPE_SIGNED_IN_NON_SYNC_PASSWORD_REUSE:
 #if BUILDFLAG(FULL_SAFE_BROWSING)
         if (safe_browsing::ChromePasswordProtectionService::
@@ -226,7 +226,7 @@
               MALICIOUS_CONTENT_STATUS_SIGNED_IN_NON_SYNC_PASSWORD_REUSE;
         }
 #endif
-        FALLTHROUGH;
+        [[fallthrough]];
       case safe_browsing::SB_THREAT_TYPE_ENTERPRISE_PASSWORD_REUSE:
 #if BUILDFLAG(FULL_SAFE_BROWSING)
         if (safe_browsing::ChromePasswordProtectionService::
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc b/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc
index 1f80979..a97aaf1 100644
--- a/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc
+++ b/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc
@@ -80,7 +80,7 @@
           // Should never happen, only used for requests from Webview
           NOTREACHED();
       }
-      FALLTHROUGH;
+      [[fallthrough]];
     case SupervisedUserURLFilter::INVALID:
       NOTREACHED();
   }
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc
index 5a3b3ae..9453b77 100644
--- a/chrome/browser/supervised_user/supervised_user_service.cc
+++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -42,7 +42,6 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/policy/core/browser/url_util.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/supervised_user/supervised_user_url_filter.cc b/chrome/browser/supervised_user/supervised_user_url_filter.cc
index 4ce1f1c..2d5faae 100644
--- a/chrome/browser/supervised_user/supervised_user_url_filter.cc
+++ b/chrome/browser/supervised_user/supervised_user_url_filter.cc
@@ -21,7 +21,7 @@
 #include "chrome/browser/supervised_user/supervised_user_denylist.h"
 #include "chrome/browser/supervised_user/supervised_user_service.h"
 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
-#include "components/policy/core/browser/url_util.h"
+#include "components/url_matcher/url_util.h"
 #include "components/variations/service/variations_service.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/buildflags/buildflags.h"
@@ -288,7 +288,7 @@
     supervised_user_error_page::FilteringBehaviorReason* reason) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  GURL effective_url = policy::url_util::GetEmbeddedURL(url);
+  GURL effective_url = url_matcher::util::GetEmbeddedURL(url);
   if (!effective_url.is_valid())
     effective_url = url;
 
@@ -302,7 +302,7 @@
   // Allow webstore crx downloads. This applies to both extension installation
   // and updates.
   if (extension_urls::GetWebstoreUpdateUrl() ==
-      policy::url_util::Normalize(effective_url)) {
+      url_matcher::util::Normalize(effective_url)) {
     return ALLOW;
   }
 
@@ -356,7 +356,7 @@
 #if BUILDFLAG(ENABLE_EXTENSIONS)
   // The user requested the Chrome Webstore, and it
   // hasn't specifically been blocked above, so allow.
-  if (policy::url_util::Normalize(effective_url).host() ==
+  if (url_matcher::util::Normalize(effective_url).host() ==
       extension_urls::GetWebstoreLaunchURL().host()) {
     return ALLOW;
   }
@@ -379,7 +379,7 @@
   bool conflict = false;
 
   // Check manual overrides for the exact URL.
-  auto url_it = url_map_.find(policy::url_util::Normalize(url));
+  auto url_it = url_map_.find(url_matcher::util::Normalize(url));
   if (url_it != url_map_.end()) {
     conflict =
         SetFilteringBehaviorResult(url_it->second ? ALLOW : BLOCK, &result);
@@ -632,7 +632,7 @@
   }
 
   return async_url_checker_->CheckURL(
-      policy::url_util::Normalize(url),
+      url_matcher::util::Normalize(url),
       base::BindOnce(&SupervisedUserURLFilter::CheckCallback,
                      base::Unretained(this), std::move(callback)));
 }
diff --git a/chrome/browser/supervised_user/web_approvals_manager.cc b/chrome/browser/supervised_user/web_approvals_manager.cc
index 2be040fc..3292ce3 100644
--- a/chrome/browser/supervised_user/web_approvals_manager.cc
+++ b/chrome/browser/supervised_user/web_approvals_manager.cc
@@ -9,7 +9,7 @@
 #include "base/logging.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/supervised_user/permission_request_creator.h"
-#include "components/policy/core/browser/url_util.h"
+#include "components/url_matcher/url_util.h"
 #include "url/gurl.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -50,12 +50,12 @@
 void WebApprovalsManager::RequestRemoteApproval(
     const GURL& url,
     ApprovalRequestInitiatedCallback callback) {
-  GURL effective_url = policy::url_util::GetEmbeddedURL(url);
+  GURL effective_url = url_matcher::util::GetEmbeddedURL(url);
   if (!effective_url.is_valid())
     effective_url = url;
   AddRemoteApprovalRequestInternal(
       base::BindRepeating(CreateURLAccessRequest,
-                          policy::url_util::Normalize(effective_url)),
+                          url_matcher::util::Normalize(effective_url)),
       std::move(callback), 0);
 }
 
diff --git a/chrome/browser/themes/theme_helper.cc b/chrome/browser/themes/theme_helper.cc
index ad332d6..6b9b927 100644
--- a/chrome/browser/themes/theme_helper.cc
+++ b/chrome/browser/themes/theme_helper.cc
@@ -741,7 +741,7 @@
     case TP::COLOR_OMNIBOX_SELECTED_KEYWORD:
       if (dark)
         return {{gfx::kGoogleGrey100, false}};
-      FALLTHROUGH;
+      [[fallthrough]];
     case TP::COLOR_OMNIBOX_RESULTS_URL:
       return url_color(results_bg_hovered_color());
     case TP::COLOR_OMNIBOX_RESULTS_URL_SELECTED:
diff --git a/chrome/browser/themes/theme_helper_win.cc b/chrome/browser/themes/theme_helper_win.cc
index f90085d1..ca4503e5 100644
--- a/chrome/browser/themes/theme_helper_win.cc
+++ b/chrome/browser/themes/theme_helper_win.cc
@@ -88,7 +88,7 @@
       if (!base::FeatureList::IsEnabled(
               views::features::kEnablePlatformHighContrastInkDrop))
         return false;
-      FALLTHROUGH;
+      [[fallthrough]];
     case ThemeProperties::COLOR_OMNIBOX_RESULTS_BG_SELECTED:
     case ThemeProperties::COLOR_OMNIBOX_RESULTS_BG_HOVERED:
       system_theme_color = ui::NativeTheme::SystemThemeColor::kHighlight;
@@ -102,7 +102,7 @@
         return GetPlatformHighContrastColor(
             ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON, color);
       }
-      FALLTHROUGH;
+      [[fallthrough]];
     case ThemeProperties::COLOR_TAB_FOREGROUND_ACTIVE_FRAME_ACTIVE:
     case ThemeProperties::COLOR_TAB_FOREGROUND_ACTIVE_FRAME_INACTIVE:
     case ThemeProperties::COLOR_OMNIBOX_RESULTS_TEXT_SELECTED:
diff --git a/chrome/browser/translate/translate_model_service_browsertest.cc b/chrome/browser/translate/translate_model_service_browsertest.cc
index 7df7efa..045a25a 100644
--- a/chrome/browser/translate/translate_model_service_browsertest.cc
+++ b/chrome/browser/translate/translate_model_service_browsertest.cc
@@ -23,6 +23,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/metrics/content/subprocess_metrics_provider.h"
+#include "components/optimization_guide/core/model_util.h"
 #include "components/optimization_guide/core/optimization_guide_features.h"
 #include "components/optimization_guide/core/optimization_guide_test_util.h"
 #include "components/optimization_guide/core/test_model_info_builder.h"
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 41dd23e..58f3ee04 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -4335,6 +4335,8 @@
       "views/overlay/constants.h",
       "views/overlay/hang_up_button.cc",
       "views/overlay/hang_up_button.h",
+      "views/overlay/overlay_window_image_button.cc",
+      "views/overlay/overlay_window_image_button.h",
       "views/overlay/overlay_window_views.cc",
       "views/overlay/overlay_window_views.h",
       "views/overlay/playback_image_button.cc",
diff --git a/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/WebContentsDarkModeMessageController.java b/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/WebContentsDarkModeMessageController.java
index bdad4871..e92bc2b2 100644
--- a/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/WebContentsDarkModeMessageController.java
+++ b/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/WebContentsDarkModeMessageController.java
@@ -12,6 +12,7 @@
 import android.view.View;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.appcompat.content.res.AppCompatResources;
 
@@ -29,6 +30,7 @@
 import org.chromium.components.messages.MessageBannerProperties;
 import org.chromium.components.messages.MessageDispatcher;
 import org.chromium.components.messages.MessageIdentifier;
+import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.modaldialog.DialogDismissalCause;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType;
@@ -95,19 +97,29 @@
      *
      * @param activity Activity for resources and to launch SettingsActivity from.
      * @param profile Profile associated with current tab.
+     * @param webContents WebContents associated with current tab.
      * @param settingsLauncher Launcher into theme settings.
      * @param messageDispatcher Dispatcher for the message we are creating.
      */
     public static void attemptToSendMessage(Activity activity, Profile profile,
-            SettingsLauncher settingsLauncher, MessageDispatcher messageDispatcher) {
+            @Nullable WebContents webContents, SettingsLauncher settingsLauncher,
+            MessageDispatcher messageDispatcher) {
         if (!shouldSendMessage(profile, activity)) return;
 
-        // Set the properties (icon, text, etc.) for the message.
+        // Create and send message based on arm.
+        if (ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
+                    ChromeFeatureList.DARKEN_WEBSITES_CHECKBOX_IN_THEMES_SETTING, OPT_OUT_PARAM,
+                    true)) {
+            sendOptOutMessage(activity, profile, settingsLauncher, messageDispatcher, null);
+        } else {
+            sendOptInMessage(activity, profile, webContents, settingsLauncher, messageDispatcher);
+        }
+    }
+
+    private static void sendOptOutMessage(Activity activity, Profile profile,
+            SettingsLauncher settingsLauncher, MessageDispatcher messageDispatcher,
+            @Nullable String description) {
         Resources resources = activity.getResources();
-        boolean optOut = ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
-                ChromeFeatureList.DARKEN_WEBSITES_CHECKBOX_IN_THEMES_SETTING, OPT_OUT_PARAM, true);
-        String messageTitle = optOut ? resources.getString(R.string.auto_dark_message_title)
-                                     : resources.getString(R.string.auto_dark_message_opt_in_title);
         PropertyModel message =
                 new PropertyModel.Builder(MessageBannerProperties.ALL_KEYS)
                         .with(MessageBannerProperties.MESSAGE_IDENTIFIER,
@@ -116,31 +128,56 @@
                                 R.drawable.ic_brightness_medium_24dp)
                         .with(MessageBannerProperties.ICON_TINT_COLOR,
                                 MessageBannerProperties.TINT_NONE)
-                        .with(MessageBannerProperties.TITLE, messageTitle)
+                        .with(MessageBannerProperties.TITLE,
+                                resources.getString(R.string.auto_dark_message_title))
+                        .with(MessageBannerProperties.DESCRIPTION, description)
                         .with(MessageBannerProperties.PRIMARY_BUTTON_TEXT,
                                 resources.getString(R.string.auto_dark_message_button))
                         .with(MessageBannerProperties.ON_PRIMARY_ACTION,
-                                () -> { onPrimaryAction(activity, settingsLauncher); })
+                                () -> { onOptOutPrimaryAction(activity, settingsLauncher); })
                         .with(MessageBannerProperties.ON_DISMISSED,
-                                (dismissReason) -> { onMessageDismissed(profile, dismissReason); })
+                                (dismissReason) -> {
+                                    onOptOutMessageDismissed(profile, dismissReason);
+                                })
                         .build();
+        messageDispatcher.enqueueWindowScopedMessage(message, false);
+    }
 
-        if (!optOut) {
-            message.set(MessageBannerProperties.DESCRIPTION,
-                    resources.getString(R.string.auto_dark_message_opt_in_body));
-        }
-
-        // Enqueue the message so that it will appear on-screen.
+    private static void sendOptInMessage(Activity activity, Profile profile,
+            WebContents webContents, SettingsLauncher settingsLauncher,
+            MessageDispatcher messageDispatcher) {
+        Resources resources = activity.getResources();
+        PropertyModel message =
+                new PropertyModel.Builder(MessageBannerProperties.ALL_KEYS)
+                        .with(MessageBannerProperties.MESSAGE_IDENTIFIER,
+                                MessageIdentifier.AUTO_DARK_WEB_CONTENTS)
+                        .with(MessageBannerProperties.ICON_RESOURCE_ID,
+                                R.drawable.ic_brightness_medium_24dp)
+                        .with(MessageBannerProperties.ICON_TINT_COLOR,
+                                MessageBannerProperties.TINT_NONE)
+                        .with(MessageBannerProperties.TITLE,
+                                resources.getString(R.string.auto_dark_message_opt_in_title))
+                        .with(MessageBannerProperties.DESCRIPTION,
+                                resources.getString(R.string.auto_dark_message_opt_in_body))
+                        .with(MessageBannerProperties.PRIMARY_BUTTON_TEXT,
+                                resources.getString(R.string.auto_dark_message_opt_in_button))
+                        .with(MessageBannerProperties.ON_PRIMARY_ACTION,
+                                () -> { onOptInPrimaryAction(profile, webContents); })
+                        .with(MessageBannerProperties.ON_DISMISSED,
+                                (dismissReason) -> {
+                                    onOptInMessageDismissed(activity, profile, webContents,
+                                            settingsLauncher, messageDispatcher, dismissReason);
+                                })
+                        .build();
         messageDispatcher.enqueueWindowScopedMessage(message, false);
     }
 
     /**
-     * The primary action associated with the created message. In this case, the settings page is
-     * opened to show users where to change the auto-dark settings.
+     * The primary action associated with the created message for the opt-out arm. In this case, the
+     * settings page is opened to show users where to change the auto-dark settings.
      */
-    @VisibleForTesting
-    static void onPrimaryAction(Activity activity, SettingsLauncher settingsLauncher) {
-        // TODO(crbug.com/1277216): Update CTA for opt-in arm.
+    private static void onOptOutPrimaryAction(
+            Activity activity, SettingsLauncher settingsLauncher) {
         Bundle args = new Bundle();
         args.putInt(ThemeSettingsFragment.KEY_THEME_SETTINGS_ENTRY,
                 ThemeSettingsEntry.AUTO_DARK_MODE_MESSAGE);
@@ -148,14 +185,41 @@
     }
 
     /**
-     * Record that the message was dismissed.
+     * The primary action associated with the created message for the opt-in arm. In this case, the
+     * global setting is enabled.
      */
-    @VisibleForTesting
-    static void onMessageDismissed(Profile profile, @DismissReason int dismissReason) {
+    private static void onOptInPrimaryAction(Profile profile, WebContents webContents) {
+        WebContentsDarkModeController.setGlobalUserSettings(profile, true);
+        if (webContents != null) {
+            webContents.notifyRendererPreferenceUpdate();
+        }
+    }
+
+    /**
+     * Record that the opt-out message was dismissed.
+     */
+    private static void onOptOutMessageDismissed(
+            Profile profile, @DismissReason int dismissReason) {
         Tracker tracker = TrackerFactory.getTrackerForProfile(profile);
         tracker.dismissed(FeatureConstants.AUTO_DARK_USER_EDUCATION_MESSAGE_FEATURE);
     }
 
+    /**
+     * Record that the opt-in message was dismissed. If the CTA was pressed, show the opt-out
+     * message.
+     */
+    private static void onOptInMessageDismissed(Activity activity, Profile profile,
+            WebContents webContents, SettingsLauncher settingsLauncher,
+            MessageDispatcher messageDispatcher, @DismissReason int dismissReason) {
+        Tracker tracker = TrackerFactory.getTrackerForProfile(profile);
+        tracker.dismissed(FeatureConstants.AUTO_DARK_USER_EDUCATION_MESSAGE_OPT_IN_FEATURE);
+
+        if (dismissReason == DismissReason.PRIMARY_ACTION) {
+            sendOptOutMessage(activity, profile, settingsLauncher, messageDispatcher,
+                    activity.getResources().getString(R.string.auto_dark_message_opt_in_body));
+        }
+    }
+
     // User feedback dialog implementation.
 
     /**
diff --git a/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/WebContentsDarkModeMessageControllerUnitTest.java b/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/WebContentsDarkModeMessageControllerUnitTest.java
index 5320114..539d5617 100644
--- a/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/WebContentsDarkModeMessageControllerUnitTest.java
+++ b/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/WebContentsDarkModeMessageControllerUnitTest.java
@@ -32,6 +32,7 @@
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 
+import org.chromium.base.Callback;
 import org.chromium.base.FeatureList;
 import org.chromium.base.FeatureList.TestValues;
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -98,8 +99,14 @@
 
         @Override
         public void dismissMessage(PropertyModel messageProperties, int dismissReason) {
-            mShownMessageModel.get(MessageBannerProperties.ON_DISMISSED).onResult(dismissReason);
+            Callback<Integer> callback =
+                    mShownMessageModel.get(MessageBannerProperties.ON_DISMISSED);
             mShownMessageModel = null;
+            callback.onResult(dismissReason);
+        }
+
+        private void clickButton() {
+            mShownMessageModel.get(MessageBannerProperties.ON_PRIMARY_ACTION).run();
         }
     }
 
@@ -132,6 +139,12 @@
         static boolean sIsFeatureEnabled;
 
         @Implementation
+        public static void setGlobalUserSettings(
+                BrowserContextHandle browserContextHandle, boolean enabled) {
+            sIsFeatureEnabled = enabled;
+        }
+
+        @Implementation
         public static boolean isFeatureEnabled(
                 Context context, BrowserContextHandle browserContextHandle) {
             return sIsFeatureEnabled;
@@ -148,6 +161,8 @@
     @Mock
     Profile mMockProfile;
     @Mock
+    WebContents mMockWebContents;
+    @Mock
     SettingsLauncher mMockSettingsLauncher;
     @Mock
     HelpAndFeedbackLauncher mMockFeedbackLauncher;
@@ -189,6 +204,7 @@
     }
 
     private void setOptOut(boolean optOut) {
+        ShadowWebContentsDarkModeController.sIsFeatureEnabled = optOut;
         if (!optOut) {
             FeatureList.TestValues testValues = new TestValues();
             testValues.addFieldTrialParamOverride(
@@ -198,120 +214,156 @@
         }
     }
 
-    private void doTestSendMessage_Sent(boolean optOut, boolean clicked) {
-        reset(mMockSettingsLauncher, mMockTracker);
-
-        String enabledFeature = optOut ? USER_ED_FEATURE : USER_ED_OPT_IN_FEATURE;
-        String messageTitle = optOut ? TEST_OPT_OUT_TITLE : TEST_OPT_IN_TITLE;
-
+    private void doTestSendMessage_OptOut_Sent(boolean clicked) {
         // Set state based on opt-in/out arm. Since message is sent, shouldTriggerHelpUI is true.
-        setOptOut(optOut);
-        ShadowWebContentsDarkModeController.sIsFeatureEnabled = optOut;
+        reset(mMockWebContents, mMockSettingsLauncher, mMockTracker);
+        setOptOut(true);
+        String enabledFeature = USER_ED_FEATURE;
+        String messageTitle = TEST_OPT_OUT_TITLE;
         when(mMockTracker.shouldTriggerHelpUI(eq(enabledFeature))).thenReturn(true);
 
         // Successfully send message.
-        WebContentsDarkModeMessageController.attemptToSendMessage(
-                mMockActivity, mMockProfile, mMockSettingsLauncher, mMessageDispatcher);
+        WebContentsDarkModeMessageController.attemptToSendMessage(mMockActivity, mMockProfile,
+                mMockWebContents, mMockSettingsLauncher, mMessageDispatcher);
         verify(mMockTracker, times(1)).shouldTriggerHelpUI(enabledFeature);
-        Assert.assertNotNull(
-                "Message model should be non-null.", mMessageDispatcher.mShownMessageModel);
+        Assert.assertNotNull("Message should be non-null.", mMessageDispatcher.mShownMessageModel);
         Assert.assertEquals("Message has incorrect title.",
                 mMessageDispatcher.mShownMessageModel.get(MessageBannerProperties.TITLE),
                 messageTitle);
 
         // Message maybe clicked.
-        if (clicked) {
-            WebContentsDarkModeMessageController.onPrimaryAction(
-                    mMockActivity, mMockSettingsLauncher);
-        }
-        verify(mMockSettingsLauncher, times(clicked ? 1 : 0))
-                .launchSettingsActivity(
-                        eq(mMockActivity), eq(ThemeSettingsFragment.class), notNull());
+        if (clicked) mMessageDispatcher.clickButton();
+        verifyLaunchSettings(clicked ? 1 : 0);
 
         // Message dismissed and marked as shown as a result.
         mMessageDispatcher.dismissMessage(null, DismissReason.UNKNOWN);
-        Assert.assertNull("Shown message model should be null, since we dismiss the message.",
+        Assert.assertNull("Shown message should be null, since we dismiss the message.",
                 mMessageDispatcher.mShownMessageModel);
-        verify(mMockTracker, times(1)).dismissed(eq(USER_ED_FEATURE));
+        verify(mMockTracker, times(1)).dismissed(eq(enabledFeature));
+    }
+
+    private void doTestSendMessage_OptIn_Sent(boolean clicked) {
+        // Set state based on opt-in/out arm. Since message is sent, shouldTriggerHelpUI is true.
+        reset(mMockWebContents, mMockSettingsLauncher, mMockTracker);
+        setOptOut(false);
+        String enabledFeature = USER_ED_OPT_IN_FEATURE;
+        String messageTitle = TEST_OPT_IN_TITLE;
+        when(mMockTracker.shouldTriggerHelpUI(eq(enabledFeature))).thenReturn(true);
+
+        // Successfully send message.
+        WebContentsDarkModeMessageController.attemptToSendMessage(mMockActivity, mMockProfile,
+                mMockWebContents, mMockSettingsLauncher, mMessageDispatcher);
+        verify(mMockTracker, times(1)).shouldTriggerHelpUI(enabledFeature);
+        Assert.assertNotNull("Message should be non-null.", mMessageDispatcher.mShownMessageModel);
+        Assert.assertEquals("Message has incorrect title.",
+                mMessageDispatcher.mShownMessageModel.get(MessageBannerProperties.TITLE),
+                messageTitle);
+
+        // Message maybe clicked.
+        if (clicked) mMessageDispatcher.clickButton();
+        Assert.assertEquals("Feature should be enabled if we click the opt-in action.",
+                ShadowWebContentsDarkModeController.sIsFeatureEnabled, clicked);
+        verify(mMockWebContents, times(clicked ? 1 : 0)).notifyRendererPreferenceUpdate();
+
+        // Message dismissed and marked as shown as a result.
+        if (clicked) {
+            mMessageDispatcher.dismissMessage(null, DismissReason.PRIMARY_ACTION);
+            Assert.assertNotNull("Shown message should be non-null after clicking opt-in action.",
+                    mMessageDispatcher.mShownMessageModel);
+        } else {
+            mMessageDispatcher.dismissMessage(null, DismissReason.UNKNOWN);
+            Assert.assertNull("Shown message should be null, since we dismiss the message.",
+                    mMessageDispatcher.mShownMessageModel);
+        }
+        verify(mMockTracker, times(1)).dismissed(eq(enabledFeature));
     }
 
     private void doTestSendMessage_NotSent(boolean optOut, boolean enabled, boolean shouldTrigger) {
-        String enabledFeature = optOut ? USER_ED_FEATURE : USER_ED_OPT_IN_FEATURE;
+        // Message will not send if the feature is enabled on the opt-in arm, the feature is
+        // disabled on the opt-out arm, or the feature engagement system requirements are not met.
+        Assert.assertFalse(
+                "Message would send under these params", optOut == enabled && shouldTrigger);
 
         // Set setting and feature engagement state.
         setOptOut(optOut);
         ShadowWebContentsDarkModeController.sIsFeatureEnabled = enabled;
+        String enabledFeature = optOut ? USER_ED_FEATURE : USER_ED_OPT_IN_FEATURE;
         when(mMockTracker.shouldTriggerHelpUI(eq(enabledFeature))).thenReturn(shouldTrigger);
 
         // Attempt to send message and fail.
-        WebContentsDarkModeMessageController.attemptToSendMessage(
-                mMockActivity, mMockProfile, mMockSettingsLauncher, mMessageDispatcher);
-        if (optOut != enabled) {
-            // Fails because setting state doesn't match.
-            verify(mMockTracker, never()).shouldTriggerHelpUI(eq(enabledFeature));
-        } else {
-            // Fails because feature engagement conditions not met.
-            verify(mMockTracker, times(1)).shouldTriggerHelpUI(eq(enabledFeature));
-        }
-        Assert.assertNull("Shown message model should be null, since we don't show the message.",
+        WebContentsDarkModeMessageController.attemptToSendMessage(mMockActivity, mMockProfile,
+                mMockWebContents, mMockSettingsLauncher, mMessageDispatcher);
+        Assert.assertNull("Shown message should be null, since we don't show the message.",
                 mMessageDispatcher.mShownMessageModel);
+        verify(mMockTracker, times(optOut == enabled ? 1 : 0))
+                .shouldTriggerHelpUI(eq(enabledFeature));
 
         // Message not shown, so action not run.
-        verify(mMockSettingsLauncher, never())
-                .launchSettingsActivity(
-                        eq(mMockActivity), eq(ThemeSettingsFragment.class), notNull());
+        verifyLaunchSettings(0);
 
         // Message not marked as shown.
         verify(mMockTracker, never()).dismissed(eq(USER_ED_FEATURE));
     }
 
-    private void doTestSendMessage(boolean optOut, boolean enabled, boolean shouldTrigger) {
-        if (optOut == enabled && shouldTrigger) {
-            // Message should send.
-            doTestSendMessage_Sent(optOut, /* clicked */ true);
-            doTestSendMessage_Sent(optOut, /* clicked */ false);
-        } else {
-            // Message should not send.
-            doTestSendMessage_NotSent(optOut, enabled, shouldTrigger);
-        }
+    private void verifyLaunchSettings(int numTimes) {
+        verify(mMockSettingsLauncher, times(numTimes))
+                .launchSettingsActivity(
+                        eq(mMockActivity), eq(ThemeSettingsFragment.class), notNull());
     }
 
     // Message sent tests.
 
     @Test
-    public void testSendMessage_OptOut_Sent() {
-        doTestSendMessage(/* optOut */ true, /* enabled */ true, /* shouldTrigger*/ true);
+    public void testSendMessage_OptOut_Sent_Clicked() {
+        doTestSendMessage_OptOut_Sent(/* clicked */ true);
     }
 
     @Test
-    public void testSendMessage_OptIn_Sent() {
-        doTestSendMessage(/* optOut */ false, /* enabled */ false, /* shouldTrigger*/ true);
+    public void testSendMessage_OptOut_Sent_NotClicked() {
+        doTestSendMessage_OptOut_Sent(/* clicked */ false);
+    }
+
+    @Test
+    public void testSendMessage_OptIn_Sent_Clicked() {
+        doTestSendMessage_OptIn_Sent(/* clicked */ true);
+    }
+
+    @Test
+    public void testSendMessage_OptIn_Sent_NotClicked() {
+        doTestSendMessage_OptIn_Sent(/* clicked */ false);
     }
 
     // Message not sent tests.
 
     @Test
-    public void testSendMessage_OptOut_Disabled() {
-        // shouldTrigger value is not used when optOut != enabled
-        doTestSendMessage(/* optOut */ true, /* enabled */ false, /* shouldTrigger*/ true);
-        doTestSendMessage(/* optOut */ true, /* enabled */ false, /* shouldTrigger*/ false);
+    public void testSendMessage_OptOut_NotSent_DisabledShouldTrigger() {
+        doTestSendMessage_NotSent(/* optOut */ true, /* enabled */ false, /* shouldTrigger*/ true);
     }
 
     @Test
-    public void testSendMessage_OptOut_ShouldNotTrigger() {
-        doTestSendMessage(/* optOut */ true, /* enabled */ true, /* shouldTrigger*/ false);
+    public void testSendMessage_OptOut_NotSent_DisabledShouldNotTrigger() {
+        doTestSendMessage_NotSent(/* optOut */ true, /* enabled */ false, /* shouldTrigger*/ false);
     }
 
     @Test
-    public void testSendMessage_OptIn_Enabled() {
-        // shouldTrigger value is not used when optOut != enabled
-        doTestSendMessage(/* optOut */ false, /* enabled */ true, /* shouldTrigger*/ true);
-        doTestSendMessage(/* optOut */ false, /* enabled */ true, /* shouldTrigger*/ false);
+    public void testSendMessage_OptOut_NotSent_EnabledShouldNotTrigger() {
+        doTestSendMessage_NotSent(/* optOut */ true, /* enabled */ true, /* shouldTrigger*/ false);
     }
 
     @Test
-    public void testSendMessage_OptIn_ShouldNotTrigger() {
-        doTestSendMessage(/* optOut */ false, /* enabled */ false, /* shouldTrigger*/ false);
+    public void testSendMessage_OptIn_NotSent_EnabledShouldTrigger() {
+        doTestSendMessage_NotSent(/* optOut */ false, /* enabled */ true, /* shouldTrigger*/ true);
+    }
+
+    @Test
+    public void testSendMessage_OptIn_NotSent_EnabledShouldNotTrigger() {
+        doTestSendMessage_NotSent(/* optOut */ false, /* enabled */ true, /* shouldTrigger*/ false);
+    }
+
+    @Test
+    public void testSendMessage_OptIn_NotSent_DisabledShouldNotTrigger() {
+        doTestSendMessage_NotSent(
+                /* optOut */ false, /* enabled */ false, /* shouldTrigger*/ false);
     }
 
     // Dialog tests.
@@ -377,8 +429,7 @@
         WebContentsDarkModeMessageController.attemptToShowDialog(mMockActivity, mMockProfile,
                 TEST_URL, mModalDialogManager, mMockSettingsLauncher, mMockFeedbackLauncher);
         mModalDialogManager.clickButton(ButtonType.POSITIVE);
-        verify(mMockSettingsLauncher, times(1))
-                .launchSettingsActivity(eq(mMockActivity), eq(ThemeSettingsFragment.class), any());
+        verifyLaunchSettings(1);
 
         // Verify dismissal.
         Assert.assertNull("Shown dialog model should be null after clicking the positive button.",
@@ -417,7 +468,6 @@
         AutoDarkClickableSpan clickableSpan =
                 new AutoDarkClickableSpan(mMockActivity, mMockSettingsLauncher);
         clickableSpan.onClick(null);
-        verify(mMockSettingsLauncher, times(1))
-                .launchSettingsActivity(eq(mMockActivity), eq(ThemeSettingsFragment.class), any());
+        verifyLaunchSettings(1);
     }
 }
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index 14cef7c..aa971a10 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -5429,6 +5429,9 @@
       <message name="IDS_AUTO_DARK_MESSAGE_BUTTON" desc="The label for the button to enter theme settings.">
         Open settings
       </message>
+      <message name="IDS_AUTO_DARK_MESSAGE_OPT_IN_BUTTON" desc="The label for the button to enable the auto dark feature.">
+        Turn on
+      </message>
       <message name="IDS_AUTO_DARK_DIALOG_TITLE" desc="Title of dialog that asks the user to give feedback on auto dark theming.">
         Share feedback on dark theme for sites?
       </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_AUTO_DARK_MESSAGE_OPT_IN_BUTTON.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_AUTO_DARK_MESSAGE_OPT_IN_BUTTON.png.sha1
new file mode 100644
index 0000000..b9e26ebf
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_AUTO_DARK_MESSAGE_OPT_IN_BUTTON.png.sha1
@@ -0,0 +1 @@
+7ec477b699f2015c2fca1d25ce573919bcc58ed8
\ No newline at end of file
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java
index c8024bbb1..2f941cd 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java
@@ -19,6 +19,7 @@
 import android.view.ViewStub;
 import android.widget.ImageButton;
 
+import androidx.annotation.ColorRes;
 import androidx.annotation.VisibleForTesting;
 import androidx.appcompat.content.res.AppCompatResources;
 import androidx.core.view.ViewCompat;
@@ -459,9 +460,10 @@
     void updateBookmarkButton(boolean isBookmarked, boolean editingAllowed) {
         if (isBookmarked) {
             mBookmarkButton.setImageResource(R.drawable.btn_star_filled);
-            ApiCompatibilityUtils.setImageTintList(mBookmarkButton,
-                    AppCompatResources.getColorStateList(
-                            getContext(), R.color.default_icon_color_accent1_tint_list));
+            final @ColorRes int tint = isIncognito() ? R.color.default_icon_color_blue_light
+                                                     : R.color.default_icon_color_accent1_tint_list;
+            ApiCompatibilityUtils.setImageTintList(
+                    mBookmarkButton, AppCompatResources.getColorStateList(getContext(), tint));
             mBookmarkButton.setContentDescription(getContext().getString(R.string.edit_bookmark));
         } else {
             mBookmarkButton.setImageResource(R.drawable.btn_star);
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_event_logger.cc b/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_event_logger.cc
index 8840f5617..226d59e6 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_event_logger.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_event_logger.cc
@@ -223,10 +223,8 @@
 
   PrefService* pref_service = profile->GetPrefs();
   if (pref_service) {
-    arc_apps_ = &base::Value::AsDictionaryValue(
-        *pref_service->GetDictionary(arc::prefs::kArcApps));
-    arc_packages_ = &base::Value::AsDictionaryValue(
-        *pref_service->GetDictionary(arc::prefs::kArcPackages));
+    arc_apps_ = pref_service->GetDictionary(arc::prefs::kArcApps);
+    arc_packages_ = pref_service->GetDictionary(arc::prefs::kArcPackages);
   }
 }
 
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_event_logger.h b/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_event_logger.h
index 4afc040..d9300ee 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_event_logger.h
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_event_logger.h
@@ -86,9 +86,9 @@
   void EnforceLoggingPolicy();
 
   // The arc apps installed on the device.
-  const base::DictionaryValue* arc_apps_ = nullptr;
+  const base::Value* arc_apps_ = nullptr;
   // The arc packages installed on the device.
-  const base::DictionaryValue* arc_packages_ = nullptr;
+  const base::Value* arc_packages_ = nullptr;
   // The Chrome extension registry.
   extensions::ExtensionRegistry* registry_ = nullptr;
 
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc
index 33eff8b..0bbbb233 100644
--- a/chrome/browser/ui/browser_command_controller.cc
+++ b/chrome/browser/ui/browser_command_controller.cc
@@ -399,7 +399,7 @@
       break;
     case IDC_RELOAD_CLEARING_CACHE:
       ClearCache(browser_);
-      FALLTHROUGH;
+      [[fallthrough]];
     case IDC_RELOAD_BYPASSING_CACHE:
       ReloadBypassingCache(browser_, disposition);
       break;
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc
index 5cbc53e..8c06522f 100644
--- a/chrome/browser/ui/browser_commands.cc
+++ b/chrome/browser/ui/browser_commands.cc
@@ -185,7 +185,7 @@
   switch (result) {
     default:
       NOTREACHED();
-      FALLTHROUGH;
+      [[fallthrough]];
     case ShowTranslateBubbleResult::SUCCESS:
       return translate::TranslateBubbleUiEvent::BUBBLE_SHOWN;
     case ShowTranslateBubbleResult::BROWSER_WINDOW_NOT_VALID:
diff --git a/chrome/browser/ui/browser_navigator.cc b/chrome/browser/ui/browser_navigator.cc
index 7086ea8..7cdef5f1 100644
--- a/chrome/browser/ui/browser_navigator.cc
+++ b/chrome/browser/ui/browser_navigator.cc
@@ -188,7 +188,7 @@
         return index;
     }
 #endif
-      FALLTHROUGH;
+      [[fallthrough]];
     case WindowOpenDisposition::CURRENT_TAB:
       if (params.browser)
         return {params.browser, -1};
@@ -212,7 +212,7 @@
           return index;
       }
     }
-      FALLTHROUGH;
+      [[fallthrough]];
     case WindowOpenDisposition::NEW_FOREGROUND_TAB:
     case WindowOpenDisposition::NEW_BACKGROUND_TAB:
       // See if we can open the tab in the window this navigator is bound to.
@@ -305,7 +305,7 @@
       // automatically.
       if (params->window_action == NavigateParams::NO_ACTION)
         params->window_action = NavigateParams::SHOW_WINDOW;
-      FALLTHROUGH;
+      [[fallthrough]];
     }
     case WindowOpenDisposition::NEW_FOREGROUND_TAB:
     case WindowOpenDisposition::SINGLETON_TAB:
diff --git a/chrome/browser/ui/media_router/media_router_file_dialog.cc b/chrome/browser/ui/media_router/media_router_file_dialog.cc
index 3d3b9b1..9a7da21 100644
--- a/chrome/browser/ui/media_router/media_router_file_dialog.cc
+++ b/chrome/browser/ui/media_router/media_router_file_dialog.cc
@@ -258,7 +258,7 @@
       // Create issue shouldn't be called with FILE_OK, but to ensure things
       // compile, fall through sets |issue_title| to the generic error.
       NOTREACHED();
-      FALLTHROUGH;
+      [[fallthrough]];
     case MediaRouterFileDialog::UNKNOWN_FAILURE:
       issue_title = l10n_util::GetStringUTF8(
           IDS_MEDIA_ROUTER_ISSUE_FILE_CAST_GENERIC_ERROR);
diff --git a/chrome/browser/ui/sad_tab.cc b/chrome/browser/ui/sad_tab.cc
index 41af712..f480697 100644
--- a/chrome/browser/ui/sad_tab.cc
+++ b/chrome/browser/ui/sad_tab.cc
@@ -220,7 +220,7 @@
 #if defined(OS_CHROMEOS)
     case SAD_TAB_KIND_KILLED_BY_OOM:
       UMA_SAD_TAB_COUNTER("Tabs.SadTab.KillDisplayed.OOM");
-      FALLTHROUGH;
+      [[fallthrough]];
 #endif
     case SAD_TAB_KIND_KILLED:
       UMA_SAD_TAB_COUNTER("Tabs.SadTab.KillDisplayed");
@@ -288,7 +288,7 @@
         memory::OomMemoryDetails::Log("Tab OOM-Killed Memory details: " + spec +
                                       ", ");
       }
-      FALLTHROUGH;
+      [[fallthrough]];
 #endif
     case SAD_TAB_KIND_KILLED:
       UMA_SAD_TAB_COUNTER("Tabs.SadTab.KillCreated");
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
index 568fb57a..59a2b95 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -467,7 +467,8 @@
   TabStripModel* tab_strip = new_browser->tab_strip_model();
   ASSERT_EQ(static_cast<int>(expected_urls.size()), tab_strip->count());
   for (size_t i = 0; i < expected_urls.size(); i++)
-    EXPECT_EQ(expected_urls[i], tab_strip->GetWebContentsAt(i)->GetURL());
+    EXPECT_EQ(expected_urls[i],
+              tab_strip->GetWebContentsAt(i)->GetVisibleURL());
 
   // The two test_server tabs, despite having the same site, should be in
   // different SiteInstances.
@@ -503,8 +504,9 @@
   // The new browser should have exactly one tab (not the startup URLs).
   TabStripModel* tab_strip = new_browser->tab_strip_model();
   ASSERT_EQ(1, tab_strip->count());
-  EXPECT_EQ(chrome::kChromeUINewTabURL,
-            tab_strip->GetWebContentsAt(0)->GetURL().possibly_invalid_spec());
+  EXPECT_EQ(
+      chrome::kChromeUINewTabURL,
+      tab_strip->GetWebContentsAt(0)->GetVisibleURL().possibly_invalid_spec());
 }
 
 IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTest, OpenAppUrlShortcut) {
@@ -693,7 +695,7 @@
     EXPECT_FALSE(browser()->is_type_app());
     EXPECT_TRUE(browser()->is_type_normal());
     EXPECT_EQ(GURL(url::kAboutBlankURL),
-              tab_strip->GetWebContentsAt(0)->GetURL());
+              tab_strip->GetWebContentsAt(0)->GetLastCommittedURL());
     // Should have opened the chrome://apps unsupported app flow in 2nd window.
     Browser* other_browser = FindOneOtherBrowser(browser());
     ASSERT_TRUE(other_browser);
@@ -702,7 +704,7 @@
     EXPECT_FALSE(other_browser->is_type_app());
     EXPECT_TRUE(other_browser->is_type_normal());
     EXPECT_EQ(GURL(chrome::kChromeUIAppsURL),
-              other_tab_strip->GetWebContentsAt(0)->GetURL());
+              other_tab_strip->GetWebContentsAt(0)->GetVisibleURL());
   }
 
   bool IsExpectedToAllowLaunch() {
@@ -1080,14 +1082,14 @@
 
   // The new browser should have only the desired URL for the profile.
   ASSERT_EQ(1, tab_strip->count());
-  EXPECT_EQ(urls1[0], tab_strip->GetWebContentsAt(0)->GetURL());
+  EXPECT_EQ(urls1[0], tab_strip->GetWebContentsAt(0)->GetVisibleURL());
 
   ASSERT_EQ(1u, chrome::GetBrowserCount(other_profile));
   new_browser = FindOneOtherBrowserForProfile(other_profile, nullptr);
   ASSERT_TRUE(new_browser);
   tab_strip = new_browser->tab_strip_model();
   ASSERT_EQ(1, tab_strip->count());
-  EXPECT_EQ(urls2[0], tab_strip->GetWebContentsAt(0)->GetURL());
+  EXPECT_EQ(urls2[0], tab_strip->GetWebContentsAt(0)->GetVisibleURL());
 }
 
 IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTest, PRE_UpdateWithTwoProfiles) {
@@ -1218,14 +1220,16 @@
   ASSERT_TRUE(new_browser);
   TabStripModel* tab_strip = new_browser->tab_strip_model();
   ASSERT_EQ(1, tab_strip->count());
-  EXPECT_EQ("/empty.html", tab_strip->GetWebContentsAt(0)->GetURL().path());
+  EXPECT_EQ("/empty.html",
+            tab_strip->GetWebContentsAt(0)->GetLastCommittedURL().path());
 
   ASSERT_EQ(1u, chrome::GetBrowserCount(profile2));
   new_browser = FindOneOtherBrowserForProfile(profile2, nullptr);
   ASSERT_TRUE(new_browser);
   tab_strip = new_browser->tab_strip_model();
   ASSERT_EQ(1, tab_strip->count());
-  EXPECT_EQ("/form.html", tab_strip->GetWebContentsAt(0)->GetURL().path());
+  EXPECT_EQ("/form.html",
+            tab_strip->GetWebContentsAt(0)->GetLastCommittedURL().path());
 }
 
 IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTest,
@@ -1319,7 +1323,7 @@
   // The new browser should have only the NTP.
   ASSERT_EQ(1, tab_strip->count());
   EXPECT_EQ(ntp_test_utils::GetFinalNtpUrl(new_browser->profile()),
-            tab_strip->GetWebContentsAt(0)->GetURL());
+            tab_strip->GetWebContentsAt(0)->GetVisibleURL());
 
   // profile_urls opened the urls.
   ASSERT_EQ(1u, chrome::GetBrowserCount(profile_urls));
@@ -1327,7 +1331,7 @@
   ASSERT_TRUE(new_browser);
   tab_strip = new_browser->tab_strip_model();
   ASSERT_EQ(1, tab_strip->count());
-  EXPECT_EQ(urls[0], tab_strip->GetWebContentsAt(0)->GetURL());
+  EXPECT_EQ(urls[0], tab_strip->GetWebContentsAt(0)->GetVisibleURL());
 
   // profile_last opened the last open pages.
   ASSERT_EQ(1u, chrome::GetBrowserCount(profile_last));
@@ -1335,7 +1339,8 @@
   ASSERT_TRUE(new_browser);
   tab_strip = new_browser->tab_strip_model();
   ASSERT_EQ(1, tab_strip->count());
-  EXPECT_EQ("/empty.html", tab_strip->GetWebContentsAt(0)->GetURL().path());
+  EXPECT_EQ("/empty.html",
+            tab_strip->GetWebContentsAt(0)->GetLastCommittedURL().path());
 
   // profile_home2 was not launched since it would've only opened the home page.
   ASSERT_EQ(0u, chrome::GetBrowserCount(profile_home2));
@@ -2161,13 +2166,15 @@
   new_browser = FindOneOtherBrowserForProfile(profile1, nullptr);
   ASSERT_TRUE(new_browser);
   TabStripModel* tab_strip = new_browser->tab_strip_model();
-  EXPECT_EQ("/title1.html", tab_strip->GetWebContentsAt(0)->GetURL().path());
+  EXPECT_EQ("/title1.html",
+            tab_strip->GetWebContentsAt(0)->GetLastCommittedURL().path());
 
   ASSERT_EQ(1u, chrome::GetBrowserCount(profile2));
   new_browser = FindOneOtherBrowserForProfile(profile2, nullptr);
   ASSERT_TRUE(new_browser);
   tab_strip = new_browser->tab_strip_model();
-  EXPECT_EQ("/title2.html", tab_strip->GetWebContentsAt(0)->GetURL().path());
+  EXPECT_EQ("/title2.html",
+            tab_strip->GetWebContentsAt(0)->GetLastCommittedURL().path());
 }
 
 #if !BUILDFLAG(IS_CHROMEOS_LACROS)
@@ -2341,7 +2348,8 @@
   EXPECT_EQ(new_browser->type(), Browser::Type::TYPE_NORMAL);
 
   TabStripModel* tab_strip = new_browser->tab_strip_model();
-  EXPECT_EQ("/title1.html", tab_strip->GetWebContentsAt(0)->GetURL().path());
+  EXPECT_EQ("/title1.html",
+            tab_strip->GetWebContentsAt(0)->GetLastCommittedURL().path());
 
   // Now get the app, it should just be the other browser from this profile.
   new_browser = FindOneOtherBrowserForProfile(profile1, new_browser);
@@ -3233,9 +3241,9 @@
   EXPECT_EQ(2, tab_strip->count());
 
   EXPECT_EQ("title1.html",
-            tab_strip->GetWebContentsAt(0)->GetURL().ExtractFileName());
+            tab_strip->GetWebContentsAt(0)->GetVisibleURL().ExtractFileName());
   EXPECT_EQ("title2.html",
-            tab_strip->GetWebContentsAt(1)->GetURL().ExtractFileName());
+            tab_strip->GetWebContentsAt(1)->GetVisibleURL().ExtractFileName());
 }
 
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING) && defined(OS_MAC)
@@ -3290,7 +3298,7 @@
   TabStripModel* tab_strip = new_browser->tab_strip_model();
   ASSERT_EQ(1, tab_strip->count());
   EXPECT_EQ("title1.html",
-            tab_strip->GetWebContentsAt(0)->GetURL().ExtractFileName());
+            tab_strip->GetWebContentsAt(0)->GetVisibleURL().ExtractFileName());
 }
 
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING) && defined(OS_MAC)
@@ -3336,7 +3344,7 @@
   TabStripModel* tab_strip = new_browser->tab_strip_model();
   ASSERT_EQ(1, tab_strip->count());
   EXPECT_EQ("title1.html",
-            tab_strip->GetWebContentsAt(0)->GetURL().ExtractFileName());
+            tab_strip->GetWebContentsAt(0)->GetVisibleURL().ExtractFileName());
 }
 
 IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorFirstRunTest, WelcomePages) {
@@ -3347,8 +3355,9 @@
   // (about:blank or new tab page will be shown instead)
   TabStripModel* tab_strip = browser()->tab_strip_model();
   ASSERT_EQ(1, tab_strip->count());
-  EXPECT_NE(chrome::kChromeUIWelcomeURL,
-            tab_strip->GetWebContentsAt(0)->GetURL().possibly_invalid_spec());
+  EXPECT_NE(chrome::kChromeUIWelcomeURL, tab_strip->GetWebContentsAt(0)
+                                             ->GetLastCommittedURL()
+                                             .possibly_invalid_spec());
 #endif
 
   ProfileManager* profile_manager = g_browser_process->profile_manager();
@@ -3377,7 +3386,7 @@
   ASSERT_EQ(1, tab_strip1->count());
   bool should_show_welcome = true;
   std::string new_tab_url1 =
-      tab_strip1->GetWebContentsAt(0)->GetURL().possibly_invalid_spec();
+      tab_strip1->GetWebContentsAt(0)->GetVisibleURL().possibly_invalid_spec();
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   // Welcome page should not be shown on Lacros.
   // (about:blank or new tab page will be shown instead)
@@ -3398,8 +3407,9 @@
 
   // Ensure that the new tab page appears on subsequent runs.
   ASSERT_EQ(1, tab_strip1->count());
-  EXPECT_EQ(chrome::kChromeUINewTabURL,
-            tab_strip1->GetWebContentsAt(0)->GetURL().possibly_invalid_spec());
+  EXPECT_EQ(
+      chrome::kChromeUINewTabURL,
+      tab_strip1->GetWebContentsAt(0)->GetVisibleURL().possibly_invalid_spec());
 }
 
 IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorFirstRunTest,
@@ -3449,8 +3459,9 @@
   // the policy is set.
   if (IsWindows10OrNewer()) {
     ASSERT_EQ(1, tab_strip->count());
-    EXPECT_EQ("title1.html",
-              tab_strip->GetWebContentsAt(0)->GetURL().ExtractFileName());
+    EXPECT_EQ(
+        "title1.html",
+        tab_strip->GetWebContentsAt(0)->GetVisibleURL().ExtractFileName());
 
     browser = CloseBrowserAndOpenNew(browser, profile1_ptr);
     ASSERT_TRUE(browser);
@@ -3461,7 +3472,7 @@
   // on first run on all other platforms.
   ASSERT_EQ(1, tab_strip->count());
   EXPECT_EQ("title1.html",
-            tab_strip->GetWebContentsAt(0)->GetURL().ExtractFileName());
+            tab_strip->GetWebContentsAt(0)->GetVisibleURL().ExtractFileName());
 
   browser = CloseBrowserAndOpenNew(browser, profile1_ptr);
   ASSERT_TRUE(browser);
@@ -3470,7 +3481,7 @@
   // Ensure that the policy page page appears on subsequent runs.
   ASSERT_EQ(1, tab_strip->count());
   EXPECT_EQ("title1.html",
-            tab_strip->GetWebContentsAt(0)->GetURL().ExtractFileName());
+            tab_strip->GetWebContentsAt(0)->GetVisibleURL().ExtractFileName());
 }
 
 #endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc b/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc
index 1eed870..b368ae7 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc
@@ -160,8 +160,10 @@
 
   TabStripModel* tab_strip = new_browser->tab_strip_model();
   ASSERT_EQ(static_cast<int>(expected_urls.size()), tab_strip->count());
-  for (size_t i = 0; i < expected_urls.size(); i++)
-    EXPECT_EQ(expected_urls[i], tab_strip->GetWebContentsAt(i)->GetURL());
+  for (size_t i = 0; i < expected_urls.size(); i++) {
+    EXPECT_EQ(expected_urls[i],
+              tab_strip->GetWebContentsAt(i)->GetVisibleURL());
+  }
 }
 
 class StartupBrowserCreatorTriggeredResetFirstRunTest
@@ -207,9 +209,9 @@
   ASSERT_EQ(2, tab_strip->count());
 
   EXPECT_EQ("title1.html",
-            tab_strip->GetWebContentsAt(0)->GetURL().ExtractFileName());
+            tab_strip->GetWebContentsAt(0)->GetVisibleURL().ExtractFileName());
   EXPECT_EQ("title2.html",
-            tab_strip->GetWebContentsAt(1)->GetURL().ExtractFileName());
+            tab_strip->GetWebContentsAt(1)->GetVisibleURL().ExtractFileName());
 }
 
 IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTriggeredResetTest,
@@ -284,5 +286,5 @@
   TabStripModel* other_tab_strip = other_profile_browser->tab_strip_model();
   ASSERT_LT(0, other_tab_strip->count());
   EXPECT_EQ(GetTriggeredResetSettingsURL(),
-            other_tab_strip->GetActiveWebContents()->GetURL());
+            other_tab_strip->GetActiveWebContents()->GetVisibleURL());
 }
diff --git a/chrome/browser/ui/startup/startup_browser_creator_welcome_back_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_welcome_back_browsertest.cc
index 73eeeeb8..bdf7096 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_welcome_back_browsertest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_welcome_back_browsertest.cc
@@ -88,7 +88,7 @@
   void ExpectUrlInBrowserAtPosition(const GURL& url, int tab_index) {
     Browser* browser = BrowserList::GetInstance()->get(0);
     TabStripModel* tab_strip = browser->tab_strip_model();
-    EXPECT_EQ(url, tab_strip->GetWebContentsAt(tab_index)->GetURL());
+    EXPECT_EQ(url, tab_strip->GetWebContentsAt(tab_index)->GetVisibleURL());
   }
 
   void TearDownOnMainThread() override {
diff --git a/chrome/browser/ui/startup/web_app_startup_utils.cc b/chrome/browser/ui/startup/web_app_startup_utils.cc
index 1293b7e0..7e8c5c1 100644
--- a/chrome/browser/ui/startup/web_app_startup_utils.cc
+++ b/chrome/browser/ui/startup/web_app_startup_utils.cc
@@ -358,7 +358,7 @@
       break;
     case apps::mojom::LaunchContainer::kLaunchContainerPanelDeprecated:
       NOTREACHED();
-      FALLTHROUGH;
+      [[fallthrough]];
     case apps::mojom::LaunchContainer::kLaunchContainerNone:
       DCHECK(!browser->is_type_app());
       mode = LaunchMode::kUnknownWebApp;
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_tab_list_unittest.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_tab_list_unittest.cc
index c8a8d495..f47029e8 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_tab_list_unittest.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_tab_list_unittest.cc
@@ -5,6 +5,8 @@
 #include "chrome/browser/ui/views/desktop_capture/desktop_media_tab_list.h"
 #include "base/memory/raw_ptr.h"
 #include "base/time/time.h"
+#include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/media/webrtc/desktop_media_list.h"
 #include "chrome/browser/media/webrtc/fake_desktop_media_list.h"
 #include "chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h"
@@ -154,7 +156,15 @@
   EXPECT_TRUE(preview_->GetImage().BackedBySameObjectAs(new_preview));
 }
 
-TEST_F(DesktopMediaTabListTest, IgnorePreviewUpdatesForUnselectedSource) {
+// crbug.com/1284150: flaky on Lacros
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#define MAYBE_IgnorePreviewUpdatesForUnselectedSource \
+  DISABLED_IgnorePreviewUpdatesForUnselectedSource
+#else
+#define MAYBE_IgnorePreviewUpdatesForUnselectedSource \
+  IgnorePreviewUpdatesForUnselectedSource
+#endif
+TEST_F(DesktopMediaTabListTest, MAYBE_IgnorePreviewUpdatesForUnselectedSource) {
   test_api_.PressMouseOnSourceAtIndex(0);
 
   // Let the tab list know that the non-selected source #1 has a new preview.
diff --git a/chrome/browser/ui/views/overlay/back_to_tab_image_button.cc b/chrome/browser/ui/views/overlay/back_to_tab_image_button.cc
index 3afa0d3..063cbf00 100644
--- a/chrome/browser/ui/views/overlay/back_to_tab_image_button.cc
+++ b/chrome/browser/ui/views/overlay/back_to_tab_image_button.cc
@@ -18,12 +18,8 @@
 
 }  // namespace
 
-namespace views {
-
 BackToTabImageButton::BackToTabImageButton(PressedCallback callback)
-    : ImageButton(std::move(callback)) {
-  SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
-  SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
+    : OverlayWindowImageButton(std::move(callback)) {
   SetImage(views::Button::STATE_NORMAL,
            gfx::CreateVectorIcon(views::kLaunchIcon, kBackToTabImageSize,
                                  kPipWindowIconColor));
@@ -33,10 +29,7 @@
       IDS_PICTURE_IN_PICTURE_BACK_TO_TAB_CONTROL_TEXT));
   SetAccessibleName(back_to_tab_button_label);
   SetTooltipText(back_to_tab_button_label);
-  SetInstallFocusRingOnFocus(true);
 }
 
-BEGIN_METADATA(BackToTabImageButton, views::ImageButton)
+BEGIN_METADATA(BackToTabImageButton, OverlayWindowImageButton)
 END_METADATA
-
-}  // namespace views
diff --git a/chrome/browser/ui/views/overlay/back_to_tab_image_button.h b/chrome/browser/ui/views/overlay/back_to_tab_image_button.h
index 1aed665..29384a4 100644
--- a/chrome/browser/ui/views/overlay/back_to_tab_image_button.h
+++ b/chrome/browser/ui/views/overlay/back_to_tab_image_button.h
@@ -5,14 +5,12 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_OVERLAY_BACK_TO_TAB_IMAGE_BUTTON_H_
 #define CHROME_BROWSER_UI_VIEWS_OVERLAY_BACK_TO_TAB_IMAGE_BUTTON_H_
 
+#include "chrome/browser/ui/views/overlay/overlay_window_image_button.h"
 #include "chrome/browser/ui/views/overlay/overlay_window_views.h"
 #include "ui/base/metadata/metadata_header_macros.h"
-#include "ui/views/controls/button/image_button.h"
-
-namespace views {
 
 // An image button representing a back-to-tab button.
-class BackToTabImageButton : public views::ImageButton {
+class BackToTabImageButton : public OverlayWindowImageButton {
  public:
   METADATA_HEADER(BackToTabImageButton);
 
@@ -22,6 +20,4 @@
   ~BackToTabImageButton() override = default;
 };
 
-}  // namespace views
-
 #endif  // CHROME_BROWSER_UI_VIEWS_OVERLAY_BACK_TO_TAB_IMAGE_BUTTON_H_
diff --git a/chrome/browser/ui/views/overlay/back_to_tab_label_button.cc b/chrome/browser/ui/views/overlay/back_to_tab_label_button.cc
index 701d212..648e199c 100644
--- a/chrome/browser/ui/views/overlay/back_to_tab_label_button.cc
+++ b/chrome/browser/ui/views/overlay/back_to_tab_label_button.cc
@@ -7,12 +7,14 @@
 #include "chrome/browser/ui/views/overlay/constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/cursor/cursor.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/background.h"
 #include "ui/views/border.h"
+#include "ui/views/native_cursor.h"
 #include "ui/views/vector_icons.h"
 
 namespace {
@@ -71,6 +73,10 @@
 
 BackToTabLabelButton::~BackToTabLabelButton() = default;
 
+gfx::NativeCursor BackToTabLabelButton::GetCursor(const ui::MouseEvent& event) {
+  return views::GetNativeHandCursor();
+}
+
 void BackToTabLabelButton::SetWindowSize(const gfx::Size& window_size) {
   if (window_size_.has_value() && window_size_.value() == window_size)
     return;
diff --git a/chrome/browser/ui/views/overlay/back_to_tab_label_button.h b/chrome/browser/ui/views/overlay/back_to_tab_label_button.h
index 79ec57f8..c1d41e0 100644
--- a/chrome/browser/ui/views/overlay/back_to_tab_label_button.h
+++ b/chrome/browser/ui/views/overlay/back_to_tab_label_button.h
@@ -19,6 +19,9 @@
   BackToTabLabelButton& operator=(const BackToTabLabelButton&) = delete;
   ~BackToTabLabelButton() override;
 
+  // views::View:
+  gfx::NativeCursor GetCursor(const ui::MouseEvent& event) override;
+
   // Updates the position of this button within the new bounds of the window.
   void SetWindowSize(const gfx::Size& window_size);
 
diff --git a/chrome/browser/ui/views/overlay/close_image_button.cc b/chrome/browser/ui/views/overlay/close_image_button.cc
index b40d96b..0c1fa867 100644
--- a/chrome/browser/ui/views/overlay/close_image_button.cc
+++ b/chrome/browser/ui/views/overlay/close_image_button.cc
@@ -20,12 +20,8 @@
 
 }  // namespace
 
-namespace views {
-
 CloseImageButton::CloseImageButton(PressedCallback callback)
-    : ImageButton(std::move(callback)) {
-  SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
-  SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
+    : OverlayWindowImageButton(std::move(callback)) {
   SetSize(gfx::Size(kCloseButtonSize, kCloseButtonSize));
   SetImage(views::Button::STATE_NORMAL,
            gfx::CreateVectorIcon(views::kIcCloseIcon, kCloseButtonSize,
@@ -36,7 +32,6 @@
       l10n_util::GetStringUTF16(IDS_PICTURE_IN_PICTURE_CLOSE_CONTROL_TEXT));
   SetAccessibleName(close_button_label);
   SetTooltipText(close_button_label);
-  SetInstallFocusRingOnFocus(true);
 }
 
 void CloseImageButton::SetPosition(
@@ -44,18 +39,16 @@
     OverlayWindowViews::WindowQuadrant quadrant) {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   if (quadrant == OverlayWindowViews::WindowQuadrant::kBottomLeft) {
-    ImageButton::SetPosition(
+    views::ImageButton::SetPosition(
         gfx::Point(kCloseButtonMargin, kCloseButtonMargin));
     return;
   }
 #endif
 
-  ImageButton::SetPosition(
+  views::ImageButton::SetPosition(
       gfx::Point(size.width() - kCloseButtonSize - kCloseButtonMargin,
                  kCloseButtonMargin));
 }
 
-BEGIN_METADATA(CloseImageButton, views::ImageButton)
+BEGIN_METADATA(CloseImageButton, OverlayWindowImageButton)
 END_METADATA
-
-}  // namespace views
diff --git a/chrome/browser/ui/views/overlay/close_image_button.h b/chrome/browser/ui/views/overlay/close_image_button.h
index 4e505716..ade1da2 100644
--- a/chrome/browser/ui/views/overlay/close_image_button.h
+++ b/chrome/browser/ui/views/overlay/close_image_button.h
@@ -5,14 +5,12 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_OVERLAY_CLOSE_IMAGE_BUTTON_H_
 #define CHROME_BROWSER_UI_VIEWS_OVERLAY_CLOSE_IMAGE_BUTTON_H_
 
+#include "chrome/browser/ui/views/overlay/overlay_window_image_button.h"
 #include "chrome/browser/ui/views/overlay/overlay_window_views.h"
 #include "ui/base/metadata/metadata_header_macros.h"
-#include "ui/views/controls/button/image_button.h"
-
-namespace views {
 
 // An image button representing a close button.
-class CloseImageButton : public views::ImageButton {
+class CloseImageButton : public OverlayWindowImageButton {
  public:
   METADATA_HEADER(CloseImageButton);
 
@@ -26,6 +24,4 @@
                    OverlayWindowViews::WindowQuadrant quadrant);
 };
 
-}  // namespace views
-
 #endif  // CHROME_BROWSER_UI_VIEWS_OVERLAY_CLOSE_IMAGE_BUTTON_H_
diff --git a/chrome/browser/ui/views/overlay/hang_up_button.cc b/chrome/browser/ui/views/overlay/hang_up_button.cc
index 7b711bd..8e54570 100644
--- a/chrome/browser/ui/views/overlay/hang_up_button.cc
+++ b/chrome/browser/ui/views/overlay/hang_up_button.cc
@@ -7,6 +7,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/gfx/paint_vector_icon.h"
 
 namespace {
@@ -16,9 +17,7 @@
 }  // namespace
 
 HangUpButton::HangUpButton(PressedCallback callback)
-    : ImageButton(std::move(callback)) {
-  SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
-  SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
+    : OverlayWindowImageButton(std::move(callback)) {
   SetTooltipText(
       l10n_util::GetStringUTF16(IDS_PICTURE_IN_PICTURE_HANG_UP_TEXT));
   UpdateImage();
@@ -36,3 +35,6 @@
            gfx::CreateVectorIcon(vector_icons::kCallEndIcon, width(),
                                  kHangUpButtonColor));
 }
+
+BEGIN_METADATA(HangUpButton, OverlayWindowImageButton)
+END_METADATA
diff --git a/chrome/browser/ui/views/overlay/hang_up_button.h b/chrome/browser/ui/views/overlay/hang_up_button.h
index 171e895d..4df8c9cd 100644
--- a/chrome/browser/ui/views/overlay/hang_up_button.h
+++ b/chrome/browser/ui/views/overlay/hang_up_button.h
@@ -5,10 +5,13 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_OVERLAY_HANG_UP_BUTTON_H_
 #define CHROME_BROWSER_UI_VIEWS_OVERLAY_HANG_UP_BUTTON_H_
 
-#include "ui/views/controls/button/image_button.h"
+#include "chrome/browser/ui/views/overlay/overlay_window_image_button.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 
-class HangUpButton : public views::ImageButton {
+class HangUpButton : public OverlayWindowImageButton {
  public:
+  METADATA_HEADER(HangUpButton);
+
   explicit HangUpButton(PressedCallback callback);
   HangUpButton(const HangUpButton&) = delete;
   HangUpButton& operator=(const HangUpButton&) = delete;
diff --git a/chrome/browser/ui/views/overlay/overlay_window_image_button.cc b/chrome/browser/ui/views/overlay/overlay_window_image_button.cc
new file mode 100644
index 0000000..1a6ac3e
--- /dev/null
+++ b/chrome/browser/ui/views/overlay/overlay_window_image_button.cc
@@ -0,0 +1,31 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/overlay/overlay_window_image_button.h"
+
+#include "chrome/browser/ui/views/overlay/constants.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/views/animation/ink_drop.h"
+#include "ui/views/controls/button/image_button_factory.h"
+#include "ui/views/native_cursor.h"
+
+OverlayWindowImageButton::OverlayWindowImageButton(PressedCallback callback)
+    : ImageButton(std::move(callback)) {
+  SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
+  SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
+
+  views::ConfigureVectorImageButton(this);
+  views::InkDrop::Get(this)->SetBaseColor(kPipWindowIconColor);
+
+  SetInstallFocusRingOnFocus(true);
+}
+
+gfx::NativeCursor OverlayWindowImageButton::GetCursor(
+    const ui::MouseEvent& event) {
+  return views::GetNativeHandCursor();
+}
+
+BEGIN_METADATA(OverlayWindowImageButton, views::ImageButton)
+END_METADATA
diff --git a/chrome/browser/ui/views/overlay/overlay_window_image_button.h b/chrome/browser/ui/views/overlay/overlay_window_image_button.h
new file mode 100644
index 0000000..275b9cf
--- /dev/null
+++ b/chrome/browser/ui/views/overlay/overlay_window_image_button.h
@@ -0,0 +1,27 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_OVERLAY_OVERLAY_WINDOW_IMAGE_BUTTON_H_
+#define CHROME_BROWSER_UI_VIEWS_OVERLAY_OVERLAY_WINDOW_IMAGE_BUTTON_H_
+
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/views/controls/button/image_button.h"
+
+// Base class for image buttons on the PiP window.
+class OverlayWindowImageButton : public views::ImageButton {
+ public:
+  METADATA_HEADER(OverlayWindowImageButton);
+
+  OverlayWindowImageButton(const OverlayWindowImageButton&) = delete;
+  OverlayWindowImageButton& operator=(const OverlayWindowImageButton&) = delete;
+
+ protected:
+  explicit OverlayWindowImageButton(PressedCallback callback);
+  ~OverlayWindowImageButton() override = default;
+
+  // views::View:
+  gfx::NativeCursor GetCursor(const ui::MouseEvent& event) override;
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_OVERLAY_OVERLAY_WINDOW_IMAGE_BUTTON_H_
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.cc b/chrome/browser/ui/views/overlay/overlay_window_views.cc
index d63256af..9635ae9 100644
--- a/chrome/browser/ui/views/overlay/overlay_window_views.cc
+++ b/chrome/browser/ui/views/overlay/overlay_window_views.cc
@@ -3,13 +3,13 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/views/overlay/overlay_window_views.h"
-#include "base/memory/raw_ptr.h"
 
 #include <memory>
 #include <string>
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/time/time.h"
@@ -377,7 +377,7 @@
   auto controls_scrim_view = std::make_unique<views::View>();
   auto controls_container_view = std::make_unique<views::View>();
   auto close_controls_view =
-      std::make_unique<views::CloseImageButton>(base::BindRepeating(
+      std::make_unique<CloseImageButton>(base::BindRepeating(
           [](OverlayWindowViews* overlay) {
             // Only pause the video if play/pause is available.
             const bool should_pause_video = overlay->show_play_pause_button_;
@@ -386,7 +386,7 @@
           },
           base::Unretained(this)));
 
-  std::unique_ptr<views::BackToTabImageButton> back_to_tab_image_button;
+  std::unique_ptr<BackToTabImageButton> back_to_tab_image_button;
   std::unique_ptr<BackToTabLabelButton> back_to_tab_label_button;
   auto back_to_tab_callback = base::BindRepeating(
       [](OverlayWindowViews* overlay) {
@@ -398,11 +398,11 @@
     back_to_tab_label_button =
         std::make_unique<BackToTabLabelButton>(std::move(back_to_tab_callback));
   } else {
-    back_to_tab_image_button = std::make_unique<views::BackToTabImageButton>(
-        std::move(back_to_tab_callback));
+    back_to_tab_image_button =
+        std::make_unique<BackToTabImageButton>(std::move(back_to_tab_callback));
   }
 
-  auto previous_track_controls_view = std::make_unique<views::TrackImageButton>(
+  auto previous_track_controls_view = std::make_unique<TrackImageButton>(
       base::BindRepeating(
           [](OverlayWindowViews* overlay) {
             overlay->controller_->PreviousTrack();
@@ -413,13 +413,13 @@
       l10n_util::GetStringUTF16(
           IDS_PICTURE_IN_PICTURE_PREVIOUS_TRACK_CONTROL_ACCESSIBLE_TEXT));
   auto play_pause_controls_view =
-      std::make_unique<views::PlaybackImageButton>(base::BindRepeating(
+      std::make_unique<PlaybackImageButton>(base::BindRepeating(
           [](OverlayWindowViews* overlay) {
             overlay->TogglePlayPause();
             overlay->RecordButtonPressed(OverlayWindowControl::kPlayPause);
           },
           base::Unretained(this)));
-  auto next_track_controls_view = std::make_unique<views::TrackImageButton>(
+  auto next_track_controls_view = std::make_unique<TrackImageButton>(
       base::BindRepeating(
           [](OverlayWindowViews* overlay) {
             overlay->controller_->NextTrack();
@@ -430,7 +430,7 @@
       l10n_util::GetStringUTF16(
           IDS_PICTURE_IN_PICTURE_NEXT_TRACK_CONTROL_ACCESSIBLE_TEXT));
   auto skip_ad_controls_view =
-      std::make_unique<views::SkipAdLabelButton>(base::BindRepeating(
+      std::make_unique<SkipAdLabelButton>(base::BindRepeating(
           [](OverlayWindowViews* overlay) {
             overlay->controller_->SkipAd();
             overlay->RecordButtonPressed(OverlayWindowControl::kSkipAd);
@@ -458,8 +458,8 @@
       },
       base::Unretained(this)));
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  auto resize_handle_view = std::make_unique<views::ResizeHandleButton>(
-      views::Button::PressedCallback());
+  auto resize_handle_view =
+      std::make_unique<ResizeHandleButton>(views::Button::PressedCallback());
 #endif
 
   window_background_view->SetPaintToLayer(ui::LAYER_SOLID_COLOR);
@@ -1328,23 +1328,23 @@
   play_pause_controls_view_->SetPlaybackState(is_active ? kPlaying : kPaused);
 }
 
-views::PlaybackImageButton*
-OverlayWindowViews::play_pause_controls_view_for_testing() const {
+PlaybackImageButton* OverlayWindowViews::play_pause_controls_view_for_testing()
+    const {
   return play_pause_controls_view_;
 }
 
-views::TrackImageButton*
-OverlayWindowViews::next_track_controls_view_for_testing() const {
+TrackImageButton* OverlayWindowViews::next_track_controls_view_for_testing()
+    const {
   return next_track_controls_view_;
 }
 
-views::TrackImageButton*
-OverlayWindowViews::previous_track_controls_view_for_testing() const {
+TrackImageButton* OverlayWindowViews::previous_track_controls_view_for_testing()
+    const {
   return previous_track_controls_view_;
 }
 
-views::SkipAdLabelButton*
-OverlayWindowViews::skip_ad_controls_view_for_testing() const {
+SkipAdLabelButton* OverlayWindowViews::skip_ad_controls_view_for_testing()
+    const {
   return skip_ad_controls_view_;
 }
 
@@ -1367,7 +1367,7 @@
   return back_to_tab_label_button_;
 }
 
-views::CloseImageButton* OverlayWindowViews::close_button_for_testing() const {
+CloseImageButton* OverlayWindowViews::close_button_for_testing() const {
   return close_controls_view_;
 }
 
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.h b/chrome/browser/ui/views/overlay/overlay_window_views.h
index b94f9c8..2e67353dd 100644
--- a/chrome/browser/ui/views/overlay/overlay_window_views.h
+++ b/chrome/browser/ui/views/overlay/overlay_window_views.h
@@ -6,31 +6,27 @@
 #define CHROME_BROWSER_UI_VIEWS_OVERLAY_OVERLAY_WINDOW_VIEWS_H_
 
 #include "base/memory/raw_ptr.h"
-#include "content/public/browser/overlay_window.h"
-
 #include "base/timer/timer.h"
 #include "build/chromeos_buildflags.h"
+#include "content/public/browser/overlay_window.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/views/widget/widget.h"
 
-namespace views {
-class BackToTabImageButton;
-class CloseImageButton;
-class PlaybackImageButton;
-class ResizeHandleButton;
-class SkipAdLabelButton;
-class TrackImageButton;
-}  // namespace views
-
 namespace viz {
 class FrameSinkId;
 }  // namespace viz
 
+class BackToTabImageButton;
 class BackToTabLabelButton;
+class CloseImageButton;
 class HangUpButton;
+class PlaybackImageButton;
+class ResizeHandleButton;
+class SkipAdLabelButton;
 class ToggleMicrophoneButton;
 class ToggleCameraButton;
+class TrackImageButton;
 
 // The Chrome desktop implementation of OverlayWindow. This will only be
 // implemented in views, which will support all desktop platforms.
@@ -109,15 +105,15 @@
   // is not done yet.
   bool IsLayoutPendingForTesting() const;
 
-  views::PlaybackImageButton* play_pause_controls_view_for_testing() const;
-  views::TrackImageButton* next_track_controls_view_for_testing() const;
-  views::TrackImageButton* previous_track_controls_view_for_testing() const;
-  views::SkipAdLabelButton* skip_ad_controls_view_for_testing() const;
+  PlaybackImageButton* play_pause_controls_view_for_testing() const;
+  TrackImageButton* next_track_controls_view_for_testing() const;
+  TrackImageButton* previous_track_controls_view_for_testing() const;
+  SkipAdLabelButton* skip_ad_controls_view_for_testing() const;
   ToggleMicrophoneButton* toggle_microphone_button_for_testing() const;
   ToggleCameraButton* toggle_camera_button_for_testing() const;
   HangUpButton* hang_up_button_for_testing() const;
   BackToTabLabelButton* back_to_tab_label_button_for_testing() const;
-  views::CloseImageButton* close_button_for_testing() const;
+  CloseImageButton* close_button_for_testing() const;
   gfx::Point close_image_position_for_testing() const;
   gfx::Point resize_handle_position_for_testing() const;
   OverlayWindowViews::PlaybackState playback_state_for_testing() const;
@@ -235,14 +231,14 @@
   raw_ptr<views::View> video_view_ = nullptr;
   raw_ptr<views::View> controls_scrim_view_ = nullptr;
   raw_ptr<views::View> controls_container_view_ = nullptr;
-  raw_ptr<views::CloseImageButton> close_controls_view_ = nullptr;
-  raw_ptr<views::BackToTabImageButton> back_to_tab_image_button_ = nullptr;
+  raw_ptr<CloseImageButton> close_controls_view_ = nullptr;
+  raw_ptr<BackToTabImageButton> back_to_tab_image_button_ = nullptr;
   raw_ptr<BackToTabLabelButton> back_to_tab_label_button_ = nullptr;
-  raw_ptr<views::TrackImageButton> previous_track_controls_view_ = nullptr;
-  raw_ptr<views::PlaybackImageButton> play_pause_controls_view_ = nullptr;
-  raw_ptr<views::TrackImageButton> next_track_controls_view_ = nullptr;
-  raw_ptr<views::SkipAdLabelButton> skip_ad_controls_view_ = nullptr;
-  raw_ptr<views::ResizeHandleButton> resize_handle_view_ = nullptr;
+  raw_ptr<TrackImageButton> previous_track_controls_view_ = nullptr;
+  raw_ptr<PlaybackImageButton> play_pause_controls_view_ = nullptr;
+  raw_ptr<TrackImageButton> next_track_controls_view_ = nullptr;
+  raw_ptr<SkipAdLabelButton> skip_ad_controls_view_ = nullptr;
+  raw_ptr<ResizeHandleButton> resize_handle_view_ = nullptr;
   raw_ptr<ToggleMicrophoneButton> toggle_microphone_button_ = nullptr;
   raw_ptr<ToggleCameraButton> toggle_camera_button_ = nullptr;
   raw_ptr<HangUpButton> hang_up_button_ = nullptr;
diff --git a/chrome/browser/ui/views/overlay/playback_image_button.cc b/chrome/browser/ui/views/overlay/playback_image_button.cc
index ab1717bd..2a1dcf3 100644
--- a/chrome/browser/ui/views/overlay/playback_image_button.cc
+++ b/chrome/browser/ui/views/overlay/playback_image_button.cc
@@ -13,19 +13,13 @@
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/vector_icons.h"
 
-namespace views {
-
 PlaybackImageButton::PlaybackImageButton(PressedCallback callback)
-    : ImageButton(std::move(callback)) {
-  SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
-  SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
-
+    : OverlayWindowImageButton(std::move(callback)) {
   // Accessibility.
   const std::u16string playback_accessible_button_label(
       l10n_util::GetStringUTF16(
           IDS_PICTURE_IN_PICTURE_PLAY_PAUSE_CONTROL_ACCESSIBLE_TEXT));
   SetAccessibleName(playback_accessible_button_label);
-  SetInstallFocusRingOnFocus(true);
 }
 
 void PlaybackImageButton::OnBoundsChanged(const gfx::Rect& rect) {
@@ -69,7 +63,5 @@
   SchedulePaint();
 }
 
-BEGIN_METADATA(PlaybackImageButton, views::ImageButton)
+BEGIN_METADATA(PlaybackImageButton, OverlayWindowImageButton)
 END_METADATA
-
-}  // namespace views
diff --git a/chrome/browser/ui/views/overlay/playback_image_button.h b/chrome/browser/ui/views/overlay/playback_image_button.h
index 6bf1de4f1..e6a266b 100644
--- a/chrome/browser/ui/views/overlay/playback_image_button.h
+++ b/chrome/browser/ui/views/overlay/playback_image_button.h
@@ -5,14 +5,12 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_OVERLAY_PLAYBACK_IMAGE_BUTTON_H_
 #define CHROME_BROWSER_UI_VIEWS_OVERLAY_PLAYBACK_IMAGE_BUTTON_H_
 
+#include "chrome/browser/ui/views/overlay/overlay_window_image_button.h"
 #include "chrome/browser/ui/views/overlay/overlay_window_views.h"
 #include "ui/base/metadata/metadata_header_macros.h"
-#include "ui/views/controls/button/image_button.h"
-
-namespace views {
 
 // A resizable playback button with 3 states: play/pause/replay.
-class PlaybackImageButton : public views::ImageButton {
+class PlaybackImageButton : public OverlayWindowImageButton {
  public:
   METADATA_HEADER(PlaybackImageButton);
 
@@ -39,6 +37,4 @@
   gfx::ImageSkia replay_image_;
 };
 
-}  // namespace views
-
 #endif  // CHROME_BROWSER_UI_VIEWS_OVERLAY_PLAYBACK_IMAGE_BUTTON_H_
diff --git a/chrome/browser/ui/views/overlay/resize_handle_button.cc b/chrome/browser/ui/views/overlay/resize_handle_button.cc
index 375efc8f..90c9dbbf 100644
--- a/chrome/browser/ui/views/overlay/resize_handle_button.cc
+++ b/chrome/browser/ui/views/overlay/resize_handle_button.cc
@@ -23,10 +23,8 @@
 
 }  // namespace
 
-namespace views {
-
 ResizeHandleButton::ResizeHandleButton(PressedCallback callback)
-    : ImageButton(std::move(callback)) {
+    : views::ImageButton(std::move(callback)) {
   SetSize(gfx::Size(kResizeHandleButtonSize, kResizeHandleButtonSize));
   SetImageForQuadrant(OverlayWindowViews::WindowQuadrant::kBottomRight);
 
@@ -63,21 +61,21 @@
   // This is determined as the opposite quadrant on the window.
   switch (quadrant) {
     case OverlayWindowViews::WindowQuadrant::kBottomLeft:
-      ImageButton::SetPosition(gfx::Point(
+      views::ImageButton::SetPosition(gfx::Point(
           size.width() - kResizeHandleButtonSize - kResizeHandleButtonMargin,
           kResizeHandleButtonMargin));
       break;
     case OverlayWindowViews::WindowQuadrant::kBottomRight:
-      ImageButton::SetPosition(
+      views::ImageButton::SetPosition(
           gfx::Point(kResizeHandleButtonMargin, kResizeHandleButtonMargin));
       break;
     case OverlayWindowViews::WindowQuadrant::kTopLeft:
-      ImageButton::SetPosition(gfx::Point(
+      views::ImageButton::SetPosition(gfx::Point(
           size.width() - kResizeHandleButtonSize - kResizeHandleButtonMargin,
           size.height() - kResizeHandleButtonSize - kResizeHandleButtonMargin));
       break;
     case OverlayWindowViews::WindowQuadrant::kTopRight:
-      ImageButton::SetPosition(gfx::Point(
+      views::ImageButton::SetPosition(gfx::Point(
           kResizeHandleButtonMargin,
           size.height() - kResizeHandleButtonSize - kResizeHandleButtonMargin));
       break;
@@ -125,5 +123,3 @@
 
 BEGIN_METADATA(ResizeHandleButton, views::ImageButton)
 END_METADATA
-
-}  // namespace views
diff --git a/chrome/browser/ui/views/overlay/resize_handle_button.h b/chrome/browser/ui/views/overlay/resize_handle_button.h
index 162dac6..7030618 100644
--- a/chrome/browser/ui/views/overlay/resize_handle_button.h
+++ b/chrome/browser/ui/views/overlay/resize_handle_button.h
@@ -9,8 +9,6 @@
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/controls/button/image_button.h"
 
-namespace views {
-
 // An image button representing a white resize handle affordance.
 class ResizeHandleButton : public views::ImageButton {
  public:
@@ -31,6 +29,4 @@
   absl::optional<OverlayWindowViews::WindowQuadrant> current_quadrant_;
 };
 
-}  // namespace views
-
 #endif  // CHROME_BROWSER_UI_VIEWS_OVERLAY_RESIZE_HANDLE_BUTTON_H_
diff --git a/chrome/browser/ui/views/overlay/skip_ad_label_button.cc b/chrome/browser/ui/views/overlay/skip_ad_label_button.cc
index 8153a0b..ae3b37b 100644
--- a/chrome/browser/ui/views/overlay/skip_ad_label_button.cc
+++ b/chrome/browser/ui/views/overlay/skip_ad_label_button.cc
@@ -24,14 +24,12 @@
 
 }  // namespace
 
-namespace views {
-
 SkipAdLabelButton::SkipAdLabelButton(PressedCallback callback)
-    : LabelButton(std::move(callback),
-                  l10n_util::GetStringUTF16(
-                      IDS_PICTURE_IN_PICTURE_SKIP_AD_CONTROL_TEXT)) {
-  SetBackground(
-      CreateBackgroundFromPainter(Painter::CreateRoundRectWith1PxBorderPainter(
+    : views::LabelButton(std::move(callback),
+                         l10n_util::GetStringUTF16(
+                             IDS_PICTURE_IN_PICTURE_SKIP_AD_CONTROL_TEXT)) {
+  SetBackground(CreateBackgroundFromPainter(
+      views::Painter::CreateRoundRectWith1PxBorderPainter(
           kSkipAdButtonBackgroundColor, kSkipAdButtonBorderColor, 1.f)));
   SetHorizontalAlignment(gfx::ALIGN_CENTER);
   SetEnabledTextColors(kSkipAdButtonTextColor);
@@ -45,7 +43,7 @@
 }
 
 void SkipAdLabelButton::SetPosition(const gfx::Size& size) {
-  LabelButton::SetPosition(gfx::Point(
+  views::LabelButton::SetPosition(gfx::Point(
       size.width() - kSkipAdButtonWidth + 1 /* border offset */,
       size.height() - kSkipAdButtonHeight - kSkipAdButtonMarginBottom));
 }
@@ -53,12 +51,10 @@
 void SkipAdLabelButton::SetVisible(bool visible) {
   // We need to do more than the usual visibility change because otherwise the
   // overlay window cannot be dragged when grabbing within the label area.
-  LabelButton::SetVisible(visible);
+  views::LabelButton::SetVisible(visible);
   SetSize(visible ? gfx::Size(kSkipAdButtonWidth, kSkipAdButtonHeight)
                   : gfx::Size());
 }
 
 BEGIN_METADATA(SkipAdLabelButton, views::LabelButton)
 END_METADATA
-
-}  // namespace views
diff --git a/chrome/browser/ui/views/overlay/skip_ad_label_button.h b/chrome/browser/ui/views/overlay/skip_ad_label_button.h
index b71db1f2..a6314bf 100644
--- a/chrome/browser/ui/views/overlay/skip_ad_label_button.h
+++ b/chrome/browser/ui/views/overlay/skip_ad_label_button.h
@@ -9,8 +9,6 @@
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/controls/button/label_button.h"
 
-namespace views {
-
 // A label button representing a skip-ad button.
 class SkipAdLabelButton : public views::LabelButton {
  public:
@@ -28,6 +26,4 @@
   void SetVisible(bool is_visible) override;
 };
 
-}  // namespace views
-
 #endif  // CHROME_BROWSER_UI_VIEWS_OVERLAY_SKIP_AD_LABEL_BUTTON_H_
diff --git a/chrome/browser/ui/views/overlay/toggle_camera_button.cc b/chrome/browser/ui/views/overlay/toggle_camera_button.cc
index a3cff2d..c525450 100644
--- a/chrome/browser/ui/views/overlay/toggle_camera_button.cc
+++ b/chrome/browser/ui/views/overlay/toggle_camera_button.cc
@@ -8,12 +8,11 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/gfx/paint_vector_icon.h"
 
 ToggleCameraButton::ToggleCameraButton(PressedCallback callback)
-    : ImageButton(std::move(callback)) {
-  SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
-  SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
+    : OverlayWindowImageButton(std::move(callback)) {
   UpdateImageAndTooltipText();
 }
 
@@ -42,3 +41,6 @@
            gfx::CreateVectorIcon(icon, width(), kPipWindowIconColor));
   SetTooltipText(l10n_util::GetStringUTF16(text));
 }
+
+BEGIN_METADATA(ToggleCameraButton, OverlayWindowImageButton)
+END_METADATA
diff --git a/chrome/browser/ui/views/overlay/toggle_camera_button.h b/chrome/browser/ui/views/overlay/toggle_camera_button.h
index e716a55..c8f73e1 100644
--- a/chrome/browser/ui/views/overlay/toggle_camera_button.h
+++ b/chrome/browser/ui/views/overlay/toggle_camera_button.h
@@ -5,10 +5,13 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_OVERLAY_TOGGLE_CAMERA_BUTTON_H_
 #define CHROME_BROWSER_UI_VIEWS_OVERLAY_TOGGLE_CAMERA_BUTTON_H_
 
-#include "ui/views/controls/button/image_button.h"
+#include "chrome/browser/ui/views/overlay/overlay_window_image_button.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 
-class ToggleCameraButton : public views::ImageButton {
+class ToggleCameraButton : public OverlayWindowImageButton {
  public:
+  METADATA_HEADER(ToggleCameraButton);
+
   explicit ToggleCameraButton(PressedCallback callback);
   ToggleCameraButton(const ToggleCameraButton&) = delete;
   ToggleCameraButton& operator=(const ToggleCameraButton&) = delete;
diff --git a/chrome/browser/ui/views/overlay/toggle_microphone_button.cc b/chrome/browser/ui/views/overlay/toggle_microphone_button.cc
index a681ba4..98d6534 100644
--- a/chrome/browser/ui/views/overlay/toggle_microphone_button.cc
+++ b/chrome/browser/ui/views/overlay/toggle_microphone_button.cc
@@ -8,12 +8,11 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/gfx/paint_vector_icon.h"
 
 ToggleMicrophoneButton::ToggleMicrophoneButton(PressedCallback callback)
-    : ImageButton(std::move(callback)) {
-  SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
-  SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
+    : OverlayWindowImageButton(std::move(callback)) {
   UpdateImageAndTooltipText();
 }
 
@@ -42,3 +41,6 @@
            gfx::CreateVectorIcon(icon, width(), kPipWindowIconColor));
   SetTooltipText(l10n_util::GetStringUTF16(text));
 }
+
+BEGIN_METADATA(ToggleMicrophoneButton, OverlayWindowImageButton)
+END_METADATA
diff --git a/chrome/browser/ui/views/overlay/toggle_microphone_button.h b/chrome/browser/ui/views/overlay/toggle_microphone_button.h
index 3b1f8bcb..830d758 100644
--- a/chrome/browser/ui/views/overlay/toggle_microphone_button.h
+++ b/chrome/browser/ui/views/overlay/toggle_microphone_button.h
@@ -5,10 +5,13 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_OVERLAY_TOGGLE_MICROPHONE_BUTTON_H_
 #define CHROME_BROWSER_UI_VIEWS_OVERLAY_TOGGLE_MICROPHONE_BUTTON_H_
 
-#include "ui/views/controls/button/image_button.h"
+#include "chrome/browser/ui/views/overlay/overlay_window_image_button.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 
-class ToggleMicrophoneButton : public views::ImageButton {
+class ToggleMicrophoneButton : public OverlayWindowImageButton {
  public:
+  METADATA_HEADER(ToggleMicrophoneButton);
+
   explicit ToggleMicrophoneButton(PressedCallback callback);
   ToggleMicrophoneButton(const ToggleMicrophoneButton&) = delete;
   ToggleMicrophoneButton& operator=(const ToggleMicrophoneButton&) = delete;
diff --git a/chrome/browser/ui/views/overlay/track_image_button.cc b/chrome/browser/ui/views/overlay/track_image_button.cc
index 4fceb3f5..d569023 100644
--- a/chrome/browser/ui/views/overlay/track_image_button.cc
+++ b/chrome/browser/ui/views/overlay/track_image_button.cc
@@ -19,28 +19,23 @@
 
 }  // namespace
 
-namespace views {
-
 TrackImageButton::TrackImageButton(PressedCallback callback,
                                    const gfx::VectorIcon& icon,
                                    std::u16string label)
-    : ImageButton(std::move(callback)),
+    : OverlayWindowImageButton(std::move(callback)),
       image_(
           gfx::CreateVectorIcon(icon, kTrackImageSize, kPipWindowIconColor)) {
-  SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
-  SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
   SetImage(views::Button::STATE_NORMAL, image_);
 
   // Accessibility.
   SetAccessibleName(label);
   SetTooltipText(label);
-  SetInstallFocusRingOnFocus(true);
 }
 
 void TrackImageButton::SetVisible(bool visible) {
   // We need to do more than the usual visibility change because otherwise the
   // overlay window cannot be dragged when grabbing within the button area.
-  ImageButton::SetVisible(visible);
+  views::ImageButton::SetVisible(visible);
   SetSize(visible ? last_visible_size_ : gfx::Size());
 }
 
@@ -49,7 +44,5 @@
     last_visible_size_ = size();
 }
 
-BEGIN_METADATA(TrackImageButton, views::ImageButton)
+BEGIN_METADATA(TrackImageButton, OverlayWindowImageButton)
 END_METADATA
-
-}  // namespace views
diff --git a/chrome/browser/ui/views/overlay/track_image_button.h b/chrome/browser/ui/views/overlay/track_image_button.h
index 9fc3ad1..9aab4b64 100644
--- a/chrome/browser/ui/views/overlay/track_image_button.h
+++ b/chrome/browser/ui/views/overlay/track_image_button.h
@@ -5,18 +5,16 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_OVERLAY_TRACK_IMAGE_BUTTON_H_
 #define CHROME_BROWSER_UI_VIEWS_OVERLAY_TRACK_IMAGE_BUTTON_H_
 
+#include "chrome/browser/ui/views/overlay/overlay_window_image_button.h"
 #include "chrome/browser/ui/views/overlay/overlay_window_views.h"
 #include "ui/base/metadata/metadata_header_macros.h"
-#include "ui/views/controls/button/image_button.h"
 
 namespace gfx {
 struct VectorIcon;
 }
 
-namespace views {
-
 // A resizable previous/next track image button.
-class TrackImageButton : public views::ImageButton {
+class TrackImageButton : public OverlayWindowImageButton {
  public:
   METADATA_HEADER(TrackImageButton);
 
@@ -41,6 +39,4 @@
   gfx::Size last_visible_size_;
 };
 
-}  // namespace views
-
 #endif  // CHROME_BROWSER_UI_VIEWS_OVERLAY_TRACK_IMAGE_BUTTON_H_
diff --git a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc
index 53c5ddb..508ee1e 100644
--- a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc
+++ b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/check_op.h"
+#include "base/strings/strcat.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/profiles/profile.h"
@@ -53,6 +54,7 @@
 #include "ui/views/layout/fill_layout.h"
 #include "ui/views/view_class_properties.h"
 #include "url/origin.h"
+#include "url/url_constants.h"
 
 namespace payments {
 namespace {
@@ -64,8 +66,7 @@
 
   const std::u16string title = web_contents->GetTitle();
   const std::u16string https_prefix =
-      base::ASCIIToUTF16(url::kHttpsScheme) +
-      base::ASCIIToUTF16(url::kStandardSchemeSeparator);
+      base::StrCat({url::kHttpsScheme16, url::kStandardSchemeSeparator16});
   return base::StartsWith(title, https_prefix, base::CompareCase::SENSITIVE)
              ? std::u16string()
              : title;
diff --git a/chrome/browser/ui/webui/certificate_viewer_webui.cc b/chrome/browser/ui/webui/certificate_viewer_webui.cc
index 6063004..752fa90 100644
--- a/chrome/browser/ui/webui/certificate_viewer_webui.cc
+++ b/chrome/browser/ui/webui/certificate_viewer_webui.cc
@@ -85,8 +85,8 @@
     : CertNodeBuilder(l10n_util::GetStringUTF8(label_id)) {}
 
 CertNodeBuilder& CertNodeBuilder::Payload(base::StringPiece payload) {
-  DCHECK(!node_.HasKey("payload.val"));
-  node_.SetString("payload.val", payload);
+  DCHECK(!node_.FindPath("payload.val"));
+  node_.SetStringPath("payload.val", payload);
   return *this;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
index 767b89c..0893f6d 100644
--- a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
@@ -26,7 +26,7 @@
 class CookieWaiter;
 
 // Possible error states of the Active Directory screen. Must be in the same
-// order as ACTIVE_DIRECTORY_ERROR_STATE enum values.
+// order as ActiveDirectoryErrorState ( in enterprise_enrollment.js ) values.
 enum class ActiveDirectoryErrorState {
   NONE = 0,
   MACHINE_NAME_INVALID = 1,
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index acae63c..d636e45 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -151,6 +151,9 @@
 constexpr char kCustomElementsJSPath[] = "custom_elements.js";
 constexpr char kDebuggerJSPath[] = "debug.js";
 constexpr char kKeyboardUtilsJSPath[] = "keyboard_utils.js";
+constexpr char kKeyboardUtilsForInjectionPath[] =
+    "components/keyboard_utils_for_injection.js";
+
 constexpr char kLoginJSPath[] = "login.js";
 constexpr char kOobeJSPath[] = "oobe.js";
 constexpr char kProductLogoPath[] = "product-logo.png";
@@ -370,6 +373,8 @@
   source->AddResourcePath(kWebviewSamlInjectedJSPath,
                           IDR_GAIA_AUTH_WEBVIEW_SAML_INJECTED_JS);
   source->AddResourcePath(kKeyboardUtilsJSPath, IDR_KEYBOARD_UTILS_JS);
+  source->AddResourcePath(kKeyboardUtilsForInjectionPath,
+                          IDR_KEYBOARD_UTILS_FOR_INJECTION_JS);
   source->OverrideContentSecurityPolicy(
       network::mojom::CSPDirectiveName::ObjectSrc, "object-src chrome:;");
   source->DisableTrustedTypesCSP();
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos.cc b/chrome/browser/ui/webui/help/version_updater_chromeos.cc
index 5cedeae..54cffa1a 100644
--- a/chrome/browser/ui/webui/help/version_updater_chromeos.cc
+++ b/chrome/browser/ui/webui/help/version_updater_chromeos.cc
@@ -321,7 +321,7 @@
       break;
     case update_engine::Operation::DOWNLOADING:
       progress = static_cast<int>(round(status.progress() * 100));
-      FALLTHROUGH;
+      [[fallthrough]];
     case update_engine::Operation::UPDATE_AVAILABLE:
       my_status = UPDATING;
       break;
diff --git a/chrome/browser/ui/webui/new_tab_page_third_party/BUILD.gn b/chrome/browser/ui/webui/new_tab_page_third_party/BUILD.gn
index db82dce..6f58d79 100644
--- a/chrome/browser/ui/webui/new_tab_page_third_party/BUILD.gn
+++ b/chrome/browser/ui/webui/new_tab_page_third_party/BUILD.gn
@@ -6,6 +6,7 @@
 
 mojom("mojo_bindings") {
   sources = [ "new_tab_page_third_party.mojom" ]
+  webui_module_path = "/"
   public_deps = [
     "//skia/public/mojom",
     "//ui/webui/resources/cr_components/most_visited:mojom",
diff --git a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
index e19f33791..ffbe1a9 100644
--- a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
@@ -452,7 +452,7 @@
         case CookieTreeNode::DetailedInfo::TYPE_COOKIE:
           DCHECK_EQ(0u, item_count);
           item_count = 1;
-          FALLTHROUGH;
+          [[fallthrough]];
         case CookieTreeNode::DetailedInfo::TYPE_COOKIES:
           description += l10n_util::GetPluralStringFUTF16(
               IDS_SETTINGS_SITE_SETTINGS_NUM_COOKIES,
diff --git a/chrome/browser/ui/webui/theme_source.cc b/chrome/browser/ui/webui/theme_source.cc
index d740ff8..c8355d83 100644
--- a/chrome/browser/ui/webui/theme_source.cc
+++ b/chrome/browser/ui/webui/theme_source.cc
@@ -119,7 +119,7 @@
       case version_info::Channel::BETA:
       case version_info::Channel::STABLE:
         NOTREACHED();
-        FALLTHROUGH;
+        [[fallthrough]];
 #endif
       case version_info::Channel::UNKNOWN:
         resource_id = IDR_PRODUCT_LOGO_32;
diff --git a/chrome/browser/webauthn/cablev2_devices.cc b/chrome/browser/webauthn/cablev2_devices.cc
index aeb597d3..9584859 100644
--- a/chrome/browser/webauthn/cablev2_devices.cc
+++ b/chrome/browser/webauthn/cablev2_devices.cc
@@ -274,7 +274,8 @@
 }  // namespace
 
 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
-  registry->RegisterListPref(kWebAuthnCablePairingsPrefName);
+  registry->RegisterListPref(kWebAuthnCablePairingsPrefName,
+                             user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
 }
 
 KnownDevices::KnownDevices() = default;
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index d11af51b..d7692175 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1641253948-cbc668e8af4c8e5ed8701f793ba392c4f270a9f6.profdata
+chrome-linux-main-1641318921-0c86e2a71b7d8f34f15c91bbc9b326a1c52464c6.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 0121ec6..d09accd2 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1641253948-2ef4768347ec7aedffa10b4c7d7380be4e62f488.profdata
+chrome-mac-main-1641296823-da170ac91f32d829a2ce4572bb1d58cc881ee63e.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 9f69de5..e57e2eb 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1641263949-97f1571730c81282f8559545652753579d907510.profdata
+chrome-win32-main-1641308323-52b3f0d25337d8bd8ef81cba90f81159d78c6f2c.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index ed8ccdb..f2c0521d 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1641263949-559c32d4a6ab761fcdfa22e6bf9614a2bb63356b.profdata
+chrome-win64-main-1641285643-0fbc9ceaa0c127fcc2480dc746a7897e488d9ed7.profdata
diff --git a/chrome/common/extensions/api/file_browser_handlers/file_browser_handler.cc b/chrome/common/extensions/api/file_browser_handlers/file_browser_handler.cc
index 0dc193d..f15e485 100644
--- a/chrome/common/extensions/api/file_browser_handlers/file_browser_handler.cc
+++ b/chrome/common/extensions/api/file_browser_handlers/file_browser_handler.cc
@@ -146,24 +146,23 @@
   std::unique_ptr<FileBrowserHandler> result(new FileBrowserHandler());
   result->set_extension_id(extension_id);
 
-  std::string handler_id;
+  const std::string* handler_id =
+      file_browser_handler->FindStringKey(keys::kFileBrowserHandlerId);
   // Read the file action |id| (mandatory).
-  if (!file_browser_handler->HasKey(keys::kFileBrowserHandlerId) ||
-      !file_browser_handler->GetString(keys::kFileBrowserHandlerId,
-                                       &handler_id)) {
+  if (!handler_id) {
     *error = errors::kInvalidFileBrowserHandlerId;
     return nullptr;
   }
-  result->set_id(handler_id);
+  result->set_id(*handler_id);
 
   // Read the page action title from |default_title| (mandatory).
-  std::string title;
-  if (!file_browser_handler->HasKey(keys::kActionDefaultTitle) ||
-      !file_browser_handler->GetString(keys::kActionDefaultTitle, &title)) {
+  const std::string* title =
+      file_browser_handler->FindStringKey(keys::kActionDefaultTitle);
+  if (!title) {
     *error = errors::kInvalidActionDefaultTitle;
     return nullptr;
   }
-  result->set_title(title);
+  result->set_title(*title);
 
   // Initialize access permissions (optional).
   const base::Value* access_list_value =
@@ -234,16 +233,15 @@
     }
   }
 
-  std::string default_icon;
   // Read the file browser action |default_icon| (optional).
-  if (file_browser_handler->HasKey(keys::kActionDefaultIcon)) {
-    if (!file_browser_handler->GetString(keys::kActionDefaultIcon,
-                                         &default_icon) ||
-        default_icon.empty()) {
+  if (const base::Value* default_icon_val =
+          file_browser_handler->FindKey(keys::kActionDefaultIcon)) {
+    const std::string* default_icon = default_icon_val->GetIfString();
+    if (!default_icon || default_icon->empty()) {
       *error = errors::kInvalidActionDefaultIcon;
       return nullptr;
     }
-    result->set_icon_path(default_icon);
+    result->set_icon_path(*default_icon);
   }
 
   return result;
diff --git a/chrome/install_static/chromium_install_modes.cc b/chrome/install_static/chromium_install_modes.cc
index c61f84a4..80bbb30c 100644
--- a/chrome/install_static/chromium_install_modes.cc
+++ b/chrome/install_static/chromium_install_modes.cc
@@ -22,6 +22,8 @@
 
 const char kSafeBrowsingName[] = "chromium";
 
+const char kDeviceManagementServerHostName[] = "";
+
 const InstallConstants kInstallModes[] = {
     // The primary (and only) install mode for Chromium.
     {
diff --git a/chrome/install_static/google_chrome_install_modes.cc b/chrome/install_static/google_chrome_install_modes.cc
index 7eb4797..dbef096 100644
--- a/chrome/install_static/google_chrome_install_modes.cc
+++ b/chrome/install_static/google_chrome_install_modes.cc
@@ -22,6 +22,8 @@
 
 const char kSafeBrowsingName[] = "googlechrome";
 
+const char kDeviceManagementServerHostName[] = "m.google.com";
+
 const InstallConstants kInstallModes[] = {
     // The primary install mode for stable Google Chrome.
     {
diff --git a/chrome/install_static/install_modes.h b/chrome/install_static/install_modes.h
index 7b3a61c5..2238d3e 100644
--- a/chrome/install_static/install_modes.h
+++ b/chrome/install_static/install_modes.h
@@ -60,6 +60,10 @@
 // The brand-specific safe browsing client name.
 extern const char kSafeBrowsingName[];
 
+// The brand-specific device management server hostname, or an empty string if
+// the brand does not restrict runtime-configured server URLs.
+extern const char kDeviceManagementServerHostName[];
+
 // A brand's collection of install modes.
 extern const InstallConstants kInstallModes[];
 
diff --git a/chrome/install_static/install_util.cc b/chrome/install_static/install_util.cc
index d0c3cec..da295354 100644
--- a/chrome/install_static/install_util.cc
+++ b/chrome/install_static/install_util.cc
@@ -415,6 +415,21 @@
   return kSafeBrowsingName;
 }
 
+const char* GetDeviceManagementServerHostName() {
+  static constexpr char kNoRestriction[] = "";
+
+  // If this brand doesn't specify a restriction, return an empty string.
+  if (!*kDeviceManagementServerHostName)
+    return kNoRestriction;
+
+  // Stable and extended stable Google Chrome are restricted to one host.
+  if (GetChromeChannel() == version_info::Channel::STABLE)
+    return kDeviceManagementServerHostName;
+
+  // Otherwise, return an empty string to indicate no restriction.
+  return kNoRestriction;
+}
+
 bool GetCollectStatsConsent() {
   bool enabled = true;
 
diff --git a/chrome/install_static/install_util.h b/chrome/install_static/install_util.h
index 0a53d20..676b7f8 100644
--- a/chrome/install_static/install_util.h
+++ b/chrome/install_static/install_util.h
@@ -164,6 +164,10 @@
 // Returns the brand-specific safe browsing client name.
 std::string GetSafeBrowsingName();
 
+// Returns the hostname of the device management server url or an empty string
+// if the brand does not restrict runtime-configured server URLs.
+const char* GetDeviceManagementServerHostName();
+
 // Returns true if usage stats collecting is enabled for this user for the
 // current executable.
 bool GetCollectStatsConsent();
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 87a8027..101d034 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -1165,12 +1165,19 @@
     auto nonce = installer::DecodeNonceSwitchValue(
         cmd_line.GetSwitchValueASCII(installer::switches::kNonce));
 
-    // RotateDeviceTrustKey() expects a single threaded task runner so
-    // creating one here.
+    // In a stable build the rotate command should only permit a prod hostname.
+    const char* dm_server_host_name =
+        install_static::GetDeviceManagementServerHostName();
+    const bool is_valid_command =
+        !*dm_server_host_name ||
+        (dm_server_url.host_piece() == dm_server_host_name);
+
+    // RotateDeviceTrustKey() expects a single
+    // threaded task runner so creating one here.
     base::SingleThreadTaskExecutor executor;
 
     *exit_code =
-        token && nonce && dm_server_url.is_valid() &&
+        token && nonce && dm_server_url.is_valid() && is_valid_command &&
                 dm_server_url.SchemeIsHTTPOrHTTPS() &&
                 installer::RotateDeviceTrustKey(
                     enterprise_connectors::KeyRotationManager::Create(),
diff --git a/chrome/services/sharing/nearby/nearby_connections.cc b/chrome/services/sharing/nearby/nearby_connections.cc
index 8a51daf..987a284 100644
--- a/chrome/services/sharing/nearby/nearby_connections.cc
+++ b/chrome/services/sharing/nearby/nearby_connections.cc
@@ -437,7 +437,7 @@
 
             switch (info.status) {
               case PayloadProgressInfo::Status::kFailure:
-                FALLTHROUGH;
+                [[fallthrough]];
               case PayloadProgressInfo::Status::kCanceled:
                 buffer_manager_.StopTrackingFailedPayload(info.payload_id);
                 break;
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js b/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js
index 67ed4c4..7970d7b 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js
@@ -549,10 +549,11 @@
     ];
     service.setStates(states);
 
-    return service.setDeviceInformation('serial number', 1, 2).then((state) => {
-      assertEquals(state.state, State.kChooseDestination);
-      assertEquals(state.error, RmadErrorCode.kOk);
-    });
+    return service.setDeviceInformation('serial number', 1, 2, 3)
+        .then((state) => {
+          assertEquals(state.state, State.kChooseDestination);
+          assertEquals(state.error, RmadErrorCode.kOk);
+        });
   });
 
   test('GetCalibrationComponentList', () => {
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_device_information_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_device_information_page_test.js
index 99fa5ec..0a32e39 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_device_information_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_device_information_page_test.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js';
-import {fakeDeviceRegions, fakeDeviceSkus} from 'chrome://shimless-rma/fake_data.js';
+import {fakeDeviceRegions, fakeDeviceSkus, fakeDeviceWhiteLabels} from 'chrome://shimless-rma/fake_data.js';
 import {FakeShimlessRmaService} from 'chrome://shimless-rma/fake_shimless_rma_service.js';
 import {setShimlessRmaServiceForTesting} from 'chrome://shimless-rma/mojo_interface_provider.js';
 import {ReimagingDeviceInformationPage} from 'chrome://shimless-rma/reimaging_device_information_page.js';
@@ -22,6 +22,7 @@
  */
 function suppressedComponentOnSelectedChange_(component) {
   component.onSelectedRegionChange_('ignored');
+  component.onSelectedWhiteLabelChange_('ignored');
   component.onSelectedSkuChange_('ignored');
 }
 
@@ -51,11 +52,13 @@
    * @param {string} serialNumber
    * @return {!Promise}
    */
-  function initializeReimagingDeviceInformationPage(serialNumber) {
+  async function initializeReimagingDeviceInformationPage(serialNumber) {
     assertFalse(!!component);
     service.setGetOriginalSerialNumberResult(serialNumber);
     service.setGetRegionListResult(fakeDeviceRegions);
     service.setGetOriginalRegionResult(2);
+    service.setGetWhiteLabelListResult(fakeDeviceWhiteLabels);
+    service.setGetOriginalWhiteLabelResult(3);
     service.setGetSkuListResult(fakeDeviceSkus);
     service.setGetOriginalSkuResult(1);
 
@@ -64,46 +67,59 @@
     assertTrue(!!component);
     document.body.appendChild(component);
 
+    // A flush tasks is required to wait for the drop lists to render and set
+    // the initial selected index.
+    await flushTasks();
+
     return flushTasks();
   }
 
   test('ReimagingDeviceInformationPageInitializes', async () => {
     await initializeReimagingDeviceInformationPage(fakeSerialNumber);
-    // A flush tasks is required to wait for the drop lists to render and set
-    // the initial selected index.
-    await flushTasks();
+
     const serialNumberComponent =
         component.shadowRoot.querySelector('#serialNumber');
     const regionSelectComponent =
         component.shadowRoot.querySelector('#regionSelect');
+    const whiteLabelSelectComponent =
+        component.shadowRoot.querySelector('#whiteLabelSelect');
     const skuSelectComponent = component.shadowRoot.querySelector('#skuSelect');
     const resetSerialNumberComponent =
         component.shadowRoot.querySelector('#resetSerialNumber');
     const resetRegionComponent =
         component.shadowRoot.querySelector('#resetRegion');
+    const resetWhiteLabelComponent =
+        component.shadowRoot.querySelector('#resetWhiteLabel');
     const resetSkuComponent = component.shadowRoot.querySelector('#resetSku');
 
     assertEquals(fakeSerialNumber, serialNumberComponent.value);
     assertEquals(2, regionSelectComponent.selectedIndex);
+    assertEquals(3, whiteLabelSelectComponent.selectedIndex);
     assertEquals(1, skuSelectComponent.selectedIndex);
     assertTrue(resetSerialNumberComponent.disabled);
     assertTrue(resetRegionComponent.disabled);
+    assertTrue(resetWhiteLabelComponent.disabled);
     assertTrue(resetSkuComponent.disabled);
   });
 
-  test('ReimagingDeviceInformationPageInitializes', async () => {
+  test('ReimagingDeviceInformationPageNextReturnsInformation', async () => {
     const resolver = new PromiseResolver();
     await initializeReimagingDeviceInformationPage(fakeSerialNumber);
+
     const serialNumberComponent =
         component.shadowRoot.querySelector('#serialNumber');
     const regionSelectComponent =
         component.shadowRoot.querySelector('#regionSelect');
+    const whiteLabelSelectComponent =
+        component.shadowRoot.querySelector('#whiteLabelSelect');
     const skuSelectComponent = component.shadowRoot.querySelector('#skuSelect');
     let expectedSerialNumber = 'expected serial number';
     let expectedRegionIndex = 0;
+    let expectedWhiteLabelIndex = 1;
     let expectedSkuIndex = 2;
     serialNumberComponent.value = expectedSerialNumber;
     regionSelectComponent.selectedIndex = expectedRegionIndex;
+    whiteLabelSelectComponent.selectedIndex = expectedWhiteLabelIndex;
     skuSelectComponent.selectedIndex = expectedSkuIndex;
     // TODO(gavindodd) how to update selectedIndex and trigger on-change
     // automatically.
@@ -111,13 +127,16 @@
     await flushTasks();
     let serialNumber;
     let regionIndex;
+    let whiteLabelIndex;
     let skuIndex;
     let callCounter = 0;
     service.setDeviceInformation =
-        (resultSerialNumber, resultRegionIndex, resultSkuIndex) => {
+        (resultSerialNumber, resultRegionIndex, resultSkuIndex,
+         resultWhiteLabelIndex) => {
           callCounter++;
           serialNumber = resultSerialNumber;
           regionIndex = resultRegionIndex;
+          whiteLabelIndex = resultWhiteLabelIndex;
           skuIndex = resultSkuIndex;
           return resolver.promise;
         };
@@ -129,15 +148,17 @@
     resolver.resolve(expectedResult);
     await flushTasks();
 
-    assertEquals(callCounter, 1);
-    assertEquals(serialNumber, expectedSerialNumber);
-    assertEquals(regionIndex, expectedRegionIndex);
-    assertEquals(skuIndex, expectedSkuIndex);
-    assertDeepEquals(savedResult, expectedResult);
+    assertEquals(1, callCounter);
+    assertEquals(expectedSerialNumber, serialNumber);
+    assertEquals(expectedRegionIndex, regionIndex);
+    assertEquals(expectedWhiteLabelIndex, whiteLabelIndex);
+    assertEquals(expectedSkuIndex, skuIndex);
+    assertDeepEquals(expectedResult, savedResult);
   });
 
   test('ReimagingDeviceInformationPageModifySerialNumberAndReset', async () => {
     await initializeReimagingDeviceInformationPage(fakeSerialNumber);
+
     let serialNumber = fakeSerialNumber + 'new serial number';
     const serialNumberComponent =
         component.shadowRoot.querySelector('#serialNumber');
diff --git a/chrome/test/data/webui/tab_strip/tab_list_test.ts b/chrome/test/data/webui/tab_strip/tab_list_test.ts
index 86c01a2..54b5fd2 100644
--- a/chrome/test/data/webui/tab_strip/tab_list_test.ts
+++ b/chrome/test/data/webui/tab_strip/tab_list_test.ts
@@ -57,6 +57,11 @@
     return tabList.shadowRoot!.querySelectorAll('#unpinnedTabs tabstrip-tab');
   }
 
+  function getUnpinnedActiveTabs(): NodeListOf<TabElement> {
+    return tabList.shadowRoot!.querySelectorAll(
+        '#unpinnedTabs tabstrip-tab[active]');
+  }
+
   function getPinnedTabs(): NodeListOf<TabElement> {
     return tabList.shadowRoot!.querySelectorAll('#pinnedTabs tabstrip-tab');
   }
@@ -617,6 +622,24 @@
     assertFalse(tabElements[2]!.tab.active);
   });
 
+  test('SingleActiveTabOnActiveTabCreated', async () => {
+    let activeTabElements = getUnpinnedActiveTabs();
+    assertEquals(activeTabElements.length, 1);
+
+    const newActiveTab = createTab({
+      active: true,
+      id: tabs.length,
+      index: tabs.length - 1,
+      title: 'Tab 4',
+    });
+    callbackRouter.tabCreated(newActiveTab);
+    await flushTasks();
+
+    activeTabElements = getUnpinnedActiveTabs();
+    assertEquals(activeTabElements.length, 1);
+    assertEquals(activeTabElements[0]!.tab.id, newActiveTab.id);
+  });
+
   test('adds a pinned tab to its designated container', async () => {
     callbackRouter.tabCreated(createTab({
       id: tabs.length,
diff --git a/chrome/updater/tools/.style.yapf b/chrome/updater/.style.yapf
similarity index 100%
rename from chrome/updater/tools/.style.yapf
rename to chrome/updater/.style.yapf
diff --git a/chrome/updater/mac/embed_variables.py b/chrome/updater/mac/embed_variables.py
index b0ac883..9d5ec5a 100644
--- a/chrome/updater/mac/embed_variables.py
+++ b/chrome/updater/mac/embed_variables.py
@@ -30,18 +30,15 @@
 def parse_options():
     parser = optparse.OptionParser()
     parser.add_option('-i', '--input_file', help='Path to the input script.')
-    parser.add_option(
-        '-o',
-        '--output_file',
-        help='Path to where we should output the script')
-    parser.add_option(
-        '-v',
-        '--version',
-        help='Version of the application bundle being built.')
-    parser.add_option(
-        '-p',
-        '--product_full_name',
-        help='Name of the product being built.')
+    parser.add_option('-o',
+                      '--output_file',
+                      help='Path to where we should output the script')
+    parser.add_option('-v',
+                      '--version',
+                      help='Version of the application bundle being built.')
+    parser.add_option('-p',
+                      '--product_full_name',
+                      help='Name of the product being built.')
     options, _ = parser.parse_args()
 
     if not options.version and not options.product_full_name:
@@ -51,8 +48,8 @@
 
 
 def main(options):
-    embed_version(options.input_file, options.output_file,
-                  options.version, options.product_full_name)
+    embed_version(options.input_file, options.output_file, options.version,
+                  options.product_full_name)
     return 0
 
 
diff --git a/chrome/updater/mac/signing/pipeline.py b/chrome/updater/mac/signing/pipeline.py
index 4904aa2..e1df98cc 100644
--- a/chrome/updater/mac/signing/pipeline.py
+++ b/chrome/updater/mac/signing/pipeline.py
@@ -25,9 +25,8 @@
     commands.copy_files(os.path.join(paths.input, config.app_dir), paths.work)
     parts.sign_all(paths, config)
     commands.make_dir(dest_dir)
-    commands.move_file(
-        os.path.join(paths.work, config.app_dir),
-        os.path.join(dest_dir, config.app_dir))
+    commands.move_file(os.path.join(paths.work, config.app_dir),
+                       os.path.join(dest_dir, config.app_dir))
 
 
 def _package_and_sign_dmg(paths, config):
@@ -41,8 +40,9 @@
         The path to the signed DMG file.
     """
     dmg_path = _package_dmg(paths, config)
-    product = model.CodeSignedProduct(
-        dmg_path, config.packaging_basename, sign_with_identifier=True)
+    product = model.CodeSignedProduct(dmg_path,
+                                      config.packaging_basename,
+                                      sign_with_identifier=True)
     signing.sign_part(paths, config, product)
     signing.verify_part(paths, product)
     return dmg_path
diff --git a/chrome/updater/test/service/win/answer_uac.py b/chrome/updater/test/service/win/answer_uac.py
index 29c99c61..0e535fa 100644
--- a/chrome/updater/test/service/win/answer_uac.py
+++ b/chrome/updater/test/service/win/answer_uac.py
@@ -1,7 +1,6 @@
 # Copyright 2021 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.
-
 """A simple command to answer UAC prompt.
 
 To interact with UAC, we create this standalone program so that the process
@@ -23,45 +22,46 @@
 
 
 def _ParseCommandLine():
-  """Parse the command line arguments."""
-  cmd_parser = argparse.ArgumentParser(description='Window UAC prompt handler')
+    """Parse the command line arguments."""
+    cmd_parser = argparse.ArgumentParser(
+        description='Window UAC prompt handler')
 
-  cmd_parser.add_argument(
-      '--actions',
-      dest='actions',
-      type=str,
-      default='A',
-      help='How to handle UAC prompt, A for accept, D for deny.')
-  cmd_parser.add_argument(
-      '--timeout',
-      default=30,
-      type=float,
-      help='Time to wait for each UAC prompt before giving up.')
-  cmd_parser.add_argument(
-      '--source',
-      default='',
-      help='Name of the source that triggers UAC, optional (for logging).')
-  return cmd_parser.parse_args()
+    cmd_parser.add_argument(
+        '--actions',
+        dest='actions',
+        type=str,
+        default='A',
+        help='How to handle UAC prompt, A for accept, D for deny.')
+    cmd_parser.add_argument(
+        '--timeout',
+        default=30,
+        type=float,
+        help='Time to wait for each UAC prompt before giving up.')
+    cmd_parser.add_argument(
+        '--source',
+        default='',
+        help='Name of the source that triggers UAC, optional (for logging).')
+    return cmd_parser.parse_args()
 
 
 def main():
-  flags = _ParseCommandLine()
+    flags = _ParseCommandLine()
 
-  logging.info('Command run: %s', sys.argv)
+    logging.info('Command run: %s', sys.argv)
 
-  actions = flags.actions.upper()
-  for action in actions:
-    if action == 'A':  # Perform action 'Accept'
-      logging.info('Next UAC prompt will be accepted.')
-      accept = True
-    elif action == 'D':  # Perform action 'Deny'
-      logging.error('Next UAC prompt will be denied.')
-      accept = False
-    else:
-      logging.error('Unknown action for UAC prompt: [%s]', action)
-      continue
-    uac.AnswerUpcomingUACPrompt(accept, flags.timeout)
+    actions = flags.actions.upper()
+    for action in actions:
+        if action == 'A':  # Perform action 'Accept'
+            logging.info('Next UAC prompt will be accepted.')
+            accept = True
+        elif action == 'D':  # Perform action 'Deny'
+            logging.error('Next UAC prompt will be denied.')
+            accept = False
+        else:
+            logging.error('Unknown action for UAC prompt: [%s]', action)
+            continue
+        uac.AnswerUpcomingUACPrompt(accept, flags.timeout)
 
 
 if __name__ == '__main__':
-  main()
\ No newline at end of file
+    main()
diff --git a/chrome/updater/test/service/win/impersonate.py b/chrome/updater/test/service/win/impersonate.py
index d453d80..b4faee82 100644
--- a/chrome/updater/test/service/win/impersonate.py
+++ b/chrome/updater/test/service/win/impersonate.py
@@ -22,76 +22,79 @@
 
 import proc_util
 
-class ImpersonationError(Exception):
-  """Error representing impersonation error."""
 
-  pass
+class ImpersonationError(Exception):
+    """Error representing impersonation error."""
+
+    pass
 
 
 class _StdoutStderrPipes(object):
-  """Helper class to read stdout/stderr from child process."""
+    """Helper class to read stdout/stderr from child process."""
 
-  def __init__(self):
-    # Pipes to stream outputs.
-    security_attributes = win32security.SECURITY_ATTRIBUTES()
-    security_attributes.bInheritHandle = 1
-    stdout_r, stdout_w = win32pipe.CreatePipe(security_attributes, 0)
-    stderr_r, stderr_w = win32pipe.CreatePipe(security_attributes, 0)
-    self.stdout_r = stdout_r.Detach()
-    self.stdout_w = self._MakeInheritable(stdout_w)
-    self.stderr_r = stderr_r.Detach()
-    self.stderr_w = self._MakeInheritable(stderr_w)
+    def __init__(self):
+        # Pipes to stream outputs.
+        security_attributes = win32security.SECURITY_ATTRIBUTES()
+        security_attributes.bInheritHandle = 1
+        stdout_r, stdout_w = win32pipe.CreatePipe(security_attributes, 0)
+        stderr_r, stderr_w = win32pipe.CreatePipe(security_attributes, 0)
+        self.stdout_r = stdout_r.Detach()
+        self.stdout_w = self._MakeInheritable(stdout_w)
+        self.stderr_r = stderr_r.Detach()
+        self.stderr_w = self._MakeInheritable(stderr_w)
 
-    # Threads to read pipes and the actual contents returned.
-    self.stdout_read_thread = None
-    self.stdout = None
-    self.stderr_read_thread = None
-    self.stderr = None
+        # Threads to read pipes and the actual contents returned.
+        self.stdout_read_thread = None
+        self.stdout = None
+        self.stderr_read_thread = None
+        self.stderr = None
 
-  def _MakeInheritable(self, handle):
-    """Returns an inheritable duplicated handle."""
-    inheritable_handle = win32api.DuplicateHandle(
-        win32api.GetCurrentProcess(), handle, win32api.GetCurrentProcess(), 0,
-        1, win32con.DUPLICATE_SAME_ACCESS)
-    win32file.CloseHandle(handle)
-    return inheritable_handle
+    def _MakeInheritable(self, handle):
+        """Returns an inheritable duplicated handle."""
+        inheritable_handle = win32api.DuplicateHandle(
+            win32api.GetCurrentProcess(), handle, win32api.GetCurrentProcess(),
+            0, 1, win32con.DUPLICATE_SAME_ACCESS)
+        win32file.CloseHandle(handle)
+        return inheritable_handle
 
-  def _ReadStdout(self):
-    """Read content from the stdout pipe."""
-    try:
-      logging.info('Into read thread for STDOUT...')
-      stdout_buf = os.fdopen(msvcrt.open_osfhandle(self.stdout_r, 0), 'rt')
-      self.stdout = stdout_buf.read()
-    except Exception as err:
-      logging.exception(err)
+    def _ReadStdout(self):
+        """Read content from the stdout pipe."""
+        try:
+            logging.info('Into read thread for STDOUT...')
+            stdout_buf = os.fdopen(msvcrt.open_osfhandle(self.stdout_r, 0),
+                                   'rt')
+            self.stdout = stdout_buf.read()
+        except Exception as err:
+            logging.exception(err)
 
-  def _ReadStderr(self):
-    """Read content from the stderr pipe."""
-    try:
-      logging.info('Into read thread for STDERR...')
-      stderr_buf = os.fdopen(msvcrt.open_osfhandle(self.stderr_r, 0), 'rt')
-      self.stderr = stderr_buf.read()
-    except Exception as err:
-      logging.exception(err)
+    def _ReadStderr(self):
+        """Read content from the stderr pipe."""
+        try:
+            logging.info('Into read thread for STDERR...')
+            stderr_buf = os.fdopen(msvcrt.open_osfhandle(self.stderr_r, 0),
+                                   'rt')
+            self.stderr = stderr_buf.read()
+        except Exception as err:
+            logging.exception(err)
 
-  def ReadAll(self):
-    """Fork threads to read stdout/stderr."""
-    self.stdout_thread = threading.Thread(target=self._ReadStdout)
-    self.stdout_thread.setDaemon(True)
-    self.stdout_thread.start()
+    def ReadAll(self):
+        """Fork threads to read stdout/stderr."""
+        self.stdout_thread = threading.Thread(target=self._ReadStdout)
+        self.stdout_thread.setDaemon(True)
+        self.stdout_thread.start()
 
-    self.stderr_thread = threading.Thread(target=self._ReadStderr)
-    self.stderr_thread.setDaemon(True)
-    self.stderr_thread.start()
+        self.stderr_thread = threading.Thread(target=self._ReadStderr)
+        self.stderr_thread.setDaemon(True)
+        self.stderr_thread.start()
 
-  def CloseWriteHandles(self):
-    """Closes write handles.
+    def CloseWriteHandles(self):
+        """Closes write handles.
 
-    This is important to unblock readers: read threads will wait until all
-    write handles are closed.
-    """
-    win32file.CloseHandle(self.stdout_w)
-    win32file.CloseHandle(self.stderr_w)
+        This is important to unblock readers: read threads will wait until all
+        write handles are closed.
+        """
+        win32file.CloseHandle(self.stdout_w)
+        win32file.CloseHandle(self.stderr_w)
 
 
 def _RunAsOnWindowStationDesktop(command_line,
@@ -101,117 +104,120 @@
                                  env=None,
                                  cwd=None,
                                  timeout=win32event.INFINITE):
-  """Runs a command as the security token user on given desktop.
+    """Runs a command as the security token user on given desktop.
 
-  Args:
-    command_line: Full command line string to run.
-    security_token: Security token that the command run as.
-    window_station: Window station for the new process to run, tpically is
-       "WinSta0", aka the interactive window station.
-    desktop: Desktop that the new process will be associatedw with, typically is
-      'default'.
-    env: The environment variables to pass to the child process, or None to
-      inherit from parent.
-    cwd: The working directory of the child process, or None to inherit from
-      parent.
-    timeout: How long should wait for child process. 0 means no wait, None means
-      infinitely.
+    Args:
+        command_line: Full command line string to run.
+        security_token: Security token that the command run as.
+        window_station: Window station for the new process to run, tpically is
+                        "WinSta0", aka the interactive window station.
+        desktop: Desktop that the new process will be associatedw with,
+                 typically is 'default'.
+        env: The environment variables to pass to the child process, or None to
+             inherit from parent.
+        cwd: The working directory of the child process, or None to inherit from
+             parent.
+        timeout: How long should wait for child process. 0 means no wait,
+                 None means infinitely.
 
-  Returns:
-    (pid, exit_code, stdout, stderr) tuple.
+    Returns:
+        (pid, exit_code, stdout, stderr) tuple.
 
-  Raises:
-    ImpersonationError: when impersonation failed.
-  """
-  pipes = _StdoutStderrPipes()
-  si = win32process.STARTUPINFO()
-  si.dwFlags = win32process.STARTF_USESHOWWINDOW | win32con.STARTF_USESTDHANDLES
-  si.wShowWindow = win32con.SW_SHOW
-  si.lpDesktop = '%s\\%s' % (window_station, desktop)
-  si.hStdOutput = pipes.stdout_w
-  si.hStdError = pipes.stderr_w
-  create_flags = (
-      win32process.CREATE_NEW_CONSOLE | win32process.CREATE_UNICODE_ENVIRONMENT)
+    Raises:
+        ImpersonationError: when impersonation failed.
+    """
+    pipes = _StdoutStderrPipes()
+    si = win32process.STARTUPINFO()
+    si.dwFlags = (win32process.STARTF_USESHOWWINDOW
+                  | win32con.STARTF_USESTDHANDLES)
+    si.wShowWindow = win32con.SW_SHOW
+    si.lpDesktop = '%s\\%s' % (window_station, desktop)
+    si.hStdOutput = pipes.stdout_w
+    si.hStdError = pipes.stderr_w
+    create_flags = (win32process.CREATE_NEW_CONSOLE
+                    | win32process.CREATE_UNICODE_ENVIRONMENT)
 
-  if env:
-    saved_env = dict(os.environ)
-    os.environ.update(env)
-  env_block = win32profile.CreateEnvironmentBlock(security_token, True)
-  (process_handle, unused_thread, pid,
-   unused_thread_id) = win32process.CreateProcessAsUser(
-       security_token, None, command_line, None, None, 1,
-       create_flags, env_block, cwd, si)
-  if env:
-    os.environ.clear()
-    os.environ.update(saved_env)
-  pipes.CloseWriteHandles()
-  if not process_handle:
-    logging.error('Failed to create child process [%s] on [%s\\%s]',
-                  command_line, window_station, desktop)
-    raise ImpersonationError(
-        'Failed to create process [%s] with impersonation: [%s\\%s][%s]' %
-        (command_line, window_station, desktop, cwd))
+    if env:
+        saved_env = dict(os.environ)
+        os.environ.update(env)
+    env_block = win32profile.CreateEnvironmentBlock(security_token, True)
+    (process_handle, unused_thread, pid,
+     unused_thread_id) = win32process.CreateProcessAsUser(
+         security_token, None, command_line, None, None, 1, create_flags,
+         env_block, cwd, si)
+    if env:
+        os.environ.clear()
+        os.environ.update(saved_env)
+    pipes.CloseWriteHandles()
+    if not process_handle:
+        logging.error('Failed to create child process [%s] on [%s\\%s]',
+                      command_line, window_station, desktop)
+        raise ImpersonationError(
+            'Failed to create process [%s] with impersonation: [%s\\%s][%s]' %
+            (command_line, window_station, desktop, cwd))
 
-  pipes.ReadAll()
-  logging.info('Child process [%s] created on [%s\\%s]',
-      command_line, window_station, desktop)
-  logging.info('Waiting %s seconds for child process.', timeout)
-  if timeout != win32event.INFINITE:
-    timeout *= 1000  # Convert from seconds to milli-seconds.
-  wait_result = win32event.WaitForSingleObject(process_handle, timeout * 1000)
-  if wait_result == win32event.WAIT_OBJECT_0:
-    exit_code = win32process.GetExitCodeProcess(process_handle)
-    logging.info('Child process exited with code %s.', exit_code)
-    logging.info('Child process STDOUT: %s', pipes.stdout)
-    logging.error('Child process STDERR: %s.', pipes.stderr)
-    return (pid, exit_code, pipes.stdout, pipes.stderr)
-  else:
-    if timeout != 0:
-      logging.warning('Wait for child process timeout in %s seconds',
-                      timeout / 1000)
-    return (pid, None, None, None)
+    pipes.ReadAll()
+    logging.info('Child process [%s] created on [%s\\%s]', command_line,
+                 window_station, desktop)
+    logging.info('Waiting %s seconds for child process.', timeout)
+    if timeout != win32event.INFINITE:
+        timeout *= 1000  # Convert from seconds to milli-seconds.
+    wait_result = win32event.WaitForSingleObject(process_handle,
+                                                 timeout * 1000)
+    if wait_result == win32event.WAIT_OBJECT_0:
+        exit_code = win32process.GetExitCodeProcess(process_handle)
+        logging.info('Child process exited with code %s.', exit_code)
+        logging.info('Child process STDOUT: %s', pipes.stdout)
+        logging.error('Child process STDERR: %s.', pipes.stderr)
+        return (pid, exit_code, pipes.stdout, pipes.stderr)
+    else:
+        if timeout != 0:
+            logging.warning('Wait for child process timeout in %s seconds',
+                            timeout / 1000)
+        return (pid, None, None, None)
 
 
 def RunAsStandardUser(command_line, env, cwd, timeout):
-  """Runs a command as non-elevated logged-on user.
+    """Runs a command as non-elevated logged-on user.
 
-  Args:
-    command_line: The command line string, including arguments, to run.
-    env: Environment variables for child process, None to inherit.
-    cwd: Working directory for child process, None to inherit from parent.
-    timeout: How long in seconds should wait for child process.
+    Args:
+        command_line: The command line string, including arguments, to run.
+        env: Environment variables for child process, None to inherit.
+        cwd: Working directory for child process, None to inherit from parent.
+        timeout: How long in seconds should wait for child process.
 
-  Returns:
-      (pid, exit_code, sdtout, stderr) tuple.
+    Returns:
+        (pid, exit_code, sdtout, stderr) tuple.
 
-  Raises:
-    ImpersonationError: when impersonation failed.
-  """
-  logging.info('Running "%s" as the logon user.', command_line)
+    Raises:
+        ImpersonationError: when impersonation failed.
+    """
+    logging.info('Running "%s" as the logon user.', command_line)
 
-  # Adjust current process to be part of the trusted computer base.
-  current_process_token = win32security.OpenProcessToken(
-      win32api.GetCurrentProcess(), win32security.TOKEN_ALL_ACCESS)
-  tcb_privilege_flag = win32security.LookupPrivilegeValue(
-      None, win32security.SE_TCB_NAME)
-  se_enable = win32security.SE_PRIVILEGE_ENABLED
-  win32security.AdjustTokenPrivileges(current_process_token, 0,
-                                      [(tcb_privilege_flag, se_enable)])
+    # Adjust current process to be part of the trusted computer base.
+    current_process_token = win32security.OpenProcessToken(
+        win32api.GetCurrentProcess(), win32security.TOKEN_ALL_ACCESS)
+    tcb_privilege_flag = win32security.LookupPrivilegeValue(
+        None, win32security.SE_TCB_NAME)
+    se_enable = win32security.SE_PRIVILEGE_ENABLED
+    win32security.AdjustTokenPrivileges(current_process_token, 0,
+                                        [(tcb_privilege_flag, se_enable)])
 
-  active_session_id = proc_util.GetActiveSessionID()
-  if not active_session_id:
-    raise ImpersonationError('Cannot find active logon session.')
+    active_session_id = proc_util.GetActiveSessionID()
+    if not active_session_id:
+        raise ImpersonationError('Cannot find active logon session.')
 
-  try:
-    logon_user_token = win32ts.WTSQueryUserToken(active_session_id)
-  except pywintypes.error as err:
-    if err.winerror == winerror.ERROR_NO_TOKEN:
-      raise ImpersonationError('No user is logged on.')
-    else:
-      raise ImpersonationError('Failed to get user token: %s' % err)
+    try:
+        logon_user_token = win32ts.WTSQueryUserToken(active_session_id)
+    except pywintypes.error as err:
+        if err.winerror == winerror.ERROR_NO_TOKEN:
+            raise ImpersonationError('No user is logged on.')
+        else:
+            raise ImpersonationError('Failed to get user token: %s' % err)
 
-  return _RunAsOnWindowStationDesktop(
-      command_line, logon_user_token, 'WinSta0', 'default', env, cwd, timeout)
+    return _RunAsOnWindowStationDesktop(command_line, logon_user_token,
+                                        'WinSta0', 'default', env, cwd,
+                                        timeout)
 
 
 def RunAsPidOnDeskstop(command_line,
@@ -221,41 +227,42 @@
                        env=None,
                        cwd=None,
                        timeout=win32event.INFINITE):
-  """Runs a command with pid's security token and on the given desktop.
+    """Runs a command with pid's security token and on the given desktop.
 
-  Args:
-    command_line: The command line string, including arguments, to run.
-    pid: ID of the process to get the security token from.
-    window_station: Window station for the new process to run, tpically is
-       "WinSta0", aka the interactive window station.
-    desktop: Desktop that the new process will be associatedw with, typically is
-      'default'. If the command needs to interact with UAC prompt on secure
-      desktop, pass 'winlogon'.
-    env: The environment variables to pass to the child process, or None to
-      inherit from parent.
-    cwd: The working directory of the child process, or None to inherit from
-      parent.
-    timeout: How long in seconds to wait for child process.
+    Args:
+        command_line: The command line string, including arguments, to run.
+        pid: ID of the process to get the security token from.
+        window_station: Window station for the new process to run, tpically is
+           "WinSta0", aka the interactive window station.
+        desktop: Desktop that the new process will be associatedw with,
+                 typically is 'default'. If the command needs to interact with
+                 UAC prompt on secure desktop, pass 'winlogon'.
+        env: The environment variables to pass to the child process, or None to
+             inherit from parent.
+        cwd: The working directory of the child process, or None to inherit from
+             parent.
+        timeout: How long in seconds to wait for child process.
 
-  Returns:
-    (pid, exit_code, stdout, stderr) tuple.
-  """
+    Returns:
+        (pid, exit_code, stdout, stderr) tuple.
+    """
 
-  logging.info('RunAsPidOnDeskstop: [%s][%s]', pid, command_line)
+    logging.info('RunAsPidOnDeskstop: [%s][%s]', pid, command_line)
 
-  process_handle = None
-  token_handle = None
-  try:
-    process_handle = win32api.OpenProcess(win32con.GENERIC_ALL, False, pid)
-    token_handle = win32security.OpenProcessToken(process_handle,
-                                                  win32con.TOKEN_ALL_ACCESS)
-    return _RunAsOnWindowStationDesktop(
-        command_line, token_handle, window_station, desktop, env, cwd, timeout)
-  except (pywintypes.error, ImpersonationError) as err:
-    logging.error(err)
-    return (None, None, None, None)
-  finally:
-    if process_handle:
-      process_handle.Close()
-    if token_handle:
-      token_handle.Close()
+    process_handle = None
+    token_handle = None
+    try:
+        process_handle = win32api.OpenProcess(win32con.GENERIC_ALL, False, pid)
+        token_handle = win32security.OpenProcessToken(
+            process_handle, win32con.TOKEN_ALL_ACCESS)
+        return _RunAsOnWindowStationDesktop(command_line, token_handle,
+                                            window_station, desktop, env, cwd,
+                                            timeout)
+    except (pywintypes.error, ImpersonationError) as err:
+        logging.error(err)
+        return (None, None, None, None)
+    finally:
+        if process_handle:
+            process_handle.Close()
+        if token_handle:
+            token_handle.Close()
diff --git a/chrome/updater/test/service/win/proc_util.py b/chrome/updater/test/service/win/proc_util.py
index 32eb655..e336663 100644
--- a/chrome/updater/test/service/win/proc_util.py
+++ b/chrome/updater/test/service/win/proc_util.py
@@ -10,36 +10,38 @@
 
 
 def GetActiveSessionID():
-  """Get the active session ID."""
-  local_server = win32ts.WTS_CURRENT_SERVER_HANDLE
-  for session in win32ts.WTSEnumerateSessions(local_server):
-    if session['State'] == win32ts.WTSActive:
-      return session['SessionId']
+    """Get the active session ID."""
+    local_server = win32ts.WTS_CURRENT_SERVER_HANDLE
+    for session in win32ts.WTSEnumerateSessions(local_server):
+        if session['State'] == win32ts.WTSActive:
+            return session['SessionId']
 
-  logging.warning('Unexpected: no active session.')
-  return None
+    logging.warning('Unexpected: no active session.')
+    return None
 
 
 def GetPIDsWithName(image_name, session=None):
-  """Gets all process PIDs, with the given image name.
+    """Gets all process PIDs, with the given image name.
 
-  Args:
-    image_name: Case-insensitive process image name.
-    session: Session filter. Only search processes within given session.
-        None means no filter.
+    Args:
+        image_name: Case-insensitive process image name.
+        session: Session filter. Only search processes within given session.
+            None means no filter.
 
-  Returns:
-    A list of process ID.
-  """
-  cmd = ['tasklist', '/FO:csv', '/NH', '/FI', 'IMAGENAME eq %s' % image_name]
-  if session is not None:
-    cmd.extend(['/FI', 'SESSION eq %s' % session])
-  proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    Returns:
+        A list of process ID.
+    """
+    cmd = ['tasklist', '/FO:csv', '/NH', '/FI', 'IMAGENAME eq %s' % image_name]
+    if session is not None:
+        cmd.extend(['/FI', 'SESSION eq %s' % session])
+    proc = subprocess.Popen(cmd,
+                            stdout=subprocess.PIPE,
+                            stderr=subprocess.PIPE)
 
-  stdout, stderr = proc.communicate()
-  if proc.returncode != 0:
-    logging.error('Unable to list processes, %s', stderr)
-    return []
+    stdout, stderr = proc.communicate()
+    if proc.returncode != 0:
+        logging.error('Unable to list processes, %s', stderr)
+        return []
 
-  stdout = stdout.decode('ascii').splitlines()
-  return [int(row[1]) for row in csv.reader(stdout, delimiter=',')]
+    stdout = stdout.decode('ascii').splitlines()
+    return [int(row[1]) for row in csv.reader(stdout, delimiter=',')]
diff --git a/chrome/updater/test/service/win/rpc_client.py b/chrome/updater/test/service/win/rpc_client.py
index 6c02cc3..3546e97 100644
--- a/chrome/updater/test/service/win/rpc_client.py
+++ b/chrome/updater/test/service/win/rpc_client.py
@@ -8,99 +8,97 @@
 import sys
 import xmlrpc.client
 
-
 # TODO(crbug.com/1233612): Query XML RPC server port once the server propgate
 # the value.
 _UPDATER_XML_RPC_PORT = 9090
 
-
 # Errors that might be raised when interacting with the RPC server.
 RPCErrors = (socket.error, socket.herror, socket.gaierror, socket.timeout)
 
 
 def GetProxy():
-  """Constructs a XML RPC server proxy."""
-  return xmlrpc.client.ServerProxy(
-      'http://localhost:%s' % _UPDATER_XML_RPC_PORT)
+    """Constructs a XML RPC server proxy."""
+    return xmlrpc.client.ServerProxy('http://localhost:%s' %
+                                     _UPDATER_XML_RPC_PORT)
 
 
 def TestConnection():
-  """Test that connection to the XML RPC server."""
-  try:
-    proxy = GetProxy()
-    return 'hi' == proxy.echo('hi')
-  except RPCErrors as err:
-    logging.error('Unable connect to XML RPC server')
-    logging.exception(err)
-    return False
+    """Test that connection to the XML RPC server."""
+    try:
+        proxy = GetProxy()
+        return 'hi' == proxy.echo('hi')
+    except RPCErrors as err:
+        logging.error('Unable connect to XML RPC server')
+        logging.exception(err)
+        return False
 
 
 def RunAsSystem(command, env=None, cwd=None, timeout=90):
-  """Runs the command as SYSTEM user.
+    """Runs the command as SYSTEM user.
 
-  Args:
-    command: The command to run. This argument will be forwarded to
-      subprocess.Popen().
-    env: Environment variables to pass to command.
-    cwd: Working directory for the command.
-    timeout: How long the child process should wait for UAC before timeout.
+    Args:
+        command: The command to run. This argument will be forwarded to
+          subprocess.Popen().
+        env: Environment variables to pass to command.
+        cwd: Working directory for the command.
+        timeout: How long the child process should wait for UAC before timeout.
 
-  Returns:
-    (pid, exit_code, sdtout, stderr) tuple.
-  """
-  try:
-    proxy = GetProxy()
-    env = env or dict(os.environ)
-    cwd = cwd or os.getcwd()
-    return proxy.RunAsSystem(command, env, cwd, timeout)
-  except RPCErrors as err:
-    logging.exception(err)
-    raise
+    Returns:
+        (pid, exit_code, sdtout, stderr) tuple.
+    """
+    try:
+        proxy = GetProxy()
+        env = env or dict(os.environ)
+        cwd = cwd or os.getcwd()
+        return proxy.RunAsSystem(command, env, cwd, timeout)
+    except RPCErrors as err:
+        logging.exception(err)
+        raise
 
 
 def RunAsStandardUser(command_line, env=None, cwd=None, timeout=90):
-  """Runs the command as the non-elevated logged-on user on default desktop.
+    """Runs the command as the non-elevated logged-on user on default desktop.
 
-  Args:
-    command_line: The command line string, includes all arguments.
-    env: Environment variables to pass to command.
-    cwd: Working directory for the command.
-    timeout: How long the child process should wait before timeout.
+    Args:
+        command_line: The command line string, includes all arguments.
+        env: Environment variables to pass to command.
+        cwd: Working directory for the command.
+        timeout: How long the child process should wait before timeout.
 
-  Returns:
-    (pid, exit_code, sdtout, stderr) tuple.
-  """
-  try:
-    proxy = GetProxy()
-    env = env or dict(os.environ)
-    cwd = cwd or os.getcwd()
-    return proxy.RunAsStandardUser(command_line, env, cwd, timeout)
-  except RPCErrors as err:
-    logging.exception(err)
-    raise
+    Returns:
+        (pid, exit_code, sdtout, stderr) tuple.
+    """
+    try:
+        proxy = GetProxy()
+        env = env or dict(os.environ)
+        cwd = cwd or os.getcwd()
+        return proxy.RunAsStandardUser(command_line, env, cwd, timeout)
+    except RPCErrors as err:
+        logging.exception(err)
+        raise
 
 
-def AnswerUpcomingUACPrompt(actions,
-                            timeout=10,
-                            wait_child=False,
-                            source=''):
-  """Answers upcoming UAC prompt that does not require username/password.
+def AnswerUpcomingUACPrompt(actions, timeout=10, wait_child=False, source=''):
+    """Answers upcoming UAC prompt that does not require username/password.
 
-  Args:
-    actions: Actions to take in string, such as 'AADDA', 'A' to accept,
-        'D' to deny.
-    timeout: How long the child process should wait for each UAC click.
-    wait_child: Whether this thread should wait the completion of child proc.
-    source: Optional name of the source that triggers this action (for logging
-        and debugging purpose).
+    Args:
+        actions: Actions to take in string, such as 'AADDA', 'A' to accept,
+            'D' to deny.
+        timeout: How long the child process should wait for each UAC click.
+        wait_child: Whether this thread should wait the completion of
+                    the child process.
+        source: Optional name of the source that triggers this action
+                (for logging and debugging purposes).
 
-  Returns:
-    (pid, exit_code) of the created UAC-answering process. If the sub-process
-    is not created, or did not finish in wait time, returns (None, None).
-  """
-  try:
-    proxy = GetProxy()
-    return proxy.AnswerUpcomingUACPrompt(actions, timeout, wait_child, source)
-  except RPCErrors as err:
-    logging.exception(err)
-    raise
+    Returns:
+        (pid, exit_code) of the created UAC-answering process.
+        If the sub-process is not created, or did not finish in wait time,
+        returns (None, None).
+    """
+    try:
+        proxy = GetProxy()
+        return proxy.AnswerUpcomingUACPrompt(actions, timeout, wait_child,
+                                             source)
+    except RPCErrors as err:
+        logging.exception(err)
+        raise
diff --git a/chrome/updater/test/service/win/rpc_handler.py b/chrome/updater/test/service/win/rpc_handler.py
index b4688cf2..0acfaf8 100644
--- a/chrome/updater/test/service/win/rpc_handler.py
+++ b/chrome/updater/test/service/win/rpc_handler.py
@@ -11,120 +11,129 @@
 import proc_util
 import uac
 
+
 class UpdaterTestRPCHandler():
+    def echo(self, message):
+        """Test method to check if server is reachable."""
+        return message
 
-  def echo(self, message):
-    """Test method to check if server is reachable."""
-    return message
+    def RunAsSystem(self, command, env=None, cwd=None, timeout=30):
+        """Runs the command as SYSTEM user.
 
-  def RunAsSystem(self, command, env=None, cwd=None, timeout=30):
-    """Runs the command as SYSTEM user.
+      Args:
+          command: The command to run. This argument will be forwarded to
+            subprocess.Popen().
+          env: Environment variables to pass to command.
+          cwd: Working directory for the command.
+          timeout: How long the child process should wait before timeout.
 
-    Args:
-      command: The command to run. This argument will be forwarded to
-        subprocess.Popen().
-      env: Environment variables to pass to command.
-      cwd: Working directory for the command.
-      timeout: How long the child process should wait before timeout.
+      Returns:
+          (pid, exit_code, sdtout, stderr) tuple.
+      """
+        try:
+            process = subprocess.Popen(command,
+                                       stdout=subprocess.PIPE,
+                                       stderr=subprocess.PIPE,
+                                       env=env,
+                                       cwd=cwd)
 
-    Returns:
-      (pid, exit_code, sdtout, stderr) tuple.
-    """
-    try:
-      process = subprocess.Popen(
-          command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
-          env=env, cwd=cwd)
+            # TODO(crbug.com/1233612): `communicate()` in Python 2.7 does not
+            # support timeout value, pass the value here once we migrate
+            # to Python 3. Also don't forget to handle subprocess.TimeoutExpired
+            # exception.
+            stdout, stderr = process.communicate()
+            logging.info('Command %s stdout:\n %s', command, stdout)
+            if stderr:
+                logging.error('Command %s stderr:\n %s', command, stderr)
 
-      # TODO(crbug.com/1233612): `communicate()` in Python 2.7 does not support
-      # timeout value, pass the value here once we migrate to Python 3. Also
-      # don't forget to handle subprocess.TimeoutExpired exception.
-      stdout, stderr = process.communicate()
-      logging.info('Command %s stdout:\n %s', command, stdout)
-      if stderr:
-        logging.error('Command %s stderr:\n %s', command, stderr)
+            return (process.pid, process.returncode, stdout, stderr)
+        except OSError as err:
+            logging.exception(err)
+            return (None, None, None, None)
 
-      return (process.pid, process.returncode, stdout, stderr)
-    except OSError as err:
-      logging.exception(err)
-      return (None, None, None, None)
+    def RunAsStandardUser(self, command_line, env=None, cwd=None, timeout=30):
+        """Runs the command as the non-elevated logon user on default desktop.
 
-  def RunAsStandardUser(self, command_line, env=None, cwd=None, timeout=30):
-    """Runs the command as the non-elevated logon user on default desktop.
+      Args:
+          command_line: The command line string, includes all arguments.
+          env: Environment variables to pass to command.
+          cwd: Working directory for the command.
+          timeout: How long the child process should wait before timeout.
 
-    Args:
-      command_line: The command line string, includes all arguments.
-      env: Environment variables to pass to command.
-      cwd: Working directory for the command.
-      timeout: How long the child process should wait before timeout.
+      Returns:
+          (pid, exit_code, sdtout, stderr) tuple.
+      """
+        return impersonate.RunAsStandardUser(command_line, env, cwd, timeout)
 
-    Returns:
-      (pid, exit_code, sdtout, stderr) tuple.
-    """
-    return impersonate.RunAsStandardUser(command_line, env, cwd, timeout)
+    def AnswerUpcomingUACPrompt(self,
+                                actions,
+                                timeout=10,
+                                wait_child=False,
+                                source=''):
+        """Answers upcoming UAC prompt that does not require username/password.
 
-  def AnswerUpcomingUACPrompt(self,
-                              actions,
-                              timeout=10,
-                              wait_child=False,
-                              source=''):
-    """Answers upcoming UAC prompt that does not require username/password.
+        Args:
+            actions: Actions to take in string, such as 'AADDA', 'A' to accept,
+                     'D' to deny.
+            timeout: How long the child process should wait for each UAC click.
+            wait_child: Whether this thread should wait the completion of child
+                        proc.
+            source: Optional name of the source that triggers this action
+                    (for logging and debugging purposes).
 
-    Args:
-      actions: Actions to take in string, such as 'AADDA', 'A' to accept,
-          'D' to deny.
-      timeout: How long the child process should wait for each UAC click.
-      wait_child: Whether this thread should wait the completion of child proc.
-      source: Optional name of the source that triggers this action (for logging
-          and debugging purpose).
+        Returns:
+            (pid, exit_code) of the created UAC-answering process.
+            If the sub-process is not created, or did not finish in wait time,
+            returns (None, None).
+        """
+        uac_tool = os.path.join(os.path.dirname(__file__), 'answer_uac.py')
+        command = ('python %s --actions=%s --timeout=%d --source=%s' %
+                   (uac_tool, actions, timeout, source))
+        logging.info('Running command: %s', command)
 
-    Returns:
-      (pid, exit_code) of the created UAC-answering process. If the sub-process
-      is not created, or did not finish in wait time, returns (None, None).
-    """
-    uac_tool = os.path.join(os.path.dirname(__file__), 'answer_uac.py')
-    command = ('python %s --actions=%s --timeout=%d --source=%s' %
-               (uac_tool, actions, timeout, source))
-    logging.info('Running command: %s', command)
+        if wait_child:
+            if timeout > 0:
+                # Each button click could take `timeout` seconds, and add
+                # 1 second extra for child process to finish.
+                timeout = timeout * len(actions) + 1
+            else:
+                # Negative timeout has special meanings, such as
+                # win32event.INFINITE.
+                # Don't touch it.
+                pass
+        else:
+            timeout = 0  # no wait
 
-    if wait_child:
-      if timeout > 0:
-        # Each button click could take `timeout` seconds, and add 1 second
-        # extra for child process to finish.
-        timeout = timeout * len(actions) + 1
-      else:
-        # Negative timeout has special meanings, such as win32event.INFINITE.
-        # Don't touch it.
-        pass
-    else:
-      timeout = 0  # no wait
+        # There could be multiple winlogon.exe instances when there are multiple
+        # login sessions. For example, when there's remote desktop session.
+        # In this case, find the active session where the UAC prompt is supposed
+        # to display.
+        winlogon_pids = proc_util.GetPIDsWithName(
+            'winlogon.exe', proc_util.GetActiveSessionID())
+        if not winlogon_pids:
+            logging.error(
+                'Unexpected: no active session or no winlogon.exe in it.')
+            return (None, None)
+        elif len(winlogon_pids) > 1:
+            logging.warning(
+                'Unexpected multiple winlogon.exe instances within '
+                'active session, the first instance will be used.')
 
-    # There could be multiple winlogon.exe instances when there are multiple
-    # login sessions. For example, when there's remote desktop session. In this
-    # case, find the active session where the UAC prompt is supposed to display.
-    winlogon_pids = proc_util.GetPIDsWithName('winlogon.exe',
-                                              proc_util.GetActiveSessionID())
-    if not winlogon_pids:
-      logging.error('Unexpected: no active session or no winlogon.exe in it.')
-      return (None, None)
-    elif len(winlogon_pids) > 1:
-      logging.warning('Unexpected multiple winlogon.exe instances within '
-                      'active session, the first instance will be used.')
+        # Must spawn child process on the same desktop as the one that UAC
+        # prompts, otherwise the child process will not be able to find the UAC
+        # dialog. Please note that there is a slight race condition here as user
+        # could change UAC desktop at any time. But we can tolerate this for the
+        # testing purpose.
+        desktop = 'winlogon' if uac.IsPromptingOnSecureDesktop() else 'default'
 
-    # Must spawn child process on the same desktop as the one that UAC prompts,
-    # otherwise the child process will not be able to find the UAC dialog.
-    # Please note that there is a slight race condition here as user could
-    # change UAC desktop at any time. But we can tolerate this for the testing
-    # purpose.
-    desktop = 'winlogon' if uac.IsPromptingOnSecureDesktop() else 'default'
-
-    logging.info('Spawn process [%s] for UAC on desktop [%s].',
-                 command, desktop)
-    pid, exit_code, stdout, stderr = impersonate.RunAsPidOnDeskstop(
-        command, winlogon_pids[0], desktop=desktop, timeout=timeout)
-    logging.info('Process [%s] is created to answer UAC, exit_code: %s', pid,
-                 exit_code)
-    if stdout and stdout.strip():
-      logging.info('STDOUT: [%s]', stdout)
-    if stderr and stderr.strip():
-      logging.error('STDERR: [%s]', stderr)
-    return (pid, exit_code)
\ No newline at end of file
+        logging.info('Spawn process [%s] for UAC on desktop [%s].', command,
+                     desktop)
+        pid, exit_code, stdout, stderr = impersonate.RunAsPidOnDeskstop(
+            command, winlogon_pids[0], desktop=desktop, timeout=timeout)
+        logging.info('Process [%s] is created to answer UAC, exit_code: %s',
+                     pid, exit_code)
+        if stdout and stdout.strip():
+            logging.info('STDOUT: [%s]', stdout)
+        if stderr and stderr.strip():
+            logging.error('STDERR: [%s]', stderr)
+        return (pid, exit_code)
diff --git a/chrome/updater/test/service/win/run_command_as_standard_user.py b/chrome/updater/test/service/win/run_command_as_standard_user.py
index f95c5453..f5f7cdb 100644
--- a/chrome/updater/test/service/win/run_command_as_standard_user.py
+++ b/chrome/updater/test/service/win/run_command_as_standard_user.py
@@ -9,7 +9,6 @@
 #    version: "version:300"
 # >
 # [VPYTHON:END]
-
 """Run the given command as the standard user.
 
 All arguments provided to this program will be used to reconstruct the command
@@ -32,68 +31,67 @@
 import updater_test_service_control
 
 
-
 def ParseCommandLine():
-  """Parse the command line arguments."""
-  cmd_parser = argparse.ArgumentParser(description='Run command as user')
+    """Parse the command line arguments."""
+    cmd_parser = argparse.ArgumentParser(description='Run command as user')
 
-  cmd_parser.add_argument(
-      '--command',
-      dest='command',
-      type=str,
-      help='The command to run.')
-  return cmd_parser.parse_known_args()
+    cmd_parser.add_argument('--command',
+                            dest='command',
+                            type=str,
+                            help='The command to run.')
+    return cmd_parser.parse_known_args()
 
 
 def LogToSTDERR(title, output):
-  if not output:
-    return
+    if not output:
+        return
 
-  logging.error('%s %s starts %s', '=' * 30, title, '=' * 30)
+    logging.error('%s %s starts %s', '=' * 30, title, '=' * 30)
 
-  # Directly dump the output to STDERR so we don't have logging prefix each
-  # line, to make it easier to read.
-  sys.stderr.write(output)
+    # Directly dump the output to STDERR so we don't have logging prefix each
+    # line, to make it easier to read.
+    sys.stderr.write(output)
 
-  logging.error('%s  %s ends  %s', '=' * 30, title, '=' * 30)
+    logging.error('%s  %s ends  %s', '=' * 30, title, '=' * 30)
 
 
 def main():
-  flags, remaining_args = ParseCommandLine()
+    flags, remaining_args = ParseCommandLine()
 
-  if not flags.command:
-    logging.error('Must specify a command to run.')
-    sys.exit(-1)
+    if not flags.command:
+        logging.error('Must specify a command to run.')
+        sys.exit(-1)
 
-  # Find the location of the command. shutil.which() looks suitable for this,
-  # only if https://bugs.python.org/issue24505 is closed. For now, use the
-  # one from distutils module.
-  command = distutils.spawn.find_executable(flags.command)
-  if not command:
-    logging.error('Cannot find command: %s', flags.command)
-    sys.exit(-2)
+    # Find the location of the command. shutil.which() looks suitable for this,
+    # only if https://bugs.python.org/issue24505 is closed. For now, use the
+    # one from distutils module.
+    command = distutils.spawn.find_executable(flags.command)
+    if not command:
+        logging.error('Cannot find command: %s', flags.command)
+        sys.exit(-2)
 
-  # Command may be in relative path. Make it absolute so that the RPC server
-  # can find it.
-  command = os.path.abspath(command)
+    # Command may be in relative path. Make it absolute so that the RPC server
+    # can find it.
+    command = os.path.abspath(command)
 
-  # RunAsStandardUser() takes a full command line string (as it is forwarded to
-  # the underlying win32 implementation). We have sys.argv, but the value is
-  # already processed by shell. It is possible that the reconstructed command
-  # line is skewed (for example, expansion of environment variable), but
-  # hopefully this works well enough in all real scenarios.
-  command_line = subprocess.list2cmdline([command] + remaining_args)
-  logging.error('Full command line: %s', command_line)
-  with updater_test_service_control.OpenService():
-    pid, exit_code, stdout, stderr = rpc_client.RunAsStandardUser(command_line)
-    if pid is None:
-      logging.error('Failed to launch command: %s', command_line)
-      sys.exit(-3)
-    LogToSTDERR('STDOUT', stdout)
-    if exit_code != 0:
-      LogToSTDERR('STDERR', stderr)
-    sys.exit(exit_code)
+    # RunAsStandardUser() takes a full command line string (as it is forwarded
+    # to the underlying win32 implementation). We have sys.argv, but the value
+    # is already processed by shell. It is possible that the reconstructed
+    # command line is skewed (for example, expansion of environment variable),
+    # but hopefully this works well enough in all real scenarios.
+    command_line = subprocess.list2cmdline([command] + remaining_args)
+    logging.error('Full command line: %s', command_line)
+    with updater_test_service_control.OpenService():
+        pid, exit_code, stdout, stderr = rpc_client.RunAsStandardUser(
+            command_line)
+        if pid is None:
+            logging.error('Failed to launch command: %s', command_line)
+            sys.exit(-3)
+        LogToSTDERR('STDOUT', stdout)
+        if exit_code != 0:
+            LogToSTDERR('STDERR', stderr)
+        sys.exit(exit_code)
 
 
 if __name__ == '__main__':
-  main()
+    main()
diff --git a/chrome/updater/test/service/win/service_client.py b/chrome/updater/test/service/win/service_client.py
index d5a91c4..8c101a8 100644
--- a/chrome/updater/test/service/win/service_client.py
+++ b/chrome/updater/test/service/win/service_client.py
@@ -1,7 +1,6 @@
 # Copyright 2021 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.
-
 """Calls a function defined in rpc_client.py, which will forward the request
 to the test service.
 
@@ -24,38 +23,37 @@
 
 
 def ParseCommandLine():
-  """Parse the command line arguments."""
-  cmd_parser = argparse.ArgumentParser(
-      description='Updater test service client')
+    """Parse the command line arguments."""
+    cmd_parser = argparse.ArgumentParser(
+        description='Updater test service client')
 
-  cmd_parser.add_argument(
-      '--function',
-      dest='function',
-      type=str,
-      help='Name of the function to call, defined in rpc_client.py')
-  cmd_parser.add_argument(
-      '--args',
-      dest='args',
-      type=json.loads,
-      help='Arguments to the function, in json format.')
-  return cmd_parser.parse_args()
+    cmd_parser.add_argument(
+        '--function',
+        dest='function',
+        type=str,
+        help='Name of the function to call, defined in rpc_client.py')
+    cmd_parser.add_argument('--args',
+                            dest='args',
+                            type=json.loads,
+                            help='Arguments to the function, in json format.')
+    return cmd_parser.parse_args()
 
 
 def main():
-  flags ParseCommandLine()
+    flags = ParseCommandLine()
 
-  if not flags.function:
-    logging.error('Must specify a function to call.')
-    sys.exit(-1)
+    if not flags.function:
+        logging.error('Must specify a function to call.')
+        sys.exit(-1)
 
-  if not hasattr(rpc_client, flags.function):
-    logging.error('Function %s is not defined in module rpc_client.',
-    flags.function)
-  function = getattr(rpc_client, flags.function)
-  result = function(**flags.args)
-  logging.error('Function [%s] returned: %s', flags.function, result)
-  sys.exit(0)
+    if not hasattr(rpc_client, flags.function):
+        logging.error('Function %s is not defined in module rpc_client.',
+                      flags.function)
+    function = getattr(rpc_client, flags.function)
+    result = function(**flags.args)
+    logging.error('Function [%s] returned: %s', flags.function, result)
+    sys.exit(0)
 
 
 if __name__ == '__main__':
-  main()
+    main()
diff --git a/chrome/updater/test/service/win/uac.py b/chrome/updater/test/service/win/uac.py
index 9772b163..2e74cb72 100644
--- a/chrome/updater/test/service/win/uac.py
+++ b/chrome/updater/test/service/win/uac.py
@@ -9,108 +9,106 @@
 
 import ui
 
-
 # UAC window title constants
 _UAC_DIALOG_TITLE = 'User Account Control'
 
-
 _REG_VALUE_ENABLE_LUA = 'EnableLUA'
 _REG_VALUE_PROMPT_ON = 'PromptOnSecureDesktop'
 _REG_VALUE_PROMPT_CONSENT = 'ConsentPromptBehaviorAdmin'
 
 
 def _QueryPolicyValue(value_name, expected_type=winreg.REG_DWORD):
-  """Queries the system policy value from registry.
+    """Queries the system policy value from registry.
 
-  Args:
-    value_name: Registry value name for the policy.
-    expected_type: Expected registry value data type.
+    Args:
+        value_name: Registry value name for the policy.
+        expected_type: Expected registry value data type.
 
-  Returns:
-    The policy value in its desired data type, or None if no such policy or
-    data type is not expected.
-  """
-  system_policy_path = (r'Software\Microsoft\Windows'
-                        r'\CurrentVersion\Policies\System')
+    Returns:
+        The policy value in its desired data type, or None if no such policy or
+        data type is not expected.
+    """
+    system_policy_path = (r'Software\Microsoft\Windows'
+                          r'\CurrentVersion\Policies\System')
 
-  try:
-    hklm = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
-    policy_key = winreg.OpenKeyEx(hklm, system_policy_path)
-    value, data_type = winreg.QueryValueEx(policy_key, value_name)
-    return value if data_type == expected_type else None
-  except FileNotFoundError:
-    return None
+    try:
+        hklm = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
+        policy_key = winreg.OpenKeyEx(hklm, system_policy_path)
+        value, data_type = winreg.QueryValueEx(policy_key, value_name)
+        return value if data_type == expected_type else None
+    except FileNotFoundError:
+        return None
 
 
 def IsPromptingOnSecureDesktop():
-  """Checks whether UAC will be prompted to the secure desktop."""
-  prompt_location_policy = _QueryPolicyValue(_REG_VALUE_PROMPT_ON)
-  return prompt_location_policy is None or bool(prompt_location_policy)
+    """Checks whether UAC will be prompted to the secure desktop."""
+    prompt_location_policy = _QueryPolicyValue(_REG_VALUE_PROMPT_ON)
+    return prompt_location_policy is None or bool(prompt_location_policy)
 
 
 def IsSupported():
-  """Checks whether current system supports UAC.
+    """Checks whether current system supports UAC.
 
-  Returns:
-    True if system supports UAC (after XP), otherwise False.
-  """
-  return sys.getwindowsversion()[0] > 5
+    Returns:
+        True if system supports UAC (after XP), otherwise False.
+    """
+    return sys.getwindowsversion()[0] > 5
 
 
 def IsLuaEnabled():
-  """Checks whether LUA is enabled on the machine.
+    """Checks whether LUA is enabled on the machine.
 
-  Returns:
-    True if LUA is enable, False otherwise.
-  """
-  enable_lua = _QueryPolicyValue(_REG_VALUE_ENABLE_LUA)
-  return enable_lua is None or bool(enable_lua)
+    Returns:
+        True if LUA is enable, False otherwise.
+    """
+    enable_lua = _QueryPolicyValue(_REG_VALUE_ENABLE_LUA)
+    return enable_lua is None or bool(enable_lua)
 
 
 def IsElevationSilent():
-  """Checks whether user can elevate silently (without UAC prompt).
+    """Checks whether user can elevate silently (without UAC prompt).
 
-  Returns:
-    True if silent elevation is possible, False otherwise.
-  """
-  prompt_behavior = _QueryPolicyValue(_REG_VALUE_PROMPT_CONSENT)
+    Returns:
+        True if silent elevation is possible, False otherwise.
+    """
+    prompt_behavior = _QueryPolicyValue(_REG_VALUE_PROMPT_CONSENT)
 
-  if prompt_behavior == 0:
-    logging.info('Silent UAC elevation is enabled.')
-    return True
-  else:
-    logging.info('UAC prompt must be explicitly clicked.')
-    return False
+    if prompt_behavior == 0:
+        logging.info('Silent UAC elevation is enabled.')
+        return True
+    else:
+        logging.info('UAC prompt must be explicitly clicked.')
+        return False
 
 
 def IsEnabled():
-  """Checks whether UAC is supported and enabled on current system."""
-  uac_enabled = IsSupported() and IsLuaEnabled() and not IsElevationSilent()
-  logging.info('UAC is %s.', 'enabled' if uac_enabled else 'NOT enabled')
-  return uac_enabled
+    """Checks whether UAC is supported and enabled on current system."""
+    uac_enabled = IsSupported() and IsLuaEnabled() and not IsElevationSilent()
+    logging.info('UAC is %s.', 'enabled' if uac_enabled else 'NOT enabled')
+    return uac_enabled
 
 
 def AnswerUpcomingUACPrompt(allow=True, timeout=30):
-  """Answer upcoming UAC prompt that does not require username/password.
+    """Answer upcoming UAC prompt that does not require username/password.
 
-  Args:
-    allow: Answer allow or not to the prompt.
-    timeout: Wait timeout value in seconds.
+    Args:
+        allow: Answer allow or not to the prompt.
+        timeout: Wait timeout value in seconds.
 
-  Returns:
-    True if UAC prompt clicked as requested.
-  """
-  logging.info('Waiting at most %s seconds for UAC prompt...', timeout)
-  uac_hwnd = ui.WaitForWindow(_UAC_DIALOG_TITLE, None, timeout)[0]
+    Returns:
+        True if UAC prompt clicked as requested.
+    """
+    logging.info('Waiting at most %s seconds for UAC prompt...', timeout)
+    uac_hwnd = ui.WaitForWindow(_UAC_DIALOG_TITLE, None, timeout)[0]
 
-  if not uac_hwnd:
-    logging.warning('UAC prompt not found in %f seconds.', timeout)
-    return False
-  else:
-    logging.info('UAC prompt appeared.')
+    if not uac_hwnd:
+        logging.warning('UAC prompt not found in %f seconds.', timeout)
+        return False
+    else:
+        logging.info('UAC prompt appeared.')
 
-  # We assume the UAC prompt does not require credentials.
-  # Press shortcut key Alt+Y or ESC to allow or deny UAC request.
-  logging.info('%s UAC prompt.', 'Accepting' if allow else 'Denying')
-  key_to_send = '%y' if allow else '{ESC}'
-  return ui.SendKeyToWindow(uac_hwnd, key_to_send)
\ No newline at end of file
+    # We assume the UAC prompt does not require credentials.
+    # Press shortcut key Alt+Y or ESC to allow or deny UAC request.
+    logging.info('%s UAC prompt.', 'Accepting' if allow else 'Denying')
+    key_to_send = '%y' if allow else '{ESC}'
+    return ui.SendKeyToWindow(uac_hwnd, key_to_send)
diff --git a/chrome/updater/test/service/win/ui.py b/chrome/updater/test/service/win/ui.py
index ee0bd0c..1907db8 100644
--- a/chrome/updater/test/service/win/ui.py
+++ b/chrome/updater/test/service/win/ui.py
@@ -17,237 +17,247 @@
 
 
 class _MessageQueueAttacher(object):
-  """Wrapper class for message queue attachment."""
+    """Wrapper class for message queue attachment."""
 
-  def __enter__(self):
-    """Attaches the current thread to the foreground window's message queue.
+    def __enter__(self):
+        """Attaches the current thread to the foreground window's message queue.
 
-    This is an old and well known exploit used to bypass Windows Focus rules:
-    http://www.google.com/search?q=attachthreadinput+setforegroundwindow
-    """
-    self._active_thread_id = 0
-    active_hwnd = win32gui.GetForegroundWindow()
-    if not active_hwnd:
-      logging.warning('No active window is found.')
-      return
-    current_thread_id = win32api.GetCurrentThreadId()
-    active_thread_id, _ = win32process.GetWindowThreadProcessId(active_hwnd)
-    win32process.AttachThreadInput(current_thread_id, active_thread_id, 1)
-    logging.info('Attached current thread input %s to active thread: %s',
-        current_thread_id, active_thread_id)
-    self._active_thread_id = active_thread_id
+        This is an old and well known exploit used to bypass Windows Focus
+        rules:
+        http://www.google.com/search?q=attachthreadinput+setforegroundwindow
+        """
+        self._active_thread_id = 0
+        active_hwnd = win32gui.GetForegroundWindow()
+        if not active_hwnd:
+            logging.warning('No active window is found.')
+            return
+        current_thread_id = win32api.GetCurrentThreadId()
+        active_thread_id, _ = win32process.GetWindowThreadProcessId(
+            active_hwnd)
+        win32process.AttachThreadInput(current_thread_id, active_thread_id, 1)
+        logging.info('Attached current thread input %s to active thread: %s',
+                     current_thread_id, active_thread_id)
+        self._active_thread_id = active_thread_id
 
-  def __exit__(self, unused_type, unused_value, unused_traceback):
-    """Detaches the current thread from the active thread's message queue."""
-    if not self._active_thread_id:
-      return
-    current_thread_id = win32api.GetCurrentThreadId()
-    win32process.AttachThreadInput(current_thread_id, self._active_thread_id, 0)
-    logging.info('Detached current thread input %s from thread: %s',
-        current_thread_id, self._active_thread_id)
+    def __exit__(self, unused_type, unused_value, unused_traceback):
+        """Detaches the current thread from the active thread's message queue.
+        """
+        if not self._active_thread_id:
+            return
+        current_thread_id = win32api.GetCurrentThreadId()
+        win32process.AttachThreadInput(current_thread_id,
+                                       self._active_thread_id, 0)
+        logging.info('Detached current thread input %s from thread: %s',
+                     current_thread_id, self._active_thread_id)
 
 
 def SetForegroundWindow(hwnd):
-  """Brings the given window to foreground.
+    """Brings the given window to foreground.
 
-  Args:
-    hwnd: Handle of the window to bring to the foreground.
-  """
-  with _MessageQueueAttacher():
-    return bool(win32gui.SetForegroundWindow(hwnd))
+    Args:
+        hwnd: Handle of the window to bring to the foreground.
+    """
+    with _MessageQueueAttacher():
+        return bool(win32gui.SetForegroundWindow(hwnd))
 
 
 def FindWindowsWithText(parent, text_to_search):
-  """Finds windows with given text.
+    """Finds windows with given text.
 
-  Args:
-    parent: Handle to the parent window whose child windows are to be searched.
-    text_to_search: Substring to search within Windows text, case-insensitive.
+    Args:
+        parent: Handle to the parent window whose child windows are to be
+                searched.
+        text_to_search: Substring to search within Windows text,
+                        case-insensitive.
 
-  Returns:
-    A list of HWND that match the search condition.
-  """
+    Returns:
+        A list of HWND that match the search condition.
+    """
 
-  class WindowFoundHandler(object):
-    """Callback class for window enumeration."""
+    class WindowFoundHandler(object):
+        """Callback class for window enumeration."""
 
-    def __init__(self, text_to_search):
-      self.result = []
-      self._text_to_search = text_to_search
+        def __init__(self, text_to_search):
+            self.result = []
+            self._text_to_search = text_to_search
 
-    def Process(self, handle):
-      """Callback function when enumerating a window.
+        def Process(self, handle):
+            """Callback function when enumerating a window.
 
       Args:
-        handle: HWND to the enumerated window.
+          handle: HWND to the enumerated window.
       """
-      text = win32gui.GetWindowText(handle).lower()
-      text_to_search = self._text_to_search.lower()
+            text = win32gui.GetWindowText(handle).lower()
+            text_to_search = self._text_to_search.lower()
 
-      if text_to_search in text:
-        self.result.append(handle)
+            if text_to_search in text:
+                self.result.append(handle)
 
-  def WinFoundCallback(hwnd, window_found_handler):
-    window_found_handler.Process(hwnd)
+    def WinFoundCallback(hwnd, window_found_handler):
+        window_found_handler.Process(hwnd)
 
-  handler = WindowFoundHandler(text_to_search)
-  try:
-    win32gui.EnumChildWindows(parent, WinFoundCallback, handler)
-  except pywintypes.error as e:
-    logging.info('Error while searching [%s], error: [%s]', text_to_search, e)
+    handler = WindowFoundHandler(text_to_search)
+    try:
+        win32gui.EnumChildWindows(parent, WinFoundCallback, handler)
+    except pywintypes.error as e:
+        logging.info('Error while searching [%s], error: [%s]', text_to_search,
+                     e)
 
-  return handler.result
+    return handler.result
 
 
 def FindWindowsWithTitle(title_to_search):
-  """Finds windows with given title.
+    """Finds windows with given title.
 
-  Args:
-    title_to_search: Window title substring to search, case-insensitive.
+    Args:
+        title_to_search: Window title substring to search, case-insensitive.
 
-  Returns:
-    A list of HWND that match the search condition.
-  """
-  desktop_handle = None
-  return FindWindowsWithText(desktop_handle, title_to_search)
+    Returns:
+        A list of HWND that match the search condition.
+    """
+    desktop_handle = None
+    return FindWindowsWithText(desktop_handle, title_to_search)
 
 
 def FindWindow(title, class_name, parent=0, child_after=0):
-  """Finds a window of a given title and class.
+    """Finds a window of a given title and class.
 
-  Args:
-    title: Title of the window to search.
-    class_name: Class name of the window to search.
-    parent: Handle to the parent window whose child windows are to be searched.
-    child_after: HWND to a child window. Search begins with the next child
-      window in the Z order.
+    Args:
+        title: Title of the window to search.
+        class_name: Class name of the window to search.
+        parent: Handle to the parent window whose child windows are to be
+                searched.
+        child_after: HWND to a child window. Search begins with the next child
+          window in the Z order.
 
-  Returns:
-    Handle of the found window, or 0 if not found.
-  """
-  hwnd = 0
-  try:
-    hwnd = win32gui.FindWindowEx(
-        int(parent), int(child_after), class_name, title)
-  except win32gui.error as err:
-    if err[0] == winrror.ERROR_INVALID_WINDOW_HANDLE:  # Could be closed.
-      pass
-    elif err[0] != winrror.ERROR_FILE_NOT_FOUND:
-      raise err
-  if hwnd:
-    win32gui.FlashWindow(hwnd, True)
-  return hwnd
+    Returns:
+        Handle of the found window, or 0 if not found.
+    """
+    hwnd = 0
+    try:
+        hwnd = win32gui.FindWindowEx(int(parent), int(child_after), class_name,
+                                     title)
+    except win32gui.error as err:
+        if err[0] == winrror.ERROR_INVALID_WINDOW_HANDLE:  # Could be closed.
+            pass
+        elif err[0] != winrror.ERROR_FILE_NOT_FOUND:
+            raise err
+    if hwnd:
+        win32gui.FlashWindow(hwnd, True)
+    return hwnd
 
 
 def FindWindowWithTitleAndText(title, text):
-  """Checks if the any window has given title, and child window has the text.
+    """Checks if the any window has given title, and child window has the text.
 
-  Args:
-    title: Expected window title.
-    text: Expected window text substring(in any child window), case-insensitive.
+    Args:
+        title: Expected window title.
+        text: Expected window text substring(in any child window),
+              case-insensitive.
 
-  Returns:
-    A list how HWND that meets the search condition.
-  """
-  hwnds_title_matched = FindWindowsWithTitle(title)
-  if not hwnds_title_matched:
-    logging.info('No window has title: [%s].', title)
+    Returns:
+        A list how HWND that meets the search condition.
+    """
+    hwnds_title_matched = FindWindowsWithTitle(title)
+    if not hwnds_title_matched:
+        logging.info('No window has title: [%s].', title)
 
-  hwnds = []
-  for hwnd in hwnds_title_matched:
-    if FindWindowsWithText(hwnd, text):
-      hwnds.append(hwnd)
-  return hwnds
+    hwnds = []
+    for hwnd in hwnds_title_matched:
+        if FindWindowsWithText(hwnd, text):
+            hwnds.append(hwnd)
+    return hwnds
 
 
 def WaitForWindow(title, class_name, timeout=30):
-  """Waits for window with given title and class to appear.
+    """Waits for window with given title and class to appear.
 
-  Args:
-    title: Windows title to search.
-    class_name: Class name of the window to search.
-    timeout: How long should wait before give up.
+    Args:
+        title: Windows title to search.
+        class_name: Class name of the window to search.
+        timeout: How long should wait before give up.
 
-  Returns:
-    A tuple of (HWND, title) of the found window, or (None, None) otherwise.
-  """
-  logging.info('ui.WaitForWindow("%s", "%s") for %s seconds', title,
-               class_name, timeout)
-  hwnd = None
-  start = time.perf_counter()
-  stop = start + int(timeout)
+    Returns:
+        A tuple of (HWND, title) of the found window, or (None, None) otherwise.
+    """
+    logging.info('ui.WaitForWindow("%s", "%s") for %s seconds', title,
+                 class_name, timeout)
+    hwnd = None
+    start = time.perf_counter()
+    stop = start + int(timeout)
 
-  while time.perf_counter() < stop:
-    hwnd = FindWindow(title, class_name)
-    if hwnd:
-      elapsed = time.perf_counter() - start
-      logging.info('Window ["%s"] found in %f seconds', title, elapsed)
-      return (hwnd, title)
-    logging.info('Window with title [%s] has not appeared yet.', title)
-    time.sleep(0.5)
+    while time.perf_counter() < stop:
+        hwnd = FindWindow(title, class_name)
+        if hwnd:
+            elapsed = time.perf_counter() - start
+            logging.info('Window ["%s"] found in %f seconds', title, elapsed)
+            return (hwnd, title)
+        logging.info('Window with title [%s] has not appeared yet.', title)
+        time.sleep(0.5)
 
-  logging.warning('WARNING: (%s,"%s") not found within %f seconds', title,
-                  class_name, timeout)
-  return (None, None)
+    logging.warning('WARNING: (%s,"%s") not found within %f seconds', title,
+                    class_name, timeout)
+    return (None, None)
 
 
 def ClickButton(button_hwnd):
-  """Clicks a button window by sending a BM_CLICK message.
+    """Clicks a button window by sending a BM_CLICK message.
 
-  Per http://msdn2.microsoft.com/en-us/library/bb775985.aspx
-  "If the button is in a dialog box and the dialog box is not active, the
-  BM_CLICK message might fail. To ensure success in this situation, call
-  the SetActiveWindow function to activate the dialog box before sending
-  the BM_CLICK message to the button."
+    Per http://msdn2.microsoft.com/en-us/library/bb775985.aspx
+    "If the button is in a dialog box and the dialog box is not active, the
+    BM_CLICK message might fail. To ensure success in this situation, call
+    the SetActiveWindow function to activate the dialog box before sending
+    the BM_CLICK message to the button."
 
-  Args:
-    button_hwnd: HWND to the button to be clicked.
-  """
-  previous_active_window = win32gui.SetActiveWindow(button_hwnd)
-  win32gui.PostMessage(button_hwnd, win32con.BM_CLICK, 0, 0)
-  if previous_active_window:
-    win32gui.SetActiveWindow(previous_active_window)
+    Args:
+        button_hwnd: HWND to the button to be clicked.
+    """
+    previous_active_window = win32gui.SetActiveWindow(button_hwnd)
+    win32gui.PostMessage(button_hwnd, win32con.BM_CLICK, 0, 0)
+    if previous_active_window:
+        win32gui.SetActiveWindow(previous_active_window)
 
 
 def ClickChildButtonWithText(parent_hwnd, button_text):
-  """Clicks a child button window with given text.
+    """Clicks a child button window with given text.
 
-  Args:
-    parent_hwnd: HWND of the button parent.
-    button_text: Button windows title.
+    Args:
+        parent_hwnd: HWND of the button parent.
+        button_text: Button windows title.
 
-  Returns:
-    Whether button is clicked.
-  """
-  button_hwnd = FindWindow(button_text, 'Button', parent_hwnd)
-  if button_hwnd:
-    logging.debug('Found child button with: %s', button_text)
-    ClickButton(button_hwnd)
-    return True
+    Returns:
+        Whether button is clicked.
+    """
+    button_hwnd = FindWindow(button_text, 'Button', parent_hwnd)
+    if button_hwnd:
+        logging.debug('Found child button with: %s', button_text)
+        ClickButton(button_hwnd)
+        return True
 
-  logging.debug('No button with [%s] found.', button_text)
-  return False
+    logging.debug('No button with [%s] found.', button_text)
+    return False
 
 
 def SendKeyToWindow(hwnd, key_to_press):
-  """Sends a key press to the window.
+    """Sends a key press to the window.
 
-  This is a blocking call until all keys are pressed.
+    This is a blocking call until all keys are pressed.
 
-  Args:
-    hwnd: handle of  the window to press key.
-    key_to_press: Actual key to send to window. eg.'{Enter}'. See `window_shell`
-        documentation for key definitions.
-  """
-  try:
-    window_shell = win32com.client.Dispatch('WScript.Shell')
-    SetForegroundWindow(hwnd)
-    window_shell.AppActivate(str(win32gui.GetForegroundWindow()))
-    window_shell.SendKeys(key_to_press)
-    logging.info('Sent %s to window %x.', key_to_press, hwnd)
-  except pywintypes.error as err:
-    logging.error('Failed to press key: %s', err)
-    raise
-  except pythoncom.com_error as err:
-    logging.error('COM exception occurred: %s, is CoInitialize() called?', err)
-    raise
\ No newline at end of file
+    Args:
+        hwnd: handle of  the window to press key.
+        key_to_press: Actual key to send to window. eg.'{Enter}'.
+                      See `window_shell` documentation for key definitions.
+    """
+    try:
+        window_shell = win32com.client.Dispatch('WScript.Shell')
+        SetForegroundWindow(hwnd)
+        window_shell.AppActivate(str(win32gui.GetForegroundWindow()))
+        window_shell.SendKeys(key_to_press)
+        logging.info('Sent %s to window %x.', key_to_press, hwnd)
+    except pywintypes.error as err:
+        logging.error('Failed to press key: %s', err)
+        raise
+    except pythoncom.com_error as err:
+        logging.error('COM exception occurred: %s, is CoInitialize() called?',
+                      err)
+        raise
diff --git a/chrome/updater/test/service/win/updater_test_service.py b/chrome/updater/test/service/win/updater_test_service.py
index 0d8e956f..0911e30 100644
--- a/chrome/updater/test/service/win/updater_test_service.py
+++ b/chrome/updater/test/service/win/updater_test_service.py
@@ -21,77 +21,75 @@
 
 
 class UpdaterTestRequestHandler(xmlrpc.server.SimpleXMLRPCRequestHandler):
-
-  def log_message(self, format, *args):
-    # Overrides base class's implementation which writes the messages to
-    # sys.stderr.
-    # When XML RPC server runs within the service, sys.stderr is None. This
-    # crashes the server and aborts connection. Workaround this issue by using
-    # python logging.
-    logging.error(format, *args)
+    def log_message(self, format, *args):
+        # Overrides base class's implementation which writes the messages to
+        # sys.stderr.
+        # When XML RPC server runs within the service, sys.stderr is None. This
+        # crashes the server and aborts connection. Workaround this issue by
+        # using python logging.
+        logging.error(format, *args)
 
 
 class UpdaterTestXmlRpcServer(xmlrpc.server.SimpleXMLRPCServer):
-  """Customized XML-RPC server for updater tests."""
+    """Customized XML-RPC server for updater tests."""
 
-  def __init__(self):
-    super().__init__(('localhost', _XML_RPC_SERVER_PORT),
-                     requestHandler=UpdaterTestRequestHandler,
-                     allow_none=True)
+    def __init__(self):
+        super().__init__(('localhost', _XML_RPC_SERVER_PORT),
+                         requestHandler=UpdaterTestRequestHandler,
+                         allow_none=True)
 
-  def run(self):
-    """xml-rpc server main loop."""
-    self.register_introspection_functions()
-    self.register_instance(rpc_handler.UpdaterTestRPCHandler())
-    self.serve_forever()
+    def run(self):
+        """xml-rpc server main loop."""
+        self.register_introspection_functions()
+        self.register_instance(rpc_handler.UpdaterTestRPCHandler())
+        self.serve_forever()
 
 
 class UpdaterTestService(win32serviceutil.ServiceFramework):
-  """Customizes updater tests behavior."""
+    """Customizes updater tests behavior."""
 
-  # Do not change these class variables names, these are required by the base
-  # class.
-  _svc_name_ = 'UpdaterTestService'
-  _svc_display_name_ = 'Updater Test Service'
-  _svc_description_ = 'Service for browser updater tests'
+    # Do not change these class variables names, these are required by the base
+    # class.
+    _svc_name_ = 'UpdaterTestService'
+    _svc_display_name_ = 'Updater Test Service'
+    _svc_description_ = 'Service for browser updater tests'
 
+    def SvcStop(self):
+        """Called by service framework to stop this service."""
+        logging.info('Updater test service stopping...')
+        self._xmlrpc_server.shutdown()
+        self.ReportServiceStatus(win32service.SERVICE_STOPPED)
 
-  def SvcStop(self):
-    """Called by service framework to stop this service."""
-    logging.info('Updater test service stopping...')
-    self._xmlrpc_server.shutdown()
-    self.ReportServiceStatus(win32service.SERVICE_STOPPED)
+    def SvcDoRun(self):
+        """Called by service framework to start this service."""
 
-  def SvcDoRun(self):
-    """Called by service framework to start this service."""
-
-    try:
-      logging.info('%s starting...', self._svc_name_)
-      servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
-                            servicemanager.PYS_SERVICE_STARTED,
-                            (self._svc_name_, ''))
-      self.ReportServiceStatus(win32service.SERVICE_RUNNING)
-      self._xmlrpc_server = UpdaterTestXmlRpcServer()
-      self._xmlrpc_server.run()
-      servicemanager.LogInfoMsg(self._svc_name_ + ' - Ended')
-    except pywintypes.error as err:
-      logging.exception(err)
-      servicemanager.LogErrorMsg(err)
-      self.ReportServiceStatus(win32service.SERVICE_ERROR_SEVERE)
+        try:
+            logging.info('%s starting...', self._svc_name_)
+            servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
+                                  servicemanager.PYS_SERVICE_STARTED,
+                                  (self._svc_name_, ''))
+            self.ReportServiceStatus(win32service.SERVICE_RUNNING)
+            self._xmlrpc_server = UpdaterTestXmlRpcServer()
+            self._xmlrpc_server.run()
+            servicemanager.LogInfoMsg(self._svc_name_ + ' - Ended')
+        except pywintypes.error as err:
+            logging.exception(err)
+            servicemanager.LogErrorMsg(err)
+            self.ReportServiceStatus(win32service.SERVICE_ERROR_SEVERE)
 
 
 if __name__ == "__main__":
-  logging.info('Command: %s', sys.argv)
+    logging.info('Command: %s', sys.argv)
 
-  # Prefer the pythonservice.exe in the same directory as the interpreter.
-  # This is mainly for the vpython case.
-  destination = os.path.join(
-      os.path.dirname(os.path.abspath(sys.executable)), 'pythonservice.exe')
-  if os.path.exists(destination):
-    os.environ['PYTHON_SERVICE_EXE'] = destination
+    # Prefer the pythonservice.exe in the same directory as the interpreter.
+    # This is mainly for the vpython case.
+    destination = os.path.join(
+        os.path.dirname(os.path.abspath(sys.executable)), 'pythonservice.exe')
+    if os.path.exists(destination):
+        os.environ['PYTHON_SERVICE_EXE'] = destination
 
-  try:
-    win32api.SetConsoleCtrlHandler(lambda _: True, True)
-    win32serviceutil.HandleCommandLine(UpdaterTestService)
-  except Exception as err:
-    servicemanager.LogErrorMsg(err)
+    try:
+        win32api.SetConsoleCtrlHandler(lambda _: True, True)
+        win32serviceutil.HandleCommandLine(UpdaterTestService)
+    except Exception as err:
+        servicemanager.LogErrorMsg(err)
diff --git a/chrome/updater/test/service/win/updater_test_service_control.py b/chrome/updater/test/service/win/updater_test_service_control.py
index 3389bdf..f98ff37e 100644
--- a/chrome/updater/test/service/win/updater_test_service_control.py
+++ b/chrome/updater/test/service/win/updater_test_service_control.py
@@ -28,230 +28,236 @@
 
 _UPDATER_TEST_SERVICE_NAME = 'UpdaterTestService'
 
-
 # Errors that might be raised when interacting with the service.
-_ServiceErrors = (OSError, pywintypes.error, win32api.error, win32service.error,
-                  WindowsError)  # pylint: disable=undefined-variable
+_ServiceErrors = (OSError, pywintypes.error, win32api.error,
+                  win32service.error, WindowsError)  # pylint: disable=undefined-variable
 
 
 def _RunCommand(command, log_error=True):
-  """Run a command and logs stdout/stderr if needed.
+    """Run a command and logs stdout/stderr if needed.
 
-  Args:
-    command: Command to run.
-    log_error: Whether to log the stderr.
+    Args:
+        command: Command to run.
+        log_error: Whether to log the stderr.
 
-  Returns:
-    True if the process exits with 0.
-  """
-  process = subprocess.Popen(command,
-                             stdout=subprocess.PIPE,
-                             stderr=subprocess.PIPE)
-  stdout, stderr = process.communicate()
-  logging.info('Command %s stdout:\n %s', command, stdout)
-  if log_error and stderr:
-    logging.error('Command %s stderr:\n %s', command, stderr)
+    Returns:
+        True if the process exits with 0.
+    """
+    process = subprocess.Popen(command,
+                               stdout=subprocess.PIPE,
+                               stderr=subprocess.PIPE)
+    stdout, stderr = process.communicate()
+    logging.info('Command %s stdout:\n %s', command, stdout)
+    if log_error and stderr:
+        logging.error('Command %s stderr:\n %s', command, stderr)
 
-  return process.returncode == 0
+    return process.returncode == 0
 
 
 def _SetupEnvironmentForVPython():
-  """Setup vpython environment."""
-  if os.getenv('VIRTUAL_ENV') is None:
-    logging.info('Not running in vpython, no additional setup is needed.')
-    return
+    """Setup vpython environment."""
+    if os.getenv('VIRTUAL_ENV') is None:
+        logging.info('Not running in vpython, no additional setup is needed.')
+        return
 
-  # vpython_spec above brings the pywin32 module we need, but it may not be
-  # ready to use, run the post install scripts as described by
-  # https://pypi.org/project/pywin32/.
-  # This script outputs some error messages to stderr if it has run before.
-  # So skip logging to avoid this log pollution.
-  post_install_script = os.path.join(
-      os.path.dirname(os.path.abspath(sys.executable)),
-      'pywin32_postinstall.py')
-  _RunCommand([sys.executable, post_install_script, '-install'],
-              log_error=False)
+    # vpython_spec above brings the pywin32 module we need, but it may not be
+    # ready to use, run the post install scripts as described by
+    # https://pypi.org/project/pywin32/.
+    # This script outputs some error messages to stderr if it has run before.
+    # So skip logging to avoid this log pollution.
+    post_install_script = os.path.join(
+        os.path.dirname(os.path.abspath(sys.executable)),
+        'pywin32_postinstall.py')
+    _RunCommand([sys.executable, post_install_script, '-install'],
+                log_error=False)
 
-  # Make pythonservice.exe explicit for our service. This is to avoid pickup
-  # an incompatible interpreter accidentally.
-  source = os.path.join(
-      os.environ['VIRTUAL_ENV'], 'Lib',
-      'site-packages', 'win32', 'pythonservice.exe')
-  python_service_path = os.path.join(
-      os.path.dirname(os.path.abspath(sys.executable)), 'pythonservice.exe')
-  if not os.path.exists(python_service_path):
-    shutil.copyfile(source, python_service_path)
-  os.environ['PYTHON_SERVICE_EXE'] = python_service_path
+    # Make pythonservice.exe explicit for our service. This is to avoid pickup
+    # an incompatible interpreter accidentally.
+    source = os.path.join(os.environ['VIRTUAL_ENV'], 'Lib', 'site-packages',
+                          'win32', 'pythonservice.exe')
+    python_service_path = os.path.join(
+        os.path.dirname(os.path.abspath(sys.executable)), 'pythonservice.exe')
+    if not os.path.exists(python_service_path):
+        shutil.copyfile(source, python_service_path)
+    os.environ['PYTHON_SERVICE_EXE'] = python_service_path
 
 
 def _IsServiceInStatus(status):
-  """Returns the if test service is in the given status."""
-  try:
-    return status == win32serviceutil.QueryServiceStatus(
-        _UPDATER_TEST_SERVICE_NAME)[1]
-  except _ServiceErrors as err:
-    return False
+    """Returns the if test service is in the given status."""
+    try:
+        return status == win32serviceutil.QueryServiceStatus(
+            _UPDATER_TEST_SERVICE_NAME)[1]
+    except _ServiceErrors as err:
+        return False
 
 
 def _MainServiceScriptPath():
-  """Returns the service main script path."""
-  # Assumes updater_test_service.py file is in the same directory as this file.
-  service_main = os.path.join(
-      os.path.abspath(os.path.dirname(__file__)), 'updater_test_service.py')
-  if not os.path.isfile(service_main):
-    logging.error('Cannot find service main module: %s', service_main)
-    return None
-  return service_main
+    """Returns the service main script path."""
+    # Assumes updater_test_service.py file is in the same directory as
+    # this file.
+    service_main = os.path.join(os.path.abspath(os.path.dirname(__file__)),
+                                'updater_test_service.py')
+    if not os.path.isfile(service_main):
+        logging.error('Cannot find service main module: %s', service_main)
+        return None
+    return service_main
 
 
 def _WaitServiceStatus(status, timeout=30):
-  """Wait the service to be in the given state."""
-  check_interval = 0.2
-  for i in range(int(timeout / check_interval)):
-    if _IsServiceInStatus(status):
-      return True
-    time.sleep(check_interval)
-  return False
+    """Wait the service to be in the given state."""
+    check_interval = 0.2
+    for i in range(int(timeout / check_interval)):
+        if _IsServiceInStatus(status):
+            return True
+        time.sleep(check_interval)
+    return False
 
 
 def InstallService():
-  """Install updater test service.
+    """Install updater test service.
 
-  If the service was previously installed, it will be updated.
+    If the service was previously installed, it will be updated.
 
-  Returns:
-    True if the service is installed successfully.
-  """
-  _SetupEnvironmentForVPython()
+    Returns:
+        True if the service is installed successfully.
+    """
+    _SetupEnvironmentForVPython()
 
-  service_main = _MainServiceScriptPath()
-  if not service_main:
-    logging.error('Cannot find the service main script [%s].', service_main)
-    return False
+    service_main = _MainServiceScriptPath()
+    if not service_main:
+        logging.error('Cannot find the service main script [%s].',
+                      service_main)
+        return False
 
-  try:
-    if _IsServiceInStatus(win32service.SERVICE_RUNNING) and not StopService():
-      logging.error('Cannot stop existing test service.')
-      return False
+    try:
+        if _IsServiceInStatus(
+                win32service.SERVICE_RUNNING) and not StopService():
+            logging.error('Cannot stop existing test service.')
+            return False
 
-    logging.info('Installing service with script: %s', service_main)
-    command = [
-        sys.executable, service_main, '--interactive', '--startup', 'auto',
-        'install'
-    ]
-    if _RunCommand(command):
-      logging.info('Service [%s] installed.', _UPDATER_TEST_SERVICE_NAME)
-      return True
-    else:
-      logging.error('Failed to install [%s].', _UPDATER_TEST_SERVICE_NAME)
-      return False
-  except _ServiceErrors as err:
-    logging.exception(err)
-    return False
+        logging.info('Installing service with script: %s', service_main)
+        command = [
+            sys.executable, service_main, '--interactive', '--startup', 'auto',
+            'install'
+        ]
+        if _RunCommand(command):
+            logging.info('Service [%s] installed.', _UPDATER_TEST_SERVICE_NAME)
+            return True
+        else:
+            logging.error('Failed to install [%s].',
+                          _UPDATER_TEST_SERVICE_NAME)
+            return False
+    except _ServiceErrors as err:
+        logging.exception(err)
+        return False
 
 
 def UninstallService():
-  """Uninstall the service."""
-  service_main = _MainServiceScriptPath()
-  if not service_main:
-    logging.error('Unexpected: missing service main script [%s].', service_main)
-    return False
+    """Uninstall the service."""
+    service_main = _MainServiceScriptPath()
+    if not service_main:
+        logging.error('Unexpected: missing service main script [%s].',
+                      service_main)
+        return False
 
-  try:
-    if _IsServiceInStatus(win32service.SERVICE_RUNNING) and not StopService():
-      logging.error('Cannot stop test service for uninstall.')
-      return False
+    try:
+        if _IsServiceInStatus(
+                win32service.SERVICE_RUNNING) and not StopService():
+            logging.error('Cannot stop test service for uninstall.')
+            return False
 
-    command = [sys.executable, service_main, 'remove']
-    if _RunCommand(command):
-      logging.error('Service [%s] uninstalled.', _UPDATER_TEST_SERVICE_NAME)
-      return True
-    else:
-      logging.error('Failed to uninstall [%s].', _UPDATER_TEST_SERVICE_NAME)
-      return False
-  except _ServiceErrors as err:
-    logging.error('Failed to install service.')
-    logging.exception(err)
-    return False
+        command = [sys.executable, service_main, 'remove']
+        if _RunCommand(command):
+            logging.error('Service [%s] uninstalled.',
+                          _UPDATER_TEST_SERVICE_NAME)
+            return True
+        else:
+            logging.error('Failed to uninstall [%s].',
+                          _UPDATER_TEST_SERVICE_NAME)
+            return False
+    except _ServiceErrors as err:
+        logging.error('Failed to install service.')
+        logging.exception(err)
+        return False
 
 
 def StartService(timeout=30):
-  """Start updater test service and make sure it is reachable.
+    """Start updater test service and make sure it is reachable.
 
-  Args:
-    timeout: How long to wait for service to be ready.
+    Args:
+        timeout: How long to wait for service to be ready.
 
-  Returns:
-    True if the service is started successfully.
-  """
-  logging.info('Starting service [%s].', _UPDATER_TEST_SERVICE_NAME)
-  if _IsServiceInStatus(win32service.SERVICE_RUNNING):
-    logging.info('Test service is already running.')
-    return True
+    Returns:
+        True if the service is started successfully.
+    """
+    logging.info('Starting service [%s].', _UPDATER_TEST_SERVICE_NAME)
+    if _IsServiceInStatus(win32service.SERVICE_RUNNING):
+        logging.info('Test service is already running.')
+        return True
 
-  try:
-    win32serviceutil.StartService(_UPDATER_TEST_SERVICE_NAME)
-    if not _WaitServiceStatus(win32service.SERVICE_RUNNING, timeout):
-      logging.error('Wait for service start failed.')
-      return False
+    try:
+        win32serviceutil.StartService(_UPDATER_TEST_SERVICE_NAME)
+        if not _WaitServiceStatus(win32service.SERVICE_RUNNING, timeout):
+            logging.error('Wait for service start failed.')
+            return False
 
-    logging.error('Service %s started.', _UPDATER_TEST_SERVICE_NAME)
-    return rpc_client.TestConnection()
-  except _ServiceErrors as err:
-    logging.error('Failed to start service.')
-    logging.exception(err)
+        logging.error('Service %s started.', _UPDATER_TEST_SERVICE_NAME)
+        return rpc_client.TestConnection()
+    except _ServiceErrors as err:
+        logging.error('Failed to start service.')
+        logging.exception(err)
 
-  return False
+    return False
 
 
 def StopService(timeout=30):
-  """Stop test service if it is running.
+    """Stop test service if it is running.
 
-  Returns:
-    True if the service is stopped successfully.
-  """
-  logging.info('Stopping service [%s]...', _UPDATER_TEST_SERVICE_NAME)
-  try:
-    if not _IsServiceInStatus(win32service.SERVICE_RUNNING):
-      return True
+    Returns:
+        True if the service is stopped successfully.
+    """
+    logging.info('Stopping service [%s]...', _UPDATER_TEST_SERVICE_NAME)
+    try:
+        if not _IsServiceInStatus(win32service.SERVICE_RUNNING):
+            return True
 
-    win32serviceutil.StopService(_UPDATER_TEST_SERVICE_NAME)
-    if not _WaitServiceStatus(win32service.SERVICE_STOPPED, timeout):
-      logging.error('Wait for service stop failed.')
-      return False
+        win32serviceutil.StopService(_UPDATER_TEST_SERVICE_NAME)
+        if not _WaitServiceStatus(win32service.SERVICE_STOPPED, timeout):
+            logging.error('Wait for service stop failed.')
+            return False
 
-    logging.info('Service [%s] stopped.', _UPDATER_TEST_SERVICE_NAME)
-    return True
-  except _ServiceErrors as err:
-    logging.error('Failed to stop service.')
-    logging.exception(err)
-    return False
+        logging.info('Service [%s] stopped.', _UPDATER_TEST_SERVICE_NAME)
+        return True
+    except _ServiceErrors as err:
+        logging.error('Failed to stop service.')
+        logging.exception(err)
+        return False
 
 
 @contextlib.contextmanager
 def OpenService():
-  """Open the service as a managed resource."""
-  try:
-    if InstallService() and StartService():
-      yield _UPDATER_TEST_SERVICE_NAME
-    else:
-      yield None
-  finally:
-    UninstallService()
+    """Open the service as a managed resource."""
+    try:
+        if InstallService() and StartService():
+            yield _UPDATER_TEST_SERVICE_NAME
+        else:
+            yield None
+    finally:
+        UninstallService()
 
 
 if __name__ == '__main__':
-  if len(sys.argv) == 1:
-    logging.error('Must provide an action.')
-    sys.exit(-1)
+    if len(sys.argv) == 1:
+        logging.error('Must provide an action.')
+        sys.exit(-1)
 
-  command = sys.argv[1]
-  if command == 'setup':
-    result = InstallService() and StartService()
-  elif command == 'teardown':
-    result = UninstallService()
-  else:
-    logging.error('Unknown command: %s.', command)
-    sys.exit(-2)
+    command = sys.argv[1]
+    if command == 'setup':
+        result = InstallService() and StartService()
+    elif command == 'teardown':
+        result = UninstallService()
+    else:
+        logging.error('Unknown command: %s.', command)
+        sys.exit(-2)
 
-  sys.exit(0 if result else 1)
+    sys.exit(0 if result else 1)
diff --git a/chrome/updater/win/installer/create_installer_archive.py b/chrome/updater/win/installer/create_installer_archive.py
index b402622..eca0c4b3 100644
--- a/chrome/updater/win/installer/create_installer_archive.py
+++ b/chrome/updater/win/installer/create_installer_archive.py
@@ -1,7 +1,6 @@
 # Copyright 2019 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
-
 """Script to create the Chrome Updater Installer archive.
 
   This script is used to create an archive of all the files required for a
@@ -31,186 +30,197 @@
 
 g_archive_inputs = []
 
+
 def CompressUsingLZMA(build_dir, compressed_file, input_file, verbose):
-  lzma_exec = GetLZMAExec(build_dir)
-  cmd = [lzma_exec,
-         'a', '-t7z',
-          # Flags equivalent to -mx9 (ultra) but with the bcj2 turned on (exe
-          # pre-filter). These arguments are the similar to what the Chrome mini
-          # installer is using.
-          '-m0=BCJ2',
-          '-m1=LZMA:d27:fb128',
-          '-m2=LZMA:d22:fb128:mf=bt2',
-          '-m3=LZMA:d22:fb128:mf=bt2',
-          '-mb0:1',
-          '-mb0s1:2',
-          '-mb0s2:3',
-          os.path.abspath(compressed_file),
-          os.path.abspath(input_file),]
-  if os.path.exists(compressed_file):
-    os.remove(compressed_file)
-  RunSystemCommand(cmd, verbose)
+    lzma_exec = GetLZMAExec(build_dir)
+    cmd = [
+        lzma_exec,
+        'a',
+        '-t7z',
+        # Flags equivalent to -mx9 (ultra) but with the bcj2 turned on (exe
+        # pre-filter). These arguments are the similar to what the Chrome mini
+        # installer is using.
+        '-m0=BCJ2',
+        '-m1=LZMA:d27:fb128',
+        '-m2=LZMA:d22:fb128:mf=bt2',
+        '-m3=LZMA:d22:fb128:mf=bt2',
+        '-mb0:1',
+        '-mb0s1:2',
+        '-mb0s2:3',
+        os.path.abspath(compressed_file),
+        os.path.abspath(input_file),
+    ]
+    if os.path.exists(compressed_file):
+        os.remove(compressed_file)
+    RunSystemCommand(cmd, verbose)
 
 
 def CopyAllFilesToStagingDir(config, staging_dir, build_dir, timestamp):
-  """Copies the files required for installer archive.
-  """
-  CopySectionFilesToStagingDir(config, 'GENERAL', staging_dir, build_dir,
-                               timestamp)
+    """Copies the files required for installer archive."""
+    CopySectionFilesToStagingDir(config, 'GENERAL', staging_dir, build_dir,
+                                 timestamp)
 
 
 def CopySectionFilesToStagingDir(config, section, staging_dir, src_dir,
                                  timestamp):
-  """Copies installer archive files specified in section from src_dir to
-  staging_dir. This method reads section from config and copies all the
-  files specified from src_dir to staging dir.
-  """
-  for option in config.options(section):
-    src_subdir = option.replace('\\', os.sep)
-    dst_dir = os.path.join(staging_dir, config.get(section, option))
-    dst_dir = dst_dir.replace('\\', os.sep)
-    src_paths = glob.glob(os.path.join(src_dir, src_subdir))
-    for src_path in src_paths:
-      if dst_dir.endswith(os.sep):
-        dst_path = os.path.join(dst_dir, os.path.basename(src_path))
-      else:
-        dst_path = dst_dir
-      if not os.path.exists(dst_path):
-        if not os.path.exists(os.path.dirname(dst_path)):
-          os.makedirs(os.path.dirname(dst_dir))
-        g_archive_inputs.append(src_path)
-        shutil.copy(src_path, dst_path)
-        os.utime(dst_path, (os.stat(dst_path).st_atime, timestamp))
-    os.utime(dst_dir, (os.stat(dst_dir).st_atime, timestamp))
+    """Copies installer archive files specified in section from src_dir to
+    staging_dir. This method reads section from config and copies all the
+    files specified from src_dir to staging dir."""
+    for option in config.options(section):
+        src_subdir = option.replace('\\', os.sep)
+        dst_dir = os.path.join(staging_dir, config.get(section, option))
+        dst_dir = dst_dir.replace('\\', os.sep)
+        src_paths = glob.glob(os.path.join(src_dir, src_subdir))
+        for src_path in src_paths:
+            if dst_dir.endswith(os.sep):
+                dst_path = os.path.join(dst_dir, os.path.basename(src_path))
+            else:
+                dst_path = dst_dir
+            if not os.path.exists(dst_path):
+                if not os.path.exists(os.path.dirname(dst_path)):
+                    os.makedirs(os.path.dirname(dst_dir))
+                g_archive_inputs.append(src_path)
+                shutil.copy(src_path, dst_path)
+                os.utime(dst_path, (os.stat(dst_path).st_atime, timestamp))
+        os.utime(dst_dir, (os.stat(dst_dir).st_atime, timestamp))
+
 
 def GetLZMAExec(build_dir):
-  if sys.platform == 'win32':
-    lzma_exec = os.path.join(build_dir, "..", "..", "third_party",
-                             "lzma_sdk", "Executable", "7za.exe")
-  else:
-    lzma_exec = '7zr'  # Use system 7zr.
-  return lzma_exec
+    if sys.platform == 'win32':
+        lzma_exec = os.path.join(build_dir, "..", "..", "third_party",
+                                 "lzma_sdk", "Executable", "7za.exe")
+    else:
+        lzma_exec = '7zr'  # Use system 7zr.
+    return lzma_exec
+
 
 def MakeStagingDirectory(staging_dir):
-  """Creates a staging path for installer archive. If directory exists already,
-  deletes the existing directory.
-  """
-  file_path = os.path.join(staging_dir, TEMP_ARCHIVE_DIR)
-  if os.path.exists(file_path):
-    shutil.rmtree(file_path)
-  os.makedirs(file_path)
-  return file_path
+    """Creates a staging path for installer archive. If directory exists
+    already, deletes the existing directory."""
+    file_path = os.path.join(staging_dir, TEMP_ARCHIVE_DIR)
+    if os.path.exists(file_path):
+        shutil.rmtree(file_path)
+    os.makedirs(file_path)
+    return file_path
+
 
 def Readconfig(input_file):
-  """Reads config information from input file after setting default value of
-  global variables.
-  """
-  variables = {}
-  variables['UpdaterDir'] = UPDATER_DIR
-  config = configparser.ConfigParser(variables)
-  config.read(input_file)
-  return config
+    """Reads config information from input file after setting default value of
+    global variables."""
+    variables = {}
+    variables['UpdaterDir'] = UPDATER_DIR
+    config = configparser.ConfigParser(variables)
+    config.read(input_file)
+    return config
+
 
 def RunSystemCommand(cmd, verbose):
-  """Runs |cmd|, prints the |cmd| and its output if |verbose|; otherwise
-  captures its output and only emits it on failure.
-  """
-  if verbose:
-    print('Running', cmd)
-
-  try:
-    # Run |cmd|, redirecting stderr to stdout in order for captured errors to be
-    # inline with corresponding stdout.
-    output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+    """Runs |cmd|, prints the |cmd| and its output if |verbose|; otherwise
+    captures its output and only emits it on failure."""
     if verbose:
-      print(output)
-  except subprocess.CalledProcessError as e:
-    raise Exception("Error while running cmd: %s\n"
-                    "Exit code: %s\n"
-                    "Command output:\n%s" %
-                    (e.cmd, e.returncode, e.output))
+        print('Running', cmd)
+
+    try:
+        # Run |cmd|, redirecting stderr to stdout in order for captured errors
+        # to be inline with corresponding stdout.
+        output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+        if verbose:
+            print(output)
+    except subprocess.CalledProcessError as e:
+        raise Exception("Error while running cmd: %s\n"
+                        "Exit code: %s\n"
+                        "Command output:\n%s" %
+                        (e.cmd, e.returncode, e.output))
+
 
 def CreateArchiveFile(options, staging_dir, timestamp):
-  """Creates a new installer archive file after deleting any existing old file.
-  """
-  # First create an uncompressed archive file for the current build (updater.7z)
-  lzma_exec = GetLZMAExec(options.build_dir)
-  archive_file = os.path.join(options.output_dir,
-                              options.output_name + ARCHIVE_SUFFIX)
+    """Creates a new installer archive file after deleting any existing old
+    file."""
+    # First create an uncompressed archive file for the current build
+    # (updater.7z)
+    lzma_exec = GetLZMAExec(options.build_dir)
+    archive_file = os.path.join(options.output_dir,
+                                options.output_name + ARCHIVE_SUFFIX)
 
-  if options.depfile:
-    # If a depfile was requested, do the glob of the staging dir and generate
-    # a list of dependencies in .d format. We list the files that were copied
-    # into the staging dir, not the files that are actually in the staging dir
-    # because the ones in the staging dir will never be edited, and we want
-    # to have the build be triggered when the thing-that-was-copied-there
-    # changes.
+    if options.depfile:
+        # If a depfile was requested, do the glob of the staging dir and
+        # generate a list of dependencies in .d format. We list the files that
+        # were copied into the staging dir, not the files that are actually in
+        # the staging dir because the ones in the staging dir will never be
+        # edited, and we want to have the build be triggered when the
+        # thing-that-was-copied-there changes.
 
-    def PathFixup(path):
-      """Fixes path for depfile format: backslash to forward slash, and
+        def PathFixup(path):
+            """Fixes path for depfile format: backslash to forward slash, and
       backslash escaping for spaces."""
-      return path.replace('\\', '/').replace(' ', '\\ ')
+            return path.replace('\\', '/').replace(' ', '\\ ')
 
-    # Gather the list of files in the staging dir that will be zipped up. We
-    # only gather this list to make sure that g_archive_inputs is complete (i.e.
-    # that there's not file copies that got missed).
-    staging_contents = []
-    for root, files in os.walk(os.path.join(staging_dir, UPDATER_DIR)):
-      for filename in files:
-        staging_contents.append(PathFixup(os.path.join(root, filename)))
+        # Gather the list of files in the staging dir that will be zipped up.
+        # We only gather this list to make sure that g_archive_inputs is
+        # complete (i.e. that there's not file copies that got missed).
+        staging_contents = []
+        for root, files in os.walk(os.path.join(staging_dir, UPDATER_DIR)):
+            for filename in files:
+                staging_contents.append(PathFixup(os.path.join(root,
+                                                               filename)))
 
-    # Make sure there's an archive_input for each staging dir file.
-    for staging_file in staging_contents:
-      for archive_input in g_archive_inputs:
-        archive_rel = PathFixup(archive_input)
-        if (os.path.basename(staging_file).lower() ==
-            os.path.basename(archive_rel).lower()):
-          break
-      else:
-        raise Exception('Did not find an archive input file for "%s"' %
-                        staging_file)
+        # Make sure there's an archive_input for each staging dir file.
+        for staging_file in staging_contents:
+            for archive_input in g_archive_inputs:
+                archive_rel = PathFixup(archive_input)
+                if (os.path.basename(staging_file).lower() == os.path.basename(
+                        archive_rel).lower()):
+                    break
+            else:
+                raise Exception('Did not find an archive input file for "%s"' %
+                                staging_file)
 
-    # Finally, write the depfile referencing the inputs.
-    with open(options.depfile, 'wb') as f:
-      f.write(PathFixup(os.path.relpath(archive_file, options.build_dir)) +
-              ': \\\n')
-      f.write('  ' + ' \\\n  '.join(PathFixup(x) for x in g_archive_inputs))
+        # Finally, write the depfile referencing the inputs.
+        with open(options.depfile, 'wb') as f:
+            f.write(
+                PathFixup(os.path.relpath(archive_file, options.build_dir)) +
+                ': \\\n')
+            f.write('  ' +
+                    ' \\\n  '.join(PathFixup(x) for x in g_archive_inputs))
 
-  # It is important to use abspath to create the path to the directory because
-  # if you use a relative path without any .. sequences then 7za.exe uses the
-  # entire relative path as part of the file paths in the archive. If you have
-  # a .. sequence or an absolute path then only the last directory is stored as
-  # part of the file paths in the archive, which is what we want.
-  cmd = [lzma_exec,
-         'a',
-         '-t7z',
-         archive_file,
-         os.path.abspath(os.path.join(staging_dir, UPDATER_DIR)),
-         '-mx0',]
-  # There does not seem to be any way in 7za.exe to override existing file so
-  # we always delete before creating a new one.
-  if not os.path.exists(archive_file):
-    RunSystemCommand(cmd, options.verbose)
-  elif options.skip_rebuild_archive != "true":
-    os.remove(archive_file)
-    RunSystemCommand(cmd, options.verbose)
+    # It is important to use abspath to create the path to the directory because
+    # if you use a relative path without any .. sequences then 7za.exe uses the
+    # entire relative path as part of the file paths in the archive. If you have
+    # a .. sequence or an absolute path then only the last directory is stored
+    # as part of the file paths in the archive, which is what we want.
+    cmd = [
+        lzma_exec,
+        'a',
+        '-t7z',
+        archive_file,
+        os.path.abspath(os.path.join(staging_dir, UPDATER_DIR)),
+        '-mx0',
+    ]
+    # There does not seem to be any way in 7za.exe to override existing file so
+    # we always delete before creating a new one.
+    if not os.path.exists(archive_file):
+        RunSystemCommand(cmd, options.verbose)
+    elif options.skip_rebuild_archive != "true":
+        os.remove(archive_file)
+        RunSystemCommand(cmd, options.verbose)
 
-  # Do not compress the archive when skip_archive_compression is specified.
-  if options.skip_archive_compression:
-    compressed_file = os.path.join(
-        options.output_dir, options.output_name + COMPRESSED_ARCHIVE_SUFFIX)
-    if os.path.exists(compressed_file):
-      os.remove(compressed_file)
-    return os.path.basename(archive_file)
+    # Do not compress the archive when skip_archive_compression is specified.
+    if options.skip_archive_compression:
+        compressed_file = os.path.join(
+            options.output_dir,
+            options.output_name + COMPRESSED_ARCHIVE_SUFFIX)
+        if os.path.exists(compressed_file):
+            os.remove(compressed_file)
+        return os.path.basename(archive_file)
 
-  compressed_archive_file = options.output_name + COMPRESSED_ARCHIVE_SUFFIX
-  compressed_archive_file_path = os.path.join(options.output_dir,
-                                              compressed_archive_file)
-  os.utime(archive_file, (os.stat(archive_file).st_atime, timestamp))
-  CompressUsingLZMA(options.build_dir, compressed_archive_file_path,
-                    archive_file, options.verbose)
+    compressed_archive_file = options.output_name + COMPRESSED_ARCHIVE_SUFFIX
+    compressed_archive_file_path = os.path.join(options.output_dir,
+                                                compressed_archive_file)
+    os.utime(archive_file, (os.stat(archive_file).st_atime, timestamp))
+    CompressUsingLZMA(options.build_dir, compressed_archive_file_path,
+                      archive_file, options.verbose)
 
-  return compressed_archive_file
+    return compressed_archive_file
 
 
 _RESOURCE_FILE_HEADER = """\
@@ -224,129 +234,151 @@
 // separate path components.
 """
 
-def CreateResourceInputFile(
-    output_dir, archive_file, resource_file_path,
-    component_build, staging_dir):
-  """Creates resource input file for installer target."""
 
-  # An array of (file, type, path) tuples of the files to be included.
-  resources = [(archive_file, 'B7',
-                    os.path.join(output_dir, archive_file))]
+def CreateResourceInputFile(output_dir, archive_file, resource_file_path,
+                            component_build, staging_dir):
+    """Creates resource input file for installer target."""
 
-  with open(resource_file_path, 'w') as f:
-    f.write(_RESOURCE_FILE_HEADER)
-    for (file, type, path) in resources:
-      f.write('\n%s  %s\n    "%s"\n' % (file, type, path.replace("\\","/")))
+    # An array of (file, type, path) tuples of the files to be included.
+    resources = [(archive_file, 'B7', os.path.join(output_dir, archive_file))]
+
+    with open(resource_file_path, 'w') as f:
+        f.write(_RESOURCE_FILE_HEADER)
+        for (file, type, path) in resources:
+            f.write('\n%s  %s\n    "%s"\n' %
+                    (file, type, path.replace("\\", "/")))
 
 
 def ParseDLLsFromDeps(build_dir, runtime_deps_file):
-  """Parses the runtime_deps file and returns the set of DLLs in it, relative
-  to build_dir."""
-  build_dlls = set()
-  args = open(runtime_deps_file).read()
-  for l in args.splitlines():
-    if os.path.splitext(l)[1] == ".dll":
-      build_dlls.add(os.path.join(build_dir, l))
-  return build_dlls
+    """Parses the runtime_deps file and returns the set of DLLs in it, relative
+    to build_dir."""
+    build_dlls = set()
+    args = open(runtime_deps_file).read()
+    for l in args.splitlines():
+        if os.path.splitext(l)[1] == ".dll":
+            build_dlls.add(os.path.join(build_dir, l))
+    return build_dlls
+
 
 # Copies component build DLLs for the setup to be able to find those DLLs at
 # run-time.
 # This is meant for developer builds only and should never be used to package
 # an official build.
 def DoComponentBuildTasks(staging_dir, build_dir, setup_runtime_deps):
-  installer_dir = os.path.join(staging_dir, UPDATER_DIR)
-  if not os.path.exists(installer_dir):
-    os.mkdir(installer_dir)
+    installer_dir = os.path.join(staging_dir, UPDATER_DIR)
+    if not os.path.exists(installer_dir):
+        os.mkdir(installer_dir)
 
-  setup_component_dlls = ParseDLLsFromDeps(build_dir, setup_runtime_deps)
+    setup_component_dlls = ParseDLLsFromDeps(build_dir, setup_runtime_deps)
 
-  for setup_component_dll in setup_component_dlls:
-    g_archive_inputs.append(setup_component_dll)
-    shutil.copy(setup_component_dll, installer_dir)
+    for setup_component_dll in setup_component_dlls:
+        g_archive_inputs.append(setup_component_dll)
+        shutil.copy(setup_component_dll, installer_dir)
+
 
 def main(options):
-  """Main method that reads input file, creates archive file and writes
-  resource input file.
-  """
-  config = Readconfig(options.input_file)
+    """Main method that reads input file, creates archive file and writes
+    resource input file."""
+    config = Readconfig(options.input_file)
 
-  staging_dir = MakeStagingDirectory(options.staging_dir)
+    staging_dir = MakeStagingDirectory(options.staging_dir)
 
-  # Copy the files from the build dir.
-  CopyAllFilesToStagingDir(config, staging_dir, options.build_dir,
-                           options.timestamp)
+    # Copy the files from the build dir.
+    CopyAllFilesToStagingDir(config, staging_dir, options.build_dir,
+                             options.timestamp)
 
-  if options.component_build == '1':
-    DoComponentBuildTasks(staging_dir, options.build_dir,
-                          options.setup_runtime_deps)
+    if options.component_build == '1':
+        DoComponentBuildTasks(staging_dir, options.build_dir,
+                              options.setup_runtime_deps)
 
-  # Name of the archive file built (for example - updater.7z)
-  archive_file = CreateArchiveFile(options, staging_dir, options.timestamp)
-  CreateResourceInputFile(options.output_dir,
-                          archive_file, options.resource_file_path,
-                          options.component_build == '1', staging_dir)
+    # Name of the archive file built (for example - updater.7z)
+    archive_file = CreateArchiveFile(options, staging_dir, options.timestamp)
+    CreateResourceInputFile(options.output_dir, archive_file,
+                            options.resource_file_path,
+                            options.component_build == '1', staging_dir)
+
 
 def _ParseOptions():
-  parser = optparse.OptionParser()
-  parser.add_option('-i', '--input_file',
-      help='Input file describing which files to archive.')
-  parser.add_option('-b', '--build_dir',
-      help='Build directory. The paths in input_file are relative to this.')
-  parser.add_option('--staging_dir',
-      help='Staging directory where intermediate files and directories '
-           'will be created')
-  parser.add_option('-o', '--output_dir',
-      help='The output directory where the archives will be written. '
-            'Defaults to the build_dir.')
-  parser.add_option('--resource_file_path',
-      help='The path where the resource file will be output. ')
-  parser.add_option('-s', '--skip_rebuild_archive',
-      default="False", help='Skip re-building updater.7z archive if it exists.')
-  parser.add_option('-n', '--output_name', default='updater',
-      help='Name used to prefix names of generated archives.')
-  parser.add_option('--component_build', default='0',
-      help='Whether this archive is packaging a component build.')
-  parser.add_option('--skip_archive_compression',
-      action='store_true', default=False,
-      help='Turn off compression of updater.7z into updater.packed.7z and '
-           'helpfully delete any old updater.packed.7z in |output_dir|.')
-  parser.add_option('--depfile',
-      help='Generate a depfile with the given name listing the implicit inputs '
-           'to the archive process that can be used with a build system.')
-  parser.add_option('--setup_runtime_deps',
-      help='A file listing runtime dependencies for setup.exe. This will be '
-           'used to get a list of DLLs to archive in a component build.')
-  parser.add_option('-v', '--verbose', action='store_true', dest='verbose',
-                    default=False)
-  parser.add_option(
-      '--timestamp',
-      type='int',
-      help='Timestamp to set archive entry modified times to.')
+    parser = optparse.OptionParser()
+    parser.add_option('-i',
+                      '--input_file',
+                      help='Input file describing which files to archive.')
+    parser.add_option(
+        '-b',
+        '--build_dir',
+        help='Build directory. The paths in input_file are relative to this.')
+    parser.add_option(
+        '--staging_dir',
+        help='Staging directory where intermediate files and directories '
+        'will be created')
+    parser.add_option(
+        '-o',
+        '--output_dir',
+        help='The output directory where the archives will be written. '
+        'Defaults to the build_dir.')
+    parser.add_option('--resource_file_path',
+                      help='The path where the resource file will be output. ')
+    parser.add_option('-s',
+                      '--skip_rebuild_archive',
+                      default="False",
+                      help='Skip re-building updater.7z archive if it exists.')
+    parser.add_option('-n',
+                      '--output_name',
+                      default='updater',
+                      help='Name used to prefix names of generated archives.')
+    parser.add_option(
+        '--component_build',
+        default='0',
+        help='Whether this archive is packaging a component build.')
+    parser.add_option(
+        '--skip_archive_compression',
+        action='store_true',
+        default=False,
+        help='Turn off compression of updater.7z into updater.packed.7z and '
+        'helpfully delete any old updater.packed.7z in |output_dir|.')
+    parser.add_option(
+        '--depfile',
+        help=
+        'Generate a depfile with the given name listing the implicit inputs '
+        'to the archive process that can be used with a build system.')
+    parser.add_option(
+        '--setup_runtime_deps',
+        help='A file listing runtime dependencies for setup.exe. This will be '
+        'used to get a list of DLLs to archive in a component build.')
+    parser.add_option('-v',
+                      '--verbose',
+                      action='store_true',
+                      dest='verbose',
+                      default=False)
+    parser.add_option('--timestamp',
+                      type='int',
+                      help='Timestamp to set archive entry modified times to.')
 
-  options, _ = parser.parse_args()
-  if not options.build_dir:
-    parser.error('You must provide a build dir.')
+    options, _ = parser.parse_args()
+    if not options.build_dir:
+        parser.error('You must provide a build dir.')
 
-  options.build_dir = os.path.normpath(options.build_dir)
+    options.build_dir = os.path.normpath(options.build_dir)
 
-  if not options.staging_dir:
-    parser.error('You must provide a staging dir.')
+    if not options.staging_dir:
+        parser.error('You must provide a staging dir.')
 
-  if not options.input_file:
-    parser.error('You must provide an input file')
+    if not options.input_file:
+        parser.error('You must provide an input file')
 
-  is_component_build = options.component_build == '1'
-  if is_component_build and not options.setup_runtime_deps:
-    parser.error("updater_runtime_deps must be specified for a component build")
+    is_component_build = options.component_build == '1'
+    if is_component_build and not options.setup_runtime_deps:
+        parser.error(
+            "updater_runtime_deps must be specified for a component build")
 
-  if not options.output_dir:
-    options.output_dir = options.build_dir
+    if not options.output_dir:
+        options.output_dir = options.build_dir
 
-  return options
+    return options
 
 
 if '__main__' == __name__:
-  options = _ParseOptions()
-  if options.verbose:
-    print(sys.argv)
-  sys.exit(main(options))
+    options = _ParseOptions()
+    if options.verbose:
+        print(sys.argv)
+    sys.exit(main(options))
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn
index f4d3c87..fe55900e9 100644
--- a/chromecast/browser/BUILD.gn
+++ b/chromecast/browser/BUILD.gn
@@ -276,6 +276,7 @@
     "//components/services/heap_profiling",
     "//components/services/heap_profiling/public/cpp",
     "//components/services/heap_profiling/public/mojom",
+    "//components/url_matcher",
     "//components/viz/service",
     "//content/public/browser",
     "//content/public/common",
diff --git a/chromecast/browser/DEPS b/chromecast/browser/DEPS
index a096691..f0cd1042 100644
--- a/chromecast/browser/DEPS
+++ b/chromecast/browser/DEPS
@@ -41,6 +41,7 @@
   "+components/services/heap_profiling/public/cpp/settings.h",
   "+components/storage_monitor",
   "+components/ui_devtools",
+  "+components/url_matcher",
   "+components/user_prefs",
   "+components/value_store",
   "+components/variations/net",
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index 8912abd..c1af2705 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -961,6 +961,14 @@
 #endif  // BUILDFLAG(ENABLE_CHROMECAST_WEBUI)
 }
 
+bool CastContentBrowserClient::ShouldAllowInsecurePrivateNetworkRequests(
+    content::BrowserContext* browser_context,
+    const url::Origin& origin) {
+  // Some Cast apps hosted over HTTP needs to access the private network so that
+  // media can be streamed from a local media server.
+  return true;
+}
+
 std::string CastContentBrowserClient::GetUserAgent() {
   return chromecast::GetUserAgent();
 }
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h
index 8d8271d2..447562d3 100644
--- a/chromecast/browser/cast_content_browser_client.h
+++ b/chromecast/browser/cast_content_browser_client.h
@@ -264,6 +264,9 @@
   bool DoesSiteRequireDedicatedProcess(content::BrowserContext* browser_context,
                                        const GURL& effective_site_url) override;
   bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin) override;
+  bool ShouldAllowInsecurePrivateNetworkRequests(
+      content::BrowserContext* browser_context,
+      const url::Origin& origin) override;
   // New Mojo bindings should be added to
   // cast_content_browser_client_receiver_bindings.cc, so that they go through
   // security review.
diff --git a/chromecast/browser/general_audience_browsing_navigation_throttle.cc b/chromecast/browser/general_audience_browsing_navigation_throttle.cc
index d291811..d096b5f 100644
--- a/chromecast/browser/general_audience_browsing_navigation_throttle.cc
+++ b/chromecast/browser/general_audience_browsing_navigation_throttle.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "chromecast/browser/general_audience_browsing_service.h"
-#include "components/policy/core/browser/url_util.h"
+#include "components/url_matcher/url_util.h"
 #include "content/public/browser/navigation_handle.h"
 #include "url/gurl.h"
 
@@ -36,10 +36,10 @@
   if (!url.SchemeIsHTTPOrHTTPS())
     return PROCEED;
 
-  GURL effective_url = policy::url_util::GetEmbeddedURL(url);
+  GURL effective_url = url_matcher::util::GetEmbeddedURL(url);
   if (!effective_url.is_valid())
     effective_url = url;
-  GURL normalized_url = policy::url_util::Normalize(effective_url);
+  GURL normalized_url = url_matcher::util::Normalize(effective_url);
 
   bool synchronous = general_audience_browsing_service_->CheckURL(
       effective_url,
diff --git a/chromecast/browser/general_audience_browsing_service.cc b/chromecast/browser/general_audience_browsing_service.cc
index a2477aa..2795c98 100644
--- a/chromecast/browser/general_audience_browsing_service.cc
+++ b/chromecast/browser/general_audience_browsing_service.cc
@@ -6,9 +6,9 @@
 
 #include "chromecast/browser/system_connector.h"
 #include "chromecast/common/mojom/constants.mojom.h"
-#include "components/policy/core/browser/url_util.h"
 #include "components/safe_search_api/safe_search/safe_search_url_checker_client.h"
 #include "components/safe_search_api/url_checker.h"
+#include "components/url_matcher/url_util.h"
 #include "net/base/net_errors.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -76,7 +76,7 @@
   }
 
   return safe_search_url_checker_->CheckURL(
-      policy::url_util::Normalize(url),
+      url_matcher::util::Normalize(url),
       base::BindOnce(&CheckURLCallbackWrapper, std::move(callback)));
 }
 
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd
index e0af001..51d632e 100644
--- a/chromeos/chromeos_strings.grd
+++ b/chromeos/chromeos_strings.grd
@@ -2400,6 +2400,12 @@
       <message name="IDS_SHIMLESS_RMA_CONFIRM_DEVICE_INFO_REGION_LABEL" translateable="false" desc="The label for the text input showing the device's current region.">
         Region
       </message>
+      <message name="IDS_SHIMLESS_RMA_CONFIRM_DEVICE_INFO_WHITE_LABEL_LABEL" translateable="false" desc="The label for the text input showing the device's white-label.">
+        White-label
+      </message>
+      <message name="IDS_SHIMLESS_RMA_CONFIRM_DEVICE_INFO_EMPTY_WHITE_LABEL_LABEL" translateable="false" desc="The label for the selection option that clears the device's white-label.">
+        --no white-label--
+      </message>
       <message name="IDS_SHIMLESS_RMA_CONFIRM_DEVICE_INFO_SKU_LABEL" translateable="false" desc="The label for the text input showing the device's SKU.">
         SKU
       </message>
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom
index ed64d770..4865dd5 100644
--- a/chromeos/crosapi/mojom/crosapi.mojom
+++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -92,7 +92,7 @@
 // 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: 62
+// Next version: 61
 // Next method id: 65
 [Stable, Uuid="8b79c34f-2bf8-4499-979a-b17cac522c1e",
  RenamedFrom="crosapi.mojom.AshChromeService"]
@@ -849,7 +849,7 @@
 // has accidentally become a kitchen sink for different features. This was not
 // intentional.
 //
-// Next MinVersion: 16.
+// Next MinVersion: 62.
 // Next ID: 14
 //
 [Stable, Uuid="4e04dc16-b34c-40fd-9e3f-3c55c2c6cf91",
diff --git a/chromeos/dbus/dlp/fake_dlp_client.cc b/chromeos/dbus/dlp/fake_dlp_client.cc
index 26d970ae..7ec9d4c22 100644
--- a/chromeos/dbus/dlp/fake_dlp_client.cc
+++ b/chromeos/dbus/dlp/fake_dlp_client.cc
@@ -5,11 +5,24 @@
 #include "chromeos/dbus/dlp/fake_dlp_client.h"
 
 #include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "chromeos/dbus/dlp/dlp_service.pb.h"
 
 namespace chromeos {
 
+namespace {
+
+ino_t GetInodeValue(const base::FilePath& path) {
+  struct stat file_stats;
+  if (stat(path.value().c_str(), &file_stats) != 0)
+    return 0;
+  return file_stats.st_ino;
+}
+
+}  // namespace
+
 FakeDlpClient::FakeDlpClient() = default;
 
 FakeDlpClient::~FakeDlpClient() = default;
@@ -24,13 +37,31 @@
 }
 
 void FakeDlpClient::AddFile(const dlp::AddFileRequest request,
-                            AddFileCallback callback) {}
+                            AddFileCallback callback) {
+  if (request.has_file_path() && request.has_source_url()) {
+    files_database_[GetInodeValue(base::FilePath(request.file_path()))] =
+        request.source_url();
+  }
+  dlp::AddFileResponse response;
+  std::move(callback).Run(response);
+}
 
 void FakeDlpClient::GetFilesSources(const dlp::GetFilesSourcesRequest request,
-                                    GetFilesSourcesCallback callback) const {}
+                                    GetFilesSourcesCallback callback) const {
+  dlp::GetFilesSourcesResponse response;
+  for (const auto& file_inode : request.files_inodes()) {
+    auto file_itr = files_database_.find(file_inode);
+    if (file_itr != files_database_.end()) {
+      dlp::FileMetadata* file_metadata = response.add_files_metadata();
+      file_metadata->set_inode(file_itr->first);
+      file_metadata->set_source_url(file_itr->second);
+    }
+  }
+  std::move(callback).Run(response);
+}
 
 bool FakeDlpClient::IsAlive() const {
-  return false;
+  return true;
 }
 
 DlpClient::TestInterface* FakeDlpClient::GetTestInterface() {
diff --git a/chromeos/dbus/dlp/fake_dlp_client.h b/chromeos/dbus/dlp/fake_dlp_client.h
index 599d167..ebdbc5b 100644
--- a/chromeos/dbus/dlp/fake_dlp_client.h
+++ b/chromeos/dbus/dlp/fake_dlp_client.h
@@ -5,6 +5,9 @@
 #ifndef CHROMEOS_DBUS_DLP_FAKE_DLP_CLIENT_H_
 #define CHROMEOS_DBUS_DLP_FAKE_DLP_CLIENT_H_
 
+#include <string>
+
+#include "base/containers/flat_map.h"
 #include "chromeos/dbus/dlp/dlp_client.h"
 #include "chromeos/dbus/dlp/dlp_service.pb.h"
 #include "dbus/object_proxy.h"
@@ -35,6 +38,7 @@
 
  private:
   int set_dlp_files_policy_count_ = 0;
+  base::flat_map<ino_t, std::string> files_database_;
 };
 
 }  // namespace chromeos
diff --git a/chromeos/network/cellular_connection_handler.cc b/chromeos/network/cellular_connection_handler.cc
index e49f1af1..65eb838 100644
--- a/chromeos/network/cellular_connection_handler.cc
+++ b/chromeos/network/cellular_connection_handler.cc
@@ -89,11 +89,11 @@
       return NetworkConnectionHandler::kErrorCellularInhibitFailure;
 
     case PrepareCellularConnectionResult::kCouldNotFindRelevantEuicc:
-      FALLTHROUGH;
+      [[fallthrough]];
     case PrepareCellularConnectionResult::kRefreshProfilesFailed:
-      FALLTHROUGH;
+      [[fallthrough]];
     case PrepareCellularConnectionResult::kCouldNotFindRelevantESimProfile:
-      FALLTHROUGH;
+      [[fallthrough]];
     case PrepareCellularConnectionResult::kEnableProfileFailed:
       return NetworkConnectionHandler::kErrorESimProfileIssue;
 
diff --git a/chromeos/network/cellular_metrics_logger.cc b/chromeos/network/cellular_metrics_logger.cc
index 017ea2cc6..6618c27 100644
--- a/chromeos/network/cellular_metrics_logger.cc
+++ b/chromeos/network/cellular_metrics_logger.cc
@@ -679,13 +679,13 @@
   for (const auto& profile : esim_profiles) {
     switch (profile.state()) {
       case CellularESimProfile::State::kPending:
-        FALLTHROUGH;
+        [[fallthrough]];
       case CellularESimProfile::State::kInstalling:
         pending_profiles_exist = true;
         break;
 
       case CellularESimProfile::State::kInactive:
-        FALLTHROUGH;
+        [[fallthrough]];
       case CellularESimProfile::State::kActive:
         active_profiles_exist = true;
         break;
diff --git a/chromeos/network/metrics/network_metrics_helper.cc b/chromeos/network/metrics/network_metrics_helper.cc
index 823867bc..0291b1e 100644
--- a/chromeos/network/metrics/network_metrics_helper.cc
+++ b/chromeos/network/metrics/network_metrics_helper.cc
@@ -127,9 +127,9 @@
     // There should not be connections requests for kEthernetEap type service.
     // kEthernetEap exists only to store auth details for ethernet.
     case NetworkState::NetworkTechnologyType::kEthernetEap:
-      FALLTHROUGH;
+      [[fallthrough]];
     case NetworkState::NetworkTechnologyType::kUnknown:
-      FALLTHROUGH;
+      [[fallthrough]];
     default:
       return {};
   }
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt
index bcc4357f..bab9823 100644
--- a/chromeos/profiles/orderfile.newest.txt
+++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@
-chromeos-chrome-orderfile-field-98-4758.0-1639998454-benchmark-98.0.4758.21-r1.orderfile.xz
+chromeos-chrome-orderfile-field-99-4758.14-1640601734-benchmark-99.0.4799.0-r1.orderfile.xz
diff --git a/chromeos/services/bluetooth_config/device_conversion_util.cc b/chromeos/services/bluetooth_config/device_conversion_util.cc
index 50d113b..12257d59 100644
--- a/chromeos/services/bluetooth_config/device_conversion_util.cc
+++ b/chromeos/services/bluetooth_config/device_conversion_util.cc
@@ -28,12 +28,12 @@
       return mojom::DeviceType::kComputer;
 
     case device::BluetoothDeviceType::PHONE:
-      FALLTHROUGH;
+      [[fallthrough]];
     case device::BluetoothDeviceType::MODEM:
       return mojom::DeviceType::kPhone;
 
     case device::BluetoothDeviceType::AUDIO:
-      FALLTHROUGH;
+      [[fallthrough]];
     case device::BluetoothDeviceType::CAR_AUDIO:
       return mojom::DeviceType::kHeadset;
 
@@ -41,14 +41,14 @@
       return mojom::DeviceType::kVideoCamera;
 
     case device::BluetoothDeviceType::PERIPHERAL:
-      FALLTHROUGH;
+      [[fallthrough]];
     case device::BluetoothDeviceType::JOYSTICK:
-      FALLTHROUGH;
+      [[fallthrough]];
     case device::BluetoothDeviceType::GAMEPAD:
       return mojom::DeviceType::kGameController;
 
     case device::BluetoothDeviceType::KEYBOARD:
-      FALLTHROUGH;
+      [[fallthrough]];
     case device::BluetoothDeviceType::KEYBOARD_MOUSE_COMBO:
       return mojom::DeviceType::kKeyboard;
 
diff --git a/chromeos/services/bluetooth_config/device_pairing_handler.cc b/chromeos/services/bluetooth_config/device_pairing_handler.cc
index 878c39d..f24c0567 100644
--- a/chromeos/services/bluetooth_config/device_pairing_handler.cc
+++ b/chromeos/services/bluetooth_config/device_pairing_handler.cc
@@ -54,20 +54,20 @@
 
   switch (failure_reason.value()) {
     case device::ConnectionFailureReason::kAuthTimeout:
-      FALLTHROUGH;
+      [[fallthrough]];
     case device::ConnectionFailureReason::kAuthFailed:
       return mojom::PairingResult::kAuthFailed;
 
     case device::ConnectionFailureReason::kUnknownError:
-      FALLTHROUGH;
+      [[fallthrough]];
     case device::ConnectionFailureReason::kSystemError:
-      FALLTHROUGH;
+      [[fallthrough]];
     case device::ConnectionFailureReason::kFailed:
-      FALLTHROUGH;
+      [[fallthrough]];
     case device::ConnectionFailureReason::kUnknownConnectionError:
-      FALLTHROUGH;
+      [[fallthrough]];
     case device::ConnectionFailureReason::kUnsupportedDevice:
-      FALLTHROUGH;
+      [[fallthrough]];
     case device::ConnectionFailureReason::kNotConnectable:
       return mojom::PairingResult::kNonAuthFailure;
   }
@@ -223,9 +223,9 @@
   using ErrorCode = device::BluetoothDevice::ConnectErrorCode;
   switch (error_code.value()) {
     case ErrorCode::ERROR_AUTH_CANCELED:
-      FALLTHROUGH;
+      [[fallthrough]];
     case ErrorCode::ERROR_AUTH_FAILED:
-      FALLTHROUGH;
+      [[fallthrough]];
     case ErrorCode::ERROR_AUTH_REJECTED:
       FinishCurrentPairingRequest(device::ConnectionFailureReason::kAuthFailed);
       return;
@@ -235,7 +235,7 @@
       return;
 
     case ErrorCode::ERROR_FAILED:
-      FALLTHROUGH;
+      [[fallthrough]];
     case ErrorCode::ERROR_INPROGRESS:
       FinishCurrentPairingRequest(device::ConnectionFailureReason::kFailed);
       return;
diff --git a/chromeos/services/device_sync/cryptauth_device_manager_impl.cc b/chromeos/services/device_sync/cryptauth_device_manager_impl.cc
index 1d1a03b7..828c69e 100644
--- a/chromeos/services/device_sync/cryptauth_device_manager_impl.cc
+++ b/chromeos/services/device_sync/cryptauth_device_manager_impl.cc
@@ -372,7 +372,7 @@
         static_cast<multidevice::SoftwareFeatureState>(it.second.GetInt())) {
       case multidevice::SoftwareFeatureState::kEnabled:
         external_device->add_enabled_software_features(software_feature);
-        FALLTHROUGH;
+        [[fallthrough]];
       case multidevice::SoftwareFeatureState::kSupported:
         external_device->add_supported_software_features(software_feature);
         break;
diff --git a/chromeos/services/device_sync/cryptauth_device_manager_impl_unittest.cc b/chromeos/services/device_sync/cryptauth_device_manager_impl_unittest.cc
index 1e75fbaa..98c20d3 100644
--- a/chromeos/services/device_sync/cryptauth_device_manager_impl_unittest.cc
+++ b/chromeos/services/device_sync/cryptauth_device_manager_impl_unittest.cc
@@ -365,7 +365,7 @@
             it.second.GetInt())) {
           case multidevice::SoftwareFeatureState::kEnabled:
             enabled_software_features.push_back(software_feature);
-            FALLTHROUGH;
+            [[fallthrough]];
           case multidevice::SoftwareFeatureState::kSupported:
             supported_software_features.push_back(software_feature);
             break;
diff --git a/chromeos/services/device_sync/cryptauth_device_syncer_impl.cc b/chromeos/services/device_sync/cryptauth_device_syncer_impl.cc
index 46a12cd..a763235 100644
--- a/chromeos/services/device_sync/cryptauth_device_syncer_impl.cc
+++ b/chromeos/services/device_sync/cryptauth_device_syncer_impl.cc
@@ -312,7 +312,7 @@
   switch (CryptAuthDeviceSyncResult::GetResultType(device_sync_result_code)) {
     case CryptAuthDeviceSyncResult::ResultType::kNonFatalError:
       did_non_fatal_error_occur_ = true;
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthDeviceSyncResult::ResultType::kSuccess:
       // At a minimum, the local device metadata should be returned if no fatal
       // error occurred.
@@ -388,7 +388,7 @@
   switch (CryptAuthDeviceSyncResult::GetResultType(device_sync_result_code)) {
     case CryptAuthDeviceSyncResult::ResultType::kNonFatalError:
       did_non_fatal_error_occur_ = true;
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthDeviceSyncResult::ResultType::kSuccess:
       // We require that the local device feature statuses are returned; the
       // local device is needed in the registry.
@@ -697,7 +697,7 @@
   switch (CryptAuthDeviceSyncResult::GetResultType(device_sync_result_code)) {
     case CryptAuthDeviceSyncResult::ResultType::kNonFatalError:
       did_non_fatal_error_occur_ = true;
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthDeviceSyncResult::ResultType::kSuccess:
       AttemptNextStep();
       return;
diff --git a/chromeos/services/device_sync/cryptauth_feature_type.cc b/chromeos/services/device_sync/cryptauth_feature_type.cc
index 2e4dc284..ad6348bd 100644
--- a/chromeos/services/device_sync/cryptauth_feature_type.cc
+++ b/chromeos/services/device_sync/cryptauth_feature_type.cc
@@ -380,82 +380,82 @@
     CryptAuthFeatureType feature_type) {
   switch (feature_type) {
     case CryptAuthFeatureType::kBetterTogetherHostSupported:
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthFeatureType::kBetterTogetherHostEnabled:
       return multidevice::SoftwareFeature::kBetterTogetherHost;
 
     case CryptAuthFeatureType::kBetterTogetherClientSupported:
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthFeatureType::kBetterTogetherClientEnabled:
       return multidevice::SoftwareFeature::kBetterTogetherClient;
 
     case CryptAuthFeatureType::kEasyUnlockHostSupported:
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthFeatureType::kEasyUnlockHostEnabled:
       return multidevice::SoftwareFeature::kSmartLockHost;
 
     case CryptAuthFeatureType::kEasyUnlockClientSupported:
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthFeatureType::kEasyUnlockClientEnabled:
       return multidevice::SoftwareFeature::kSmartLockClient;
 
     case CryptAuthFeatureType::kMagicTetherHostSupported:
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthFeatureType::kMagicTetherHostEnabled:
       return multidevice::SoftwareFeature::kInstantTetheringHost;
 
     case CryptAuthFeatureType::kMagicTetherClientSupported:
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthFeatureType::kMagicTetherClientEnabled:
       return multidevice::SoftwareFeature::kInstantTetheringClient;
 
     case CryptAuthFeatureType::kSmsConnectHostSupported:
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthFeatureType::kSmsConnectHostEnabled:
       return multidevice::SoftwareFeature::kMessagesForWebHost;
 
     case CryptAuthFeatureType::kSmsConnectClientSupported:
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthFeatureType::kSmsConnectClientEnabled:
       return multidevice::SoftwareFeature::kMessagesForWebClient;
 
     case CryptAuthFeatureType::kPhoneHubHostSupported:
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthFeatureType::kPhoneHubHostEnabled:
       return multidevice::SoftwareFeature::kPhoneHubHost;
 
     case CryptAuthFeatureType::kPhoneHubClientSupported:
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthFeatureType::kPhoneHubClientEnabled:
       return multidevice::SoftwareFeature::kPhoneHubClient;
 
     case CryptAuthFeatureType::kWifiSyncHostSupported:
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthFeatureType::kWifiSyncHostEnabled:
       return multidevice::SoftwareFeature::kWifiSyncHost;
 
     case CryptAuthFeatureType::kWifiSyncClientSupported:
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthFeatureType::kWifiSyncClientEnabled:
       return multidevice::SoftwareFeature::kWifiSyncClient;
 
     case CryptAuthFeatureType::kEcheHostSupported:
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthFeatureType::kEcheHostEnabled:
       return multidevice::SoftwareFeature::kEcheHost;
 
     case CryptAuthFeatureType::kEcheClientSupported:
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthFeatureType::kEcheClientEnabled:
       return multidevice::SoftwareFeature::kEcheClient;
 
     case CryptAuthFeatureType::kPhoneHubCameraRollHostSupported:
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthFeatureType::kPhoneHubCameraRollHostEnabled:
       return multidevice::SoftwareFeature::kPhoneHubCameraRollHost;
 
     case CryptAuthFeatureType::kPhoneHubCameraRollClientSupported:
-      FALLTHROUGH;
+      [[fallthrough]];
     case CryptAuthFeatureType::kPhoneHubCameraRollClientEnabled:
       return multidevice::SoftwareFeature::kPhoneHubCameraRollClient;
   }
diff --git a/chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.cc b/chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.cc
index 79a82713..f789ba3 100644
--- a/chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.cc
+++ b/chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.cc
@@ -425,13 +425,13 @@
 
   switch (user_key_pair_state) {
     case (UserKeyPairState::kNoV1KeyNoV2Key):
-      FALLTHROUGH;
+      [[fallthrough]];
     case (UserKeyPairState::kNoV1KeyYesV2Key):
-      FALLTHROUGH;
+      [[fallthrough]];
     case (UserKeyPairState::kYesV1KeyYesV2KeyAgree):
       return;
     case (UserKeyPairState::kYesV1KeyNoV2Key):
-      FALLTHROUGH;
+      [[fallthrough]];
     case (UserKeyPairState::kYesV1KeyYesV2KeyDisagree):
       key_registry_->AddKey(CryptAuthKeyBundle::Name::kUserKeyPair,
                             CryptAuthKey(public_key_v1, private_key_v1,
diff --git a/chromeos/services/device_sync/device_sync_impl.cc b/chromeos/services/device_sync/device_sync_impl.cc
index db3025a3..9c186c4 100644
--- a/chromeos/services/device_sync/device_sync_impl.cc
+++ b/chromeos/services/device_sync/device_sync_impl.cc
@@ -793,7 +793,7 @@
       ProcessPrimaryAccountInfo(event.GetCurrentState().primary_account);
       break;
     case signin::PrimaryAccountChangeEvent::Type::kCleared:
-      FALLTHROUGH;
+      [[fallthrough]];
     case signin::PrimaryAccountChangeEvent::Type::kNone:
       // Ignored
       break;
diff --git a/chromeos/services/secure_channel/pending_nearby_initiator_connection_request.cc b/chromeos/services/secure_channel/pending_nearby_initiator_connection_request.cc
index a24ef319..de9acbf31 100644
--- a/chromeos/services/secure_channel/pending_nearby_initiator_connection_request.cc
+++ b/chromeos/services/secure_channel/pending_nearby_initiator_connection_request.cc
@@ -73,9 +73,9 @@
 
   switch (failure_detail) {
     case NearbyInitiatorFailureType::kNearbyApiError:
-      FALLTHROUGH;
+      [[fallthrough]];
     case NearbyInitiatorFailureType::kConnectionRejected:
-      FALLTHROUGH;
+      [[fallthrough]];
     case NearbyInitiatorFailureType::kConnectivityError:
       StopRequestDueToConnectionFailures(
           mojom::ConnectionAttemptFailureReason::NEARBY_CONNECTION_ERROR);
diff --git a/chromeos/services/secure_channel/secure_channel_impl.cc b/chromeos/services/secure_channel/secure_channel_impl.cc
index 83810c9..fece2b23 100644
--- a/chromeos/services/secure_channel/secure_channel_impl.cc
+++ b/chromeos/services/secure_channel/secure_channel_impl.cc
@@ -230,7 +230,7 @@
 
       // Nearby Connections requires Bluetooth functionality, so fall through to
       // the Bluetooth case below.
-      FALLTHROUGH;
+      [[fallthrough]];
     case ConnectionMedium::kBluetoothLowEnergy:
       // Is the local Bluetooth adapter disabled or not present? If either,
       // notify client and return early.
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index b11722f..48d68f8 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -141,8 +141,7 @@
 
 void AutofillManager::OnLanguageDetermined(
     const translate::LanguageDetectionDetails& details) {
-  if (!base::FeatureList::IsEnabled(
-          features::kAutofillParsingPatternsLanguageDetection)) {
+  if (!base::FeatureList::IsEnabled(features::kAutofillPageLanguageDetection)) {
     return;
   }
   for (auto& p : form_structures_) {
diff --git a/components/autofill/core/browser/browser_autofill_manager_unittest.cc b/components/autofill/core/browser/browser_autofill_manager_unittest.cc
index 2435fbf..33d0682 100644
--- a/components/autofill/core/browser/browser_autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/browser_autofill_manager_unittest.cc
@@ -9319,7 +9319,7 @@
 TEST_F(BrowserAutofillManagerTest, PageLanguageGetsCorrectlyDetected) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(
-      features::kAutofillParsingPatternsLanguageDetection);
+      features::kAutofillPageLanguageDetection);
 
   FormData form;
   test::CreateTestAddressFormData(&form);
diff --git a/components/autofill/core/browser/form_parsing/form_field.cc b/components/autofill/core/browser/form_parsing/form_field.cc
index 4932d8e..eb0cbe3 100644
--- a/components/autofill/core/browser/form_parsing/form_field.cc
+++ b/components/autofill/core/browser/form_parsing/form_field.cc
@@ -165,11 +165,12 @@
 }
 
 // static
-bool FormField::ParseField(AutofillScanner* scanner,
-                           base::StringPiece16 pattern,
-                           AutofillField** match,
-                           const RegExLogging& logging) {
-  return ParseFieldSpecifics(scanner, pattern, MATCH_DEFAULT, match, logging);
+bool FormField::ParseFieldWithLegacyPattern(AutofillScanner* scanner,
+                                            base::StringPiece16 pattern,
+                                            AutofillField** match,
+                                            const RegExLogging& logging) {
+  return ParseFieldSpecificsWithLegacyPattern(scanner, pattern, MATCH_DEFAULT,
+                                              match, logging);
 }
 
 bool FormField::ParseField(AutofillScanner* scanner,
@@ -184,22 +185,18 @@
                            const std::vector<MatchingPattern>& patterns,
                            AutofillField** match,
                            const RegExLogging& logging) {
-  if (base::FeatureList::IsEnabled(
-          features::kAutofillParsingPatternsLanguageDependent) ||
-      base::FeatureList::IsEnabled(
-          features::kAutofillParsingPatternsNegativeMatching)) {
-    return ParseField(scanner, patterns, match, logging);
-  } else {
-    return ParseField(scanner, pattern, match, logging);
-  }
+  return base::FeatureList::IsEnabled(features::kAutofillParsingPatternProvider)
+             ? ParseField(scanner, patterns, match, logging)
+             : ParseFieldWithLegacyPattern(scanner, pattern, match, logging);
 }
 
-bool FormField::ParseFieldSpecifics(AutofillScanner* scanner,
-                                    base::StringPiece16 pattern,
-                                    int match_field_attributes,
-                                    int match_field_input_types,
-                                    AutofillField** match,
-                                    const RegExLogging& logging) {
+bool FormField::ParseFieldSpecificsWithLegacyPattern(
+    AutofillScanner* scanner,
+    base::StringPiece16 pattern,
+    int match_field_attributes,
+    int match_field_input_types,
+    AutofillField** match,
+    const RegExLogging& logging) {
   if (scanner->IsEnd())
     return false;
 
@@ -229,21 +226,30 @@
       continue;
     }
 
-    // TODO(crbug.com/1132831): Remove feature check once launched.
-    if (base::FeatureList::IsEnabled(
-            features::kAutofillParsingPatternsNegativeMatching)) {
-      if (!pattern.negative_pattern.empty() &&
-          FormField::Match(field, pattern.negative_pattern,
-                           pattern.match_field_attributes,
-                           pattern.match_field_input_types, logging)) {
-        continue;
+    // For each of the two match field attributes, MATCH_NAME and MATCH_LABEL,
+    // that are active for the current pattern, test if it matches the negative
+    // pattern. If yes, remove it from the attributes that are considered for
+    // positive matching.
+    uint8_t match_field_attributes = pattern.match_field_attributes;
+
+    if (!pattern.negative_pattern.empty()) {
+      for (auto attribute : {MATCH_LABEL, MATCH_NAME}) {
+        if ((match_field_attributes & attribute) &&
+            FormField::Match(field, pattern.negative_pattern, attribute,
+                             pattern.match_field_input_types, logging)) {
+          match_field_attributes &= ~attribute;
+        }
       }
     }
 
+    if (match_field_attributes == 0)
+      continue;
+
+    // Apply the positive matching against all remaining match field attributes.
     if (!pattern.positive_pattern.empty() &&
         MatchAndAdvance(scanner, pattern.positive_pattern,
-                        pattern.match_field_attributes,
-                        pattern.match_field_input_types, match, logging)) {
+                        match_field_attributes, pattern.match_field_input_types,
+                        match, logging)) {
       return true;
     }
   }
@@ -251,16 +257,18 @@
 }
 
 // static
-bool FormField::ParseFieldSpecifics(AutofillScanner* scanner,
-                                    base::StringPiece16 pattern,
-                                    int match_type,
-                                    AutofillField** match,
-                                    const RegExLogging& logging) {
+bool FormField::ParseFieldSpecificsWithLegacyPattern(
+    AutofillScanner* scanner,
+    base::StringPiece16 pattern,
+    int match_type,
+    AutofillField** match,
+    const RegExLogging& logging) {
   int match_field_attributes = match_type & 0b11;
   int match_field_types = match_type & ~0b11;
 
-  return ParseFieldSpecifics(scanner, pattern, match_field_attributes,
-                             match_field_types, match, logging);
+  return ParseFieldSpecificsWithLegacyPattern(
+      scanner, pattern, match_field_attributes, match_field_types, match,
+      logging);
 }
 
 bool FormField::ParseFieldSpecifics(
@@ -271,10 +279,7 @@
     AutofillField** match,
     const RegExLogging& logging,
     MatchFieldBitmasks match_field_bitmasks) {
-  if (base::FeatureList::IsEnabled(
-          features::kAutofillParsingPatternsLanguageDependent) ||
-      base::FeatureList::IsEnabled(
-          features::kAutofillParsingPatternsNegativeMatching)) {
+  if (base::FeatureList::IsEnabled(features::kAutofillParsingPatternProvider)) {
     // TODO(crbug/1142936): This hack is to allow
     // AddressField::ParseNameAndLabelSeparately().
     if (match_field_bitmasks.restrict_attributes != ~0 ||
@@ -288,15 +293,16 @@
     }
     return ParseFieldSpecifics(scanner, patterns, match, logging);
   } else {
-    return ParseFieldSpecifics(scanner, pattern, match_type, match, logging);
+    return ParseFieldSpecificsWithLegacyPattern(scanner, pattern, match_type,
+                                                match, logging);
   }
 }
 
 // static
 bool FormField::ParseEmptyLabel(AutofillScanner* scanner,
                                 AutofillField** match) {
-  return ParseFieldSpecifics(scanner, u"^$", MATCH_LABEL | MATCH_ALL_INPUTS,
-                             match);
+  return ParseFieldSpecificsWithLegacyPattern(
+      scanner, u"^$", MATCH_LABEL | MATCH_ALL_INPUTS, match);
 }
 
 // static
diff --git a/components/autofill/core/browser/form_parsing/form_field.h b/components/autofill/core/browser/form_parsing/form_field.h
index 6d9cd75..4c4c86ff 100644
--- a/components/autofill/core/browser/form_parsing/form_field.h
+++ b/components/autofill/core/browser/form_parsing/form_field.h
@@ -84,10 +84,10 @@
 
   // Attempts to parse a form field with the given pattern.  Returns true on
   // success and fills |match| with a pointer to the field.
-  static bool ParseField(AutofillScanner* scanner,
-                         base::StringPiece16 pattern,
-                         AutofillField** match,
-                         const RegExLogging& logging = {});
+  static bool ParseFieldWithLegacyPattern(AutofillScanner* scanner,
+                                          base::StringPiece16 pattern,
+                                          AutofillField** match,
+                                          const RegExLogging& logging = {});
 
   static bool ParseField(AutofillScanner* scanner,
                          const std::vector<MatchingPattern>& patterns,
@@ -105,11 +105,12 @@
   // is non-NULL and the pattern matches, |match| will be set to the matched
   // field, and the scanner would advance by one step. A |true| result is
   // returned in the case of a successful match, false otherwise.
-  static bool ParseFieldSpecifics(AutofillScanner* scanner,
-                                  base::StringPiece16 pattern,
-                                  int match_type,
-                                  AutofillField** match,
-                                  const RegExLogging& logging = {});
+  static bool ParseFieldSpecificsWithLegacyPattern(
+      AutofillScanner* scanner,
+      base::StringPiece16 pattern,
+      int match_type,
+      AutofillField** match,
+      const RegExLogging& logging = {});
 
   static bool ParseFieldSpecifics(AutofillScanner* scanner,
                                   const std::vector<MatchingPattern>& patterns,
@@ -118,12 +119,13 @@
 
   // The same as ParseFieldSpecifics but with splitted match_types into
   // MatchAttributes and MatchFieldTypes.
-  static bool ParseFieldSpecifics(AutofillScanner* scanner,
-                                  base::StringPiece16 pattern,
-                                  int match_field_attributes,
-                                  int match_field_input_types,
-                                  AutofillField** match,
-                                  const RegExLogging& logging = {});
+  static bool ParseFieldSpecificsWithLegacyPattern(
+      AutofillScanner* scanner,
+      base::StringPiece16 pattern,
+      int match_field_attributes,
+      int match_field_input_types,
+      AutofillField** match,
+      const RegExLogging& logging = {});
 
   struct MatchFieldBitmasks {
     int restrict_attributes = ~0;
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index cfa1a04..c3c48f1 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -730,8 +730,7 @@
         1 << AutofillMetrics::FORM_CONTAINS_UPI_VPA_HINT;
   }
 
-  if (base::FeatureList::IsEnabled(
-          features::kAutofillParsingPatternsLanguageDetection)) {
+  if (base::FeatureList::IsEnabled(features::kAutofillPageLanguageDetection)) {
     RationalizeRepeatedFields(form_interactions_ukm_logger, log_manager);
   }
   RationalizeFieldTypePredictions(log_manager);
diff --git a/components/autofill/core/browser/pattern_provider/default_regex_patterns_unittest.cc b/components/autofill/core/browser/pattern_provider/default_regex_patterns_unittest.cc
index 0601e8d..58a65ddbf 100644
--- a/components/autofill/core/browser/pattern_provider/default_regex_patterns_unittest.cc
+++ b/components/autofill/core/browser/pattern_provider/default_regex_patterns_unittest.cc
@@ -86,10 +86,11 @@
 
 TEST_P(DefaultRegExPatternsTest, TestPositiveAndNegativeCases) {
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitWithFeatures(
-      /*enabled_features=*/{features::kAutofillParsingPatternsLanguageDependent,
-                            features::kAutofillParsingPatternsNegativeMatching},
-      /*disabled_features=*/{});
+  base::FieldTrialParams feature_parameters{
+      {features::kAutofillParsingWithLanguageSpecificPatternsParam.name,
+       "true"}};
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      features::kAutofillParsingPatternProvider, feature_parameters);
 
   PatternTestCase test_case = GetParam();
 
diff --git a/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.cc b/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.cc
index 52f329e..7cb40f96 100644
--- a/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.cc
+++ b/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.cc
@@ -83,8 +83,7 @@
 // are equal or both unspecified (i.e. set to 0) this prioritizes the remote
 // configuration over the local one.
 void OnJsonParsed(data_decoder::DataDecoder::ValueOrError result) {
-  if (!base::FeatureList::IsEnabled(
-          features::kAutofillParsingPatternsFromRemote)) {
+  if (features::kAutofillParsingWithRemotePatternsParam.Get()) {
     DVLOG(1) << "Remote patterns are disabled.";
     return;
   }
diff --git a/components/autofill/core/browser/pattern_provider/pattern_provider.cc b/components/autofill/core/browser/pattern_provider/pattern_provider.cc
index f1e0d90..8ca764b7 100644
--- a/components/autofill/core/browser/pattern_provider/pattern_provider.cc
+++ b/components/autofill/core/browser/pattern_provider/pattern_provider.cc
@@ -99,8 +99,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // TODO(crbug.com/1134496): Remove feature check once launched.
-  if (base::FeatureList::IsEnabled(
-          features::kAutofillParsingPatternsLanguageDependent)) {
+  if (features::kAutofillParsingWithLanguageSpecificPatternsParam.Get()) {
     auto outer_it = patterns_.find(pattern_name);
     if (outer_it != patterns_.end()) {
       const std::map<LanguageCode, std::vector<MatchingPattern>>&
@@ -113,13 +112,8 @@
         }
       }
     }
-    return GetAllPatternsByType(pattern_name);
-  } else if (base::FeatureList::IsEnabled(
-                 features::kAutofillParsingPatternsNegativeMatching)) {
-    return GetAllPatternsByType(pattern_name);
-  } else {
-    return {};
   }
+  return GetAllPatternsByType(pattern_name);
 }
 
 const std::vector<MatchingPattern> PatternProvider::GetMatchPatterns(
diff --git a/components/autofill/core/browser/pattern_provider/pattern_provider.h b/components/autofill/core/browser/pattern_provider/pattern_provider.h
index 129aa3d4..4c33a74 100644
--- a/components/autofill/core/browser/pattern_provider/pattern_provider.h
+++ b/components/autofill/core/browser/pattern_provider/pattern_provider.h
@@ -35,22 +35,24 @@
   // Setter for loading patterns from external storage.
   void SetPatterns(const Map patterns, const base::Version& version);
 
-  // Find the patterns for a given ServerFieldType and for a given
+  // Finds the patterns for a given ServerFieldType and for a given
   // |page_language|.
   const std::vector<MatchingPattern> GetMatchPatterns(
       ServerFieldType type,
       const LanguageCode& page_language) const;
 
-  // Find the patterns for a given |pattern_name| and a given |page_language|.
+  // Finds the patterns for a given |pattern_name| and a given |page_language|.
+  // If there are no patterns for a given |page_language|, returns all patterns
+  // for |pattern_name| for any language.
   const std::vector<MatchingPattern> GetMatchPatterns(
       const std::string& pattern_name,
       const LanguageCode& page_language) const;
 
-  // Find all patterns, across all languages, for a given server field |type|.
+  // Finds all patterns, across all languages, for a given server field |type|.
   const std::vector<MatchingPattern> GetAllPatternsByType(
       ServerFieldType type) const;
 
-  // Find all patterns, across all languages, for a given server field |type|.
+  // Finds all patterns, across all languages, for a given server field |type|.
   const std::vector<MatchingPattern> GetAllPatternsByType(
       const std::string& type) const;
 
diff --git a/components/autofill/core/browser/pattern_provider/pattern_provider_unittest.cc b/components/autofill/core/browser/pattern_provider/pattern_provider_unittest.cc
index a51a6df..044ff668 100644
--- a/components/autofill/core/browser/pattern_provider/pattern_provider_unittest.cc
+++ b/components/autofill/core/browser/pattern_provider/pattern_provider_unittest.cc
@@ -32,6 +32,13 @@
 LanguageCode kLanguageDe("de");
 LanguageCode kLanguageEn("en");
 
+base::FieldTrialParams GetFeatureParams(bool language_dependent) {
+  base::FieldTrialParams feature_parameters{
+      {features::kAutofillParsingWithLanguageSpecificPatternsParam.name,
+       language_dependent ? "true" : "false"}};
+  return feature_parameters;
+}
+
 MatchingPattern GetCompanyPatternEn() {
   autofill::MatchingPattern m_p;
   m_p.positive_pattern = u"company|business|organization|organisation";
@@ -119,8 +126,9 @@
 
 TEST(AutofillPatternProviderTest, Single_Match) {
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(
-      features::kAutofillParsingPatternsLanguageDependent);
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      features::kAutofillParsingPatternProvider,
+      GetFeatureParams(/*language_dependent=*/true));
 
   UnitTestPatternProvider p;
   EXPECT_THAT(p.GetMatchPatterns("COMPANY_NAME", kLanguageEn),
@@ -164,12 +172,10 @@
 
 TEST(AutofillPatternProviderTest, UnknownLanguages) {
   {
-    base::test::ScopedFeatureList feature;
-    feature.InitWithFeatures(
-        // enabled
-        {features::kAutofillParsingPatternsLanguageDependent},
-        // disabled
-        {features::kAutofillParsingPatternsNegativeMatching});
+    base::test::ScopedFeatureList scoped_feature_list;
+    scoped_feature_list.InitAndEnableFeatureWithParameters(
+        features::kAutofillParsingPatternProvider,
+        GetFeatureParams(/*language_dependent=*/true));
     UnitTestPatternProvider p;
     EXPECT_EQ(p.GetMatchPatterns(COMPANY_NAME, LanguageCode("")),
               p.GetAllPatternsByType(COMPANY_NAME));
@@ -178,12 +184,10 @@
   }
 
   {
-    base::test::ScopedFeatureList feature;
-    feature.InitWithFeatures(
-        // enabled
-        {features::kAutofillParsingPatternsNegativeMatching},
-        // disabled
-        {features::kAutofillParsingPatternsLanguageDependent});
+    base::test::ScopedFeatureList scoped_feature_list;
+    scoped_feature_list.InitAndEnableFeatureWithParameters(
+        features::kAutofillParsingPatternProvider,
+        GetFeatureParams(/*language_dependent=*/false));
     UnitTestPatternProvider p;
     EXPECT_EQ(p.GetMatchPatterns(COMPANY_NAME, LanguageCode("")),
               p.GetAllPatternsByType(COMPANY_NAME));
@@ -194,12 +198,10 @@
 
 TEST(AutofillPatternProviderTest, EnrichPatternsWithEnVersion) {
   {
-    base::test::ScopedFeatureList feature;
-    feature.InitWithFeatures(
-        // enabled
-        {features::kAutofillParsingPatternsLanguageDependent},
-        // disabled
-        {features::kAutofillParsingPatternsNegativeMatching});
+    base::test::ScopedFeatureList scoped_feature_list;
+    scoped_feature_list.InitAndEnableFeatureWithParameters(
+        features::kAutofillParsingPatternProvider,
+        GetFeatureParams(/*language_dependent=*/true));
     UnitTestPatternProvider p;
     EXPECT_EQ(p.GetMatchPatterns(COMPANY_NAME, kLanguageEn),
               std::vector<MatchingPattern>{GetCompanyPatternEn()});
@@ -209,12 +211,10 @@
   }
 
   {
-    base::test::ScopedFeatureList feature;
-    feature.InitWithFeatures(
-        // enabled
-        {features::kAutofillParsingPatternsNegativeMatching},
-        // disabled
-        {features::kAutofillParsingPatternsLanguageDependent});
+    base::test::ScopedFeatureList scoped_feature_list;
+    scoped_feature_list.InitAndEnableFeatureWithParameters(
+        features::kAutofillParsingPatternProvider,
+        GetFeatureParams(/*language_dependent=*/false));
     UnitTestPatternProvider p;
     EXPECT_EQ(p.GetMatchPatterns(COMPANY_NAME, kLanguageEn),
               std::vector<MatchingPattern>(
@@ -226,13 +226,10 @@
 }
 
 TEST(AutofillPatternProviderTest, SortPatternsByScore) {
-  base::test::ScopedFeatureList feature;
-  feature.InitWithFeatures(
-      // enabled
-      {features::kAutofillParsingPatternsLanguageDependent,
-       features::kAutofillParsingPatternsNegativeMatching},
-      // disabled
-      {});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      features::kAutofillParsingPatternProvider,
+      GetFeatureParams(/*language_dependent=*/true));
   std::vector<MatchingPattern> de_input_patterns;
   de_input_patterns.push_back(GetCompanyPatternDe());
   de_input_patterns.push_back(GetCompanyPatternDe());
diff --git a/components/autofill/core/browser/pattern_provider/resources/regex_patterns.json b/components/autofill/core/browser/pattern_provider/resources/regex_patterns.json
index 7664323..a889b7c 100644
--- a/components/autofill/core/browser/pattern_provider/resources/regex_patterns.json
+++ b/components/autofill/core/browser/pattern_provider/resources/regex_patterns.json
@@ -857,8 +857,17 @@
         "pattern_identifier": "en_zip_code_preserving",
         "positive_pattern": "zip|postal|post.*code|pcode|pin.?code",
         "positive_score": 1.1,
-        "negative_pattern": "\\.zip",
-        "negative_patterns_explainer": ".zip refers to a file extension",
+        "negative_pattern": "\\.zip\\b",
+        "negative_patterns_explainer": ".zip refers to a file extension. However, there are field billingAddress.zip",
+        "match_field_attributes": 3,
+        "match_field_input_types": 69
+      },
+      {
+        "pattern_identifier": "en_zip_code_preserving",
+        "positive_pattern": "address\\.zip",
+        "positive_score": 1.1,
+        "negative_pattern": null,
+        "negative_patterns_explainer": "",
         "match_field_attributes": 3,
         "match_field_input_types": 69
       }
@@ -1867,8 +1876,18 @@
         "match_field_attributes": 3,
         "match_field_input_types": 205
       }
+    ],
+    "id": [
+      {
+        "pattern_identifier": "id_card_exp_date_preserving",
+        "positive_pattern": "masa berlaku|berlaku hingga",
+        "positive_score": 1.0,
+        "negative_pattern": null,
+        "match_field_attributes": 3,
+        "match_field_input_types": 205
+      }
     ]
-  },
+   },
   "CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR": {
     "en": [
       {
@@ -1973,16 +1992,6 @@
         "match_field_attributes": 3,
         "match_field_input_types": 205
       }
-    ],
-    "id": [
-      {
-        "pattern_identifier": "id_card_exp_date_preserving",
-        "positive_pattern": "masa berlaku|berlaku hingga",
-        "positive_score": 1.0,
-        "negative_pattern": null,
-        "match_field_attributes": 3,
-        "match_field_input_types": 205
-      }
     ]
   },
   "CREDIT_CARD_EXP_MONTH_BEFORE_YEAR": {
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc
index 684d3d244..f91ab04 100644
--- a/components/autofill/core/common/autofill_features.cc
+++ b/components/autofill/core/common/autofill_features.cc
@@ -286,28 +286,31 @@
     "AutofillPreventOverridingPrefilledValues",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
-// When enabled, Autofill will load remote patterns via the component updater.
+// Uses the pattern provider to retrieve parsing patterns for the heuristic
+// field type detection.
 // TODO(crbug/1121990): Remove once launched.
-extern const base::Feature kAutofillParsingPatternsFromRemote{
-    "AutofillParsingPatternsFromRemote", base::FEATURE_DISABLED_BY_DEFAULT};
+extern const base::Feature kAutofillParsingPatternProvider{
+    "AutofillParsingPatternProvider", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Controls if language-specific patterns are used for the heuristic field type
+// detection.
+// For this to work, the feature kAutofillPageLanguageDetection must be enabled.
+// Otherwise the pattern provider will revert back to language unspecific
+// patterns.
+const base::FeatureParam<bool>
+    kAutofillParsingWithLanguageSpecificPatternsParam{
+        &kAutofillParsingPatternProvider, "use_language_specific_patterns",
+        true};
+
+// Controls if patterns retrieved with the component updater are used.
+const base::FeatureParam<bool> kAutofillParsingWithRemotePatternsParam{
+    &kAutofillParsingPatternProvider,
+    "use_patterns_retrieved_with_the_component_udpater", false};
 
 // Enables detection of language from Translate.
 // TODO(crbug/1150895): Cleanup when launched.
-const base::Feature kAutofillParsingPatternsLanguageDetection{
-    "AutofillParsingPatternsLanguageDetection",
-    base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Controls whether negative patterns are used to parse the field type.
-// TODO(crbug.com/1132831): Remove once launched.
-const base::Feature kAutofillParsingPatternsNegativeMatching{
-    "AutofillParsingPatternsNegativeMatching",
-    base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Controls whether page language is used to match patterns.
-// TODO(crbug.com/1134496): Remove once launched.
-const base::Feature kAutofillParsingPatternsLanguageDependent{
-    "AutofillParsingPatternsLanguageDependent",
-    base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kAutofillPageLanguageDetection{
+    "AutofillPageLanguageDetection", base::FEATURE_DISABLED_BY_DEFAULT};
 
 // If the feature is enabled, FormTracker's probable-form-submission detection
 // is disabled and replaced with browser-side detection.
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h
index d79f983..d6186a1 100644
--- a/components/autofill/core/common/autofill_features.h
+++ b/components/autofill/core/common/autofill_features.h
@@ -108,13 +108,14 @@
 extern const base::FeatureParam<int>
     kAutofillMaxiumWidthPercentageToMoveSuggestionPopupToCenter;
 COMPONENT_EXPORT(AUTOFILL)
-extern const base::Feature kAutofillParsingPatternsFromRemote;
+extern const base::Feature kAutofillParsingPatternProvider;
 COMPONENT_EXPORT(AUTOFILL)
-extern const base::Feature kAutofillParsingPatternsLanguageDetection;
+extern const base::FeatureParam<bool>
+    kAutofillParsingWithLanguageSpecificPatternsParam;
 COMPONENT_EXPORT(AUTOFILL)
-extern const base::Feature kAutofillParsingPatternsNegativeMatching;
+extern const base::FeatureParam<bool> kAutofillParsingWithRemotePatternsParam;
 COMPONENT_EXPORT(AUTOFILL)
-extern const base::Feature kAutofillParsingPatternsLanguageDependent;
+extern const base::Feature kAutofillPageLanguageDetection;
 COMPONENT_EXPORT(AUTOFILL)
 extern const base::Feature kAutofillPreventOverridingPrefilledValues;
 COMPONENT_EXPORT(AUTOFILL)
diff --git a/components/autofill_assistant/browser/actions/action_delegate_util.cc b/components/autofill_assistant/browser/actions/action_delegate_util.cc
index 93eff1aa..fc923a2 100644
--- a/components/autofill_assistant/browser/actions/action_delegate_util.cc
+++ b/components/autofill_assistant/browser/actions/action_delegate_util.cc
@@ -186,7 +186,7 @@
   switch (optional_step) {
     case STEP_UNSPECIFIED:
       NOTREACHED() << __func__ << " unspecified optional_step";
-      FALLTHROUGH;
+      [[fallthrough]];
 
     case SKIP_STEP:
       break;
diff --git a/components/component_updater/component_installer_unittest.cc b/components/component_updater/component_installer_unittest.cc
index 48d3de2..51c206c 100644
--- a/components/component_updater/component_installer_unittest.cc
+++ b/components/component_updater/component_installer_unittest.cc
@@ -17,7 +17,9 @@
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
+#include "base/sequence_checker.h"
 #include "base/task/post_task.h"
+#include "base/test/bind.h"
 #include "base/test/scoped_path_override.h"
 #include "base/test/task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -126,7 +128,13 @@
 
 class MockInstallerPolicy : public ComponentInstallerPolicy {
  public:
-  MockInstallerPolicy() = default;
+  using ComponentReadyCallback =
+      base::OnceCallback<void(const base::Version& version,
+                              const base::FilePath& install_dir,
+                              base::Value manifest)>;
+  explicit MockInstallerPolicy(
+      ComponentReadyCallback component_ready_cb = ComponentReadyCallback())
+      : component_ready_cb_(std::move(component_ready_cb)) {}
   ~MockInstallerPolicy() override = default;
 
   bool VerifyInstallation(const base::Value& manifest,
@@ -150,7 +158,12 @@
 
   void ComponentReady(const base::Version& version,
                       const base::FilePath& install_dir,
-                      base::Value manifest) override {}
+                      base::Value manifest) override {
+    if (component_ready_cb_) {
+      std::move(component_ready_cb_)
+          .Run(version, install_dir, std::move(manifest));
+    }
+  }
 
   base::FilePath GetRelativeInstallDir() const override {
     return base::FilePath(relative_install_dir);
@@ -171,6 +184,8 @@
   static void GetPkHash(std::vector<uint8_t>* hash) {
     hash->assign(std::begin(kSha256Hash), std::end(kSha256Hash));
   }
+
+  ComponentReadyCallback component_ready_cb_;
 };
 
 class MockUpdateScheduler : public UpdateScheduler {
@@ -337,6 +352,96 @@
   EXPECT_TRUE(component.requires_network_encryption);
 }
 
+// Tests that `ComponentInstallerPolicy::ComponentReady` and the completion
+// callback of `ComponentInstaller::Register` are called in sequence.
+TEST_F(ComponentInstallerTest, InstallerRegister_CheckSequence) {
+  class RegisterHandler {
+   public:
+    virtual ~RegisterHandler() = default;
+
+    virtual void ComponentReady() = 0;
+    virtual void RegisterComplete() = 0;
+  };
+
+  // Allows defining call expectations on its functions when the functions
+  // are invoked by callbacks posted from `ComponentInstaller::Register`.
+  class MockRegisterHandler : public RegisterHandler {
+   public:
+    MockRegisterHandler() {
+      ON_CALL(*this, ComponentReady)
+          .WillByDefault(Invoke(this, &MockRegisterHandler::CheckSequence));
+      ON_CALL(*this, RegisterComplete)
+          .WillByDefault(Invoke(this, &MockRegisterHandler::CheckSequence));
+    }
+
+    MOCK_METHOD(void, ComponentReady, (), (override));
+    MOCK_METHOD(void, RegisterComplete, (), (override));
+
+   private:
+    void CheckSequence() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker); }
+    SEQUENCE_CHECKER(sequence_checker);
+  };
+
+  base::ScopedPathOverride scoped_path_override(DIR_COMPONENT_USER);
+
+  // Install a CRX component so that `ComponentInstallerPolicy::ComponentReady`
+  // can be invoked later on.
+  {
+    base::RunLoop run_loop;
+    auto installer = base::MakeRefCounted<ComponentInstaller>(
+        std::make_unique<MockInstallerPolicy>());
+    Unpack(test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
+    ASSERT_EQ(result().error, update_client::UnpackerError::kNone);
+    base::FilePath base_dir;
+    ASSERT_TRUE(base::PathService::Get(DIR_COMPONENT_USER, &base_dir));
+    base_dir = base_dir.Append(relative_install_dir);
+    ASSERT_TRUE(base::CreateDirectory(base_dir));
+    installer->Install(
+        result().unpack_path, update_client::jebg_public_key, nullptr,
+        base::DoNothing(),
+        base::BindLambdaForTesting(
+            [&run_loop](const update_client::CrxInstaller::Result& result) {
+              ASSERT_EQ(result.error, 0);
+              run_loop.QuitClosure().Run();
+            }));
+    run_loop.Run();
+  }
+
+  base::RunLoop run_loop;
+  EXPECT_CALL(update_client(), DoUpdate(_, _)).WillOnce(Invoke([&run_loop]() {
+    run_loop.QuitClosure().Run();
+  }));
+
+  // Set up expectations for uninteresting calls on the mocks due to component
+  // updater waking up after the component is registered.
+  EXPECT_CALL(scheduler(), Schedule(_, _, _, _)).Times(1);
+  EXPECT_CALL(scheduler(), Stop()).Times(1);
+  EXPECT_CALL(update_client(), Stop()).Times(1);
+
+  MockRegisterHandler mock_register_handler;
+  {
+    ::testing::InSequence seq;
+    EXPECT_CALL(mock_register_handler, ComponentReady()).Times(1);
+    EXPECT_CALL(mock_register_handler, RegisterComplete()).Times(1);
+  }
+
+  auto installer_policy =
+      std::make_unique<MockInstallerPolicy>(base::BindLambdaForTesting(
+          [&mock_register_handler](const base::Version& version,
+                                   const base::FilePath& install_dir,
+                                   base::Value manifest) {
+            EXPECT_EQ(version.GetString(), "1.0");
+            mock_register_handler.ComponentReady();
+          }));
+  auto installer =
+      base::MakeRefCounted<ComponentInstaller>(std::move(installer_policy));
+  installer->Register(component_updater(),
+                      base::BindLambdaForTesting([&mock_register_handler]() {
+                        mock_register_handler.RegisterComplete();
+                      }));
+  run_loop.Run();
+}
+
 // Tests that the unpack path is removed when the install succeeded.
 TEST_F(ComponentInstallerTest, UnpackPathInstallSuccess) {
   auto installer = base::MakeRefCounted<ComponentInstaller>(
diff --git a/components/content_settings/browser/page_specific_content_settings.cc b/components/content_settings/browser/page_specific_content_settings.cc
index c255196..799da01a 100644
--- a/components/content_settings/browser/page_specific_content_settings.cc
+++ b/components/content_settings/browser/page_specific_content_settings.cc
@@ -827,7 +827,7 @@
           map_->GetContentSetting(current_url, current_url, content_type);
       if (geolocation_setting == CONTENT_SETTING_ALLOW)
         geolocation_was_just_granted_on_site_level_ = true;
-      FALLTHROUGH;
+      [[fallthrough]];
     }
     case ContentSettingsType::IMAGES:
     case ContentSettingsType::JAVASCRIPT:
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc
index f8e6eff..fea063fd 100644
--- a/components/cronet/url_request_context_config.cc
+++ b/components/cronet/url_request_context_config.cc
@@ -377,35 +377,32 @@
             net::kDefaultMaxQuicServerEntries;
       }
 
-      int quic_max_server_configs_stored_in_properties = 0;
-      if (quic_args->GetInteger(
-              kQuicMaxServerConfigsStoredInProperties,
-              &quic_max_server_configs_stored_in_properties)) {
+      absl::optional<int> quic_max_server_configs_stored_in_properties =
+          quic_args->FindIntKey(kQuicMaxServerConfigsStoredInProperties);
+      if (quic_max_server_configs_stored_in_properties) {
         quic_params->max_server_configs_stored_in_properties =
-            static_cast<size_t>(quic_max_server_configs_stored_in_properties);
+            static_cast<size_t>(*quic_max_server_configs_stored_in_properties);
       }
 
-      int quic_idle_connection_timeout_seconds = 0;
-      if (quic_args->GetInteger(kQuicIdleConnectionTimeoutSeconds,
-                                &quic_idle_connection_timeout_seconds)) {
+      absl::optional<int> quic_idle_connection_timeout_seconds =
+          quic_args->FindIntKey(kQuicIdleConnectionTimeoutSeconds);
+      if (quic_idle_connection_timeout_seconds) {
         quic_params->idle_connection_timeout =
-            base::Seconds(quic_idle_connection_timeout_seconds);
+            base::Seconds(*quic_idle_connection_timeout_seconds);
       }
 
-      int quic_max_time_before_crypto_handshake_seconds = 0;
-      if (quic_args->GetInteger(
-              kQuicMaxTimeBeforeCryptoHandshakeSeconds,
-              &quic_max_time_before_crypto_handshake_seconds)) {
+      absl::optional<int> quic_max_time_before_crypto_handshake_seconds =
+          quic_args->FindIntKey(kQuicMaxTimeBeforeCryptoHandshakeSeconds);
+      if (quic_max_time_before_crypto_handshake_seconds) {
         quic_params->max_time_before_crypto_handshake =
-            base::Seconds(quic_max_time_before_crypto_handshake_seconds);
+            base::Seconds(*quic_max_time_before_crypto_handshake_seconds);
       }
 
-      int quic_max_idle_time_before_crypto_handshake_seconds = 0;
-      if (quic_args->GetInteger(
-              kQuicMaxIdleTimeBeforeCryptoHandshakeSeconds,
-              &quic_max_idle_time_before_crypto_handshake_seconds)) {
+      absl::optional<int> quic_max_idle_time_before_crypto_handshake_seconds =
+          quic_args->FindIntKey(kQuicMaxIdleTimeBeforeCryptoHandshakeSeconds);
+      if (quic_max_idle_time_before_crypto_handshake_seconds) {
         quic_params->max_idle_time_before_crypto_handshake =
-            base::Seconds(quic_max_idle_time_before_crypto_handshake_seconds);
+            base::Seconds(*quic_max_idle_time_before_crypto_handshake_seconds);
       }
 
       absl::optional<bool> quic_close_sessions_on_ip_change =
@@ -442,47 +439,49 @@
           quic_args->FindBoolKey(kQuicEnableSocketRecvOptimization)
               .value_or(quic_params->enable_socket_recv_optimization);
 
-      int quic_max_time_on_non_default_network_seconds = 0;
-      int quic_max_migrations_to_non_default_network_on_write_error = 0;
-      int quic_max_migrations_to_non_default_network_on_path_degrading = 0;
-
       absl::optional<bool> quic_migrate_sessions_on_network_change_v2_in =
           quic_args->FindBoolKey(kQuicMigrateSessionsOnNetworkChangeV2);
       if (quic_migrate_sessions_on_network_change_v2_in.has_value()) {
         quic_params->migrate_sessions_on_network_change_v2 =
             quic_migrate_sessions_on_network_change_v2_in.value();
-        if (quic_args->GetInteger(
-                kQuicMaxTimeOnNonDefaultNetworkSeconds,
-                &quic_max_time_on_non_default_network_seconds)) {
+
+        absl::optional<int> quic_max_time_on_non_default_network_seconds =
+            quic_args->FindIntKey(kQuicMaxTimeOnNonDefaultNetworkSeconds);
+        if (quic_max_time_on_non_default_network_seconds) {
           quic_params->max_time_on_non_default_network =
-              base::Seconds(quic_max_time_on_non_default_network_seconds);
+              base::Seconds(*quic_max_time_on_non_default_network_seconds);
         }
-        if (quic_args->GetInteger(
-                kQuicMaxMigrationsToNonDefaultNetworkOnWriteError,
-                &quic_max_migrations_to_non_default_network_on_write_error)) {
+
+        absl::optional<int>
+            quic_max_migrations_to_non_default_network_on_write_error =
+                quic_args->FindIntKey(
+                    kQuicMaxMigrationsToNonDefaultNetworkOnWriteError);
+        if (quic_max_migrations_to_non_default_network_on_write_error) {
           quic_params->max_migrations_to_non_default_network_on_write_error =
-              quic_max_migrations_to_non_default_network_on_write_error;
+              *quic_max_migrations_to_non_default_network_on_write_error;
         }
-        if (quic_args->GetInteger(
-                kQuicMaxMigrationsToNonDefaultNetworkOnPathDegrading,
-                &quic_max_migrations_to_non_default_network_on_path_degrading)) {
+
+        absl::optional<int>
+            quic_max_migrations_to_non_default_network_on_path_degrading =
+                quic_args->FindIntKey(
+                    kQuicMaxMigrationsToNonDefaultNetworkOnPathDegrading);
+        if (quic_max_migrations_to_non_default_network_on_path_degrading) {
           quic_params->max_migrations_to_non_default_network_on_path_degrading =
-              quic_max_migrations_to_non_default_network_on_path_degrading;
+              *quic_max_migrations_to_non_default_network_on_path_degrading;
         }
       }
 
-      int quic_idle_session_migration_period_seconds = 0;
-
       absl::optional<bool> quic_migrate_idle_sessions_in =
           quic_args->FindBoolKey(kQuicMigrateIdleSessions);
       if (quic_migrate_idle_sessions_in.has_value()) {
         quic_params->migrate_idle_sessions =
             quic_migrate_idle_sessions_in.value();
-        if (quic_args->GetInteger(
-                kQuicIdleSessionMigrationPeriodSeconds,
-                &quic_idle_session_migration_period_seconds)) {
+
+        absl::optional<int> quic_idle_session_migration_period_seconds =
+            quic_args->FindIntKey(kQuicIdleSessionMigrationPeriodSeconds);
+        if (quic_idle_session_migration_period_seconds) {
           quic_params->idle_session_migration_period =
-              base::Seconds(quic_idle_session_migration_period_seconds);
+              base::Seconds(*quic_idle_session_migration_period_seconds);
         }
       }
 
@@ -493,12 +492,11 @@
             quic_migrate_sessions_early_v2_in.value();
       }
 
-      int quic_retransmittable_on_wire_timeout_milliseconds = 0;
-      if (quic_args->GetInteger(
-              kQuicRetransmittableOnWireTimeoutMilliseconds,
-              &quic_retransmittable_on_wire_timeout_milliseconds)) {
+      absl::optional<int> quic_retransmittable_on_wire_timeout_milliseconds =
+          quic_args->FindIntKey(kQuicRetransmittableOnWireTimeoutMilliseconds);
+      if (quic_retransmittable_on_wire_timeout_milliseconds) {
         quic_params->retransmittable_on_wire_timeout = base::Milliseconds(
-            quic_retransmittable_on_wire_timeout_milliseconds);
+            *quic_retransmittable_on_wire_timeout_milliseconds);
       }
 
       quic_params->retry_on_alternate_network_before_handshake =
@@ -546,10 +544,10 @@
         }
       }
 
-      int quic_ios_network_service_type;
-      if (quic_args->GetInteger(kQuicIOSNetworkServiceType,
-                                &quic_ios_network_service_type)) {
-        quic_params->ios_network_service_type = quic_ios_network_service_type;
+      absl::optional<int> quic_ios_network_service_type =
+          quic_args->FindIntKey(kQuicIOSNetworkServiceType);
+      if (quic_ios_network_service_type) {
+        quic_params->ios_network_service_type = *quic_ios_network_service_type;
       }
     } else if (it.key() == kAsyncDnsFieldTrialName) {
       const base::DictionaryValue* async_dns_args = nullptr;
@@ -574,27 +572,35 @@
       if (stale_dns_enable_in.has_value() && stale_dns_enable_in.value()) {
         stale_dns_enable = stale_dns_enable_in.value();
 
-        int delay;
-        if (stale_dns_args->GetInteger(kStaleDnsDelayMs, &delay))
-          stale_dns_options.delay = base::Milliseconds(delay);
-        int max_expired_time_ms;
-        if (stale_dns_args->GetInteger(kStaleDnsMaxExpiredTimeMs,
-                                       &max_expired_time_ms)) {
+        absl::optional<int> delay =
+            stale_dns_args->FindIntKey(kStaleDnsDelayMs);
+        if (delay)
+          stale_dns_options.delay = base::Milliseconds(*delay);
+
+        absl::optional<int> max_expired_time_ms =
+            stale_dns_args->FindIntKey(kStaleDnsMaxExpiredTimeMs);
+        if (max_expired_time_ms) {
           stale_dns_options.max_expired_time =
-              base::Milliseconds(max_expired_time_ms);
+              base::Milliseconds(*max_expired_time_ms);
         }
-        int max_stale_uses;
-        if (stale_dns_args->GetInteger(kStaleDnsMaxStaleUses, &max_stale_uses))
-          stale_dns_options.max_stale_uses = max_stale_uses;
+
+        absl::optional<int> max_stale_uses =
+            stale_dns_args->FindIntKey(kStaleDnsMaxStaleUses);
+        if (max_stale_uses)
+          stale_dns_options.max_stale_uses = *max_stale_uses;
+
         stale_dns_options.allow_other_network =
             stale_dns_args->FindBoolKey(kStaleDnsAllowOtherNetwork)
                 .value_or(stale_dns_options.allow_other_network);
         enable_host_cache_persistence =
             stale_dns_args->FindBoolKey(kStaleDnsPersist)
                 .value_or(enable_host_cache_persistence);
-        int persist_timer;
-        if (stale_dns_args->GetInteger(kStaleDnsPersistTimer, &persist_timer))
-          host_cache_persistence_delay_ms = persist_timer;
+
+        absl::optional<int> persist_timer =
+            stale_dns_args->FindIntKey(kStaleDnsPersistTimer);
+        if (persist_timer)
+          host_cache_persistence_delay_ms = *persist_timer;
+
         stale_dns_options.use_stale_on_name_not_resolved =
             stale_dns_args->FindBoolKey(kStaleDnsUseStaleOnNameNotResolved)
                 .value_or(stale_dns_options.use_stale_on_name_not_resolved);
diff --git a/components/download/internal/common/download_item_impl.cc b/components/download/internal/common/download_item_impl.cc
index 9761fe9..1e80fe33 100644
--- a/components/download/internal/common/download_item_impl.cc
+++ b/components/download/internal/common/download_item_impl.cc
@@ -2243,7 +2243,7 @@
       }
       // else - Fallthrough for cancellation handling which is equivalent to the
       // IN_PROGRESS state.
-      FALLTHROUGH;
+      [[fallthrough]];
 
     case IN_PROGRESS_INTERNAL:
     case TARGET_RESOLVED_INTERNAL: {
diff --git a/components/download/internal/common/download_utils.cc b/components/download/internal/common/download_utils.cc
index b2d7bc26..f6a725a 100644
--- a/components/download/internal/common/download_utils.cc
+++ b/components/download/internal/common/download_utils.cc
@@ -647,7 +647,7 @@
     case DownloadItem::IN_PROGRESS:
       return false;
     case DownloadItem::COMPLETE:
-      FALLTHROUGH;
+      [[fallthrough]];
     case DownloadItem::CANCELLED:
       return true;
     case DownloadItem::INTERRUPTED:
diff --git a/components/embedder_support/android/delegate/web_contents_delegate_android.cc b/components/embedder_support/android/delegate/web_contents_delegate_android.cc
index 1aec422..1911b055 100644
--- a/components/embedder_support/android/delegate/web_contents_delegate_android.cc
+++ b/components/embedder_support/android/delegate/web_contents_delegate_android.cc
@@ -272,7 +272,7 @@
   if (obj.is_null())
     return;
   Java_WebContentsDelegateAndroid_onUpdateUrl(
-      env, obj, url::GURLAndroid::FromNativeGURL(env, source->GetURL()));
+      env, obj, url::GURLAndroid::FromNativeGURL(env, source->GetVisibleURL()));
 }
 
 bool WebContentsDelegateAndroid::HandleKeyboardEvent(
diff --git a/components/enterprise/browser/reporting/report_scheduler.cc b/components/enterprise/browser/reporting/report_scheduler.cc
index 842c3e2..1db7656 100644
--- a/components/enterprise/browser/reporting/report_scheduler.cc
+++ b/components/enterprise/browser/reporting/report_scheduler.cc
@@ -233,7 +233,7 @@
     case kTriggerNone:
     case kTriggerExtensionRequestRealTime:
       NOTREACHED();
-      FALLTHROUGH;
+      [[fallthrough]];
     case kTriggerTimer:
       VLOG(1) << "Generating enterprise report.";
       break;
@@ -299,7 +299,7 @@
 
       delegate_->GetLocalState()->SetTime(kLastUploadSucceededTimestamp,
                                           base::Time::Now());
-      FALLTHROUGH;
+      [[fallthrough]];
     case ReportUploader::kTransientError:
       // Stop retrying and schedule the next report to avoid stale report.
       // Failure count is not reset so retry delay remains.
diff --git a/components/enterprise/content/clipboard_restriction_service.cc b/components/enterprise/content/clipboard_restriction_service.cc
index 766edfc..cd87f4e 100644
--- a/components/enterprise/content/clipboard_restriction_service.cc
+++ b/components/enterprise/content/clipboard_restriction_service.cc
@@ -9,6 +9,7 @@
 #include "components/policy/core/common/policy_pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "components/strings/grit/components_strings.h"
+#include "components/url_matcher/url_util.h"
 #include "components/user_prefs/user_prefs.h"
 #include "content/public/browser/browser_context.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -96,10 +97,10 @@
   // and the copy will be blocked. While confusing, this is mostly to map to the
   // same policy format as the content analysis connector, which also has
   // "enable" and "disable" lists used in this way.
-  policy::url_util::AddFilters(enable_url_matcher_.get(), true, &next_id_,
-                               enable_list);
-  policy::url_util::AddFilters(disable_url_matcher_.get(), false, &next_id_,
-                               disable_list);
+  url_matcher::util::AddFilters(enable_url_matcher_.get(), true, &next_id_,
+                                enable_list);
+  url_matcher::util::AddFilters(disable_url_matcher_.get(), false, &next_id_,
+                                disable_list);
 
   absl::optional<int> min_data_size = settings->FindIntKey(
       enterprise::content::kCopyPreventionSettingsMinDataSizeFieldName);
diff --git a/components/enterprise/content/clipboard_restriction_service.h b/components/enterprise/content/clipboard_restriction_service.h
index fc42fc93..113cda9 100644
--- a/components/enterprise/content/clipboard_restriction_service.h
+++ b/components/enterprise/content/clipboard_restriction_service.h
@@ -11,7 +11,6 @@
 #include "base/memory/singleton.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "components/policy/core/browser/url_util.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/url_matcher/url_matcher.h"
 
diff --git a/components/guest_view/browser/guest_view_base.cc b/components/guest_view/browser/guest_view_base.cc
index 8fe70ba32..920e032 100644
--- a/components/guest_view/browser/guest_view_base.cc
+++ b/components/guest_view/browser/guest_view_base.cc
@@ -710,6 +710,7 @@
   // embedded in a cross-process frame, this method should be overrode for that
   // specific guest type. For all other guests, the owner RenderWidgetHost is
   // that of the owner WebContents.
+  DCHECK(!CanBeEmbeddedInsideCrossProcessFrames());
   auto* owner = GetOwnerWebContents();
   if (owner && owner->GetRenderWidgetHostView())
     return owner->GetRenderWidgetHostView()->GetRenderWidgetHost();
@@ -722,6 +723,7 @@
   // embedded in a cross-process frame, this method should be overrode for that
   // specific guest type. For all other guests, the owner site instance can be
   // from the owner WebContents.
+  DCHECK(!CanBeEmbeddedInsideCrossProcessFrames());
   if (auto* owner_contents = GetOwnerWebContents())
     return owner_contents->GetSiteInstance();
   return nullptr;
@@ -912,7 +914,7 @@
                     : std::string();
 }
 
-bool GuestViewBase::CanBeEmbeddedInsideCrossProcessFrames() {
+bool GuestViewBase::CanBeEmbeddedInsideCrossProcessFrames() const {
   return false;
 }
 
diff --git a/components/guest_view/browser/guest_view_base.h b/components/guest_view/browser/guest_view_base.h
index 13074ca..6660784 100644
--- a/components/guest_view/browser/guest_view_base.h
+++ b/components/guest_view/browser/guest_view_base.h
@@ -164,7 +164,10 @@
   // Returns the user browser context of the embedder.
   content::BrowserContext* browser_context() const { return browser_context_; }
 
-  // Returns the URL of the owner WebContents.
+  // Returns the URL of the owner WebContents' SiteInstance.
+  // WARNING: Be careful using this with GuestViews where
+  // `CanBeEmbeddedInsideCrossProcessFrames` is true. This returns the site of
+  // the WebContents, not the embedding frame.
   const GURL& GetOwnerSiteURL() const;
 
   // Returns the host of the owner WebContents. For extensions, this is the
@@ -201,7 +204,7 @@
 
   // Returns true if the corresponding guest is allowed to be embedded inside an
   // <iframe> which is cross process.
-  virtual bool CanBeEmbeddedInsideCrossProcessFrames();
+  virtual bool CanBeEmbeddedInsideCrossProcessFrames() const;
 
  protected:
   explicit GuestViewBase(content::WebContents* owner_web_contents);
diff --git a/components/invalidation/impl/per_user_topic_subscription_manager.cc b/components/invalidation/impl/per_user_topic_subscription_manager.cc
index 4cbc6e82..04a562d3 100644
--- a/components/invalidation/impl/per_user_topic_subscription_manager.cc
+++ b/components/invalidation/impl/per_user_topic_subscription_manager.cc
@@ -91,8 +91,7 @@
       : update_(prefs, kTypeSubscribedForInvalidations) {
     per_sender_pref_ = update_->FindDictKey(project_id);
     if (!per_sender_pref_) {
-      update_->SetDictionary(project_id,
-                             std::make_unique<base::DictionaryValue>());
+      update_->SetKey(project_id, base::Value(base::Value::Type::DICTIONARY));
       per_sender_pref_ = update_->FindDictKey(project_id);
     }
     DCHECK(per_sender_pref_);
diff --git a/components/metrics/stability_metrics_helper.cc b/components/metrics/stability_metrics_helper.cc
index c4dc7f7..538c9ca3 100644
--- a/components/metrics/stability_metrics_helper.cc
+++ b/components/metrics/stability_metrics_helper.cc
@@ -311,6 +311,12 @@
                    : prefs::kStabilityRendererLaunchCount;
   RecordStabilityEvent(metric);
   IncrementPrefValue(pref);
+
+  // TODO(crbug/1283745): Remove the scheduled write if it does not improve the
+  // renderer launch ratio on Android WebView.
+#if defined(OS_ANDROID)
+  local_state_->CommitPendingWrite();
+#endif
 }
 
 void StabilityMetricsHelper::LogRendererLaunchFailed(
diff --git a/components/optimization_guide/core/BUILD.gn b/components/optimization_guide/core/BUILD.gn
index 0f858834..02ab759 100644
--- a/components/optimization_guide/core/BUILD.gn
+++ b/components/optimization_guide/core/BUILD.gn
@@ -32,14 +32,68 @@
   ]
 }
 
+static_library("model_executor") {
+  sources = [
+    "execution_status.cc",
+    "execution_status.h",
+    "model_enums.h",
+    "model_executor.h",
+    "model_info.cc",
+    "model_info.h",
+    "model_util.cc",
+    "model_util.h",
+  ]
+  if (build_with_tflite_lib) {
+    sources += [
+      "base_model_executor.h",
+      "base_model_executor_helpers.h",
+      "bert_model_executor.cc",
+      "bert_model_executor.h",
+      "tflite_model_executor.h",
+    ]
+  }
+
+  public_deps = [
+    "//components/optimization_guide:machine_learning_tflite_buildflags",
+    "//third_party/re2",
+  ]
+  if (build_with_tflite_lib) {
+    public_deps += [
+      "//components/optimization_guide/core:machine_learning",
+      "//third_party/abseil-cpp:absl",
+      "//third_party/tflite",
+      "//third_party/tflite:tflite_public_headers",
+      "//third_party/tflite_support",
+      "//third_party/tflite_support:tflite_support_proto",
+    ]
+  }
+  deps = [
+    "//base",
+    "//components/optimization_guide/proto:optimization_guide_proto",
+    "//net",
+    "//url",
+  ]
+}
+
+if (build_with_tflite_lib) {
+  static_library("machine_learning") {
+    sources = [
+      "tflite_op_resolver.cc",
+      "tflite_op_resolver.h",
+    ]
+    deps = [
+      "//third_party/tflite",
+      "//third_party/tflite:tflite_public_headers",
+    ]
+  }
+}
+
 static_library("core") {
   sources = [
     "command_line_top_host_provider.cc",
     "command_line_top_host_provider.h",
     "decision_tree_prediction_model.cc",
     "decision_tree_prediction_model.h",
-    "execution_status.cc",
-    "execution_status.h",
     "hint_cache.cc",
     "hint_cache.h",
     "hints_component_info.h",
@@ -58,10 +112,7 @@
     "local_page_entities_metadata_provider.h",
     "memory_hint.cc",
     "memory_hint.h",
-    "model_executor.h",
     "model_handler.h",
-    "model_info.cc",
-    "model_info.h",
     "noisy_metrics_recorder.cc",
     "noisy_metrics_recorder.h",
     "optimization_filter.cc",
@@ -110,10 +161,6 @@
   ]
   if (build_with_tflite_lib) {
     sources += [
-      "base_model_executor.h",
-      "base_model_executor_helpers.h",
-      "bert_model_executor.cc",
-      "bert_model_executor.h",
       "bert_model_handler.cc",
       "bert_model_handler.h",
       "model_validator.cc",
@@ -125,12 +172,12 @@
       "page_topics_model_executor.h",
       "page_visibility_model_executor.cc",
       "page_visibility_model_executor.h",
-      "tflite_model_executor.h",
     ]
   }
 
   public_deps = [
     ":entities",
+    ":model_executor",
     "//components/optimization_guide:machine_learning_tflite_buildflags",
     "//third_party/re2",
   ]
@@ -165,19 +212,6 @@
   ]
 }
 
-if (build_with_tflite_lib) {
-  static_library("machine_learning") {
-    sources = [
-      "tflite_op_resolver.cc",
-      "tflite_op_resolver.h",
-    ]
-    deps = [
-      "//third_party/tflite",
-      "//third_party/tflite:tflite_public_headers",
-    ]
-  }
-}
-
 static_library("test_support") {
   testonly = true
   sources = [
diff --git a/components/optimization_guide/core/bert_model_executor.cc b/components/optimization_guide/core/bert_model_executor.cc
index ab2b7306..9e8e7b0 100644
--- a/components/optimization_guide/core/bert_model_executor.cc
+++ b/components/optimization_guide/core/bert_model_executor.cc
@@ -5,7 +5,7 @@
 #include "components/optimization_guide/core/bert_model_executor.h"
 
 #include "base/trace_event/trace_event.h"
-#include "components/optimization_guide/core/optimization_guide_util.h"
+#include "components/optimization_guide/core/model_util.h"
 #include "components/optimization_guide/core/tflite_op_resolver.h"
 #include "third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/bert_nl_classifier.h"
 
diff --git a/components/optimization_guide/core/model_enums.h b/components/optimization_guide/core/model_enums.h
new file mode 100644
index 0000000..1e6c495c
--- /dev/null
+++ b/components/optimization_guide/core/model_enums.h
@@ -0,0 +1,57 @@
+// Copyright 2021 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 COMPONENTS_OPTIMIZATION_GUIDE_CORE_MODEL_ENUMS_H_
+#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_MODEL_ENUMS_H_
+
+namespace optimization_guide {
+
+// The types of decisions that can be made for an optimization target.
+//
+// Keep in sync with OptimizationGuideOptimizationTargetDecision in enums.xml.
+enum class OptimizationTargetDecision {
+  kUnknown = 0,
+  // The page load does not match the optimization target.
+  kPageLoadDoesNotMatch = 1,
+  // The page load matches the optimization target.
+  kPageLoadMatches = 2,
+  // The model needed to make the target decision was not available on the
+  // client.
+  kModelNotAvailableOnClient = 3,
+  // The page load is part of a model prediction holdback where all decisions
+  // will return |OptimizationGuideDecision::kFalse| in an attempt to not taint
+  // the data for understanding the production recall of the model.
+  kModelPredictionHoldback = 4,
+  // The OptimizationGuideDecider was not initialized yet.
+  kDeciderNotInitialized = 5,
+
+  // Add new values above this line.
+  kMaxValue = kDeciderNotInitialized,
+};
+
+// The statuses for a prediction model in the prediction manager when requested
+// to be evaluated.
+//
+// Keep in sync with OptimizationGuidePredictionManagerModelStatus in enums.xml.
+enum class PredictionManagerModelStatus {
+  kUnknown = 0,
+  // The model is loaded and available for use.
+  kModelAvailable = 1,
+  // The store is initialized but does not contain a model for the optimization
+  // target.
+  kStoreAvailableNoModelForTarget = 2,
+  // The store is initialized and contains a model for the optimization target
+  // but it is not loaded in memory.
+  kStoreAvailableModelNotLoaded = 3,
+  // The store is not initialized and it is unknown if it contains a model for
+  // the optimization target.
+  kStoreUnavailableModelUnknown = 4,
+
+  // Add new values above this line.
+  kMaxValue = kStoreUnavailableModelUnknown,
+};
+
+}  // namespace optimization_guide
+
+#endif  // COMPONENTS_OPTIMIZATION_GUIDE_CORE_OPTIMIZATION_GUIDE_ENUMS_H_
diff --git a/components/optimization_guide/core/model_handler.h b/components/optimization_guide/core/model_handler.h
index 010734b..1d0e7e7 100644
--- a/components/optimization_guide/core/model_handler.h
+++ b/components/optimization_guide/core/model_handler.h
@@ -16,6 +16,7 @@
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/time/time.h"
 #include "components/optimization_guide/core/model_executor.h"
+#include "components/optimization_guide/core/model_util.h"
 #include "components/optimization_guide/core/optimization_guide_model_provider.h"
 #include "components/optimization_guide/core/optimization_guide_util.h"
 #include "components/optimization_guide/core/optimization_target_model_observer.h"
diff --git a/components/optimization_guide/core/model_info.cc b/components/optimization_guide/core/model_info.cc
index 077b95d..cab55ff 100644
--- a/components/optimization_guide/core/model_info.cc
+++ b/components/optimization_guide/core/model_info.cc
@@ -6,10 +6,29 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/notreached.h"
-#include "components/optimization_guide/core/optimization_guide_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "components/optimization_guide/core/model_util.h"
 
 namespace optimization_guide {
 
+namespace {
+
+// Returns a string representation of the given |file_path|, handling platform
+// differences in the conversion.
+//
+// TODO(crbug.com/1283494): Remove this duplicate implementation when
+// model_util.cc is stablized and this function can be moved there.
+std::string FilePathToString(const base::FilePath& file_path) {
+#if defined(OS_WIN)
+  return base::WideToUTF8(file_path.value());
+#else
+  return file_path.value();
+#endif
+}
+
+}  // namespace
+
 ModelInfo::ModelInfo(const base::FilePath& model_file_path,
                      const base::flat_set<base::FilePath>& additional_files,
                      const int64_t version,
diff --git a/components/optimization_guide/core/model_util.cc b/components/optimization_guide/core/model_util.cc
new file mode 100644
index 0000000..9bb75b4
--- /dev/null
+++ b/components/optimization_guide/core/model_util.cc
@@ -0,0 +1,78 @@
+// Copyright 2021 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 "components/optimization_guide/core/model_util.h"
+
+#include "base/base64.h"
+#include "base/containers/flat_set.h"
+#include "base/notreached.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "net/base/url_util.h"
+#include "url/url_canon.h"
+
+namespace optimization_guide {
+
+// These names are persisted to histograms, so don't change them.
+std::string GetStringNameForOptimizationTarget(
+    optimization_guide::proto::OptimizationTarget optimization_target) {
+  switch (optimization_target) {
+    case proto::OPTIMIZATION_TARGET_UNKNOWN:
+      return "Unknown";
+    case proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD:
+      return "PainfulPageLoad";
+    case proto::OPTIMIZATION_TARGET_LANGUAGE_DETECTION:
+      return "LanguageDetection";
+    case proto::OPTIMIZATION_TARGET_PAGE_TOPICS:
+      return "PageTopics";
+    case proto::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
+      return "SegmentationNewTab";
+    case proto::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
+      return "SegmentationShare";
+    case proto::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
+      return "SegmentationVoice";
+    case proto::OPTIMIZATION_TARGET_MODEL_VALIDATION:
+      return "ModelValidation";
+    case proto::OPTIMIZATION_TARGET_PAGE_ENTITIES:
+      return "PageEntities";
+    case proto::OPTIMIZATION_TARGET_NOTIFICATION_PERMISSION_PREDICTIONS:
+      return "NotificationPermissions";
+    case proto::OPTIMIZATION_TARGET_SEGMENTATION_DUMMY:
+      return "SegmentationDummyFeature";
+    case proto::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_START_ANDROID:
+      return "SegmentationChromeStartAndroid";
+    case proto::OPTIMIZATION_TARGET_SEGMENTATION_QUERY_TILES:
+      return "SegmentationQueryTiles";
+    case proto::OPTIMIZATION_TARGET_PAGE_VISIBILITY:
+      return "PageVisibility";
+    case proto::OPTIMIZATION_TARGET_AUTOFILL_ASSISTANT:
+      return "AutofillAssistant";
+    case proto::OPTIMIZATION_TARGET_PAGE_TOPICS_V2:
+      return "PageTopicsV2";
+    case proto::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT:
+      return "SegmentationChromeLowUserEngagement";
+      // Whenever a new value is added, make sure to add it to the OptTarget
+      // variant list in
+      // //tools/metrics/histograms/metadata/optimization/histograms.xml.
+  }
+  NOTREACHED();
+  return std::string();
+}
+
+absl::optional<base::FilePath> StringToFilePath(const std::string& str_path) {
+  if (str_path.empty())
+    return absl::nullopt;
+
+#if defined(OS_WIN)
+  return base::FilePath(base::UTF8ToWide(str_path));
+#else
+  return base::FilePath(str_path);
+#endif
+}
+
+base::FilePath GetBaseFileNameForModels() {
+  return base::FilePath(FILE_PATH_LITERAL("model.tflite"));
+}
+
+}  // namespace optimization_guide
diff --git a/components/optimization_guide/core/model_util.h b/components/optimization_guide/core/model_util.h
new file mode 100644
index 0000000..db12304
--- /dev/null
+++ b/components/optimization_guide/core/model_util.h
@@ -0,0 +1,33 @@
+// Copyright 2021 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 COMPONENTS_OPTIMIZATION_GUIDE_CORE_MODEL_UTIL_H_
+#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_MODEL_UTIL_H_
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace optimization_guide {
+
+// Returns the string than can be used to record histograms for the optimization
+// target. If adding a histogram to use the string or adding an optimization
+// target, update the OptimizationGuide.OptimizationTargets histogram suffixes
+// in histograms.xml.
+std::string GetStringNameForOptimizationTarget(
+    proto::OptimizationTarget optimization_target);
+
+// Returns the file path represented by the given string, handling platform
+// differences in the conversion. nullopt is only returned iff the passed string
+// is empty.
+absl::optional<base::FilePath> StringToFilePath(const std::string& str_path);
+
+// Returns the base file name to use for storing all prediction models.
+base::FilePath GetBaseFileNameForModels();
+
+}  // namespace optimization_guide
+
+#endif  // COMPONENTS_OPTIMIZATION_GUIDE_CORE_MODEL_UTIL_H_
diff --git a/components/optimization_guide/core/model_validator_unittest.cc b/components/optimization_guide/core/model_validator_unittest.cc
index 48a66a6..5a3cd12 100644
--- a/components/optimization_guide/core/model_validator_unittest.cc
+++ b/components/optimization_guide/core/model_validator_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
+#include "components/optimization_guide/core/model_util.h"
 #include "components/optimization_guide/core/model_validator.h"
 #include "components/optimization_guide/core/optimization_guide_switches.h"
 #include "components/optimization_guide/core/optimization_guide_util.h"
diff --git a/components/optimization_guide/core/optimization_guide_enums.h b/components/optimization_guide/core/optimization_guide_enums.h
index 88d24bc..a7e817c2 100644
--- a/components/optimization_guide/core/optimization_guide_enums.h
+++ b/components/optimization_guide/core/optimization_guide_enums.h
@@ -49,29 +49,6 @@
   kMaxValue = kHintFetchStartedButNotAvailableInTime,
 };
 
-// The types of decisions that can be made for an optimization target.
-//
-// Keep in sync with OptimizationGuideOptimizationTargetDecision in enums.xml.
-enum class OptimizationTargetDecision {
-  kUnknown,
-  // The page load does not match the optimization target.
-  kPageLoadDoesNotMatch,
-  // The page load matches the optimization target.
-  kPageLoadMatches,
-  // The model needed to make the target decision was not available on the
-  // client.
-  kModelNotAvailableOnClient,
-  // The page load is part of a model prediction holdback where all decisions
-  // will return |OptimizationGuideDecision::kFalse| in an attempt to not taint
-  // the data for understanding the production recall of the model.
-  kModelPredictionHoldback,
-  // The OptimizationGuideDecider was not initialized yet.
-  kDeciderNotInitialized,
-
-  // Add new values above this line.
-  kMaxValue = kDeciderNotInitialized,
-};
-
 // The statuses for racing a hints fetch with the current navigation based
 // on the availability of hints for both the current host and URL.
 //
@@ -101,28 +78,6 @@
       kDeprecatedRaceNavigationFetchNotAttemptedTooManyConcurrentFetches,
 };
 
-// The statuses for a prediction model in the prediction manager when requested
-// to be evaluated.
-//
-// Keep in sync with OptimizationGuidePredictionManagerModelStatus in enums.xml.
-enum class PredictionManagerModelStatus {
-  kUnknown,
-  // The model is loaded and available for use.
-  kModelAvailable,
-  // The store is initialized but does not contain a model for the optimization
-  // target.
-  kStoreAvailableNoModelForTarget,
-  // The store is initialized and contains a model for the optimization target
-  // but it is not loaded in memory.
-  kStoreAvailableModelNotLoaded,
-  // The store is not initialized and it is unknown if it contains a model for
-  // the optimization target.
-  kStoreUnavailableModelUnknown,
-
-  // Add new values above this line.
-  kMaxValue = kStoreUnavailableModelUnknown,
-};
-
 // The statuses for a download file containing a prediction model when verified
 // and processed.
 //
diff --git a/components/optimization_guide/core/optimization_guide_store.cc b/components/optimization_guide/core/optimization_guide_store.cc
index 635cac8..080e6ba 100644
--- a/components/optimization_guide/core/optimization_guide_store.cc
+++ b/components/optimization_guide/core/optimization_guide_store.cc
@@ -20,6 +20,7 @@
 #include "components/leveldb_proto/public/proto_database_provider.h"
 #include "components/leveldb_proto/public/shared_proto_database_client_list.h"
 #include "components/optimization_guide/core/memory_hint.h"
+#include "components/optimization_guide/core/model_util.h"
 #include "components/optimization_guide/core/optimization_guide_features.h"
 #include "components/optimization_guide/core/optimization_guide_util.h"
 #include "components/optimization_guide/proto/hint_cache.pb.h"
diff --git a/components/optimization_guide/core/optimization_guide_store_unittest.cc b/components/optimization_guide/core/optimization_guide_store_unittest.cc
index 9bd9d7e..40326eb 100644
--- a/components/optimization_guide/core/optimization_guide_store_unittest.cc
+++ b/components/optimization_guide/core/optimization_guide_store_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
 #include "components/leveldb_proto/testing/fake_db.h"
+#include "components/optimization_guide/core/model_util.h"
 #include "components/optimization_guide/core/optimization_guide_features.h"
 #include "components/optimization_guide/core/optimization_guide_util.h"
 #include "components/optimization_guide/core/store_update_data.h"
diff --git a/components/optimization_guide/core/optimization_guide_util.cc b/components/optimization_guide/core/optimization_guide_util.cc
index 3e87107..a5bb5665 100644
--- a/components/optimization_guide/core/optimization_guide_util.cc
+++ b/components/optimization_guide/core/optimization_guide_util.cc
@@ -19,52 +19,6 @@
 
 namespace optimization_guide {
 
-// These names are persisted to histograms, so don't change them.
-std::string GetStringNameForOptimizationTarget(
-    optimization_guide::proto::OptimizationTarget optimization_target) {
-  switch (optimization_target) {
-    case proto::OPTIMIZATION_TARGET_UNKNOWN:
-      return "Unknown";
-    case proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD:
-      return "PainfulPageLoad";
-    case proto::OPTIMIZATION_TARGET_LANGUAGE_DETECTION:
-      return "LanguageDetection";
-    case proto::OPTIMIZATION_TARGET_PAGE_TOPICS:
-      return "PageTopics";
-    case proto::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
-      return "SegmentationNewTab";
-    case proto::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
-      return "SegmentationShare";
-    case proto::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
-      return "SegmentationVoice";
-    case proto::OPTIMIZATION_TARGET_MODEL_VALIDATION:
-      return "ModelValidation";
-    case proto::OPTIMIZATION_TARGET_PAGE_ENTITIES:
-      return "PageEntities";
-    case proto::OPTIMIZATION_TARGET_NOTIFICATION_PERMISSION_PREDICTIONS:
-      return "NotificationPermissions";
-    case proto::OPTIMIZATION_TARGET_SEGMENTATION_DUMMY:
-      return "SegmentationDummyFeature";
-    case proto::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_START_ANDROID:
-      return "SegmentationChromeStartAndroid";
-    case proto::OPTIMIZATION_TARGET_SEGMENTATION_QUERY_TILES:
-      return "SegmentationQueryTiles";
-    case proto::OPTIMIZATION_TARGET_PAGE_VISIBILITY:
-      return "PageVisibility";
-    case proto::OPTIMIZATION_TARGET_AUTOFILL_ASSISTANT:
-      return "AutofillAssistant";
-    case proto::OPTIMIZATION_TARGET_PAGE_TOPICS_V2:
-      return "PageTopicsV2";
-    case proto::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT:
-      return "SegmentationChromeLowUserEngagement";
-      // Whenever a new value is added, make sure to add it to the OptTarget
-      // variant list in
-      // //tools/metrics/histograms/metadata/optimization/histograms.xml.
-  }
-  NOTREACHED();
-  return std::string();
-}
-
 bool IsHostValidToFetchFromRemoteOptimizationGuide(const std::string& host) {
   if (net::HostStringIsLocalhost(host))
     return false;
@@ -110,17 +64,6 @@
   return filtered_active_field_trials;
 }
 
-absl::optional<base::FilePath> StringToFilePath(const std::string& str_path) {
-  if (str_path.empty())
-    return absl::nullopt;
-
-#if defined(OS_WIN)
-  return base::FilePath(base::UTF8ToWide(str_path));
-#else
-  return base::FilePath(str_path);
-#endif
-}
-
 std::string FilePathToString(const base::FilePath& file_path) {
 #if defined(OS_WIN)
   return base::WideToUTF8(file_path.value());
@@ -129,10 +72,6 @@
 #endif
 }
 
-base::FilePath GetBaseFileNameForModels() {
-  return base::FilePath(FILE_PATH_LITERAL("model.tflite"));
-}
-
 std::string GetStringForOptimizationGuideDecision(
     OptimizationGuideDecision decision) {
   switch (decision) {
diff --git a/components/optimization_guide/core/optimization_guide_util.h b/components/optimization_guide/core/optimization_guide_util.h
index f425dde..425d16b6 100644
--- a/components/optimization_guide/core/optimization_guide_util.h
+++ b/components/optimization_guide/core/optimization_guide_util.h
@@ -18,13 +18,6 @@
 
 enum class OptimizationGuideDecision;
 
-// Returns the string than can be used to record histograms for the optimization
-// target. If adding a histogram to use the string or adding an optimization
-// target, update the OptimizationGuide.OptimizationTargets histogram suffixes
-// in histograms.xml.
-std::string GetStringNameForOptimizationTarget(
-    proto::OptimizationTarget optimization_target);
-
 // Returns false if the host is an IP address, localhosts, or an invalid
 // host that is not supported by the remote optimization guide.
 bool IsHostValidToFetchFromRemoteOptimizationGuide(const std::string& host);
@@ -34,18 +27,10 @@
 google::protobuf::RepeatedPtrField<proto::FieldTrial>
 GetActiveFieldTrialsAllowedForFetch();
 
-// Returns the file path represented by the given string, handling platform
-// differences in the conversion. nullopt is only returned iff the passed string
-// is empty.
-absl::optional<base::FilePath> StringToFilePath(const std::string& str_path);
-
 // Returns a string representation of the given |file_path|, handling platform
 // differences in the conversion.
 std::string FilePathToString(const base::FilePath& file_path);
 
-// Returns the base file name to use for storing all prediction models.
-base::FilePath GetBaseFileNameForModels();
-
 // Validates that the metadata stored in |any_metadata_| is of the same type
 // and is parseable as |T|. Will return metadata if all checks pass.
 template <class T,
diff --git a/components/optimization_guide/core/prediction_model.h b/components/optimization_guide/core/prediction_model.h
index bf81903..d2c5fba 100644
--- a/components/optimization_guide/core/prediction_model.h
+++ b/components/optimization_guide/core/prediction_model.h
@@ -11,6 +11,7 @@
 
 #include "base/containers/flat_map.h"
 #include "base/containers/flat_set.h"
+#include "components/optimization_guide/core/model_enums.h"
 #include "components/optimization_guide/core/optimization_guide_enums.h"
 #include "components/optimization_guide/proto/models.pb.h"
 
diff --git a/components/optimization_guide/core/test_model_info_builder.cc b/components/optimization_guide/core/test_model_info_builder.cc
index 9efa9d48..c1eef84 100644
--- a/components/optimization_guide/core/test_model_info_builder.cc
+++ b/components/optimization_guide/core/test_model_info_builder.cc
@@ -4,6 +4,7 @@
 
 #include "components/optimization_guide/core/test_model_info_builder.h"
 
+#include "components/optimization_guide/core/model_util.h"
 #include "components/optimization_guide/core/optimization_guide_test_util.h"
 #include "components/optimization_guide/core/optimization_guide_util.h"
 
diff --git a/components/optimization_guide/core/tflite_model_executor.h b/components/optimization_guide/core/tflite_model_executor.h
index fe615dc..560ef7d 100644
--- a/components/optimization_guide/core/tflite_model_executor.h
+++ b/components/optimization_guide/core/tflite_model_executor.h
@@ -17,9 +17,9 @@
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
 #include "components/optimization_guide/core/execution_status.h"
+#include "components/optimization_guide/core/model_enums.h"
 #include "components/optimization_guide/core/model_executor.h"
-#include "components/optimization_guide/core/optimization_guide_enums.h"
-#include "components/optimization_guide/core/optimization_guide_util.h"
+#include "components/optimization_guide/core/model_util.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/tflite/src/tensorflow/lite/c/common.h"
 #include "third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/base_task_api.h"
diff --git a/components/password_manager/core/browser/ui/insecure_credentials_manager.cc b/components/password_manager/core/browser/ui/insecure_credentials_manager.cc
index 826dec7..7de587c 100644
--- a/components/password_manager/core/browser/ui/insecure_credentials_manager.cc
+++ b/components/password_manager/core/browser/ui/insecure_credentials_manager.cc
@@ -257,7 +257,8 @@
   for (const PasswordForm& saved_password : presenter_->GetSavedPasswords()) {
     if (saved_password.password_value == credential.password() &&
         CanonicalizeUsername(saved_password.username_value) ==
-            canonicalized_username) {
+            canonicalized_username &&
+        !saved_password.password_issues.contains(InsecureType::kLeaked)) {
       PasswordForm form_to_update = saved_password;
       form_to_update.password_issues.insert_or_assign(
           InsecureType::kLeaked,
diff --git a/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc b/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc
index 9644846e..90aad248 100644
--- a/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc
+++ b/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc
@@ -666,6 +666,32 @@
   EXPECT_THAT(provider().GetInsecureCredentials(), ElementsAre(expected));
 }
 
+// Test verifies that saving LeakCheckCredential doesn't occur for already
+// leaked passwords.
+TEST_F(InsecureCredentialsManagerTest, SaveCompromisedPasswordForExistingLeak) {
+  PasswordForm password_form =
+      MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
+  LeakCheckCredential credential = MakeLeakCredential(kUsername1, kPassword1);
+
+  InsecurityMetadata insecurity_metadata(base::Time::Now() - base::Days(3),
+                                         IsMuted(true));
+  password_form.password_issues.insert(
+      {InsecureType::kLeaked, insecurity_metadata});
+
+  store().AddLogin(password_form);
+  RunUntilIdle();
+
+  provider().SaveInsecureCredential(credential);
+  RunUntilIdle();
+
+  EXPECT_EQ(insecurity_metadata,
+            store()
+                .stored_passwords()
+                .at(kExampleCom)
+                .back()
+                .password_issues.at(InsecureType::kLeaked));
+}
+
 // Test verifies that editing Compromised Credential via provider change the
 // original password form.
 TEST_F(InsecureCredentialsManagerTest, UpdateCompromisedPassword) {
diff --git a/components/permissions/contexts/geolocation_permission_context_android.cc b/components/permissions/contexts/geolocation_permission_context_android.cc
index 9215a91..42d8f07 100644
--- a/components/permissions/contexts/geolocation_permission_context_android.cc
+++ b/components/permissions/contexts/geolocation_permission_context_android.cc
@@ -307,7 +307,7 @@
       break;
     case LocationSettingsDialogBackOff::kOneMonth:
       backoff_level = LocationSettingsDialogBackOff::kThreeMonths;
-      FALLTHROUGH;
+      [[fallthrough]];
     case LocationSettingsDialogBackOff::kThreeMonths:
       next_show += base::Days(90);
       break;
diff --git a/components/permissions/permission_context_base_unittest.cc b/components/permissions/permission_context_base_unittest.cc
index fe893242..2358bbe07 100644
--- a/components/permissions/permission_context_base_unittest.cc
+++ b/components/permissions/permission_context_base_unittest.cc
@@ -772,7 +772,13 @@
 }
 
 // Test setting a custom number of dismissals before block via variations.
-TEST_F(PermissionContextBaseTests, TestDismissVariations) {
+// TODO(crbug.com/1278842): Fix flaky test on Linux TSan.
+#if defined(OS_LINUX) && defined(THREAD_SANITIZER)
+#define MAYBE_TestDismissVariations DISABLED_TestDismissVariations
+#else
+#define MAYBE_TestDismissVariations TestDismissVariations
+#endif
+TEST_F(PermissionContextBaseTests, MAYBE_TestDismissVariations) {
   TestVariationBlockOnSeveralDismissals_TestContent();
 }
 
@@ -804,7 +810,12 @@
 
 // Tests the global kill switch by enabling/disabling the Field Trials.
 // TODO(crbug.com/1278842): Fix flaky test on Linux TSan.
-TEST_F(PermissionContextBaseTests, DISABLED_TestGlobalKillSwitch) {
+#if defined(OS_LINUX) && defined(THREAD_SANITIZER)
+#define MAYBE_TestGlobalKillSwitch DISABLED_TestGlobalKillSwitch
+#else
+#define MAYBE_TestGlobalKillSwitch TestGlobalKillSwitch
+#endif
+TEST_F(PermissionContextBaseTests, MAYBE_TestGlobalKillSwitch) {
   TestGlobalPermissionsKillSwitch(ContentSettingsType::GEOLOCATION);
   TestGlobalPermissionsKillSwitch(ContentSettingsType::NOTIFICATIONS);
   TestGlobalPermissionsKillSwitch(ContentSettingsType::MIDI_SYSEX);
diff --git a/components/permissions/prediction_service/BUILD.gn b/components/permissions/prediction_service/BUILD.gn
index 2abe8e2c..dabb2a0 100644
--- a/components/permissions/prediction_service/BUILD.gn
+++ b/components/permissions/prediction_service/BUILD.gn
@@ -13,10 +13,6 @@
   sources = [
     "prediction_common.cc",
     "prediction_common.h",
-    "prediction_model_executor.cc",
-    "prediction_model_executor.h",
-    "prediction_model_handler.cc",
-    "prediction_model_handler.h",
     "prediction_request_features.h",
     "prediction_service.cc",
     "prediction_service.h",
@@ -29,15 +25,27 @@
     "//content/public/browser",
     "//services/network/public/cpp:cpp",
     "//third_party/protobuf:protobuf_lite",
-    "//third_party/tflite:tflite_public_headers",
-    "//third_party/tflite_support",
-    "//third_party/tflite_support:tflite_support_proto",
   ]
   public_deps = [
     ":prediction_service_messages_proto",
     "//components/optimization_guide/core",
     "//components/optimization_guide/proto:optimization_guide_proto",
   ]
+
+  if (build_with_tflite_lib) {
+    sources += [
+      "prediction_model_executor.cc",
+      "prediction_model_executor.h",
+      "prediction_model_handler.cc",
+      "prediction_model_handler.h",
+    ]
+
+    deps += [
+      "//third_party/tflite:tflite_public_headers",
+      "//third_party/tflite_support",
+      "//third_party/tflite_support:tflite_support_proto",
+    ]
+  }
 }
 
 source_set("unit_tests") {
diff --git a/components/policy/content/BUILD.gn b/components/policy/content/BUILD.gn
index 2709062..2d2ef93 100644
--- a/components/policy/content/BUILD.gn
+++ b/components/policy/content/BUILD.gn
@@ -20,6 +20,7 @@
     "//components/policy/core/browser",
     "//components/safe_search_api",
     "//components/safe_search_api:safe_search_client",
+    "//components/url_matcher",
     "//content/public/browser",
     "//net",
   ]
diff --git a/components/policy/content/DEPS b/components/policy/content/DEPS
index 9cc3c03..ca396db 100644
--- a/components/policy/content/DEPS
+++ b/components/policy/content/DEPS
@@ -4,6 +4,7 @@
   "+components/keyed_service",
   "+components/prefs",
   "+components/safe_search_api",
+  "+components/url_matcher",
   "+components/user_prefs",
   "+net/base",
 ]
diff --git a/components/policy/content/safe_search_service.cc b/components/policy/content/safe_search_service.cc
index dcd0a82..704571f 100644
--- a/components/policy/content/safe_search_service.cc
+++ b/components/policy/content/safe_search_service.cc
@@ -8,9 +8,9 @@
 
 #include "base/bind.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/policy/core/browser/url_util.h"
 #include "components/safe_search_api/safe_search/safe_search_url_checker_client.h"
 #include "components/safe_search_api/url_checker.h"
+#include "components/url_matcher/url_util.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/storage_partition.h"
 #include "net/base/net_errors.h"
@@ -70,7 +70,7 @@
   }
 
   return safe_search_url_checker_->CheckURL(
-      policy::url_util::Normalize(url),
+      url_matcher::util::Normalize(url),
       base::BindOnce(&OnCheckURLDone, std::move(callback)));
 }
 
diff --git a/components/policy/content/safe_sites_navigation_throttle.cc b/components/policy/content/safe_sites_navigation_throttle.cc
index dec33b96..8c420e1 100644
--- a/components/policy/content/safe_sites_navigation_throttle.cc
+++ b/components/policy/content/safe_sites_navigation_throttle.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/strings/string_piece.h"
 #include "components/policy/content/safe_search_service.h"
-#include "components/policy/core/browser/url_util.h"
+#include "components/url_matcher/url_util.h"
 #include "content/public/browser/navigation_handle.h"
 #include "url/gurl.h"
 
@@ -57,7 +57,7 @@
   if (!url.SchemeIsHTTPOrHTTPS())
     return PROCEED;
 
-  GURL effective_url = policy::url_util::GetEmbeddedURL(url);
+  GURL effective_url = url_matcher::util::GetEmbeddedURL(url);
   if (!effective_url.is_valid())
     effective_url = url;
 
diff --git a/components/policy/core/browser/BUILD.gn b/components/policy/core/browser/BUILD.gn
index 73efbdb..db298f4 100644
--- a/components/policy/core/browser/BUILD.gn
+++ b/components/policy/core/browser/BUILD.gn
@@ -42,8 +42,6 @@
     "url_blocklist_manager.h",
     "url_blocklist_policy_handler.cc",
     "url_blocklist_policy_handler.h",
-    "url_util.cc",
-    "url_util.h",
     "webui/json_generation.cc",
     "webui/json_generation.h",
     "webui/machine_level_user_cloud_policy_status_provider.cc",
@@ -142,7 +140,6 @@
     "url_allowlist_policy_handler_unittest.cc",
     "url_blocklist_manager_unittest.cc",
     "url_blocklist_policy_handler_unittest.cc",
-    "url_util_unittest.cc",
   ]
   deps = [
     ":browser",
@@ -153,6 +150,7 @@
     "//components/signin/public/identity_manager:identity_manager",
     "//components/signin/public/identity_manager:test_support",
     "//components/url_formatter",
+    "//components/url_matcher",
     "//google_apis",
     "//net",
     "//services/network:test_support",
diff --git a/components/policy/core/browser/configuration_policy_handler.cc b/components/policy/core/browser/configuration_policy_handler.cc
index 5bc81c96..4430fb7 100644
--- a/components/policy/core/browser/configuration_policy_handler.cc
+++ b/components/policy/core/browser/configuration_policy_handler.cc
@@ -31,7 +31,10 @@
 
 namespace policy {
 
-// ConfigurationPolicyHandler implementation -----------------------------------
+const size_t kMaxUrlFiltersPerPolicy = 1000;
+
+// ConfigurationPolicyHandler implementation
+// -----------------------------------
 
 ConfigurationPolicyHandler::ConfigurationPolicyHandler() {}
 
diff --git a/components/policy/core/browser/configuration_policy_handler.h b/components/policy/core/browser/configuration_policy_handler.h
index 17ce16dd..ddcae76f 100644
--- a/components/policy/core/browser/configuration_policy_handler.h
+++ b/components/policy/core/browser/configuration_policy_handler.h
@@ -23,6 +23,8 @@
 struct PolicyHandlerParameters;
 class PolicyMap;
 
+extern POLICY_EXPORT const size_t kMaxUrlFiltersPerPolicy;
+
 // Maps a policy type to a preference path, and to the expected value type.
 struct POLICY_EXPORT PolicyToPreferenceMapEntry {
   const char* const policy_name;
diff --git a/components/policy/core/browser/url_allowlist_policy_handler.cc b/components/policy/core/browser/url_allowlist_policy_handler.cc
index da2a985..7de0bf33 100644
--- a/components/policy/core/browser/url_allowlist_policy_handler.cc
+++ b/components/policy/core/browser/url_allowlist_policy_handler.cc
@@ -13,12 +13,12 @@
 #include "base/strings/string_util.h"
 #include "base/values.h"
 #include "components/policy/core/browser/policy_error_map.h"
-#include "components/policy/core/browser/url_util.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_pref_names.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_value_map.h"
 #include "components/strings/grit/components_strings.h"
+#include "components/url_matcher/url_util.h"
 
 namespace policy {
 
@@ -40,12 +40,12 @@
     return true;
   }
 
-  // Filters more than |url_util::kMaxFiltersPerPolicy| are ignored, add a
+  // Filters more than |policy::kMaxUrlFiltersPerPolicy| are ignored, add a
   // warning message.
-  if (url_allowlist->GetList().size() > url_util::GetMaxFiltersPerPolicy()) {
+  if (url_allowlist->GetList().size() > kMaxUrlFiltersPerPolicy) {
     errors->AddError(policy_name(),
                      IDS_POLICY_URL_ALLOW_BLOCK_LIST_MAX_FILTERS_LIMIT_WARNING,
-                     base::NumberToString(url_util::GetMaxFiltersPerPolicy()));
+                     base::NumberToString(kMaxUrlFiltersPerPolicy));
   }
 
   bool type_error = false;
@@ -93,8 +93,8 @@
 }
 
 bool URLAllowlistPolicyHandler::ValidatePolicy(const std::string& policy) {
-  url_util::FilterComponents components;
-  return url_util::FilterToComponents(
+  url_matcher::util::FilterComponents components;
+  return url_matcher::util::FilterToComponents(
       policy, &components.scheme, &components.host,
       &components.match_subdomains, &components.port, &components.path,
       &components.query);
diff --git a/components/policy/core/browser/url_allowlist_policy_handler_unittest.cc b/components/policy/core/browser/url_allowlist_policy_handler_unittest.cc
index f2737b79..beb82e5 100644
--- a/components/policy/core/browser/url_allowlist_policy_handler_unittest.cc
+++ b/components/policy/core/browser/url_allowlist_policy_handler_unittest.cc
@@ -10,13 +10,13 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
 #include "components/policy/core/browser/policy_error_map.h"
-#include "components/policy/core/browser/url_util.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_pref_names.h"
 #include "components/policy/core/common/policy_types.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_value_map.h"
 #include "components/strings/grit/components_strings.h"
+#include "components/url_matcher/url_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -122,7 +122,7 @@
 
 TEST_F(URLAllowlistPolicyHandlerTest,
        ApplyPolicySettings_CheckPolicySettingsMaxFiltersLimitOK) {
-  size_t max_filters_per_policy = url_util::GetMaxFiltersPerPolicy();
+  size_t max_filters_per_policy = policy::kMaxUrlFiltersPerPolicy;
   base::Value urls =
       GetURLAllowlistPolicyValueWithEntries(max_filters_per_policy);
 
@@ -142,7 +142,7 @@
 // |errors_| when URLAllowlist entries exceed the max filters per policy limit.
 TEST_F(URLAllowlistPolicyHandlerTest,
        ApplyPolicySettings_CheckPolicySettingsMaxFiltersLimitExceeded) {
-  size_t max_filters_per_policy = url_util::GetMaxFiltersPerPolicy();
+  size_t max_filters_per_policy = policy::kMaxUrlFiltersPerPolicy;
   base::Value urls =
       GetURLAllowlistPolicyValueWithEntries(max_filters_per_policy + 1);
 
diff --git a/components/policy/core/browser/url_blocklist_manager.cc b/components/policy/core/browser/url_blocklist_manager.cc
index 244825593d..19f11ebc 100644
--- a/components/policy/core/browser/url_blocklist_manager.cc
+++ b/components/policy/core/browser/url_blocklist_manager.cc
@@ -46,9 +46,9 @@
 
 namespace policy {
 
-using url_util::CreateConditionSet;
-using url_util::FilterComponents;
-using url_util::FilterToComponents;
+using url_matcher::util::CreateConditionSet;
+using url_matcher::util::FilterComponents;
+using url_matcher::util::FilterToComponents;
 
 namespace {
 
@@ -112,16 +112,18 @@
 
 }  // namespace
 
-URLBlocklist::URLBlocklist() : id_(0), url_matcher_(new URLMatcher) {}
+URLBlocklist::URLBlocklist() : url_matcher_(new URLMatcher) {}
 
 URLBlocklist::~URLBlocklist() = default;
 
 void URLBlocklist::Block(const base::ListValue* filters) {
-  url_util::AddFilters(url_matcher_.get(), false, &id_, filters, &filters_);
+  url_matcher::util::AddFilters(url_matcher_.get(), false, &id_, filters,
+                                &filters_);
 }
 
 void URLBlocklist::Allow(const base::ListValue* filters) {
-  url_util::AddFilters(url_matcher_.get(), true, &id_, filters, &filters_);
+  url_matcher::util::AddFilters(url_matcher_.get(), true, &id_, filters,
+                                &filters_);
 }
 
 bool URLBlocklist::IsURLBlocked(const GURL& url) const {
@@ -150,7 +152,7 @@
   // Some of the internal Chrome URLs are not affected by the "*" in the
   // blocklist. Note that the "*" is the lowest priority filter possible, so
   // any higher priority filter will be applied first.
-  if (max->IsBlocklistWildcard() && BypassBlocklistWildcardForURL(url))
+  if (!max->allow && max->IsWildcard() && BypassBlocklistWildcardForURL(url))
     return URLBlocklist::URLBlocklistState::URL_IN_ALLOWLIST;
 
   return max->allow ? URLBlocklist::URLBlocklistState::URL_IN_ALLOWLIST
@@ -164,8 +166,8 @@
 // static
 bool URLBlocklist::FilterTakesPrecedence(const FilterComponents& lhs,
                                          const FilterComponents& rhs) {
-  // The "*" wildcard is the lowest priority filter.
-  if (rhs.IsBlocklistWildcard())
+  // The "*" wildcard in the blocklist is the lowest priority filter.
+  if (!rhs.allow && rhs.IsWildcard())
     return true;
 
   if (lhs.match_subdomains && !rhs.match_subdomains)
@@ -183,8 +185,10 @@
   if (path_length != other_path_length)
     return path_length > other_path_length;
 
-  if (lhs.number_of_key_value_pairs != rhs.number_of_key_value_pairs)
-    return lhs.number_of_key_value_pairs > rhs.number_of_key_value_pairs;
+  if (lhs.number_of_url_matching_conditions !=
+      rhs.number_of_url_matching_conditions)
+    return lhs.number_of_url_matching_conditions >
+           rhs.number_of_url_matching_conditions;
 
   if (lhs.allow && !rhs.allow)
     return true;
diff --git a/components/policy/core/browser/url_blocklist_manager.h b/components/policy/core/browser/url_blocklist_manager.h
index 0a77b5b..155064f 100644
--- a/components/policy/core/browser/url_blocklist_manager.h
+++ b/components/policy/core/browser/url_blocklist_manager.h
@@ -15,10 +15,10 @@
 #include "base/memory/raw_ptr.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "components/policy/core/browser/url_util.h"
 #include "components/policy/policy_export.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/url_matcher/url_matcher.h"
+#include "components/url_matcher/url_util.h"
 #include "url/gurl.h"
 
 class PrefService;
@@ -71,11 +71,13 @@
 
  private:
   // Returns true if |lhs| takes precedence over |rhs|.
-  static bool FilterTakesPrecedence(const url_util::FilterComponents& lhs,
-                                    const url_util::FilterComponents& rhs);
+  static bool FilterTakesPrecedence(
+      const url_matcher::util::FilterComponents& lhs,
+      const url_matcher::util::FilterComponents& rhs);
 
-  url_matcher::URLMatcherConditionSet::ID id_;
-  std::map<url_matcher::URLMatcherConditionSet::ID, url_util::FilterComponents>
+  url_matcher::URLMatcherConditionSet::ID id_ = 0;
+  std::map<url_matcher::URLMatcherConditionSet::ID,
+           url_matcher::util::FilterComponents>
       filters_;
   std::unique_ptr<url_matcher::URLMatcher> url_matcher_;
 };
diff --git a/components/policy/core/browser/url_blocklist_policy_handler.cc b/components/policy/core/browser/url_blocklist_policy_handler.cc
index 992268d9..0415748 100644
--- a/components/policy/core/browser/url_blocklist_policy_handler.cc
+++ b/components/policy/core/browser/url_blocklist_policy_handler.cc
@@ -14,12 +14,12 @@
 #include "base/strings/string_util.h"
 #include "base/values.h"
 #include "components/policy/core/browser/policy_error_map.h"
-#include "components/policy/core/browser/url_util.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_pref_names.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_value_map.h"
 #include "components/strings/grit/components_strings.h"
+#include "components/url_matcher/url_util.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace policy {
@@ -58,10 +58,10 @@
   // Filters more than |url_util::kMaxFiltersPerPolicy| are ignored, add a
   // warning message.
   if (url_blocklist->GetList().size() + disabled_schemes_entries >
-      url_util::GetMaxFiltersPerPolicy()) {
+      kMaxUrlFiltersPerPolicy) {
     errors->AddError(policy_name(),
                      IDS_POLICY_URL_ALLOW_BLOCK_LIST_MAX_FILTERS_LIMIT_WARNING,
-                     base::NumberToString(url_util::GetMaxFiltersPerPolicy()));
+                     base::NumberToString(kMaxUrlFiltersPerPolicy));
   }
 
   bool type_error = false;
@@ -128,8 +128,8 @@
 }
 
 bool URLBlocklistPolicyHandler::ValidatePolicy(const std::string& policy) {
-  url_util::FilterComponents components;
-  return url_util::FilterToComponents(
+  url_matcher::util::FilterComponents components;
+  return url_matcher::util::FilterToComponents(
       policy, &components.scheme, &components.host,
       &components.match_subdomains, &components.port, &components.path,
       &components.query);
diff --git a/components/policy/core/browser/url_blocklist_policy_handler_unittest.cc b/components/policy/core/browser/url_blocklist_policy_handler_unittest.cc
index 56c6d49..22dda01d 100644
--- a/components/policy/core/browser/url_blocklist_policy_handler_unittest.cc
+++ b/components/policy/core/browser/url_blocklist_policy_handler_unittest.cc
@@ -10,13 +10,13 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
 #include "components/policy/core/browser/policy_error_map.h"
-#include "components/policy/core/browser/url_util.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_pref_names.h"
 #include "components/policy/core/common/policy_types.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_value_map.h"
 #include "components/strings/grit/components_strings.h"
+#include "components/url_matcher/url_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -230,7 +230,7 @@
 
 TEST_F(URLBlocklistPolicyHandlerTest,
        ApplyPolicySettings_CheckPolicySettingsMaxFiltersLimitOK) {
-  size_t max_filters_per_policy = url_util::GetMaxFiltersPerPolicy();
+  size_t max_filters_per_policy = policy::kMaxUrlFiltersPerPolicy;
   base::Value urls =
       GetURLBlocklistPolicyValueWithEntries(max_filters_per_policy);
 
@@ -250,7 +250,7 @@
 // |errors_| when URLBlocklist entries exceed the max filters per policy limit.
 TEST_F(URLBlocklistPolicyHandlerTest,
        ApplyPolicySettings_CheckPolicySettingsMaxFiltersLimitExceeded_1) {
-  size_t max_filters_per_policy = url_util::GetMaxFiltersPerPolicy();
+  size_t max_filters_per_policy = policy::kMaxUrlFiltersPerPolicy;
   base::Value urls =
       GetURLBlocklistPolicyValueWithEntries(max_filters_per_policy + 1);
 
@@ -281,7 +281,7 @@
   in_disabled_schemes.Append(kTestDisabledScheme);
   SetPolicy(key::kDisabledSchemes, std::move(in_disabled_schemes));
 
-  size_t max_filters_per_policy = url_util::GetMaxFiltersPerPolicy();
+  size_t max_filters_per_policy = policy::kMaxUrlFiltersPerPolicy;
   base::Value urls =
       GetURLBlocklistPolicyValueWithEntries(max_filters_per_policy);
 
diff --git a/components/policy/core/browser/url_util.h b/components/policy/core/browser/url_util.h
deleted file mode 100644
index dbd34ff9..0000000
--- a/components/policy/core/browser/url_util.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2018 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 COMPONENTS_POLICY_CORE_BROWSER_URL_UTIL_H_
-#define COMPONENTS_POLICY_CORE_BROWSER_URL_UTIL_H_
-
-#include "base/memory/scoped_refptr.h"
-#include "base/values.h"
-#include "components/policy/policy_export.h"
-#include "components/url_matcher/url_matcher.h"
-
-class GURL;
-
-namespace policy {
-namespace url_util {
-
-// Normalizes a URL for matching purposes.
-POLICY_EXPORT GURL Normalize(const GURL& url);
-
-// Helper function to extract the underlying URL wrapped by services such as
-// Google AMP or Google Translate. Returns an empty GURL if |url| doesn't match
-// a known format.
-POLICY_EXPORT GURL GetEmbeddedURL(const GURL& url);
-
-// Gets maximum filters per policy.
-POLICY_EXPORT size_t GetMaxFiltersPerPolicy();
-
-struct FilterComponents {
-  FilterComponents();
-  FilterComponents(const FilterComponents&) = delete;
-  FilterComponents(FilterComponents&&);
-  FilterComponents& operator=(const FilterComponents&) = delete;
-  FilterComponents& operator=(FilterComponents&&) = default;
-
-  ~FilterComponents();
-
-  // Returns true if |this| represents the "*" filter in the blocklist.
-  bool IsBlocklistWildcard() const;
-
-  std::string scheme;
-  std::string host;
-  uint16_t port;
-  std::string path;
-  std::string query;
-  int number_of_key_value_pairs;
-  bool match_subdomains;
-  bool allow;
-};
-
-// Creates a condition set that can be used with the |url_matcher|. |id| needs
-// to be a unique number that will be returned by the |url_matcher| if the URL
-// matches that condition set. |allow| indicates if it is an allow-list (true)
-// or block-list (false) filter.
-POLICY_EXPORT scoped_refptr<url_matcher::URLMatcherConditionSet>
-CreateConditionSet(url_matcher::URLMatcher* url_matcher,
-                   url_matcher::URLMatcherConditionSet::ID id,
-                   const std::string& scheme,
-                   const std::string& host,
-                   bool match_subdomains,
-                   uint16_t port,
-                   const std::string& path,
-                   const std::string& query,
-                   bool allow);
-
-// Splits a URL filter into its components. A GURL isn't used because these
-// can be invalid URLs e.g. "google.com".
-// Returns false if the URL couldn't be parsed. In case false is returned,
-// the values of output parameters are undefined.
-// The |host| is preprocessed so it can be passed to URLMatcher for the
-// appropriate condition.
-// The optional username and password are ignored.
-// |match_subdomains| specifies whether the filter should include subdomains
-// of the hostname (if it is one.)
-// |port| is 0 if none is explicitly defined.
-// |path| does not include query parameters.
-// |query| contains the query parameters ('?' not included).
-// All arguments are mandatory.
-POLICY_EXPORT bool FilterToComponents(const std::string& filter,
-                                      std::string* scheme,
-                                      std::string* host,
-                                      bool* match_subdomains,
-                                      uint16_t* port,
-                                      std::string* path,
-                                      std::string* query);
-
-// Adds the filters in |list| to |url_matcher| as a ConditionSet::Vector.
-POLICY_EXPORT void AddFilters(
-    url_matcher::URLMatcher* matcher,
-    bool allow,
-    url_matcher::URLMatcherConditionSet::ID* id,
-    const base::ListValue* patterns,
-    std::map<url_matcher::URLMatcherConditionSet::ID,
-             url_util::FilterComponents>* filters = nullptr);
-
-POLICY_EXPORT void AddAllowFilters(url_matcher::URLMatcher* matcher,
-                                   const base::ListValue* patterns);
-
-}  // namespace url_util
-}  // namespace policy
-
-#endif  // COMPONENTS_POLICY_CORE_BROWSER_URL_UTIL_H_
diff --git a/components/policy/resources/policy_templates_de.xtb b/components/policy/resources/policy_templates_de.xtb
index 61bb09f1..07eb744 100644
--- a/components/policy/resources/policy_templates_de.xtb
+++ b/components/policy/resources/policy_templates_de.xtb
@@ -2582,6 +2582,7 @@
 <translation id="3964298692570794635">Unsichere Inhalte auf diesen Websites zulassen</translation>
 <translation id="3965339130942650562">Zeitlimit bis zur Abmeldung eines inaktiven Nutzers</translation>
 <translation id="396536755218079668">Betreute Nutzer</translation>
+<translation id="3968218878014278212">Aktivieren von „Eche“ zulassen.</translation>
 <translation id="3971673686578912106">Wenn die Richtlinie aktiviert ist, ist <ph name="PLUGIN_VM_NAME" /> für das Gerät aktiviert, solange andere Einstellungen dies ebenfalls zulassen. „<ph name="PLUGIN_VM_ALLOWED_POLICY_NAME" />“ und „<ph name="USER_PLUGIN_VM_ALLOWED_POLICY_NAME" />“ müssen „True“ sein und entweder „<ph name="PLUGIN_VM_LICENSE_KEY_POLICY_NAME" />“ oder „<ph name="PLUGIN_VM_USER_ID_POLICY_NAME" />“ muss für <ph name="PLUGIN_VM_NAME" /> aktiviert sein.
 
       Wenn die Richtlinie deaktiviert oder nicht konfiguriert ist, ist <ph name="PLUGIN_VM_NAME" /> für das Gerät nicht aktiviert.</translation>
@@ -3416,6 +3417,7 @@
       Wenn diese Richtlinie nicht konfiguriert oder auf "False" gesetzt ist, verwendet <ph name="PRODUCT_NAME" /> die vorhandenen Online-Einstellungen zur Widerrufsprüfung.</translation>
 <translation id="5078623750797048009">PDF-Anmerkungen aktivieren</translation>
 <translation id="5081204761483900654">Eingeschränkte verwaltete Gastsitzungen</translation>
+<translation id="5082296146261894974">Ermöglicht Nutzern, auf die Phone Hub-Benachrichtigung zu klicken, um die App „Eche“ zu starten.</translation>
 <translation id="5082572440690475059">Lesezugriff über die File System API auf diesen Websites erlauben</translation>
 <translation id="5085647276663819155">Druckvorschau deaktivieren</translation>
 <translation id="5090791951240382356">Zusammenführen von Wörterbuchrichtlinien aus unterschiedlichen Quellen erlauben</translation>
@@ -4160,6 +4162,7 @@
 
       Das Feld <ph name="RUN_ON_OS_LOGIN_FIELD" /> gibt an, ob eine Web-App während OS Login verwendet werden kann. Wenn dieses Feld auf <ph name="BLOCKED" /> gesetzt ist, funktioniert die Web-App während OS Login nicht. Nutzer können dies später nicht aktivieren. Ist es auf <ph name="RUN_WINDOWED" /> gesetzt, funktioniert die Web-App während OS Login. Nutzer können dies später nicht deaktivieren. Wenn das Feld auf <ph name="ALLOWED" /> gesetzt ist, können Nutzer die Web-App so konfigurieren, dass sie während OS Login funktioniert. Die Standardkonfiguration lässt nur die Werte <ph name="ALLOWED" /> und <ph name="BLOCKED" /> zu.
       </translation>
+<translation id="5945312246863177268">Verhindert, dass Nutzer auf eine Phone Hub-Benachrichtigung klicken, um die App „Eche“ zu starten.</translation>
 <translation id="5946082169633555022">Beta-Kanal</translation>
 <translation id="5946329690214660966">Benutzerdefinierten Zeitplan zum Prüfen auf Updates festlegen</translation>
 <translation id="5950069117106131681">Wenn die Richtlinie aktiviert ist, werden Kopf- und Fußzeilen in der Druckvorschau angezeigt. Ist die Richtlinie deaktiviert, werden sie in der Druckvorschau ausgeblendet.
@@ -4741,6 +4744,11 @@
 <translation id="66265932317331474">CPU-Informationen ausgeben</translation>
 <translation id="6628120204569232711">Speicherstatus melden</translation>
 <translation id="663685822663765995">Farbdruck einschränken</translation>
+<translation id="6640355849038068978">Wenn diese Einstellung aktiviert ist, können Nutzer die App „Eche“ starten, z. B. mit einem Klick auf eine Phone Hub-Benachrichtigung.
+
+      Ist diese Einstellung deaktiviert, können Nutzer die App „Eche“ nicht starten.
+
+      Wenn diese Richtlinie nicht konfiguriert ist, ist die Einstellung für vom Unternehmen verwaltete Nutzer und für nicht verwaltete Nutzer standardmäßig aktiviert.</translation>
 <translation id="6641981670621198190">Unterstützung für 3D-Grafik-APIs deaktivieren</translation>
 <translation id="6642682198621199507">Wenn diese Richtlinie konfiguriert ist, können Sie eine Liste mit Websites erstellen, die automatisch die Berechtigung für den Zugriff auf alle verfügbaren seriellen Ports erhalten.
 
diff --git a/components/policy/resources/policy_templates_es.xtb b/components/policy/resources/policy_templates_es.xtb
index e00aa49..6a11e966 100644
--- a/components/policy/resources/policy_templates_es.xtb
+++ b/components/policy/resources/policy_templates_es.xtb
@@ -2605,6 +2605,7 @@
 <translation id="3964298692570794635">Permite el contenido no seguro en estos sitios web</translation>
 <translation id="3965339130942650562">Tiempo de espera para cerrar sesión cuando el usuario se encuentre inactivo</translation>
 <translation id="396536755218079668">Usuarios supervisados</translation>
+<translation id="3968218878014278212">Permitir que se habilite Eche.</translation>
 <translation id="3971673686578912106">Si se habilita esta política, se activará <ph name="PLUGIN_VM_NAME" /> en el dispositivo siempre y cuando los demás ajustes también lo permitan. A <ph name="PLUGIN_VM_ALLOWED_POLICY_NAME" /> y <ph name="USER_PLUGIN_VM_ALLOWED_POLICY_NAME" /> se les debe haber asignado el valor "True", y <ph name="PLUGIN_VM_LICENSE_KEY_POLICY_NAME" /> o <ph name="PLUGIN_VM_USER_ID_POLICY_NAME" /> deben haberse configurado para que se puede ejecutar <ph name="PLUGIN_VM_NAME" />.
 
       Si se inhabilita esta política o no se le asigna ningún valor, no se activará <ph name="PLUGIN_VM_NAME" /> en el dispositivo.</translation>
@@ -3441,6 +3442,7 @@
       Si se le asigna el valor "Falso" o no se le asigna ninguno, <ph name="PRODUCT_NAME" /> usará la configuración que se esté aplicando en ese momento para comprobar la revocación online.</translation>
 <translation id="5078623750797048009">Habilitar anotaciones en PDF</translation>
 <translation id="5081204761483900654">Sesiones de invitado administradas y restringidas</translation>
+<translation id="5082296146261894974">Permitir que los usuarios hagan clic en una notificación de la función Mi teléfono para abrir la aplicación Eche.</translation>
 <translation id="5082572440690475059">Permitir el acceso de lectura a través de la API File System en estos sitios web</translation>
 <translation id="5085647276663819155">Inhabilitar vista previa de impresión</translation>
 <translation id="5090791951240382356">Permite combinar políticas de diccionario de fuentes distintas</translation>
@@ -4196,6 +4198,7 @@
 
       El campo <ph name="RUN_ON_OS_LOGIN_FIELD" /> especifica si una aplicación web se podrá ejecutar durante el inicio de sesión en el sistema operativo. Si a este campo se le asigna el valor <ph name="BLOCKED" />, la aplicación web no se ejecutará durante el inicio de sesión en el sistema operativo y el usuario no podrá habilitar esta opción después. Si a este campo se le asigna el valor <ph name="RUN_WINDOWED" />, la aplicación web se ejecutará durante el inicio de sesión en el sistema operativo y el usuario no podrá inhabilitar esta opción después. Si a este campo se le asigna el valor <ph name="ALLOWED" />, el usuario podrá configurar la aplicación web para que se ejecute durante el inicio de sesión en el sistema operativo. La configuración predeterminada solo permite los valores <ph name="ALLOWED" /> y <ph name="BLOCKED" />.
       </translation>
+<translation id="5945312246863177268">No permitir que los usuarios hagan clic en una notificación de la función Mi teléfono para abrir la aplicación Eche.</translation>
 <translation id="5946082169633555022">Canal beta</translation>
 <translation id="5946329690214660966">Define la programación personalizada para buscar actualizaciones</translation>
 <translation id="5950069117106131681">Si se habilita la política, activa los encabezados y pies de página en la vista previa de impresión. Si se inhabilita la política, los desactiva en la vista previa de impresión.
@@ -4777,6 +4780,11 @@
 <translation id="66265932317331474">Proporcionar información sobre la CPU</translation>
 <translation id="6628120204569232711">Informar sobre el estado del almacenamiento</translation>
 <translation id="663685822663765995">Restringir el modo de impresión en color</translation>
+<translation id="6640355849038068978">Si se habilita esta opción, los usuarios podrán abrir la aplicación Eche (por ejemplo, haciendo clic en una notificación de la función Mi teléfono).
+
+      Si se inhabilita esta opción, los usuarios no podrán abrir la aplicación Eche.
+
+      Si no se establece esta política, el valor predeterminado para los usuarios gestionados por una empresa y para los no gestionados es permitir abrir la aplicación Eche.</translation>
 <translation id="6641981670621198190">Inhabilitar compatibilidad con API de gráficos 3D</translation>
 <translation id="6642682198621199507">Establecer esta política permite definir una lista de sitios a los que se les concederá permiso automáticamente para acceder a todos los puertos serie disponibles.
 
diff --git a/components/policy/resources/policy_templates_it.xtb b/components/policy/resources/policy_templates_it.xtb
index 750b99f..fafe3c8f 100644
--- a/components/policy/resources/policy_templates_it.xtb
+++ b/components/policy/resources/policy_templates_it.xtb
@@ -2583,6 +2583,7 @@
 <translation id="3964298692570794635">Consenti contenuti non sicuri su questi siti</translation>
 <translation id="3965339130942650562">Timeout fino a esecuzione uscita utente non attivo</translation>
 <translation id="396536755218079668">Utenti supervisionati</translation>
+<translation id="3968218878014278212">Consenti l'attivazione di Eche.</translation>
 <translation id="3971673686578912106">Se il criterio viene impostato su Attivato, il plug-in <ph name="PLUGIN_VM_NAME" /> viene abilitato per il dispositivo, a condizione che anche le altre impostazioni lo permettano. <ph name="PLUGIN_VM_ALLOWED_POLICY_NAME" /> e <ph name="USER_PLUGIN_VM_ALLOWED_POLICY_NAME" /> devono essere impostati su True e <ph name="PLUGIN_VM_LICENSE_KEY_POLICY_NAME" /> o <ph name="PLUGIN_VM_USER_ID_POLICY_NAME" /> devono essere configurati per consentire l'esecuzione di <ph name="PLUGIN_VM_NAME" />.
 
       Se il criterio viene impostato su Disattivato o se non viene configurato, il plug-in <ph name="PLUGIN_VM_NAME" /> non viene attivato per il dispositivo.</translation>
@@ -3422,6 +3423,7 @@
       Se il criterio è impostato su False o se non viene configurato, <ph name="PRODUCT_NAME" /> utilizza le impostazioni di controllo delle revoche online esistenti.</translation>
 <translation id="5078623750797048009">Attiva annotazioni PDF</translation>
 <translation id="5081204761483900654">Sessioni Ospite gestite limitate</translation>
+<translation id="5082296146261894974">Consente agli utenti di fare clic sulla notifica di Phone Hub per avviare l'applicazione Eche.</translation>
 <translation id="5082572440690475059">Consenti l'accesso di lettura tramite l'API file system su questi siti</translation>
 <translation id="5085647276663819155">Disattiva anteprima di stampa</translation>
 <translation id="5090791951240382356">Consenti l'unione dei criteri del dizionario provenienti da origini diverse</translation>
@@ -4167,6 +4169,7 @@
 
       Il campo <ph name="RUN_ON_OS_LOGIN_FIELD" /> consente di specificare se è possibile o meno eseguire un'app web durante l'accesso al sistema operativo. Se questo campo viene impostato su <ph name="BLOCKED" />, l'app web non verrà eseguita durante l'accesso al sistema operativo e l'utente non potrà attivare questa funzionalità in un secondo momento. Se questo campo viene impostato su <ph name="RUN_WINDOWED" />, l'app web verrà eseguita durante l'accesso al sistema operativo e l'utente non potrà disattivare questa funzionalità in un secondo momento. Se questo campo viene impostato su <ph name="ALLOWED" />, l'utente potrà configurare l'esecuzione dell'app web al momento dell'accesso al sistema operativo. Per la configurazione predefinita sono consentiti soltanto i valori <ph name="ALLOWED" /> e <ph name="BLOCKED" />.
       </translation>
+<translation id="5945312246863177268">Non consente agli utenti di fare clic sulla notifica di Phone Hub per avviare l'applicazione Eche.</translation>
 <translation id="5946082169633555022">Canale Beta</translation>
 <translation id="5946329690214660966">Imposta una pianificazione personalizzata per verificare la presenza di aggiornamenti</translation>
 <translation id="5950069117106131681">Se il criterio viene impostato su Attivato, vengono attivati intestazioni e piè di pagina nell'anteprima di stampa. Se il criterio viene impostato su Disattivato, questi elementi vengono disattivati nell'anteprima di stampa.
@@ -4747,6 +4750,11 @@
 <translation id="66265932317331474">Segnala informazioni sulla CPU</translation>
 <translation id="6628120204569232711">Segnala lo stato di archiviazione</translation>
 <translation id="663685822663765995">Limita la modalità di stampa a colori</translation>
+<translation id="6640355849038068978">Se questa impostazione viene attivata, gli utenti potranno avviare l'applicazione Eche, ad esempio facendo clic su una notifica di Phone Hub.
+
+      Se questa impostazione viene disattivata, gli utenti non potranno avviare l'applicazione Eche.
+
+      Se questo criterio non viene configurato, per impostazione predefinita la funzionalità è consentita sia per gli utenti gestiti a livello aziendale sia per quelli non gestiti.</translation>
 <translation id="6641981670621198190">Disattiva supporto per le API grafiche 3D</translation>
 <translation id="6642682198621199507">La configurazione del criterio consente di elencare i siti a cui viene concessa automaticamente l'autorizzazione ad accedere a tutte le porte seriali disponibili.
 
diff --git a/components/policy/resources/policy_templates_uk.xtb b/components/policy/resources/policy_templates_uk.xtb
index 4ec847a9..11338ec 100644
--- a/components/policy/resources/policy_templates_uk.xtb
+++ b/components/policy/resources/policy_templates_uk.xtb
@@ -2603,6 +2603,7 @@
 <translation id="3964298692570794635">Дозволити незахищений контент на цих сайтах</translation>
 <translation id="3965339130942650562">Час очікування до виходу неактивного користувача</translation>
 <translation id="396536755218079668">Контрольовані користувачі</translation>
+<translation id="3968218878014278212">Дозволити запускати Eche.</translation>
 <translation id="3971673686578912106">Якщо це правило активовано, <ph name="PLUGIN_VM_NAME" /> буде ввімкнено на пристрої, доки це дозволяється іншими параметрами. Щоб дозволити запуск <ph name="PLUGIN_VM_NAME" />, для <ph name="PLUGIN_VM_ALLOWED_POLICY_NAME" /> і <ph name="USER_PLUGIN_VM_ALLOWED_POLICY_NAME" /> потрібно вказати значення True, а також налаштувати параметр <ph name="PLUGIN_VM_LICENSE_KEY_POLICY_NAME" /> або <ph name="PLUGIN_VM_USER_ID_POLICY_NAME" />.
 
       Якщо це правило деактивовано або не налаштовано, <ph name="PLUGIN_VM_NAME" /> буде вимкнено на пристрої.</translation>
@@ -3439,6 +3440,7 @@
       Якщо для цього правила вибрано значення False або його не налаштовано, <ph name="PRODUCT_NAME" /> використовуватиме наявні онлайн-налаштування перевірки відкликання.</translation>
 <translation id="5078623750797048009">Увімкнути примітки у файлах PDF</translation>
 <translation id="5081204761483900654">Керовані сеанси в режимі "Гість" з обмеженнями</translation>
+<translation id="5082296146261894974">Дозволити користувачам натискати сповіщення, згенероване функцією "Керування телефоном", щоб запускати додаток Eche.</translation>
 <translation id="5082572440690475059">Дозволити перегляд через File System API на цих сайтах</translation>
 <translation id="5085647276663819155">Вимкнути попередній перегляд друку</translation>
 <translation id="5090791951240382356">Дає змогу об'єднувати правила словників із різних джерел</translation>
@@ -4192,6 +4194,7 @@
 
       Поле <ph name="RUN_ON_OS_LOGIN_FIELD" /> визначає, чи можна запускати веб-додаток під час входу в ОС. Якщо вибрати для цього поля значення <ph name="BLOCKED" />, веб-додаток не запускатиметься під час входу в ОС і користувач не зможе пізніше ввімкнути такий запуск. Якщо вибрати для цього поля значення <ph name="RUN_WINDOWED" />, веб-додаток запускатиметься під час входу в ОС і користувач не зможе пізніше вимкнути такий запуск. Якщо вибрати для цього поля значення <ph name="ALLOWED" />, користувач зможе самостійно ввімкнути запуск веб-додатка під час входу в ОС. Для налаштування за умовчанням допускаються лише значення <ph name="ALLOWED" /> і <ph name="BLOCKED" />.
       </translation>
+<translation id="5945312246863177268">Заборонити користувачам натискати сповіщення, згенероване функцією "Керування телефоном", щоб запускати додаток Eche.</translation>
 <translation id="5946082169633555022">Бета-версія</translation>
 <translation id="5946329690214660966">Установити власний розклад перевірки оновлень</translation>
 <translation id="5950069117106131681">Якщо ввімкнути це правило, у вікні попереднього перегляду версії для друку відображаються верхні та нижні колонтитули. Якщо вимкнути це правило, колонтитули не відображаються.
@@ -4771,6 +4774,11 @@
 <translation id="66265932317331474">Повідомляти інформацію про ЦП</translation>
 <translation id="6628120204569232711">Повідомляти про стан пам’яті</translation>
 <translation id="663685822663765995">Обмежити кольоровий друк</translation>
+<translation id="6640355849038068978">Якщо ввімкнути це налаштування, користувачі зможуть запускати додаток Eche, натиснувши сповіщення, згенероване функцією "Керування телефоном".
+
+      Якщо вимкнути це налаштування, користувачі не зможуть запускати додаток Eche.
+
+      Якщо це правило не налаштувати, за умовчанням цю функцію зможуть вмикати користувачі, якими керує адміністратор, і ті, якими він не керує.</translation>
 <translation id="6641981670621198190">Вимкнути підтримку API для 3D-графіки</translation>
 <translation id="6642682198621199507">За допомогою цього правила можна задати список сайтів, яким автоматично дозволятиметься доступ до всіх доступних послідовних портів.
 
diff --git a/components/prefs/json_pref_store_unittest.cc b/components/prefs/json_pref_store_unittest.cc
index acce087..3082f81 100644
--- a/components/prefs/json_pref_store_unittest.cc
+++ b/components/prefs/json_pref_store_unittest.cc
@@ -140,7 +140,7 @@
     CommitPendingWriteMode commit_mode) {
   switch (commit_mode) {
     case CommitPendingWriteMode::WITHOUT_CALLBACK:
-      FALLTHROUGH;
+      [[fallthrough]];
     case CommitPendingWriteMode::WITH_CALLBACK:
       return base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED;
     case CommitPendingWriteMode::WITH_SYNCHRONOUS_CALLBACK:
diff --git a/components/safe_browsing/core/common/safe_browsing_prefs.cc b/components/safe_browsing/core/common/safe_browsing_prefs.cc
index 05e74a72..971d4424 100644
--- a/components/safe_browsing/core/common/safe_browsing_prefs.cc
+++ b/components/safe_browsing/core/common/safe_browsing_prefs.cc
@@ -288,8 +288,8 @@
 
 base::ListValue GetSafeBrowsingPoliciesList(PrefService* prefs) {
   base::ListValue preferences_list;
-  const base::ListValue* allowlist_domains = &base::Value::AsListValue(
-      *prefs->GetList(prefs::kSafeBrowsingAllowlistDomains));
+  const base::Value* allowlist_domains =
+      prefs->GetList(prefs::kSafeBrowsingAllowlistDomains);
   std::vector<std::string> domain_list;
   CanonicalizeDomainList(*allowlist_domains, &domain_list);
   std::string domains;
@@ -321,13 +321,13 @@
 void GetSafeBrowsingAllowlistDomainsPref(
     const PrefService& prefs,
     std::vector<std::string>* out_canonicalized_domain_list) {
-  const base::ListValue* pref_value = &base::Value::AsListValue(
-      *prefs.GetList(prefs::kSafeBrowsingAllowlistDomains));
+  const base::Value* pref_value =
+      prefs.GetList(prefs::kSafeBrowsingAllowlistDomains);
   CanonicalizeDomainList(*pref_value, out_canonicalized_domain_list);
 }
 
 void CanonicalizeDomainList(
-    const base::ListValue& raw_domain_list,
+    const base::Value& raw_domain_list,
     std::vector<std::string>* out_canonicalized_domain_list) {
   out_canonicalized_domain_list->clear();
   for (auto it = raw_domain_list.GetList().begin();
diff --git a/components/safe_browsing/core/common/safe_browsing_prefs.h b/components/safe_browsing/core/common/safe_browsing_prefs.h
index c72b92a..05136ba 100644
--- a/components/safe_browsing/core/common/safe_browsing_prefs.h
+++ b/components/safe_browsing/core/common/safe_browsing_prefs.h
@@ -291,7 +291,7 @@
 
 // Helper function to validate and canonicalize a list of domain strings.
 void CanonicalizeDomainList(
-    const base::ListValue& raw_domain_list,
+    const base::Value& raw_domain_list,
     std::vector<std::string>* out_canonicalized_domain_list);
 
 // Helper function to determine if |url| matches Safe Browsing allowlist domains
diff --git a/components/security_interstitials/core/safe_browsing_loud_error_ui.cc b/components/security_interstitials/core/safe_browsing_loud_error_ui.cc
index 2e462a38..eae06a31 100644
--- a/components/security_interstitials/core/safe_browsing_loud_error_ui.cc
+++ b/components/security_interstitials/core/safe_browsing_loud_error_ui.cc
@@ -140,7 +140,7 @@
         break;
       }
       // If the user can't proceed, fall through to CMD_DONT_PROCEED.
-      FALLTHROUGH;
+      [[fallthrough]];
     }
     case CMD_DONT_PROCEED: {
       // User pressed on the button to return to safety.
diff --git a/components/segmentation_platform/internal/service_proxy_impl.cc b/components/segmentation_platform/internal/service_proxy_impl.cc
index 5e67333..81757ae 100644
--- a/components/segmentation_platform/internal/service_proxy_impl.cc
+++ b/components/segmentation_platform/internal/service_proxy_impl.cc
@@ -7,7 +7,7 @@
 #include <inttypes.h>
 
 #include "base/strings/stringprintf.h"
-#include "components/optimization_guide/core/optimization_guide_util.h"
+#include "components/optimization_guide/core/model_util.h"
 #include "components/segmentation_platform/internal/database/metadata_utils.h"
 #include "components/segmentation_platform/internal/segmentation_platform_service_impl.h"
 
diff --git a/components/segmentation_platform/internal/service_proxy_impl_unittest.cc b/components/segmentation_platform/internal/service_proxy_impl_unittest.cc
index 8c91940..08763c6 100644
--- a/components/segmentation_platform/internal/service_proxy_impl_unittest.cc
+++ b/components/segmentation_platform/internal/service_proxy_impl_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "components/leveldb_proto/public/proto_database.h"
 #include "components/leveldb_proto/testing/fake_db.h"
-#include "components/optimization_guide/core/optimization_guide_util.h"
+#include "components/optimization_guide/core/model_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace segmentation_platform {
diff --git a/components/sync/driver/model_type_controller.cc b/components/sync/driver/model_type_controller.cc
index e03c0246..c53e1a1 100644
--- a/components/sync/driver/model_type_controller.cc
+++ b/components/sync/driver/model_type_controller.cc
@@ -272,7 +272,7 @@
       DCHECK(!model_stop_callbacks_.empty());
       DCHECK(!model_load_callback_);
       state_ = NOT_RUNNING;
-      FALLTHROUGH;
+      [[fallthrough]];
     case FAILED:
       DVLOG(1) << "Successful sync start completion received late for "
                << ModelTypeToString(type())
diff --git a/components/sync/driver/sync_session_durations_metrics_recorder.cc b/components/sync/driver/sync_session_durations_metrics_recorder.cc
index c4b9a38..078dcd5e 100644
--- a/components/sync/driver/sync_session_durations_metrics_recorder.cc
+++ b/components/sync/driver/sync_session_durations_metrics_recorder.cc
@@ -224,7 +224,7 @@
     case FeatureState::UNKNOWN:
       // Since the feature wasn't working for the user if we didn't know its
       // state, log the status as off.
-      FALLTHROUGH;
+      [[fallthrough]];
     case FeatureState::OFF:
       LogDuration("Session.TotalDuration.WithoutAccount", session_length);
       break;
@@ -246,7 +246,7 @@
       break;
     case GetFeatureStates(FeatureState::ON, FeatureState::UNKNOWN):
       // Sync engine not initialized yet, default to it being off.
-      FALLTHROUGH;
+      [[fallthrough]];
     case GetFeatureStates(FeatureState::ON, FeatureState::OFF):
       LogDuration("Session.TotalDuration.NotOptedInToSyncWithAccount",
                   session_length);
@@ -257,7 +257,7 @@
       break;
     case GetFeatureStates(FeatureState::OFF, FeatureState::UNKNOWN):
       // Sync engine not initialized yet, default to it being off.
-      FALLTHROUGH;
+      [[fallthrough]];
     case GetFeatureStates(FeatureState::OFF, FeatureState::OFF):
       LogDuration("Session.TotalDuration.NotOptedInToSyncWithoutAccount",
                   session_length);
diff --git a/components/sync/model/syncable_service_based_bridge.cc b/components/sync/model/syncable_service_based_bridge.cc
index e10cfcc..89e9b8c 100644
--- a/components/sync/model/syncable_service_based_bridge.cc
+++ b/components/sync/model/syncable_service_based_bridge.cc
@@ -550,7 +550,7 @@
             change->data(),
             /*storage_key=*/change->data().client_tag_hash.value(),
             batch->GetMetadataChangeList());
-        FALLTHROUGH;
+        [[fallthrough]];
 
       case EntityChange::ACTION_UPDATE: {
         const std::string& storage_key = change->data().client_tag_hash.value();
diff --git a/components/sync/nigori/nigori_sync_bridge_impl.cc b/components/sync/nigori/nigori_sync_bridge_impl.cc
index 102901a..ea07db77 100644
--- a/components/sync/nigori/nigori_sync_bridge_impl.cc
+++ b/components/sync/nigori/nigori_sync_bridge_impl.cc
@@ -154,7 +154,7 @@
       if (!SpecificsHasValidKeyDerivationParams(specifics)) {
         return false;
       }
-      FALLTHROUGH;
+      [[fallthrough]];
     case NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE:
       if (!specifics.encrypt_everything()) {
         DLOG(ERROR) << "Nigori with explicit passphrase type should have "
diff --git a/components/url_matcher/BUILD.gn b/components/url_matcher/BUILD.gn
index f7c8a10..f1d6277 100644
--- a/components/url_matcher/BUILD.gn
+++ b/components/url_matcher/BUILD.gn
@@ -17,8 +17,8 @@
     "url_matcher_export.h",
     "url_matcher_factory.cc",
     "url_matcher_factory.h",
-    "url_matcher_helpers.cc",
-    "url_matcher_helpers.h",
+    "url_util.cc",
+    "url_util.h",
   ]
 
   defines = [ "URL_MATCHER_IMPLEMENTATION" ]
@@ -26,6 +26,9 @@
   public_deps = [
     "//base",
     "//base/third_party/dynamic_annotations",
+    "//components/google/core/common",
+    "//components/url_formatter",
+    "//net",
     "//third_party/re2",
     "//url",
   ]
@@ -39,6 +42,7 @@
     "substring_set_matcher_unittest.cc",
     "url_matcher_factory_unittest.cc",
     "url_matcher_unittest.cc",
+    "url_util_unittest.cc",
   ]
   deps = [
     ":url_matcher",
diff --git a/components/url_matcher/DEPS b/components/url_matcher/DEPS
index 0de07bb..802809a 100644
--- a/components/url_matcher/DEPS
+++ b/components/url_matcher/DEPS
@@ -1,3 +1,6 @@
 include_rules = [
+  "+components/google/core/common",
+  "+components/url_formatter",
+  "+net/base",
   "+third_party/re2",
 ]
diff --git a/components/url_matcher/url_matcher_factory.cc b/components/url_matcher/url_matcher_factory.cc
index d446f3430..cf00364 100644
--- a/components/url_matcher/url_matcher_factory.cc
+++ b/components/url_matcher/url_matcher_factory.cc
@@ -14,12 +14,11 @@
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
 #include "components/url_matcher/url_matcher_constants.h"
-#include "components/url_matcher/url_matcher_helpers.h"
+#include "components/url_matcher/url_util.h"
 #include "third_party/re2/src/re2/re2.h"
 
 namespace url_matcher {
 
-namespace helpers = url_matcher_helpers;
 namespace keys = url_matcher_constants;
 
 namespace {
@@ -225,7 +224,7 @@
 URLMatcherFactory::CreateURLMatcherScheme(const base::Value* value,
                                           std::string* error) {
   std::vector<std::string> schemas;
-  if (!helpers::GetAsStringVector(value, &schemas)) {
+  if (!util::GetAsStringVector(value, &schemas)) {
     *error = base::StringPrintf(kVectorOfStringsExpected, keys::kSchemesKey);
     return nullptr;
   }
diff --git a/components/url_matcher/url_matcher_helpers.cc b/components/url_matcher/url_matcher_helpers.cc
deleted file mode 100644
index d21c8796..0000000
--- a/components/url_matcher/url_matcher_helpers.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 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 "components/url_matcher/url_matcher_helpers.h"
-
-#include <stddef.h>
-
-#include "base/values.h"
-
-namespace url_matcher {
-namespace url_matcher_helpers {
-
-// Converts a ValueList |value| of strings into a vector. Returns true if
-// successful.
-bool GetAsStringVector(const base::Value* value,
-                       std::vector<std::string>* out) {
-  if (!value->is_list())
-    return false;
-
-  for (const base::Value& item : value->GetList()) {
-    if (!item.is_string())
-      return false;
-
-    out->push_back(item.GetString());
-  }
-  return true;
-}
-
-}  // namespace url_matcher_helpers
-}  // namespace url_matcher
diff --git a/components/url_matcher/url_matcher_helpers.h b/components/url_matcher/url_matcher_helpers.h
deleted file mode 100644
index 15aa0c5..0000000
--- a/components/url_matcher/url_matcher_helpers.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2013 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.
-
-// Helper functions used for URLMatcher and Declarative APIs.
-
-#ifndef COMPONENTS_URL_MATCHER_URL_MATCHER_HELPERS_H_
-#define COMPONENTS_URL_MATCHER_URL_MATCHER_HELPERS_H_
-
-#include <string>
-#include <vector>
-
-namespace base {
-class Value;
-}
-
-namespace url_matcher {
-namespace url_matcher_helpers {
-
-// Converts a ValueList |value| of strings into a vector. Returns true if
-// successful.
-bool GetAsStringVector(const base::Value* value, std::vector<std::string>* out);
-
-}  // namespace url_matcher_helpers
-}  // namespace url_matcher
-
-#endif  // COMPONENTS_URL_MATCHER_URL_MATCHER_HELPERS_H_
diff --git a/components/policy/core/browser/url_util.cc b/components/url_matcher/url_util.cc
similarity index 82%
rename from components/policy/core/browser/url_util.cc
rename to components/url_matcher/url_util.cc
index 7f0b856b..8347a09 100644
--- a/components/policy/core/browser/url_util.cc
+++ b/components/url_matcher/url_util.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/policy/core/browser/url_util.h"
+#include "components/url_matcher/url_util.h"
 
 #include <memory>
 #include <string>
@@ -29,8 +29,8 @@
 using url_matcher::URLMatcherSchemeFilter;
 using url_matcher::URLQueryElementMatcherCondition;
 
-namespace policy {
-namespace url_util {
+namespace url_matcher {
+namespace util {
 
 namespace {
 
@@ -52,8 +52,8 @@
 const char kGoogleTranslateSubdomain[] = "translate.";
 const char kAlternateGoogleTranslateHost[] = "translate.googleusercontent.com";
 
-// Maximum filters per policy. Filters over this index are ignored.
-const size_t kMaxFiltersPerPolicy = 1000;
+// Maximum filters allowed. Filters over this index are ignored.
+const size_t kMaxFiltersAllowed = 1000;
 
 // Returns a full URL using either "http" or "https" as the scheme.
 GURL BuildURL(bool is_https, const std::string& host_and_path) {
@@ -213,6 +213,22 @@
 
 }  // namespace
 
+// Converts a ValueList |value| of strings into a vector. Returns true if
+// successful.
+bool GetAsStringVector(const base::Value* value,
+                       std::vector<std::string>* out) {
+  if (!value->is_list())
+    return false;
+
+  for (const base::Value& item : value->GetList()) {
+    if (!item.is_string())
+      return false;
+
+    out->push_back(item.GetString());
+  }
+  return true;
+}
+
 GURL Normalize(const GURL& url) {
   GURL normalized_url = url;
   GURL::Replacements replacements;
@@ -228,18 +244,17 @@
   return EmbeddedURLExtractor::GetInstance()->GetEmbeddedURL(url);
 }
 
-size_t GetMaxFiltersPerPolicy() {
-  return kMaxFiltersPerPolicy;
+size_t GetMaxFiltersAllowed() {
+  return kMaxFiltersAllowed;
 }
 
-FilterComponents::FilterComponents()
-    : port(0), match_subdomains(true), allow(true) {}
+FilterComponents::FilterComponents() = default;
 FilterComponents::~FilterComponents() = default;
 FilterComponents::FilterComponents(FilterComponents&&) = default;
 
-bool FilterComponents::IsBlocklistWildcard() const {
-  return !allow && host.empty() && scheme.empty() && path.empty() &&
-         query.empty() && port == 0 && number_of_key_value_pairs == 0 &&
+bool FilterComponents::IsWildcard() const {
+  return host.empty() && scheme.empty() && path.empty() && query.empty() &&
+         port == 0 && number_of_url_matching_conditions == 0 &&
          match_subdomains;
 }
 
@@ -393,15 +408,15 @@
   return true;
 }
 
-POLICY_EXPORT void AddFilters(URLMatcher* matcher,
-                              bool allow,
-                              URLMatcherConditionSet::ID* id,
-                              const base::ListValue* patterns,
-                              std::map<url_matcher::URLMatcherConditionSet::ID,
-                                       url_util::FilterComponents>* filters) {
+void AddFilters(URLMatcher* matcher,
+                bool allow,
+                URLMatcherConditionSet::ID* id,
+                const base::ListValue* patterns,
+                std::map<url_matcher::URLMatcherConditionSet::ID,
+                         url_matcher::util::FilterComponents>* filters) {
   URLMatcherConditionSet::Vector all_conditions;
   base::Value::ConstListView patterns_list = patterns->GetList();
-  size_t size = std::min(kMaxFiltersPerPolicy, patterns_list.size());
+  size_t size = std::min(kMaxFiltersAllowed, patterns_list.size());
   scoped_refptr<URLMatcherConditionSet> condition_set;
   for (size_t i = 0; i < size; ++i) {
     std::string pattern;
@@ -423,7 +438,7 @@
                            components.match_subdomains, components.port,
                            components.path, components.query, allow);
     if (filters) {
-      components.number_of_key_value_pairs =
+      components.number_of_url_matching_conditions =
           condition_set->query_conditions().size();
       (*filters)[*id] = std::move(components);
     }
@@ -432,11 +447,49 @@
   matcher->AddConditionSets(all_conditions);
 }
 
-POLICY_EXPORT void AddAllowFilters(url_matcher::URLMatcher* matcher,
-                                   const base::ListValue* patterns) {
+void AddFilters(URLMatcher* matcher,
+                bool allow,
+                URLMatcherConditionSet::ID* id,
+                const std::vector<std::string>& patterns,
+                std::map<url_matcher::URLMatcherConditionSet::ID,
+                         url_matcher::util::FilterComponents>* filters) {
+  URLMatcherConditionSet::Vector all_conditions;
+  size_t size = std::min(kMaxFiltersAllowed, patterns.size());
+  scoped_refptr<URLMatcherConditionSet> condition_set;
+  for (size_t i = 0; i < size; ++i) {
+    FilterComponents components;
+    components.allow = allow;
+    if (!FilterToComponents(patterns[i], &components.scheme, &components.host,
+                            &components.match_subdomains, &components.port,
+                            &components.path, &components.query)) {
+      LOG(ERROR) << "Invalid pattern " << patterns[i];
+      continue;
+    }
+    condition_set =
+        CreateConditionSet(matcher, ++(*id), components.scheme, components.host,
+                           components.match_subdomains, components.port,
+                           components.path, components.query, allow);
+    if (filters) {
+      components.number_of_url_matching_conditions =
+          condition_set->query_conditions().size();
+      (*filters)[*id] = std::move(components);
+    }
+    all_conditions.push_back(std::move(condition_set));
+  }
+  matcher->AddConditionSets(all_conditions);
+}
+
+void AddAllowFilters(url_matcher::URLMatcher* matcher,
+                     const base::ListValue* patterns) {
   url_matcher::URLMatcherConditionSet::ID id(0);
   AddFilters(matcher, true, &id, patterns);
 }
 
-}  // namespace url_util
-}  // namespace policy
+void AddAllowFilters(url_matcher::URLMatcher* matcher,
+                     const std::vector<std::string>& patterns) {
+  url_matcher::URLMatcherConditionSet::ID id(0);
+  AddFilters(matcher, true, &id, patterns);
+}
+
+}  // namespace util
+}  // namespace url_matcher
diff --git a/components/url_matcher/url_util.h b/components/url_matcher/url_util.h
new file mode 100644
index 0000000..868f2ea
--- /dev/null
+++ b/components/url_matcher/url_util.h
@@ -0,0 +1,133 @@
+// Copyright 2018 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 COMPONENTS_URL_MATCHER_URL_UTIL_H_
+#define COMPONENTS_URL_MATCHER_URL_UTIL_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "base/values.h"
+#include "components/url_matcher/url_matcher.h"
+#include "components/url_matcher/url_matcher_export.h"
+
+class GURL;
+
+namespace url_matcher {
+namespace util {
+
+// Converts a ValueList `value` of strings into a vector. Returns true if
+// successful.
+bool GetAsStringVector(const base::Value* value, std::vector<std::string>* out);
+
+// Normalizes a URL for matching purposes.
+URL_MATCHER_EXPORT GURL Normalize(const GURL& url);
+
+// Helper function to extract the underlying URL wrapped by services such as
+// Google AMP or Google Translate. Returns an empty GURL if `url` doesn't match
+// a known format.
+URL_MATCHER_EXPORT GURL GetEmbeddedURL(const GURL& url);
+
+// Utility struct used to represent a url filter scheme into its components.
+struct URL_MATCHER_EXPORT FilterComponents {
+  FilterComponents();
+  FilterComponents(const FilterComponents&) = delete;
+  FilterComponents(FilterComponents&&);
+  FilterComponents& operator=(const FilterComponents&) = delete;
+  FilterComponents& operator=(FilterComponents&&) = default;
+
+  ~FilterComponents();
+
+  // Returns true if `this` represents the "*" filter.
+  bool IsWildcard() const;
+  std::string scheme;
+  std::string host;
+  uint16_t port = 0;
+  std::string path;
+  std::string query;
+  // Number of conditions that a url needs to match it to be considered a match
+  // for this filter.
+  int number_of_url_matching_conditions = 0;
+  bool match_subdomains = true;
+  bool allow = true;
+};
+
+// Creates a condition set that can be used with the `url_matcher`. `id` needs
+// to be a unique number that will be returned by the `url_matcher` if the URL
+// matches that condition set. `allow` indicates if it is an allow-list (true)
+// or block-list (false) filter.
+URL_MATCHER_EXPORT scoped_refptr<url_matcher::URLMatcherConditionSet>
+CreateConditionSet(url_matcher::URLMatcher* url_matcher,
+                   url_matcher::URLMatcherConditionSet::ID id,
+                   const std::string& scheme,
+                   const std::string& host,
+                   bool match_subdomains,
+                   uint16_t port,
+                   const std::string& path,
+                   const std::string& query,
+                   bool allow);
+
+// Splits a URL filter into its components. A GURL isn't used because these
+// can be invalid URLs e.g. "google.com".
+// Returns false if the URL couldn't be parsed. In case false is returned,
+// the values of output parameters are undefined.
+// The `filter` should have the format described at
+// http://www.chromium.org/administrators/url-blocklist-filter-format and
+// accepts wildcards. The `host` is preprocessed so it can be passed to
+// URLMatcher for the appropriate condition. The optional username and password
+// are ignored. `match_subdomains` specifies whether the filter should include
+// subdomains of the hostname (if it is one.) `port` is 0 if none is explicitly
+// defined. `path` does not include query parameters. `query` contains the query
+// parameters ('?' not included). All arguments are mandatory.
+URL_MATCHER_EXPORT bool FilterToComponents(const std::string& filter,
+                                           std::string* scheme,
+                                           std::string* host,
+                                           bool* match_subdomains,
+                                           uint16_t* port,
+                                           std::string* path,
+                                           std::string* query);
+
+// Adds the filters in `patterns` to `url_matcher` as a ConditionSet::Vector.
+// `matcher` is the URLMatcher where filters are added.
+// `allow` specifies whether the filter accepts or blocks the macthed urls.
+// `id` is the id of given to the filter being added.
+// `patterns` is a list of url schemes following the format described
+// http://www.chromium.org/administrators/url-blocklist-filter-format and
+// accepts wildcards.
+// `filters` is an optional map of id to FilterComponent where the generated
+// FilterComponent will be added.
+URL_MATCHER_EXPORT void AddFilters(
+    url_matcher::URLMatcher* matcher,
+    bool allow,
+    url_matcher::URLMatcherConditionSet::ID* id,
+    const base::ListValue* patterns,
+    std::map<url_matcher::URLMatcherConditionSet::ID,
+             url_matcher::util::FilterComponents>* filters = nullptr);
+
+// Adds the filters in `patterns` to `url_matcher` as a ConditionSet::Vector.
+// `matcher` is the URLMatcher where filters are added.
+// `allow` specifies whether the filter accepts or blocks the macthed urls.
+// `id` is the id of given to the filter being added.
+// `patterns` is a list of url schemes following the format described
+// http://www.chromium.org/administrators/url-blocklist-filter-format and
+// accepts wildcards.
+// `filters` is an optional map of id to FilterComponent where the generated
+// FilterComponent will be added.
+URL_MATCHER_EXPORT void AddFilters(
+    url_matcher::URLMatcher* matcher,
+    bool allow,
+    url_matcher::URLMatcherConditionSet::ID* id,
+    const std::vector<std::string>& patterns,
+    std::map<url_matcher::URLMatcherConditionSet::ID,
+             url_matcher::util::FilterComponents>* filters = nullptr);
+
+URL_MATCHER_EXPORT void AddAllowFilters(url_matcher::URLMatcher* matcher,
+                                        const base::ListValue* patterns);
+
+URL_MATCHER_EXPORT void AddAllowFilters(
+    url_matcher::URLMatcher* matcher,
+    const std::vector<std::string>& patterns);
+
+}  // namespace util
+}  // namespace url_matcher
+
+#endif  // COMPONENTS_URL_MATCHER_URL_UTIL_H_
diff --git a/components/policy/core/browser/url_util_unittest.cc b/components/url_matcher/url_util_unittest.cc
similarity index 98%
rename from components/policy/core/browser/url_util_unittest.cc
rename to components/url_matcher/url_util_unittest.cc
index 34527ad..4849019 100644
--- a/components/policy/core/browser/url_util_unittest.cc
+++ b/components/url_matcher/url_util_unittest.cc
@@ -2,20 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/policy/core/browser/url_util.h"
+#include "components/url_matcher/url_util.h"
 #include <memory>
 
 #include "base/values.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
-namespace policy {
-namespace url_util {
+namespace url_matcher {
+namespace util {
 
 namespace {
 
 GURL GetEmbeddedURL(const std::string& url) {
-  return policy::url_util::GetEmbeddedURL(GURL(url));
+  return url_matcher::util::GetEmbeddedURL(GURL(url));
 }
 
 // Parameters for the FilterToComponents test.
@@ -78,7 +78,7 @@
 bool MatchFilters(const std::vector<std::string>& patterns,
                   const std::string& url) {
   // Add the pattern to the matcher.
-  url_matcher::URLMatcher matcher;
+  URLMatcher matcher;
   base::Value list(base::Value::Type::LIST);
   for (const auto& pattern : patterns)
     list.Append(pattern);
@@ -663,8 +663,8 @@
   std::string path;
   std::string query;
 
-  url_util::FilterToComponents(GetParam().filter(), &scheme, &host,
-                               &match_subdomains, &port, &path, &query);
+  FilterToComponents(GetParam().filter(), &scheme, &host, &match_subdomains,
+                     &port, &path, &query);
   EXPECT_EQ(GetParam().scheme(), scheme);
   EXPECT_EQ(GetParam().host(), host);
   EXPECT_EQ(GetParam().match_subdomains(), match_subdomains);
@@ -672,5 +672,5 @@
   EXPECT_EQ(GetParam().path(), path);
 }
 
-}  // namespace url_util
-}  // namespace policy
+}  // namespace util
+}  // namespace url_matcher
diff --git a/components/viz/common/gpu/context_lost_reason.h b/components/viz/common/gpu/context_lost_reason.h
index b285d3a4..eb13396 100644
--- a/components/viz/common/gpu/context_lost_reason.h
+++ b/components/viz/common/gpu/context_lost_reason.h
@@ -32,9 +32,10 @@
   CONTEXT_LOST_DIRECT_COMPOSITION_OVERLAY_FAILED = 15,
   CONTEXT_LOST_SWAP_FAILED = 16,
   CONTEXT_LOST_BEGIN_PAINT_FAILED = 17,
+  CONTEXT_LOST_ALLOCATE_FRAME_BUFFERS_FAILED = 18,
   // Update kMaxValue here and <enum name="ContextLostReason"> in
   // tools/metrics/histograms/enum.xml when adding new values.
-  kMaxValue = CONTEXT_LOST_BEGIN_PAINT_FAILED
+  kMaxValue = CONTEXT_LOST_ALLOCATE_FRAME_BUFFERS_FAILED
 };
 
 VIZ_COMMON_EXPORT ContextLostReason
diff --git a/components/viz/service/display_embedder/skia_output_device.cc b/components/viz/service/display_embedder/skia_output_device.cc
index 1aea6cc..8cada302 100644
--- a/components/viz/service/display_embedder/skia_output_device.cc
+++ b/components/viz/service/display_embedder/skia_output_device.cc
@@ -138,8 +138,9 @@
   NOTREACHED();
 }
 
-void SkiaOutputDevice::AllocateFrameBuffers(size_t n) {
+bool SkiaOutputDevice::AllocateFrameBuffers(size_t n) {
   NOTREACHED();
+  return false;
 }
 
 void SkiaOutputDevice::ReleaseOneFrameBuffer() {
diff --git a/components/viz/service/display_embedder/skia_output_device.h b/components/viz/service/display_embedder/skia_output_device.h
index 8970ff97..35f4554 100644
--- a/components/viz/service/display_embedder/skia_output_device.h
+++ b/components/viz/service/display_embedder/skia_output_device.h
@@ -135,7 +135,7 @@
   virtual void CommitOverlayPlanes(BufferPresentedCallback feedback,
                                    OutputSurfaceFrame frame);
 
-  virtual void AllocateFrameBuffers(size_t n);
+  virtual bool AllocateFrameBuffers(size_t n);
 
   // Release one frame buffer. Only called if `UseDynamicFrameBufferAllocation`
   // is true.
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
index 177ba37..d0df34a 100644
--- a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
+++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
@@ -726,7 +726,8 @@
 
   if (allocate_frame_buffer) {
     DCHECK(!current_image_);
-    AllocateFrameBuffers(1u);
+    if (!AllocateFrameBuffers(1u))
+      return nullptr;
   }
   if (!current_image_) {
     current_image_ = GetNextImage();
@@ -743,18 +744,20 @@
   current_image_->EndWriteSkia();
 }
 
-void SkiaOutputDeviceBufferQueue::AllocateFrameBuffers(size_t n) {
+bool SkiaOutputDeviceBufferQueue::AllocateFrameBuffers(size_t n) {
   std::vector<std::unique_ptr<OutputPresenter::Image>> new_images =
       presenter_->AllocateImages(color_space_, image_size_, n);
   if (new_images.size() != n) {
-    LOG(FATAL) << "AllocateImages failed " << new_images.size() << " " << n;
-    return;
+    LOG(ERROR) << "AllocateImages failed " << new_images.size() << " " << n;
+    CheckForLoopFailuresBufferQueue();
+    return false;
   }
   for (auto& image : new_images) {
     available_images_.push_front(image.get());
   }
   images_.insert(images_.end(), std::make_move_iterator(new_images.begin()),
                  std::make_move_iterator(new_images.end()));
+  return true;
 }
 
 void SkiaOutputDeviceBufferQueue::ReleaseOneFrameBuffer() {
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue.h b/components/viz/service/display_embedder/skia_output_device_buffer_queue.h
index 599a89a..f71805ae 100644
--- a/components/viz/service/display_embedder/skia_output_device_buffer_queue.h
+++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue.h
@@ -59,7 +59,7 @@
       bool allocate_frame_buffer,
       std::vector<GrBackendSemaphore>* end_semaphores) override;
   void EndPaint() override;
-  void AllocateFrameBuffers(size_t n) override;
+  bool AllocateFrameBuffers(size_t n) override;
   void ReleaseOneFrameBuffer() override;
 
   bool IsPrimaryPlaneOverlay() const override;
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
index eadf5c80..cbcf2527 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -490,7 +490,9 @@
 
 void SkiaOutputSurfaceImplOnGpu::AllocateFrameBuffers(size_t n) {
   MakeCurrent(/*need_framebuffer=*/false);
-  output_device_->AllocateFrameBuffers(n);
+  if (!output_device_->AllocateFrameBuffers(n)) {
+    MarkContextLost(CONTEXT_LOST_ALLOCATE_FRAME_BUFFERS_FAILED);
+  }
 }
 
 void SkiaOutputSurfaceImplOnGpu::ReleaseFrameBuffers(size_t n) {
diff --git a/components/webapps/browser/android/add_to_homescreen_mediator.cc b/components/webapps/browser/android/add_to_homescreen_mediator.cc
index 30c5b85..2c212065 100644
--- a/components/webapps/browser/android/add_to_homescreen_mediator.cc
+++ b/components/webapps/browser/android/add_to_homescreen_mediator.cc
@@ -105,7 +105,7 @@
 void AddToHomescreenMediator::AddToHomescreen(
     JNIEnv* env,
     const JavaParamRef<jstring>& j_user_title) {
-  if (!params_)
+  if (!params_ || GetWebContents() == nullptr)
     return;
 
   if (params_->app_type == AddToHomescreenParams::AppType::SHORTCUT) {
diff --git a/components/webapps/browser/android/app_banner_manager_android.cc b/components/webapps/browser/android/app_banner_manager_android.cc
index 40b3b70..edef9de 100644
--- a/components/webapps/browser/android/app_banner_manager_android.cc
+++ b/components/webapps/browser/android/app_banner_manager_android.cc
@@ -282,7 +282,7 @@
           TrackUserResponse(USER_RESPONSE_NATIVE_APP_ACCEPTED);
           break;
         case AddToHomescreenParams::AppType::WEBAPK:
-          FALLTHROUGH;
+          [[fallthrough]];
         case AddToHomescreenParams::AppType::SHORTCUT:
           TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED);
           AppBannerSettingsHelper::RecordBannerInstallEvent(
diff --git a/components/webapps/browser/banners/app_banner_manager.cc b/components/webapps/browser/banners/app_banner_manager.cc
index 96537be..2e0739a 100644
--- a/components/webapps/browser/banners/app_banner_manager.cc
+++ b/components/webapps/browser/banners/app_banner_manager.cc
@@ -686,7 +686,7 @@
     case State::SENDING_EVENT_GOT_EARLY_PROMPT:
     case State::PENDING_PROMPT:
       Terminate();
-      FALLTHROUGH;
+      [[fallthrough]];
     case State::COMPLETE:
       if (!manifest_url.is_empty()) {
         // This call resets has_sufficient_engagement_data_. In order to
diff --git a/content/browser/direct_sockets/direct_sockets_service_impl.cc b/content/browser/direct_sockets/direct_sockets_service_impl.cc
index 8bb0e10e..1e4ece30 100644
--- a/content/browser/direct_sockets/direct_sockets_service_impl.cc
+++ b/content/browser/direct_sockets/direct_sockets_service_impl.cc
@@ -393,9 +393,7 @@
     return;
   }
 
-  const net::Error result = ValidateOptions(*options);
-
-  if (result != net::OK) {
+  if (const net::Error result = ValidateOptions(*options); result != net::OK) {
     std::move(callback).Run(result, absl::nullopt, absl::nullopt,
                             mojo::ScopedDataPipeConsumerHandle(),
                             mojo::ScopedDataPipeProducerHandle());
@@ -426,9 +424,7 @@
     return;
   }
 
-  const net::Error result = ValidateOptions(*options);
-
-  if (result != net::OK) {
+  if (const net::Error result = ValidateOptions(*options); result != net::OK) {
     std::move(callback).Run(result, absl::nullopt, absl::nullopt);
     return;
   }
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
index 1ccb50d5..c3de66fa 100644
--- a/content/browser/loader/navigation_url_loader_impl.cc
+++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -995,14 +995,6 @@
     return;
   }
 
-  // While not a true redirect, a redirect loop can be simulated by repeatedly
-  // closing the socket and presenting a different ALPS setting with each new
-  // handshake.
-  if (redirect_limit_-- == 0) {
-    std::move(callback).Run(net::ERR_TOO_MANY_REDIRECTS);
-    return;
-  }
-
   net::HttpRequestHeaders modified_headers;
   client_hint_delegate->SetAdditionalClientHints(filtered_hints);
   AddNavigationRequestClientHintsHeaders(
@@ -1016,11 +1008,39 @@
 
   LogAcceptCHFrameStatus(AcceptCHFrameRestart::kNavigationRestarted);
 
+  // Only restart if new headers are actually added. Given that header values
+  // can be changed via the navigation interceptors or previous restarts, the
+  // header values are ignored and only the presence of header names are
+  // checked.
+  bool restart = false;
+  net::HttpRequestHeaders::Iterator header_iter(modified_headers);
+  while (header_iter.GetNext()) {
+    if (!resource_request_->headers.HasHeader(header_iter.name())) {
+      restart = true;
+      break;
+    }
+  }
+
+  if (!restart) {
+    std::move(callback).Run(net::OK);
+    return;
+  }
+
+  // While not a true redirect, a redirect loop can be simulated by repeatedly
+  // closing the socket and presenting a different ALPS setting with each new
+  // handshake.
+  if (redirect_limit_-- == 0) {
+    std::move(callback).Run(net::ERR_TOO_MANY_REDIRECTS);
+    return;
+  }
+
+  std::move(callback).Run(net::ERR_ABORTED);
+
+  // If the request is restarted, all of the client hints should be replaced
+  // the "original"/non-edited values.
   resource_request_->headers.MergeFrom(modified_headers);
   url_loader_.reset();
   Restart();
-
-  std::move(callback).Run(net::ERR_ABORTED);
 }
 
 void NavigationURLLoaderImpl::Clone(
diff --git a/content/browser/renderer_host/input/touch_action_filter.cc b/content/browser/renderer_host/input/touch_action_filter.cc
index f7ff726..a7e18765 100644
--- a/content/browser/renderer_host/input/touch_action_filter.cc
+++ b/content/browser/renderer_host/input/touch_action_filter.cc
@@ -193,7 +193,7 @@
     case WebInputEvent::Type::kGesturePinchBegin:
       drop_pinch_events_ = (touch_action & cc::TouchAction::kPinchZoom) ==
                            cc::TouchAction::kNone;
-      FALLTHROUGH;
+      [[fallthrough]];
     case WebInputEvent::Type::kGesturePinchUpdate:
       gesture_sequence_.append("P");
       if (!drop_pinch_events_)
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
index 950411f..349657c3 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
@@ -360,7 +360,7 @@
   switch (event) {
     case ui::SELECTION_HANDLES_SHOWN:
       quick_menu_requested_ = true;
-      FALLTHROUGH;
+      [[fallthrough]];
     case ui::INSERTION_HANDLE_SHOWN:
       UpdateQuickMenu();
       env_event_observer_ = std::make_unique<EnvEventObserver>(
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index 9c864f5..63a531a 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -2620,6 +2620,55 @@
       ->set_client_hints_controller_delegate(nullptr);
 }
 
+// Verifies client hints are updated when the user-agent is changed in
+// DidStartNavigation().
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTestClientHintsEnabled,
+                       SetUserAgentOverrideWithAcceptCHRestart) {
+  net::EmbeddedTestServer http2_server(
+      net::EmbeddedTestServer::TYPE_HTTPS,
+      net::test_server::HttpConnection::Protocol::kHttp2);
+
+  MockClientHintsControllerDelegate client_hints_controller_delegate(
+      content::GetShellUserAgentMetadata());
+  ShellContentBrowserClient::Get()
+      ->browser_context()
+      ->set_client_hints_controller_delegate(&client_hints_controller_delegate);
+
+  std::vector<std::string> accept_ch_tokens;
+  for (const auto& pair : network::GetClientHintToNameMap())
+    accept_ch_tokens.push_back(pair.second);
+  http2_server.SetAlpsAcceptCH("", base::JoinString(accept_ch_tokens, ","));
+  http2_server.ServeFilesFromSourceDirectory("content/test/data");
+
+  base::RunLoop run_loop;
+  http2_server.RegisterRequestMonitor(base::BindRepeating(
+      [](base::RunLoop* run_loop,
+         const net::test_server::HttpRequest& request) {
+        for (auto header : request.headers)
+          LOG(INFO) << header.first << ": " << header.second;
+        if (request.relative_url.compare("/empty.html") == 0) {
+          EXPECT_EQ(request.headers.at("User-Agent"), "x");
+          run_loop->Quit();
+        }
+      },
+      &run_loop));
+
+  auto handle = http2_server.StartAndReturnHandle();
+
+  blink::UserAgentOverride ua_override;
+  ua_override.ua_string_override = "x";
+  // Do NOT set `ua_metadata_override`, so the UA-CH headers are *removed*
+  ua_override.ua_metadata_override = absl::nullopt;
+  UserAgentInjector injector(shell()->web_contents(), ua_override);
+  EXPECT_TRUE(NavigateToURL(shell(), http2_server.GetURL("/empty.html")));
+
+  run_loop.Run();
+  // This test fails if the browser hangs
+  ShellContentBrowserClient::Get()
+      ->browser_context()
+      ->set_client_hints_controller_delegate(nullptr);
+}
+
 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
                        DialogsFromJavaScriptEndFullscreen) {
   WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
diff --git a/device/fido/win/webauthn_api.cc b/device/fido/win/webauthn_api.cc
index 6d13ef62..d58a9b8d 100644
--- a/device/fido/win/webauthn_api.cc
+++ b/device/fido/win/webauthn_api.cc
@@ -285,12 +285,12 @@
   if (request_options.make_u2f_api_credential) {
     authenticator_attachment =
         WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM_U2F_V2;
-  } else if (request_options.is_off_the_record_context) {
-    // Disable all platform authenticators in off-the-record contexts.
-    //
-    // TODO(crbug.com/908622): Revisit this if the Windows WebAuthn API supports
-    // showing an equivalent dialog to what Chrome is displaying before creating
-    // a platform credential in Incognito mode.
+  } else if (request_options.is_off_the_record_context &&
+             api_version < WEBAUTHN_API_VERSION_4) {
+    // API versions before `WEBAUTHN_API_VERSION_4` don't have support for
+    // showing a warning message that platform credentials will out last the
+    // Incognito session. Thus, in this case, only external authenticators are
+    // enabled.
     authenticator_attachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM;
   } else {
     authenticator_attachment =
@@ -350,7 +350,7 @@
       exclude_list_ptrs.data()};
 
   WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS options{
-      WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_4,
+      WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_5,
       kWinWebAuthnTimeoutMilliseconds,
       WEBAUTHN_CREDENTIALS{
           0, nullptr},  // Ignored because pExcludeCredentialList is set.
@@ -368,6 +368,7 @@
       WEBAUTHN_LARGE_BLOB_SUPPORT_NONE,
       /*bPreferResidentKey=*/request_options.resident_key ==
           ResidentKeyRequirement::kPreferred,
+      request_options.is_off_the_record_context,
   };
 
   WEBAUTHN_CREDENTIAL_ATTESTATION* credential_attestation = nullptr;
@@ -410,6 +411,7 @@
                                   CtapGetAssertionRequest request,
                                   CtapGetAssertionOptions request_options) {
   DCHECK(webauthn_api->IsAvailable());
+  const int api_version = webauthn_api->Version();
 
   std::u16string rp_id16 = base::UTF8ToUTF16(request.rp_id);
   std::string client_data_json = request.client_data_json;
@@ -447,20 +449,12 @@
   if (request.is_u2f_only) {
     authenticator_attachment =
         WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM_U2F_V2;
-  } else if (request.is_off_the_record_context) {
-    // Disable all platform authenticators in off-the-record contexts.
-    //
-    // TODO(crbug.com/908622): Revisit this if the Windows WebAuthn API supports
-    // showing an equivalent dialog to what Chrome is displaying before creating
-    // a platform credential in Incognito mode.
-    authenticator_attachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM;
   } else {
     authenticator_attachment = WEBAUTHN_AUTHENTICATOR_ATTACHMENT_ANY;
   }
 
   std::vector<WEBAUTHN_EXTENSION> extensions;
-  if (webauthn_api->Version() >= WEBAUTHN_API_VERSION_3 &&
-      request.get_cred_blob) {
+  if (api_version >= WEBAUTHN_API_VERSION_3 && request.get_cred_blob) {
     static const BOOL kCredBlobTrue = TRUE;
     extensions.emplace_back(WEBAUTHN_EXTENSION{
         /*pwszExtensionIdentifier=*/WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_BLOB,
diff --git a/docs/callback.md b/docs/callback.md
index 236aea2..c0aac4c0 100644
--- a/docs/callback.md
+++ b/docs/callback.md
@@ -271,6 +271,49 @@
                base::OnceClosure work_aborted_cb);
 ```
 
+### BarrierCallback<T>
+
+Sometimes you might need to request data from several sources, then do something
+with the collective results once all data is available. You can do this with a
+`BarrierCallback<T>`. The `BarrierCallback<T>` is created with two parameters:
+
+-   `num_callbacks`: The number of times the `BarrierCallback` can be run, each
+    time being passed an object of type T.
+-   `done_callback`: This will be run once the `BarrierCallback` has been run
+    `num_callbacks` times.
+
+The `done_callback` will receive a `std::vector<T>` containing the
+`num_callbacks` parameters passed in the respective `Run` calls. The order of
+`Ts` in the `vector` is unspecified.
+
+Note that
+
+-   barrier callback must not be run more than `num_callback` times,
+-   `done_callback` will be called on the same thread as the final call to the
+    barrier callback. `done_callback` will also be cleared on the same thread.
+
+Example:
+
+```cpp
+void Merge(const std::vector<Data>& data);
+
+void Collect(base::OnceCallback<void(Data)> collect_and_merge) {
+  // Do something, probably asynchronously, and at some point:
+  std::move(collect_and_merge).Run(data);
+}
+
+CollectAndMerge() {
+  const auto collect_and_merge =
+      base::BarrierCallback<Image>(sources_.size(), base::BindOnce(&Merge));
+  for (const auto& source : sources_) {
+    // Copy the barrier callback for asynchronous data collection.
+    // Once all sources have called `collect_and_merge` with their respective
+    // data, |Merge| will be called with a vector of the collected data.
+    source.Collect(collect_and_merge);
+  }
+}
+```
+
 ## Quick reference for basic stuff
 
 ### Binding A Bare Function
diff --git a/extensions/browser/api/declarative_webrequest/webrequest_action.cc b/extensions/browser/api/declarative_webrequest/webrequest_action.cc
index c5023925..b2d611d 100644
--- a/extensions/browser/api/declarative_webrequest/webrequest_action.cc
+++ b/extensions/browser/api/declarative_webrequest/webrequest_action.cc
@@ -246,20 +246,20 @@
     const base::Value* value,
     std::string* error,
     bool* bad_message) {
-  const base::DictionaryValue* dict = NULL;
-  CHECK(value->GetAsDictionary(&dict));
+  CHECK(value->is_dict());
   bool has_parameter = false;
   int minimum_priority = std::numeric_limits<int>::min();
   std::string ignore_tag;
-  if (dict->HasKey(keys::kLowerPriorityThanKey)) {
+  if (value->FindKey(keys::kLowerPriorityThanKey)) {
     absl::optional<int> minimum_priority_value =
-        dict->FindIntKey(keys::kLowerPriorityThanKey);
+        value->FindIntKey(keys::kLowerPriorityThanKey);
     INPUT_FORMAT_VALIDATE(minimum_priority_value);
     minimum_priority = *minimum_priority_value;
     has_parameter = true;
   }
-  if (dict->HasKey(keys::kHasTagKey)) {
-    INPUT_FORMAT_VALIDATE(dict->GetString(keys::kHasTagKey, &ignore_tag));
+  if (const base::Value* tag = value->FindKey(keys::kHasTagKey)) {
+    INPUT_FORMAT_VALIDATE(tag->is_string());
+    ignore_tag = tag->GetString();
     has_parameter = true;
   }
   if (!has_parameter) {
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc
index 3174306..66524e8 100644
--- a/extensions/browser/extension_prefs.cc
+++ b/extensions/browser/extension_prefs.cc
@@ -1227,7 +1227,7 @@
 bool ExtensionPrefs::HasWithholdingPermissionsSetting(
     const ExtensionId& extension_id) const {
   const base::DictionaryValue* ext = GetExtensionPref(extension_id);
-  return ext && ext->HasKey(kPrefWithholdingPermissions);
+  return ext && ext->FindKey(kPrefWithholdingPermissions);
 }
 
 std::unique_ptr<const PermissionSet>
@@ -1305,7 +1305,7 @@
 bool ExtensionPrefs::HasAllowFileAccessSetting(
     const std::string& extension_id) const {
   const base::DictionaryValue* ext = GetExtensionPref(extension_id);
-  return ext && ext->HasKey(kPrefAllowFileAccess);
+  return ext && ext->FindKey(kPrefAllowFileAccess);
 }
 
 bool ExtensionPrefs::DoesExtensionHaveState(
diff --git a/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc b/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc
index 9a894d5..8321005 100644
--- a/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc
+++ b/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc
@@ -96,6 +96,8 @@
   const Extension* owner_extension = ProcessManager::Get(context_)->
       GetExtensionForWebContents(guest->owner_web_contents());
 
+  // Using `GetOwnerSiteURL` in the case of MimeHandlerViewGuest is safe, since
+  // mimeHandlerViewGuestInternal allows all urls.
   const GURL& owner_site_url = guest->GetOwnerSiteURL();
   // Ok for |owner_extension| to be nullptr, the embedder might be WebUI.
   Feature::Availability availability = feature->IsAvailableToContext(
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
index ded1894..7c2c383 100644
--- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
+++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
@@ -119,7 +119,7 @@
   return rfh ? rfh->GetSiteInstance() : nullptr;
 }
 
-bool MimeHandlerViewGuest::CanBeEmbeddedInsideCrossProcessFrames() {
+bool MimeHandlerViewGuest::CanBeEmbeddedInsideCrossProcessFrames() const {
   return true;
 }
 
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
index 4c0820c6..8aa91c42 100644
--- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
+++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
@@ -92,7 +92,7 @@
   static const char Type[];
 
   // GuestViewBase overrides.
-  bool CanBeEmbeddedInsideCrossProcessFrames() override;
+  bool CanBeEmbeddedInsideCrossProcessFrames() const override;
   content::RenderWidgetHost* GetOwnerRenderWidgetHost() override;
   content::SiteInstance* GetOwnerSiteInstance() override;
 
diff --git a/extensions/browser/updater/extension_downloader.cc b/extensions/browser/updater/extension_downloader.cc
index a364920..7cb2ae90 100644
--- a/extensions/browser/updater/extension_downloader.cc
+++ b/extensions/browser/updater/extension_downloader.cc
@@ -1238,9 +1238,9 @@
             "This feature cannot be disabled. It is only enabled when the user "
             "has installed extensions and it needs updating."
           chrome_policy {
-            ExtensionInstallBlacklist {
+            ExtensionInstallBlocklist {
               policy_options {mode: MANDATORY}
-              ExtensionInstallBlacklist: {
+              ExtensionInstallBlocklist: {
                 entries: '*'
               }
             }
diff --git a/extensions/common/api/extension_action/action_info.cc b/extensions/common/api/extension_action/action_info.cc
index 92f35c0..0fb8338 100644
--- a/extensions/common/api/extension_action/action_info.cc
+++ b/extensions/common/api/extension_action/action_info.cc
@@ -67,22 +67,25 @@
   // Read the page action |default_icon| (optional).
   // The |default_icon| value can be either dictionary {icon size -> icon path}
   // or non empty string value.
-  if (dict->HasKey(keys::kActionDefaultIcon)) {
-    const base::DictionaryValue* icons_value = NULL;
-    std::string default_icon;
-    if (dict->GetDictionary(keys::kActionDefaultIcon, &icons_value)) {
+  if (const base::Value* default_icon =
+          dict->FindKey(keys::kActionDefaultIcon)) {
+    std::string default_icon_str;
+    if (default_icon->is_string())
+      default_icon_str = default_icon->GetString();
+
+    if (default_icon->is_dict()) {
       if (!manifest_handler_helpers::LoadIconsFromDictionary(
-              icons_value, &result->default_icon, error)) {
+              default_icon, &result->default_icon, error)) {
         return nullptr;
       }
-    } else if (dict->GetString(keys::kActionDefaultIcon, &default_icon) &&
+    } else if (default_icon->is_string() &&
                manifest_handler_helpers::NormalizeAndValidatePath(
-                   &default_icon)) {
+                   &default_icon_str)) {
       // Choose the most optimistic (highest) icon density regardless of the
       // actual icon resolution, whatever that happens to be. Code elsewhere
       // knows how to scale down to 19.
       result->default_icon.Add(extension_misc::EXTENSION_ICON_GIGANTOR,
-                               default_icon);
+                               default_icon_str);
     } else {
       *error = errors::kInvalidActionDefaultIcon;
       return nullptr;
@@ -91,25 +94,28 @@
 
   // Read the page action title from |default_title| if present, |name| if not
   // (both optional).
-  if (dict->HasKey(keys::kActionDefaultTitle)) {
-    if (!dict->GetString(keys::kActionDefaultTitle, &result->default_title)) {
+  if (const base::Value* default_title =
+          dict->FindKey(keys::kActionDefaultTitle)) {
+    if (!default_title->is_string()) {
       *error = errors::kInvalidActionDefaultTitle;
       return nullptr;
     }
+    result->default_title = default_title->GetString();
   }
 
   // Read the action's default popup (optional).
-  if (dict->HasKey(keys::kActionDefaultPopup)) {
-    std::string url_str;
-    if (!dict->GetString(keys::kActionDefaultPopup, &url_str)) {
+  if (const base::Value* default_popup =
+          dict->FindKey(keys::kActionDefaultPopup)) {
+    const std::string* url_str = default_popup->GetIfString();
+    if (!url_str) {
       *error = errors::kInvalidActionDefaultPopup;
       return nullptr;
     }
 
-    if (!url_str.empty()) {
+    if (!url_str->empty()) {
       // An empty string is treated as having no popup.
       result->default_popup_url =
-          Extension::GetResourceURL(extension->url(), url_str);
+          Extension::GetResourceURL(extension->url(), *url_str);
       if (!result->default_popup_url.is_valid()) {
         *error = errors::kInvalidActionDefaultPopup;
         return nullptr;
@@ -120,7 +126,8 @@
     }
   }
 
-  if (dict->HasKey(keys::kActionDefaultState)) {
+  if (const base::Value* default_state =
+          dict->FindKey(keys::kActionDefaultState)) {
     // The default_state key is only valid for TYPE_ACTION; throw an error for
     // others.
     if (type != TYPE_ACTION) {
@@ -128,13 +135,13 @@
       return nullptr;
     }
 
-    std::string default_state;
-    if (!dict->GetString(keys::kActionDefaultState, &default_state) ||
-        !(default_state == kEnabled || default_state == kDisabled)) {
+    if (!default_state->is_string() ||
+        !(default_state->GetString() == kEnabled ||
+          default_state->GetString() == kDisabled)) {
       *error = errors::kInvalidActionDefaultState;
       return nullptr;
     }
-    result->default_state = default_state == kEnabled
+    result->default_state = default_state->GetString() == kEnabled
                                 ? ActionInfo::STATE_ENABLED
                                 : ActionInfo::STATE_DISABLED;
   }
diff --git a/extensions/common/event_filter.cc b/extensions/common/event_filter.cc
index 789eadc2..2f6b33d 100644
--- a/extensions/common/event_filter.cc
+++ b/extensions/common/event_filter.cc
@@ -96,7 +96,7 @@
     return AddDictionaryAsConditionSet(&empty_dict, condition_sets);
   }
   for (int i = 0; i < url_filter_count; i++) {
-    base::DictionaryValue* url_filter;
+    const base::DictionaryValue* url_filter;
     if (!matcher->GetURLFilter(i, &url_filter))
       return false;
     if (!AddDictionaryAsConditionSet(url_filter, condition_sets))
@@ -106,7 +106,7 @@
 }
 
 bool EventFilter::AddDictionaryAsConditionSet(
-    base::DictionaryValue* url_filter,
+    const base::DictionaryValue* url_filter,
     URLMatcherConditionSet::Vector* condition_sets) {
   std::string error;
   URLMatcherConditionSet::ID condition_set_id = next_condition_set_id_++;
diff --git a/extensions/common/event_filter.h b/extensions/common/event_filter.h
index 1ff2797..f3a944a 100644
--- a/extensions/common/event_filter.h
+++ b/extensions/common/event_filter.h
@@ -105,7 +105,7 @@
       url_matcher::URLMatcherConditionSet::Vector* condition_sets);
 
   bool AddDictionaryAsConditionSet(
-      base::DictionaryValue* url_filter,
+      const base::DictionaryValue* url_filter,
       url_matcher::URLMatcherConditionSet::Vector* condition_sets);
 
   url_matcher::URLMatcher url_matcher_;
diff --git a/extensions/common/event_matcher.cc b/extensions/common/event_matcher.cc
index 72d363a..a56b567 100644
--- a/extensions/common/event_matcher.cc
+++ b/extensions/common/event_matcher.cc
@@ -64,10 +64,18 @@
   return 0;
 }
 
-bool EventMatcher::GetURLFilter(int i, base::DictionaryValue** url_filter_out) {
+bool EventMatcher::GetURLFilter(int i,
+                                const base::DictionaryValue** url_filter_out) {
   base::ListValue* url_filters = nullptr;
   if (filter_->GetList(kUrlFiltersKey, &url_filters)) {
-    return url_filters->GetDictionary(i, url_filter_out);
+    base::Value& dict = url_filters->GetList()[i];
+    if (!dict.is_dict()) {
+      return false;
+    }
+    if (url_filter_out) {
+      *url_filter_out = &base::Value::AsDictionaryValue(dict);
+    }
+    return true;
   }
   return false;
 }
diff --git a/extensions/common/event_matcher.h b/extensions/common/event_matcher.h
index e5224db3..7bd54211 100644
--- a/extensions/common/event_matcher.h
+++ b/extensions/common/event_matcher.h
@@ -31,7 +31,7 @@
   bool MatchNonURLCriteria(const mojom::EventFilteringInfo& event_info) const;
 
   int GetURLFilterCount() const;
-  bool GetURLFilter(int i, base::DictionaryValue** url_filter_out);
+  bool GetURLFilter(int i, const base::DictionaryValue** url_filter_out);
 
   int GetWindowTypeCount() const;
   bool GetWindowType(int i, std::string* window_type_out) const;
diff --git a/extensions/common/extension.cc b/extensions/common/extension.cc
index 40ca522..6147505 100644
--- a/extensions/common/extension.cc
+++ b/extensions/common/extension.cc
@@ -147,11 +147,11 @@
                         int creation_flags,
                         std::u16string* error,
                         ExtensionId* extension_id) {
-  if (manifest.HasKey(keys::kPublicKey)) {
-    std::string public_key;
+  if (const base::Value* public_key = manifest.FindKey(keys::kPublicKey)) {
     std::string public_key_bytes;
-    if (!manifest.GetString(keys::kPublicKey, &public_key) ||
-        !Extension::ParsePEMKeyBytes(public_key, &public_key_bytes)) {
+    if (!public_key->is_string() ||
+        !Extension::ParsePEMKeyBytes(public_key->GetString(),
+                                     &public_key_bytes)) {
       *error = errors::kInvalidKey;
       return false;
     }
diff --git a/extensions/common/extension_l10n_util.cc b/extensions/common/extension_l10n_util.cc
index 14cc1d95..0824e3c 100644
--- a/extensions/common/extension_l10n_util.cc
+++ b/extensions/common/extension_l10n_util.cc
@@ -106,16 +106,16 @@
 // Localizes manifest value of string type for a given key.
 bool LocalizeManifestValue(const std::string& key,
                            const extensions::MessageBundle& messages,
-                           base::DictionaryValue* manifest,
+                           base::Value* manifest,
                            std::string* error) {
-  std::string result;
-  if (!manifest->GetString(key, &result))
+  std::string* result = manifest->FindStringPath(key);
+  if (!result)
     return true;
 
-  if (!messages.ReplaceMessages(&result, error))
+  if (!messages.ReplaceMessages(result, error))
     return false;
 
-  manifest->SetString(key, result);
+  manifest->SetStringPath(key, *result);
   return true;
 }
 
@@ -207,11 +207,14 @@
   if (!manifest)
     return false;
 
-  if (!manifest->HasKey(keys::kDefaultLocale))
+  if (!manifest->FindKey(keys::kDefaultLocale))
     return false;
 
   std::string manifest_current_locale;
-  manifest->GetString(keys::kCurrentLocale, &manifest_current_locale);
+  const std::string* manifest_current_locale_in =
+      manifest->FindStringKey(keys::kCurrentLocale);
+  if (manifest_current_locale_in)
+    manifest_current_locale = *manifest_current_locale_in;
   return manifest_current_locale != LocaleForLocalization();
 }
 
@@ -219,8 +222,8 @@
                       base::DictionaryValue* manifest,
                       std::string* error) {
   // Initialize name.
-  std::string result;
-  if (!manifest->GetString(keys::kName, &result)) {
+  const std::string* result = manifest->FindStringKey(keys::kName);
+  if (!result) {
     *error = errors::kInvalidName;
     return false;
   }
@@ -266,13 +269,12 @@
 
   base::ListValue* file_handlers = NULL;
   if (manifest->GetList(keys::kFileBrowserHandlers, &file_handlers)) {
-    for (size_t i = 0; i < file_handlers->GetList().size(); i++) {
-      base::DictionaryValue* handler = NULL;
-      if (!file_handlers->GetDictionary(i, &handler)) {
+    for (base::Value& handler : file_handlers->GetList()) {
+      if (!handler.is_dict()) {
         *error = errors::kInvalidFileBrowserHandler;
         return false;
       }
-      if (!LocalizeManifestValue(keys::kActionDefaultTitle, messages, handler,
+      if (!LocalizeManifestValue(keys::kActionDefaultTitle, messages, &handler,
                                  error))
         return false;
     }
@@ -281,15 +283,14 @@
   // Initialize all input_components
   base::ListValue* input_components = NULL;
   if (manifest->GetList(keys::kInputComponents, &input_components)) {
-    for (size_t i = 0; i < input_components->GetList().size(); ++i) {
-      base::DictionaryValue* module = NULL;
-      if (!input_components->GetDictionary(i, &module)) {
+    for (base::Value& module : input_components->GetList()) {
+      if (!module.is_dict()) {
         *error = errors::kInvalidInputComponents;
         return false;
       }
-      if (!LocalizeManifestValue(keys::kName, messages, module, error))
+      if (!LocalizeManifestValue(keys::kName, messages, &module, error))
         return false;
-      if (!LocalizeManifestValue(keys::kDescription, messages, module, error))
+      if (!LocalizeManifestValue(keys::kDescription, messages, &module, error))
         return false;
     }
   }
diff --git a/extensions/common/features/manifest_feature.cc b/extensions/common/features/manifest_feature.cc
index 67d9569..8f9676e 100644
--- a/extensions/common/features/manifest_feature.cc
+++ b/extensions/common/features/manifest_feature.cc
@@ -29,7 +29,7 @@
 
   // We know we can skip manifest()->GetKey() here because we just did the same
   // validation it would do above.
-  if (extension && !extension->manifest()->value()->HasKey(name()))
+  if (extension && !extension->manifest()->value()->FindKey(name()))
     return CreateAvailability(NOT_PRESENT, extension->GetType());
 
   return CreateAvailability(IS_AVAILABLE);
diff --git a/extensions/common/manifest.cc b/extensions/common/manifest.cc
index 23ec971..a6267d6e 100644
--- a/extensions/common/manifest.cc
+++ b/extensions/common/manifest.cc
@@ -204,11 +204,11 @@
     const base::DictionaryValue& value,
     bool for_login_screen) {
   Type type = TYPE_UNKNOWN;
-  if (value.HasKey(keys::kTheme)) {
+  if (value.FindKey(keys::kTheme)) {
     type = TYPE_THEME;
-  } else if (value.HasKey(api::shared_module::ManifestKeys::kExport)) {
+  } else if (value.FindKey(api::shared_module::ManifestKeys::kExport)) {
     type = TYPE_SHARED_MODULE;
-  } else if (value.HasKey(keys::kApp)) {
+  } else if (value.FindKey(keys::kApp)) {
     if (value.Get(keys::kWebURLs, nullptr) ||
         value.Get(keys::kLaunchWebURL, nullptr)) {
       type = TYPE_HOSTED_APP;
@@ -217,7 +217,7 @@
     } else {
       type = TYPE_LEGACY_PACKAGED_APP;
     }
-  } else if (value.HasKey(keys::kChromeOSSystemExtension)) {
+  } else if (value.FindKey(keys::kChromeOSSystemExtension)) {
     type = TYPE_CHROMEOS_SYSTEM_EXTENSION;
   } else if (for_login_screen) {
     type = TYPE_LOGIN_SCREEN_EXTENSION;
diff --git a/extensions/renderer/bindings/api_binding.cc b/extensions/renderer/bindings/api_binding.cc
index 348531e..de292082 100644
--- a/extensions/renderer/bindings/api_binding.cc
+++ b/extensions/renderer/bindings/api_binding.cc
@@ -483,7 +483,7 @@
 
     std::string type;
     CHECK(dict->GetString("type", &type));
-    if (type != "object" && !dict->HasKey(kValueKey)) {
+    if (type != "object" && !dict->FindKey(kValueKey)) {
       // TODO(devlin): What does a fundamental property not having a value mean?
       // It doesn't seem useful, and looks like it's only used by runtime.id,
       // which is set by custom bindings. Investigate, and remove.
@@ -633,7 +633,7 @@
         return;  // Our work here is done.
       case APIBindingHooks::RequestResult::ARGUMENTS_UPDATED:
         updated_args = true;
-        FALLTHROUGH;
+        [[fallthrough]];
       case APIBindingHooks::RequestResult::NOT_HANDLED:
         break;  // Handle in the default manner.
     }
diff --git a/extensions/renderer/native_extension_bindings_system.cc b/extensions/renderer/native_extension_bindings_system.cc
index 469360f..81710ea 100644
--- a/extensions/renderer/native_extension_bindings_system.cc
+++ b/extensions/renderer/native_extension_bindings_system.cc
@@ -834,7 +834,7 @@
       ipc_message_sender_->SendAddUnfilteredEventListenerIPC(script_context,
                                                              event_name);
       // Check if we need to add a lazy listener as well.
-      FALLTHROUGH;
+      [[fallthrough]];
     case binding::EventListenersChanged::
         kFirstUnfilteredListenerForContextAdded: {
       // If the listener is the first for the event page, we need to
@@ -852,7 +852,7 @@
       ipc_message_sender_->SendRemoveUnfilteredEventListenerIPC(script_context,
                                                                 event_name);
       // Check if we need to remove a lazy listener as well.
-      FALLTHROUGH;
+      [[fallthrough]];
     case binding::EventListenersChanged::
         kLastUnfilteredListenerForContextRemoved: {
       // If the listener was the last for the event page, we need to remove
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json
index c1910ac0..2c2fc20 100644
--- a/gpu/config/gpu_driver_bug_list.json
+++ b/gpu/config/gpu_driver_bug_list.json
@@ -3902,6 +3902,17 @@
         "disable_accelerated_vp8_decode",
         "disable_accelerated_vp9_decode"
       ]
+    },
+    {
+      "id": 389,
+      "description": "Avoid waiting on a egl fence before pageflipping and rely on implicit sync.",
+      "os": {
+        "type": "chromeos"
+      },
+      "gl_vendor": "nouveau.*",
+      "features": [
+        "rely_on_implicit_sync_for_swap_buffers"
+      ]
     }
   ]
 }
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg
index 3435ffc0..7dbf544 100644
--- a/infra/config/generated/luci/commit-queue.cfg
+++ b/infra/config/generated/luci/commit-queue.cfg
@@ -90,6 +90,12 @@
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
+        name: "chrome/try/fuchsia-fyi-astro"
+        includable_only: true
+        owner_whitelist_group: "googlers"
+        owner_whitelist_group: "project-chromium-robot-committers"
+      }
+      builders {
         name: "chrome/try/ipad-device"
         includable_only: true
         owner_whitelist_group: "googlers"
diff --git a/infra/config/subprojects/chromium/try.star b/infra/config/subprojects/chromium/try.star
index 796b4e2..d5dc5125 100644
--- a/infra/config/subprojects/chromium/try.star
+++ b/infra/config/subprojects/chromium/try.star
@@ -174,6 +174,10 @@
 )
 
 chrome_internal_verifier(
+    builder = "fuchsia-fyi-astro",
+)
+
+chrome_internal_verifier(
     builder = "ipad-device",
 )
 
diff --git a/ios/chrome/app/strings/ios_chromium_strings.grd b/ios/chrome/app/strings/ios_chromium_strings.grd
index 1db2de84..25f5f14 100644
--- a/ios/chrome/app/strings/ios_chromium_strings.grd
+++ b/ios/chrome/app/strings/ios_chromium_strings.grd
@@ -502,6 +502,9 @@
       <message name="IDS_IOS_SETTINGS_ADD_PASSWORD_FOOTER" desc="Disclaimer telling users what will happen to their passwords">
         Your password will be saved in your Account (<ph name="EMAIL">$1<ex>example@gmail.com</ex></ph>).
       </message>
+      <message name="IDS_IOS_SETTINGS_ADD_PASSWORD_FOOTER_BRANDED" desc="Disclaimer telling users what will happen to their passwords">
+        Your password will be saved to Password Manager for <ph name="EMAIL">$1<ex>example@gmail.com</ex></ph>.
+      </message>
     </messages>
   </release>
 </grit>
diff --git a/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_SETTINGS_ADD_PASSWORD_FOOTER_BRANDED.png.sha1 b/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_SETTINGS_ADD_PASSWORD_FOOTER_BRANDED.png.sha1
new file mode 100644
index 0000000..a6c90ee
--- /dev/null
+++ b/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_SETTINGS_ADD_PASSWORD_FOOTER_BRANDED.png.sha1
@@ -0,0 +1 @@
+4787baaa9075f10a4c0222549723c77cdcc7d1b1
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings.grd b/ios/chrome/app/strings/ios_google_chrome_strings.grd
index 7dee437f..466cbe74 100644
--- a/ios/chrome/app/strings/ios_google_chrome_strings.grd
+++ b/ios/chrome/app/strings/ios_google_chrome_strings.grd
@@ -502,6 +502,9 @@
       <message name="IDS_IOS_SETTINGS_ADD_PASSWORD_FOOTER" desc="Disclaimer telling users what will happen to their passwords">
         Your password will be saved in your Google Account (<ph name="EMAIL">$1<ex>example@gmail.com</ex></ph>).
       </message>
+      <message name="IDS_IOS_SETTINGS_ADD_PASSWORD_FOOTER_BRANDED" desc="Disclaimer telling users what will happen to their passwords">
+        Your password will be saved to Google Password Manager for <ph name="EMAIL">$1<ex>example@gmail.com</ex></ph>.
+      </message>
     </messages>
   </release>
 </grit>
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_SETTINGS_ADD_PASSWORD_FOOTER_BRANDED.png.sha1 b/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_SETTINGS_ADD_PASSWORD_FOOTER_BRANDED.png.sha1
new file mode 100644
index 0000000..a6c90ee
--- /dev/null
+++ b/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_SETTINGS_ADD_PASSWORD_FOOTER_BRANDED.png.sha1
@@ -0,0 +1 @@
+4787baaa9075f10a4c0222549723c77cdcc7d1b1
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index cc96f0d..33dc8e8 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1577,6 +1577,9 @@
       <message name="IDS_IOS_PASSWORD_MANAGER_BLOCK_BUTTON" desc="Button text for the 'Save Password' infobar's 'Never remember for this site' option [Length: 10em]">
         Never
       </message>
+      <message name="IDS_IOS_PASSWORD_MANAGER_LOGO_ACCESSIBILITY_LABEL" desc="Accessibility label for the password manager logo." meaning="Text read by Text-to-Speech when the picture is selected.">
+        Google Password Manager
+      </message>
       <message name="IDS_IOS_PASSWORD_MANAGER_MODAL_BLOCK_BUTTON" desc="Button text for the 'Save Password' Infobar's Modal 'Never remember this site' option [Length: 70em]">
         Never For This Site
       </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORD_MANAGER_LOGO_ACCESSIBILITY_LABEL.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORD_MANAGER_LOGO_ACCESSIBILITY_LABEL.png.sha1
new file mode 100644
index 0000000..ba543f2
--- /dev/null
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORD_MANAGER_LOGO_ACCESSIBILITY_LABEL.png.sha1
@@ -0,0 +1 @@
+7ae76f4ba5fa37508937f96c6b58cff9ebcf1c04
\ No newline at end of file
diff --git a/ios/chrome/browser/autofill/form_structure_browsertest.mm b/ios/chrome/browser/autofill/form_structure_browsertest.mm
index d6af29c..fe75c3f 100644
--- a/ios/chrome/browser/autofill/form_structure_browsertest.mm
+++ b/ios/chrome/browser/autofill/form_structure_browsertest.mm
@@ -157,7 +157,8 @@
        // TODO(crbug/1165780): Remove once shared labels are launched.
        autofill::features::kAutofillEnableSupportForParsingWithSharedLabels,
        // TODO(crbug.com/1150895) Remove once launched.
-       autofill::features::kAutofillParsingPatternsLanguageDetection,
+       autofill::features::kAutofillParsingPatternProvider,
+       autofill::features::kAutofillPageLanguageDetection,
        // TODO(crbug.com/1277480): Remove once launched.
        autofill::features::kAutofillEnableNameSurenameParsing,
        // TODO(crbug.com/1190334): Remove once launched.
diff --git a/ios/chrome/browser/ui/follow/follow_site_info.h b/ios/chrome/browser/ui/follow/follow_site_info.h
index 18bc035..f273a82 100644
--- a/ios/chrome/browser/ui/follow/follow_site_info.h
+++ b/ios/chrome/browser/ui/follow/follow_site_info.h
@@ -11,16 +11,17 @@
 // status.
 @interface FollowSiteInfo : NSObject
 
-// Initiates a FollowSiteInfo with |siteURL| and |rssLinks|.
+// Initiates a FollowSiteInfo with |siteURL| and |RSSLinks|.
+// |RSSlinks| can be empty.
 - (instancetype)initWithPageURL:(NSURL*)siteURL
-                       rssLinks:(NSArray<NSURL*>*)rssLinks
+                       RSSLinks:(NSArray<NSURL*>*)RSSLinks
     NS_DESIGNATED_INITIALIZER;
 - (instancetype)init NS_UNAVAILABLE;
 
 // The URL of the site.
 @property(nonatomic, strong, readonly) NSURL* siteURL;
 // The list of RSS links.
-@property(nonatomic, strong, readonly) NSArray<NSURL*>* rssLinks;
+@property(nonatomic, strong, readonly) NSArray<NSURL*>* RSSLinks;
 
 @end
 
diff --git a/ios/chrome/browser/ui/follow/follow_site_info.mm b/ios/chrome/browser/ui/follow/follow_site_info.mm
index 3665c1f..ac4cba75 100644
--- a/ios/chrome/browser/ui/follow/follow_site_info.mm
+++ b/ios/chrome/browser/ui/follow/follow_site_info.mm
@@ -11,11 +11,11 @@
 @implementation FollowSiteInfo
 
 - (instancetype)initWithPageURL:(NSURL*)siteURL
-                       rssLinks:(NSArray<NSURL*>*)rssLinks {
+                       RSSLinks:(NSArray<NSURL*>*)RSSLinks {
   self = [super init];
   if (self) {
     _siteURL = siteURL;
-    _rssLinks = rssLinks;
+    _RSSLinks = RSSLinks;
   }
   return self;
 }
diff --git a/ios/chrome/browser/ui/passwords/password_breach_view_controller.mm b/ios/chrome/browser/ui/passwords/password_breach_view_controller.mm
index e98e016..f2e0a1c 100644
--- a/ios/chrome/browser/ui/passwords/password_breach_view_controller.mm
+++ b/ios/chrome/browser/ui/passwords/password_breach_view_controller.mm
@@ -35,22 +35,6 @@
               kIOSEnablePasswordManagerBrandingUpdate)) {
     self.image = [UIImage imageNamed:@"password_breach_illustration"];
     self.showDismissBarButton = NO;
-
-    UIImageView* imageView = [[UIImageView alloc]
-        initWithImage:[UIImage imageNamed:@"passwords_logo_colored"]];
-    imageView.contentMode = UIViewContentModeScaleAspectFit;
-    imageView.translatesAutoresizingMaskIntoConstraints = NO;
-    [self.specificContentView addSubview:imageView];
-
-    [NSLayoutConstraint activateConstraints:@[
-      [imageView.topAnchor
-          constraintEqualToAnchor:self.specificContentView.topAnchor],
-      [imageView.centerXAnchor
-          constraintEqualToAnchor:self.specificContentView.centerXAnchor],
-      [imageView.widthAnchor constraintLessThanOrEqualToConstant:kLogoWidth],
-      [imageView.bottomAnchor
-          constraintEqualToAnchor:self.specificContentView.bottomAnchor],
-    ]];
   } else {
     self.image = [UIImage imageNamed:@"legacy_password_breach_illustration"];
   }
@@ -62,6 +46,33 @@
   [super viewDidLoad];
   self.view.accessibilityIdentifier =
       kPasswordBreachViewAccessibilityIdentifier;
+
+  if (base::FeatureList::IsEnabled(
+          password_manager::features::
+              kIOSEnablePasswordManagerBrandingUpdate)) {
+    UIImageView* logoImageView = [[UIImageView alloc]
+        initWithImage:[UIImage imageNamed:@"passwords_logo_colored"]];
+    logoImageView.contentMode = UIViewContentModeScaleAspectFit;
+    logoImageView.translatesAutoresizingMaskIntoConstraints = NO;
+
+    [self.specificContentSuperview addSubview:logoImageView];
+
+    logoImageView.isAccessibilityElement = YES;
+    logoImageView.accessibilityLabel = l10n_util::GetNSString(
+        IDS_IOS_PASSWORD_MANAGER_LOGO_ACCESSIBILITY_LABEL);
+
+    [NSLayoutConstraint activateConstraints:@[
+      [logoImageView.topAnchor
+          constraintEqualToAnchor:self.specificContentLayoutGuide.topAnchor],
+      [logoImageView.centerXAnchor
+          constraintEqualToAnchor:self.specificContentLayoutGuide
+                                      .centerXAnchor],
+      [logoImageView.widthAnchor
+          constraintLessThanOrEqualToConstant:kLogoWidth],
+      [logoImageView.bottomAnchor
+          constraintEqualToAnchor:self.specificContentLayoutGuide.bottomAnchor],
+    ]];
+  }
 }
 
 #pragma mark - PasswordBreachConsumer
diff --git a/ios/chrome/browser/ui/settings/cells/settings_image_detail_text_cell.mm b/ios/chrome/browser/ui/settings/cells/settings_image_detail_text_cell.mm
index a7c8975..b3d129b 100644
--- a/ios/chrome/browser/ui/settings/cells/settings_image_detail_text_cell.mm
+++ b/ios/chrome/browser/ui/settings/cells/settings_image_detail_text_cell.mm
@@ -174,10 +174,15 @@
 #pragma mark - UIAccessibility
 
 - (NSString*)accessibilityLabel {
+  if (!self.textLabel.text) {
+    return self.detailTextLabel.text;
+  }
+
   if (self.detailTextLabel.text) {
     return [NSString stringWithFormat:@"%@, %@", self.textLabel.text,
                                       self.detailTextLabel.text];
   }
+
   return self.textLabel.text;
 }
 
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm
index 59242e36..09227411 100644
--- a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm
@@ -505,14 +505,26 @@
 }
 
 - (NSString*)footerText {
-  if (self.syncingUserEmail) {
-    return l10n_util::GetNSStringF(
-        IDS_IOS_SETTINGS_ADD_PASSWORD_FOOTER,
-        base::SysNSStringToUTF16(self.syncingUserEmail));
-  }
+  if (base::FeatureList::IsEnabled(
+          password_manager::features::
+              kIOSEnablePasswordManagerBrandingUpdate)) {
+    if (self.syncingUserEmail) {
+      return l10n_util::GetNSStringF(
+          IDS_IOS_SETTINGS_ADD_PASSWORD_FOOTER_BRANDED,
+          base::SysNSStringToUTF16(self.syncingUserEmail));
+    }
 
-  return l10n_util::GetNSString(
-      IDS_IOS_SETTINGS_ADD_PASSWORD_FOOTER_NON_SYNCING);
+    return l10n_util::GetNSString(IDS_IOS_SAVE_PASSWORD_FOOTER_NOT_SYNCING);
+  } else {
+    if (self.syncingUserEmail) {
+      return l10n_util::GetNSStringF(
+          IDS_IOS_SETTINGS_ADD_PASSWORD_FOOTER,
+          base::SysNSStringToUTF16(self.syncingUserEmail));
+    }
+
+    return l10n_util::GetNSString(
+        IDS_IOS_SETTINGS_ADD_PASSWORD_FOOTER_NON_SYNCING);
+  }
 }
 
 #pragma mark - UITableViewDelegate
diff --git a/ios/chrome/browser/ui/settings/search_engine_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/search_engine_table_view_controller_unittest.mm
index 661d1b4..f1e54ad 100644
--- a/ios/chrome/browser/ui/settings/search_engine_table_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/search_engine_table_view_controller_unittest.mm
@@ -471,15 +471,14 @@
   histogram_tester_.ExpectTotalCount(kUmaSelectDefaultSearchEngine, 3);
 
   // Check that the selection was written back to the prefs.
-  const base::DictionaryValue* searchProviderDict =
-      &base::Value::AsDictionaryValue(
-          *chrome_browser_state_->GetTestingPrefService()->GetDictionary(
-              DefaultSearchManager::kDefaultSearchProviderDataPrefName));
+  const base::Value* searchProviderDict =
+      chrome_browser_state_->GetTestingPrefService()->GetDictionary(
+          DefaultSearchManager::kDefaultSearchProviderDataPrefName);
   ASSERT_TRUE(searchProviderDict);
-  std::u16string short_name;
-  EXPECT_TRUE(searchProviderDict->GetString(DefaultSearchManager::kShortName,
-                                            &short_name));
-  EXPECT_EQ(url_c1->short_name(), short_name);
+  const std::string* short_name =
+      searchProviderDict->FindStringKey(DefaultSearchManager::kShortName);
+  ASSERT_TRUE(short_name);
+  EXPECT_EQ(url_c1->short_name(), base::ASCIIToUTF16(*short_name));
 }
 
 // Tests that prepopulated engines are disabled with checkmark removed in
diff --git a/ios/chrome/browser/ui/ui_feature_flags.cc b/ios/chrome/browser/ui/ui_feature_flags.cc
index 224494d..0d7436c7 100644
--- a/ios/chrome/browser/ui/ui_feature_flags.cc
+++ b/ios/chrome/browser/ui/ui_feature_flags.cc
@@ -50,7 +50,7 @@
                                             base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kSearchHistoryLinkIOS{"SearchHistoryLinkIOS",
-                                          base::FEATURE_DISABLED_BY_DEFAULT};
+                                          base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kUpdateHistoryEntryPointsInIncognito{
     "UpdateHistoryEntryPointsInIncognito", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.h b/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.h
index 9d83c8e..ee6a4219 100644
--- a/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.h
+++ b/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.h
@@ -86,9 +86,15 @@
 // The action handler for interactions in this View Controller.
 @property(nonatomic, weak) id<ConfirmationAlertActionHandler> actionHandler;
 
+// Layout guide to specific content added in derived view controller.
+@property(nonatomic, strong, readonly)
+    UILayoutGuide* specificContentLayoutGuide;
+
 // The container view for the screen-specific content. Derived view controllers
-// should add their UI elements to it, before the VC is loaded.
-@property(nonatomic, strong, readonly) UIView* specificContentView;
+// should add their UI elements to it after -viewDidLoad. This view contains the
+// confirmation alert contents, use |specificContentLayoutGuide| for set
+// constraints below the contents. See crbug.com/1282434 for more.
+@property(nonatomic, strong) UIView* specificContentSuperview;
 
 @end
 
diff --git a/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.mm b/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.mm
index 207befa..2ee1fe6b 100644
--- a/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.mm
+++ b/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.mm
@@ -69,8 +69,7 @@
     _customSpacingAfterImage = kStackViewSpacingAfterIllustration;
     _showDismissBarButton = YES;
     _dismissBarButtonSystemItem = UIBarButtonSystemItemDone;
-    _specificContentView = [[UIView alloc] init];
-    _specificContentView.translatesAutoresizingMaskIntoConstraints = NO;
+    _specificContentLayoutGuide = [[UILayoutGuide alloc] init];
   }
   return self;
 }
@@ -93,16 +92,24 @@
   UIStackView* stackView =
       [self createStackViewWithArrangedSubviews:stackSubviews];
 
-  // UILayoutGuide that wraps the scrollable content. Needed in order to pin UI
-  // elements in view specific content above actions buttons.
-  UILayoutGuide* scrollContentLayoutGuide = [[UILayoutGuide alloc] init];
+  // UIView used to set constraints to the scrollable content. Needed in order
+  // to pin UI elements in specific content view above actions buttons. UI
+  // elements can't be added to this view as it does not work with VoiceOver,
+  // see crbug.com/1281364. UILayoutGuide can't be use here as it does not work
+  // with dynamic type, see crbug.com/1283622.
+  UIView* scrollContentView = [[UIView alloc] init];
+  scrollContentView.translatesAutoresizingMaskIntoConstraints = NO;
 
   UIScrollView* scrollView = [self createScrollView];
-  [scrollView addLayoutGuide:scrollContentLayoutGuide];
+  [scrollView addSubview:scrollContentView];
   [scrollView addSubview:stackView];
-  [scrollView addSubview:self.specificContentView];
+  [scrollView addLayoutGuide:self.specificContentLayoutGuide];
   [self.view addSubview:scrollView];
 
+  // Needed to have VoiceOver working to elements added in derived view
+  // controller.
+  self.specificContentSuperview = scrollView;
+
   self.view.preservesSuperviewLayoutMargins = YES;
   UILayoutGuide* margins = self.view.layoutMarginsGuide;
 
@@ -126,26 +133,25 @@
         constraintLessThanOrEqualToAnchor:margins.widthAnchor],
 
     [stackView.topAnchor
-        constraintGreaterThanOrEqualToAnchor:scrollContentLayoutGuide
-                                                 .topAnchor],
+        constraintGreaterThanOrEqualToAnchor:scrollContentView.topAnchor],
     [stackView.bottomAnchor
-        constraintLessThanOrEqualToAnchor:self.specificContentView.topAnchor
+        constraintLessThanOrEqualToAnchor:self.specificContentLayoutGuide
+                                              .topAnchor
                                  constant:-kScrollViewBottomInsets],
 
-    [self.specificContentView.bottomAnchor
-        constraintEqualToAnchor:scrollContentLayoutGuide.bottomAnchor],
-    [self.specificContentView.centerXAnchor
+    [self.specificContentLayoutGuide.bottomAnchor
+        constraintEqualToAnchor:scrollContentView.bottomAnchor],
+    [self.specificContentLayoutGuide.centerXAnchor
         constraintEqualToAnchor:self.view.centerXAnchor],
-    [self.specificContentView.widthAnchor
+    [self.specificContentLayoutGuide.widthAnchor
         constraintLessThanOrEqualToAnchor:scrollView.widthAnchor],
 
     // Constrain its height to at least the scroll view height, so that derived
     // VCs can pin UI elements just above the buttons.
-    [scrollContentLayoutGuide.topAnchor
-        constraintEqualToAnchor:scrollView.topAnchor],
-    [scrollContentLayoutGuide.bottomAnchor
+    [scrollContentView.topAnchor constraintEqualToAnchor:scrollView.topAnchor],
+    [scrollContentView.bottomAnchor
         constraintEqualToAnchor:scrollView.bottomAnchor],
-    [scrollContentLayoutGuide.heightAnchor
+    [scrollContentView.heightAnchor
         constraintGreaterThanOrEqualToAnchor:scrollView.heightAnchor],
   ]];
 
@@ -210,12 +216,11 @@
       .active = YES;
 
   if (self.topAlignedLayout) {
-    [stackView.topAnchor
-        constraintEqualToAnchor:scrollContentLayoutGuide.topAnchor]
+    [stackView.topAnchor constraintEqualToAnchor:scrollContentView.topAnchor]
         .active = YES;
   } else {
     [stackView.centerYAnchor
-        constraintEqualToAnchor:scrollContentLayoutGuide.centerYAnchor]
+        constraintEqualToAnchor:scrollContentView.centerYAnchor]
         .active = YES;
   }
 
diff --git a/ios/chrome/credential_provider_extension/ui/consent_view_controller.mm b/ios/chrome/credential_provider_extension/ui/consent_view_controller.mm
index 2c3b39f..d0c56582 100644
--- a/ios/chrome/credential_provider_extension/ui/consent_view_controller.mm
+++ b/ios/chrome/credential_provider_extension/ui/consent_view_controller.mm
@@ -87,7 +87,7 @@
   captionLabel.textAlignment = NSTextAlignmentCenter;
   captionLabel.font =
       [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote];
-  captionLabel.textColor = [UIColor colorNamed:kGrey600Color];
+  captionLabel.textColor = [UIColor colorNamed:kTextSecondaryColor];
   captionLabel.translatesAutoresizingMaskIntoConstraints = NO;
   captionLabel.adjustsFontForContentSizeCategory = YES;
   return captionLabel;
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 908905db..c000a8d 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 @@
-a09d2f378d0f4d2260761a8c77c15ef1a4b1856f
\ No newline at end of file
+a47f27d6a2771dbd8557d6112f5af54ac31b8f05
\ 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 cbf25322..b6bae159 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 @@
-ff141047bb2928195bf884ede9895300fadcac13
\ No newline at end of file
+8c11db9da0cb981e26aece834920c400a4354800
\ 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 7ebd86e..34df20e8 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 @@
-1d043260197d58e8ff96e91cae020e96362720a5
\ No newline at end of file
+555d594d6f557a201476ed6927877af560086f76
\ 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 08d5d894..6396c12a 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 @@
-20e59f72b4637b093516aa8ac10f4be4a41bf821
\ No newline at end of file
+803b689b6ed9217b26a48f06fd243c76d3a06da1
\ 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 63a912b..c58f383 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 @@
-c98bb464959094b3ea92f91bb07c4432961eb39b
\ No newline at end of file
+5ef5fa22ce1ecebad53f4b62998c7f91c2da65e4
\ 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 a16fc876..f9ada47a 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 @@
-bb1806a02eddc7026dab0a298606fdf4368675d3
\ No newline at end of file
+fb6e4ece640b174cdcc9e302e52bbaae6ba60452
\ 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 acce0ed..7c63749 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 @@
-7e5fd9c87619923884b1f1cc178c2b8acfa940d4
\ No newline at end of file
+08e685af6993439a65ef2ccc8d30ad860eaad17a
\ 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 6ed146a5..6578d21 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 @@
-cd9c06b2d2bbec949364da4d76e2b4146e6420e7
\ No newline at end of file
+e8b42bc927ddc698c1f61ca7d2f3844f33e1cfa0
\ 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 bb08db3..69f95da 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 @@
-c0a0497f53bc7bb55a2e766763ebe03758c6e7ef
\ No newline at end of file
+0d22c891e526892c917a083f7454b77b69681c1e
\ 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 09359b8..0d60816f 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 @@
-d557d5933ac1edb0967306d2dd63cde13d8f0896
\ No newline at end of file
+cd2642ea0ceacd10e25a3cf1a985326fe2993901
\ No newline at end of file
diff --git a/ios/public/provider/chrome/browser/follow/follow_provider.h b/ios/public/provider/chrome/browser/follow/follow_provider.h
index 778d440..cecc9696 100644
--- a/ios/public/provider/chrome/browser/follow/follow_provider.h
+++ b/ios/public/provider/chrome/browser/follow/follow_provider.h
@@ -19,15 +19,14 @@
   FollowProvider(const FollowProvider&) = delete;
   FollowProvider& operator=(const FollowProvider&) = delete;
 
-  // Returns YES if the website with |followSiteInfo| has been followed.
+  // Returns true if the website with |followSiteInfo| has been followed.
   virtual bool GetFollowStatus(FollowSiteInfo* followSiteInfo);
 
   // Returns a list of followed websites.
-  virtual NSMutableArray<FollowSiteInfo*>* GetFollowedChannels();
+  virtual NSArray<FollowSiteInfo*>* GetFollowedChannels();
 
-  // Updates the following status of |sites| to |status|.
-  virtual void updateFollowStatus(NSMutableArray<FollowSiteInfo*>* sites,
-                                  bool status);
+  // Updates the following status of |site| to |state|.
+  virtual void UpdateFollowStatus(FollowSiteInfo* site, bool state);
 };
 
 #endif  // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_FOLLOW_FOLLOW_PROVIDER_H_
diff --git a/ios/public/provider/chrome/browser/follow/follow_provider.mm b/ios/public/provider/chrome/browser/follow/follow_provider.mm
index 3c6d64c0..a158771 100644
--- a/ios/public/provider/chrome/browser/follow/follow_provider.mm
+++ b/ios/public/provider/chrome/browser/follow/follow_provider.mm
@@ -12,9 +12,8 @@
   return false;
 }
 
-NSMutableArray<FollowSiteInfo*>* FollowProvider::GetFollowedChannels() {
+NSArray<FollowSiteInfo*>* FollowProvider::GetFollowedChannels() {
   return nil;
 }
 
-void FollowProvider::updateFollowStatus(NSMutableArray<FollowSiteInfo*>* sites,
-                                        bool newStatus) {}
+void FollowProvider::UpdateFollowStatus(FollowSiteInfo* site, bool state) {}
diff --git a/ios/web/js_messaging/web_frame_impl.h b/ios/web/js_messaging/web_frame_impl.h
index 73c8edc..ff85ed2 100644
--- a/ios/web/js_messaging/web_frame_impl.h
+++ b/ios/web/js_messaging/web_frame_impl.h
@@ -68,6 +68,9 @@
       base::TimeDelta timeout) override;
 
   bool ExecuteJavaScript(const std::string& script) override;
+  bool ExecuteJavaScript(
+      const std::string& script,
+      base::OnceCallback<void(const base::Value*)> callback) override;
 
   // WebFrameContentWorldAPI:
   bool CallJavaScriptFunctionInContentWorld(
diff --git a/ios/web/js_messaging/web_frame_impl.mm b/ios/web/js_messaging/web_frame_impl.mm
index 4d42c2d..4c7e7ec 100644
--- a/ios/web/js_messaging/web_frame_impl.mm
+++ b/ios/web/js_messaging/web_frame_impl.mm
@@ -287,6 +287,43 @@
   return false;
 }
 
+bool WebFrameImpl::ExecuteJavaScript(
+    const std::string& script,
+    base::OnceCallback<void(const base::Value*)> callback) {
+  DCHECK(base::ios::IsRunningOnIOS14OrLater());
+  DCHECK(frame_info_);
+
+  if (!IsMainFrame()) {
+    return false;
+  }
+
+  NSString* ns_script = base::SysUTF8ToNSString(script);
+  // Because Objective-C blocks treat scoped-variables
+  // as const, we have to redefine the callback with the
+  // __block keyword to be able to run the callback inside
+  // the completion handler.
+  __block auto internal_callback = std::move(callback);
+  void (^completion_handler)(id, NSError*) = ^void(id value, NSError* error) {
+    if (error) {
+      DLOG(WARNING) << "Script execution of:"
+                    << base::SysNSStringToUTF16(ns_script)
+                    << "\nfailed with error: "
+                    << base::SysNSStringToUTF16(
+                           error.userInfo[NSLocalizedDescriptionKey]);
+    } else {
+      std::move(internal_callback).Run(ValueResultFromWKResult(value).get());
+    }
+  };
+
+  if (@available(iOS 14.0, *)) {
+    web::ExecuteJavaScript(frame_info_.webView, WKContentWorld.pageWorld,
+                           frame_info_, ns_script, completion_handler);
+    return true;
+  }
+
+  return false;
+}
+
 bool WebFrameImpl::ExecuteJavaScriptFunction(
     JavaScriptContentWorld* content_world,
     const std::string& name,
diff --git a/ios/web/js_messaging/web_frame_impl_unittest.mm b/ios/web/js_messaging/web_frame_impl_unittest.mm
index 21f0f34..15284e02 100644
--- a/ios/web/js_messaging/web_frame_impl_unittest.mm
+++ b/ios/web/js_messaging/web_frame_impl_unittest.mm
@@ -447,7 +447,7 @@
   EXPECT_EQ(last_script.length, 0ul);
 }
 
-// Tests that the WebFrame can execute arbitrary JavaScript.
+// Tests that the WebFrame can execute arbitrary JavaScript
 // if and only if it is a main frame.
 TEST_F(WebFrameImplTest, ExecuteJavaScript) {
   if (!base::ios::IsRunningOnIOS14OrLater()) {
@@ -475,4 +475,38 @@
   EXPECT_FALSE(web_frame2.ExecuteJavaScript(base::SysNSStringToUTF8(script)));
 }
 
+// Tests that the WebFrame can execute arbitrary JavaScript given
+// a callback if and only if it is a main frame.
+TEST_F(WebFrameImplTest, ExecuteJavaScriptWithCallback) {
+  if (!base::ios::IsRunningOnIOS14OrLater()) {
+    return;
+  }
+
+  FakeWebState fake_web_state;
+  GURL security_origin;
+
+  NSString* script = @"__gCrWeb = {};"
+                     @"__gCrWeb['fakeFunction'] = function() {"
+                     @"  return '10';"
+                     @"}";
+
+  WebFrameImpl web_frame([[WKFrameInfo alloc] init], kFrameId,
+                         /*is_main_frame=*/true, security_origin,
+                         &fake_web_state);
+
+  EXPECT_TRUE(
+      web_frame.ExecuteJavaScript(base::SysNSStringToUTF8(script),
+                                  base::BindOnce(^(const base::Value* value){
+                                  })));
+
+  WebFrameImpl web_frame2([[WKFrameInfo alloc] init], kFrameId,
+                          /*is_main_frame=*/false, security_origin,
+                          &fake_web_state);
+
+  EXPECT_FALSE(
+      web_frame2.ExecuteJavaScript(base::SysNSStringToUTF8(script),
+                                   base::BindOnce(^(const base::Value* value){
+                                   })));
+}
+
 }  // namespace web
diff --git a/ios/web/public/js_messaging/web_frame.h b/ios/web/public/js_messaging/web_frame.h
index 31ddc73..aa732d1 100644
--- a/ios/web/public/js_messaging/web_frame.h
+++ b/ios/web/public/js_messaging/web_frame.h
@@ -73,6 +73,13 @@
   // Executes the given |script| and returns whether the script was run.
   virtual bool ExecuteJavaScript(const std::string& script) = 0;
 
+  // Executes the given |script| and returns whether the script was run.
+  // If the script is successfully executed, |callback| is called with
+  // the result.
+  virtual bool ExecuteJavaScript(
+      const std::string& script,
+      base::OnceCallback<void(const base::Value*)> callback) = 0;
+
   // Returns the WebFrameInternal instance for this object.
   virtual WebFrameInternal* GetWebFrameInternal() = 0;
 
diff --git a/ios/web/test/fakes/fake_web_frame_impl.cc b/ios/web/test/fakes/fake_web_frame_impl.cc
index 2f9e320d..79fa95cc 100644
--- a/ios/web/test/fakes/fake_web_frame_impl.cc
+++ b/ios/web/test/fakes/fake_web_frame_impl.cc
@@ -149,6 +149,12 @@
   return false;
 }
 
+bool FakeWebFrameImpl::ExecuteJavaScript(
+    const std::string& script,
+    base::OnceCallback<void(const base::Value*)> callback) {
+  return false;
+}
+
 void FakeWebFrameImpl::AddJsResultForFunctionCall(
     base::Value* js_result,
     const std::string& function_name) {
diff --git a/ios/web/test/fakes/fake_web_frame_impl.h b/ios/web/test/fakes/fake_web_frame_impl.h
index 0d028845..702a374 100644
--- a/ios/web/test/fakes/fake_web_frame_impl.h
+++ b/ios/web/test/fakes/fake_web_frame_impl.h
@@ -42,6 +42,9 @@
       base::OnceCallback<void(const base::Value*)> callback,
       base::TimeDelta timeout) override;
   bool ExecuteJavaScript(const std::string& script) override;
+  bool ExecuteJavaScript(
+      const std::string& script,
+      base::OnceCallback<void(const base::Value*)> callback) override;
 
   // FakeWebFrame:
   std::string GetLastJavaScriptCall() const override;
diff --git a/mojo/public/tools/bindings/generators/mojom_js_generator.py b/mojo/public/tools/bindings/generators/mojom_js_generator.py
index 3769a77..f2ceecb 100644
--- a/mojo/public/tools/bindings/generators/mojom_js_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_js_generator.py
@@ -203,7 +203,7 @@
 }
 
 
-_SHARED_MODULE_PREFIX = 'chrome://resources/mojo'
+_SHARED_MODULE_PREFIX = 'chrome://resources/'
 
 
 def _GetWebUiModulePath(module):
diff --git a/net/cookies/canonical_cookie.cc b/net/cookies/canonical_cookie.cc
index 6e41e32..d0ee8ee6 100644
--- a/net/cookies/canonical_cookie.cc
+++ b/net/cookies/canonical_cookie.cc
@@ -978,7 +978,7 @@
       DCHECK(IsSameParty());
       status.AddExclusionReason(
           CookieInclusionStatus::EXCLUDE_SAMEPARTY_CROSS_PARTY_CONTEXT);
-      FALLTHROUGH;
+      [[fallthrough]];
     case CookieSamePartyStatus::kEnforceSamePartyInclude: {
       status.AddWarningReason(CookieInclusionStatus::WARN_TREATED_AS_SAMEPARTY);
       // Remove any SameSite exclusion reasons, since SameParty overrides
@@ -1200,7 +1200,7 @@
       DCHECK(IsSameParty());
       access_result.status.AddExclusionReason(
           CookieInclusionStatus::EXCLUDE_SAMEPARTY_CROSS_PARTY_CONTEXT);
-      FALLTHROUGH;
+      [[fallthrough]];
     case CookieSamePartyStatus::kEnforceSamePartyInclude: {
       DCHECK(IsSameParty());
       access_result.status.AddWarningReason(
diff --git a/net/der/parse_values.cc b/net/der/parse_values.cc
index b7656ea..a297c27 100644
--- a/net/der/parse_values.cc
+++ b/net/der/parse_values.cc
@@ -466,21 +466,23 @@
   if (in.Length() % 2 != 0)
     return false;
 
-  std::u16string in_16bit;
-  if (in.Length()) {
-    memcpy(base::WriteInto(&in_16bit, in.Length() / 2 + 1), in.UnsafeData(),
-           in.Length());
-  }
-  for (char16_t& c : in_16bit) {
+  out->clear();
+  std::vector<uint16_t> in_16bit(in.Length() / 2);
+  if (in.Length())
+    memcpy(in_16bit.data(), in.UnsafeData(), in.Length());
+  for (const uint16_t c : in_16bit) {
     // BMPString is UCS-2 in big-endian order.
-    c = base::NetToHost16(c);
+    uint32_t codepoint = base::NetToHost16(c);
 
     // BMPString only supports codepoints in the Basic Multilingual Plane;
-    // surrogates are not allowed.
-    if (CBU_IS_SURROGATE(c))
+    // surrogates are not allowed. CBU_IS_UNICODE_CHAR excludes the surrogate
+    // code points, among other invalid values.
+    if (!CBU_IS_UNICODE_CHAR(codepoint))
       return false;
+
+    base::WriteUnicodeCharacter(codepoint, out);
   }
-  return base::UTF16ToUTF8(in_16bit.data(), in_16bit.size(), out);
+  return true;
 }
 
 }  // namespace der
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc
index 1ba1520..72c7952 100644
--- a/net/quic/crypto/proof_verifier_chromium.cc
+++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -423,7 +423,7 @@
         break;
       case TransportSecurityState::PKPStatus::BYPASSED:
         verify_details_->pkp_bypassed = true;
-        FALLTHROUGH;
+        [[fallthrough]];
       case TransportSecurityState::PKPStatus::OK:
         // Do nothing.
         break;
diff --git a/sandbox/win/src/job.cc b/sandbox/win/src/job.cc
index 7ef429d8..d12a565 100644
--- a/sandbox/win/src/job.cc
+++ b/sandbox/win/src/job.cc
@@ -39,26 +39,26 @@
     case JOB_LOCKDOWN: {
       jeli.BasicLimitInformation.LimitFlags |=
           JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION;
-      FALLTHROUGH;
+      [[fallthrough]];
     }
     case JOB_RESTRICTED: {
       jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
       jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_READCLIPBOARD;
       jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES;
       jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_GLOBALATOMS;
-      FALLTHROUGH;
+      [[fallthrough]];
     }
     case JOB_LIMITED_USER: {
       jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DISPLAYSETTINGS;
       jeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
       jeli.BasicLimitInformation.ActiveProcessLimit = 1;
-      FALLTHROUGH;
+      [[fallthrough]];
     }
     case JOB_INTERACTIVE: {
       jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS;
       jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DESKTOP;
       jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_EXITWINDOWS;
-      FALLTHROUGH;
+      [[fallthrough]];
     }
     case JOB_UNPROTECTED: {
       if (memory_limit) {
diff --git a/sandbox/win/src/policy_low_level.cc b/sandbox/win/src/policy_low_level.cc
index 79ef57c..471d641 100644
--- a/sandbox/win/src/policy_low_level.cc
+++ b/sandbox/win/src/policy_low_level.cc
@@ -267,7 +267,7 @@
         if (L'?' == current_char[1]) {
           ++current_char;
         }
-        FALLTHROUGH;
+        [[fallthrough]];
       default:
         fragment += *current_char;
         last_char = kLastCharIsAlpha;
diff --git a/services/tracing/tracing_service_unittest.cc b/services/tracing/tracing_service_unittest.cc
index 3ecf9477..6d0b374 100644
--- a/services/tracing/tracing_service_unittest.cc
+++ b/services/tracing/tracing_service_unittest.cc
@@ -272,9 +272,9 @@
   wait_for_data_loop.Run();
   DCHECK(!tokenizer.has_more());
 
-  auto result = base::DictionaryValue::From(
-      base::Value::ToUniquePtrValue(*base::JSONReader::Read(json)));
-  EXPECT_TRUE(result->HasKey("traceEvents"));
+  absl::optional<base::Value> result = base::JSONReader::Read(json);
+  ASSERT_TRUE(result.has_value());
+  EXPECT_TRUE(result->FindKey("traceEvents"));
 }
 
 class CustomDataSource : public perfetto::DataSource<CustomDataSource> {
diff --git a/styleguide/c++/c++11.md b/styleguide/c++/c++11.md
index b063974..6147e37 100644
--- a/styleguide/c++/c++11.md
+++ b/styleguide/c++/c++11.md
@@ -405,6 +405,25 @@
 [Google Style Guide](https://google.github.io/styleguide/cppguide.html#CTAD).
 ***
 
+### Selection statements with initializer <sup>[allowed]</sup>
+
+```c++
+if (int a = Func(); a < 3) { ...
+switch (int a = Func(); a) { ...
+```
+
+**Description:** New versions of the if and switch statements which simplify
+common code patterns and help users keep scopes tight.
+
+**Documentation:**
+[if statement](https://en.cppreference.com/w/cpp/language/if),
+[switch statement](https://en.cppreference.com/w/cpp/language/switch)
+
+**Notes:**
+*** promo
+[@cxx discussion thread](https://groups.google.com/a/chromium.org/g/cxx/c/4GP43nftePE)
+***
+
 ## C++17 Allowed Library Features {#library-allowlist-17}
 
 The following C++17 language features are allowed in the Chromium codebase.
@@ -678,25 +697,6 @@
 None
 ***
 
-### Selection statements with initializer <sup>[tbd]</sup>
-
-```c++
-if (int a = Func(); a < 3) { ...
-switch (int a = Func(); a) { ...
-```
-
-**Description:** New versions of the if and switch statements which simplify
-common code patterns and help users keep scopes tight.
-
-**Documentation:**
-[if statement](https://en.cppreference.com/w/cpp/language/if),
-[switch statement](https://en.cppreference.com/w/cpp/language/switch)
-
-**Notes:**
-*** promo
-None
-***
-
 ### constexpr if <sup>[tbd]</sup>
 
 ```c++
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index 1769c1e8..0280fec 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -1713,7 +1713,7 @@
       {
         "args": [],
         "cros_board": "atlas",
-        "cros_img": "atlas-release/R99-14435.0.0",
+        "cros_img": "atlas-release/R99-14436.0.0",
         "name": "lacros_all_tast_tests_ATLAS_LKGM",
         "resultdb": {
           "enable": true,
@@ -1773,7 +1773,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R99-14435.0.0",
+        "cros_img": "eve-release/R99-14436.0.0",
         "name": "lacros_all_tast_tests_EVE_LKGM",
         "resultdb": {
           "enable": true,
@@ -1878,7 +1878,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R99-14435.0.0",
+        "cros_img": "kevin-release/R99-14436.0.0",
         "name": "lacros_all_tast_tests_KEVIN_LKGM",
         "resultdb": {
           "enable": true,
@@ -1893,7 +1893,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R99-14435.0.0",
+        "cros_img": "kevin-release/R99-14436.0.0",
         "name": "ozone_unittests_KEVIN_LKGM",
         "resultdb": {
           "enable": true,
@@ -1907,7 +1907,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R99-14435.0.0",
+        "cros_img": "kevin-release/R99-14436.0.0",
         "name": "viz_unittests_KEVIN_LKGM",
         "resultdb": {
           "enable": true,
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json
index 79b423c..08a6f9e 100644
--- a/testing/buildbot/internal.chromeos.fyi.json
+++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1096,7 +1096,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R99-14435.0.0",
+        "cros_img": "octopus-release/R99-14436.0.0",
         "name": "lacros_fyi_tast_tests_OCTOPUS_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1140,7 +1140,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R99-14435.0.0",
+        "cros_img": "octopus-release/R99-14436.0.0",
         "name": "ozone_unittests_OCTOPUS_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1188,7 +1188,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R99-14435.0.0",
+        "cros_img": "kevin-release/R99-14436.0.0",
         "name": "lacros_all_tast_tests_KEVIN_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && \"dep:lacros_unstable\")",
@@ -1199,7 +1199,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R99-14435.0.0",
+        "cros_img": "kevin-release/R99-14436.0.0",
         "name": "ozone_unittests_KEVIN_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1209,7 +1209,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R99-14435.0.0",
+        "cros_img": "kevin-release/R99-14436.0.0",
         "name": "viz_unittests_KEVIN_LKGM",
         "swarming": {},
         "test": "viz_unittests",
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 2170493..9d597a6 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -563,8 +563,8 @@
   'CROS_ATLAS_LKGM': {
     'skylab': {
       'cros_board': 'atlas',
-      'cros_chrome_version': '99.0.4801.0',
-      'cros_img': 'atlas-release/R99-14435.0.0',
+      'cros_chrome_version': '99.0.4803.0',
+      'cros_img': 'atlas-release/R99-14436.0.0',
     },
     'enabled': True,
     'identifier': 'ATLAS_LKGM',
@@ -599,8 +599,8 @@
   'CROS_EVE_LKGM': {
     'skylab': {
       'cros_board': 'eve',
-      'cros_chrome_version': '99.0.4801.0',
-      'cros_img': 'eve-release/R99-14435.0.0',
+      'cros_chrome_version': '99.0.4803.0',
+      'cros_img': 'eve-release/R99-14436.0.0',
     },
     'enabled': True,
     'identifier': 'EVE_LKGM',
@@ -635,8 +635,8 @@
   'CROS_KEVIN_LKGM': {
     'skylab': {
       'cros_board': 'kevin',
-      'cros_chrome_version': '99.0.4801.0',
-      'cros_img': 'kevin-release/R99-14435.0.0',
+      'cros_chrome_version': '99.0.4803.0',
+      'cros_img': 'kevin-release/R99-14436.0.0',
     },
     'enabled': True,
     'identifier': 'KEVIN_LKGM',
@@ -644,8 +644,8 @@
   'CROS_OCTOPUS_LKGM': {
     'skylab': {
       'cros_board': 'octopus',
-      'cros_chrome_version': '99.0.4801.0',
-      'cros_img': 'octopus-release/R99-14435.0.0',
+      'cros_chrome_version': '99.0.4803.0',
+      'cros_img': 'octopus-release/R99-14436.0.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_LKGM',
diff --git a/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc b/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc
index 80580b923..0f050d5 100644
--- a/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc
+++ b/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc
@@ -42,8 +42,8 @@
   // Intentionally leaked during fuzzing.
   v8::Platform* platform = v8::platform::NewDefaultPlatform().release();
   v8::V8::InitializePlatform(platform);
-#ifdef V8_VIRTUAL_MEMORY_CAGE
-  v8::V8::InitializeVirtualMemoryCage();
+#ifdef V8_SANDBOX
+  v8::V8::InitializeSandbox();
 #endif
   v8::V8::Initialize();
 
diff --git a/testing/libfuzzer/fuzzers/v8_fuzzer.cc b/testing/libfuzzer/fuzzers/v8_fuzzer.cc
index c28e4a2..f0e7557c 100644
--- a/testing/libfuzzer/fuzzers/v8_fuzzer.cc
+++ b/testing/libfuzzer/fuzzers/v8_fuzzer.cc
@@ -96,8 +96,8 @@
         v8::platform::InProcessStackDumping::kDisabled, nullptr);
 
     v8::V8::InitializePlatform(platform_.get());
-#ifdef V8_VIRTUAL_MEMORY_CAGE
-    v8::V8::InitializeVirtualMemoryCage();
+#ifdef V8_SANDBOX
+    v8::V8::InitializeSandbox();
 #endif
     v8::V8::Initialize();
     v8::Isolate::CreateParams create_params;
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 03c9e0b..b5aa00e 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -2348,23 +2348,6 @@
             ]
         }
     ],
-    "ClankStartupOptimizations": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "None",
-                    "enable_features": [
-                        "ElidePrioritizationOfPreNativeBootstrapTasks",
-                        "ElideTabPreloadAtStartup",
-                        "TreatBootstrapAsDefault"
-                    ]
-                }
-            ]
-        }
-    ],
     "ClientSideDetectionReferrerChain": [
         {
             "platforms": [
diff --git a/third_party/.gitignore b/third_party/.gitignore
index a9dc787..ade78a8 100644
--- a/third_party/.gitignore
+++ b/third_party/.gitignore
@@ -41,7 +41,6 @@
 /arcore-android-sdk/test-apks/arcore/*.apk
 /asan
 /barhopper
-/binutils
 /bison
 /boringssl/src
 /bouncycastle/lib/
diff --git a/third_party/abseil-cpp/README.chromium b/third_party/abseil-cpp/README.chromium
index 1b4c4b4b..c9db3784b 100644
--- a/third_party/abseil-cpp/README.chromium
+++ b/third_party/abseil-cpp/README.chromium
@@ -4,7 +4,7 @@
 License: Apache 2.0
 License File: LICENSE
 Version: 0
-Revision: f523d0dd69806d8057a898bb2595910558156aaa
+Revision: 04610889a913d29037205ca72e9d7fd7acc925fe
 Security Critical: yes
 
 Description:
diff --git a/third_party/abseil-cpp/absl/base/attributes.h b/third_party/abseil-cpp/absl/base/attributes.h
index e390782..f180cd7 100644
--- a/third_party/abseil-cpp/absl/base/attributes.h
+++ b/third_party/abseil-cpp/absl/base/attributes.h
@@ -136,9 +136,10 @@
 // for further information.
 // The MinGW compiler doesn't complain about the weak attribute until the link
 // step, presumably because Windows doesn't use ELF binaries.
-#if (ABSL_HAVE_ATTRIBUTE(weak) ||                   \
-     (defined(__GNUC__) && !defined(__clang__))) && \
-    (!defined(_WIN32) || __clang_major__ < 9) && !defined(__MINGW32__)
+#if (ABSL_HAVE_ATTRIBUTE(weak) ||                                        \
+     (defined(__GNUC__) && !defined(__clang__))) &&                      \
+    (!defined(_WIN32) || (defined(__clang__) && __clang_major__ < 9)) && \
+    !defined(__MINGW32__)
 #undef ABSL_ATTRIBUTE_WEAK
 #define ABSL_ATTRIBUTE_WEAK __attribute__((weak))
 #define ABSL_HAVE_ATTRIBUTE_WEAK 1
diff --git a/third_party/abseil-cpp/absl/base/internal/spinlock.h b/third_party/abseil-cpp/absl/base/internal/spinlock.h
index ac40daff..6d8d8ddd 100644
--- a/third_party/abseil-cpp/absl/base/internal/spinlock.h
+++ b/third_party/abseil-cpp/absl/base/internal/spinlock.h
@@ -120,6 +120,14 @@
     return (lockword_.load(std::memory_order_relaxed) & kSpinLockHeld) != 0;
   }
 
+  // Return immediately if this thread holds the SpinLock exclusively.
+  // Otherwise, report an error by crashing with a diagnostic.
+  inline void AssertHeld() const ABSL_ASSERT_EXCLUSIVE_LOCK() {
+    if (!IsHeld()) {
+      ABSL_RAW_LOG(FATAL, "thread should hold the lock on SpinLock");
+    }
+  }
+
  protected:
   // These should not be exported except for testing.
 
diff --git a/third_party/abseil-cpp/absl/container/internal/btree.h b/third_party/abseil-cpp/absl/container/internal/btree.h
index 29603379..26bd5e1 100644
--- a/third_party/abseil-cpp/absl/container/internal/btree.h
+++ b/third_party/abseil-cpp/absl/container/internal/btree.h
@@ -238,7 +238,7 @@
 
   using allocator_type = Alloc;
   using key_type = Key;
-  using size_type = std::make_signed<size_t>::type;
+  using size_type = size_t;
   using difference_type = ptrdiff_t;
 
   using slot_policy = SlotPolicy;
@@ -1497,7 +1497,7 @@
   set_finish(finish() + 1);
 
   if (!leaf() && finish() > i + 1) {
-    for (int j = finish(); j > i + 1; --j) {
+    for (field_type j = finish(); j > i + 1; --j) {
       set_child(j, child(j - 1));
     }
     clear_child(i + 1);
@@ -2124,7 +2124,7 @@
     return {0, begin};
   }
 
-  if (count == size_) {
+  if (static_cast<size_type>(count) == size_) {
     clear();
     return {count, this->end()};
   }
diff --git a/third_party/abseil-cpp/absl/synchronization/mutex.cc b/third_party/abseil-cpp/absl/synchronization/mutex.cc
index 376ea79..8f25e3d 100644
--- a/third_party/abseil-cpp/absl/synchronization/mutex.cc
+++ b/third_party/abseil-cpp/absl/synchronization/mutex.cc
@@ -1744,23 +1744,33 @@
   ABSL_TSAN_MUTEX_POST_UNLOCK(this, __tsan_mutex_read_lock);
 }
 
-// The zap_desig_waker bitmask is used to clear the designated waker flag in
-// the mutex if this thread has blocked, and therefore may be the designated
-// waker.
-static const intptr_t zap_desig_waker[] = {
-    ~static_cast<intptr_t>(0),  // not blocked
-    ~static_cast<intptr_t>(
-        kMuDesig)  // blocked; turn off the designated waker bit
-};
+// Clears the designated waker flag in the mutex if this thread has blocked, and
+// therefore may be the designated waker.
+static intptr_t ClearDesignatedWakerMask(int flag) {
+  assert(flag >= 0);
+  assert(flag <= 1);
+  switch (flag) {
+    case 0:  // not blocked
+      return ~static_cast<intptr_t>(0);
+    case 1:  // blocked; turn off the designated waker bit
+      return ~static_cast<intptr_t>(kMuDesig);
+  }
+  ABSL_INTERNAL_UNREACHABLE;
+}
 
-// The ignore_waiting_writers bitmask is used to ignore the existence
-// of waiting writers if a reader that has already blocked once
-// wakes up.
-static const intptr_t ignore_waiting_writers[] = {
-    ~static_cast<intptr_t>(0),  // not blocked
-    ~static_cast<intptr_t>(
-        kMuWrWait)  // blocked; pretend there are no waiting writers
-};
+// Conditionally ignores the existence of waiting writers if a reader that has
+// already blocked once wakes up.
+static intptr_t IgnoreWaitingWritersMask(int flag) {
+  assert(flag >= 0);
+  assert(flag <= 1);
+  switch (flag) {
+    case 0:  // not blocked
+      return ~static_cast<intptr_t>(0);
+    case 1:  // blocked; pretend there are no waiting writers
+      return ~static_cast<intptr_t>(kMuWrWait);
+  }
+  ABSL_INTERNAL_UNREACHABLE;
+}
 
 // Internal version of LockWhen().  See LockSlowWithDeadline()
 ABSL_ATTRIBUTE_NOINLINE void Mutex::LockSlow(MuHow how, const Condition *cond,
@@ -1852,8 +1862,10 @@
   bool unlock = false;
   if ((v & how->fast_need_zero) == 0 &&  // try fast acquire
       mu_.compare_exchange_strong(
-          v, (how->fast_or | (v & zap_desig_waker[flags & kMuHasBlocked])) +
-                 how->fast_add,
+          v,
+          (how->fast_or |
+           (v & ClearDesignatedWakerMask(flags & kMuHasBlocked))) +
+              how->fast_add,
           std::memory_order_acquire, std::memory_order_relaxed)) {
     if (cond == nullptr ||
         EvalConditionAnnotated(cond, this, true, false, how == kShared)) {
@@ -1927,9 +1939,10 @@
     CheckForMutexCorruption(v, "Lock");
     if ((v & waitp->how->slow_need_zero) == 0) {
       if (mu_.compare_exchange_strong(
-              v, (waitp->how->fast_or |
-                  (v & zap_desig_waker[flags & kMuHasBlocked])) +
-                     waitp->how->fast_add,
+              v,
+              (waitp->how->fast_or |
+               (v & ClearDesignatedWakerMask(flags & kMuHasBlocked))) +
+                  waitp->how->fast_add,
               std::memory_order_acquire, std::memory_order_relaxed)) {
         if (waitp->cond == nullptr ||
             EvalConditionAnnotated(waitp->cond, this, true, false,
@@ -1946,8 +1959,9 @@
       if ((v & (kMuSpin|kMuWait)) == 0) {   // no waiters
         // This thread tries to become the one and only waiter.
         PerThreadSynch *new_h = Enqueue(nullptr, waitp, v, flags);
-        intptr_t nv = (v & zap_desig_waker[flags & kMuHasBlocked] & kMuLow) |
-                      kMuWait;
+        intptr_t nv =
+            (v & ClearDesignatedWakerMask(flags & kMuHasBlocked) & kMuLow) |
+            kMuWait;
         ABSL_RAW_CHECK(new_h != nullptr, "Enqueue to empty list failed");
         if (waitp->how == kExclusive && (v & kMuReader) != 0) {
           nv |= kMuWrWait;
@@ -1961,12 +1975,13 @@
           waitp->thread->waitp = nullptr;
         }
       } else if ((v & waitp->how->slow_inc_need_zero &
-                  ignore_waiting_writers[flags & kMuHasBlocked]) == 0) {
+                  IgnoreWaitingWritersMask(flags & kMuHasBlocked)) == 0) {
         // This is a reader that needs to increment the reader count,
         // but the count is currently held in the last waiter.
         if (mu_.compare_exchange_strong(
-                v, (v & zap_desig_waker[flags & kMuHasBlocked]) | kMuSpin |
-                       kMuReader,
+                v,
+                (v & ClearDesignatedWakerMask(flags & kMuHasBlocked)) |
+                    kMuSpin | kMuReader,
                 std::memory_order_acquire, std::memory_order_relaxed)) {
           PerThreadSynch *h = GetPerThreadSynch(v);
           h->readers += kMuOne;       // inc reader count in waiter
@@ -1987,8 +2002,9 @@
         }
       } else if ((v & kMuSpin) == 0 &&  // attempt to queue ourselves
                  mu_.compare_exchange_strong(
-                     v, (v & zap_desig_waker[flags & kMuHasBlocked]) | kMuSpin |
-                            kMuWait,
+                     v,
+                     (v & ClearDesignatedWakerMask(flags & kMuHasBlocked)) |
+                         kMuSpin | kMuWait,
                      std::memory_order_acquire, std::memory_order_relaxed)) {
         PerThreadSynch *h = GetPerThreadSynch(v);
         PerThreadSynch *new_h = Enqueue(h, waitp, v, flags);
diff --git a/third_party/blink/public/strings/blink_accessibility_strings.grd b/third_party/blink/public/strings/blink_accessibility_strings.grd
index 3cfb0dc..3cf4d6d 100644
--- a/third_party/blink/public/strings/blink_accessibility_strings.grd
+++ b/third_party/blink/public/strings/blink_accessibility_strings.grd
@@ -40,7 +40,7 @@
       <output filename="blink_accessibility_strings_zh-HK.pak" type="data_package" lang="zh-HK" />
       <output filename="blink_accessibility_strings_zu.pak" type="data_package" lang="zu" />
     </if>
-    <if expr="chromeos or lacros">
+    <if expr="chromeos_ash or chromeos_lacros">
       <output filename="blink_accessibility_strings_is.pak" type="data_package" lang="is" />
     </if>
     <output filename="blink_accessibility_strings_am.pak" type="data_package" lang="am" />
diff --git a/third_party/blink/renderer/core/css/css_gradient_value.cc b/third_party/blink/renderer/core/css/css_gradient_value.cc
index b9bb4c0..79c5b8b 100644
--- a/third_party/blink/renderer/core/css/css_gradient_value.cc
+++ b/third_party/blink/renderer/core/css/css_gradient_value.cc
@@ -93,7 +93,7 @@
   return true;
 }
 
-}  // anonymous ns
+}  // namespace
 
 bool CSSGradientColorStop::IsCacheable() const {
   if (!IsHint()) {
@@ -510,7 +510,7 @@
   desc.r1 = adjusted_r1;
 }
 
-}  // anonymous ns
+}  // namespace
 
 void CSSGradientValue::AddStops(
     CSSGradientValue::GradientDesc& desc,
@@ -1079,6 +1079,22 @@
   return result;
 }
 
+static bool IsUsingCurrentColor(
+    const HeapVector<CSSGradientColorStop, 2>& stops) {
+  for (const CSSGradientColorStop& stop : stops) {
+    auto* identifier_value = DynamicTo<CSSIdentifierValue>(stop.color_.Get());
+    if (identifier_value &&
+        identifier_value->GetValueID() == CSSValueID::kCurrentcolor) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool CSSLinearGradientValue::IsUsingCurrentColor() const {
+  return blink::cssvalue::IsUsingCurrentColor(stops_);
+}
+
 void CSSLinearGradientValue::TraceAfterDispatch(blink::Visitor* visitor) const {
   visitor->Trace(first_x_);
   visitor->Trace(first_y_);
@@ -1479,6 +1495,10 @@
   return result;
 }
 
+bool CSSRadialGradientValue::IsUsingCurrentColor() const {
+  return blink::cssvalue::IsUsingCurrentColor(stops_);
+}
+
 void CSSRadialGradientValue::TraceAfterDispatch(blink::Visitor* visitor) const {
   visitor->Trace(first_x_);
   visitor->Trace(first_y_);
@@ -1559,6 +1579,10 @@
   return result;
 }
 
+bool CSSConicGradientValue::IsUsingCurrentColor() const {
+  return blink::cssvalue::IsUsingCurrentColor(stops_);
+}
+
 void CSSConicGradientValue::TraceAfterDispatch(blink::Visitor* visitor) const {
   visitor->Trace(x_);
   visitor->Trace(y_);
diff --git a/third_party/blink/renderer/core/css/css_gradient_value.h b/third_party/blink/renderer/core/css/css_gradient_value.h
index f3fb338..f3649c0 100644
--- a/third_party/blink/renderer/core/css/css_gradient_value.h
+++ b/third_party/blink/renderer/core/css/css_gradient_value.h
@@ -179,6 +179,8 @@
   CSSLinearGradientValue* ComputedCSSValue(const ComputedStyle&,
                                            bool allow_visited_style) const;
 
+  bool IsUsingCurrentColor() const;
+
   void TraceAfterDispatch(blink::Visitor*) const;
 
  private:
@@ -277,6 +279,8 @@
   CSSRadialGradientValue* ComputedCSSValue(const ComputedStyle&,
                                            bool allow_visited_style) const;
 
+  bool IsUsingCurrentColor() const;
+
   void TraceAfterDispatch(blink::Visitor*) const;
 
  private:
@@ -323,6 +327,8 @@
   CSSConicGradientValue* ComputedCSSValue(const ComputedStyle&,
                                           bool allow_visited_style) const;
 
+  bool IsUsingCurrentColor() const;
+
   void TraceAfterDispatch(blink::Visitor*) const;
 
  private:
diff --git a/third_party/blink/renderer/core/css/css_image_generator_value.cc b/third_party/blink/renderer/core/css/css_image_generator_value.cc
index b454d27a..99c865cc 100644
--- a/third_party/blink/renderer/core/css/css_image_generator_value.cc
+++ b/third_party/blink/renderer/core/css/css_image_generator_value.cc
@@ -170,6 +170,19 @@
   return false;
 }
 
+bool CSSImageGeneratorValue::IsUsingCurrentColor() const {
+  switch (GetClassType()) {
+    case kLinearGradientClass:
+      return To<CSSLinearGradientValue>(this)->IsUsingCurrentColor();
+    case kRadialGradientClass:
+      return To<CSSRadialGradientValue>(this)->IsUsingCurrentColor();
+    case kConicGradientClass:
+      return To<CSSConicGradientValue>(this)->IsUsingCurrentColor();
+    default:
+      return false;
+  }
+}
+
 bool CSSImageGeneratorValue::KnownToBeOpaque(const Document& document,
                                              const ComputedStyle& style) const {
   switch (GetClassType()) {
diff --git a/third_party/blink/renderer/core/css/css_image_generator_value.h b/third_party/blink/renderer/core/css/css_image_generator_value.h
index 80450d0..f2c7fd2 100644
--- a/third_party/blink/renderer/core/css/css_image_generator_value.h
+++ b/third_party/blink/renderer/core/css/css_image_generator_value.h
@@ -102,6 +102,7 @@
 
   bool IsUsingCustomProperty(const AtomicString& custom_property_name,
                              const Document&) const;
+  bool IsUsingCurrentColor() const;
 
   void TraceAfterDispatch(blink::Visitor*) const;
 
diff --git a/third_party/blink/renderer/core/css/style_recalc_change_test.cc b/third_party/blink/renderer/core/css/style_recalc_change_test.cc
index 765f9c5..1c4ddc48 100644
--- a/third_party/blink/renderer/core/css/style_recalc_change_test.cc
+++ b/third_party/blink/renderer/core/css/style_recalc_change_test.cc
@@ -251,4 +251,45 @@
   EXPECT_FALSE(affected->GetLayoutObject());
 }
 
+TEST_F(StyleRecalcChangeTestCQ, DontSkipLayoutRoot) {
+  GetDocument().body()->setInnerHTML(R"HTML(
+    <style>
+      #outer, #inner { container-type: size; }
+    </style>
+    <div id="outer">
+      <div id="inner">
+        <span id="inner_child"></span>
+      </div>
+      <span id="outer_child"></span>
+    </div>
+  )HTML",
+                                     ASSERT_NO_EXCEPTION);
+
+  UpdateAllLifecyclePhasesForTest();
+
+  Element* outer = GetDocument().getElementById("outer");
+  Element* inner = GetDocument().getElementById("inner");
+  Element* outer_child = GetDocument().getElementById("outer_child");
+  Element* inner_child = GetDocument().getElementById("inner_child");
+
+  inner_child->GetLayoutObject()->SetNeedsLayout("test");
+  outer_child->GetLayoutObject()->SetNeedsLayout("test");
+  inner->SetInlineStyleProperty(CSSPropertyID::kColor, "green");
+  outer->SetInlineStyleProperty(CSSPropertyID::kColor, "green");
+
+  EXPECT_TRUE(outer->GetLayoutObject()->NeedsLayout());
+  EXPECT_TRUE(inner->GetLayoutObject()->NeedsLayout());
+
+  GetDocument().UpdateStyleAndLayoutTreeForThisDocument();
+
+  ASSERT_TRUE(outer->GetContainerQueryData());
+  EXPECT_FALSE(outer->GetContainerQueryData()->SkippedStyleRecalc());
+
+  ASSERT_TRUE(inner->GetContainerQueryData());
+  EXPECT_FALSE(inner->GetContainerQueryData()->SkippedStyleRecalc());
+
+  // Should not fail DCHECKs.
+  UpdateAllLifecyclePhasesForTest();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 8360ec4..0f7173a1 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -2986,7 +2986,7 @@
     }
   } else {
     LayoutObject* layout_object = GetLayoutObject();
-    if (!layout_object || !layout_object->NeedsLayout() ||
+    if (!layout_object || !layout_object->SelfNeedsLayout() ||
         !layout_object->IsEligibleForSizeContainment()) {
       return false;
     }
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc
index eae5acd..e05fc87 100644
--- a/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -310,9 +310,7 @@
   if (!box.ShouldApplySizeContainment()) {
     for (auto* const option : select.GetOptionList()) {
       String text = option->TextIndentedToRespectGroupLabel();
-      const ComputedStyle* item_style =
-          option->GetComputedStyle() ? option->GetComputedStyle() : &style;
-      item_style->ApplyTextTransform(&text);
+      style.ApplyTextTransform(&text);
       // We apply SELECT's style, not OPTION's style because max_option_width is
       // used to determine intrinsic width of the menulist box.
       TextRun text_run = ConstructTextRun(style.GetFont(), text, style);
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc
index 99b9dbf..084a4c2 100644
--- a/third_party/blink/renderer/core/style/computed_style.cc
+++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -38,6 +38,7 @@
 #include "third_party/blink/renderer/core/css/css_primitive_value.h"
 #include "third_party/blink/renderer/core/css/css_property_equality.h"
 #include "third_party/blink/renderer/core/css/css_property_names.h"
+#include "third_party/blink/renderer/core/css/properties/computed_style_utils.h"
 #include "third_party/blink/renderer/core/css/properties/css_property.h"
 #include "third_party/blink/renderer/core/css/properties/longhand.h"
 #include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
@@ -911,6 +912,19 @@
     // Changes of background fill layers, such as images, may have
     // changed alpha.
     diff.SetHasAlphaChanged();
+    return;
+  }
+
+  // If the background image depends on currentColor
+  // (e.g., background-image: linear-gradient(currentColor, #fff)), and the
+  // color has changed, we need to recompute it even though VisuallyEqual()
+  // thinks the old and new background styles are identical.
+  if (BackgroundInternal().AnyLayerUsesCurrentColor() &&
+      (GetCurrentColor() != other.GetCurrentColor() ||
+       GetInternalVisitedCurrentColor() !=
+           other.GetInternalVisitedCurrentColor())) {
+    diff.SetNeedsPaintInvalidation();
+    diff.SetHasAlphaChanged();
   }
 }
 
@@ -1029,8 +1043,7 @@
 
   bool has_clip = HasOutOfFlowPosition() && !HasAutoClip();
   bool other_has_clip = other.HasOutOfFlowPosition() && !other.HasAutoClip();
-  if (has_clip != other_has_clip ||
-      (has_clip && Clip() != other.Clip()))
+  if (has_clip != other_has_clip || (has_clip && Clip() != other.Clip()))
     diff.SetCSSClipChanged();
 
   if (GetBlendMode() != other.GetBlendMode())
diff --git a/third_party/blink/renderer/core/style/fill_layer.cc b/third_party/blink/renderer/core/style/fill_layer.cc
index bd260e5..b3f9df5a 100644
--- a/third_party/blink/renderer/core/style/fill_layer.cc
+++ b/third_party/blink/renderer/core/style/fill_layer.cc
@@ -24,6 +24,7 @@
 #include "third_party/blink/renderer/core/css/css_value.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/core/style/data_equivalency.h"
+#include "third_party/blink/renderer/core/style/style_generated_image.h"
 #include "third_party/blink/renderer/platform/wtf/size_assertions.h"
 
 namespace blink {
@@ -356,6 +357,9 @@
       any_layer_has_image_ && Attachment() == EFillAttachment::kFixed;
   any_layer_has_default_attachment_image_ =
       any_layer_has_image_ && Attachment() == EFillAttachment::kScroll;
+  any_layer_uses_current_color_ =
+      (image_ && image_->IsGeneratedImage() &&
+       To<StyleGeneratedImage>(image_.Get())->IsUsingCurrentColor());
   cached_properties_computed_ = true;
 
   if (next_) {
@@ -370,6 +374,7 @@
         next_->any_layer_has_fixed_attachment_image_;
     any_layer_has_default_attachment_image_ |=
         next_->any_layer_has_default_attachment_image_;
+    any_layer_uses_current_color_ |= next_->any_layer_uses_current_color_;
   }
 }
 
@@ -425,7 +430,8 @@
     case kCompositeSourceOver:
       return GetBlendMode() == BlendMode::kNormal && ImageTilesLayer() &&
              ImageIsOpaque(document, style);
-    default: {}
+    default: {
+    }
   }
 
   return false;
diff --git a/third_party/blink/renderer/core/style/fill_layer.h b/third_party/blink/renderer/core/style/fill_layer.h
index 3b045ae..fae3def 100644
--- a/third_party/blink/renderer/core/style/fill_layer.h
+++ b/third_party/blink/renderer/core/style/fill_layer.h
@@ -252,6 +252,10 @@
     ComputeCachedPropertiesIfNeeded();
     return any_layer_has_default_attachment_image_;
   }
+  bool AnyLayerUsesCurrentColor() const {
+    ComputeCachedPropertiesIfNeeded();
+    return any_layer_uses_current_color_;
+  }
 
   static EFillAttachment InitialFillAttachment(EFillLayerType) {
     return EFillAttachment::kScroll;
@@ -352,6 +356,9 @@
   mutable unsigned any_layer_has_fixed_attachment_image_ : 1;
   // True if any of this or subsequent layers has default attachment image.
   mutable unsigned any_layer_has_default_attachment_image_ : 1;
+  // True if any of this or subsequent layers depends on the value of
+  // currentColor.
+  mutable unsigned any_layer_uses_current_color_ : 1;
   // Set once any of the above is accessed. The layers will be frozen
   // thereafter.
   mutable unsigned cached_properties_computed_ : 1;
diff --git a/third_party/blink/renderer/core/style/style_generated_image.cc b/third_party/blink/renderer/core/style/style_generated_image.cc
index 7eb878f..94f8ba0 100644
--- a/third_party/blink/renderer/core/style/style_generated_image.cc
+++ b/third_party/blink/renderer/core/style/style_generated_image.cc
@@ -82,6 +82,10 @@
                                                        document);
 }
 
+bool StyleGeneratedImage::IsUsingCurrentColor() const {
+  return image_generator_value_->IsUsingCurrentColor();
+}
+
 scoped_refptr<Image> StyleGeneratedImage::GetImage(
     const ImageResourceObserver& observer,
     const Document& document,
diff --git a/third_party/blink/renderer/core/style/style_generated_image.h b/third_party/blink/renderer/core/style/style_generated_image.h
index 847e0fb670..2689992 100644
--- a/third_party/blink/renderer/core/style/style_generated_image.h
+++ b/third_party/blink/renderer/core/style/style_generated_image.h
@@ -64,6 +64,7 @@
 
   bool IsUsingCustomProperty(const AtomicString& custom_property_name,
                              const Document&) const;
+  bool IsUsingCurrentColor() const;
 
   void Trace(Visitor*) const override;
 
diff --git a/third_party/blink/renderer/modules/payments/abort_test.cc b/third_party/blink/renderer/modules/payments/abort_test.cc
index b9ca0e39..26d6fb1 100644
--- a/third_party/blink/renderer/modules/payments/abort_test.cc
+++ b/third_party/blink/renderer/modules/payments/abort_test.cc
@@ -5,7 +5,9 @@
 // Tests for PaymentRequest::abort().
 
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/mock_function_scope.h"
 #include "third_party/blink/renderer/modules/payments/payment_request.h"
 #include "third_party/blink/renderer/modules/payments/payment_test_helper.h"
@@ -34,7 +36,11 @@
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
+
   request->abort(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
 
   request->abort(scope.GetScriptState(), scope.GetExceptionState());
@@ -50,6 +56,9 @@
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
 
   request->abort(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
@@ -64,6 +73,9 @@
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
 
   request->abort(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
@@ -81,7 +93,11 @@
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
+
   request->abort(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
   static_cast<payments::mojom::blink::PaymentRequestClient*>(request)->OnAbort(
       false);
@@ -99,6 +115,8 @@
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
   request->abort(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
diff --git a/third_party/blink/renderer/modules/payments/complete_test.cc b/third_party/blink/renderer/modules/payments/complete_test.cc
index 9624f75..9801adb5 100644
--- a/third_party/blink/renderer/modules/payments/complete_test.cc
+++ b/third_party/blink/renderer/modules/payments/complete_test.cc
@@ -5,7 +5,9 @@
 // Tests for PaymentRequest::complete().
 
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/mock_function_scope.h"
 #include "third_party/blink/renderer/modules/payments/payment_request.h"
 #include "third_party/blink/renderer/modules/payments/payment_test_helper.h"
@@ -19,6 +21,9 @@
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
   static_cast<payments::mojom::blink::PaymentRequestClient*>(request)
       ->OnPaymentResponse(BuildPaymentResponseForTest());
@@ -39,6 +44,9 @@
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
   static_cast<payments::mojom::blink::PaymentRequestClient*>(request)
       ->OnPaymentResponse(BuildPaymentResponseForTest());
@@ -59,6 +67,9 @@
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
   static_cast<payments::mojom::blink::PaymentRequestClient*>(request)
       ->OnPaymentResponse(BuildPaymentResponseForTest());
@@ -81,6 +92,9 @@
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
   static_cast<payments::mojom::blink::PaymentRequestClient*>(request)
       ->OnPaymentResponse(BuildPaymentResponseForTest());
@@ -101,6 +115,9 @@
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
   static_cast<payments::mojom::blink::PaymentRequestClient*>(request)
       ->OnPaymentResponse(BuildPaymentResponseForTest());
@@ -121,6 +138,9 @@
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectCall(), funcs.ExpectNoCall());
   static_cast<payments::mojom::blink::PaymentRequestClient*>(request)
@@ -145,6 +165,9 @@
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectCall(), funcs.ExpectNoCall());
   static_cast<payments::mojom::blink::PaymentRequestClient*>(request)
diff --git a/third_party/blink/renderer/modules/payments/on_payment_response_test.cc b/third_party/blink/renderer/modules/payments/on_payment_response_test.cc
index a7435f4..e93f322f 100644
--- a/third_party/blink/renderer/modules/payments/on_payment_response_test.cc
+++ b/third_party/blink/renderer/modules/payments/on_payment_response_test.cc
@@ -7,9 +7,11 @@
 #include <utility>
 
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_function.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_payment_response.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/mock_function_scope.h"
 #include "third_party/blink/renderer/modules/payments/payment_address.h"
 #include "third_party/blink/renderer/modules/payments/payment_request.h"
@@ -34,6 +36,8 @@
   response->shipping_address = payments::mojom::blink::PaymentAddress::New();
   response->shipping_address->country = "US";
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -55,6 +59,8 @@
       BuildPaymentResponseForTest();
   response->shipping_option = "standardShipping";
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -75,6 +81,8 @@
   payments::mojom::blink::PaymentResponsePtr response =
       BuildPaymentResponseForTest();
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -95,6 +103,8 @@
   payments::mojom::blink::PaymentResponsePtr response =
       BuildPaymentResponseForTest();
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -115,6 +125,8 @@
   payments::mojom::blink::PaymentResponsePtr response =
       BuildPaymentResponseForTest();
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -138,6 +150,8 @@
   response->shipping_address = payments::mojom::blink::PaymentAddress::New();
   response->shipping_address->country = "US";
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -160,6 +174,8 @@
   response->shipping_option = "standardShipping";
   response->shipping_address = payments::mojom::blink::PaymentAddress::New();
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -181,6 +197,8 @@
       BuildPaymentResponseForTest();
   response->payer->name = "";
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -202,6 +220,8 @@
       BuildPaymentResponseForTest();
   response->payer->email = "";
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -223,6 +243,8 @@
       BuildPaymentResponseForTest();
   response->payer->phone = "";
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -245,6 +267,8 @@
   response->shipping_address = payments::mojom::blink::PaymentAddress::New();
   response->shipping_address->country = "US";
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -266,6 +290,8 @@
       BuildPaymentResponseForTest();
   response->shipping_option = "";
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -287,6 +313,8 @@
       BuildPaymentResponseForTest();
   response->payer->name = "";
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -308,6 +336,8 @@
       BuildPaymentResponseForTest();
   response->payer->email = "";
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -329,6 +359,8 @@
       BuildPaymentResponseForTest();
   response->payer->phone = "";
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -352,6 +384,8 @@
   response->shipping_address = payments::mojom::blink::PaymentAddress::New();
   response->shipping_address->country = "Atlantis";
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -390,6 +424,9 @@
   response->shipping_option = "standardShipping";
   response->shipping_address = payments::mojom::blink::PaymentAddress::New();
   response->shipping_address->country = "US";
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   ScriptValue out_value;
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(MakeGarbageCollected<NewScriptFunction>(
@@ -421,6 +458,9 @@
       BuildPaymentResponseForTest();
   response->payer = payments::mojom::blink::PayerDetail::New();
   response->payer->name = "Jon Doe";
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   ScriptValue out_value;
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(MakeGarbageCollected<NewScriptFunction>(
@@ -451,6 +491,9 @@
   payments::mojom::blink::PaymentResponsePtr response =
       BuildPaymentResponseForTest();
   response->payer->email = "abc@gmail.com";
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   ScriptValue out_value;
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(MakeGarbageCollected<NewScriptFunction>(
@@ -482,6 +525,8 @@
       BuildPaymentResponseForTest();
   response->payer->phone = "0123";
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   ScriptValue out_value;
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(MakeGarbageCollected<NewScriptFunction>(
@@ -509,6 +554,9 @@
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), options, ASSERT_NO_EXCEPTION);
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   ScriptValue out_value;
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(MakeGarbageCollected<NewScriptFunction>(
@@ -529,7 +577,7 @@
 
 // If the merchant does not request a phone number, the resolved show() promise
 // should contain null phone number.
-TEST(OnPaymentResponseTest, PhoneNotRequred) {
+TEST(OnPaymentResponseTest, PhoneNotRequired) {
   PaymentRequestV8TestingScope scope;
   MockFunctionScope funcs(scope.GetScriptState());
   PaymentOptions* options = PaymentOptions::Create();
@@ -540,6 +588,9 @@
   payments::mojom::blink::PaymentResponsePtr response =
       BuildPaymentResponseForTest();
   response->payer->phone = String();
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   ScriptValue out_value;
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(MakeGarbageCollected<NewScriptFunction>(
@@ -570,6 +621,9 @@
   payments::mojom::blink::PaymentResponsePtr response =
       BuildPaymentResponseForTest();
   response->payer->name = String();
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   ScriptValue out_value;
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(MakeGarbageCollected<NewScriptFunction>(
@@ -600,6 +654,9 @@
   payments::mojom::blink::PaymentResponsePtr response =
       BuildPaymentResponseForTest();
   response->payer->email = String();
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   ScriptValue out_value;
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(MakeGarbageCollected<NewScriptFunction>(
diff --git a/third_party/blink/renderer/modules/payments/payment_request_for_invalid_origin_or_ssl_test.cc b/third_party/blink/renderer/modules/payments/payment_request_for_invalid_origin_or_ssl_test.cc
index f531ab6..cd517ff 100644
--- a/third_party/blink/renderer/modules/payments/payment_request_for_invalid_origin_or_ssl_test.cc
+++ b/third_party/blink/renderer/modules/payments/payment_request_for_invalid_origin_or_ssl_test.cc
@@ -3,9 +3,11 @@
 // found in the LICENSE file.
 
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
 #include "third_party/blink/public/mojom/payments/payment_request.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/modules/payments/payment_request.h"
 #include "third_party/blink/renderer/modules/payments/payment_test_helper.h"
 #include "third_party/blink/renderer/platform/bindings/exception_code.h"
@@ -105,6 +107,8 @@
        ShowIsRejected_WhenShowBeforeIdle) {
   PaymentRequestV8TestingScope scope;
   PaymentRequest* request = CreatePaymentRequest(scope);
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   ScriptPromise promise =
       request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
   // PaymentRequest.OnError() runs in this idle.
@@ -121,6 +125,8 @@
   // PaymentRequest.OnError() runs in this idle.
   platform_->RunUntilIdle();
 
+  // The show() will be rejected before user activation is checked, so there is
+  // no need to trigger user-activation here.
   ScriptPromise promise =
       request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
   EXPECT_EQ("NotSupportedError: mock error message",
@@ -134,6 +140,8 @@
   // PaymentRequest.OnError() runs in this idle.
   platform_->RunUntilIdle();
 
+  // The show()s will be rejected before user activation is checked, so there is
+  // no need to trigger user-activation here.
   ScriptPromise promise1 =
       request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
   EXPECT_EQ("NotSupportedError: mock error message",
diff --git a/third_party/blink/renderer/modules/payments/payment_request_test.cc b/third_party/blink/renderer/modules/payments/payment_request_test.cc
index 0c69487..4fb21a8 100644
--- a/third_party/blink/renderer/modules/payments/payment_request_test.cc
+++ b/third_party/blink/renderer/modules/payments/payment_request_test.cc
@@ -256,6 +256,8 @@
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -270,6 +272,8 @@
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectNoCall());
 
@@ -283,8 +287,12 @@
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
 
+  // The second show() call will be rejected before user activation is checked,
+  // so there is no need to re-trigger user-activation here.
   request->show(scope.GetScriptState(), scope.GetExceptionState());
   EXPECT_EQ(scope.GetExceptionState().Code(),
             ToExceptionCode(DOMExceptionCode::kInvalidStateError));
@@ -296,11 +304,16 @@
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
   request->abort(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
   static_cast<payments::mojom::blink::PaymentRequestClient*>(request)->OnAbort(
       true);
 
+  // The second show() call will be rejected before user activation is checked,
+  // so there is no need to re-trigger user-activation here.
   request->show(scope.GetScriptState(), scope.GetExceptionState());
   EXPECT_EQ(scope.GetExceptionState().Code(),
             ToExceptionCode(DOMExceptionCode::kInvalidStateError));
@@ -348,6 +361,8 @@
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   String error_message;
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall(&error_message));
@@ -368,6 +383,8 @@
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   String error_message;
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall(&error_message));
@@ -387,6 +404,8 @@
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   String error_message;
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall(&error_message));
@@ -405,6 +424,9 @@
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectCall(), funcs.ExpectNoCall());
   static_cast<payments::mojom::blink::PaymentRequestClient*>(request)
@@ -421,6 +443,8 @@
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -437,6 +461,8 @@
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall());
 
@@ -461,8 +487,12 @@
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(), details,
       options, ASSERT_NO_EXCEPTION);
   EXPECT_TRUE(request->shippingOption().IsNull());
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectNoCall());
+
   static_cast<payments::mojom::blink::PaymentRequestClient*>(request)
       ->OnShippingAddressChange(BuildPaymentAddressForTest());
   String detail_with_shipping_options =
@@ -502,8 +532,11 @@
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), options, ASSERT_NO_EXCEPTION);
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectNoCall());
+
   String detail =
       "{\"total\": {\"label\": \"Total\", \"amount\": {\"currency\": \"USD\", "
       "\"value\": \"5.00\"}},"
@@ -529,10 +562,13 @@
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), options, ASSERT_NO_EXCEPTION);
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectNoCall());
   static_cast<payments::mojom::blink::PaymentRequestClient*>(request)
       ->OnShippingAddressChange(BuildPaymentAddressForTest());
+
   String detail =
       "{\"total\": {\"label\": \"Total\", \"amount\": {\"currency\": \"USD\", "
       "\"value\": \"5.00\"}},"
@@ -557,6 +593,8 @@
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   request->show(scope.GetScriptState(), ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectNoCall());
   String detail_with_error_msg =
@@ -638,6 +676,8 @@
       ExecutionContext::From(script_state), method_data,
       BuildPaymentDetailsInitForTest(), ASSERT_NO_EXCEPTION);
   request->setOnpaymentmethodchange(page_deleter);
+  LocalFrame::NotifyUserActivation(
+      &frame, mojom::UserActivationNotificationType::kTest);
   request->show(script_state, ASSERT_NO_EXCEPTION)
       .Then(funcs.ExpectNoCall(), funcs.ExpectNoCall());
 
diff --git a/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc b/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc
index b1e2f47..e0bd03b 100644
--- a/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc
+++ b/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc
@@ -8,9 +8,11 @@
 
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
 #include "third_party/blink/renderer/core/event_type_names.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/mock_function_scope.h"
 #include "third_party/blink/renderer/modules/payments/payment_request.h"
 #include "third_party/blink/renderer/modules/payments/payment_request_delegate.h"
@@ -145,6 +147,8 @@
   event->SetTrusted(true);
   EXPECT_FALSE(scope.GetExceptionState().HadException());
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   String error_message;
   request->show(scope.GetScriptState(), scope.GetExceptionState())
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall(&error_message));
@@ -182,6 +186,8 @@
   event->SetPaymentRequest(request);
   EXPECT_FALSE(scope.GetExceptionState().HadException());
 
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   String error_message;
   request->show(scope.GetScriptState(), scope.GetExceptionState())
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall(&error_message));
@@ -219,6 +225,9 @@
   event->SetTrusted(true);
   event->SetPaymentRequest(request);
   event->SetEventPhase(Event::kCapturingPhase);
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   String error_message;
   request->show(scope.GetScriptState(), scope.GetExceptionState())
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall(&error_message));
@@ -253,6 +262,9 @@
   event->SetTrusted(true);
   event->SetPaymentRequest(request);
   event->SetEventPhase(Event::kCapturingPhase);
+
+  LocalFrame::NotifyUserActivation(
+      &scope.GetFrame(), mojom::UserActivationNotificationType::kTest);
   String error_message;
   request->show(scope.GetScriptState(), scope.GetExceptionState())
       .Then(funcs.ExpectNoCall(), funcs.ExpectCall(&error_message));
diff --git a/third_party/blink/tools/blinkpy/w3c/test_importer.py b/third_party/blink/tools/blinkpy/w3c/test_importer.py
index 5bee21d..0fa8653 100644
--- a/third_party/blink/tools/blinkpy/w3c/test_importer.py
+++ b/third_party/blink/tools/blinkpy/w3c/test_importer.py
@@ -605,7 +605,17 @@
         # Move any No-Export tag to the end of the description.
         description = description.replace('No-Export: true', '')
         description = description.replace('\n\n\n\n', '\n\n')
-        description += 'No-Export: true'
+        description += 'No-Export: true\n'
+
+        # Add the wptrunner MVP tryjobs as blocking trybots, to catch any test
+        # changes or infrastructure changes from upstream.
+        #
+        # If this starts blocking the importer unnecessarily, revert
+        # https://chromium-review.googlesource.com/c/chromium/src/+/2451504
+        description += (
+            'Cq-Include-Trybots: luci.chromium.try:linux-wpt-identity-fyi-rel,'
+            'linux-wpt-input-fyi-rel')
+
         return description
 
     @staticmethod
diff --git a/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py b/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
index abfff2c..d15abe64 100644
--- a/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
+++ b/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
@@ -431,7 +431,10 @@
             'https://chromium.googlesource.com'
             '/chromium/src/+/main/docs/testing/web_platform_tests.md\n\n'
             'NOAUTOREVERT=true\n'
-            'No-Export: true')
+            'No-Export: true\n'
+            'Cq-Include-Trybots: luci.chromium.try:linux-wpt-identity-fyi-rel,'
+            'linux-wpt-input-fyi-rel')
+        print(host.executive.calls)
         self.assertEqual(host.executive.calls,
                          [MANIFEST_INSTALL_CMD] +
                          [['git', 'log', '-1', '--format=%B']])
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 2be60e5..3a494ca 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2965,6 +2965,7 @@
 crbug.com/626703 [ Mac11 ] external/wpt/css/css-flexbox/abspos/flex-abspos-staticpos-align-self-006.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-022.html [ Failure Crash ]
 crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-dotted-001.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-dotted-002.html [ Failure ]
 crbug.com/626703 [ Mac11-arm64 ] external/wpt/fetch/private-network-access/fetch.https.window.html?include=from-treat-as-public [ Timeout ]
@@ -5967,16 +5968,10 @@
 crbug.com/1043675 [ Win ] external/wpt/css/filter-effects/css-filters-animation-opacity.html [ Failure ]
 crbug.com/1043675 [ Win ] svg/custom/svg-root-with-opacity.html [ Failure ]
 
-# Required to land DevTools change
-crbug.com/106759 http/tests/devtools/command-line-api-inspect.js [ Failure Pass ]
-crbug.com/106759 http/tests/devtools/sources/debugger-console/debugger-command-line-api.js [ Failure Pass ]
-
 crbug.com/989665 [ Mac ] external/wpt/resource-timing/resource_timing_buffer_full_eventually.html [ Crash Pass ]
 crbug.com/989665 [ Linux ] virtual/plz-dedicated-worker/external/wpt/resource-timing/resource_timing_buffer_full_eventually.html [ Crash Pass ]
 
 # Sheriff 2020-01-23
-crbug.com/1044505 http/tests/devtools/tracing-session-id.js [ Failure Pass Skip Timeout ]
-
 crbug.com/1046784 http/tests/devtools/oopif/oopif-storage.js [ Failure Pass ]
 crbug.com/1046784 http/tests/inspector-protocol/service-worker/target-reloaded-after-crash.js [ Failure Pass Timeout ]
 
@@ -6621,9 +6616,6 @@
 
 # DevTools roll
 crbug.com/1050549 http/tests/devtools/console/console-correct-suggestions.js [ Failure Pass ]
-crbug.com/1016266 http/tests/devtools/security/interstitial-sidebar.js [ Failure Pass ]
-crbug.com/1016266 http/tests/devtools/security/mixed-content-sidebar.js [ Failure Pass ]
-crbug.com/1016266 http/tests/devtools/console/console-format-classes.js [ Failure Pass ]
 
 # Flaky test
 crbug.com/1173439 http/tests/devtools/service-workers/service-worker-manager.js [ Pass Skip Timeout ]
@@ -7988,6 +7980,5 @@
 crbug.com/1280736 [ Win10.20h2 ] http/tests/inspector-protocol/network/blocked-setcookie-same-site-strict.js [ Pass Timeout ]
 crbug.com/1280736 [ Win10.20h2 ] http/tests/inspector-protocol/network/blocked-setcookie-same-site-lax.js [ Pass Timeout ]
 
-# Sheriff 2022-01-03
-crbug.com/1283865 [ Mac11 ] external/wpt/webmessaging/without-ports/020.html [ Failure Pass ]
-
+# Sheriff 2022-01-04
+crbug.com/1283865 external/wpt/webmessaging/without-ports/020.html [ Failure Pass ]
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 bb8cbcf..ef7df5b 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
@@ -71532,6 +71532,58 @@
        {}
       ]
      ],
+     "background-image-gradient-currentcolor-conic-repaint.html": [
+      "cbd524615f52086c81b7d00e56a7ed11980aa292",
+      [
+       null,
+       [
+        [
+         "/css/css-backgrounds/background-image-gradient-currentcolor-conic-repaint-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "background-image-gradient-currentcolor-linear-repaint.html": [
+      "1ad63ccef6772ca01b2ccdfba2faabb5b0db491c",
+      [
+       null,
+       [
+        [
+         "/css/css-backgrounds/background-image-gradient-currentcolor-linear-repaint-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "background-image-gradient-currentcolor-radial-repaint.html": [
+      "3182f343cfbf17caaedb1a00179fb002a9ff9f74",
+      [
+       null,
+       [
+        [
+         "/css/css-backgrounds/background-image-gradient-currentcolor-radial-repaint-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "background-image-gradient-currentcolor-visited.html": [
+      "65467b5ebae3f42e3dd5e0a75a4d695b90751697",
+      [
+       null,
+       [
+        [
+         "/css/css-backgrounds/background-image-gradient-currentcolor-visited-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "background-image-large-with-auto.html": [
       "a5e487b3e12125d25416da4461253ffc4d9b36ea",
       [
@@ -213846,6 +213898,19 @@
          {}
         ]
        ],
+       "select-intrinsic-text-transform.html": [
+        "1026e29977bfbc1ccc24bd2597743c40fb7eb4c3",
+        [
+         null,
+         [
+          [
+           "/html/rendering/replaced-elements/the-select-element/select-intrinsic-text-transform-ref.html",
+           "=="
+          ]
+         ],
+         {}
+        ]
+       ],
        "select-multiple-re-add-option-via-document-fragment.html": [
         "844f05639c9ce1812071903866a751cf7396431a",
         [
@@ -239898,6 +239963,22 @@
       "f52cd963ad25238bafc2081b7024aa5375614f5a",
       []
      ],
+     "background-image-gradient-currentcolor-conic-repaint-ref.html": [
+      "32158493df0409621ee8150f517eeed6119f8ca7",
+      []
+     ],
+     "background-image-gradient-currentcolor-linear-repaint-ref.html": [
+      "9a534e3b4600d3bfcab26adfcb4029250deb01a8",
+      []
+     ],
+     "background-image-gradient-currentcolor-radial-repaint-ref.html": [
+      "45ff24dfeebdb711952ccb53d60550654c9b7d01",
+      []
+     ],
+     "background-image-gradient-currentcolor-visited-ref.html": [
+      "43e0d1c0652dd9549416c1e4442e2d426a059289",
+      []
+     ],
      "background-margin-iframe-root-ref.html": [
       "e7f00b00e8c1229592f8dde05b5252d91e0ebff2",
       []
@@ -293284,6 +293365,10 @@
         "31ba23a5cf86f161b1204ea3f4c9fef4585af909",
         []
        ],
+       "select-intrinsic-text-transform-ref.html": [
+        "18e272ba10d3c319c06cdb669e5f7a535946d024",
+        []
+       ],
        "select-multiple-re-add-option-via-document-fragment-ref.html": [
         "cb66ddaaaf369479e59f6092d04633a2dc2baf6c",
         []
@@ -453973,7 +454058,7 @@
         ]
        ],
        "inert-inlines.html": [
-        "8acdb570fc602e3cec63dc1ec207b376f994bb8b",
+        "5ee4113985fc827608c180cbeb25013c1c83e1e0",
         [
          null,
          {
@@ -453991,7 +454076,7 @@
         ]
        ],
        "inert-node-is-uneditable.html": [
-        "393e5e10b52e37749d741aab3ab56120aa32ce44",
+        "9141a383b01ad0536404c926f5cb81ed88ddc086",
         [
          null,
          {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-conic-repaint-ref.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-conic-repaint-ref.html
new file mode 100644
index 0000000..3215849
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-conic-repaint-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test Reference</title>
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<p>There should be a square with a white-to-green gradient and some text below.</p>
+<div style="color: green">
+  <div style="width: 100px; height: 100px; background: conic-gradient(white, green)">This text should be green</div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-conic-repaint.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-conic-repaint.html
new file mode 100644
index 0000000..cbd52461
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-conic-repaint.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>CSS Backgrounds and Borders: Repaint gradient on currentColor change</title>
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<link rel="match" href="background-image-gradient-currentcolor-conic-repaint-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-images-3/#color-stop-syntax">
+<style>
+  #outer {
+    color: red;
+  }
+  #inner {
+    width: 100px;
+    height: 100px;
+    background: conic-gradient(white, currentColor);
+  }
+</style>
+<p>There should be a square with a white-to-green gradient and some text below.</p>
+<div id="outer">
+  <div id="inner">This text should be green</div>
+</div>
+<script>
+  requestAnimationFrame(function(){
+    requestAnimationFrame(function(){
+      outer.style.color = "green";
+      document.documentElement.classList.remove("reftest-wait");
+    });
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-linear-repaint-ref.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-linear-repaint-ref.html
new file mode 100644
index 0000000..9a534e3
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-linear-repaint-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test Reference</title>
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<p>There should be a square with a white-to-green gradient and some text below.</p>
+<div style="color: green">
+  <div style="width: 100px; height: 100px; background: linear-gradient(white, green)">This text should be green</div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-linear-repaint.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-linear-repaint.html
new file mode 100644
index 0000000..1ad63ccef
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-linear-repaint.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>CSS Backgrounds and Borders: Repaint gradient on currentColor change</title>
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<link rel="match" href="background-image-gradient-currentcolor-linear-repaint-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-images-3/#color-stop-syntax">
+<style>
+  #outer {
+    color: red;
+  }
+  #inner {
+    width: 100px;
+    height: 100px;
+    background: linear-gradient(white, currentColor);
+  }
+</style>
+<p>There should be a square with a white-to-green gradient and some text below.</p>
+<div id="outer">
+  <div id="inner">This text should be green</div>
+</div>
+<script>
+  requestAnimationFrame(function(){
+    requestAnimationFrame(function(){
+      outer.style.color = "green";
+      document.documentElement.classList.remove("reftest-wait");
+    });
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-radial-repaint-ref.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-radial-repaint-ref.html
new file mode 100644
index 0000000..45ff24d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-radial-repaint-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test Reference</title>
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<p>There should be a square with a white-to-green gradient and some text below.</p>
+<div style="color: green">
+  <div style="width: 100px; height: 100px; background: radial-gradient(white, green)">This text should be green</div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-radial-repaint.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-radial-repaint.html
new file mode 100644
index 0000000..3182f34
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-radial-repaint.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>CSS Backgrounds and Borders: Repaint gradient on currentColor change</title>
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<link rel="match" href="background-image-gradient-currentcolor-radial-repaint-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-images-3/#color-stop-syntax">
+<style>
+  #outer {
+    color: red;
+  }
+  #inner {
+    width: 100px;
+    height: 100px;
+    background: radial-gradient(white, currentColor);
+  }
+</style>
+<p>There should be a square with a white-to-green gradient and some text below.</p>
+<div id="outer">
+  <div id="inner">This text should be green</div>
+</div>
+<script>
+  requestAnimationFrame(function(){
+    requestAnimationFrame(function(){
+      outer.style.color = "green";
+      document.documentElement.classList.remove("reftest-wait");
+    });
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-visited-ref.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-visited-ref.html
new file mode 100644
index 0000000..43e0d1c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-visited-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test Reference</title>
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<p>There should be a square with a white-to-green gradient and some text below.</p>
+<a style="color: green; width: 100px; height: 100px; display: block; background: linear-gradient(white, green);" href="">
+  This text should be green
+</a>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-visited.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-visited.html
new file mode 100644
index 0000000..65467b5e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-gradient-currentcolor-visited.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>CSS Backgrounds and Borders: Repaint gradient on currentColor change (visited)</title>
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<link rel="match" href="background-image-gradient-currentcolor-visited-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-images-3/#color-stop-syntax">
+<style>
+  a {
+    color: red;
+    width: 100px;
+    height: 100px;
+    display: block;
+    background: linear-gradient(white, currentColor);
+  }
+  a:visited {
+    color: blue;
+  }
+  a.green:visited {
+    color: green;
+  }
+</style>
+<p>There should be a square with a white-to-green gradient and some text below.</p>
+<a id="target" href="">
+  This text should be green
+</a>
+<script>
+  requestAnimationFrame(function(){
+    requestAnimationFrame(function(){
+      target.classList.add("green");
+      document.documentElement.classList.remove("reftest-wait");
+    });
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/the-select-element/select-intrinsic-text-transform-ref.html b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/the-select-element/select-intrinsic-text-transform-ref.html
new file mode 100644
index 0000000..18e272b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/the-select-element/select-intrinsic-text-transform-ref.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<select>
+  <option>ABCDEFGHIJK</option>
+</select>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/the-select-element/select-intrinsic-text-transform.html b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/the-select-element/select-intrinsic-text-transform.html
new file mode 100644
index 0000000..1026e29
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/the-select-element/select-intrinsic-text-transform.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<title>text-transform in option doesn't affect combobox rendering</title>
+<link rel=match href=select-intrinsic-text-transform-ref.html>
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=1283930">
+<link rel=author href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<select>
+  <option style="text-transform: lowercase">ABCDEFGHIJK</option>
+</select>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/inert-inlines.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/inert-inlines.html
index 8acdb570..5ee4113 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/inert-inlines.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/inert-inlines.html
@@ -39,8 +39,8 @@
       absoluteTop += parentNode.offsetTop;
     }
 
-    const x = absoluteLeft + element.offsetWidth / 2;
-    const y = absoluteTop + element.offsetHeight / 2;
+    const x = Math.round(absoluteLeft + element.offsetWidth / 2);
+    const y = Math.round(absoluteTop + element.offsetHeight / 2);
     const actions = new test_driver.Actions()
       .pointerMove(x, y)
       .pointerDown()
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/inert-node-is-uneditable.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/inert-node-is-uneditable.html
index 393e5e1..9141a38 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/inert-node-is-uneditable.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/inert-node-is-uneditable.html
@@ -24,8 +24,8 @@
       absoluteTop += parentNode.offsetTop;
     }
 
-    const x = absoluteLeft + element.offsetWidth / 2;
-    const y = absoluteTop + element.offsetHeight / 2;
+    const x = Math.round(absoluteLeft + element.offsetWidth / 2);
+    const y = Math.round(absoluteTop + element.offsetHeight / 2);
     const actions = new test_driver.Actions()
       .pointerMove(x, y)
       .pointerDown()
diff --git a/third_party/blink/web_tests/http/tests/devtools/command-line-api-inspect.js b/third_party/blink/web_tests/http/tests/devtools/command-line-api-inspect.js
index 5d00588c..27853af 100644
--- a/third_party/blink/web_tests/http/tests/devtools/command-line-api-inspect.js
+++ b/third_party/blink/web_tests/http/tests/devtools/command-line-api-inspect.js
@@ -10,7 +10,7 @@
       </p>
     `);
 
-  TestRunner.addSniffer(SDK.RuntimeModel.prototype, '_inspectRequested', sniffInspect, true);
+  TestRunner.addSniffer(SDK.RuntimeModel.prototype, 'inspectRequested', sniffInspect, true);
 
   function sniffInspect(objectId, hints) {
     TestRunner.addResult('WebInspector.inspect called with: ' + objectId.description);
diff --git a/third_party/blink/web_tests/http/tests/devtools/console/console-format-classes-expected.txt b/third_party/blink/web_tests/http/tests/devtools/console/console-format-classes-expected.txt
index 4ceec07..960e7d00 100644
--- a/third_party/blink/web_tests/http/tests/devtools/console/console-format-classes-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/console/console-format-classes-expected.txt
@@ -21,6 +21,7 @@
             tree-outline hide-selection-when-blurred source-code object-properties-section
               parent object-properties-section-root-element
                 selection fill
+                tree-element-content
           console-object console-object-preview
             object-description
             object-properties-preview
@@ -42,6 +43,7 @@
             tree-outline hide-selection-when-blurred source-code object-properties-section
               parent object-properties-section-root-element
                 selection fill
+                tree-element-content
           console-object console-object-preview
             object-properties-preview
               name
@@ -59,6 +61,7 @@
             tree-outline hide-selection-when-blurred source-code object-properties-section
               parent object-properties-section-root-element
                 selection fill
+                tree-element-content
           console-object console-object-preview
             object-properties-preview
               name
@@ -84,6 +87,7 @@
             tree-outline hide-selection-when-blurred source-code object-properties-section
               parent object-properties-section-root-element
                 selection fill
+                tree-element-content
           console-object console-object-preview
             object-properties-preview
               name
@@ -109,6 +113,7 @@
             tree-outline hide-selection-when-blurred source-code object-properties-section
               parent object-properties-section-root-element
                 selection fill
+                tree-element-content
           console-object console-object-preview
             object-description
             object-properties-preview
@@ -127,6 +132,7 @@
             tree-outline hide-selection-when-blurred source-code object-properties-section
               parent object-properties-section-root-element
                 selection fill
+                tree-element-content
           console-object console-object-preview
             object-description
             object-properties-preview
@@ -152,6 +158,7 @@
             tree-outline hide-selection-when-blurred source-code object-properties-section
               parent object-properties-section-root-element
                 selection fill
+                tree-element-content
           console-object console-object-preview
             object-description
             object-properties-preview
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/interstitial-sidebar-expected.txt b/third_party/blink/web_tests/http/tests/devtools/security/interstitial-sidebar-expected.txt
index 370e5b48..570a4e8 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/interstitial-sidebar-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/security/interstitial-sidebar-expected.txt
@@ -18,8 +18,10 @@
                 <LI role=treeitem class=security-main-view-sidebar-tree-item selected force-white-icons title=Overview tabindex=0 aria-selected=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
-                    </SPAN>
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
+                        </SPAN>
+                    </DIV>
                     <DIV class=icon lock-icon lock-icon-unknown >
                     </DIV>
                     <SPAN class=title >
@@ -31,17 +33,21 @@
                 <LI title=Main origin role=treeitem class=parent always-parent expanded security-sidebar-origins aria-expanded=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
 Main origin
-                    </SPAN>
+                        </SPAN>
+                    </DIV>
                 </LI>
                 <OL class=children expanded role=group aria-label=Main origin >
                     <LI title=Reload to view details role=treeitem class=security-main-view-reload-message >
                         <DIV class=selection fill >
                         </DIV>
-                        <SPAN class=tree-element-title >
+                        <DIV class=tree-element-content >
+                            <SPAN class=tree-element-title >
 Reload to view details
-                        </SPAN>
+                            </SPAN>
+                        </DIV>
                     </LI>
                     <OL class=children role=group >
                     </OL>
@@ -49,25 +55,31 @@
                 <LI title=Non-secure origins role=treeitem class=parent always-parent expanded security-sidebar-origins hidden aria-expanded=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
 Non-secure origins
-                    </SPAN>
+                        </SPAN>
+                    </DIV>
                 </LI>
                 <OL class=children expanded hidden role=group aria-label=Non-secure origins >
                 </OL>
                 <LI title=Secure origins role=treeitem class=parent always-parent expanded security-sidebar-origins aria-expanded=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
 Secure origins
-                    </SPAN>
+                        </SPAN>
+                    </DIV>
                 </LI>
                 <OL class=children expanded role=group aria-label=Secure origins >
                     <LI role=treeitem class=security-sidebar-tree-item title=https://foo.test >
                         <DIV class=selection fill >
                         </DIV>
-                        <SPAN class=tree-element-title >
-                        </SPAN>
+                        <DIV class=tree-element-content >
+                            <SPAN class=tree-element-title >
+                            </SPAN>
+                        </DIV>
                         <DIV class=icon security-property security-property-secure >
                         </DIV>
                         <SPAN >
@@ -87,8 +99,10 @@
                     <LI role=treeitem class=security-sidebar-tree-item title=https://bar.test >
                         <DIV class=selection fill >
                         </DIV>
-                        <SPAN class=tree-element-title >
-                        </SPAN>
+                        <DIV class=tree-element-content >
+                            <SPAN class=tree-element-title >
+                            </SPAN>
+                        </DIV>
                         <DIV class=icon security-property security-property-secure >
                         </DIV>
                         <SPAN >
@@ -109,9 +123,11 @@
                 <LI title=Unknown / canceled role=treeitem class=parent always-parent expanded security-sidebar-origins hidden aria-expanded=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
 Unknown / canceled
-                    </SPAN>
+                        </SPAN>
+                    </DIV>
                 </LI>
                 <OL class=children expanded hidden role=group aria-label=Unknown / canceled >
                 </OL>
@@ -137,8 +153,10 @@
                 <LI role=treeitem class=security-main-view-sidebar-tree-item selected force-white-icons title=Overview tabindex=0 aria-selected=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
-                    </SPAN>
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
+                        </SPAN>
+                    </DIV>
                     <DIV class=icon lock-icon lock-icon-unknown >
                     </DIV>
                     <SPAN class=title >
@@ -150,17 +168,21 @@
                 <LI title=Main origin role=treeitem class=parent always-parent expanded security-sidebar-origins hidden aria-expanded=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
 Main origin
-                    </SPAN>
+                        </SPAN>
+                    </DIV>
                 </LI>
                 <OL class=children expanded hidden role=group aria-label=Main origin >
                     <LI title=Reload to view details role=treeitem class=security-main-view-reload-message >
                         <DIV class=selection fill >
                         </DIV>
-                        <SPAN class=tree-element-title >
+                        <DIV class=tree-element-content >
+                            <SPAN class=tree-element-title >
 Reload to view details
-                        </SPAN>
+                            </SPAN>
+                        </DIV>
                     </LI>
                     <OL class=children role=group >
                     </OL>
@@ -168,25 +190,31 @@
                 <LI title=Non-secure origins role=treeitem class=parent always-parent expanded security-sidebar-origins hidden aria-expanded=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
 Non-secure origins
-                    </SPAN>
+                        </SPAN>
+                    </DIV>
                 </LI>
                 <OL class=children expanded hidden role=group aria-label=Non-secure origins >
                 </OL>
                 <LI title=Secure origins role=treeitem class=parent always-parent expanded security-sidebar-origins hidden aria-expanded=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
 Secure origins
-                    </SPAN>
+                        </SPAN>
+                    </DIV>
                 </LI>
                 <OL class=children expanded hidden role=group aria-label=Secure origins >
                     <LI role=treeitem class=security-sidebar-tree-item title=https://foo.test >
                         <DIV class=selection fill >
                         </DIV>
-                        <SPAN class=tree-element-title >
-                        </SPAN>
+                        <DIV class=tree-element-content >
+                            <SPAN class=tree-element-title >
+                            </SPAN>
+                        </DIV>
                         <DIV class=icon security-property security-property-secure >
                         </DIV>
                         <SPAN >
@@ -206,8 +234,10 @@
                     <LI role=treeitem class=security-sidebar-tree-item title=https://bar.test >
                         <DIV class=selection fill >
                         </DIV>
-                        <SPAN class=tree-element-title >
-                        </SPAN>
+                        <DIV class=tree-element-content >
+                            <SPAN class=tree-element-title >
+                            </SPAN>
+                        </DIV>
                         <DIV class=icon security-property security-property-secure >
                         </DIV>
                         <SPAN >
@@ -228,9 +258,11 @@
                 <LI title=Unknown / canceled role=treeitem class=parent always-parent expanded security-sidebar-origins hidden aria-expanded=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
 Unknown / canceled
-                    </SPAN>
+                        </SPAN>
+                    </DIV>
                 </LI>
                 <OL class=children expanded hidden role=group aria-label=Unknown / canceled >
                 </OL>
@@ -256,8 +288,10 @@
                 <LI role=treeitem class=security-main-view-sidebar-tree-item selected force-white-icons title=Overview tabindex=0 aria-selected=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
-                    </SPAN>
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
+                        </SPAN>
+                    </DIV>
                     <DIV class=icon lock-icon lock-icon-unknown >
                     </DIV>
                     <SPAN class=title >
@@ -269,17 +303,21 @@
                 <LI title=Main origin role=treeitem class=parent always-parent expanded security-sidebar-origins aria-expanded=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
 Main origin
-                    </SPAN>
+                        </SPAN>
+                    </DIV>
                 </LI>
                 <OL class=children expanded role=group aria-label=Main origin >
                     <LI title=Reload to view details role=treeitem class=security-main-view-reload-message >
                         <DIV class=selection fill >
                         </DIV>
-                        <SPAN class=tree-element-title >
+                        <DIV class=tree-element-content >
+                            <SPAN class=tree-element-title >
 Reload to view details
-                        </SPAN>
+                            </SPAN>
+                        </DIV>
                     </LI>
                     <OL class=children role=group >
                     </OL>
@@ -287,25 +325,31 @@
                 <LI title=Non-secure origins role=treeitem class=parent always-parent expanded security-sidebar-origins aria-expanded=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
 Non-secure origins
-                    </SPAN>
+                        </SPAN>
+                    </DIV>
                 </LI>
                 <OL class=children expanded role=group aria-label=Non-secure origins >
                 </OL>
                 <LI title=Secure origins role=treeitem class=parent always-parent expanded security-sidebar-origins aria-expanded=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
 Secure origins
-                    </SPAN>
+                        </SPAN>
+                    </DIV>
                 </LI>
                 <OL class=children expanded role=group aria-label=Secure origins >
                     <LI role=treeitem class=security-sidebar-tree-item title=https://foo.test >
                         <DIV class=selection fill >
                         </DIV>
-                        <SPAN class=tree-element-title >
-                        </SPAN>
+                        <DIV class=tree-element-content >
+                            <SPAN class=tree-element-title >
+                            </SPAN>
+                        </DIV>
                         <DIV class=icon security-property security-property-secure >
                         </DIV>
                         <SPAN >
@@ -325,8 +369,10 @@
                     <LI role=treeitem class=security-sidebar-tree-item title=https://bar.test >
                         <DIV class=selection fill >
                         </DIV>
-                        <SPAN class=tree-element-title >
-                        </SPAN>
+                        <DIV class=tree-element-content >
+                            <SPAN class=tree-element-title >
+                            </SPAN>
+                        </DIV>
                         <DIV class=icon security-property security-property-secure >
                         </DIV>
                         <SPAN >
@@ -347,9 +393,11 @@
                 <LI title=Unknown / canceled role=treeitem class=parent always-parent expanded security-sidebar-origins aria-expanded=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
 Unknown / canceled
-                    </SPAN>
+                        </SPAN>
+                    </DIV>
                 </LI>
                 <OL class=children expanded role=group aria-label=Unknown / canceled >
                 </OL>
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-sidebar-expected.txt b/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-sidebar-expected.txt
index 3346c0be..3637796f 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-sidebar-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-sidebar-expected.txt
@@ -18,8 +18,10 @@
                 <LI role=treeitem class=security-main-view-sidebar-tree-item selected force-white-icons title=Overview tabindex=0 aria-selected=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
-                    </SPAN>
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
+                        </SPAN>
+                    </DIV>
                     <DIV class=icon lock-icon lock-icon-neutral >
                     </DIV>
                     <SPAN class=title >
@@ -31,17 +33,21 @@
                 <LI title=Main origin role=treeitem class=parent always-parent expanded security-sidebar-origins aria-expanded=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
 Main origin
-                    </SPAN>
+                        </SPAN>
+                    </DIV>
                 </LI>
                 <OL class=children expanded role=group aria-label=Main origin >
                     <LI title=Reload to view details role=treeitem class=security-main-view-reload-message >
                         <DIV class=selection fill >
                         </DIV>
-                        <SPAN class=tree-element-title >
+                        <DIV class=tree-element-content >
+                            <SPAN class=tree-element-title >
 Reload to view details
-                        </SPAN>
+                            </SPAN>
+                        </DIV>
                     </LI>
                     <OL class=children role=group >
                     </OL>
@@ -49,16 +55,20 @@
                 <LI title=Non-secure origins role=treeitem class=parent always-parent expanded security-sidebar-origins aria-expanded=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
 Non-secure origins
-                    </SPAN>
+                        </SPAN>
+                    </DIV>
                 </LI>
                 <OL class=children expanded role=group aria-label=Non-secure origins >
                     <LI role=treeitem class=security-sidebar-tree-item title=http://foo.test >
                         <DIV class=selection fill >
                         </DIV>
-                        <SPAN class=tree-element-title >
-                        </SPAN>
+                        <DIV class=tree-element-content >
+                            <SPAN class=tree-element-title >
+                            </SPAN>
+                        </DIV>
                         <DIV class=icon security-property security-property-insecure >
                         </DIV>
                         <SPAN >
@@ -78,8 +88,10 @@
                     <LI role=treeitem class=security-sidebar-tree-item title=http://bar.test >
                         <DIV class=selection fill >
                         </DIV>
-                        <SPAN class=tree-element-title >
-                        </SPAN>
+                        <DIV class=tree-element-content >
+                            <SPAN class=tree-element-title >
+                            </SPAN>
+                        </DIV>
                         <DIV class=icon security-property security-property-insecure >
                         </DIV>
                         <SPAN >
@@ -100,18 +112,22 @@
                 <LI title=Secure origins role=treeitem class=parent always-parent expanded security-sidebar-origins hidden aria-expanded=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
 Secure origins
-                    </SPAN>
+                        </SPAN>
+                    </DIV>
                 </LI>
                 <OL class=children expanded hidden role=group aria-label=Secure origins >
                 </OL>
                 <LI title=Unknown / canceled role=treeitem class=parent always-parent expanded security-sidebar-origins hidden aria-expanded=true >
                     <DIV class=selection fill >
                     </DIV>
-                    <SPAN class=tree-element-title >
+                    <DIV class=tree-element-content >
+                        <SPAN class=tree-element-title >
 Unknown / canceled
-                    </SPAN>
+                        </SPAN>
+                    </DIV>
                 </LI>
                 <OL class=children expanded hidden role=group aria-label=Unknown / canceled >
                 </OL>
diff --git a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-console/debugger-command-line-api.js b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-console/debugger-command-line-api.js
index 50857cd5..cb6f006 100644
--- a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-console/debugger-command-line-api.js
+++ b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-console/debugger-command-line-api.js
@@ -19,7 +19,7 @@
       }
   `);
 
-  TestRunner.addSniffer(SDK.RuntimeModel.prototype, '_inspectRequested', inspect);
+  TestRunner.addSniffer(SDK.RuntimeModel.prototype, 'inspectRequested', inspect);
   const originalReveal = Common.Revealer.reveal;
   Common.Revealer.setRevealForTest((node) => {
     if (!(node instanceof SDK.RemoteObject)) {
diff --git a/third_party/blink/web_tests/paint/invalidation/background/gradient-currentcolor-expected.html b/third_party/blink/web_tests/paint/invalidation/background/gradient-currentcolor-expected.html
new file mode 100644
index 0000000..f1f3f7ba
--- /dev/null
+++ b/third_party/blink/web_tests/paint/invalidation/background/gradient-currentcolor-expected.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<div id="outer" style="color: green">
+  <div id="inner" style="height: 100px; background: linear-gradient(white, green)">Text</div>
+</div>
diff --git a/third_party/blink/web_tests/paint/invalidation/background/gradient-currentcolor.html b/third_party/blink/web_tests/paint/invalidation/background/gradient-currentcolor.html
new file mode 100644
index 0000000..c1b87cd
--- /dev/null
+++ b/third_party/blink/web_tests/paint/invalidation/background/gradient-currentcolor.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<script src="../../../resources/run-after-layout-and-paint.js"></script>
+<script>
+onload = () => {
+  runAfterLayoutAndPaint(() => {
+    outer.style.color = "green";
+  }, true);
+}
+</script>
+<div id="outer" style="color: red">
+  <div id="inner" style="height: 100px; background: linear-gradient(white, currentColor)">Text</div>
+</div>
diff --git a/third_party/blink/web_tests/wpt_internal/fenced_frame/embedder-no-coep.https.html.headers b/third_party/blink/web_tests/wpt_internal/fenced_frame/embedder-no-coep.https.html.headers
deleted file mode 100644
index 1b63235..0000000
--- a/third_party/blink/web_tests/wpt_internal/fenced_frame/embedder-no-coep.https.html.headers
+++ /dev/null
@@ -1 +0,0 @@
-Supports-Loading-Mode: fenced-frame
diff --git a/third_party/blink/web_tests/wpt_internal/fenced_frame/embedder-require-corp.https.html.headers b/third_party/blink/web_tests/wpt_internal/fenced_frame/embedder-require-corp.https.html.headers
index 6a268d77..8df9847 100644
--- a/third_party/blink/web_tests/wpt_internal/fenced_frame/embedder-require-corp.https.html.headers
+++ b/third_party/blink/web_tests/wpt_internal/fenced_frame/embedder-require-corp.https.html.headers
@@ -1,2 +1 @@
-Supports-Loading-Mode: fenced-frame
 cross-origin-embedder-policy: require-corp
diff --git a/third_party/blink/web_tests/wpt_internal/payments/promises-keep-request-alive.https.html b/third_party/blink/web_tests/wpt_internal/payments/promises-keep-request-alive.https.html
index b532070..3fb55d1 100644
--- a/third_party/blink/web_tests/wpt_internal/payments/promises-keep-request-alive.https.html
+++ b/third_party/blink/web_tests/wpt_internal/payments/promises-keep-request-alive.https.html
@@ -1,6 +1,8 @@
 <!DOCTYPE html>
 <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 type="module">
 import {PaymentRequestMock} from './resources/payment-request-mock.js';
 var details = {
@@ -19,6 +21,7 @@
 const paymentRequestMock = new PaymentRequestMock();
 
 promise_test(async () => {
+  await test_driver.bless();
   let result = new PaymentRequest([
       {'supportedMethods': ['basic-card']}
   ], details).show();
diff --git a/third_party/distributed_point_functions/code/dpf/distributed_point_function.h b/third_party/distributed_point_functions/code/dpf/distributed_point_function.h
index 3d2dc20..1ce34c7d 100644
--- a/third_party/distributed_point_functions/code/dpf/distributed_point_function.h
+++ b/third_party/distributed_point_functions/code/dpf/distributed_point_function.h
@@ -679,7 +679,7 @@
     int block_index = DomainToBlockIndex(prefixes[i], previous_hierarchy_level);
 
     // Check if `tree_index` already exists in `tree_indices`.
-    int64_t previous_size = tree_indices_inverse.size();
+    auto previous_size = tree_indices_inverse.size();
     auto it = tree_indices_inverse.try_emplace(tree_indices_inverse.end(),
                                                tree_index, tree_indices.size());
     if (tree_indices_inverse.size() > previous_size) {
diff --git a/third_party/leveldatabase/BUILD.gn b/third_party/leveldatabase/BUILD.gn
index 744ce88..1149afa 100644
--- a/third_party/leveldatabase/BUILD.gn
+++ b/third_party/leveldatabase/BUILD.gn
@@ -197,8 +197,6 @@
     visibility = [ ":*" ]
 
     sources = [
-      "src/util/histogram.cc",
-      "src/util/histogram.h",
       "src/util/testutil.cc",
       "src/util/testutil.h",
     ]
@@ -214,49 +212,63 @@
     deps = [ "//base" ]
   }
 
-  test("leveldb_arena_test") {
-    sources = [ "src/util/arena_test.cc" ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [ ":leveldb_testutil" ]
-  }
+  test("leveldb_unittests") {
+    sources = [
+      # The project's tests.
+      "src/db/autocompact_test.cc",
+      "src/db/corruption_test.cc",
+      "src/db/db_test.cc",
+      "src/db/dbformat_test.cc",
+      "src/db/filename_test.cc",
+      "src/db/log_test.cc",
+      "src/db/recovery_test.cc",
+      "src/db/skiplist_test.cc",
+      "src/db/version_edit_test.cc",
+      "src/db/version_set_test.cc",
+      "src/db/write_batch_test.cc",
+      "src/helpers/memenv/memenv_test.cc",
+      "src/issues/issue178_test.cc",
+      "src/issues/issue200_test.cc",
+      "src/issues/issue320_test.cc",
+      "src/table/filter_block_test.cc",
+      "src/table/table_test.cc",
+      "src/util/arena_test.cc",
+      "src/util/bloom_test.cc",
+      "src/util/cache_test.cc",
+      "src/util/coding_test.cc",
+      "src/util/crc32c_test.cc",
+      "src/util/env_test.cc",
+      "src/util/hash_test.cc",
+      "src/util/logging_test.cc",
+      "src/util/no_destructor_test.cc",
+      "src/util/status_test.cc",
 
-  test("leveldb_bloom_test") {
-    sources = [ "src/util/bloom_test.cc" ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [ ":leveldb_testutil" ]
-  }
+      # Custom main() needed by Chromium's leveldb::Env.
+      "leveldb_unittest_main.cc",
+    ]
 
-  test("leveldb_cache_test") {
-    sources = [ "src/util/cache_test.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [ ":leveldb_testutil" ]
 
     if (is_win) {
       # util\cache_test.cc(167): warning C4018: '<': signed/unsigned mismatch
       # util\cache_test.cc(171): warning C4018: '<': signed/unsigned mismatch
       cflags = [ "/wd4018" ]  # Signed/unsigned mismatch in comparison.
     }
-  }
 
-  test("leveldb_corruption_test") {
-    sources = [ "src/db/corruption_test.cc" ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [ ":leveldb_testutil" ]
-  }
-
-  test("leveldb_crc32c_test") {
-    sources = [ "src/util/crc32c_test.cc" ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [ ":leveldb_testutil" ]
+    deps = [
+      ":leveldb_testutil",
+      "//base",
+      "//base/test:test_support",
+    ]
   }
 
   test("leveldb_db_bench") {
-    sources = [ "src/benchmarks/db_bench.cc" ]
+    sources = [
+      "src/benchmarks/db_bench.cc",
+      "src/util/histogram.cc",
+      "src/util/histogram.h",
+    ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
     deps = [ ":leveldb_testutil" ]
@@ -265,8 +277,8 @@
   # The google/banchmark third_party dependency is optional, and only
   # available if specified. See third_party/google_benchmark/README.chromium.
   if (enable_google_benchmarks) {
-    test("leveldb_db_test") {
-      sources = [ "src/db/db_test.cc" ]
+    test("leveldb_db_bench_log") {
+      sources = [ "src/benchmarks/db_bench_log.cc" ]
       configs -= [ "//build/config/compiler:chromium_code" ]
       configs += [ "//build/config/compiler:no_chromium_code" ]
       deps = [
@@ -276,38 +288,6 @@
     }
   }
 
-  test("leveldb_dbformat_test") {
-    sources = [ "src/db/dbformat_test.cc" ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [ ":leveldb_testutil" ]
-  }
-
-  test("leveldb_env_test") {
-    sources = [ "src/util/env_test.cc" ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [ ":leveldb_testutil" ]
-
-    if (is_win) {
-      cflags = [ "/wd4018" ]  # Signed/unsigned mismatch in comparison.
-    }
-  }
-
-  test("leveldb_filename_test") {
-    sources = [ "src/db/filename_test.cc" ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [ ":leveldb_testutil" ]
-  }
-
-  test("leveldb_filter_block_test") {
-    sources = [ "src/table/filter_block_test.cc" ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [ ":leveldb_testutil" ]
-  }
-
   executable("leveldb_leveldbutil") {
     sources = [ "src/db/leveldbutil.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
@@ -315,70 +295,15 @@
     deps = [ ":leveldb_static" ]
   }
 
-  test("leveldb_log_test") {
-    sources = [ "src/db/log_test.cc" ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [ ":leveldb_testutil" ]
-
-    if (is_win) {
-      # db\log_test.cc(486) triggers two warnings:
-      # util\testharness.h(91): warning C4018: '<=': signed/unsigned mismatch
-      # util\testharness.h(89): warning C4018: '>=': signed/unsigned mismatch
-      cflags = [ "/wd4018" ]  # Signed/unsigned mismatch in comparison.
-    }
-  }
-
-  test("leveldb_skiplist_test") {
-    sources = [ "src/db/skiplist_test.cc" ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [ ":leveldb_testutil" ]
-  }
-
-  test("leveldb_table_test") {
-    sources = [ "src/table/table_test.cc" ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [ ":leveldb_testutil" ]
-  }
-
-  test("leveldb_version_edit_test") {
-    sources = [ "src/db/version_edit_test.cc" ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [ ":leveldb_testutil" ]
-  }
-
-  test("leveldb_write_batch_test") {
-    sources = [ "src/db/write_batch_test.cc" ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [ ":leveldb_testutil" ]
-  }
-
   group("leveldb_test_targets") {
     testonly = true
     deps = [
       ":env_chromium_unittests",
-      ":leveldb_arena_test",
-      ":leveldb_bloom_test",
-      ":leveldb_cache_test",
-      ":leveldb_corruption_test",
-      ":leveldb_crc32c_test",
       ":leveldb_db_bench",
-      ":leveldb_dbformat_test",
-      ":leveldb_env_test",
-      ":leveldb_filename_test",
-      ":leveldb_filter_block_test",
-      ":leveldb_log_test",
-      ":leveldb_skiplist_test",
-      ":leveldb_table_test",
-      ":leveldb_version_edit_test",
-      ":leveldb_write_batch_test",
+      ":leveldb_unittests",
     ]
     if (enable_google_benchmarks) {
-      deps += [ ":leveldb_db_test" ]
+      deps += [ ":leveldb_db_bench_log" ]
     }
   }
 }
diff --git a/third_party/leveldatabase/leveldb_unittest_main.cc b/third_party/leveldatabase/leveldb_unittest_main.cc
new file mode 100644
index 0000000..90adfda
--- /dev/null
+++ b/third_party/leveldatabase/leveldb_unittest_main.cc
@@ -0,0 +1,22 @@
+
+// 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. See the AUTHORS file for names of contributors.
+
+#include "base/command_line.h"
+#include "base/test/task_environment.h"
+#include "base/test/test_timeouts.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  testing::InitGoogleMock(&argc, argv);
+
+  // Chromium's leveldb::Env uses PostTask.
+  base::CommandLine::Init(argc, argv);
+  TestTimeouts::Initialize();
+  base::test::TaskEnvironment task_environment;
+
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/microsoft_webauthn/webauthn.h b/third_party/microsoft_webauthn/webauthn.h
index 08f8b9d..3961974 100644
--- a/third_party/microsoft_webauthn/webauthn.h
+++ b/third_party/microsoft_webauthn/webauthn.h
@@ -84,7 +84,15 @@
 //          - WEBAUTHN_EXTENSIONS_IDENTIFIER_MIN_PIN_LENGTH
 //
 
-#define WEBAUTHN_API_CURRENT_VERSION WEBAUTHN_API_VERSION_3
+#define WEBAUTHN_API_VERSION_4 4
+// WEBAUTHN_API_VERSION_4 : Delta From WEBAUTHN_API_VERSION_3
+//      Data Structures and their sub versions:
+//          - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS    :   5
+//          - WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS      :   6
+//          - WEBAUTHN_ASSERTION                                :   3
+//
+
+#define WEBAUTHN_API_CURRENT_VERSION WEBAUTHN_API_VERSION_4
 
 //+------------------------------------------------------------------------------------------
 // Information about an RP Entity
@@ -273,6 +281,44 @@
 typedef const WEBAUTHN_CREDENTIAL_LIST *PCWEBAUTHN_CREDENTIAL_LIST;
 
 //+------------------------------------------------------------------------------------------
+// PRF values.
+//-------------------------------------------------------------------------------------------
+
+#define WEBAUTHN_CTAP_ONE_HMAC_SECRET_LENGTH 32
+
+typedef struct _WEBAUTHN_HMAC_SECRET_SALT {
+  // Size of pbFirst.
+  DWORD cbFirst;
+  _Field_size_bytes_(cbFirst) PBYTE pbFirst;  // Required
+
+  // Size of pbSecond.
+  DWORD cbSecond;
+  _Field_size_bytes_(cbSecond) PBYTE pbSecond;
+} WEBAUTHN_HMAC_SECRET_SALT, *PWEBAUTHN_HMAC_SECRET_SALT;
+typedef const WEBAUTHN_HMAC_SECRET_SALT* PCWEBAUTHN_HMAC_SECRET_SALT;
+
+typedef struct _WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT {
+  // Size of pbCredID.
+  DWORD cbCredID;
+  _Field_size_bytes_(cbCredID) PBYTE pbCredID;  // Required
+
+  // PRF Values for above credential
+  PWEBAUTHN_HMAC_SECRET_SALT pHmacSecretSalt;  // Required
+} WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT, *PWEBAUTHN_CRED_WITH_HMAC_SECRET_SALT;
+typedef const WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT*
+    PCWEBAUTHN_CRED_WITH_HMAC_SECRET_SALT;
+
+typedef struct _WEBAUTHN_HMAC_SECRET_SALT_VALUES {
+  PWEBAUTHN_HMAC_SECRET_SALT pGlobalHmacSalt;
+
+  DWORD cCredWithHmacSecretSaltList;
+  _Field_size_(cCredWithHmacSecretSaltList)
+      PWEBAUTHN_CRED_WITH_HMAC_SECRET_SALT pCredWithHmacSecretSaltList;
+} WEBAUTHN_HMAC_SECRET_SALT_VALUES, *PWEBAUTHN_HMAC_SECRET_SALT_VALUES;
+typedef const WEBAUTHN_HMAC_SECRET_SALT_VALUES*
+    PCWEBAUTHN_HMAC_SECRET_SALT_VALUES;
+
+//+------------------------------------------------------------------------------------------
 // Hmac-Secret extension
 //-------------------------------------------------------------------------------------------
 
@@ -416,8 +462,9 @@
 #define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_2            2
 #define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_3            3
 #define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_4 4
+#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_5 5
 #define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_CURRENT_VERSION \
-  WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_4
+  WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_5
 
 typedef struct _WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS {
     // Version of this structure, to allow for modifications in the future.
@@ -473,13 +520,21 @@
     // Large Blob Support: none, required or preferred
     //
     // NTE_INVALID_PARAMETER when large blob required or preferred and
-    //   both bRequireResidentKey and bPreferResidentKey are set to FALSE.
+    //   bRequireResidentKey isn't set to TRUE
     DWORD dwLargeBlobSupport;
 
     // Optional. Prefer key to be resident. Defaulting to FALSE. When TRUE,
     // overrides the above bRequireResidentKey.
     BOOL bPreferResidentKey;
 
+    //
+    // The following fields have been added in
+    // WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_5
+    //
+
+    // Optional. BrowserInPrivate Mode. Defaulting to FALSE.
+    BOOL bBrowserInPrivateMode;
+
 } WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS, *PWEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS;
 typedef const WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS *PCWEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS;
 
@@ -493,8 +548,9 @@
 #define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_3          3
 #define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_4          4
 #define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_5 5
+#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_6 6
 #define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_CURRENT_VERSION \
-  WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_5
+  WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_6
 
 typedef struct _WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS {
     // Version of this structure, to allow for modifications in the future.
@@ -554,6 +610,19 @@
     // Size of pbCredLargeBlob
     DWORD cbCredLargeBlob;
     _Field_size_bytes_(cbCredLargeBlob) PBYTE pbCredLargeBlob;
+
+    //
+    // The following fields have been added in
+    // WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_6
+    //
+
+    // PRF values which will be converted into HMAC-SECRET values according to
+    // WebAuthn Spec.
+    PWEBAUTHN_HMAC_SECRET_SALT_VALUES pHmacSecretSaltValues;
+
+    // Optional. BrowserInPrivate Mode. Defaulting to FALSE.
+    BOOL bBrowserInPrivateMode;
+
 } WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS,  *PWEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS;
 typedef const WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS  *PCWEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS;
 
@@ -716,7 +785,8 @@
 
 #define WEBAUTHN_ASSERTION_VERSION_1 1
 #define WEBAUTHN_ASSERTION_VERSION_2 2
-#define WEBAUTHN_ASSERTION_CURRENT_VERSION WEBAUTHN_ASSERTION_VERSION_2
+#define WEBAUTHN_ASSERTION_VERSION_3 3
+#define WEBAUTHN_ASSERTION_CURRENT_VERSION WEBAUTHN_ASSERTION_VERSION_3
 
 typedef struct _WEBAUTHN_ASSERTION {
     // Version of this structure, to allow for modifications in the future.
@@ -755,6 +825,12 @@
 
     DWORD dwCredLargeBlobStatus;
 
+    //
+    // Following fields have been added in WEBAUTHN_ASSERTION_VERSION_3
+    //
+
+    PWEBAUTHN_HMAC_SECRET_SALT pHmacSecret;
+
 } WEBAUTHN_ASSERTION, *PWEBAUTHN_ASSERTION;
 typedef const WEBAUTHN_ASSERTION *PCWEBAUTHN_ASSERTION;
 
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 6f9fd92..31ec0a2 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -15593,6 +15593,7 @@
   <int value="15" label="CONTEXT_LOST_DIRECT_COMPOSITION_OVERLAY_FAILED"/>
   <int value="16" label="CONTEXT_LOST_SWAP_FAILED"/>
   <int value="17" label="CONTEXT_LOST_BEGIN_PAINT_FAILED"/>
+  <int value="18" label="CONTEXT_LOST_ALLOCATE_FRAME_BUFFERS_FAILED"/>
 </enum>
 
 <enum name="ContextMenuDelayedElementDetails">
@@ -51433,6 +51434,7 @@
   <int value="-1460561942" label="SystemEmojiPicker:disabled"/>
   <int value="-1460462432" label="disable-media-source"/>
   <int value="-1459907288" label="DesksTemplates:enabled"/>
+  <int value="-1458056084" label="SyncUndecryptablePasswordsLinux:enabled"/>
   <int value="-1457775295" label="PasswordSearchMobile:disabled"/>
   <int value="-1456789591" label="MediaFoundationVideoCapture:enabled"/>
   <int value="-1456627355" label="EnableEmojiContextMenu:disabled"/>
@@ -52221,6 +52223,7 @@
   <int value="-894214299" label="fill-on-account-select:enabled"/>
   <int value="-894185031" label="HighDynamicRange:disabled"/>
   <int value="-893673593" label="BentoOffline:disabled"/>
+  <int value="-893656784" label="SyncUndecryptablePasswordsLinux:disabled"/>
   <int value="-892428689" label="ManualPasswordGenerationAndroid:enabled"/>
   <int value="-891856063" label="MidiManagerAndroid:enabled"/>
   <int value="-890517779" label="JXL:enabled"/>
diff --git a/tools/metrics/histograms/metadata/accessibility/histograms.xml b/tools/metrics/histograms/metadata/accessibility/histograms.xml
index e027eef..bfff227 100644
--- a/tools/metrics/histograms/metadata/accessibility/histograms.xml
+++ b/tools/metrics/histograms/metadata/accessibility/histograms.xml
@@ -1808,7 +1808,7 @@
 </histogram>
 
 <histogram name="DomDistiller.ReaderMode.EntryPoint"
-    enum="ReaderModeEntryPoint" expires_after="2022-05-01">
+    enum="ReaderModeEntryPoint" expires_after="2022-07-03">
   <owner>katie@chromium.org</owner>
   <owner>gilmanmh@google.com</owner>
   <owner>chrome-a11y-core@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml
index 58b26be..5c2e41c 100644
--- a/tools/metrics/histograms/metadata/android/histograms.xml
+++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -411,7 +411,7 @@
 </histogram>
 
 <histogram name="Android.BackgroundTaskScheduler.TaskCanceled"
-    enum="BackgroundTaskId" expires_after="2022-05-01">
+    enum="BackgroundTaskId" expires_after="2022-07-03">
   <owner>fgorski@chromium.org</owner>
   <owner>nyquist@chromium.org</owner>
   <summary>Records that a specific background task has been canceled.</summary>
@@ -440,7 +440,7 @@
 </histogram>
 
 <histogram name="Android.BackgroundTaskScheduler.TaskExpired"
-    enum="BackgroundTaskId" expires_after="2022-05-01">
+    enum="BackgroundTaskId" expires_after="2022-07-03">
   <owner>fgorski@chromium.org</owner>
   <owner>nator@chromium.org</owner>
   <owner>knollr@chromium.org</owner>
@@ -451,7 +451,7 @@
 </histogram>
 
 <histogram name="Android.BackgroundTaskScheduler.TaskLoadedNative"
-    enum="BackgroundTaskId" expires_after="2022-05-01">
+    enum="BackgroundTaskId" expires_after="2022-07-03">
   <owner>fgorski@chromium.org</owner>
   <owner>nyquist@chromium.org</owner>
   <summary>
@@ -461,7 +461,7 @@
 </histogram>
 
 <histogram name="Android.BackgroundTaskScheduler.TaskLoadedNative.FullBrowser"
-    enum="BackgroundTaskId" expires_after="2022-05-01">
+    enum="BackgroundTaskId" expires_after="2022-07-03">
   <owner>mheikal@chromium.org</owner>
   <owner>hanxi@chromium.org</owner>
   <owner>hnakashima@chromium.org</owner>
@@ -472,7 +472,7 @@
 </histogram>
 
 <histogram name="Android.BackgroundTaskScheduler.TaskLoadedNative.ReducedMode"
-    enum="BackgroundTaskId" expires_after="2022-05-01">
+    enum="BackgroundTaskId" expires_after="2022-07-03">
   <owner>mheikal@chromium.org</owner>
   <owner>hanxi@chromium.org</owner>
   <owner>hnakashima@chromium.org</owner>
@@ -482,7 +482,7 @@
 </histogram>
 
 <histogram name="Android.BackgroundTaskScheduler.TaskScheduled.Failure"
-    enum="BackgroundTaskId" expires_after="2022-05-01">
+    enum="BackgroundTaskId" expires_after="2022-07-03">
   <owner>fgorski@chromium.org</owner>
   <owner>nyquist@chromium.org</owner>
   <summary>
@@ -491,7 +491,7 @@
 </histogram>
 
 <histogram name="Android.BackgroundTaskScheduler.TaskScheduled.Success"
-    enum="BackgroundTaskId" expires_after="2022-05-01">
+    enum="BackgroundTaskId" expires_after="2022-07-03">
   <owner>fgorski@chromium.org</owner>
   <owner>nyquist@chromium.org</owner>
   <summary>
@@ -500,14 +500,14 @@
 </histogram>
 
 <histogram name="Android.BackgroundTaskScheduler.TaskStarted"
-    enum="BackgroundTaskId" expires_after="2022-05-01">
+    enum="BackgroundTaskId" expires_after="2022-07-03">
   <owner>fgorski@chromium.org</owner>
   <owner>nyquist@chromium.org</owner>
   <summary>Records that a specific background task has been started.</summary>
 </histogram>
 
 <histogram name="Android.BackgroundTaskScheduler.TaskStopped"
-    enum="BackgroundTaskId" expires_after="2022-05-01">
+    enum="BackgroundTaskId" expires_after="2022-07-03">
   <owner>fgorski@chromium.org</owner>
   <owner>nyquist@chromium.org</owner>
   <summary>
@@ -1427,7 +1427,7 @@
 </histogram>
 
 <histogram name="Android.FontLookup.FetchAllFontFiles.Time" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>twellington@chromium.org</owner>
   <owner>clank-app-team@google.com</owner>
   <summary>
@@ -1472,7 +1472,7 @@
 </histogram>
 
 <histogram name="Android.FontLookup.MatchLocalFontByUniqueName.Time" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>twellington@chromium.org</owner>
   <owner>clank-app-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/apps/histograms.xml b/tools/metrics/histograms/metadata/apps/histograms.xml
index 9a44b73..a12fe01 100644
--- a/tools/metrics/histograms/metadata/apps/histograms.xml
+++ b/tools/metrics/histograms/metadata/apps/histograms.xml
@@ -238,7 +238,7 @@
 </histogram>
 
 <histogram name="Apps.AppInfoDialog.CreateWebAppShortcutSuccess" enum="Boolean"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>dmurph@chromium.org</owner>
   <owner>desktop-pwas-team@google.com</owner>
   <summary>
@@ -1583,7 +1583,7 @@
 </histogram>
 
 <histogram name="Apps.AppListFolderOpened" enum="AppListFolderOpened"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>mmourgos@chromium.org</owner>
   <owner>newcomer@chromium.org</owner>
   <summary>
@@ -1867,7 +1867,7 @@
 </histogram>
 
 <histogram name="Apps.AppListSearchResultInternalApp.Show"
-    enum="AppListInternalAppName" expires_after="2022-05-01">
+    enum="AppListInternalAppName" expires_after="2022-07-03">
   <owner>wutao@chromium.org</owner>
   <summary>
     The app list search result of an internal app that was shown to the user.
@@ -2200,7 +2200,7 @@
 </histogram>
 
 <histogram name="Apps.CreateShortcutIcon.Linux.Result"
-    enum="WebAppCreateShortcutIconLinuxResult" expires_after="2022-05-01">
+    enum="WebAppCreateShortcutIconLinuxResult" expires_after="2022-07-03">
   <owner>estade@chromium.org</owner>
   <owner>desktop-pwas-team@google.com</owner>
   <summary>
@@ -2218,7 +2218,7 @@
 </histogram>
 
 <histogram name="Apps.CreateShortcuts.Mac.Result"
-    enum="WebAppCreateShortcutMacResult" expires_after="2022-05-01">
+    enum="WebAppCreateShortcutMacResult" expires_after="2022-07-03">
   <owner>phillis@chromium.org</owner>
   <owner>cmumford@chromium.org</owner>
   <summary>
@@ -2388,7 +2388,7 @@
 </histogram>
 
 <histogram name="Apps.Launcher.InstallLocallyShortcutsCreated" enum="Boolean"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>dmurph@chromium.org</owner>
   <owner>desktop-pwas-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml
index 94feabc..b794f97a 100644
--- a/tools/metrics/histograms/metadata/autofill/histograms.xml
+++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -198,7 +198,7 @@
 
 <histogram
     name="Autofill.Ablation.FillDurationSinceInteraction.{FormType}.{Group}"
-    units="ms" expires_after="M100">
+    units="ms" expires_after="M108">
   <owner>battre@chromium.org</owner>
   <owner>chrome-autofill-team@google.com</owner>
   <summary>
@@ -213,7 +213,7 @@
 
 <histogram
     name="Autofill.Ablation.FormSubmissionAfterInteraction.{FormType}.{Group}"
-    enum="Boolean" expires_after="M100">
+    enum="Boolean" expires_after="M108">
   <owner>battre@chromium.org</owner>
   <owner>chrome-autofill-team@google.com</owner>
   <summary>
@@ -2434,7 +2434,7 @@
 </histogram>
 
 <histogram name="Autofill.ProfileImport.NewProfileEditedType"
-    enum="AutofillSettingsVisibleTypes" expires_after="2022-04-24">
+    enum="AutofillSettingsVisibleTypes" expires_after="2022-07-03">
   <owner>koerber@google.com</owner>
   <owner>src/components/autofill/OWNERS</owner>
   <summary>
@@ -2446,7 +2446,7 @@
 </histogram>
 
 <histogram name="Autofill.ProfileImport.NewProfileNumberOfEditedFields"
-    units="fields" expires_after="2022-04-24">
+    units="fields" expires_after="2022-07-03">
   <owner>koerber@google.com</owner>
   <owner>src/components/autofill/OWNERS</owner>
   <summary>
@@ -2545,7 +2545,7 @@
 </histogram>
 
 <histogram name="Autofill.ProfileImport.UpdateProfileEditedType"
-    enum="AutofillSettingsVisibleTypes" expires_after="2022-04-17">
+    enum="AutofillSettingsVisibleTypes" expires_after="2022-07-03">
   <owner>koerber@google.com</owner>
   <owner>src/components/autofill/OWNERS</owner>
   <summary>
@@ -2611,7 +2611,7 @@
 </histogram>
 
 <histogram name="Autofill.ProfileImport.UpdateProfileNumberOfEditedFields"
-    units="fields" expires_after="2022-04-17">
+    units="fields" expires_after="2022-07-03">
   <owner>koerber@google.com</owner>
   <owner>src/components/autofill/OWNERS</owner>
   <summary>
@@ -3180,7 +3180,7 @@
 </histogram>
 
 <histogram name="Autofill.SuggestionShown.OffTheRecord" units="units"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>rhalavati@chromium.org</owner>
   <owner>chrome-privacy-core@google.com</owner>
   <summary>
@@ -3242,7 +3242,7 @@
 </histogram>
 
 <histogram name="Autofill.UnmaskPrompt.Events" enum="AutofillUnmaskPromptEvent"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml
index 5af2c70a..4a6771e 100644
--- a/tools/metrics/histograms/metadata/blink/histograms.xml
+++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -88,7 +88,7 @@
 </histogram>
 
 <histogram name="Blink.Animation.CompositedAnimationFailureReason"
-    enum="CompositorAnimationsFailureReason" expires_after="2022-05-01">
+    enum="CompositorAnimationsFailureReason" expires_after="2022-07-03">
   <owner>smcgruer@chromium.org</owner>
   <owner>animations-dev@chromium.org</owner>
   <summary>
@@ -732,7 +732,7 @@
 </histogram>
 
 <histogram name="Blink.Canvas.WebGPUStaleResourceCount"
-    units="recyclable resources" expires_after="2022-05-01">
+    units="recyclable resources" expires_after="2022-07-03">
   <owner>magchen@chromium.org</owner>
   <owner>enga@chromium.org</owner>
   <summary>
@@ -1870,7 +1870,7 @@
 </histogram>
 
 <histogram name="Blink.ImageDecoders.Jpeg.ColorSpace" enum="JpegColorSpace"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>andrescj@chromium.org</owner>
   <owner>mcasas@chromium.org</owner>
   <summary>
@@ -2442,7 +2442,7 @@
 </histogram>
 
 <histogram base="true" name="Blink.MainFrame.UpdateTime" units="microseconds"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" -->
 
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" -->
@@ -2668,7 +2668,7 @@
 </histogram>
 
 <histogram base="true" name="Blink.Paint.UpdateTime" units="microseconds"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" -->
 
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" -->
@@ -2897,7 +2897,7 @@
 </histogram>
 
 <histogram base="true" name="Blink.ScrollDocumentUpdate.UpdateTime"
-    units="microseconds" expires_after="2022-05-01">
+    units="microseconds" expires_after="2022-07-03">
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" -->
 
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" -->
@@ -2944,7 +2944,7 @@
 </histogram>
 
 <histogram base="true" name="Blink.ServiceDocumentUpdate.UpdateTime"
-    units="microseconds" expires_after="2022-05-01">
+    units="microseconds" expires_after="2022-07-03">
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" -->
 
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" -->
@@ -3494,7 +3494,7 @@
 </histogram>
 
 <histogram base="true" name="Blink.UserDrivenDocumentUpdate.UpdateTime"
-    units="microseconds" expires_after="2022-05-01">
+    units="microseconds" expires_after="2022-07-03">
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" -->
 
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" -->
diff --git a/tools/metrics/histograms/metadata/bluetooth/histograms.xml b/tools/metrics/histograms/metadata/bluetooth/histograms.xml
index c30fed417..90e1090 100644
--- a/tools/metrics/histograms/metadata/bluetooth/histograms.xml
+++ b/tools/metrics/histograms/metadata/bluetooth/histograms.xml
@@ -1313,7 +1313,7 @@
 </histogram>
 
 <histogram name="Bluetooth.Web.RequestDevice.UnionOfServices.Services"
-    enum="GATTServiceHash" expires_after="2022-04-24">
+    enum="GATTServiceHash" expires_after="2022-07-03">
   <owner>reillyg@chromium.org</owner>
   <owner>deviceapi-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/chrome/histograms.xml b/tools/metrics/histograms/metadata/chrome/histograms.xml
index a4cdf28..f333d03 100644
--- a/tools/metrics/histograms/metadata/chrome/histograms.xml
+++ b/tools/metrics/histograms/metadata/chrome/histograms.xml
@@ -98,7 +98,7 @@
 </histogram>
 
 <histogram name="Chrome.ProcessSingleton.TimeToCreate" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>etienneb@chromium.org</owner>
   <owner>gab@chromium.org</owner>
   <summary>
@@ -108,7 +108,7 @@
 </histogram>
 
 <histogram name="Chrome.ProcessSingleton.TimeToFailure" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>etienneb@chromium.org</owner>
   <owner>gab@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/chromeos/histograms.xml b/tools/metrics/histograms/metadata/chromeos/histograms.xml
index e2bfa5e..34c207b 100644
--- a/tools/metrics/histograms/metadata/chromeos/histograms.xml
+++ b/tools/metrics/histograms/metadata/chromeos/histograms.xml
@@ -910,7 +910,7 @@
 </histogram>
 
 <histogram name="ChromeOS.HardwareVerifier.Report.IsCompliant" enum="Boolean"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>itspeter@chromium.org</owner>
   <owner>stimim@chromium.org</owner>
   <owner>chromeos-hw-checker@google.com</owner>
@@ -1316,7 +1316,7 @@
 </histogram>
 
 <histogram name="ChromeOS.PlatformVerification.Result2"
-    enum="ChromeOSPlatformVerificationResult2" expires_after="2022-05-01">
+    enum="ChromeOSPlatformVerificationResult2" expires_after="2022-07-03">
   <owner>erikchen@chromium.org</owner>
   <owner>cros-hwsec+uma@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/compositing/histograms.xml b/tools/metrics/histograms/metadata/compositing/histograms.xml
index 63667e3e..84ad605a 100644
--- a/tools/metrics/histograms/metadata/compositing/histograms.xml
+++ b/tools/metrics/histograms/metadata/compositing/histograms.xml
@@ -172,7 +172,7 @@
 </histogram>
 
 <histogram name="Compositing.DirectRenderer.OverlayProcessingUs"
-    units="microseconds" expires_after="2022-05-01">
+    units="microseconds" expires_after="2022-07-03">
   <owner>khaslett@chromium.org</owner>
   <owner>kylechar@chromium.org</owner>
   <summary>
@@ -483,7 +483,7 @@
 </histogram>
 
 <histogram name="Compositing.Renderer.CALayerResult" enum="CALayerResult"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>ccameron@chromium.org</owner>
   <owner>graphics-dev@chromium.org</owner>
   <summary>
@@ -720,7 +720,7 @@
 </histogram>
 
 <histogram name="Compositing.SurfaceAggregator.CopiedSurfaceCount"
-    units="surfaces" expires_after="2022-05-01">
+    units="surfaces" expires_after="2022-07-03">
   <owner>kylechar@chromium.org</owner>
   <owner>jonross@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/content/histograms.xml b/tools/metrics/histograms/metadata/content/histograms.xml
index 5575c695..d9b821ed5 100644
--- a/tools/metrics/histograms/metadata/content/histograms.xml
+++ b/tools/metrics/histograms/metadata/content/histograms.xml
@@ -422,7 +422,7 @@
 </histogram>
 
 <histogram name="ContentSettings.ExtensionNonEmbeddedSettingSet"
-    enum="ContentType" expires_after="2022-05-01">
+    enum="ContentType" expires_after="2022-07-03">
   <owner>engedy@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
@@ -624,7 +624,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.ActivityLoggingEnabled" enum="Boolean"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>rogerm@chromium.org</owner>
   <owner>feed@chromium.org</owner>
   <summary>
@@ -737,7 +737,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.ContentAgeOnLoad.BlockingRefresh"
-    units="ms" expires_after="2022-05-01">
+    units="ms" expires_after="2022-07-03">
   <owner>carlosk@chromium.org</owner>
   <owner>harringtond@chromium.org</owner>
   <owner>feed@chromium.org</owner>
@@ -751,7 +751,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.ContentAgeOnLoad.NotRefreshed"
-    units="ms" expires_after="2022-05-01">
+    units="ms" expires_after="2022-07-03">
   <owner>carlosk@chromium.org</owner>
   <owner>harringtond@chromium.org</owner>
   <owner>feed@chromium.org</owner>
@@ -911,7 +911,7 @@
 </histogram>
 
 <histogram base="true" name="ContentSuggestions.Feed.LoadStepLatency"
-    units="ms" expires_after="2022-05-01">
+    units="ms" expires_after="2022-07-03">
   <owner>harringtond@chromium.org</owner>
   <owner>feed@chromium.org</owner>
   <summary>
@@ -925,7 +925,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.LoadStreamStatus.LoadMore"
-    enum="FeedLoadStreamStatus" expires_after="2022-05-01">
+    enum="FeedLoadStreamStatus" expires_after="2022-07-03">
   <owner>harringtond@chromium.org</owner>
   <owner>carlosk@chromium.org</owner>
   <owner>feed@chromium.org</owner>
@@ -949,7 +949,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.Network.CompressedResponseSizeKB"
-    units="KB" expires_after="2022-05-01">
+    units="KB" expires_after="2022-07-03">
   <owner>carlosk@chromium.org</owner>
   <owner>harringtond@chromium.org</owner>
   <owner>feed@chromium.org</owner>
@@ -961,7 +961,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.Network.Duration" units="ms"
-    expires_after="2022-06-26">
+    expires_after="2022-07-03">
   <owner>carlosk@chromium.org</owner>
   <owner>harringtond@chromium.org</owner>
   <owner>feed@chromium.org</owner>
@@ -1012,7 +1012,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.Network.ResponseSizeKB" units="KB"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>carlosk@chromium.org</owner>
   <owner>harringtond@chromium.org</owner>
   <owner>feed@chromium.org</owner>
@@ -1023,7 +1023,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.Network.ResponseStatus"
-    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-05-01">
+    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-07-03">
   <owner>carlosk@chromium.org</owner>
   <owner>harringtond@chromium.org</owner>
   <owner>feed@chromium.org</owner>
@@ -1057,7 +1057,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.NoticeCardFulfilled" enum="Boolean"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>vincb@google.com</owner>
   <owner>feed@chromium.org</owner>
   <summary>
@@ -1261,7 +1261,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.TimeSpentInFeed" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>carlosk@chromium.org</owner>
   <owner>harringtond@chromium.org</owner>
   <owner>feed@chromium.org</owner>
@@ -1353,7 +1353,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.UserActions" enum="FeedUserActionType"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>harringtond@chromium.org</owner>
   <owner>carlosk@chromium.org</owner>
   <owner>feed@chromium.org</owner>
@@ -1364,7 +1364,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.UserActions.Commands"
-    enum="FeedUserCommandType" expires_after="2022-05-01">
+    enum="FeedUserCommandType" expires_after="2022-07-03">
   <owner>harringtond@chromium.org</owner>
   <owner>sczs@chromium.org</owner>
   <owner>feed@chromium.org</owner>
@@ -1387,7 +1387,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.UserJourney.GetMore.SuccessDuration"
-    units="ms" expires_after="2022-05-01">
+    units="ms" expires_after="2022-07-03">
   <owner>harringtond@chromium.org</owner>
   <owner>carlosk@chromium.org</owner>
   <owner>feed@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/content_creation/histograms.xml b/tools/metrics/histograms/metadata/content_creation/histograms.xml
index cfa744d..6ccb549 100644
--- a/tools/metrics/histograms/metadata/content_creation/histograms.xml
+++ b/tools/metrics/histograms/metadata/content_creation/histograms.xml
@@ -305,7 +305,7 @@
 </histogram>
 
 <histogram name="SharedHighlights.AsyncTask.SearchDuration" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>gayane@chromium.org</owner>
   <owner>chrome-shared-highlighting@google.com</owner>
   <summary>
@@ -336,7 +336,7 @@
 </histogram>
 
 <histogram name="SharedHighlights.LinkGenerated.Error.Iterations"
-    units="iterations" expires_after="2022-05-01">
+    units="iterations" expires_after="2022-07-03">
   <owner>gayane@chromium.org</owner>
   <owner>chrome-shared-highlighting@google.com</owner>
   <summary>
@@ -457,7 +457,7 @@
 </histogram>
 
 <histogram name="TextFragmentAnchor.ElementIdFragmentFound" enum="Boolean"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>bokan@chromium.org</owner>
   <owner>chrome-shared-highlighting@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/cookie/histograms.xml b/tools/metrics/histograms/metadata/cookie/histograms.xml
index 41026f0..986a957 100644
--- a/tools/metrics/histograms/metadata/cookie/histograms.xml
+++ b/tools/metrics/histograms/metadata/cookie/histograms.xml
@@ -67,7 +67,7 @@
 </histogram>
 
 <histogram name="Cookie.CookiePrefix" enum="CookiePrefix"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>estark@chromium.org</owner>
   <summary>
     Number of times a cookie was set with a name prefixed by
@@ -94,7 +94,7 @@
 </histogram>
 
 <histogram name="Cookie.CookieSchemeRequestScheme" enum="CookieRequestScheme"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>bingler@chromium.org</owner>
   <owner>miketaylr@chromium.org</owner>
   <summary>
@@ -105,7 +105,7 @@
 </histogram>
 
 <histogram name="Cookie.CookieSourceScheme" enum="CookieSourceScheme"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>estark@chromium.org</owner>
   <summary>
     For each cookie added to the store, record whether its source URL has a
@@ -532,7 +532,7 @@
 </histogram>
 
 <histogram name="Cookie.Port.OmniboxURLNavigation.Localhost"
-    enum="InterestingCookiePorts" expires_after="2022-05-01">
+    enum="InterestingCookiePorts" expires_after="2022-07-03">
   <owner>bingler@chromium.org</owner>
   <owner>miketaylr@chromium.org</owner>
   <summary>
@@ -553,7 +553,7 @@
 </histogram>
 
 <histogram name="Cookie.Port.OmniboxURLNavigation.RemoteHost"
-    enum="InterestingCookiePorts" expires_after="2022-05-01">
+    enum="InterestingCookiePorts" expires_after="2022-07-03">
   <owner>bingler@chromium.org</owner>
   <owner>miketaylr@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/cras/histograms.xml b/tools/metrics/histograms/metadata/cras/histograms.xml
index b59e15d..2d2895d 100644
--- a/tools/metrics/histograms/metadata/cras/histograms.xml
+++ b/tools/metrics/histograms/metadata/cras/histograms.xml
@@ -837,6 +837,20 @@
   </token>
 </histogram>
 
+<histogram name="Cras.SetAecRefDeviceType" enum="CrasDeviceType"
+    expires_after="2023-01-03">
+  <owner>hychao@chromium.org</owner>
+  <owner>chromeos-audio@google.com</owner>
+  <summary>
+    It is used to log the call to InputStream::SetOutputDeviceForAec() which
+    results different types of audio device being set as AEC referefence in
+    CRAS(Chrome OS audio server). Based on this metrics we can analyze the user
+    behavior in voice communication app. Note that CRAS_METRICS_DEVICE_NO_DEVICE
+    is tracking the case when the call sets a NULL device meaning to leave AEC
+    reference on system default.
+  </summary>
+</histogram>
+
 <histogram name="Cras.StreamCallbackThreshold" units="frames"
     expires_after="2022-04-24">
 <!-- Name completed by histogram_suffixes
diff --git a/tools/metrics/histograms/metadata/cros/histograms.xml b/tools/metrics/histograms/metadata/cros/histograms.xml
index 390a313..d29ef71 100644
--- a/tools/metrics/histograms/metadata/cros/histograms.xml
+++ b/tools/metrics/histograms/metadata/cros/histograms.xml
@@ -119,7 +119,7 @@
 </histogram>
 
 <histogram name="CrosDisksClient.FormatTime" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>austinct@chromium.org</owner>
   <summary>
     Time taken for the Chrome OS cros-disks daemon to perform a format
diff --git a/tools/metrics/histograms/metadata/cross_device/histograms.xml b/tools/metrics/histograms/metadata/cross_device/histograms.xml
index 347bcebab..74d5c1e 100644
--- a/tools/metrics/histograms/metadata/cross_device/histograms.xml
+++ b/tools/metrics/histograms/metadata/cross_device/histograms.xml
@@ -1214,6 +1214,9 @@
 
 <histogram name="EasyUnlock.StartupTimeFromSuspend" units="ms"
     expires_after="2022-02-02">
+  <obsolete>
+    Deprecated as of 12/29/2021.
+  </obsolete>
   <owner>hansberry@chromium.org</owner>
   <owner>better-together-dev@google.com</owner>
   <summary>
@@ -1899,7 +1902,7 @@
 </histogram>
 
 <histogram name="MultiDevice.SecureChannel.Nearby.MessageAction"
-    enum="MultiDeviceNearbyMessageAction" expires_after="2022-05-01">
+    enum="MultiDeviceNearbyMessageAction" expires_after="2022-07-03">
   <owner>hansenmichael@google.com</owner>
   <owner>better-together-dev@google.com</owner>
   <summary>
@@ -2163,7 +2166,7 @@
 </histogram>
 
 <histogram name="SmartLock.AuthResult.SignIn.Failure.UserControllerAuth"
-    enum="LoginFailureReason" expires_after="2022-02-01">
+    enum="LoginFailureReason" expires_after="2022-06-05">
   <owner>hansberry@chromium.org</owner>
   <owner>better-together-dev@google.com</owner>
   <summary>
@@ -2194,6 +2197,9 @@
 
 <histogram name="SmartLock.EligibleDevicesCount" units="devices"
     expires_after="2022-02-02">
+  <obsolete>
+    Deprecated as of 12/29/2021.
+  </obsolete>
   <owner>hansberry@chromium.org</owner>
   <owner>better-together-dev@google.com</owner>
   <summary>
@@ -2229,7 +2235,7 @@
 </histogram>
 
 <histogram name="SmartLock.FindAndConnectToHostResult.SignIn"
-    enum="SmartLockFindAndConnectToHostResult" expires_after="2022-02-02">
+    enum="SmartLockFindAndConnectToHostResult" expires_after="2022-06-05">
   <owner>hansberry@chromium.org</owner>
   <owner>better-together-dev@google.com</owner>
   <summary>
@@ -2379,7 +2385,10 @@
 
 <histogram name="SmartLock.ToggleFeature" enum="BooleanEnabled"
     expires_after="2022-02-02">
-  <owner>jhawkins@chromium.org</owner>
+  <obsolete>
+    Deprecated as of 12/29/2021.
+  </obsolete>
+  <owner>hansberry@chromium.org</owner>
   <owner>better-together-dev@google.com</owner>
   <summary>
     The number of times the user actively enabled or disabled the SmartLock
@@ -2389,7 +2398,10 @@
 
 <histogram name="SmartLock.ToggleFeature.Disable.Result" enum="BooleanSuccess"
     expires_after="2022-02-02">
-  <owner>jhawkins@chromium.org</owner>
+  <obsolete>
+    Deprecated as of 12/29/2021.
+  </obsolete>
+  <owner>hansberry@chromium.org</owner>
   <owner>better-together-dev@google.com</owner>
   <summary>The result of the operation to disable SmartLock.</summary>
 </histogram>
diff --git a/tools/metrics/histograms/metadata/crostini/histograms.xml b/tools/metrics/histograms/metadata/crostini/histograms.xml
index dcb358e7..93d89a92 100644
--- a/tools/metrics/histograms/metadata/crostini/histograms.xml
+++ b/tools/metrics/histograms/metadata/crostini/histograms.xml
@@ -46,7 +46,7 @@
 </histogram>
 
 <histogram name="Crostini.AppLaunchResult" enum="CrostiniResult"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>clumptini@google.com</owner>
   <owner>laurentt@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/data/histograms.xml b/tools/metrics/histograms/metadata/data/histograms.xml
index 54be802..5e5c406 100644
--- a/tools/metrics/histograms/metadata/data/histograms.xml
+++ b/tools/metrics/histograms/metadata/data/histograms.xml
@@ -281,7 +281,7 @@
 </histogram>
 
 <histogram name="DataReductionProxy.LastWeekAggregateKB.Services"
-    enum="DataUseServicesHash" expires_after="2022-05-01">
+    enum="DataUseServicesHash" expires_after="2022-07-03">
   <owner>rajendrant@chromium.org</owner>
   <owner>bengr@chromium.org</owner>
   <summary>
@@ -296,7 +296,7 @@
 
 <histogram
     name="DataReductionProxy.LastWeekAggregateKB.UserTraffic.Downstream.ContentType"
-    enum="DataUseContentType" expires_after="2022-05-01">
+    enum="DataUseContentType" expires_after="2022-07-03">
   <owner>rajendrant@chromium.org</owner>
   <owner>bengr@chromium.org</owner>
   <summary>
@@ -398,7 +398,7 @@
 </histogram>
 
 <histogram name="DataReductionProxy.ThisWeekAggregateKB.Services"
-    enum="DataUseServicesHash" expires_after="2022-05-01">
+    enum="DataUseServicesHash" expires_after="2022-07-03">
   <owner>rajendrant@chromium.org</owner>
   <owner>mcrouse@chromium.org</owner>
   <summary>
@@ -413,7 +413,7 @@
 
 <histogram
     name="DataReductionProxy.ThisWeekAggregateKB.UserTraffic.Downstream.ContentType"
-    enum="DataUseContentType" expires_after="2022-05-01">
+    enum="DataUseContentType" expires_after="2022-07-03">
   <owner>rajendrant@chromium.org</owner>
   <owner>mcrouse@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/disk/histograms.xml b/tools/metrics/histograms/metadata/disk/histograms.xml
index af8b380b..3762add0 100644
--- a/tools/metrics/histograms/metadata/disk/histograms.xml
+++ b/tools/metrics/histograms/metadata/disk/histograms.xml
@@ -125,7 +125,7 @@
 </histogram>
 
 <histogram name="DiskCache.0.Error" enum="DiskCacheError"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>wfh@chromium.org</owner>
   <owner>src/net/disk_cache/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/download/histograms.xml b/tools/metrics/histograms/metadata/download/histograms.xml
index 8d73c727..bba04778 100644
--- a/tools/metrics/histograms/metadata/download/histograms.xml
+++ b/tools/metrics/histograms/metadata/download/histograms.xml
@@ -147,7 +147,7 @@
 </histogram>
 
 <histogram name="Download.DangerousFile.DownloadValidatedByType"
-    enum="SBClientDownloadExtensions" expires_after="2022-04-17">
+    enum="SBClientDownloadExtensions" expires_after="2022-07-03">
   <owner>drubery@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@chromium.org</owner>
   <summary>
@@ -602,7 +602,7 @@
 </histogram>
 
 <histogram base="true" name="Download.NetworkConnectionType.Complete"
-    enum="NetworkConnectionType" expires_after="2022-04-30">
+    enum="NetworkConnectionType" expires_after="2022-07-03">
 <!-- Name completed by histogram_suffixes name="DownloadSource" -->
 
   <owner>dtrainor@chromium.org</owner>
@@ -611,7 +611,7 @@
 </histogram>
 
 <histogram base="true" name="Download.NetworkConnectionType.StartNew"
-    enum="NetworkConnectionType" expires_after="2022-04-30">
+    enum="NetworkConnectionType" expires_after="2022-07-03">
 <!-- Name completed by histogram_suffixes name="DownloadSource" -->
 
   <owner>dtrainor@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/enterprise/histograms.xml b/tools/metrics/histograms/metadata/enterprise/histograms.xml
index 5097f0cb..92a064e 100644
--- a/tools/metrics/histograms/metadata/enterprise/histograms.xml
+++ b/tools/metrics/histograms/metadata/enterprise/histograms.xml
@@ -1562,7 +1562,7 @@
 
 <histogram
     name="Enterprise.FCMInvalidationService.PolicyInvalidationsRegistrationResult"
-    enum="BooleanSuccess" expires_after="2022-05-01">
+    enum="BooleanSuccess" expires_after="2022-07-03">
   <owner>asumaneev@google.com</owner>
   <owner>managed-platforms@google.com</owner>
   <summary>
@@ -1901,7 +1901,7 @@
 </histogram>
 
 <histogram name="Enterprise.PolicyInvalidations"
-    enum="EnterprisePolicyInvalidations" expires_after="2022-05-01">
+    enum="EnterprisePolicyInvalidations" expires_after="2022-07-03">
   <owner>asumaneev@google.com</owner>
   <owner>managed-platforms@google.com</owner>
   <summary>
@@ -1913,7 +1913,7 @@
 </histogram>
 
 <histogram name="Enterprise.PolicyInvalidationsRegistrationResult"
-    enum="BooleanSuccess" expires_after="2022-05-01">
+    enum="BooleanSuccess" expires_after="2022-07-03">
   <owner>asumaneev@google.com</owner>
   <owner>managed-platforms@google.com</owner>
   <summary>
@@ -2098,7 +2098,7 @@
 </histogram>
 
 <histogram name="Enterprise.RemoteCommandInvalidationsRegistrationResult"
-    enum="BooleanSuccess" expires_after="2022-05-01">
+    enum="BooleanSuccess" expires_after="2022-07-03">
   <owner>asumaneev@google.com</owner>
   <owner>managed-platforms@google.com</owner>
   <summary>
@@ -2186,7 +2186,7 @@
 </histogram>
 
 <histogram name="Enterprise.SystemLogUploadResult"
-    enum="EnterpriseSystemLogUploadResult" expires_after="2022-05-01">
+    enum="EnterpriseSystemLogUploadResult" expires_after="2022-07-03">
   <owner>bmalcolm@chromium.org</owner>
   <owner>cros-client-wa@google.com</owner>
   <summary>Result of a single attempt to upload system logs.</summary>
diff --git a/tools/metrics/histograms/metadata/event/histograms.xml b/tools/metrics/histograms/metadata/event/histograms.xml
index 94bc231..01422397 100644
--- a/tools/metrics/histograms/metadata/event/histograms.xml
+++ b/tools/metrics/histograms/metadata/event/histograms.xml
@@ -1163,7 +1163,7 @@
 
 <histogram
     name="Event.Latency.ScrollBegin.Wheel.BrowserNotifiedToBeforeGpuSwap2"
-    units="microseconds" expires_after="2022-05-01">
+    units="microseconds" expires_after="2022-07-03">
   <owner>flackr@chromium.org</owner>
   <owner>input-dev@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/extensions/histograms.xml b/tools/metrics/histograms/metadata/extensions/histograms.xml
index d4673cd2..f886d8189 100644
--- a/tools/metrics/histograms/metadata/extensions/histograms.xml
+++ b/tools/metrics/histograms/metadata/extensions/histograms.xml
@@ -822,7 +822,7 @@
 </histogram>
 
 <histogram name="Extensions.DeclarativeNetRequest.RequestHeaderAdded"
-    enum="WebRequest.RequestHeader" expires_after="2022-05-01">
+    enum="WebRequest.RequestHeader" expires_after="2022-07-03">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>kelvinjiang@chromium.org</owner>
   <owner>src/extensions/OWNERS</owner>
@@ -834,7 +834,7 @@
 </histogram>
 
 <histogram name="Extensions.DeclarativeNetRequest.RequestHeaderChanged"
-    enum="WebRequest.RequestHeader" expires_after="2022-05-01">
+    enum="WebRequest.RequestHeader" expires_after="2022-07-03">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>kelvinjiang@chromium.org</owner>
   <owner>src/extensions/OWNERS</owner>
@@ -882,7 +882,7 @@
 </histogram>
 
 <histogram name="Extensions.DeclarativeNetRequest.ResponseHeaderRemoved"
-    enum="WebRequest.ResponseHeader" expires_after="2022-05-01">
+    enum="WebRequest.ResponseHeader" expires_after="2022-07-03">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>kelvinjiang@chromium.org</owner>
   <owner>src/extensions/OWNERS</owner>
@@ -3197,7 +3197,7 @@
 </histogram>
 
 <histogram name="Extensions.NewTabPageOverrides" units="units"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>kelvinjiang@chromium.org</owner>
   <summary>
@@ -3782,7 +3782,7 @@
 </histogram>
 
 <histogram name="Extensions.Toolbar.InvocationSource"
-    enum="ExtensionActionInvocationSource" expires_after="2022-05-01">
+    enum="ExtensionActionInvocationSource" expires_after="2022-07-03">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/feature_engagement/histograms.xml b/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
index 142a998..2aeaf7dd 100644
--- a/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
+++ b/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
@@ -256,7 +256,7 @@
 </variants>
 
 <histogram name="InProductHelp.Config.ParsingEvent" enum="ConfigParsingEvent"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>nyquist@chromium.org</owner>
   <owner>xingliu@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/gpu/histograms.xml b/tools/metrics/histograms/metadata/gpu/histograms.xml
index 56377c7b..155c6447 100644
--- a/tools/metrics/histograms/metadata/gpu/histograms.xml
+++ b/tools/metrics/histograms/metadata/gpu/histograms.xml
@@ -491,7 +491,7 @@
 </histogram>
 
 <histogram name="GPU.BlocklistTestResultsPerEntry"
-    enum="GPUBlocklistTestResultPerEntry" expires_after="2022-05-01">
+    enum="GPUBlocklistTestResultPerEntry" expires_after="2022-07-03">
   <owner>vmiura@chromium.org</owner>
   <owner>graphics-dev@chromium.org</owner>
   <summary>
@@ -790,7 +790,7 @@
 </histogram>
 
 <histogram name="GPU.DirectComposition.IsUnderlay" enum="BooleanUnderlay"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>magchen@chromium.org</owner>
   <owner>zmo@chromium.org</owner>
   <summary>
@@ -1210,7 +1210,7 @@
 </histogram>
 
 <histogram name="GPU.InitializeOneOffMediumTime" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>jonahr@google.com</owner>
   <owner>angle-team@google.com</owner>
   <summary>
@@ -1249,7 +1249,7 @@
 </histogram>
 
 <histogram name="GPU.IOSurface.CreateTime" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>ccameron@chromium.org</owner>
   <summary>
     The time that it took for a call to IOSurfaceCreate to complete.
@@ -1265,7 +1265,7 @@
 </histogram>
 
 <histogram name="GPU.IOSurface.TexImageTime" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>ccameron@chromium.org</owner>
   <summary>
     The time that it took for a call to CGLTexImageIOSurface2D to complete.
@@ -2137,7 +2137,7 @@
 </histogram>
 
 <histogram name="Viz.DisplayCompositor.OverlaySwitchInterval" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>petermcneeley@chromium.org</owner>
   <owner>dcastagna@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/history/histograms.xml b/tools/metrics/histograms/metadata/history/histograms.xml
index 0743860a..e1e92f5 100644
--- a/tools/metrics/histograms/metadata/history/histograms.xml
+++ b/tools/metrics/histograms/metadata/history/histograms.xml
@@ -964,7 +964,7 @@
 </histogram>
 
 <histogram name="History.HistoryPageView" enum="HistoryPageView"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>calamity@chromium.org</owner>
   <owner>src/chrome/browser/resources/history/OWNERS</owner>
   <summary>
@@ -1055,7 +1055,7 @@
 </histogram>
 
 <histogram name="History.InMemoryURLIndexingTime" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>mpearson@chromium.org</owner>
   <owner>ssid@chromium.org</owner>
   <summary>
@@ -1065,7 +1065,7 @@
 </histogram>
 
 <histogram name="History.InMemoryURLIndexingTime.RoundTripTime" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>tommycli@chromium.org</owner>
   <owner>mpearson@chromium.org</owner>
   <summary>
@@ -1091,7 +1091,7 @@
 </histogram>
 
 <histogram name="History.InMemoryURLIndexSaveCacheTime" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>tommycli@chromium.org</owner>
   <owner>mpearson@chromium.org</owner>
   <summary>
@@ -1293,7 +1293,7 @@
 </histogram>
 
 <histogram name="History.WeeklyURLCount" units="URLs"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>mpearson@chromium.org</owner>
   <owner>sky@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/input/histograms.xml b/tools/metrics/histograms/metadata/input/histograms.xml
index f4ffa64..d71e3542 100644
--- a/tools/metrics/histograms/metadata/input/histograms.xml
+++ b/tools/metrics/histograms/metadata/input/histograms.xml
@@ -990,7 +990,7 @@
 </histogram>
 
 <histogram name="InputMethod.VirtualKeyboard.InitLatency.KeyboardShownLongTail"
-    units="ms" expires_after="2022-05-01">
+    units="ms" expires_after="2022-07-03">
   <owner>jopalmer@chromium.org</owner>
   <owner>essential-inputs-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/ios/histograms.xml b/tools/metrics/histograms/metadata/ios/histograms.xml
index febd05d..7ff2dc1 100644
--- a/tools/metrics/histograms/metadata/ios/histograms.xml
+++ b/tools/metrics/histograms/metadata/ios/histograms.xml
@@ -1157,7 +1157,7 @@
 </histogram>
 
 <histogram name="IOS.Reauth.Password.ManualFallback"
-    enum="ReauthenticationEvent" expires_after="2022-05-01">
+    enum="ReauthenticationEvent" expires_after="2022-07-03">
   <owner>sarraf@google.com</owner>
   <owner>djean@chromium.org</owner>
   <summary>
@@ -1332,7 +1332,7 @@
   </summary>
 </histogram>
 
-<histogram name="IOS.Snapshots.ImageSize" units="KB" expires_after="2022-05-01">
+<histogram name="IOS.Snapshots.ImageSize" units="KB" expires_after="2022-07-03">
   <owner>ajuma@chromium.org</owner>
   <owner>edchin@chromium.org</owner>
   <summary>
@@ -1458,7 +1458,7 @@
 </histogram>
 
 <histogram name="IOS.TabSwitcher.PageChangeInteraction"
-    enum="IOSTabSwitcherPageChangeInteraction" expires_after="2022-05-01">
+    enum="IOSTabSwitcherPageChangeInteraction" expires_after="2022-07-03">
   <owner>marq@chromium.org</owner>
   <owner>bling-team@google.com</owner>
   <summary>
@@ -1478,7 +1478,7 @@
 </histogram>
 
 <histogram name="IOS.Web.URLDidChangeToEmptyURL" enum="BooleanHit"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>gambard@chromium.org</owner>
   <owner>justincohen@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/login/histograms.xml b/tools/metrics/histograms/metadata/login/histograms.xml
index f00b27e..1310866 100644
--- a/tools/metrics/histograms/metadata/login/histograms.xml
+++ b/tools/metrics/histograms/metadata/login/histograms.xml
@@ -259,7 +259,7 @@
 </histogram>
 
 <histogram name="Login.SessionExitType" enum="LoginSessionExitType"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>iby@chromium.org</owner>
   <summary>
     Tracks whether a ChromeOS user was logged out because Chrome repeatedly
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml
index 4c6a0cd3..da4811be 100644
--- a/tools/metrics/histograms/metadata/media/histograms.xml
+++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -111,7 +111,7 @@
 </histogram>
 
 <histogram name="Media.Android.MediaPlayerWatchTime"
-    enum="MediaPlayerWatchTimeType" expires_after="2022-05-01">
+    enum="MediaPlayerWatchTimeType" expires_after="2022-07-03">
   <owner>sandersd@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -895,7 +895,7 @@
 </histogram>
 
 <histogram name="Media.Audio.Render.GetSourceDataTime.WebRTC"
-    units="microseconds" expires_after="2022-05-01">
+    units="microseconds" expires_after="2022-07-03">
   <owner>guidou@chromium.org</owner>
   <owner>olka@chromium.org</owner>
   <summary>
@@ -1023,7 +1023,7 @@
 
 <histogram
     name="Media.Audio.Render.SinkCache.GetOutputDeviceInfoCacheUtilization"
-    enum="GetOutputDeviceInfoCacheHit" expires_after="2022-05-01">
+    enum="GetOutputDeviceInfoCacheHit" expires_after="2022-07-03">
   <owner>guidou@chromium.org</owner>
   <owner>olka@chromium.org</owner>
   <summary>
@@ -1837,7 +1837,7 @@
 </histogram>
 
 <histogram name="Media.D3D11.DecoderLifetimeProgression"
-    enum="D3D11LifetimeProgression" expires_after="2022-05-01">
+    enum="D3D11LifetimeProgression" expires_after="2022-07-03">
   <owner>liberato@chromium.org</owner>
   <owner>tmathmeyer@chromium.org</owner>
   <summary>
@@ -2000,7 +2000,7 @@
 </histogram>
 
 <histogram name="Media.DXVAVDA.UseD3D11" enum="DXVADXVersion"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>liberato@chromium.org</owner>
   <owner>tmathmeyer@chromium.org</owner>
   <owner>sandersd@chromium.org</owner>
@@ -2615,7 +2615,7 @@
 </histogram>
 
 <histogram name="Media.GlobalMediaControls.InteractionDelayAfterPause"
-    units="ms" expires_after="2022-05-01">
+    units="ms" expires_after="2022-07-03">
   <owner>steimel@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -2649,7 +2649,7 @@
 </histogram>
 
 <histogram name="Media.GlobalMediaControls.UserActionFocus"
-    enum="BooleanFocused" expires_after="2022-05-01">
+    enum="BooleanFocused" expires_after="2022-07-03">
   <owner>steimel@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -3134,7 +3134,7 @@
 </histogram>
 
 <histogram name="Media.MeanTimeBetweenRebuffers" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>dalecurtis@chromium.org</owner>
   <summary>
     The total watch time (see Media.WatchTime) of a given playback divided by
@@ -3143,7 +3143,7 @@
 </histogram>
 
 <histogram name="Media.MediaElement.ContentTypeParseable"
-    enum="ContentTypeParseableResult" expires_after="2022-05-01">
+    enum="ContentTypeParseableResult" expires_after="2022-07-03">
   <owner>jrummell@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -4571,7 +4571,7 @@
 </histogram>
 
 <histogram name="Media.VaapiVideoDecoder.VaapiWrapperCreationSuccess"
-    enum="BooleanSuccess" expires_after="2022-05-01">
+    enum="BooleanSuccess" expires_after="2022-07-03">
   <owner>mcasas@chromium.org</owner>
   <owner>chromeos-gfx-video@google.com</owner>
   <summary>
@@ -4620,7 +4620,7 @@
 </histogram>
 
 <histogram name="Media.Video.Autoplay" enum="AutoplaySource"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>dalecurtis@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -4777,7 +4777,7 @@
 </histogram>
 
 <histogram name="Media.VideoCapture.Device.SupportedPixelFormat"
-    enum="VideoPixelFormatUnion" expires_after="2022-05-01">
+    enum="VideoPixelFormatUnion" expires_after="2022-07-03">
   <owner>eshr@google.com</owner>
   <owner>handellm@google.com</owner>
   <summary>
@@ -4867,7 +4867,7 @@
 
 <histogram
     name="Media.VideoCapture.Mac.Device.CapturedWithRequestedPixelFormat"
-    enum="Boolean" expires_after="2022-05-01">
+    enum="Boolean" expires_after="2022-07-03">
   <owner>eshr@google.com</owner>
   <owner>handellm@google.com</owner>
   <summary>
@@ -5004,7 +5004,7 @@
 </histogram>
 
 <histogram name="Media.VideoCapture.Win.Device.CapturePixelFormat"
-    enum="VideoPixelFormatUnion" expires_after="2022-05-01">
+    enum="VideoPixelFormatUnion" expires_after="2022-07-03">
   <owner>ilnik@google.com</owner>
   <owner>video-cmi-mpp@google.com</owner>
   <summary>
@@ -5014,7 +5014,7 @@
 </histogram>
 
 <histogram name="Media.VideoCapture.Win.Device.InternalPixelFormat"
-    enum="VideoPixelFormatUnion" expires_after="2022-05-01">
+    enum="VideoPixelFormatUnion" expires_after="2022-07-03">
   <owner>ilnik@google.com</owner>
   <owner>video-cmi-mpp@google.com</owner>
   <summary>
@@ -5024,7 +5024,7 @@
 </histogram>
 
 <histogram name="Media.VideoCapture.Win.Device.RequestedPixelFormat"
-    enum="VideoPixelFormatUnion" expires_after="2022-05-01">
+    enum="VideoPixelFormatUnion" expires_after="2022-07-03">
   <owner>ilnik@google.com</owner>
   <owner>video-cmi-mpp@google.com</owner>
   <summary>
@@ -5411,7 +5411,7 @@
   </summary>
 </histogram>
 
-<histogram name="Media.WatchTime" units="ms" expires_after="2022-05-01">
+<histogram name="Media.WatchTime" units="ms" expires_after="2022-07-03">
   <owner>dalecurtis@chromium.org</owner>
   <summary>
     Watch time is defined as the amount of elapsed media time for audio+video
@@ -5649,7 +5649,7 @@
 </histogram>
 
 <histogram name="MediaRouter.Cast.Discovery.CachedSinksAvailableCount"
-    units="devices" expires_after="2022-05-01">
+    units="devices" expires_after="2022-07-03">
   <owner>btolsch@chromium.org</owner>
   <owner>openscreen-eng@google.com</owner>
   <summary>
@@ -5669,7 +5669,7 @@
 </histogram>
 
 <histogram name="MediaRouter.Cast.Discovery.KnownDevicesCount" units="devices"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>mfoltz@chromium.org</owner>
   <owner>openscreen-eng@google.com</owner>
   <summary>
@@ -5679,7 +5679,7 @@
 </histogram>
 
 <histogram name="MediaRouter.Cast.Discovery.SinkSource"
-    enum="MediaRouterCastSinkSource" expires_after="2022-05-01">
+    enum="MediaRouterCastSinkSource" expires_after="2022-07-03">
   <owner>btolsch@chromium.org</owner>
   <owner>openscreen-eng@google.com</owner>
   <summary>The source of discovery for a newly-created Cast sink.</summary>
@@ -5752,7 +5752,7 @@
 </histogram>
 
 <histogram name="MediaRouter.CastStreaming.Session.Length" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>takumif@chromium.org</owner>
   <owner>openscreen-eng@google.com</owner>
   <summary>
@@ -6017,7 +6017,7 @@
 </histogram>
 
 <histogram name="MediaRouter.Provider.JoinRoute.Result"
-    enum="MediaRouteProviderResult" expires_after="2022-05-01">
+    enum="MediaRouteProviderResult" expires_after="2022-07-03">
 <!-- Name completed by histogram_suffixes name="MediaRouteProvider" -->
 
   <owner>takumif@chromium.org</owner>
@@ -6291,7 +6291,7 @@
 </histogram>
 
 <histogram name="MediaRouter.Ui.FirstAction" enum="MediaRouterUserAction"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>takumif@chromium.org</owner>
   <owner>openscreen-eng@google.com</owner>
   <summary>
@@ -6321,7 +6321,7 @@
 </histogram>
 
 <histogram name="MediaRouter.WiredDisplay.AvailableDevicesCount" units="units"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>takumif@chromium.org</owner>
   <owner>openscreen-eng@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/memory/histograms.xml b/tools/metrics/histograms/metadata/memory/histograms.xml
index 9fb29d0..6f59e134 100644
--- a/tools/metrics/histograms/metadata/memory/histograms.xml
+++ b/tools/metrics/histograms/metadata/memory/histograms.xml
@@ -537,7 +537,7 @@
 </histogram>
 
 <histogram name="Memory.Discardable.VirtualSize.Foreground" units="KiB"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>thiabaud@google.com</owner>
   <owner>lizeb@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/mobile/histograms.xml b/tools/metrics/histograms/metadata/mobile/histograms.xml
index bb28cb0d..d23473b 100644
--- a/tools/metrics/histograms/metadata/mobile/histograms.xml
+++ b/tools/metrics/histograms/metadata/mobile/histograms.xml
@@ -81,7 +81,7 @@
 </histogram>
 
 <histogram name="Mobile.AppMenu.TimeToTakeAction.SelectedItem" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>gangwu@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <summary>
@@ -288,7 +288,7 @@
 </histogram>
 
 <histogram base="true" name="Mobile.Messages.Passwords.Modal.Dismiss"
-    enum="MobileMessagesPasswordsModalDismiss" expires_after="2022-05-01">
+    enum="MobileMessagesPasswordsModalDismiss" expires_after="2022-07-03">
 <!-- Name completed by histogram_suffixes name="Mobile.Messages.Password.Type" -->
 
   <owner>sczs@chromium.org</owner>
@@ -906,7 +906,7 @@
 </histogram>
 
 <histogram name="MobileFre.Progress" enum="MobileFreProgress"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>bsazonov@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
   <owner>droger@chromium.org</owner>
@@ -1202,7 +1202,7 @@
 </histogram>
 
 <histogram name="MobileStartup.IntentToCreationTime" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>tedchoc@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <owner>yfriedman@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml
index 7514310..d8fe1e4 100644
--- a/tools/metrics/histograms/metadata/navigation/histograms.xml
+++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -816,7 +816,7 @@
 </histogram>
 
 <histogram name="Navigation.EngagementTime.Ratio" units="%"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>estark@chromium.org</owner>
   <owner>security-enamel@chromium.org</owner>
   <summary>
@@ -1597,7 +1597,7 @@
 </histogram>
 
 <histogram name="NavigationSuggestion.Event2" enum="NavigationSuggestionEvent"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>meacer@chromium.org</owner>
   <owner>security-enamel@chromium.org</owner>
   <summary>
@@ -1614,7 +1614,7 @@
 </histogram>
 
 <histogram name="NavigationSuggestion.UpdateEngagedSitesDeferTime" units="ms"
-    expires_after="2022-05-03">
+    expires_after="2022-07-03">
   <owner>meacer@chromium.org</owner>
   <owner>cduvall@chromium.org</owner>
   <owner>security-enamel@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml
index 0a386dbc..090be2f2 100644
--- a/tools/metrics/histograms/metadata/net/histograms.xml
+++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -462,7 +462,7 @@
 </histogram>
 
 <histogram name="Net.CertificateTransparency.SCT.VerificationTime"
-    units="microseconds" expires_after="2022-05-01">
+    units="microseconds" expires_after="2022-07-03">
   <owner>estark@chromium.org</owner>
   <owner>rsleevi@chromium.org</owner>
   <summary>
@@ -474,7 +474,7 @@
 </histogram>
 
 <histogram name="Net.CertificateTransparency.SCTOrigin" enum="SCTOrigin"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>estark@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
   <summary>
@@ -634,7 +634,7 @@
 </histogram>
 
 <histogram name="Net.Cors.PreflightCacheKeySize" units="bytes"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>toyoshim@chromium.org</owner>
   <owner>yhirano@chromium.org</owner>
   <summary>
@@ -1836,7 +1836,7 @@
 </histogram>
 
 <histogram name="Net.DomainReliability.BeaconOutcome"
-    enum="DomainReliabilityBeaconOutcome" expires_after="2022-05-01">
+    enum="DomainReliabilityBeaconOutcome" expires_after="2022-07-03">
   <owner>mmenke@chromium.org</owner>
   <owner>src/net/network_error_logging/OWNERS</owner>
   <summary>
@@ -1976,7 +1976,7 @@
 </histogram>
 
 <histogram name="Net.ExpectCT.HeaderPresentOnResponse" units="BooleanPresent"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>estark@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
   <summary>
@@ -2175,7 +2175,7 @@
 </histogram>
 
 <histogram name="Net.HttpJob.PrefilterBytesRead" units="bytes"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>jkarlin@chromium.org</owner>
   <owner>shivanisha@chromium.org</owner>
   <summary>
@@ -5680,7 +5680,7 @@
 </histogram>
 
 <histogram name="Net.SSLRSAKeyUsage.UnknownRoot" enum="RSAKeyUsage"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>davidben@chromium.org</owner>
   <summary>
     For each TLS connection which uses a unknown root, an RSA key, and TLS 1.2
diff --git a/tools/metrics/histograms/metadata/network/histograms.xml b/tools/metrics/histograms/metadata/network/histograms.xml
index 77a5d0669..276d6af 100644
--- a/tools/metrics/histograms/metadata/network/histograms.xml
+++ b/tools/metrics/histograms/metadata/network/histograms.xml
@@ -3618,7 +3618,7 @@
 </histogram>
 
 <histogram name="NetworkService.TimeToGrantCacheAccess" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>wfh@chromium.org</owner>
   <owner>mmenke@chromium.org</owner>
   <summary>
@@ -3632,7 +3632,7 @@
 </histogram>
 
 <histogram name="NetworkService.TimeToGrantDataAccess" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>wfh@chromium.org</owner>
   <owner>mmenke@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
index 5391a4f6..e49ce81 100644
--- a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
+++ b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
@@ -942,7 +942,7 @@
 </histogram>
 
 <histogram name="NewTabPage.LogoShown" enum="NewTabPageLogoShown"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>tiborg@chromium.org</owner>
   <owner>yyushkina@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
@@ -1487,7 +1487,7 @@
 </histogram>
 
 <histogram name="NewTabPage.Realbox.CharTypedToRepaintLatency.ToPaint"
-    units="ms" expires_after="2022-05-01">
+    units="ms" expires_after="2022-07-03">
   <owner>mahmadi@chromium.org</owner>
   <owner>tommycli@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/notifications/histograms.xml b/tools/metrics/histograms/metadata/notifications/histograms.xml
index 4116c758..5ef7572 100644
--- a/tools/metrics/histograms/metadata/notifications/histograms.xml
+++ b/tools/metrics/histograms/metadata/notifications/histograms.xml
@@ -674,7 +674,7 @@
 </histogram>
 
 <histogram name="Notifications.PersistentWebNotificationCloseResult"
-    enum="PlatformNotificationStatus" expires_after="2022-05-01">
+    enum="PlatformNotificationStatus" expires_after="2022-07-03">
   <owner>peter@chromium.org</owner>
   <owner>knollr@chromium.org</owner>
   <summary>
@@ -733,7 +733,7 @@
 </histogram>
 
 <histogram name="Notifications.Scheduler.IconDb.RecordCount" units="records"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>xingliu@chromium.org</owner>
   <owner>hesen@chromium.org</owner>
   <summary>
@@ -1045,7 +1045,7 @@
 </histogram>
 
 <histogram name="Notifications.Windows.DisplayFailure" enum="Hresult"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>finnur@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
@@ -1133,7 +1133,7 @@
 </histogram>
 
 <histogram name="Notifications.Windows.GetSettingStatusStartup"
-    enum="WindowsNotificationGetSettingStatus" expires_after="2022-05-01">
+    enum="WindowsNotificationGetSettingStatus" expires_after="2022-07-03">
   <owner>finnur@chromium.org</owner>
   <owner>knollr@chromium.org</owner>
   <owner>peter@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/offline/histograms.xml b/tools/metrics/histograms/metadata/offline/histograms.xml
index 5bde6f04..995a5c9 100644
--- a/tools/metrics/histograms/metadata/offline/histograms.xml
+++ b/tools/metrics/histograms/metadata/offline/histograms.xml
@@ -1047,7 +1047,7 @@
 </histogram>
 
 <histogram name="OfflinePages.PrefetchUsage" enum="OfflinePagesPrefetchUsage"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>dimich@chromium.org</owner>
   <owner>offline-dev@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/omnibox/histograms.xml b/tools/metrics/histograms/metadata/omnibox/histograms.xml
index 59c9b66..333a987 100644
--- a/tools/metrics/histograms/metadata/omnibox/histograms.xml
+++ b/tools/metrics/histograms/metadata/omnibox/histograms.xml
@@ -152,7 +152,7 @@
 </histogram>
 
 <histogram name="Omnibox.ClipboardSuggestionRemovedAge" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>gangwu@chromium.org</owner>
   <owner>fgorski@chromium.org</owner>
   <summary>
@@ -654,7 +654,7 @@
   </summary>
 </histogram>
 
-<histogram name="Omnibox.PaintTime" units="ms" expires_after="2022-05-01">
+<histogram name="Omnibox.PaintTime" units="ms" expires_after="2022-07-03">
   <owner>asvitkine@chromium.org</owner>
   <owner>mpearson@chromium.org</owner>
   <owner>jdonnelly@chromium.org</owner>
@@ -810,7 +810,7 @@
 </histogram>
 
 <histogram name="Omnibox.SelectedPosition" units="position"
-    expires_after="2022-06-26">
+    expires_after="2022-07-03">
   <owner>jdonnelly@chromium.org</owner>
   <owner>mpearson@chromium.org</owner>
   <owner>chrome-omnibox-team@google.com</owner>
@@ -1114,7 +1114,7 @@
 </histogram>
 
 <histogram name="Omnibox.ToggleSuggestionGroupId.On" enum="SuggestionGroupId"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>mahmadi@google.com</owner>
   <owner>chrome-omnibox-team@google.com</owner>
   <summary>
@@ -1126,7 +1126,7 @@
 </histogram>
 
 <histogram name="Omnibox.URLNavigationScheme" enum="NavigationScheme"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>mpearson@chromium.org</owner>
   <owner>jdonnelly@chromium.org</owner>
   <owner>chrome-omnibox-team@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml
index 4834bd1..5b2927ff 100644
--- a/tools/metrics/histograms/metadata/others/histograms.xml
+++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -1264,7 +1264,7 @@
 </histogram>
 
 <histogram name="AutocompleteActionPredictor.DatabaseAction"
-    enum="AutocompleteActionPredictorDatabaseAction" expires_after="2022-05-01">
+    enum="AutocompleteActionPredictorDatabaseAction" expires_after="2022-07-03">
   <owner>tbansal@chromium.org</owner>
   <owner>chrome-omnibox-team@google.com</owner>
   <owner>jdonnelly@chromium.org</owner>
@@ -1284,7 +1284,7 @@
 </histogram>
 
 <histogram name="AutocompleteActionPredictor.MatchIsInDb" units="units"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>tbansal@chromium.org</owner>
   <owner>chrome-omnibox-team@google.com</owner>
   <owner>jdonnelly@chromium.org</owner>
@@ -1866,7 +1866,7 @@
 </histogram>
 
 <histogram name="Bookmarks.BookmarkAllTabsWithTabsCount.Regular" units="tabs"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>roagarwal@chromium.org</owner>
   <owner>sideyilmaz@chromium.org</owner>
   <owner>chrome-incognito@google.com</owner>
@@ -2072,7 +2072,7 @@
 </histogram>
 
 <histogram name="Bookmarks.OpenBookmarkManager.PerProfileType"
-    enum="BrowserProfileType" expires_after="2022-05-01">
+    enum="BrowserProfileType" expires_after="2022-07-03">
   <owner>roagarwal@chromium.org</owner>
   <owner>chrome-incognito@google.com</owner>
   <component>UI&gt;Browser&gt;Bookmarks</component>
@@ -3784,7 +3784,7 @@
 </histogram>
 
 <histogram name="ContextMenu.Shown" enum="BooleanPresent"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>mpearson@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <owner>clank-app-team@google.com</owner>
@@ -3857,7 +3857,7 @@
 </histogram>
 
 <histogram name="ContextMenu.ViewsTextServices.Emoji" enum="Boolean"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>yyushkina@chromium.org</owner>
   <summary>
     Number of times the emoji item in the views text services context menu is
@@ -4026,7 +4026,7 @@
 </histogram>
 
 <histogram name="Conversions.RegisteredConversionsPerPage" units="conversions"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>johnidel@chromium.org</owner>
   <owner>csharrison@chromium.org</owner>
   <summary>
@@ -5503,7 +5503,7 @@
 </histogram>
 
 <histogram name="Drive.PushNotificationInitiallyEnabled" enum="BooleanEnabled"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>simmonsjosh@google.com</owner>
   <owner>src/ui/file_manager/OWNERS</owner>
   <summary>
@@ -5514,7 +5514,7 @@
 </histogram>
 
 <histogram name="Drive.PushNotificationRegistered" enum="BooleanRegistered"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>simmonsjosh@google.com</owner>
   <owner>src/ui/file_manager/OWNERS</owner>
   <summary>
@@ -6954,7 +6954,7 @@
 </histogram>
 
 <histogram name="Gamepad.UnknownGamepadConnected" enum="GamepadSource"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>mattreynolds@chromium.org</owner>
   <owner>deviceapi-team@google.com</owner>
   <summary>
@@ -7081,7 +7081,7 @@
 </histogram>
 
 <histogram base="true" name="GridTabSwitcher.FramePerSecond" units="frame/sec"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>yusufo@chromium.org</owner>
   <owner>wychen@chromium.org</owner>
   <summary>
@@ -7313,7 +7313,7 @@
 </histogram>
 
 <histogram base="true" name="Hwsec.Attestation.Status"
-    enum="HwsecAttestationOpsStatus" expires_after="2022-05-01">
+    enum="HwsecAttestationOpsStatus" expires_after="2022-07-03">
 <!-- Name completed by histogram_suffixes name="AttestationOps" -->
 
   <owner>garryxiao@chromium.org</owner>
@@ -7466,7 +7466,7 @@
 </histogram>
 
 <histogram name="ImportantFile.FileReplaceRetryCount" units="attempt count"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>brucedawson@chromium.org</owner>
   <owner>grt@chromium.org</owner>
   <summary>
@@ -8262,7 +8262,7 @@
 
 <histogram
     name="Lens.ImageClassification.ClassificationTime.SuccessOnQueryResultMs"
-    units="ms" expires_after="2022-05-01">
+    units="ms" expires_after="2022-07-03">
   <owner>yusuyoutube@google.com</owner>
   <owner>benwgold@google.com</owner>
   <summary>
@@ -8790,7 +8790,7 @@
 </histogram>
 
 <histogram name="Manifest.ParseIdResult" enum="ManifestParseIdResultType"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>phillis@chromium.org</owner>
   <owner>desktop-pwas-team@chromium.org</owner>
   <summary>Tracks the result of parsing id field in the Manifest.</summary>
@@ -9363,7 +9363,7 @@
 </histogram>
 
 <histogram name="MPArch.ChildProcessLaunchFirst" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>pasko@chromium.org</owner>
   <owner>yfriedman@chromium.org</owner>
   <summary>
@@ -9581,7 +9581,7 @@
 </histogram>
 
 <histogram name="NativeTheme.GetSystemColor.UsesColorProvider" enum="Boolean"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>pkasting@chromium.org</owner>
   <owner>robliao@chromium.org</owner>
   <summary>Records if the color provider computed the color.</summary>
@@ -11664,7 +11664,7 @@
 </histogram>
 
 <histogram name="Privacy.ClearOnExitSyncEvent" enum="ClearOnExitSyncEvent"
-    expires_after="M100">
+    expires_after="M103">
   <owner>sauski@google.com</owner>
   <owner>chrome-friendly-settings@google.com</owner>
   <summary>
@@ -12054,7 +12054,7 @@
 </histogram>
 
 <histogram name="PushMessaging.UnregistrationStatus"
-    enum="PushUnregistrationStatus" expires_after="2022-05-01">
+    enum="PushUnregistrationStatus" expires_after="2022-07-03">
   <owner>peter@chromium.org</owner>
   <owner>knollr@chromium.org</owner>
   <summary>
@@ -12901,7 +12901,7 @@
 </histogram>
 
 <histogram name="SB2.DownloadChecks" enum="SB2DownloadChecks"
-    expires_after="2022-05-02">
+    expires_after="2022-07-03">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -13991,7 +13991,7 @@
 </histogram>
 
 <histogram name="Skia.SubmitRenderPasses" units="renderpasses"
-    expires_after="2022-01-09">
+    expires_after="2022-07-09">
   <owner>egdaniel@google.com</owner>
   <owner>bsalomon@google.com</owner>
   <summary>
@@ -14004,7 +14004,7 @@
 </histogram>
 
 <histogram name="Skia.VulkanMemoryAllocator.AmountAllocated" units="KB"
-    expires_after="2022-01-09">
+    expires_after="2022-07-09">
   <owner>egdaniel@google.com</owner>
   <owner>bsalomon@google.com</owner>
   <summary>
@@ -14133,7 +14133,7 @@
 </histogram>
 
 <histogram name="SpellCheck.SpellingService.RequestResultType"
-    enum="ServiceRequestResultType" expires_after="2022-05-01">
+    enum="ServiceRequestResultType" expires_after="2022-07-03">
   <owner>yyushkina@google.com</owner>
   <owner>gujen@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -14190,7 +14190,7 @@
 </histogram>
 
 <histogram base="true" name="Spellcheck.Windows.SpellcheckRequestDuration"
-    units="ms" expires_after="2022-05-01">
+    units="ms" expires_after="2022-07-03">
   <owner>gujen@google.com</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -15549,7 +15549,7 @@
 </histogram>
 
 <histogram name="TouchBar.Default.Metrics" enum="DefaultTouchBarActions"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>ellyjones@chromium.org</owner>
   <owner>chrome-mac-dev@google.com</owner>
   <summary>Tracks the usage of the default touch bar buttons.</summary>
@@ -15838,7 +15838,7 @@
   </summary>
 </histogram>
 
-<histogram name="UI.DeviceScale" units="%" expires_after="2022-05-01">
+<histogram name="UI.DeviceScale" units="%" expires_after="2022-07-03">
   <owner>bsep@chromium.org</owner>
   <summary>
     The device scales available on the system at startup. A system may report
@@ -16762,7 +16762,7 @@
 </histogram>
 
 <histogram name="WebFont.BlankTextShownTime" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>kenjibaheux@chromium.org</owner>
   <owner>ksakamoto@chromium.org</owner>
   <summary>
@@ -16797,7 +16797,7 @@
 </histogram>
 
 <histogram name="WebFont.DownloadTime.0.Under10KB" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>kenjibaheux@chromium.org</owner>
   <owner>ksakamoto@chromium.org</owner>
   <summary>
@@ -17063,7 +17063,7 @@
 </histogram>
 
 <histogram name="WebUITabStrip.CloseTabAction"
-    enum="WebUITabStripCloseTabActions" expires_after="2022-05-01">
+    enum="WebUITabStripCloseTabActions" expires_after="2022-07-03">
   <owner>johntlee@chromium.org</owner>
   <owner>dpapad@chromium.org</owner>
   <summary>
@@ -17274,7 +17274,7 @@
 </histogram>
 
 <histogram name="WhatsNew.LoadResponseCode"
-    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-05-01">
+    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-07-03">
   <owner>rbpotter@chromium.org</owner>
   <owner>mahmadi@chromium.org</owner>
   <summary>
@@ -17374,7 +17374,7 @@
 </histogram>
 
 <histogram name="WrenchMenu.TimeToAction" units="units"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>ainslie@chromium.org</owner>
   <owner>edwardjung@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml
index 3abbb86..d97d7f5 100644
--- a/tools/metrics/histograms/metadata/page/histograms.xml
+++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -65,7 +65,7 @@
 </variants>
 
 <histogram name="PageActionController.ExtensionsWithPageActions" units="units"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
@@ -120,7 +120,7 @@
 </histogram>
 
 <histogram name="PageLoad.BackForwardCache.Event"
-    enum="PageLoadBackForwardCacheEvent" expires_after="2022-05-01">
+    enum="PageLoadBackForwardCacheEvent" expires_after="2022-07-03">
   <owner>altimin@chromium.org</owner>
   <owner>bmcquade@chromium.org</owner>
   <owner>hajimehoshi@chromium.org</owner>
@@ -392,7 +392,7 @@
 
 <histogram
     name="PageLoad.Clients.AMP.Experimental.PageTiming.InputToNavigation.Subframe"
-    units="ms" expires_after="2022-05-01">
+    units="ms" expires_after="2022-07-03">
   <owner>bmcquade@chromium.org</owner>
   <owner>sullivan@chromium.org</owner>
   <owner>speed-metrics-dev@chromium.org</owner>
@@ -1784,7 +1784,7 @@
 </histogram>
 
 <histogram name="PageLoad.Experimental.PaintTiming.InputToFirstContentfulPaint"
-    units="ms" expires_after="2022-05-01">
+    units="ms" expires_after="2022-07-03">
   <owner>sullivan@chromium.org</owner>
   <summary>
     The time between the OS-level input event that initiated a navigation, and
@@ -2084,7 +2084,7 @@
 </histogram>
 
 <histogram name="PageLoad.InteractiveTiming.FirstInputTimestamp4" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>sullivan@chromium.org</owner>
   <owner>speed-metrics-dev@chromium.org</owner>
   <summary>
@@ -2295,7 +2295,7 @@
 
 <histogram
     name="PageLoad.Internal.PaintTiming.LargestContentfulPaint.ContentType"
-    enum="LargestContentType" expires_after="2022-04-24">
+    enum="LargestContentType" expires_after="2022-07-03">
   <owner>npm@chromium.org</owner>
   <owner>speed-metrics-dev@chromium.org</owner>
   <summary>
@@ -2308,7 +2308,7 @@
 
 <histogram
     name="PageLoad.Internal.PaintTiming.LargestContentfulPaint.MainFrame.ContentType"
-    enum="LargestContentType" expires_after="2022-05-01">
+    enum="LargestContentType" expires_after="2022-07-03">
   <owner>npm@chromium.org</owner>
   <owner>speed-metrics-dev@chromium.org</owner>
   <summary>
@@ -3136,7 +3136,7 @@
 </histogram>
 
 <histogram name="PageSerialization.MhtmlLoading.LoadResult"
-    enum="MhtmlLoadResult" expires_after="2022-05-01">
+    enum="MhtmlLoadResult" expires_after="2022-07-03">
   <owner>sclittle@chromium.org</owner>
   <owner>offline-dev@chromium.org</owner>
   <summary>Reports the result of an attempt to load an MHTML archive.</summary>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml
index c27133a..8a74cb0 100644
--- a/tools/metrics/histograms/metadata/password/histograms.xml
+++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -117,7 +117,7 @@
 </histogram>
 
 <histogram name="KeyboardAccessory.AccessoryToggleClicked"
-    enum="AccessoryToggleType" expires_after="2022-04-17">
+    enum="AccessoryToggleType" expires_after="2022-07-03">
   <owner>ioanap@chromium.org</owner>
   <owner>fhorschig@chromium.org</owner>
   <summary>
@@ -166,7 +166,7 @@
 </histogram>
 
 <histogram name="PasswordBubble.CompromisedBubble.CheckClicked"
-    enum="BooleanClicked" expires_after="2022-05-01">
+    enum="BooleanClicked" expires_after="2022-07-03">
   <owner>vasilii@chromium.org</owner>
   <owner>kazinova@google.com</owner>
   <summary>
@@ -176,7 +176,7 @@
 </histogram>
 
 <histogram name="PasswordBubble.CompromisedBubble.Type"
-    enum="PasswordBubbleFollowupType" expires_after="2022-05-01">
+    enum="PasswordBubbleFollowupType" expires_after="2022-07-03">
   <owner>vasilii@chromium.org</owner>
   <owner>kazinova@google.com</owner>
   <summary>
@@ -303,7 +303,7 @@
 </histogram>
 
 <histogram name="PasswordManager.AcceptedSaveUpdateSubmissionIndicatorEvent"
-    enum="SubmissionIndicatorEvent" expires_after="2022-05-01">
+    enum="SubmissionIndicatorEvent" expires_after="2022-07-03">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -624,7 +624,7 @@
 </histogram>
 
 <histogram name="PasswordManager.AffiliationBackend.FirstFetchDelay" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>vsemeniuk@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -647,7 +647,7 @@
 </histogram>
 
 <histogram name="PasswordManager.AffiliationFetcher.FetchErrorCode"
-    enum="NetErrorCodes" expires_after="2022-05-01">
+    enum="NetErrorCodes" expires_after="2022-07-03">
   <owner>vsemeniuk@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -658,7 +658,7 @@
 </histogram>
 
 <histogram name="PasswordManager.AffiliationFetcher.FetchHttpResponseCode"
-    enum="HttpResponseCode" expires_after="2022-05-01">
+    enum="HttpResponseCode" expires_after="2022-07-03">
   <owner>vsemeniuk@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -1236,7 +1236,7 @@
 </histogram>
 
 <histogram name="PasswordManager.CredentialsWithDuplicates" units="units"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -1276,7 +1276,7 @@
 </histogram>
 
 <histogram name="PasswordManager.DeleteUndecryptableLoginsReturnValue"
-    enum="DeleteCorruptedPasswordsResult" expires_after="2022-05-01">
+    enum="DeleteCorruptedPasswordsResult" expires_after="2022-07-03">
   <owner>vasilii@chromium.org</owner>
   <owner>kazinova@google.com</owner>
   <summary>
@@ -1287,7 +1287,7 @@
 </histogram>
 
 <histogram name="PasswordManager.DropdownShown.OffTheRecord" units="units"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>rhalavati@chromium.org</owner>
   <owner>chrome-privacy-core@google.com</owner>
   <summary>
@@ -1493,7 +1493,7 @@
 </histogram>
 
 <histogram name="PasswordManager.GeneratedFormHasNoFormManager"
-    enum="BooleanFormManager" expires_after="2022-05-01">
+    enum="BooleanFormManager" expires_after="2022-07-03">
   <owner>kazinova@google.com</owner>
   <owner>kolos@chromium.org</owner>
   <summary>
@@ -1559,7 +1559,7 @@
 </histogram>
 
 <histogram name="PasswordManager.HttpPasswordMigrationCount"
-    units="saved credentials" expires_after="2022-05-01">
+    units="saved credentials" expires_after="2022-07-03">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -1627,7 +1627,7 @@
 </histogram>
 
 <histogram name="PasswordManager.IsSyncPasswordHashSaved"
-    enum="IsSyncPasswordHashSaved" expires_after="2022-05-01">
+    enum="IsSyncPasswordHashSaved" expires_after="2022-07-03">
   <owner>vakh@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -1649,7 +1649,7 @@
 </histogram>
 
 <histogram name="PasswordManager.ItemSelected.OffTheRecord" units="units"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>rhalavati@chromium.org</owner>
   <owner>chrome-privacy-core@google.com</owner>
   <summary>
@@ -1922,7 +1922,7 @@
 </histogram>
 
 <histogram name="PasswordManager.MediationRequired"
-    enum="CredentialManagerGetResult" expires_after="2022-05-01">
+    enum="CredentialManagerGetResult" expires_after="2022-07-03">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -2351,7 +2351,7 @@
 </histogram>
 
 <histogram name="PasswordManager.PasswordStoreInitResult" enum="BooleanSuccess"
-    expires_after="M100">
+    expires_after="M105">
   <owner>vasilii@chromium.org</owner>
   <owner>src/components/password_manager/OWNERS</owner>
   <summary>
@@ -2610,7 +2610,7 @@
 </histogram>
 
 <histogram name="PasswordManager.StoreDecryptionResult"
-    enum="PasswordDecryptionResult" expires_after="2022-05-01">
+    enum="PasswordDecryptionResult" expires_after="2022-07-03">
   <owner>cfroussios@chromium.org</owner>
   <owner>kazinova@google.com</owner>
   <summary>
@@ -2688,7 +2688,7 @@
 </histogram>
 
 <histogram name="PasswordManager.SuccessfulSubmissionIndicatorEvent"
-    enum="SubmissionIndicatorEvent" expires_after="2022-05-01">
+    enum="SubmissionIndicatorEvent" expires_after="2022-07-03">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -2878,7 +2878,7 @@
 </histogram>
 
 <histogram name="PasswordManager.WeakCheck.Time" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>The time it took to complete the passwords weak check.</summary>
@@ -3148,7 +3148,7 @@
 </histogram>
 
 <histogram name="PasswordProtection.DomFeatureExtractionDuration" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>drubery@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/payment/histograms.xml b/tools/metrics/histograms/metadata/payment/histograms.xml
index 68a59ec..6489cac 100644
--- a/tools/metrics/histograms/metadata/payment/histograms.xml
+++ b/tools/metrics/histograms/metadata/payment/histograms.xml
@@ -308,7 +308,7 @@
 </histogram>
 
 <histogram name="PaymentRequest.TimeToCheckout.UserAborted" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
 <!-- Name completed by histogram_suffixes name="PaymentRequestPaymentSheetShowStatus" -->
 
   <owner>rouslan@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/permissions/histograms.xml b/tools/metrics/histograms/metadata/permissions/histograms.xml
index 9265a29..bff2166 100644
--- a/tools/metrics/histograms/metadata/permissions/histograms.xml
+++ b/tools/metrics/histograms/metadata/permissions/histograms.xml
@@ -314,7 +314,7 @@
 </histogram>
 
 <histogram name="Permissions.CrowdDeny.SafeBrowsing.Verdict"
-    enum="CrowdDenySafeBrowsingVerdict" expires_after="2022-05-01">
+    enum="CrowdDenySafeBrowsingVerdict" expires_after="2022-07-03">
   <owner>engedy@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/platform/histograms.xml b/tools/metrics/histograms/metadata/platform/histograms.xml
index 27a1424..99ff3dbc 100644
--- a/tools/metrics/histograms/metadata/platform/histograms.xml
+++ b/tools/metrics/histograms/metadata/platform/histograms.xml
@@ -1603,7 +1603,7 @@
 </histogram>
 
 <histogram name="PlatformThread.Mac.SucceededRealtimePeriod"
-    units="microseconds" expires_after="2022-05-01">
+    units="microseconds" expires_after="2022-07-03">
   <owner>olka@chromium.org</owner>
   <owner>handellm@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/power/histograms.xml b/tools/metrics/histograms/metadata/power/histograms.xml
index 8ef8f29f1..c38b1d2 100644
--- a/tools/metrics/histograms/metadata/power/histograms.xml
+++ b/tools/metrics/histograms/metadata/power/histograms.xml
@@ -1066,7 +1066,7 @@
 </histogram>
 
 <histogram name="Power.Mac.AppleSMCOpened" enum="BooleanSuccess"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>lgrey@chromium.org</owner>
   <summary>
     When metrics collection started, records true if a handle to the System
@@ -1531,7 +1531,7 @@
 </histogram>
 
 <histogram name="PowerML.SmartDimModel.RequestCompleteDuration" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>amoylan@chromium.org</owner>
   <owner>napper@chromium.org</owner>
   <owner>napper@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/prefetch/histograms.xml b/tools/metrics/histograms/metadata/prefetch/histograms.xml
index cb011460..0c52474 100644
--- a/tools/metrics/histograms/metadata/prefetch/histograms.xml
+++ b/tools/metrics/histograms/metadata/prefetch/histograms.xml
@@ -261,7 +261,7 @@
 </histogram>
 
 <histogram name="PrefetchProxy.AfterClick.Mainframe.CookieWaitTime" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>robertogden@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
   <owner>tbansal@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/print/histograms.xml b/tools/metrics/histograms/metadata/print/histograms.xml
index f865df11..984b822a 100644
--- a/tools/metrics/histograms/metadata/print/histograms.xml
+++ b/tools/metrics/histograms/metadata/print/histograms.xml
@@ -297,7 +297,7 @@
 </histogram>
 
 <histogram name="PrintPreview.RendererError" enum="PrintPreviewFailureType"
-    expires_after="2022-04-24">
+    expires_after="2022-07-03">
   <owner>thestig@chromium.org</owner>
   <owner>dhoss@chromium.org</owner>
   <summary>
@@ -313,7 +313,7 @@
 </histogram>
 
 <histogram name="PrintPreview.RenderToPDFTime" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>thestig@chromium.org</owner>
   <owner>awscreen@chromium.org</owner>
   <summary>Time taken to render to PDF for print preview.</summary>
diff --git a/tools/metrics/histograms/metadata/profile/histograms.xml b/tools/metrics/histograms/metadata/profile/histograms.xml
index 178f9e1..e18d21d9 100644
--- a/tools/metrics/histograms/metadata/profile/histograms.xml
+++ b/tools/metrics/histograms/metadata/profile/histograms.xml
@@ -85,7 +85,7 @@
 </histogram>
 
 <histogram name="Profile.Avatar" enum="ProfileAvatar"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>jkrcal@chromium.org</owner>
   <owner>droger@chromium.org</owner>
   <summary>The frequency of selection of each avatar.</summary>
@@ -619,7 +619,7 @@
 </histogram>
 
 <histogram base="true" name="Profile.State.Avatar" enum="ProfileAvatarState"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>jkrcal@chromium.org</owner>
   <owner>droger@chromium.org</owner>
   <summary>
@@ -640,7 +640,7 @@
 </histogram>
 
 <histogram base="true" name="Profile.State.Name" enum="ProfileNameState"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>jkrcal@chromium.org</owner>
   <owner>droger@chromium.org</owner>
   <summary>
@@ -720,7 +720,7 @@
   </summary>
 </histogram>
 
-<histogram name="Profile.TopSitesSize" units="MB" expires_after="2022-05-01">
+<histogram name="Profile.TopSitesSize" units="MB" expires_after="2022-07-03">
   <owner>etienneb@chromium.org</owner>
   <owner>gab@chromium.org</owner>
   <summary>Size of the top sites database.</summary>
@@ -821,13 +821,13 @@
 </histogram>
 
 <histogram name="Profile.VisitedLinksSize" units="MB"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>etienneb@chromium.org</owner>
   <owner>gab@chromium.org</owner>
   <summary>Size of the visited links database.</summary>
 </histogram>
 
-<histogram name="Profile.WebDataSize" units="MB" expires_after="2022-05-01">
+<histogram name="Profile.WebDataSize" units="MB" expires_after="2022-07-03">
   <owner>etienneb@chromium.org</owner>
   <owner>gab@chromium.org</owner>
   <summary>Size of the web data database.</summary>
@@ -943,7 +943,7 @@
 </histogram>
 
 <histogram name="ProfilePicker.Shown" enum="ProfilePickerEntryPoint"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>msalama@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
   <summary>
@@ -953,7 +953,7 @@
 </histogram>
 
 <histogram name="ProfilePicker.StartupTime.BeforeCreation" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>alexilin@chromium.org</owner>
   <owner>dgn@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
@@ -965,7 +965,7 @@
 </histogram>
 
 <histogram name="ProfilePicker.StartupTime.FirstPaint" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>alexilin@chromium.org</owner>
   <owner>dgn@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
@@ -991,7 +991,7 @@
 </histogram>
 
 <histogram name="ProfilePicker.StartupTime.MainViewInitialized" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>alexilin@chromium.org</owner>
   <owner>dgn@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
@@ -1002,7 +1002,7 @@
 </histogram>
 
 <histogram name="ProfilePicker.StartupTime.WebViewCreated" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>alexilin@chromium.org</owner>
   <owner>dgn@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/quota/histograms.xml b/tools/metrics/histograms/metadata/quota/histograms.xml
index 22bf46f..9abb560 100644
--- a/tools/metrics/histograms/metadata/quota/histograms.xml
+++ b/tools/metrics/histograms/metadata/quota/histograms.xml
@@ -254,7 +254,7 @@
 </histogram>
 
 <histogram name="Quota.PercentUsedByOrigin" units="%"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>jarrydg@chromium.org</owner>
   <owner>chrome-owp-storage@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/renderer/histograms.xml b/tools/metrics/histograms/metadata/renderer/histograms.xml
index 2b66608..3f51038 100644
--- a/tools/metrics/histograms/metadata/renderer/histograms.xml
+++ b/tools/metrics/histograms/metadata/renderer/histograms.xml
@@ -270,7 +270,7 @@
 </histogram>
 
 <histogram name="Renderer.Font.PrimaryFont.DomContentLoaded.Style" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>kojii@chromium.org</owner>
   <owner>tkent@chromium.org</owner>
   <owner>yosin@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
index 2a9742c..d6ae77a 100644
--- a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
+++ b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
@@ -990,7 +990,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.EsbDisabled.LastEnabledInterval" units="days"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -1211,7 +1211,7 @@
 
 <histogram
     name="SafeBrowsing.NavigationObserver.IdentifyReferrerChainByWebContentsTime"
-    units="ms" expires_after="2022-05-01">
+    units="ms" expires_after="2022-07-03">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -1485,7 +1485,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.RT.AllowlistSizeTooSmall"
-    enum="BooleanUnavailable" expires_after="2022-05-01">
+    enum="BooleanUnavailable" expires_after="2022-07-03">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -1509,7 +1509,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.RT.Backoff.State" enum="BooleanEnabled"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>vakh@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -1520,7 +1520,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.RT.CacheManager.CleanUpTime" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -2659,7 +2659,7 @@
 </histogram>
 
 <histogram name="SafeBrowsingFCMService.IncomingMessageHasValidToken"
-    enum="Boolean" expires_after="2022-05-01">
+    enum="Boolean" expires_after="2022-07-03">
   <owner>drubery@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/scheduler/histograms.xml b/tools/metrics/histograms/metadata/scheduler/histograms.xml
index f1ca32a..c46dfab4 100644
--- a/tools/metrics/histograms/metadata/scheduler/histograms.xml
+++ b/tools/metrics/histograms/metadata/scheduler/histograms.xml
@@ -294,7 +294,7 @@
 </histogram>
 
 <histogram name="Scheduling.Renderer.DrawIntervalWithCustomPropertyAnimations2"
-    units="microseconds" expires_after="2022-05-01">
+    units="microseconds" expires_after="2022-07-03">
   <owner>xidachen@chromium.org</owner>
   <owner>animations-dev@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/search/histograms.xml b/tools/metrics/histograms/metadata/search/histograms.xml
index 871a0d30..b001eed3 100644
--- a/tools/metrics/histograms/metadata/search/histograms.xml
+++ b/tools/metrics/histograms/metadata/search/histograms.xml
@@ -1471,7 +1471,7 @@
 </histogram>
 
 <histogram name="Search.RegionSearch.Lens.RegionAspectRatio"
-    enum="LensRegionSearchAspectRatio" expires_after="2022-05-01">
+    enum="LensRegionSearchAspectRatio" expires_after="2022-07-03">
   <owner>juanmojica@google.com</owner>
   <owner>benwgold@google.com</owner>
   <owner>stanfield@google.com</owner>
@@ -1483,7 +1483,7 @@
 </histogram>
 
 <histogram name="Search.RegionSearch.Lens.RegionViewportProportion" units="pct"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>juanmojica@google.com</owner>
   <owner>benwgold@google.com</owner>
   <owner>stanfield@google.com</owner>
@@ -1495,7 +1495,7 @@
 </histogram>
 
 <histogram name="Search.RegionSearch.Lens.Result"
-    enum="LensRegionSearchCaptureResult" expires_after="2022-05-01">
+    enum="LensRegionSearchCaptureResult" expires_after="2022-07-03">
   <owner>juanmojica@google.com</owner>
   <owner>benwgold@google.com</owner>
   <owner>stanfield@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/security/histograms.xml b/tools/metrics/histograms/metadata/security/histograms.xml
index 0001342..71456e9 100644
--- a/tools/metrics/histograms/metadata/security/histograms.xml
+++ b/tools/metrics/histograms/metadata/security/histograms.xml
@@ -383,7 +383,7 @@
 </histogram>
 
 <histogram name="Security.PageInfo.TimeOpen" units="units"
-    expires_after="2022-06-26">
+    expires_after="2022-07-03">
   <owner>cthomp@chromium.org</owner>
   <owner>security-enamel@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml b/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
index 00e4740a..aef5a66 100644
--- a/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
+++ b/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
@@ -438,7 +438,7 @@
 </histogram>
 
 <histogram name="SegmentationPlatform.SignalDatabase.GetSamples.SampleCount"
-    units="samples" expires_after="2022-05-01">
+    units="samples" expires_after="2022-07-03">
   <owner>nyquist@chromium.org</owner>
   <owner>shaktisahu@chromium.org</owner>
   <owner>chrome-segmentation-platform@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/service/histograms.xml b/tools/metrics/histograms/metadata/service/histograms.xml
index 4876ec49..b9569bde 100644
--- a/tools/metrics/histograms/metadata/service/histograms.xml
+++ b/tools/metrics/histograms/metadata/service/histograms.xml
@@ -378,7 +378,7 @@
 </histogram>
 
 <histogram name="ServiceWorker.FetchEvent.MainResource.Status"
-    enum="ServiceWorkerStatusCode" expires_after="2022-05-01">
+    enum="ServiceWorkerStatusCode" expires_after="2022-07-03">
   <owner>wanderview@chromium.org</owner>
   <owner>asamidoi@chromium.org</owner>
   <owner>chrome-worker@google.com</owner>
@@ -402,7 +402,7 @@
 </histogram>
 
 <histogram name="ServiceWorker.FetchEvent.Subresource.Status"
-    enum="ServiceWorkerStatusCode" expires_after="2022-05-01">
+    enum="ServiceWorkerStatusCode" expires_after="2022-07-03">
   <owner>wanderview@chromium.org</owner>
   <owner>asamidoi@chromium.org</owner>
   <owner>chrome-worker@google.com</owner>
@@ -826,7 +826,7 @@
 </histogram>
 
 <histogram name="ServiceWorker.RegisteredStorageKeyCount" units="origins"
-    expires_after="2022-04-29">
+    expires_after="2022-07-03">
   <owner>wanderview@chromium.org</owner>
   <owner>asamidoi@chromium.org</owner>
   <owner>chrome-worker@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/session/histograms.xml b/tools/metrics/histograms/metadata/session/histograms.xml
index 02f5dcb..0ce6868 100644
--- a/tools/metrics/histograms/metadata/session/histograms.xml
+++ b/tools/metrics/histograms/metadata/session/histograms.xml
@@ -574,7 +574,7 @@
 </histogram>
 
 <histogram base="true" name="Session.WebStates.NavigationItem" units="KB"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>djean@chromium.org</owner>
   <owner>sdefresne@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/settings/histograms.xml b/tools/metrics/histograms/metadata/settings/histograms.xml
index 6b13acd..465b9dc 100644
--- a/tools/metrics/histograms/metadata/settings/histograms.xml
+++ b/tools/metrics/histograms/metadata/settings/histograms.xml
@@ -260,7 +260,7 @@
 </histogram>
 
 <histogram name="Settings.SafetyCheck.Interactions"
-    enum="SettingsSafetyCheckInteractions" expires_after="2022-05-01">
+    enum="SettingsSafetyCheckInteractions" expires_after="2022-07-03">
   <owner>rainhard@chromium.org</owner>
   <owner>msramek@chromium.org</owner>
   <owner>anaudrey@chromium.org</owner>
@@ -293,7 +293,7 @@
 </histogram>
 
 <histogram name="Settings.SearchEngines.Interactions"
-    enum="SettingsSearchEnginesInteractions" expires_after="2022-05-02">
+    enum="SettingsSearchEnginesInteractions" expires_after="2022-07-03">
   <owner>yoangela@chromium.org</owner>
   <owner>chrome-omnibox-team@google.com</owner>
   <summary>
@@ -421,7 +421,7 @@
 </histogram>
 
 <histogram name="Settings.StartupPageEngineTypes"
-    enum="OmniboxSearchEngineType" expires_after="2022-05-01">
+    enum="OmniboxSearchEngineType" expires_after="2022-07-03">
   <owner>mpearson@chromium.org</owner>
   <owner>csharp@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/sharing/histograms.xml b/tools/metrics/histograms/metadata/sharing/histograms.xml
index 56e7d4b6..054d7f3 100644
--- a/tools/metrics/histograms/metadata/sharing/histograms.xml
+++ b/tools/metrics/histograms/metadata/sharing/histograms.xml
@@ -42,7 +42,7 @@
 </histogram>
 
 <histogram name="Sharing.ClickToCallAppsToShow" units="apps"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
 <!-- Name completed by histogram_suffixes name="SharingClickToCallUi" -->
 
   <owner>mvanouwerkerk@chromium.org</owner>
@@ -291,7 +291,7 @@
 </histogram>
 
 <histogram name="Sharing.MessageReceivedType" enum="SharingMessageType"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>mvanouwerkerk@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
@@ -437,7 +437,7 @@
 </histogram>
 
 <histogram name="Sharing.ScreenshotsAndroid.IsEditorDismissedOnStart"
-    enum="Boolean" expires_after="2022-05-01">
+    enum="Boolean" expires_after="2022-07-03">
   <owner>jeffreycohen@chromium.org</owner>
   <owner>kristipark@chromium.org</owner>
   <owner>src/chrome/browser/share/OWNERS</owner>
@@ -446,7 +446,7 @@
 
 <histogram name="Sharing.ScrollCapture.BitmapGeneratorStatus"
     enum="SharingScrollCaptureBitmapGenerationStatus"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>yashard@chromium.org</owner>
   <owner>ckitagawa@chromium.org</owner>
   <owner>src/components/paint_preview/OWNERS</owner>
@@ -459,7 +459,7 @@
 </histogram>
 
 <histogram name="Sharing.ScrollCapture.SuccessfulCaptureDuration" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>yashard@chromium.org</owner>
   <owner>ckitagawa@chromium.org</owner>
   <owner>src/components/paint_preview/OWNERS</owner>
@@ -582,7 +582,7 @@
 </histogram>
 
 <histogram name="Sharing.ShareTargetUpdate.ResourceBundleResult"
-    enum="ShareTargetUpdateResult" expires_after="2022-05-01">
+    enum="ShareTargetUpdateResult" expires_after="2022-07-03">
   <owner>jeffreycohen@chromium.org</owner>
   <owner>kristipark@chromium.org</owner>
   <owner>src/chrome/browser/share/OWNERS</owner>
@@ -596,7 +596,7 @@
 </histogram>
 
 <histogram name="Sharing.SharingHubAndroid.CloseReason"
-    enum="BottomSheet.StateChangeReason" expires_after="2022-05-01">
+    enum="BottomSheet.StateChangeReason" expires_after="2022-07-03">
   <owner>ellyjones@chromium.org</owner>
   <owner>src/chrome/browser/share/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/signin/histograms.xml b/tools/metrics/histograms/metadata/signin/histograms.xml
index b86f2f4f..c5927ea 100644
--- a/tools/metrics/histograms/metadata/signin/histograms.xml
+++ b/tools/metrics/histograms/metadata/signin/histograms.xml
@@ -81,7 +81,7 @@
 
 <histogram name="Signin.AccountCapabilities.GetFromSystemLibraryResult"
     enum="AccountCapabilitiesGetFromSystemLibraryResult"
-    expires_after="2021-12-31">
+    expires_after="2022-06-30">
   <owner>aliceywang@chromium.org</owner>
   <owner>fernandex@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
@@ -632,7 +632,7 @@
 </histogram>
 
 <histogram name="Signin.Intercept.ProfileCreationDuration" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>alexilin@chromium.org</owner>
   <owner>droger@chromium.org</owner>
   <summary>
@@ -1103,7 +1103,7 @@
 </histogram>
 
 <histogram name="Signin.Reconciler.Operation" enum="SigninReconcilerOperation"
-    expires_after="2022-05-02">
+    expires_after="2022-07-03">
   <owner>msarda@chromium.org</owner>
   <owner>droger@chromium.org</owner>
   <summary>
@@ -1327,7 +1327,7 @@
 </histogram>
 
 <histogram name="Signin.SigninCompletedAccessPoint" enum="SigninAccessPoint"
-    expires_after="2022-04-30">
+    expires_after="2022-07-03">
   <owner>msarda@chromium.org</owner>
   <owner>bsazonov@chromium.org</owner>
   <owner>droger@chromium.org</owner>
@@ -1336,7 +1336,7 @@
 </histogram>
 
 <histogram name="Signin.SigninReason" enum="SigninReason"
-    expires_after="2022-04-30">
+    expires_after="2022-07-03">
   <owner>msarda@chromium.org</owner>
   <owner>bsazonov@chromium.org</owner>
   <owner>droger@chromium.org</owner>
@@ -1345,7 +1345,7 @@
 </histogram>
 
 <histogram name="Signin.SigninStartedAccessPoint" enum="SigninAccessPoint"
-    expires_after="2022-04-30">
+    expires_after="2022-07-03">
   <owner>msarda@chromium.org</owner>
   <owner>bsazonov@chromium.org</owner>
   <owner>droger@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/software/histograms.xml b/tools/metrics/histograms/metadata/software/histograms.xml
index 497e5ba..7053ee9 100644
--- a/tools/metrics/histograms/metadata/software/histograms.xml
+++ b/tools/metrics/histograms/metadata/software/histograms.xml
@@ -220,7 +220,7 @@
 </histogram>
 
 <histogram name="SoftwareReporter.FoundUwSReadError" enum="BooleanError"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>drubery@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/stability/histograms.xml b/tools/metrics/histograms/metadata/stability/histograms.xml
index 39ed796..6702717 100644
--- a/tools/metrics/histograms/metadata/stability/histograms.xml
+++ b/tools/metrics/histograms/metadata/stability/histograms.xml
@@ -23,7 +23,7 @@
 <histograms>
 
 <histogram name="Stability.Android.OomKillReverseRank" units="rank"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>boliu@chromium.org</owner>
   <owner>ssid@chromium.org</owner>
   <summary>
@@ -78,7 +78,7 @@
 </histogram>
 
 <histogram name="Stability.Android.ProcessedSimulatedMinidumps"
-    enum="AndroidProcessedMinidumps" expires_after="2022-05-01">
+    enum="AndroidProcessedMinidumps" expires_after="2022-07-03">
   <owner>mheikal@chromium.org</owner>
   <owner>smaier@chromium.org</owner>
   <owner>wnwen@chromium.org</owner>
@@ -131,7 +131,7 @@
 </histogram>
 
 <histogram base="true" name="Stability.Android.SystemExitReason"
-    enum="AndroidProcessExitReason" expires_after="2022-05-01">
+    enum="AndroidProcessExitReason" expires_after="2022-07-03">
   <owner>boliu@chromium.org</owner>
   <owner>ssid@chromium.org</owner>
   <owner>wnwen@chromium.org</owner>
@@ -571,7 +571,7 @@
 </histogram>
 
 <histogram name="Stability.iOS.UTE.BatteryCharge" units="%"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>michaeldo@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -584,7 +584,7 @@
 </histogram>
 
 <histogram name="Stability.iOS.UTE.DeviceThermalState"
-    enum="IOSDeviceThermalState" expires_after="2022-05-01">
+    enum="IOSDeviceThermalState" expires_after="2022-07-03">
   <owner>michaeldo@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -654,7 +654,7 @@
 </histogram>
 
 <histogram name="Stability.iOS.UTE.OSRestartedAfterPreviousSession"
-    enum="BooleanRebooted" expires_after="2022-05-01">
+    enum="BooleanRebooted" expires_after="2022-07-03">
   <owner>olivierrobin@chromium.org</owner>
   <owner>michaeldo@chromium.org</owner>
   <summary>
@@ -677,7 +677,7 @@
 </histogram>
 
 <histogram name="Stability.iOS.UTE.TimeBetweenUTEAndNextLaunch" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>michaeldo@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -688,7 +688,7 @@
 </histogram>
 
 <histogram name="Stability.MobileSessionShutdownType"
-    enum="MobileSessionShutdownType" expires_after="2022-05-01">
+    enum="MobileSessionShutdownType" expires_after="2022-07-03">
   <owner>michaeldo@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/startup/histograms.xml b/tools/metrics/histograms/metadata/startup/histograms.xml
index 798da49..b8189a9c 100644
--- a/tools/metrics/histograms/metadata/startup/histograms.xml
+++ b/tools/metrics/histograms/metadata/startup/histograms.xml
@@ -211,7 +211,7 @@
 </histogram>
 
 <histogram name="Startup.Android.FeedsLoadingPlaceholderShown.Instant"
-    units="ms" expires_after="2022-05-01">
+    units="ms" expires_after="2022-07-03">
   <owner>hanxi@chromium.org</owner>
   <owner>spdonghao@chromium.org</owner>
   <owner>wychen@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/subresource/histograms.xml b/tools/metrics/histograms/metadata/subresource/histograms.xml
index d0cf001..fa0a0ca 100644
--- a/tools/metrics/histograms/metadata/subresource/histograms.xml
+++ b/tools/metrics/histograms/metadata/subresource/histograms.xml
@@ -23,7 +23,7 @@
 <histograms>
 
 <histogram name="SubresourceFilter.Actions2" enum="SubresourceFilterActions2"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>alexmt@chromium.org</owner>
   <owner>chrome-ads-histograms@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/sync/histograms.xml b/tools/metrics/histograms/metadata/sync/histograms.xml
index 460f94b2..5c15b00 100644
--- a/tools/metrics/histograms/metadata/sync/histograms.xml
+++ b/tools/metrics/histograms/metadata/sync/histograms.xml
@@ -555,7 +555,7 @@
 </histogram>
 
 <histogram name="Sync.CryptographerPendingKeys"
-    enum="SyncCryptographerPendingKeysState" expires_after="2022-05-01">
+    enum="SyncCryptographerPendingKeysState" expires_after="2022-07-03">
   <owner>mastiz@chromium.org</owner>
   <owner>treib@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -576,7 +576,7 @@
 </histogram>
 
 <histogram name="Sync.CustomEncryption" enum="SyncCustomEncryptionEvent"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>mastiz@chromium.org</owner>
   <owner>treib@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -768,7 +768,7 @@
 </histogram>
 
 <histogram name="Sync.KeystoreDecryptionFailed"
-    enum="SyncKeystoreDecryptionFailure" expires_after="2022-05-01">
+    enum="SyncKeystoreDecryptionFailure" expires_after="2022-07-03">
   <owner>mmoskvitin@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -786,7 +786,7 @@
   </summary>
 </histogram>
 
-<histogram name="Sync.Local.FileSizeKB" units="KB" expires_after="2022-04-30">
+<histogram name="Sync.Local.FileSizeKB" units="KB" expires_after="2022-07-03">
   <owner>pastarmovj@chromium.org</owner>
   <component>Services&gt;Sync</component>
   <summary>
@@ -817,7 +817,7 @@
 </histogram>
 
 <histogram name="Sync.Local.RoamingProfileUnavailable" enum="BooleanError"
-    expires_after="2022-04-30">
+    expires_after="2022-07-03">
   <owner>pastarmovj@chromium.org</owner>
   <component>Services&gt;Sync</component>
   <summary>
@@ -1502,7 +1502,7 @@
 </histogram>
 
 <histogram name="Sync.RecordedUserEventType" enum="SyncUserEventType"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>mmoskvitin@google.com</owner>
   <owner>treib@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -1542,7 +1542,7 @@
 </histogram>
 
 <histogram name="Sync.ResetEngineReason" enum="SyncResetEngineReason"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>rushans@google.com</owner>
   <owner>treib@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -1771,7 +1771,7 @@
 </histogram>
 
 <histogram name="Sync.TrustedVaultAccessTokenFetchSuccess" enum="Boolean"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>mmoskvitin@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -1782,7 +1782,7 @@
 </histogram>
 
 <histogram name="Sync.TrustedVaultAddKeysAttemptIsSuccessful" enum="Boolean"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>mmoskvitin@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -1793,7 +1793,7 @@
 </histogram>
 
 <histogram name="Sync.TrustedVaultDeviceRegistrationState"
-    enum="TrustedVaultDeviceRegistrationState" expires_after="2022-05-01">
+    enum="TrustedVaultDeviceRegistrationState" expires_after="2022-07-03">
   <owner>mmoskvitin@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -1805,7 +1805,7 @@
 </histogram>
 
 <histogram name="Sync.TrustedVaultErrorShownOnStartup" enum="Boolean"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>mmoskvitin@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -1817,7 +1817,7 @@
 </histogram>
 
 <histogram name="Sync.TrustedVaultFetchedKeysCount" units="keys"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>mmoskvitin@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -1827,7 +1827,7 @@
 </histogram>
 
 <histogram name="Sync.TrustedVaultFetchKeysAttempt"
-    enum="TrustedVaultFetchKeysAttempt" expires_after="2022-05-01">
+    enum="TrustedVaultFetchKeysAttempt" expires_after="2022-07-03">
   <owner>mmoskvitin@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -1859,7 +1859,7 @@
 </histogram>
 
 <histogram name="Sync.TrustedVaultRecoverabilityDegradedOnStartup"
-    enum="Boolean" expires_after="2022-05-01">
+    enum="Boolean" expires_after="2022-07-03">
   <owner>mmoskvitin@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -1872,7 +1872,7 @@
 </histogram>
 
 <histogram name="Sync.TrustedVaultURLFetchResponse"
-    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-05-01">
+    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-07-03">
   <owner>mmoskvitin@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml
index 4185697..b533c04 100644
--- a/tools/metrics/histograms/metadata/tab/histograms.xml
+++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -463,7 +463,7 @@
 </histogram>
 
 <histogram name="Tab.Screenshot.Action" enum="TabScreenshotAction"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>skare@chromium.org</owner>
   <summary>
     Records actions taken after one or more screenshots of a page were taken.
@@ -1050,7 +1050,7 @@
 </histogram>
 
 <histogram name="TabManager.Discarding.DiscardToReloadTime" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>chrisha@chromium.org</owner>
   <owner>catan-team@chromium.org</owner>
   <summary>
@@ -1652,7 +1652,7 @@
 </histogram>
 
 <histogram name="Tabs.PersistedTabData.Deserialize.Critical"
-    enum="BooleanSuccess" expires_after="2022-05-01">
+    enum="BooleanSuccess" expires_after="2022-07-03">
   <owner>yusufo@chromium.org</owner>
   <owner>nyquist@chromium.org</owner>
   <owner>dtrainor@chromium.org</owner>
@@ -1678,7 +1678,7 @@
 </histogram>
 
 <histogram name="Tabs.PersistedTabData.Storage.Delete.File"
-    enum="BooleanSuccess" expires_after="2022-05-01">
+    enum="BooleanSuccess" expires_after="2022-07-03">
   <owner>yusufo@chromium.org</owner>
   <owner>nyquist@chromium.org</owner>
   <owner>dtrainor@chromium.org</owner>
@@ -1691,7 +1691,7 @@
 </histogram>
 
 <histogram name="Tabs.PersistedTabData.Storage.Exists.File"
-    enum="BooleanSuccess" expires_after="2022-05-01">
+    enum="BooleanSuccess" expires_after="2022-07-03">
   <owner>yusufo@chromium.org</owner>
   <owner>nyquist@chromium.org</owner>
   <owner>dtrainor@chromium.org</owner>
@@ -2630,7 +2630,7 @@
   </summary>
 </histogram>
 
-<histogram name="Tabs.TabState.LoadTime" units="ms" expires_after="2022-05-01">
+<histogram name="Tabs.TabState.LoadTime" units="ms" expires_after="2022-07-03">
   <owner>yusufo@chromium.org</owner>
   <owner>nyquist@chromium.org</owner>
   <owner>dtrainor@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/ukm/histograms.xml b/tools/metrics/histograms/metadata/ukm/histograms.xml
index e04e06a..c8b6072f 100644
--- a/tools/metrics/histograms/metadata/ukm/histograms.xml
+++ b/tools/metrics/histograms/metadata/ukm/histograms.xml
@@ -175,7 +175,7 @@
 </histogram>
 
 <histogram name="UKM.LogUpload.ResponseOrErrorCode"
-    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-05-01">
+    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-07-03">
   <owner>rkaplow@chromium.org</owner>
   <owner>ukm-team@google.com</owner>
   <summary>
@@ -285,7 +285,7 @@
 </histogram>
 
 <histogram name="UKM.Sources.UnsentSourcesCount" units="sources"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>rkaplow@chromium.org</owner>
   <owner>ukm-team@google.com</owner>
   <summary>
@@ -305,7 +305,7 @@
 </histogram>
 
 <histogram name="UKM.UnsentLogs.NumDropped" units="units"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>rkaplow@chromium.org</owner>
   <owner>ukm-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/v8/histograms.xml b/tools/metrics/histograms/metadata/v8/histograms.xml
index f1e3c617..7d765bda 100644
--- a/tools/metrics/histograms/metadata/v8/histograms.xml
+++ b/tools/metrics/histograms/metadata/v8/histograms.xml
@@ -151,7 +151,7 @@
 </histogram>
 
 <histogram name="V8.CompileScript.CacheBehaviour" enum="V8CacheBehaviour"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>leszeks@chromium.org</owner>
   <owner>v8-runtime@google.com</owner>
   <summary>
@@ -793,7 +793,7 @@
 </histogram>
 
 <histogram name="V8.GC.TimeToCollectionOnBackground" units="microseconds"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>dinfuehr@chromium.org</owner>
   <owner>v8-memory-sheriffs@google.com</owner>
   <summary>
@@ -984,7 +984,7 @@
 </histogram>
 
 <histogram name="V8.GCFinalizeMCReduceMemory" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>mlippautz@chromium.org</owner>
   <owner>hpayer@chromium.org</owner>
   <owner>v8-memory-sheriffs@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/variations/histograms.xml b/tools/metrics/histograms/metadata/variations/histograms.xml
index f41d5be..c0a61ea 100644
--- a/tools/metrics/histograms/metadata/variations/histograms.xml
+++ b/tools/metrics/histograms/metadata/variations/histograms.xml
@@ -228,7 +228,7 @@
 </histogram>
 
 <histogram name="Variations.Headers.ExperimentCount" units="units"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>asvitkine@chromium.org</owner>
   <owner>rkaplow@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
@@ -521,7 +521,7 @@
 </histogram>
 
 <histogram name="Variations.SeedFreshness" units="minutes"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>asvitkine@chromium.org</owner>
   <owner>rkaplow@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
@@ -561,7 +561,7 @@
 </histogram>
 
 <histogram name="Variations.SeedLoadResult" enum="VariationsSeedLoadResult"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>asvitkine@chromium.org</owner>
   <owner>rkaplow@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
@@ -707,7 +707,7 @@
 </histogram>
 
 <histogram name="Variations.UserChannel" enum="UserChannels"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>asvitkine@chromium.org</owner>
   <owner>rkaplow@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
diff --git a/tools/metrics/histograms/metadata/video_tutorials/histograms.xml b/tools/metrics/histograms/metadata/video_tutorials/histograms.xml
index 3c458ea..5491653 100644
--- a/tools/metrics/histograms/metadata/video_tutorials/histograms.xml
+++ b/tools/metrics/histograms/metadata/video_tutorials/histograms.xml
@@ -54,7 +54,7 @@
 </histogram>
 
 <histogram name="VideoTutorials.Player.LoadTimeLatency" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>shaktisahu@chromium.org</owner>
   <owner>chrome-upboarding-eng@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/web_apk/histograms.xml b/tools/metrics/histograms/metadata/web_apk/histograms.xml
index 4f20925..e3fc116a 100644
--- a/tools/metrics/histograms/metadata/web_apk/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_apk/histograms.xml
@@ -357,7 +357,7 @@
 </histogram>
 
 <histogram name="WebApk.WebappRegistry.NumberOfOrigins" units="count"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>eirage@chromium.org</owner>
   <owner>
     src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS
diff --git a/tools/metrics/histograms/metadata/web_audio/histograms.xml b/tools/metrics/histograms/metadata/web_audio/histograms.xml
index 5e2146d..db828c1 100644
--- a/tools/metrics/histograms/metadata/web_audio/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_audio/histograms.xml
@@ -121,7 +121,7 @@
 </histogram>
 
 <histogram name="WebAudio.AudioContextOptions.sampleRateRatio" units="units"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>hongchan@chromium.org</owner>
   <summary>
     The ratio of the user-selected sample rate to the hardware sample rate of an
diff --git a/tools/metrics/histograms/metadata/web_rtc/histograms.xml b/tools/metrics/histograms/metadata/web_rtc/histograms.xml
index dd93522..2003953b 100644
--- a/tools/metrics/histograms/metadata/web_rtc/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_rtc/histograms.xml
@@ -523,7 +523,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.AudioMixer.NumIncomingStreams" units="streams"
-    expires_after="2022-04-30">
+    expires_after="2022-07-03">
   <owner>alessiob@chromium.org</owner>
   <owner>webrtc-audio@google.com</owner>
   <summary>
@@ -1115,7 +1115,7 @@
 </histogram>
 
 <histogram name="WebRTC.BWE.RampUpTimeTo2000kbpsInMs" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>holmer@chromium.org</owner>
   <summary>
     The time it takes the estimated bandwidth to reach 2000 kbps from the first
@@ -1153,7 +1153,7 @@
 </histogram>
 
 <histogram name="WebRTC.Call.BitrateReceivedInKbps" units="kbps"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>holmer@chromium.org</owner>
   <summary>
     Average total bitrate received during a call (audio + video + RTCP), counted
@@ -1181,7 +1181,7 @@
 </histogram>
 
 <histogram name="WebRTC.Call.PacerBitrateInKbps" units="kbps"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>holmer@chromium.org</owner>
   <summary>
     Average pacer bitrate during a call, counted from first packet sent until
@@ -1225,7 +1225,7 @@
 </histogram>
 
 <histogram name="WebRTC.Call.VideoBitrateReceivedInKbps" units="kbps"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>holmer@chromium.org</owner>
   <summary>
     Average video bitrate received during a call, counted from first packet
@@ -1362,7 +1362,7 @@
 </histogram>
 
 <histogram name="WebRTC.DesktopCaptureCounters" enum="DesktopCaptureCounters"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>toprice@chromium.org</owner>
   <owner>webrtc-dev@chromium.org</owner>
   <summary>
@@ -1464,7 +1464,7 @@
 </histogram>
 
 <histogram name="WebRTC.PeerConnection.CandidatePoolUsage.{BundlePolicy}"
-    units="components" expires_after="2022-01-01">
+    units="components" expires_after="2022-07-01">
   <owner>hta@chromium.org</owner>
   <owner>webrtc-dev@chromium.org</owner>
   <summary>
@@ -1847,7 +1847,7 @@
 </histogram>
 
 <histogram name="WebRTC.PeerConnection.SdpFormatReceivedAnswer"
-    enum="PeerConnectionSdpFormatReceived" expires_after="2022-05-01">
+    enum="PeerConnectionSdpFormatReceived" expires_after="2022-07-03">
   <owner>steveanton@chromium.org</owner>
   <owner>hta@chromium.org</owner>
   <owner>webrtc-dev@chromium.org</owner>
@@ -1859,7 +1859,7 @@
 </histogram>
 
 <histogram name="WebRTC.PeerConnection.SdpSemanticNegotiated"
-    enum="PeerConnectionSdpSemanticNegotiated" expires_after="2022-05-01">
+    enum="PeerConnectionSdpSemanticNegotiated" expires_after="2022-07-03">
   <owner>hta@chromium.org</owner>
   <owner>webrtc-dev@chromium.org</owner>
   <summary>
@@ -1872,7 +1872,7 @@
 </histogram>
 
 <histogram name="WebRTC.PeerConnection.SdpSemanticRequested"
-    enum="PeerConnectionSdpSemanticRequested" expires_after="2022-05-01">
+    enum="PeerConnectionSdpSemanticRequested" expires_after="2022-07-03">
   <owner>hta@chromium.org</owner>
   <owner>webrtc-dev@chromium.org</owner>
   <summary>
@@ -4176,7 +4176,7 @@
 </histogram>
 
 <histogram name="WebRtcTextLogging.UploadFailureReason"
-    enum="WebRtcLoggingUploadFailureReason" expires_after="2022-05-01">
+    enum="WebRtcLoggingUploadFailureReason" expires_after="2022-07-03">
   <owner>toprice@chromium.org</owner>
   <owner>olka@chromium.org</owner>
   <owner>webrtc-dev@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/webapps/histograms.xml b/tools/metrics/histograms/metadata/webapps/histograms.xml
index 2a4b242..d726b7b 100644
--- a/tools/metrics/histograms/metadata/webapps/histograms.xml
+++ b/tools/metrics/histograms/metadata/webapps/histograms.xml
@@ -62,7 +62,7 @@
 </histogram>
 
 <histogram name="AppBanners.InstallableStatusCode"
-    enum="AppBannersInstallableStatusCode" expires_after="2022-05-01">
+    enum="AppBannersInstallableStatusCode" expires_after="2022-07-03">
   <owner>dominickn@chromium.org</owner>
   <owner>pjmclachlan@google.com</owner>
   <summary>
@@ -75,7 +75,7 @@
 </histogram>
 
 <histogram name="AppBanners.InstallEvent" enum="AppBannersInstallEvent"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>dominickn@chromium.org</owner>
   <owner>pjmclachlan@google.com</owner>
   <owner>pcovell@google.com</owner>
@@ -502,7 +502,7 @@
 </histogram>
 
 <histogram name="WebApp.Preinstalled.EnabledCount" units="apps"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>alancutter@chromium.org</owner>
   <owner>desktop-pwas-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/webauthn/histograms.xml b/tools/metrics/histograms/metadata/webauthn/histograms.xml
index 43fa742..54dc324f 100644
--- a/tools/metrics/histograms/metadata/webauthn/histograms.xml
+++ b/tools/metrics/histograms/metadata/webauthn/histograms.xml
@@ -40,7 +40,7 @@
 </histogram>
 
 <histogram name="WebAuthentication.CableV1DiscoveryEvent"
-    enum="WebAuthenticationCableV1DiscoveryEvent" expires_after="2022-05-01">
+    enum="WebAuthenticationCableV1DiscoveryEvent" expires_after="2022-07-03">
   <owner>agl@chromium.org</owner>
   <owner>martinkr@google.com</owner>
   <summary>
@@ -68,7 +68,7 @@
 </histogram>
 
 <histogram name="WebAuthentication.CableV2.GetAssertionTime" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>agl@chromium.org</owner>
   <owner>martinkr@google.com</owner>
   <summary>
@@ -250,7 +250,7 @@
 </histogram>
 
 <histogram name="WebAuthentication.IsUVPlatformAuthenticatorAvailable2"
-    enum="Boolean" expires_after="2022-05-01">
+    enum="Boolean" expires_after="2022-07-03">
   <owner>kenrb@chromium.org</owner>
   <owner>martinkr@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/windows/histograms.xml b/tools/metrics/histograms/metadata/windows/histograms.xml
index c19c6f4..449f75e 100644
--- a/tools/metrics/histograms/metadata/windows/histograms.xml
+++ b/tools/metrics/histograms/metadata/windows/histograms.xml
@@ -369,7 +369,7 @@
 </histogram>
 
 <histogram name="Windows.ProcessorFamily" enum="ProcessorFamily"
-    expires_after="2022-05-01">
+    expires_after="2022-07-03">
   <owner>rkc@chromium.org</owner>
   <owner>rockot@chromium.org</owner>
   <summary>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index dc36edb7..a0faa6b8f 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,28 +5,24 @@
             "remote_path": "perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "win": {
-            "hash": "721a33cf76548482ca67d76a59793e52d05a73cf",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/e780c370b9272c36eab718bacaa100537fd8d215/trace_processor_shell.exe"
-        },
-        "linux_arm": {
-            "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
+            "hash": "c14f8752d1b3b0b943ba077f058b962e1cab199a",
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/6303738528d33d2ac5ed455564eb8f08e14c931b/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893",
             "remote_path": "perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "mac": {
-            "hash": "802fed751d62ca3db41bc4ae27e43b546d000ce8",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/e780c370b9272c36eab718bacaa100537fd8d215/trace_processor_shell"
+            "hash": "43533dae803276f1c5302f76e8a3efd840648580",
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/6303738528d33d2ac5ed455564eb8f08e14c931b/trace_processor_shell"
         },
         "mac_arm64": {
             "hash": "c0397e87456ad6c6a7aa0133e5b81c97adbab4ab",
             "remote_path": "perfetto_binaries/trace_processor_shell/mac_arm64/cefb3e0ec3a0580c996f801e854fe02963c03d5c/trace_processor_shell"
         },
         "linux": {
-            "hash": "b398814dcad4d922530117d4c3d0d3517e8ac4a7",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/e780c370b9272c36eab718bacaa100537fd8d215/trace_processor_shell"
+            "hash": "26ff45cad5f66068a3d6ca17d9905653f74787c4",
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/6303738528d33d2ac5ed455564eb8f08e14c931b/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/perf/page_sets/rendering/motionmark.py b/tools/perf/page_sets/rendering/motionmark.py
index d8a95e7..92acdb6 100644
--- a/tools/perf/page_sets/rendering/motionmark.py
+++ b/tools/perf/page_sets/rendering/motionmark.py
@@ -17,12 +17,12 @@
                page_set,
                shared_page_state_class=shared_page_state.SharedMobilePageState,
                name_suffix='',
-               make_javascript_deterministic=False,
                extra_browser_args=None):
     super(MotionMarkPage, self).__init__(
         page_set=page_set,
         shared_page_state_class=shared_page_state_class,
         name_suffix=name_suffix,
+        make_javascript_deterministic=False,
         extra_browser_args=['--report-silk-details', '--disable-top-sites'])
     self._score = 0
     self._scoreLowerBound = 0
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 5a646828..1422aa2 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -85,7 +85,7 @@
  <item id="enterprise_safe_browsing_realtime_url_lookup" added_in_milestone="86" content_hash_code="00d66dca" os_list="linux,windows,chromeos" file_path="chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.cc" />
  <item id="expect_ct_reporter" added_in_milestone="69" content_hash_code="07c7284e" os_list="linux,windows,chromeos,android" file_path="services/network/expect_ct_reporter.cc" />
  <item id="extension_blacklist" added_in_milestone="62" content_hash_code="06f55974" os_list="linux,windows,chromeos" file_path="chrome/browser/extensions/blocklist_state_fetcher.cc" />
- <item id="extension_crx_fetcher" added_in_milestone="62" content_hash_code="04b7bcef" os_list="linux,windows,chromeos" file_path="extensions/browser/updater/extension_downloader.cc" />
+ <item id="extension_crx_fetcher" added_in_milestone="62" content_hash_code="05d3e86d" os_list="linux,windows,chromeos" file_path="extensions/browser/updater/extension_downloader.cc" />
  <item id="extension_install_signer" added_in_milestone="62" content_hash_code="065c4bce" os_list="linux,windows,chromeos" file_path="chrome/browser/extensions/install_signer.cc" />
  <item id="extension_manifest_fetcher" added_in_milestone="62" content_hash_code="05983aa9" os_list="linux,windows,chromeos" file_path="extensions/browser/updater/extension_downloader.cc" />
  <item id="external_policy_fetcher" added_in_milestone="62" content_hash_code="03d48984" os_list="linux,windows,chromeos" file_path="components/policy/core/common/cloud/external_policy_data_fetcher.cc" />
diff --git a/ui/aura/cursor/cursors_aura.cc b/ui/aura/cursor/cursors_aura.cc
index f22b7159..fff9928 100644
--- a/ui/aura/cursor/cursors_aura.cc
+++ b/ui/aura/cursor/cursors_aura.cc
@@ -164,7 +164,7 @@
      IDR_AURA_CURSOR_BIG_NO_DROP,
      {10, 10},
      {20, 20}},
-    {mojom::CursorType::kCopy, IDR_AURA_CURSOR_BIG_COPY, {10, 10}, {20, 20}},
+    {mojom::CursorType::kCopy, IDR_AURA_CURSOR_BIG_COPY, {21, 11}, {42, 22}},
     {mojom::CursorType::kHand, IDR_AURA_CURSOR_BIG_HAND, {25, 7}, {50, 14}},
     {mojom::CursorType::kMove, IDR_AURA_CURSOR_BIG_MOVE, {32, 31}, {64, 62}},
     {mojom::CursorType::kNorthEastResize,
diff --git a/ui/aura/env_input_state_controller.cc b/ui/aura/env_input_state_controller.cc
index b8eb033..0f21c8b6 100644
--- a/ui/aura/env_input_state_controller.cc
+++ b/ui/aura/env_input_state_controller.cc
@@ -51,7 +51,7 @@
     case ui::ET_TOUCH_CANCELLED:
       if (!event.HasNativeEvent())
         break;
-      FALLTHROUGH;
+      [[fallthrough]];
     case ui::ET_TOUCH_RELEASED:
       touch_ids_down_ = (touch_ids_down_ | (1 << event.pointer_details().id)) ^
                         (1 << event.pointer_details().id);
diff --git a/ui/base/cursor/cursor_factory.cc b/ui/base/cursor/cursor_factory.cc
index 1b727571..edb3c7b 100644
--- a/ui/base/cursor/cursor_factory.cc
+++ b/ui/base/cursor/cursor_factory.cc
@@ -192,7 +192,7 @@
       // kCustom is for custom image cursors. The platform cursor will be set
       // at WebCursor::GetNativeCursor().
       NOTREACHED();
-      FALLTHROUGH;
+      [[fallthrough]];
     case mojom::CursorType::kNull:
     case mojom::CursorType::kPointer:
       return {"left_ptr"};
diff --git a/ui/gfx/animation/tween.cc b/ui/gfx/animation/tween.cc
index 1f1191beb..51de0ba8 100644
--- a/ui/gfx/animation/tween.cc
+++ b/ui/gfx/animation/tween.cc
@@ -104,6 +104,9 @@
 
     case ACCEL_0_80_DECEL_80:
       return gfx::CubicBezier(0, 0.8, 0.2, 1).Solve(state);
+
+    case ACCEL_0_100_DECEL_80:
+      return gfx::CubicBezier(0, 1, 0.2, 1).Solve(state);
   }
 
   NOTREACHED();
diff --git a/ui/gfx/animation/tween.h b/ui/gfx/animation/tween.h
index d5d7d41..f3f564c4 100644
--- a/ui/gfx/animation/tween.h
+++ b/ui/gfx/animation/tween.h
@@ -74,6 +74,9 @@
     ACCEL_0_80_DECEL_80,   // Variant of ACCEL_0_40_DECEL_100 which drops in
                            // value faster, but flattens out into the drift
                            // sooner.
+
+    ACCEL_0_100_DECEL_80,  // Variant of ACCEL_0_80_DECEL_80 which drops in
+                           // value even faster.
   };
 
   Tween(const Tween&) = delete;
diff --git a/ui/message_center/views/notification_view.cc b/ui/message_center/views/notification_view.cc
index 2c1ebe5..8f1fcf6d 100644
--- a/ui/message_center/views/notification_view.cc
+++ b/ui/message_center/views/notification_view.cc
@@ -412,7 +412,7 @@
           IDS_MESSAGE_CENTER_BLOCK_ALL_NOTIFICATIONS;
       break;
     case NotifierType::CROSTINI_APPLICATION:
-      FALLTHROUGH;
+      [[fallthrough]];
     // PhoneHub notifications do not have inline settings.
     case NotifierType::PHONE_HUB:
       NOTREACHED();
diff --git a/ui/message_center/views/notification_view_base.h b/ui/message_center/views/notification_view_base.h
index 8101b706..19f003d 100644
--- a/ui/message_center/views/notification_view_base.h
+++ b/ui/message_center/views/notification_view_base.h
@@ -239,6 +239,8 @@
   views::Label* message_view() { return message_view_; }
   const views::Label* message_view() const { return message_view_; }
 
+  ProportionalImageView* icon_view() const { return icon_view_; }
+
   views::View* inline_settings_row() { return settings_row_; }
   const views::View* inline_settings_row() const { return settings_row_; }
 
@@ -262,6 +264,8 @@
     inline_settings_enabled_ = inline_settings_enabled;
   }
 
+  bool hide_icon_on_expanded() const { return hide_icon_on_expanded_; }
+
   virtual bool IsExpandable() const = 0;
 
   virtual void SetExpandButtonEnabled(bool enabled);
diff --git a/ui/native_theme/native_theme_win.cc b/ui/native_theme/native_theme_win.cc
index 2165990..ed2509d 100644
--- a/ui/native_theme/native_theme_win.cc
+++ b/ui/native_theme/native_theme_win.cc
@@ -458,7 +458,7 @@
           PaintLeftMenuArrowThemed(hdc, handle, part_id, state_id, rect);
           return;
         }
-        FALLTHROUGH;
+        [[fallthrough]];
       case kCheckbox:
       case kInnerSpinButton:
       case kMenuCheck:
@@ -1425,7 +1425,7 @@
     case kScrollbarVerticalThumb:
       if ((state == kHovered) && !extra.scrollbar_thumb.is_hovering)
         return SCRBS_HOT;
-      FALLTHROUGH;
+      [[fallthrough]];
     case kScrollbarHorizontalTrack:
     case kScrollbarVerticalTrack:
       switch (state) {
diff --git a/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc b/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
index 574bdfa..ea3e84fa 100644
--- a/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
+++ b/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
@@ -288,7 +288,7 @@
                                      primary_plane_rect_.size()))
           LOG(FATAL) << "Failed to recreate buffer";
       }
-      FALLTHROUGH;  // We want to render a new frame anyways.
+      [[fallthrough]];  // We want to render a new frame anyways.
     case gfx::SwapResult::SWAP_ACK:
       SkiaGlRenderer::PostRenderFrameTask(std::move(result));
       break;
diff --git a/ui/ozone/demo/surfaceless_gl_renderer.cc b/ui/ozone/demo/surfaceless_gl_renderer.cc
index e91670d..87e4adf 100644
--- a/ui/ozone/demo/surfaceless_gl_renderer.cc
+++ b/ui/ozone/demo/surfaceless_gl_renderer.cc
@@ -306,7 +306,7 @@
         if (!buffers_[i]->Initialize(widget_, primary_plane_rect_.size()))
           LOG(FATAL) << "Failed to recreate buffer";
       }
-      FALLTHROUGH;  // We want to render a new frame anyways.
+      [[fallthrough]];  // We want to render a new frame anyways.
     case gfx::SwapResult::SWAP_ACK:
       base::ThreadTaskRunnerHandle::Get()->PostTask(
           FROM_HERE, base::BindOnce(&SurfacelessGlRenderer::RenderFrame,
diff --git a/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc b/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
index d1ece63..a4162ad 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
+++ b/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
@@ -193,14 +193,22 @@
     uint32_t planes_count,
     uint32_t buffer_id) {
   DCHECK(gpu_thread_runner_);
-  // Do the mojo call on the GpuMainThread.
-  gpu_thread_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&WaylandBufferManagerGpu::CreateDmabufBasedBufferInternal,
-                     base::Unretained(this), std::move(dmabuf_fd),
-                     std::move(size), std::move(strides), std::move(offsets),
-                     std::move(modifiers), current_format, planes_count,
-                     buffer_id));
+  if (!gpu_thread_runner_->BelongsToCurrentThread()) {
+    // Do the mojo call on the GpuMainThread.
+    gpu_thread_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&WaylandBufferManagerGpu::CreateDmabufBasedBuffer,
+                       base::Unretained(this), std::move(dmabuf_fd),
+                       std::move(size), std::move(strides), std::move(offsets),
+                       std::move(modifiers), current_format, planes_count,
+                       buffer_id));
+    return;
+  }
+
+  DCHECK(remote_host_);
+  remote_host_->CreateDmabufBasedBuffer(
+      mojo::PlatformHandle(std::move(dmabuf_fd)), size, strides, offsets,
+      modifiers, current_format, planes_count, buffer_id);
 }
 
 void WaylandBufferManagerGpu::CreateShmBasedBuffer(base::ScopedFD shm_fd,
@@ -209,22 +217,35 @@
                                                    uint32_t buffer_id) {
   DCHECK(gpu_thread_runner_);
   // Do the mojo call on the GpuMainThread.
-  gpu_thread_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&WaylandBufferManagerGpu::CreateShmBasedBufferInternal,
-                     base::Unretained(this), std::move(shm_fd), length,
-                     std::move(size), buffer_id));
+  if (!gpu_thread_runner_->BelongsToCurrentThread()) {
+    gpu_thread_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&WaylandBufferManagerGpu::CreateShmBasedBuffer,
+                       base::Unretained(this), std::move(shm_fd), length,
+                       std::move(size), buffer_id));
+    return;
+  }
+
+  DCHECK(remote_host_);
+  remote_host_->CreateShmBasedBuffer(mojo::PlatformHandle(std::move(shm_fd)),
+                                     length, size, buffer_id);
 }
 
 void WaylandBufferManagerGpu::CreateSolidColorBuffer(SkColor color,
                                                      const gfx::Size& size,
                                                      uint32_t buf_id) {
   DCHECK(gpu_thread_runner_);
-  // Do the mojo call on the GpuMainThread.
-  gpu_thread_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&WaylandBufferManagerGpu::CreateSolidColorBufferInternal,
-                     base::Unretained(this), color, size, buf_id));
+  if (!gpu_thread_runner_->BelongsToCurrentThread()) {
+    // Do the mojo call on the GpuMainThread.
+    gpu_thread_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&WaylandBufferManagerGpu::CreateSolidColorBuffer,
+                       base::Unretained(this), color, size, buf_id));
+    return;
+  }
+
+  DCHECK(remote_host_);
+  remote_host_->CreateSolidColorBuffer(size, color, buf_id);
 }
 
 void WaylandBufferManagerGpu::CommitBuffer(gfx::AcceleratedWidget widget,
@@ -248,20 +269,32 @@
     gfx::AcceleratedWidget widget,
     std::vector<ozone::mojom::WaylandOverlayConfigPtr> overlays) {
   DCHECK(gpu_thread_runner_);
-  // Do the mojo call on the GpuMainThread.
-  gpu_thread_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&WaylandBufferManagerGpu::CommitOverlaysInternal,
-                     base::Unretained(this), widget, std::move(overlays)));
+  if (!gpu_thread_runner_->BelongsToCurrentThread()) {
+    // Do the mojo call on the GpuMainThread.
+    gpu_thread_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&WaylandBufferManagerGpu::CommitOverlays,
+                       base::Unretained(this), widget, std::move(overlays)));
+    return;
+  }
+
+  DCHECK(remote_host_);
+  remote_host_->CommitOverlays(widget, std::move(overlays));
 }
 
 void WaylandBufferManagerGpu::DestroyBuffer(gfx::AcceleratedWidget widget,
                                             uint32_t buffer_id) {
   DCHECK(gpu_thread_runner_);
-  // Do the mojo call on the GpuMainThread.
-  gpu_thread_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&WaylandBufferManagerGpu::DestroyBufferInternal,
-                                base::Unretained(this), widget, buffer_id));
+  if (!gpu_thread_runner_->BelongsToCurrentThread()) {
+    // Do the mojo call on the GpuMainThread.
+    gpu_thread_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&WaylandBufferManagerGpu::DestroyBuffer,
+                                  base::Unretained(this), widget, buffer_id));
+    return;
+  }
+
+  DCHECK(remote_host_);
+  remote_host_->DestroyBuffer(widget, buffer_id);
 }
 
 #if defined(WAYLAND_GBM)
@@ -307,63 +340,6 @@
   return ++next_buffer_id_;
 }
 
-void WaylandBufferManagerGpu::CreateDmabufBasedBufferInternal(
-    base::ScopedFD dmabuf_fd,
-    gfx::Size size,
-    const std::vector<uint32_t>& strides,
-    const std::vector<uint32_t>& offsets,
-    const std::vector<uint64_t>& modifiers,
-    uint32_t current_format,
-    uint32_t planes_count,
-    uint32_t buffer_id) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
-
-  DCHECK(remote_host_);
-  remote_host_->CreateDmabufBasedBuffer(
-      mojo::PlatformHandle(std::move(dmabuf_fd)), size, strides, offsets,
-      modifiers, current_format, planes_count, buffer_id);
-}
-
-void WaylandBufferManagerGpu::CreateShmBasedBufferInternal(
-    base::ScopedFD shm_fd,
-    size_t length,
-    gfx::Size size,
-    uint32_t buffer_id) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
-
-  DCHECK(remote_host_);
-  remote_host_->CreateShmBasedBuffer(mojo::PlatformHandle(std::move(shm_fd)),
-                                     length, size, buffer_id);
-}
-
-void WaylandBufferManagerGpu::CreateSolidColorBufferInternal(
-    SkColor color,
-    const gfx::Size& size,
-    uint32_t buf_id) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
-
-  DCHECK(remote_host_);
-  remote_host_->CreateSolidColorBuffer(size, color, buf_id);
-}
-
-void WaylandBufferManagerGpu::CommitOverlaysInternal(
-    gfx::AcceleratedWidget widget,
-    std::vector<ozone::mojom::WaylandOverlayConfigPtr> overlays) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
-
-  DCHECK(remote_host_);
-  remote_host_->CommitOverlays(widget, std::move(overlays));
-}
-
-void WaylandBufferManagerGpu::DestroyBufferInternal(
-    gfx::AcceleratedWidget widget,
-    uint32_t buffer_id) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
-
-  DCHECK(remote_host_);
-  remote_host_->DestroyBuffer(widget, buffer_id);
-}
-
 void WaylandBufferManagerGpu::BindHostInterface(
     mojo::PendingRemote<ozone::mojom::WaylandBufferManagerHost> remote_host) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
diff --git a/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h b/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
index 68854841..7fb4a7b 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
+++ b/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
@@ -162,26 +162,6 @@
   FRIEND_TEST_ALL_PREFIXES(WaylandSurfaceFactoryTest,
                            GbmSurfacelessWaylandGroupOnSubmissionCallbacksTest);
 
-  void CreateDmabufBasedBufferInternal(base::ScopedFD dmabuf_fd,
-                                       gfx::Size size,
-                                       const std::vector<uint32_t>& strides,
-                                       const std::vector<uint32_t>& offsets,
-                                       const std::vector<uint64_t>& modifiers,
-                                       uint32_t current_format,
-                                       uint32_t planes_count,
-                                       uint32_t buffer_id);
-  void CreateShmBasedBufferInternal(base::ScopedFD shm_fd,
-                                    size_t length,
-                                    gfx::Size size,
-                                    uint32_t buffer_id);
-  void CreateSolidColorBufferInternal(SkColor color,
-                                      const gfx::Size& size,
-                                      uint32_t buf_id);
-  void CommitOverlaysInternal(
-      gfx::AcceleratedWidget widget,
-      std::vector<ozone::mojom::WaylandOverlayConfigPtr> overlays);
-  void DestroyBufferInternal(gfx::AcceleratedWidget widget, uint32_t buffer_id);
-
   void BindHostInterface(
       mojo::PendingRemote<ozone::mojom::WaylandBufferManagerHost> remote_host);
 
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
index c0d2c4e..424b297 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
+++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
@@ -50,7 +50,7 @@
       return DragOperation::kMove;
     case WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK:
       // Unsupported in the browser.
-      FALLTHROUGH;
+      [[fallthrough]];
     default:
       return DragOperation::kNone;
   }
diff --git a/ui/ozone/platform/x11/BUILD.gn b/ui/ozone/platform/x11/BUILD.gn
index 8028b74..4828f27 100644
--- a/ui/ozone/platform/x11/BUILD.gn
+++ b/ui/ozone/platform/x11/BUILD.gn
@@ -18,8 +18,6 @@
     "gl_egl_utility_x11.h",
     "gl_ozone_glx.cc",
     "gl_ozone_glx.h",
-    "gl_surface_egl_readback_x11.cc",
-    "gl_surface_egl_readback_x11.h",
     "linux_ui_delegate_x11.cc",
     "linux_ui_delegate_x11.h",
     "ozone_platform_x11.cc",
diff --git a/ui/ozone/platform/x11/gl_surface_egl_readback_x11.cc b/ui/ozone/platform/x11/gl_surface_egl_readback_x11.cc
deleted file mode 100644
index c76733f..0000000
--- a/ui/ozone/platform/x11/gl_surface_egl_readback_x11.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2018 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 "ui/ozone/platform/x11/gl_surface_egl_readback_x11.h"
-
-#include "base/logging.h"
-#include "third_party/skia/include/core/SkImageInfo.h"
-#include "third_party/skia/include/core/SkPixmap.h"
-#include "ui/base/x/x11_util.h"
-#include "ui/gfx/x/xproto.h"
-
-namespace ui {
-
-namespace {
-
-constexpr x11::GraphicsContext kNoGC = x11::GraphicsContext{};
-
-}
-
-GLSurfaceEglReadbackX11::GLSurfaceEglReadbackX11(gfx::AcceleratedWidget window)
-    : window_(static_cast<x11::Window>(window)),
-      connection_(x11::Connection::Get()) {}
-
-bool GLSurfaceEglReadbackX11::Initialize(gl::GLSurfaceFormat format) {
-  if (!GLSurfaceEglReadback::Initialize(format))
-    return false;
-
-  // We don't need to reinitialize |window_graphics_context_|.
-  if (window_graphics_context_ != kNoGC)
-    return true;
-
-  window_graphics_context_ = connection_->GenerateId<x11::GraphicsContext>();
-  auto gc_future = connection_->CreateGC({window_graphics_context_, window_});
-
-  if (auto attributes = connection_->GetWindowAttributes({window_}).Sync()) {
-    visual_ = attributes->visual;
-  } else {
-    DLOG(ERROR) << "Failed to get attributes for window "
-                << static_cast<uint32_t>(window_);
-    Destroy();
-    return false;
-  }
-
-  if (gc_future.Sync().error) {
-    DLOG(ERROR) << "XCreateGC failed";
-    Destroy();
-    return false;
-  }
-
-  return true;
-}
-
-void GLSurfaceEglReadbackX11::Destroy() {
-  if (window_graphics_context_ != kNoGC) {
-    connection_->FreeGC({window_graphics_context_});
-    window_graphics_context_ = kNoGC;
-  }
-
-  connection_->Sync();
-
-  GLSurfaceEglReadback::Destroy();
-}
-
-GLSurfaceEglReadbackX11::~GLSurfaceEglReadbackX11() {
-  Destroy();
-}
-
-bool GLSurfaceEglReadbackX11::HandlePixels(uint8_t* pixels) {
-  SkImageInfo image_info =
-      SkImageInfo::Make(GetSize().width(), GetSize().height(),
-                        kBGRA_8888_SkColorType, kPremul_SkAlphaType);
-  SkPixmap pixmap(image_info, pixels, image_info.minRowBytes());
-
-  // Copy pixels into pixmap and then update the XWindow.
-  const gfx::Size size = GetSize();
-  DrawPixmap(connection_, visual_, window_, window_graphics_context_, pixmap, 0,
-             0, 0, 0, size.width(), size.height());
-
-  return true;
-}
-
-}  // namespace ui
diff --git a/ui/ozone/platform/x11/gl_surface_egl_readback_x11.h b/ui/ozone/platform/x11/gl_surface_egl_readback_x11.h
deleted file mode 100644
index 7459e00..0000000
--- a/ui/ozone/platform/x11/gl_surface_egl_readback_x11.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2018 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 UI_OZONE_PLATFORM_X11_GL_SURFACE_EGL_READBACK_X11_H_
-#define UI_OZONE_PLATFORM_X11_GL_SURFACE_EGL_READBACK_X11_H_
-
-#include "ui/gfx/x/xproto.h"
-#include "ui/ozone/common/gl_surface_egl_readback.h"
-
-namespace ui {
-
-// GLSurface implementation that copies pixels from readback to an XWindow.
-class GLSurfaceEglReadbackX11 : public GLSurfaceEglReadback {
- public:
-  explicit GLSurfaceEglReadbackX11(gfx::AcceleratedWidget window);
-
-  GLSurfaceEglReadbackX11(const GLSurfaceEglReadbackX11&) = delete;
-  GLSurfaceEglReadbackX11& operator=(const GLSurfaceEglReadbackX11&) = delete;
-
-  // gl::GLSurface:
-  bool Initialize(gl::GLSurfaceFormat format) override;
-  void Destroy() override;
-
- private:
-  ~GLSurfaceEglReadbackX11() override;
-
-  // gl::GLSurfaceEglReadback:
-  bool HandlePixels(uint8_t* pixels) override;
-
-  const x11::Window window_;
-  x11::Connection* const connection_;
-  x11::GraphicsContext window_graphics_context_{};
-  x11::VisualId visual_{};
-};
-
-}  // namespace ui
-
-#endif  // UI_OZONE_PLATFORM_X11_GL_SURFACE_EGL_READBACK_X11_H_
diff --git a/ui/ozone/platform/x11/x11_surface_factory.cc b/ui/ozone/platform/x11/x11_surface_factory.cc
index ae6544a8..bccc3eb 100644
--- a/ui/ozone/platform/x11/x11_surface_factory.cc
+++ b/ui/ozone/platform/x11/x11_surface_factory.cc
@@ -17,7 +17,6 @@
 #include "ui/ozone/common/egl_util.h"
 #include "ui/ozone/common/gl_ozone_egl.h"
 #include "ui/ozone/platform/x11/gl_ozone_glx.h"
-#include "ui/ozone/platform/x11/gl_surface_egl_readback_x11.h"
 #include "ui/ozone/platform/x11/x11_canvas_surface.h"
 
 #if BUILDFLAG(ENABLE_VULKAN)
@@ -39,29 +38,26 @@
   // GLOzone:
   bool InitializeStaticGLBindings(
       const gl::GLImplementationParts& implementation) override {
-    is_swiftshader_ = gl::IsSoftwareGLImplementation(implementation);
     return GLOzoneEGL::InitializeStaticGLBindings(implementation);
   }
 
   scoped_refptr<gl::GLSurface> CreateViewGLSurface(
       gfx::AcceleratedWidget window) override {
-    if (is_swiftshader_) {
-      return gl::InitializeGLSurface(
-          base::MakeRefCounted<GLSurfaceEglReadbackX11>(window));
-    } else {
-      switch (gl::GetGLImplementation()) {
-        case gl::kGLImplementationEGLGLES2:
-          DCHECK(window != gfx::kNullAcceleratedWidget);
-          return gl::InitializeGLSurface(new gl::NativeViewGLSurfaceEGLX11GLES2(
-              static_cast<x11::Window>(window)));
-        case gl::kGLImplementationEGLANGLE:
-          DCHECK(window != gfx::kNullAcceleratedWidget);
-          return gl::InitializeGLSurface(new gl::NativeViewGLSurfaceEGLX11(
-              static_cast<x11::Window>(window)));
-        default:
-          NOTREACHED();
-          return nullptr;
-      }
+    switch (gl::GetGLImplementation()) {
+      // TODO(penghuang): remove NativeViewGLSurfaceEGLX11GLES2, since ANGLE
+      // is enabled by default.
+      case gl::kGLImplementationEGLGLES2:
+        DCHECK(window != gfx::kNullAcceleratedWidget);
+        return gl::InitializeGLSurface(new gl::NativeViewGLSurfaceEGLX11GLES2(
+            static_cast<x11::Window>(window)));
+      case gl::kGLImplementationEGLANGLE:
+      case gl::kGLImplementationSwiftShaderGL:
+        DCHECK(window != gfx::kNullAcceleratedWidget);
+        return gl::InitializeGLSurface(new gl::NativeViewGLSurfaceEGLX11(
+            static_cast<x11::Window>(window)));
+      default:
+        NOTREACHED();
+        return nullptr;
     }
   }
 
@@ -86,9 +82,6 @@
       const gl::GLImplementationParts& implementation) override {
     return LoadDefaultEGLGLES2Bindings(implementation);
   }
-
- private:
-  bool is_swiftshader_ = false;
 };
 
 }  // namespace
diff --git a/ui/resources/default_100_percent/common/pointers/copy_big.png b/ui/resources/default_100_percent/common/pointers/copy_big.png
index f39a430..cd246db 100644
--- a/ui/resources/default_100_percent/common/pointers/copy_big.png
+++ b/ui/resources/default_100_percent/common/pointers/copy_big.png
Binary files differ
diff --git a/weblayer/browser/content_browser_client_impl.cc b/weblayer/browser/content_browser_client_impl.cc
index 35f67e88..fbb5956 100644
--- a/weblayer/browser/content_browser_client_impl.cc
+++ b/weblayer/browser/content_browser_client_impl.cc
@@ -694,11 +694,11 @@
   // the only ones that should be hit for this code path.
   switch (disposition) {
     case WindowOpenDisposition::NEW_FOREGROUND_TAB:
-      FALLTHROUGH;
+      [[fallthrough]];
     case WindowOpenDisposition::NEW_BACKGROUND_TAB:
-      FALLTHROUGH;
+      [[fallthrough]];
     case WindowOpenDisposition::NEW_POPUP:
-      FALLTHROUGH;
+      [[fallthrough]];
     case WindowOpenDisposition::NEW_WINDOW:
       break;
     default: