diff --git a/DEPS b/DEPS
index c7f95a9e4..58218e3 100644
--- a/DEPS
+++ b/DEPS
@@ -301,11 +301,11 @@
   # 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': '744b5679da9970b6332684ef61778571a63656ae',
+  'v8_revision': '39f7e75c7737a84651f7d399427b6b6a75d3fff4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '4b4c90efb9027eaaa06319b1ca69d35a1d3c92d8',
+  'angle_revision': 'caf2b4279bfbdddddc758fc668cf6acd10b43c58',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -412,7 +412,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': 'a39e56c817db275b38d62d1fc23f208a6a440350',
+  'dawn_revision': 'ee25586aec81e62f22a594fc3ab2669ecfd92c2b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -862,7 +862,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/linux-amd64',
-          'version': 'UD_TOS2jnbZQRMi0jLFnYYZ0FiomOclnY1KK5YpgRUUC',
+          'version': '-hRyRHSvk0tM0uvhPoeDLXZB_wBgKBj5gK5v4fkDETsC',
         },
       ],
       'dep_type': 'cipd',
@@ -873,7 +873,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/mac-amd64',
-          'version': 'XSpW5Z8xdllSeyZiEjwy8GjsU5nNVx5rjFCoQbuTLvIC',
+          'version': 'FmrmUyT9Te-_XCc0AP-86q83Uekia6URZjHKSYzB9hAC',
         },
       ],
       'dep_type': 'cipd',
@@ -884,7 +884,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/windows-amd64',
-          'version': '2FbQDBm1u3MXdt0zr2nkbqQMZpykPKjIYYhh9TP1MpAC',
+          'version': 'zvFjssSCs4zBfn_laQCAzp-AYuLMFCL9_WfiSFptZBAC',
         },
       ],
       'dep_type': 'cipd',
@@ -1184,7 +1184,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '44b73307ee51f90f632088f6d08c56cd3cabf8df',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'e19b7624efd703aae3e29521cb902dd516df4ae2',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1729,10 +1729,10 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '44e4c8770158c505b03ee7feafa4859d083b0912',
 
   'src/third_party/webgpu-cts/src':
-    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'f102e6b2677d4819182154c6dd7390887ae9bb10',
+    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'd82d4e1630c29c03bd2420deac7e01386959a12a',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'e9d58df24da9a8f70c00ec1c6d2c7c308bd919b0',
+    Var('webrtc_git') + '/src.git' + '@' + 'b22f0c2238d0915426aa29c11499731fd9c2cc3b',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1805,7 +1805,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@854f7a88bbb36f811a8f837e24e2cb012f9f9137',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@697211251cf3bbf8643e118b9fdad0593c47626d',
     'condition': 'checkout_src_internal',
   },
 
@@ -1835,7 +1835,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 'CBlZRwb43ggeJgQ964ULe9QqxNwvCbdsWhCNw-OLIdsC',
+        'version': 'l34gGtctuj1o7RivmHrmtiMYXmbTfZPNshZkPrW-NhoC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/support_library/boundary_interfaces/BUILD.gn b/android_webview/support_library/boundary_interfaces/BUILD.gn
index 6ad2c3c..10f07cdb 100644
--- a/android_webview/support_library/boundary_interfaces/BUILD.gn
+++ b/android_webview/support_library/boundary_interfaces/BUILD.gn
@@ -10,6 +10,7 @@
     "src/org/chromium/support_lib_boundary/FeatureFlagHolderBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/IsomorphicObjectBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/JsReplyProxyBoundaryInterface.java",
+    "src/org/chromium/support_lib_boundary/ProcessGlobalConfigConstants.java",
     "src/org/chromium/support_lib_boundary/ProxyControllerBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/SafeBrowsingResponseBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/ScriptHandlerBoundaryInterface.java",
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/ProcessGlobalConfigConstants.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/ProcessGlobalConfigConstants.java
new file mode 100644
index 0000000..50e32b3a
--- /dev/null
+++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/ProcessGlobalConfigConstants.java
@@ -0,0 +1,36 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.support_lib_boundary;
+
+import androidx.annotation.RestrictTo;
+import androidx.annotation.StringDef;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Constants for ProcessGlobalConfig shared between chromium and AndroidX.
+ */
+public final class ProcessGlobalConfigConstants {
+    private ProcessGlobalConfigConstants() {}
+
+    /** @hide */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @StringDef(value =
+                       {
+                               DATA_DIRECTORY_SUFFIX,
+                       })
+    @Retention(RetentionPolicy.SOURCE)
+    @Target({ElementType.PARAMETER, ElementType.METHOD})
+    public @interface ProcessGlobalConfigMapKey {}
+
+    /**
+     * Key for the data directory suffix in the process global config map that is read in chromium
+     * via reflection into AndroidX class.
+     */
+    public static final String DATA_DIRECTORY_SUFFIX = "DATA_DIRECTORY_SUFFIX";
+}
\ No newline at end of file
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 5ced17f..d51a4e9 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -1722,7 +1722,7 @@
 // on ChromeOS.
 const base::Feature kDeviceActiveClientMonthlyCheckMembership{
     "DeviceActiveClientMonthlyCheckMembership",
-    base::FEATURE_DISABLED_BY_DEFAULT};
+    base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enables or disables forced reboots when DeviceScheduledReboot policy is set.
 const base::Feature kDeviceForceScheduledReboot{
diff --git a/ash/glanceables/glanceables_controller.cc b/ash/glanceables/glanceables_controller.cc
index 7deb0a1..ae60271 100644
--- a/ash/glanceables/glanceables_controller.cc
+++ b/ash/glanceables/glanceables_controller.cc
@@ -18,14 +18,25 @@
 
 namespace ash {
 
-GlanceablesController::GlanceablesController(
-    std::unique_ptr<GlanceablesDelegate> delegate)
-    : delegate_(std::move(delegate)) {
-  DCHECK(delegate_);
-}
+GlanceablesController::GlanceablesController() = default;
 
 GlanceablesController::~GlanceablesController() = default;
 
+void GlanceablesController::Init(
+    std::unique_ptr<GlanceablesDelegate> delegate) {
+  DCHECK(delegate);
+  delegate_ = std::move(delegate);
+}
+
+void GlanceablesController::ShowOnLogin() {
+  CreateUi();
+  FetchData();
+}
+
+bool GlanceablesController::IsShowing() const {
+  return !!widget_;
+}
+
 void GlanceablesController::CreateUi() {
   widget_ = std::make_unique<views::Widget>();
   views::Widget::InitParams params;
@@ -54,6 +65,10 @@
   view_ = nullptr;
 }
 
+void GlanceablesController::RestoreSession() {
+  delegate_->RestoreSession();
+}
+
 void GlanceablesController::FetchData() {
   // GlanceablesWeatherView observes the weather model for updates.
   Shell::Get()
@@ -62,8 +77,4 @@
       ->FetchWeather();
 }
 
-void GlanceablesController::RestoreSession() {
-  delegate_->RestoreSession();
-}
-
 }  // namespace ash
diff --git a/ash/glanceables/glanceables_controller.h b/ash/glanceables/glanceables_controller.h
index 030cada..a5ebb4d 100644
--- a/ash/glanceables/glanceables_controller.h
+++ b/ash/glanceables/glanceables_controller.h
@@ -21,27 +21,35 @@
 // Controls the "welcome back" glanceables screen shown on login.
 class ASH_EXPORT GlanceablesController {
  public:
-  explicit GlanceablesController(std::unique_ptr<GlanceablesDelegate> delegate);
+  GlanceablesController();
   GlanceablesController(const GlanceablesController&) = delete;
   GlanceablesController& operator=(const GlanceablesController&) = delete;
   ~GlanceablesController();
 
+  // Initializes the controller and sets the delegate.
+  void Init(std::unique_ptr<GlanceablesDelegate> delegate);
+
+  // Creates the UI and starts fetching data.
+  void ShowOnLogin();
+
+  // Returns true if the glanceables screen is showing.
+  bool IsShowing() const;
+
   // Creates the glanceables widget and view.
   void CreateUi();
 
   // Destroys the glanceables widget and view.
   void DestroyUi();
 
-  // Triggers a fetch of data from the server. This method is separate from
-  // CreateUi() so we can avoid triggering server fetches in tests.
-  void FetchData();
-
   // Triggers a session restore.
   void RestoreSession();
 
  private:
   friend class GlanceablesTest;
 
+  // Triggers a fetch of data from the server.
+  void FetchData();
+
   std::unique_ptr<GlanceablesDelegate> delegate_;
   std::unique_ptr<views::Widget> widget_;
   GlanceablesView* view_ = nullptr;
diff --git a/ash/glanceables/glanceables_unittests.cc b/ash/glanceables/glanceables_unittests.cc
index bede21ea..c015accf 100644
--- a/ash/glanceables/glanceables_unittests.cc
+++ b/ash/glanceables/glanceables_unittests.cc
@@ -31,19 +31,14 @@
 }  // namespace
 
 // Unified test suite for the glanceables controller, views, etc.
-//
-// Use a "no session" test so the glanceables widget is not automatically
-// created at the start of the test.
-// TODO(crbug.com/1353119): Once glanceables are shown by code in the
-// chrome/browser/ash layer, switch this to AshTestBase.
-class GlanceablesTest : public NoSessionAshTestBase {
+class GlanceablesTest : public AshTestBase {
  public:
   GlanceablesTest() = default;
   ~GlanceablesTest() override = default;
 
   // testing::Test:
   void SetUp() override {
-    NoSessionAshTestBase::SetUp();
+    AshTestBase::SetUp();
     controller_ = Shell::Get()->glanceables_controller();
     DCHECK(controller_);
   }
diff --git a/ash/keyboard/OWNERS b/ash/keyboard/OWNERS
index 3811005..e7cd741 100644
--- a/ash/keyboard/OWNERS
+++ b/ash/keyboard/OWNERS
@@ -1,4 +1,3 @@
 shend@chromium.org
 shuchen@chromium.org
-wuyingbing@chromium.org
 yhanada@chromium.org
diff --git a/ash/keyboard/ui/resources/OWNERS b/ash/keyboard/ui/resources/OWNERS
deleted file mode 100644
index d1ba0b0..0000000
--- a/ash/keyboard/ui/resources/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-bshe@chromium.org
-rsadam@chromium.org
diff --git a/ash/login/ui/access_code_input.cc b/ash/login/ui/access_code_input.cc
index f8ad780..3c24db1 100644
--- a/ash/login/ui/access_code_input.cc
+++ b/ash/login/ui/access_code_input.cc
@@ -305,8 +305,17 @@
 }
 
 void FixedLengthCodeInput::SetInputColor(SkColor color) {
+  const SkColor kErrorColor = AshColorProvider::Get()->GetContentLayerColor(
+      AshColorProvider::ContentLayerType::kTextColorAlert);
+
   for (auto* field : input_fields_) {
     field->SetTextColor(color);
+    // We don't update the underline color to red.
+    if (color != kErrorColor) {
+      field->SetBorder(views::CreateSolidSidedBorder(
+          gfx::Insets::TLBR(0, 0, kAccessCodeInputFieldUnderlineThicknessDp, 0),
+          color));
+    }
   }
 }
 
diff --git a/ash/login/ui/login_pin_input_view.cc b/ash/login/ui/login_pin_input_view.cc
index 477a9e6..f2549a2 100644
--- a/ash/login/ui/login_pin_input_view.cc
+++ b/ash/login/ui/login_pin_input_view.cc
@@ -52,6 +52,10 @@
   // views::view
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
 
+  void UpdatePalette(const LoginPalette& palette) {
+    SetInputColor(palette.pin_input_text_color);
+  }
+
  private:
   int length_ = 0;
   LoginPinInputView::OnPinSubmit on_submit_;
@@ -199,17 +203,9 @@
     return;
 
   length_ = pin_length;
-  UpdateView();
-}
 
-void LoginPinInputView::UpdatePalette(const LoginPalette& palette) {
-  palette_ = palette;
-  UpdateView();
-}
-
-void LoginPinInputView::UpdateView() {
-  const bool was_visible = GetVisible();
   const bool was_readonly = IsReadOnly();
+  const bool was_visible = GetVisible();
 
   // Hide the view before deleting.
   SetVisible(false);
@@ -222,11 +218,18 @@
                           base::Unretained(this)),
       base::BindRepeating(&LoginPinInputView::OnChanged,
                           base::Unretained(this))));
+
   SetReadOnly(was_readonly);
   Layout();
   SetVisible(was_visible);
 }
 
+void LoginPinInputView::UpdatePalette(const LoginPalette& palette) {
+  palette_ = palette;
+  DCHECK(code_input_);
+  code_input_->UpdatePalette(palette_);
+}
+
 void LoginPinInputView::SetAuthenticateWithEmptyPinOnReturnKey(bool enabled) {
   authenticate_with_empty_pin_on_return_key_ = enabled;
 }
@@ -243,7 +246,7 @@
 
 void LoginPinInputView::InsertDigit(int digit) {
   DCHECK(code_input_);
-  if (!is_read_only_)
+  if (!IsReadOnly())
     code_input_->InsertDigit(digit);
 }
 
@@ -273,7 +276,7 @@
   // It just performs an unlock attempt with an empty PIN, which triggers a
   // SmartLock attempt in LoginAuthUserView. The user's PIN is only submitted
   // when the last digit is inserted.
-  if (event.key_code() == ui::KeyboardCode::VKEY_RETURN && !is_read_only_ &&
+  if (event.key_code() == ui::KeyboardCode::VKEY_RETURN && !IsReadOnly() &&
       authenticate_with_empty_pin_on_return_key_) {
     SubmitPin(u"");
     return true;
diff --git a/ash/login/ui/login_pin_input_view.h b/ash/login/ui/login_pin_input_view.h
index 8521285b..edd92c39 100644
--- a/ash/login/ui/login_pin_input_view.h
+++ b/ash/login/ui/login_pin_input_view.h
@@ -69,10 +69,6 @@
   // Updates the palette use by the view.
   void UpdatePalette(const LoginPalette& palette);
 
-  // Updates the view. This can be called when either the length or the
-  // palette is updated.
-  void UpdateView();
-
   // When set, hitting return will attempt an unlock with an empty PIN.
   // LoginAuthUserView interprets such attempts as a SmartLock unlock.
   void SetAuthenticateWithEmptyPinOnReturnKey(bool enabled);
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index 4288eae..92034a8 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -14,6 +14,8 @@
     "accelerator_configuration.h",
     "accelerators.cc",
     "accelerators.h",
+    "accelerators_util.cc",
+    "accelerators_util.h",
     "accessibility_controller.cc",
     "accessibility_controller.h",
     "accessibility_controller_client.h",
@@ -395,10 +397,14 @@
     "//services/network/public/cpp:cpp",
     "//skia/public/mojom",
     "//ui/aura",
+    "//ui/base",
     "//ui/chromeos/strings",
     "//ui/compositor_extra",
     "//ui/display",
+    "//ui/events",
+    "//ui/events:dom_keycode_converter",
     "//ui/events/devices",
+    "//ui/events/ozone/layout",
     "//ui/message_center/public/cpp",
     "//ui/strings:ui_strings_grit",
     "//ui/views",
@@ -433,6 +439,7 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
+    "accelerators_util_unittest.cc",
     "ambient/ambient_metrics_unittest.cc",
     "android_intent_helper_unittest.cc",
     "app_list/app_list_config_provider_unittest.cc",
@@ -462,6 +469,10 @@
     "//ui/aura:test_support",
     "//ui/chromeos/styles:cros_styles_views",
     "//ui/compositor_extra",
+    "//ui/events",
+    "//ui/events:dom_keycode_converter",
+    "//ui/events/devices",
+    "//ui/events/ozone/layout",
     "//ui/gfx:test_support",
     "//ui/views",
     "//ui/views:test_support",
diff --git a/ash/public/cpp/accelerators_util.cc b/ash/public/cpp/accelerators_util.cc
new file mode 100644
index 0000000..d871769
--- /dev/null
+++ b/ash/public/cpp/accelerators_util.cc
@@ -0,0 +1,108 @@
+// Copyright 2022 The Chromium Authors.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/public/cpp/accelerators_util.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "ui/base/ui_base_features.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/keycodes/dom/dom_codes_array.h"
+#include "ui/events/keycodes/dom/dom_key.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
+#include "ui/events/keycodes/keyboard_codes_posix.h"
+#include "ui/events/ozone/layout/keyboard_layout_engine.h"
+#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
+
+namespace {
+
+// Dead keys work by combining two consecutive keystrokes together. The first
+// keystroke does not produce an output character, it acts as a one-shot
+// modifier for a subsequent keystroke. So for example on a German keyboard,
+// pressing the acute ´ dead key, then pressing the letter e will produce é.
+// The first character is called the combining character and does not produce
+// an output glyph. This table maps the combining character to a string
+// containing the non-combining equivalent that can be displayed.
+std::u16string GetStringForDeadKey(ui::DomKey dom_key) {
+  DCHECK(dom_key.IsDeadKey());
+  int32_t ch = dom_key.ToDeadKeyCombiningCharacter();
+  switch (ch) {
+    // Combining grave.
+    case 0x300:
+      return u"`";
+    // Combining acute.
+    case 0x301:
+      return u"´";
+    // Combining circumflex.
+    case 0x302:
+      return u"^";
+    // Combining tilde.
+    case 0x303:
+      return u"~";
+    // Combining diaeresis.
+    case 0x308:
+      return u"¨";
+    default:
+      break;
+  }
+
+  LOG(WARNING) << "No mapping for dead key: " << ch;
+  return base::UTF8ToUTF16(ui::KeycodeConverter::DomKeyToKeyString(dom_key));
+}
+
+}  // namespace
+
+namespace ash {
+
+std::u16string KeycodeToKeyString(ui::KeyboardCode key_code,
+                                  bool remap_positional_key) {
+  ui::DomKey dom_key;
+  ui::KeyboardCode key_code_to_compare = ui::VKEY_UNKNOWN;
+  const ui::KeyboardLayoutEngine* layout_engine =
+      ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine();
+
+  // The input |key_code| is the |KeyboardCode| aka VKEY of the shortcut in
+  // the US layout which is registered from the shortcut table. |key_code|
+  // is first mapped to the |DomCode| this key is on in the US layout. If
+  // the key is not positional, this processing is skipped and it is handled
+  // normally in the loop below. For the positional keys, the |DomCode| is
+  // then mapped to the |DomKey| in the current layout which represents the
+  // glyph/character that appears on the key (and usually when typed).
+  if (remap_positional_key &&
+      ::features::IsImprovedKeyboardShortcutsEnabled()) {
+    ui::DomCode dom_code =
+        ui::KeycodeConverter::MapUSPositionalShortcutKeyToDomCode(key_code);
+    if (dom_code != ui::DomCode::NONE) {
+      if (layout_engine->Lookup(dom_code, /*event_flags=*/ui::EF_NONE, &dom_key,
+                                &key_code_to_compare)) {
+        if (dom_key.IsDeadKey()) {
+          return GetStringForDeadKey(dom_key);
+        }
+        if (!dom_key.IsValid()) {
+          return std::u16string();
+        }
+        return base::UTF8ToUTF16(
+            ui::KeycodeConverter::DomKeyToKeyString(dom_key));
+      }
+      return std::u16string();
+    }
+  }
+
+  for (const auto& dom_code : ui::kDomCodesArray) {
+    if (!layout_engine->Lookup(dom_code, /*event_flags=*/ui::EF_NONE, &dom_key,
+                               &key_code_to_compare)) {
+      continue;
+    }
+    if (key_code_to_compare != key_code || !dom_key.IsValid() ||
+        dom_key.IsDeadKey()) {
+      continue;
+    }
+    return base::UTF8ToUTF16(ui::KeycodeConverter::DomKeyToKeyString(dom_key));
+  }
+  return std::u16string();
+}
+
+}  // namespace ash
diff --git a/ash/public/cpp/accelerators_util.h b/ash/public/cpp/accelerators_util.h
new file mode 100644
index 0000000..3ea6411
--- /dev/null
+++ b/ash/public/cpp/accelerators_util.h
@@ -0,0 +1,28 @@
+// Copyright 2022 The Chromium Authors.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_PUBLIC_CPP_ACCELERATORS_UTIL_H_
+#define ASH_PUBLIC_CPP_ACCELERATORS_UTIL_H_
+
+#include <string>
+
+#include "ash/public/cpp/ash_public_export.h"
+#include "ui/events/keycodes/keyboard_codes_posix.h"
+
+namespace ash {
+
+// Returns the string of a DomKey for a given KeyboardCode. A keyboard code
+// needs to be mapped to a physical key, DomCode, and then the DomCode needs
+// to be mapped to a meaning or character of a DomKey based on the
+// corresponding keyboard layout.
+// `remap_postional_key` is an optional param, by default will attempt to
+// convert any positional keys to the corresponding Domkey string.
+// This function does take into account of keyboard locale.
+ASH_PUBLIC_EXPORT std::u16string KeycodeToKeyString(
+    ui::KeyboardCode key_code,
+    bool remap_positional_key = true);
+
+}  // namespace ash
+
+#endif  // ASH_PUBLIC_CPP_ACCELERATORS_UTIL_H_
\ No newline at end of file
diff --git a/ash/public/cpp/accelerators_util_unittest.cc b/ash/public/cpp/accelerators_util_unittest.cc
new file mode 100644
index 0000000..ae95b43
--- /dev/null
+++ b/ash/public/cpp/accelerators_util_unittest.cc
@@ -0,0 +1,70 @@
+// Copyright 2022 The Chromium Authors.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/public/cpp/accelerators_util.h"
+
+#include <memory>
+#include <string>
+
+#include "base/strings/utf_string_conversions.h"
+#include "ui/events/keycodes/dom/dom_codes_array.h"
+#include "ui/events/keycodes/dom/dom_key.h"
+#include "ui/events/keycodes/keyboard_codes_posix.h"
+#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
+#include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ash {
+
+class AcceleratorsUtilTest : public testing::Test {
+ public:
+  AcceleratorsUtilTest() {
+    layout_engine_ = std::make_unique<ui::StubKeyboardLayoutEngine>();
+    ui::KeyboardLayoutEngineManager::ResetKeyboardLayoutEngine();
+    ui::KeyboardLayoutEngineManager::SetKeyboardLayoutEngine(
+        layout_engine_.get());
+  }
+
+  ~AcceleratorsUtilTest() override = default;
+
+ protected:
+  std::unique_ptr<ui::StubKeyboardLayoutEngine> layout_engine_;
+};
+
+TEST_F(AcceleratorsUtilTest, BasicDomCode) {
+  const std::u16string expected = u"a";
+  EXPECT_EQ(expected, KeycodeToKeyString(ui::KeyboardCode::VKEY_A));
+}
+
+TEST_F(AcceleratorsUtilTest, PositionalKeyCode) {
+  // Provide a custom layout that mimics behavior of a de-DE keyboard.
+  // In the German keyboard, VKEY_OEM_4 is located at DomCode position MINUS
+  // with DomKey `ß`. With positional remapping, VKEY_OEM_4 is remapped to
+  // search for DomCode BRACKET_LEFT, resulting in DomKey `ü`.
+  const std::vector<ui::StubKeyboardLayoutEngine::CustomLookupEntry> table = {
+      {ui::DomCode::MINUS, /**character=*/u'ß', /**character_shifted=*/u'?',
+       ui::KeyboardCode::VKEY_OEM_4},
+      {ui::DomCode::BRACKET_LEFT, /**character=*/u'ü',
+       /**character_shifted=*/u'Ü', ui::KeyboardCode::VKEY_OEM_1}};
+
+  layout_engine_->SetCustomLookupTableForTesting(table);
+
+  // Without positional remapping, expect `ß` to be the returned string.
+  const std::u16string expected = u"ß";
+  EXPECT_EQ(expected, KeycodeToKeyString(ui::KeyboardCode::VKEY_OEM_4,
+                                         /*remap_positional_key=*/false));
+
+  // With positional remmaping, expect `ü` to be the returned string.
+  const std::u16string expected2 = u"ü";
+  EXPECT_EQ(expected2, KeycodeToKeyString(ui::KeyboardCode::VKEY_OEM_4,
+                                          /*remap_positional_key=*/true));
+}
+
+TEST_F(AcceleratorsUtilTest, NonAlphanumericKey) {
+  const std::u16string expected = u"Meta";
+  EXPECT_EQ(expected, KeycodeToKeyString(ui::KeyboardCode::VKEY_COMMAND));
+}
+
+}  // namespace ash
diff --git a/ash/public/cpp/app_list/app_list_features.cc b/ash/public/cpp/app_list/app_list_features.cc
index 2628e16..e6cbcf3c 100644
--- a/ash/public/cpp/app_list/app_list_features.cc
+++ b/ash/public/cpp/app_list/app_list_features.cc
@@ -34,6 +34,8 @@
     "ForceShowContinueSection", base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kSearchResultInlineIcon{"SearchResultInlineIcon",
                                             base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kQuickActionShowBubbleLauncher{
+    "QuickActionShowBubbleLauncher", base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kDynamicSearchUpdateAnimation{
     "DynamicSearchUpdateAnimation", base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kCompactBubbleLauncher{"CompactBubbleLauncher",
@@ -93,6 +95,11 @@
          base::FeatureList::IsEnabled(kSearchResultInlineIcon);
 }
 
+bool IsQuickActionShowBubbleLauncherEnabled() {
+  return ash::features::IsProductivityLauncherEnabled() &&
+         base::FeatureList::IsEnabled(kQuickActionShowBubbleLauncher);
+}
+
 bool IsDynamicSearchUpdateAnimationEnabled() {
   // Search update animations are only supported for categorical search.
   return IsCategoricalSearchEnabled() &&
diff --git a/ash/public/cpp/app_list/app_list_features.h b/ash/public/cpp/app_list/app_list_features.h
index 3fb06b0d..2dd75b2 100644
--- a/ash/public/cpp/app_list/app_list_features.h
+++ b/ash/public/cpp/app_list/app_list_features.h
@@ -57,6 +57,10 @@
 // Enables iconified text and inline icons in launcher search.
 ASH_PUBLIC_EXPORT extern const base::Feature kSearchResultInlineIcon;
 
+// Enables a fling gesture or mouse scroll from the shelf to show the bubble
+// launcher.
+ASH_PUBLIC_EXPORT extern const base::Feature kQuickActionShowBubbleLauncher;
+
 // Enable shortened search result update animations when in progress animations
 // are interrupted by search model updates.
 ASH_PUBLIC_EXPORT extern const base::Feature kDynamicSearchUpdateAnimation;
@@ -81,6 +85,7 @@
 ASH_PUBLIC_EXPORT bool IsLauncherSearchNormalizationEnabled();
 ASH_PUBLIC_EXPORT bool IsCategoricalSearchEnabled();
 ASH_PUBLIC_EXPORT bool IsSearchResultInlineIconEnabled();
+ASH_PUBLIC_EXPORT bool IsQuickActionShowBubbleLauncherEnabled();
 ASH_PUBLIC_EXPORT bool IsDynamicSearchUpdateAnimationEnabled();
 ASH_PUBLIC_EXPORT base::TimeDelta DynamicSearchUpdateAnimationDuration();
 ASH_PUBLIC_EXPORT bool IsCompactBubbleLauncherEnabled();
diff --git a/ash/shelf/shelf.cc b/ash/shelf/shelf.cc
index 7b038ab3..adb254e 100644
--- a/ash/shelf/shelf.cc
+++ b/ash/shelf/shelf.cc
@@ -604,10 +604,12 @@
   if (!shelf_layout_manager_->is_active_session_state())
     return;
 
-  // Productivity launcher does not show or hide on scroll events. The legacy
-  // peeking launcher had this behavior, but it doesn't make sense for a bubble.
-  if (features::IsProductivityLauncherEnabled())
+  // Productivity launcher does not show or hide on scroll events by default.
+  // Introduce the swipe up gesture behind a flag over certain conditions.
+  if (features::IsProductivityLauncherEnabled() &&
+      !shelf_layout_manager_->IsBubbleLauncherShowOnGestureScrollAvailable()) {
     return;
+  }
 
   auto* app_list_controller = Shell::Get()->app_list_controller();
   DCHECK(app_list_controller);
@@ -627,10 +629,12 @@
       !IsHorizontalAlignment())
     return;
 
-  // Productivity launcher does not show or hide on wheel events. The legacy
-  // peeking launcher had this behavior, but it doesn't make sense for a bubble.
-  if (features::IsProductivityLauncherEnabled())
+  // Productivity launcher does not show or hide on scroll events by default.
+  // Introduce the swipe up gesture behind a flag over certain conditions.
+  if (features::IsProductivityLauncherEnabled() &&
+      !shelf_layout_manager_->IsBubbleLauncherShowOnGestureScrollAvailable()) {
     return;
+  }
 
   auto* app_list_controller = Shell::Get()->app_list_controller();
   DCHECK(app_list_controller);
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc
index c8a2c75..8e164491 100644
--- a/ash/shelf/shelf_layout_manager.cc
+++ b/ash/shelf/shelf_layout_manager.cc
@@ -18,6 +18,7 @@
 #include "ash/controls/contextual_tooltip.h"
 #include "ash/display/screen_orientation_controller.h"
 #include "ash/drag_drop/scoped_drag_drop_observer.h"
+#include "ash/public/cpp/app_list/app_list_features.h"
 #include "ash/public/cpp/app_list/app_list_types.h"
 #include "ash/public/cpp/shelf_config.h"
 #include "ash/public/cpp/shelf_types.h"
@@ -126,6 +127,9 @@
     "afihfgfghkmdmggakhkgnfhlikhdpima",  // Infinite Painter
 };
 
+// Minimum velocity required for the shelf to process a gesture fling event.
+constexpr int kShelfFlingVelocityThresehold = 100;
+
 // Returns the `aura::client::DragDropClient` for the given `shelf_widget`. Note
 // that this may return `nullptr` if the browser is performing its shutdown
 // sequence.
@@ -805,7 +809,8 @@
 
   if (drag_status_ != kDragInProgress &&
       drag_status_ != kDragAppListInProgress &&
-      drag_status_ != kDragHomeToOverviewInProgress) {
+      drag_status_ != kDragHomeToOverviewInProgress &&
+      drag_status_ != kFlingBubbleLauncherInProgress) {
     return false;
   }
 
@@ -814,6 +819,11 @@
     return true;
   }
 
+  if (event_in_screen.type() == ui::ET_SCROLL_FLING_START) {
+    if (MaybeHandleShelfFling(event_in_screen))
+      return true;
+  }
+
   if (event_in_screen.type() == ui::ET_GESTURE_SCROLL_END ||
       event_in_screen.type() == ui::ET_SCROLL_FLING_START) {
     if (event_in_screen.type() == ui::ET_SCROLL_FLING_START) {
@@ -824,6 +834,8 @@
       CompleteAppListDrag(event_in_screen);
     } else if (drag_status_ == kDragHomeToOverviewInProgress) {
       CompleteDragHomeToOverview(event_in_screen);
+    } else if (drag_status_ == kFlingBubbleLauncherInProgress) {
+      CompleteShelfFling(event_in_screen);
     } else {
       CompleteDrag(event_in_screen);
     }
@@ -868,39 +880,107 @@
 }
 
 void ShelfLayoutManager::ProcessScrollOffset(int offset,
-                                             base::TimeTicks time_stamp) {
-  DCHECK(!features::IsProductivityLauncherEnabled());
-
+                                             const ui::LocatedEvent& event) {
   if (offset <= ShelfConfig::Get()->mousewheel_scroll_offset_threshold())
     return;
 
+  if (app_list_features::IsQuickActionShowBubbleLauncherEnabled() &&
+      !IsLocationInBubbleLauncherShowBounds(event.root_location())) {
+    return;
+  }
+
   Shell::Get()->app_list_controller()->ToggleAppList(
       display::Screen::GetScreen()
           ->GetDisplayNearestWindow(shelf_widget_->GetNativeWindow())
           .id(),
-      kScrollFromShelf, time_stamp);
+      kScrollFromShelf, event.time_stamp());
 }
 
 void ShelfLayoutManager::ProcessScrollEventFromShelf(ui::ScrollEvent* event) {
-  DCHECK(!features::IsProductivityLauncherEnabled());
   if (shelf_->IsHorizontalAlignment()) {
     ProcessScrollOffset(GetOffset(event->y_offset(), prefs::kNaturalScroll),
-                        event->time_stamp());
+                        *event);
   } else {
     int offset = shelf_->alignment() == ShelfAlignment::kLeft
                      ? -event->x_offset()
                      : event->x_offset();
     offset = GetOffset(offset, prefs::kNaturalScroll),
-    ProcessScrollOffset(offset, event->time_stamp());
+    ProcessScrollOffset(offset, *event);
   }
 }
 
+bool ShelfLayoutManager::IsBubbleLauncherShowOnGestureScrollAvailable() {
+  if (!app_list_features::IsQuickActionShowBubbleLauncherEnabled())
+    return false;
+
+  if (!state_.IsShelfVisible())
+    return false;
+
+  if (Shell::Get()->IsInTabletMode())
+    return false;
+
+  return Shell::Get()->app_list_controller() &&
+         !Shell::Get()->app_list_controller()->IsVisible(display_.id());
+}
+
+bool ShelfLayoutManager::MaybeHandleShelfFling(
+    const ui::GestureEvent& event_in_screen) {
+  if (!IsBubbleLauncherShowOnGestureScrollAvailable())
+    return false;
+  int velocity = shelf_->SelectValueForShelfAlignment(
+      event_in_screen.AsGestureEvent()->details().velocity_y(),
+      -event_in_screen.AsGestureEvent()->details().velocity_x(),
+      event_in_screen.AsGestureEvent()->details().velocity_x());
+
+  if (velocity > -kShelfFlingVelocityThresehold)
+    return false;
+
+  if (!IsLocationInBubbleLauncherShowBounds(drag_start_point_in_screen_))
+    return false;
+
+  Shell::Get()->app_list_controller()->ToggleAppList(
+      display::Screen::GetScreen()
+          ->GetDisplayNearestWindow(shelf_widget_->GetNativeWindow())
+          .id(),
+      kSwipeFromShelf, event_in_screen.time_stamp());
+
+  return true;
+}
+
+bool ShelfLayoutManager::IsLocationInBubbleLauncherShowBounds(
+    const gfx::Point& location_in_screen) {
+  gfx::Rect app_list_swipe_bounds =
+      shelf_->shelf_widget()->GetWindowBoundsInScreen();
+
+  // We want to be able to recognize the swipe/fling action only on part of the
+  // shelf that is closer to the launcher button.
+  if (shelf_->IsHorizontalAlignment()) {
+    const int app_list_swipe_width = app_list_swipe_bounds.width() / 4;
+    // On the horizontal shelf, the poision of the launcher button may vary if
+    // the UI direction is RTL.
+    gfx::Insets insets;
+    const int non_actionable_insets =
+        app_list_swipe_bounds.width() - app_list_swipe_width;
+    if (base::i18n::IsRTL())
+      insets.set_left(non_actionable_insets);
+    else
+      insets.set_right(non_actionable_insets);
+
+    app_list_swipe_bounds.Inset(insets);
+  } else {
+    // On the vertical shelf, the launcher button is always on top regardless of
+    // locale.
+    app_list_swipe_bounds.set_height(app_list_swipe_bounds.height() / 4);
+  }
+
+  return app_list_swipe_bounds.Contains(location_in_screen);
+}
+
 void ShelfLayoutManager::ProcessMouseWheelEventFromShelf(
     ui::MouseWheelEvent* event) {
-  DCHECK(!features::IsProductivityLauncherEnabled());
   const int y_offset =
       GetOffset(event->offset().y(), prefs::kMouseReverseScroll);
-  ProcessScrollOffset(y_offset, event->time_stamp());
+  ProcessScrollOffset(y_offset, *event);
 }
 
 ShelfBackgroundType ShelfLayoutManager::GetShelfBackgroundType() const {
@@ -2084,7 +2164,8 @@
   }
 
   if (drag_status_ == kDragCompleteInProgress ||
-      drag_status_ == kDragCancelInProgress) {
+      drag_status_ == kDragCancelInProgress ||
+      drag_status_ == kFlingBubbleLauncherInProgress) {
     return drag_auto_hide_state_;
   }
 
@@ -2351,10 +2432,18 @@
   if (Shell::Get()->app_list_controller()->IsVisible(display_.id()))
     return true;
 
-  return StartShelfDrag(
-      gesture_in_screen,
-      gfx::Vector2dF(gesture_in_screen.details().scroll_x_hint(),
-                     scroll_y_hint));
+  if (StartShelfDrag(gesture_in_screen,
+                     gfx::Vector2dF(gesture_in_screen.details().scroll_x_hint(),
+                                    scroll_y_hint))) {
+    return true;
+  }
+
+  if (IsBubbleLauncherShowOnGestureScrollAvailable()) {
+    drag_status_ = kFlingBubbleLauncherInProgress;
+    return true;
+  }
+
+  return false;
 }
 
 void ShelfLayoutManager::UpdateGestureDrag(
@@ -2370,6 +2459,12 @@
     return;
   }
 
+  if (drag_status_ == kFlingBubbleLauncherInProgress) {
+    if (drag_start_point_in_screen_ == gfx::Point())
+      drag_start_point_in_screen_ = gesture_in_screen.location();
+    return;
+  }
+
   UpdateDrag(gesture_in_screen, scroll_x, scroll_y);
 }
 
@@ -2699,6 +2794,13 @@
   drag_status_ = kDragNone;
 }
 
+void ShelfLayoutManager::CompleteShelfFling(
+    const ui::LocatedEvent& event_in_screen) {
+  drag_status_ = kDragNone;
+  drag_start_point_in_screen_ = gfx::Point();
+  last_drag_velocity_ = 0;
+}
+
 void ShelfLayoutManager::CompleteDragHomeToOverview(
     const ui::LocatedEvent& event_in_screen) {
   absl::optional<float> velocity_y;
@@ -2754,6 +2856,7 @@
 
     hotseat_presentation_time_recorder_.reset();
   }
+
   hotseat_is_in_drag_ = false;
   drag_status_ = kDragNone;
   drag_start_point_in_screen_ = gfx::Point();
diff --git a/ash/shelf/shelf_layout_manager.h b/ash/shelf/shelf_layout_manager.h
index 5344c62..46adc23 100644
--- a/ash/shelf/shelf_layout_manager.h
+++ b/ash/shelf/shelf_layout_manager.h
@@ -93,6 +93,7 @@
     kDragCompleteInProgress,
     kDragAppListInProgress,
     kDragHomeToOverviewInProgress,
+    kFlingBubbleLauncherInProgress,
   };
 
   // Suspend work area updates within its scope. Note that relevant
@@ -201,8 +202,25 @@
   // Handles scroll events from the shelf.
   void ProcessScrollEventFromShelf(ui::ScrollEvent* event);
 
+  // Returns whether the current state of the shelf allows a gesture fling or
+  // scroll to show the bubble launcher.
+  bool IsBubbleLauncherShowOnGestureScrollAvailable();
+
+  // Handles a fling event over the shelf. Returns whether the event was handled
+  // by the manager or false if it was ignored.
+  bool MaybeHandleShelfFling(const ui::GestureEvent& event_in_screen);
+
+  // Cleans up after a fling event was successfully completed on the shelf.
+  void CompleteShelfFling(const ui::LocatedEvent& event_in_screen);
+
+  // Returns true if the location is within the bounds of the area designated to
+  // receive the gesture fling or scroll over the shelf to show the bubble
+  // launcher.
+  bool IsLocationInBubbleLauncherShowBounds(
+      const gfx::Point& location_in_screen);
+
   // Contains logic that is the same between mouse wheel and gesture scrolling.
-  void ProcessScrollOffset(int offset, base::TimeTicks time_stamp);
+  void ProcessScrollOffset(int offset, const ui::LocatedEvent& event);
 
   // Returns how the shelf background should be painted.
   ShelfBackgroundType GetShelfBackgroundType() const;
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc
index 8388a72..8f04698 100644
--- a/ash/shelf/shelf_layout_manager_unittest.cc
+++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -22,6 +22,7 @@
 #include "ash/keyboard/ui/keyboard_ui.h"
 #include "ash/keyboard/ui/keyboard_ui_controller.h"
 #include "ash/keyboard/ui/keyboard_util.h"
+#include "ash/public/cpp/app_list/app_list_features.h"
 #include "ash/public/cpp/ash_prefs.h"
 #include "ash/public/cpp/keyboard/keyboard_controller.h"
 #include "ash/public/cpp/keyboard/keyboard_controller_observer.h"
@@ -4571,8 +4572,9 @@
       DoMouseWheelScrollAtLocation(start, scroll_offset_threshold + 1,
                                    test.reverse_scroll);
     } else {
-      DoTwoFingerVerticalScrollAtLocation(start, scroll_offset_threshold + 10,
-                                          test.reverse_scroll);
+      DoTwoFingerScrollAtLocation(start, /*x_offset=*/0,
+                                  scroll_offset_threshold + 10,
+                                  test.reverse_scroll);
     }
 
     GetAppListTestHelper()->WaitUntilIdle();
@@ -4594,8 +4596,9 @@
       // A ScrollEvent gets amplified when transformed into a mousewheel event.
       // We need to set a lower offset so when it gets amplified, it still is
       // under the threshold.
-      DoTwoFingerVerticalScrollAtLocation(start, scroll_offset_threshold - 10,
-                                          test.reverse_scroll);
+      DoTwoFingerScrollAtLocation(start, /*x_offset=*/0,
+                                  scroll_offset_threshold - 10,
+                                  test.reverse_scroll);
     }
 
     GetAppListTestHelper()->WaitUntilIdle();
@@ -4607,6 +4610,128 @@
   }
 }
 
+class QuickActionShowBubbleTest : public ShelfLayoutManagerTestBase,
+                                  public testing::WithParamInterface<bool> {
+ public:
+  QuickActionShowBubbleTest() : scoped_locale_(GetParam() ? "ar" : "") {}
+  ~QuickActionShowBubbleTest() override = default;
+  // ShelfLayoutManagerTestBase:
+  void SetUp() override {
+    ShelfLayoutManagerTestBase::SetUp();
+    scoped_features_.InitWithFeatures(
+        /*enabled_features=*/{features::kProductivityLauncher,
+                              app_list_features::
+                                  kQuickActionShowBubbleLauncher},
+        /*disabled_features=*/{});
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_features_;
+  base::test::ScopedRestoreICUDefaultLocale scoped_locale_;
+};
+
+// Used to test RTL UI orientation.
+INSTANTIATE_TEST_SUITE_P(All, QuickActionShowBubbleTest, testing::Bool());
+
+// Tests that the two finger gesture and the swipe gesture when the mouse is
+// over the shelf near the edge shows the bubble launcher.
+TEST_P(QuickActionShowBubbleTest,
+       ScrollFromShelfToShowAppListWithProductivityLauncher) {
+  const struct {
+    ShelfAlignment alignment;
+    bool swipe_gesture;
+  } test_table[]{
+      {ShelfAlignment::kBottom, false},
+      {ShelfAlignment::kBottom, true},
+      {ShelfAlignment::kBottomLocked, false},
+      {ShelfAlignment::kBottomLocked, true},
+      {ShelfAlignment::kLeft, false},
+      {ShelfAlignment::kLeft, true},
+      {ShelfAlignment::kRight, false},
+      {ShelfAlignment::kRight, true},
+  };
+  base::HistogramTester histogram_tester;
+  const int scroll_offset_threshold =
+      ShelfConfig::Get()->mousewheel_scroll_offset_threshold() + 10;
+  int bucket_scroll_count = 0;
+  int bucket_swipe_count = 0;
+
+  for (auto test : test_table) {
+    GetShelfLayoutManager()->LayoutShelf();
+    GetPrimaryShelf()->SetAlignment(test.alignment);
+    ASSERT_EQ(test.alignment, GetPrimaryShelf()->alignment());
+
+    // Direction of the swipe gesture depends on the shelf alignment and on the
+    // event being a swipe or a fling.
+    gfx::Vector2d offset;
+    switch (test.alignment) {
+      case ShelfAlignment::kBottom:
+      case ShelfAlignment::kBottomLocked:
+        offset.set_y(scroll_offset_threshold);
+        break;
+      case ShelfAlignment::kLeft:
+        offset.set_x(-scroll_offset_threshold);
+        break;
+      case ShelfAlignment::kRight:
+        offset.set_x(scroll_offset_threshold);
+        break;
+    }
+
+    // Action performed from the navigation_widget should show the bubble
+    // launcher.
+    const gfx::Point navigation_widget_center = GetPrimaryShelf()
+                                                    ->navigation_widget()
+                                                    ->GetContentsView()
+                                                    ->GetBoundsInScreen()
+                                                    .CenterPoint();
+    if (test.swipe_gesture) {
+      FlingBetweenLocations(navigation_widget_center,
+                            navigation_widget_center - offset);
+      ++bucket_swipe_count;
+    } else {
+      DoTwoFingerScrollAtLocation(navigation_widget_center, offset.x(),
+                                  offset.y(), false);
+      ++bucket_scroll_count;
+    }
+
+    GetAppListTestHelper()->WaitUntilIdle();
+    GetAppListTestHelper()->CheckVisibility(true);
+    histogram_tester.ExpectBucketCount("Apps.AppListBubbleShowSource",
+                                       AppListShowSource::kSwipeFromShelf,
+                                       bucket_swipe_count);
+    histogram_tester.ExpectBucketCount("Apps.AppListBubbleShowSource",
+                                       AppListShowSource::kScrollFromShelf,
+                                       bucket_scroll_count);
+
+    GetAppListTestHelper()->DismissAndRunLoop();
+    GetAppListTestHelper()->CheckVisibility(false);
+
+    // Action performed from the status area should not show the bubble
+    // launcher.
+    const gfx::Point status_area_widget_center = GetShelfWidget()
+                                                     ->status_area_widget()
+                                                     ->GetContentsView()
+                                                     ->GetBoundsInScreen()
+                                                     .CenterPoint();
+    if (test.swipe_gesture) {
+      FlingBetweenLocations(status_area_widget_center,
+                            status_area_widget_center - offset);
+    } else {
+      DoTwoFingerScrollAtLocation(status_area_widget_center, offset.x(),
+                                  offset.y(), false);
+    }
+
+    GetAppListTestHelper()->WaitUntilIdle();
+    GetAppListTestHelper()->CheckVisibility(false);
+    histogram_tester.ExpectBucketCount("Apps.AppListBubbleShowSource",
+                                       AppListShowSource::kSwipeFromShelf,
+                                       bucket_swipe_count);
+    histogram_tester.ExpectBucketCount("Apps.AppListBubbleShowSource",
+                                       AppListShowSource::kScrollFromShelf,
+                                       bucket_scroll_count);
+  }
+}
+
 // Tests that the shelf background is opaque in both screens after app list is
 // dismissed in a secondary display. (See https://crbug.com/1060686)
 TEST_F(ShelfLayoutManagerTest, ShelfBackgroundOpaqueAfetrAppListUpdate) {
diff --git a/ash/shelf/test/shelf_layout_manager_test_base.cc b/ash/shelf/test/shelf_layout_manager_test_base.cc
index 5269ce0..54a80223 100644
--- a/ash/shelf/test/shelf_layout_manager_test_base.cc
+++ b/ash/shelf/test/shelf_layout_manager_test_base.cc
@@ -316,10 +316,16 @@
 }
 
 void ShelfLayoutManagerTestBase::FlingUpOnShelf() {
-  gfx::Rect display_bounds =
-      display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
-  const gfx::Point start(display_bounds.bottom_center());
-  const gfx::Point end(start.x(), 10);
+  const gfx::Point location_start(display::Screen::GetScreen()
+                                      ->GetPrimaryDisplay()
+                                      .bounds()
+                                      .bottom_center());
+  const gfx::Point location_end(location_start.x(), 10);
+  FlingBetweenLocations(location_start, location_end);
+}
+
+void ShelfLayoutManagerTestBase::FlingBetweenLocations(gfx::Point start,
+                                                       gfx::Point end) {
   const base::TimeDelta kTimeDelta = base::Milliseconds(10);
   const int kNumScrollSteps = 4;
   GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
@@ -359,17 +365,18 @@
   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, GetPrimaryShelf()->GetAutoHideState());
 }
 
-// Move mouse to |location| and do a two-finger vertical scroll.
-void ShelfLayoutManagerTestBase::DoTwoFingerVerticalScrollAtLocation(
+// Move mouse to |location| and do a two-finger scroll.
+void ShelfLayoutManagerTestBase::DoTwoFingerScrollAtLocation(
     gfx::Point location,
+    int x_offset,
     int y_offset,
     bool reverse_scroll) {
   PrefService* prefs =
       Shell::Get()->session_controller()->GetLastActiveUserPrefService();
   prefs->SetBoolean(prefs::kNaturalScroll, reverse_scroll);
   y_offset = reverse_scroll ? -y_offset : y_offset;
-  GetEventGenerator()->ScrollSequence(location, base::TimeDelta(),
-                                      /*x_offset=*/0, y_offset, /*steps=*/1,
+  GetEventGenerator()->ScrollSequence(location, base::TimeDelta(), x_offset,
+                                      y_offset, /*steps=*/1,
                                       /*num_fingers=*/2);
 }
 
diff --git a/ash/shelf/test/shelf_layout_manager_test_base.h b/ash/shelf/test/shelf_layout_manager_test_base.h
index 6e62916..b75b7ca2 100644
--- a/ash/shelf/test/shelf_layout_manager_test_base.h
+++ b/ash/shelf/test/shelf_layout_manager_test_base.h
@@ -71,16 +71,20 @@
   // Move mouse to show Shelf in auto-hide mode.
   void MouseMouseToShowAutoHiddenShelf();
 
-  // Move mouse to |location| and do a two-finger vertical scroll.
-  void DoTwoFingerVerticalScrollAtLocation(gfx::Point location,
-                                           int y_offset,
-                                           bool reverse_scroll);
+  // Move mouse to |location| and do a two-finger scroll.
+  void DoTwoFingerScrollAtLocation(gfx::Point location,
+                                   int x_offset,
+                                   int y_offset,
+                                   bool reverse_scroll);
 
   // Move mouse to |location| and do a mousewheel scroll.
   void DoMouseWheelScrollAtLocation(gfx::Point location,
                                     int delta_y,
                                     bool reverse_scroll);
 
+  // Do a fling gesture event from |start| to |end|.
+  void FlingBetweenLocations(gfx::Point start, gfx::Point end);
+
   // Run the |visibility_update_for_tray_callback_| if set in
   // ShelfLayoutManager and return true. Otherwise, return false.
   bool RunVisibilityUpdateForTrayCallback();
diff --git a/ash/shell.cc b/ash/shell.cc
index 0ad3b12..3276dc64 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -594,8 +594,9 @@
   AccelerometerReader::GetInstance()->Initialize();
 
   if (features::AreGlanceablesEnabled()) {
-    glanceables_controller_ = std::make_unique<GlanceablesController>(
-        shell_delegate_->CreateGlanceablesDelegate());
+    glanceables_controller_ = std::make_unique<GlanceablesController>();
+    glanceables_controller_->Init(shell_delegate_->CreateGlanceablesDelegate(
+        glanceables_controller_.get()));
   }
 
   login_screen_controller_ =
@@ -1620,13 +1621,6 @@
   // the session starts.
   app_list_feature_usage_metrics_ =
       std::make_unique<AppListFeatureUsageMetrics>();
-
-  if (features::AreGlanceablesEnabled()) {
-    // Show glanceables after signin.
-    // TODO(crbug.com/1353119): Show only when session restore would trigger.
-    glanceables_controller_->CreateUi();
-    glanceables_controller_->FetchData();
-  }
 }
 
 void Shell::OnSessionStateChanged(session_manager::SessionState state) {
diff --git a/ash/shell_delegate.h b/ash/shell_delegate.h
index 86db1a01..e6980d4 100644
--- a/ash/shell_delegate.h
+++ b/ash/shell_delegate.h
@@ -37,6 +37,7 @@
 class BackGestureContextualNudgeDelegate;
 class CaptureModeDelegate;
 class DesksTemplatesDelegate;
+class GlanceablesController;
 class GlanceablesDelegate;
 class NearbyShareController;
 class NearbyShareDelegate;
@@ -56,8 +57,8 @@
       const = 0;
 
   // Creates the delegate for the Glanceables feature.
-  virtual std::unique_ptr<GlanceablesDelegate> CreateGlanceablesDelegate()
-      const = 0;
+  virtual std::unique_ptr<GlanceablesDelegate> CreateGlanceablesDelegate(
+      GlanceablesController* controller) const = 0;
 
   // Creates a accessibility delegate. Shell takes ownership of the delegate.
   virtual AccessibilityDelegate* CreateAccessibilityDelegate() = 0;
diff --git a/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc b/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
index 34fdf45..8fb7026 100644
--- a/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
+++ b/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
@@ -5,6 +5,7 @@
 #include "ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.h"
 
 #include "ash/constants/ash_features.h"
+#include "ash/public/cpp/accelerators_util.h"
 #include "ash/public/cpp/keyboard_shortcut_item.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/shortcut_viewer/strings/grit/shortcut_viewer_strings.h"
@@ -104,40 +105,6 @@
   return l10n_util::GetStringUTF16(msg_id);
 }
 
-// Dead keys work by combining two consecutive keystrokes together. The first
-// keystroke does not produce an output character, it acts as a one-shot
-// modifier for a subsequent keystroke. So for example on a German keyboard,
-// pressing the acute ´ dead key, then pressing the letter e will produce é.
-// The first character is called the combining character and does not produce
-// an output glyph. This table maps the combining character to a string
-// containing the non-combining equivalent that can be displayed.
-std::u16string GetStringForDeadKey(ui::DomKey dom_key) {
-  DCHECK(dom_key.IsDeadKey());
-  int32_t ch = dom_key.ToDeadKeyCombiningCharacter();
-  switch (ch) {
-    // Combining grave.
-    case 0x300:
-      return u"`";
-    // Combining acute.
-    case 0x301:
-      return u"´";
-    // Combining circumflex.
-    case 0x302:
-      return u"^";
-    // Combining tilde.
-    case 0x303:
-      return u"~";
-    // Combining diaeresis.
-    case 0x308:
-      return u"¨";
-    default:
-      break;
-  }
-
-  LOG(WARNING) << "No mapping for dead key shortcut " << ch;
-  return base::UTF8ToUTF16(ui::KeycodeConverter::DomKeyToKeyString(dom_key));
-}
-
 }  // namespace
 
 std::u16string GetStringForCategory(ShortcutCategory category) {
@@ -175,50 +142,7 @@
   if (key_label)
     return key_label.value();
 
-  ui::DomKey dom_key;
-  ui::KeyboardCode key_code_to_compare = ui::VKEY_UNKNOWN;
-  const ui::KeyboardLayoutEngine* layout_engine =
-      ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine();
-
-  // The input |key_code| is the |KeyboardCode| aka VKEY of the shortcut in
-  // the US layout which is registered from the shortcut table. |key_code|
-  // is first mapped to the |DomCode| this key is on in the US layout. If
-  // the key is not positional, this processing is skipped and it is handled
-  // normally in the loop below. For the positional keys, the |DomCode| is
-  // then mapped to the |DomKey| in the current layout which represents the
-  // glyph/character that appears on the key (and usually when typed).
-  if (remap_positional_key &&
-      ::features::IsImprovedKeyboardShortcutsEnabled()) {
-    ui::DomCode dom_code =
-        ui::KeycodeConverter::MapUSPositionalShortcutKeyToDomCode(key_code);
-    if (dom_code != ui::DomCode::NONE) {
-      if (layout_engine->Lookup(dom_code, /*flags=*/ui::EF_NONE, &dom_key,
-                                &key_code_to_compare)) {
-        if (dom_key.IsDeadKey()) {
-          return GetStringForDeadKey(dom_key);
-        }
-        if (!dom_key.IsValid()) {
-          return std::u16string();
-        }
-        return base::UTF8ToUTF16(
-            ui::KeycodeConverter::DomKeyToKeyString(dom_key));
-      }
-      return std::u16string();
-    }
-  }
-
-  for (const auto& dom_code : ui::kDomCodesArray) {
-    if (!layout_engine->Lookup(dom_code, /*flags=*/ui::EF_NONE, &dom_key,
-                               &key_code_to_compare)) {
-      continue;
-    }
-    if (key_code_to_compare != key_code || !dom_key.IsValid() ||
-        dom_key.IsDeadKey()) {
-      continue;
-    }
-    return base::UTF8ToUTF16(ui::KeycodeConverter::DomKeyToKeyString(dom_key));
-  }
-  return std::u16string();
+  return ash::KeycodeToKeyString(key_code, remap_positional_key);
 }
 
 std::u16string GetAccessibleNameForKeyboardCode(ui::KeyboardCode key_code) {
diff --git a/ash/system/network/network_section_header_view.cc b/ash/system/network/network_section_header_view.cc
index 70a211e..962426e 100644
--- a/ash/system/network/network_section_header_view.cc
+++ b/ash/system/network/network_section_header_view.cc
@@ -55,7 +55,7 @@
          chromeos::network_config::mojom::InhibitReason::kNotInhibited;
 }
 
-bool IsCellularSimLocked() {
+bool IsCellularInhibited() {
   const DeviceStateProperties* cellular_device =
       Shell::Get()->system_tray_model()->network_state_model()->GetDevice(
           NetworkType::kCellular);
@@ -318,7 +318,7 @@
   // (Tether may be enabled by turning on Bluetooth and turning on
   // 'Get data connection' in the Settings > Mobile data subpage).
   if (cellular_state != DeviceStateType::kUnavailable) {
-    if (is_on && IsCellularSimLocked()) {
+    if (is_on && IsCellularInhibited()) {
       ShowCellularSettings();
       return;
     }
diff --git a/ash/system/privacy/privacy_indicators_tray_item_view.cc b/ash/system/privacy/privacy_indicators_tray_item_view.cc
index a88721a5..b2e6ed45 100644
--- a/ash/system/privacy/privacy_indicators_tray_item_view.cc
+++ b/ash/system/privacy/privacy_indicators_tray_item_view.cc
@@ -37,11 +37,13 @@
   SetVisible(false);
 
   auto container_view = std::make_unique<views::View>();
-  auto* layout =
+  layout_manager_ =
       container_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
-          views::BoxLayout::Orientation::kHorizontal,
+          shelf->PrimaryAxisValue(views::BoxLayout::Orientation::kHorizontal,
+                                  views::BoxLayout::Orientation::kVertical),
           kPrivacyIndicatorsViewPadding, kPrivacyIndicatorsViewSpacing));
-  layout->set_main_axis_alignment(views::BoxLayout::MainAxisAlignment::kCenter);
+  layout_manager_->set_main_axis_alignment(
+      views::BoxLayout::MainAxisAlignment::kCenter);
 
   auto camera_icon = std::make_unique<views::ImageView>();
   camera_icon_ = container_view->AddChildView(std::move(camera_icon));
@@ -76,7 +78,9 @@
 }
 
 void PrivacyIndicatorsTrayItemView::UpdateAlignmentForShelf(Shelf* shelf) {
-  // TODO(crbug/1352593): Handle layout change when shelf alignment changes.
+  layout_manager_->SetOrientation(
+      shelf->PrimaryAxisValue(views::BoxLayout::Orientation::kHorizontal,
+                              views::BoxLayout::Orientation::kVertical));
 }
 
 void PrivacyIndicatorsTrayItemView::HandleLocaleChange() {
@@ -84,14 +88,24 @@
 }
 
 gfx::Size PrivacyIndicatorsTrayItemView::CalculatePreferredSize() const {
+  // If the view is laid out vertically in vertical shelf, the view is rotated
+  // 90 degree.
+  if (layout_manager_->GetOrientation() ==
+      views::BoxLayout::Orientation::kVertical) {
+    return gfx::Size(kPrivacyIndicatorsViewHeight, kPrivacyIndicatorsViewWidth);
+  }
   return gfx::Size(kPrivacyIndicatorsViewWidth, kPrivacyIndicatorsViewHeight);
 }
 
 void PrivacyIndicatorsTrayItemView::OnThemeChanged() {
   views::View::OnThemeChanged();
+
+  // We round the corners and set the border thickness based on the shorter side
+  // of the view (the shorter size changes based on shelf alignment).
+  int shorter_side = std::min(width(), height());
   SetBackground(views::CreateThemedRoundedRectBackground(
-      ui::kColorAshPrivacyIndicatorsBackground, height() / 2,
-      height() - kPrivacyIndicatorsViewHeight));
+      ui::kColorAshPrivacyIndicatorsBackground, shorter_side / 2,
+      shorter_side - kPrivacyIndicatorsViewHeight));
   UpdateIcons();
 }
 
diff --git a/ash/system/privacy/privacy_indicators_tray_item_view.h b/ash/system/privacy/privacy_indicators_tray_item_view.h
index 0622553..ab68819 100644
--- a/ash/system/privacy/privacy_indicators_tray_item_view.h
+++ b/ash/system/privacy/privacy_indicators_tray_item_view.h
@@ -8,6 +8,10 @@
 #include "ash/ash_export.h"
 #include "ash/system/tray/tray_item_view.h"
 
+namespace views {
+class BoxLayout;
+}  // namespace views
+
 namespace ash {
 class Shelf;
 
@@ -43,6 +47,8 @@
   // Update the icons for the children views.
   void UpdateIcons();
 
+  views::BoxLayout* layout_manager_ = nullptr;
+
   // Owned by the views hierarchy.
   views::ImageView* camera_icon_ = nullptr;
   views::ImageView* microphone_icon_ = nullptr;
diff --git a/ash/system/privacy/privacy_indicators_tray_item_view_unittest.cc b/ash/system/privacy/privacy_indicators_tray_item_view_unittest.cc
index 09c7cf3..5a6ca7a 100644
--- a/ash/system/privacy/privacy_indicators_tray_item_view_unittest.cc
+++ b/ash/system/privacy/privacy_indicators_tray_item_view_unittest.cc
@@ -6,10 +6,15 @@
 
 #include <string>
 
+#include "ash/constants/ash_features.h"
+#include "ash/shelf/shelf.h"
 #include "ash/strings/grit/ash_strings.h"
+#include "ash/system/unified/unified_system_tray.h"
 #include "ash/test/ash_test_base.h"
+#include "base/test/scoped_feature_list.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/views/controls/image_view.h"
+#include "ui/views/layout/box_layout.h"
 
 namespace ash {
 
@@ -24,6 +29,8 @@
 
   // AshTestBase:
   void SetUp() override {
+    scoped_feature_list_.InitAndEnableFeature(features::kPrivacyIndicators);
+
     AshTestBase::SetUp();
     privacy_indicators_view_ =
         std::make_unique<PrivacyIndicatorsTrayItemView>(GetPrimaryShelf());
@@ -33,6 +40,11 @@
     return privacy_indicators_view_->GetTooltipText(gfx::Point());
   }
 
+  views::BoxLayout* GetLayoutManager(
+      PrivacyIndicatorsTrayItemView* privacy_indicators_view) {
+    return privacy_indicators_view->layout_manager_;
+  }
+
  protected:
   PrivacyIndicatorsTrayItemView* privacy_indicators_view() {
     return privacy_indicators_view_.get();
@@ -47,6 +59,8 @@
 
  private:
   std::unique_ptr<PrivacyIndicatorsTrayItemView> privacy_indicators_view_;
+
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 TEST_F(PrivacyIndicatorsTrayItemViewTest, IconsVisibility) {
@@ -99,4 +113,25 @@
   EXPECT_EQ(std::u16string(), GetTooltipText());
 }
 
+TEST_F(PrivacyIndicatorsTrayItemViewTest, ShelfAlignmentChanged) {
+  auto* privacy_indicators_view =
+      GetPrimaryUnifiedSystemTray()->privacy_indicators_view();
+
+  GetPrimaryShelf()->SetAlignment(ShelfAlignment::kLeft);
+  EXPECT_EQ(views::BoxLayout::Orientation::kVertical,
+            GetLayoutManager(privacy_indicators_view)->GetOrientation());
+
+  GetPrimaryShelf()->SetAlignment(ShelfAlignment::kBottom);
+  EXPECT_EQ(views::BoxLayout::Orientation::kHorizontal,
+            GetLayoutManager(privacy_indicators_view)->GetOrientation());
+
+  GetPrimaryShelf()->SetAlignment(ShelfAlignment::kRight);
+  EXPECT_EQ(views::BoxLayout::Orientation::kVertical,
+            GetLayoutManager(privacy_indicators_view)->GetOrientation());
+
+  GetPrimaryShelf()->SetAlignment(ShelfAlignment::kBottomLocked);
+  EXPECT_EQ(views::BoxLayout::Orientation::kHorizontal,
+            GetLayoutManager(privacy_indicators_view)->GetOrientation());
+}
+
 }  // namespace ash
diff --git a/ash/system/unified/unified_system_tray.cc b/ash/system/unified/unified_system_tray.cc
index c0c1171..80bdc5e3 100644
--- a/ash/system/unified/unified_system_tray.cc
+++ b/ash/system/unified/unified_system_tray.cc
@@ -655,6 +655,8 @@
 void UnifiedSystemTray::UpdateLayout() {
   TrayBackgroundView::UpdateLayout();
   time_view_->UpdateAlignmentForShelf(shelf());
+  if (privacy_indicators_view_)
+    privacy_indicators_view_->UpdateAlignmentForShelf(shelf());
 }
 
 void UnifiedSystemTray::ShowBubbleInternal() {
diff --git a/ash/test_shell_delegate.cc b/ash/test_shell_delegate.cc
index ea4fb99..71b0dd0 100644
--- a/ash/test_shell_delegate.cc
+++ b/ash/test_shell_delegate.cc
@@ -32,7 +32,8 @@
 }
 
 std::unique_ptr<GlanceablesDelegate>
-TestShellDelegate::CreateGlanceablesDelegate() const {
+TestShellDelegate::CreateGlanceablesDelegate(
+    GlanceablesController* controller) const {
   return std::make_unique<TestGlanceablesDelegate>();
 }
 
diff --git a/ash/test_shell_delegate.h b/ash/test_shell_delegate.h
index fb6a6f28..971cc59 100644
--- a/ash/test_shell_delegate.h
+++ b/ash/test_shell_delegate.h
@@ -37,8 +37,8 @@
   bool CanShowWindowForUser(const aura::Window* window) const override;
   std::unique_ptr<CaptureModeDelegate> CreateCaptureModeDelegate()
       const override;
-  std::unique_ptr<GlanceablesDelegate> CreateGlanceablesDelegate()
-      const override;
+  std::unique_ptr<GlanceablesDelegate> CreateGlanceablesDelegate(
+      GlanceablesController* controller) const override;
   AccessibilityDelegate* CreateAccessibilityDelegate() override;
   std::unique_ptr<BackGestureContextualNudgeDelegate>
   CreateBackGestureContextualNudgeDelegate(
diff --git a/ash/webui/print_management/mojom/BUILD.gn b/ash/webui/print_management/mojom/BUILD.gn
index 0d95299..accf3e3 100644
--- a/ash/webui/print_management/mojom/BUILD.gn
+++ b/ash/webui/print_management/mojom/BUILD.gn
@@ -10,6 +10,8 @@
 mojom("mojom") {
   sources = [ "printing_manager.mojom" ]
 
+  webui_module_path = "/ash/webui/print_management"
+
   public_deps = [
     "//mojo/public/mojom/base",
     "//url/mojom:url_mojom_gurl",
diff --git a/ash/webui/print_management/print_management_ui.cc b/ash/webui/print_management/print_management_ui.cc
index d52a596..997d0e3 100644
--- a/ash/webui/print_management/print_management_ui.cc
+++ b/ash/webui/print_management/print_management_ui.cc
@@ -123,8 +123,8 @@
                                          kAshPrintManagementResourcesSize);
   SetUpWebUIDataSource(html_source, resources, IDR_PRINT_MANAGEMENT_INDEX_HTML);
 
-  html_source->AddResourcePath("printing_manager.mojom-lite.js",
-                               IDR_PRINTING_MANAGER_MOJO_LITE_JS);
+  html_source->AddResourcePath("printing_manager.mojom-webui.js",
+                               IDR_PRINTING_MANAGER_MOJO_WEBUI_JS);
 
   AddPrintManagementStrings(html_source);
 }
diff --git a/ash/webui/print_management/resources/BUILD.gn b/ash/webui/print_management/resources/BUILD.gn
index d3a0531..733b6bc 100644
--- a/ash/webui/print_management/resources/BUILD.gn
+++ b/ash/webui/print_management/resources/BUILD.gn
@@ -12,6 +12,13 @@
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
+  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/ash/webui/print_management/mojom/",
+                root_build_dir),
+      ]
   deps = [
     ":mojo_interface_provider",
     ":print_job_clear_history_dialog",
@@ -29,7 +36,7 @@
 js_library("print_job_entry") {
   deps = [
     ":icons",
-    "//ash/webui/print_management/mojom:mojom_js_library_for_compile",
+    "//ash/webui/print_management/mojom:mojom_webui_js",
     "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/js:i18n_behavior.m",
@@ -63,7 +70,7 @@
 
 js_library("mojo_interface_provider") {
   deps = [
-    "//ash/webui/print_management/mojom:mojom_js_library_for_compile",
+    "//ash/webui/print_management/mojom:mojom_webui_js",
     "//ui/webui/resources/js:cr.m",
   ]
 }
@@ -78,3 +85,9 @@
     "print_management_shared_css.js",
   ]
 }
+
+copy("copy_webui_mojo") {
+  deps = [ "../mojom:mojom_webui_js" ]
+  sources = [ "$root_gen_dir/mojom-webui/ash/webui/print_management/mojom/printing_manager.mojom-webui.js" ]
+  outputs = [ "$target_gen_dir/{{source_file_part}}" ]
+}
diff --git a/ash/webui/print_management/resources/index.html b/ash/webui/print_management/resources/index.html
index 123cdf27..49f7277 100644
--- a/ash/webui/print_management/resources/index.html
+++ b/ash/webui/print_management/resources/index.html
@@ -21,8 +21,6 @@
     <print-management></print-management>
     <script type="module" src="print_management.js"></script>
     <script type="module" src="mojo_interface_provider.js"></script>
-    <!-- Below mojo script required to run browser tests -->
-    <script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js">
     </script>
   </body>
 </html>
diff --git a/ash/webui/print_management/resources/mojo_interface_provider.js b/ash/webui/print_management/resources/mojo_interface_provider.js
index 08553e1..ab8e5dc 100644
--- a/ash/webui/print_management/resources/mojo_interface_provider.js
+++ b/ash/webui/print_management/resources/mojo_interface_provider.js
@@ -2,39 +2,27 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
-import 'chrome://resources/mojo/mojo/public/mojom/base/big_buffer.mojom-lite.js';
-import 'chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-lite.js';
-import 'chrome://resources/mojo/mojo/public/mojom/base/time.mojom-lite.js';
-import 'chrome://resources/mojo/url/mojom/url.mojom-lite.js';
-import './printing_manager.mojom-lite.js';
+import {PrintingMetadataProvider, PrintingMetadataProviderInterface} from './printing_manager.mojom-webui.js';
 
 /**
- * @type {
- *    ?ash.printing.printingManager.mojom.PrintingMetadataProviderInterface
- * }
+ * @type {?PrintingMetadataProviderInterface}
  */
 let metadataProvider = null;
 
 /**
- * @param {
- *    !ash.printing.printingManager.mojom.PrintingMetadataProviderInterface
- * } testProvider
+ * @param {!PrintingMetadataProviderInterface} testProvider
  */
 export function setMetadataProviderForTesting(testProvider) {
   metadataProvider = testProvider;
 }
 
 /**
- * @return {
- *    !ash.printing.printingManager.mojom.PrintingMetadataProviderInterface
- * }
+ * @return {!PrintingMetadataProviderInterface}
  */
 export function getMetadataProvider() {
   if (metadataProvider) {
     return metadataProvider;
   }
-  metadataProvider =
-      ash.printing.printingManager.mojom.PrintingMetadataProvider.getRemote();
+  metadataProvider = PrintingMetadataProvider.getRemote();
   return metadataProvider;
 }
diff --git a/ash/webui/print_management/resources/print_job_clear_history_dialog.js b/ash/webui/print_management/resources/print_job_clear_history_dialog.js
index aec2186c..dcc34ef 100644
--- a/ash/webui/print_management/resources/print_job_clear_history_dialog.js
+++ b/ash/webui/print_management/resources/print_job_clear_history_dialog.js
@@ -4,12 +4,7 @@
 
 import 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
-import 'chrome://resources/mojo/mojo/public/mojom/base/big_buffer.mojom-lite.js';
-import 'chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-lite.js';
-import 'chrome://resources/mojo/mojo/public/mojom/base/time.mojom-lite.js';
-import 'chrome://resources/mojo/url/mojom/url.mojom-lite.js';
 import './print_management_shared_css.js';
-import './printing_manager.mojom-lite.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/ash/webui/print_management/resources/print_job_entry.js b/ash/webui/print_management/resources/print_job_entry.js
index 27d0699..4696bfc 100644
--- a/ash/webui/print_management/resources/print_job_entry.js
+++ b/ash/webui/print_management/resources/print_job_entry.js
@@ -5,27 +5,25 @@
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
 import 'chrome://resources/cr_elements/cr_icons_css.m.js';
 import 'chrome://resources/cr_elements/icons.m.js';
-import 'chrome://resources/mojo/mojo/public/mojom/base/big_buffer.mojom-lite.js';
-import 'chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-lite.js';
-import 'chrome://resources/mojo/mojo/public/mojom/base/time.mojom-lite.js';
-import 'chrome://resources/mojo/url/mojom/url.mojom-lite.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import 'chrome://resources/polymer/v3_0/iron-media-query/iron-media-query.js';
 import 'chrome://resources/polymer/v3_0/paper-progress/paper-progress.js';
 import './icons.js';
 import './print_management_fonts_css.js';
 import './print_management_shared_css.js';
-import './printing_manager.mojom-lite.js';
 import './strings.m.js';
 
 import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js';
 import {FocusRowBehavior} from 'chrome://resources/js/cr/ui/focus_row_behavior.m.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {String16} from 'chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-webui.js';
+import {Time} from 'chrome://resources/mojo/mojo/public/mojom/base/time.mojom-webui.js';
 import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {getMetadataProvider} from './mojo_interface_provider.js';
+import {PrinterErrorCode, PrintJobCompletionStatus, PrintJobInfo} from './printing_manager.mojom-webui.js';
 
 const GENERIC_FILE_EXTENSION_ICON = 'print-management:file-generic';
 
@@ -49,7 +47,7 @@
 
 /**
  * Converts a mojo time to a JS time.
- * @param {!mojoBase.mojom.Time} mojoTime
+ * @param {!Time} mojoTime
  * @return {!Date}
  */
 function convertMojoTimeToJS(mojoTime) {
@@ -185,7 +183,7 @@
 
   static get properties() {
     return {
-      /** @type {!ash.printing.printingManager.mojom.PrintJobInfo} */
+      /** @type {!PrintJobInfo} */
       jobEntry: {
         type: Object,
       },
@@ -372,7 +370,7 @@
 
   /**
    * Converts utf16 to a readable string.
-   * @param {!mojoBase.mojom.String16} arr
+   * @param {!String16} arr
    * @return {string}
    * @private
    */
@@ -383,7 +381,7 @@
   /**
    * Converts mojo time to JS time. Returns "Today" if |mojoTime| is at the
    * current day.
-   * @param {!mojoBase.mojom.Time} mojoTime
+   * @param {!Time} mojoTime
    * @return {string}
    * @private
    */
@@ -403,19 +401,18 @@
 
   /**
    * Returns the corresponding completion status from |mojoCompletionStatus|.
-   * @param {!ash.printing.printingManager.mojom.PrintJobCompletionStatus}
+   * @param {!PrintJobCompletionStatus}
    *     mojoCompletionStatus
    * @return {string}
    * @private
    */
   convertStatusToString_(mojoCompletionStatus) {
     switch (mojoCompletionStatus) {
-      case ash.printing.printingManager.mojom.PrintJobCompletionStatus.kFailed:
+      case PrintJobCompletionStatus.kFailed:
         return this.getFailedStatusString_(this.jobEntry.printerErrorCode);
-      case ash.printing.printingManager.mojom.PrintJobCompletionStatus
-          .kCanceled:
+      case PrintJobCompletionStatus.kCanceled:
         return loadTimeData.getString('completionStatusCanceled');
-      case ash.printing.printingManager.mojom.PrintJobCompletionStatus.kPrinted:
+      case PrintJobCompletionStatus.kPrinted:
         return loadTimeData.getString('completionStatusPrinted');
       default:
         assertNotReached();
@@ -518,38 +515,36 @@
   }
 
   /**
-   * @param {!ash.printing.printingManager.mojom.PrinterErrorCode}
+   * @param {!PrinterErrorCode}
    *     mojoPrinterErrorCode
    * @return {string}
    * @private
    */
   getFailedStatusString_(mojoPrinterErrorCode) {
     switch (mojoPrinterErrorCode) {
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kNoError:
+      case PrinterErrorCode.kNoError:
         return loadTimeData.getString('completionStatusPrinted');
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kPaperJam:
+      case PrinterErrorCode.kPaperJam:
         return loadTimeData.getString('paperJam');
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kOutOfPaper:
+      case PrinterErrorCode.kOutOfPaper:
         return loadTimeData.getString('outOfPaper');
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kOutOfInk:
+      case PrinterErrorCode.kOutOfInk:
         return loadTimeData.getString('outOfInk');
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kDoorOpen:
+      case PrinterErrorCode.kDoorOpen:
         return loadTimeData.getString('doorOpen');
-      case ash.printing.printingManager.mojom.PrinterErrorCode
-          .kPrinterUnreachable:
+      case PrinterErrorCode.kPrinterUnreachable:
         return loadTimeData.getString('printerUnreachable');
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kTrayMissing:
+      case PrinterErrorCode.kTrayMissing:
         return loadTimeData.getString('trayMissing');
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kOutputFull:
+      case PrinterErrorCode.kOutputFull:
         return loadTimeData.getString('outputFull');
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kStopped:
+      case PrinterErrorCode.kStopped:
         return loadTimeData.getString('stopped');
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kFilterFailed:
+      case PrinterErrorCode.kFilterFailed:
         return loadTimeData.getString('filterFailed');
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kUnknownError:
+      case PrinterErrorCode.kUnknownError:
         return loadTimeData.getString('unknownPrinterError');
-      case ash.printing.printingManager.mojom.PrinterErrorCode
-          .kClientUnauthorized:
+      case PrinterErrorCode.kClientUnauthorized:
         return loadTimeData.getString('clientUnauthorized');
       default:
         assertNotReached();
@@ -558,7 +553,7 @@
   }
 
   /**
-   * @param {!ash.printing.printingManager.mojom.PrinterErrorCode}
+   * @param {!PrinterErrorCode}
    *     mojoPrinterErrorCode
    * @return {string}
    * @private
@@ -569,31 +564,29 @@
     }
 
     switch (mojoPrinterErrorCode) {
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kNoError:
+      case PrinterErrorCode.kNoError:
         return '';
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kPaperJam:
+      case PrinterErrorCode.kPaperJam:
         return loadTimeData.getString('paperJamStopped');
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kOutOfPaper:
+      case PrinterErrorCode.kOutOfPaper:
         return loadTimeData.getString('outOfPaperStopped');
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kOutOfInk:
+      case PrinterErrorCode.kOutOfInk:
         return loadTimeData.getString('outOfInkStopped');
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kDoorOpen:
+      case PrinterErrorCode.kDoorOpen:
         return loadTimeData.getString('doorOpenStopped');
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kTrayMissing:
+      case PrinterErrorCode.kTrayMissing:
         return loadTimeData.getString('trayMissingStopped');
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kOutputFull:
+      case PrinterErrorCode.kOutputFull:
         return loadTimeData.getString('outputFullStopped');
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kStopped:
+      case PrinterErrorCode.kStopped:
         return loadTimeData.getString('stoppedGeneric');
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kFilterFailed:
+      case PrinterErrorCode.kFilterFailed:
         return loadTimeData.getString('filterFailed');
-      case ash.printing.printingManager.mojom.PrinterErrorCode.kUnknownError:
+      case PrinterErrorCode.kUnknownError:
         return loadTimeData.getString('unknownPrinterErrorStopped');
-      case ash.printing.printingManager.mojom.PrinterErrorCode
-          .kClientUnauthorized:
+      case PrinterErrorCode.kClientUnauthorized:
         return loadTimeData.getString('clientUnauthorized');
-      case ash.printing.printingManager.mojom.PrinterErrorCode
-          .kPrinterUnreachable:
+      case PrinterErrorCode.kPrinterUnreachable:
         assertNotReached();
         return loadTimeData.getString('unknownPrinterErrorStopped');
       default:
diff --git a/ash/webui/print_management/resources/print_management.js b/ash/webui/print_management/resources/print_management.js
index f35d4ce..2e5c3e9 100644
--- a/ash/webui/print_management/resources/print_management.js
+++ b/ash/webui/print_management/resources/print_management.js
@@ -9,10 +9,6 @@
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import 'chrome://resources/polymer/v3_0/paper-tooltip/paper-tooltip.js';
-import 'chrome://resources/mojo/mojo/public/mojom/base/big_buffer.mojom-lite.js';
-import 'chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-lite.js';
-import 'chrome://resources/mojo/mojo/public/mojom/base/time.mojom-lite.js';
-import 'chrome://resources/mojo/url/mojom/url.mojom-lite.js';
 import './print_job_clear_history_dialog.js';
 import './print_job_entry.js';
 import './print_management_fonts_css.js';
@@ -25,19 +21,20 @@
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {getMetadataProvider} from './mojo_interface_provider.js';
+import {ActivePrintJobState, PrintJobInfo, PrintJobsObserverInterface, PrintJobsObserverReceiver} from './printing_manager.mojom-webui.js';
 
 const METADATA_STORED_INDEFINITELY = -1;
 const METADATA_STORED_FOR_ONE_DAY = 1;
 const METADATA_NOT_STORED = 0;
 
 /**
- * @typedef {Array<!ash.printing.printingManager.mojom.PrintJobInfo>}
+ * @typedef {Array<!PrintJobInfo>}
  */
 let PrintJobInfoArr;
 
 /**
- * @param {!ash.printing.printingManager.mojom.PrintJobInfo} first
- * @param {!ash.printing.printingManager.mojom.PrintJobInfo} second
+ * @param {!PrintJobInfo} first
+ * @param {!PrintJobInfo} second
  * @return {number}
  */
 function comparePrintJobsReverseChronologically(first, second) {
@@ -45,8 +42,8 @@
 }
 
 /**
- * @param {!ash.printing.printingManager.mojom.PrintJobInfo} first
- * @param {!ash.printing.printingManager.mojom.PrintJobInfo} second
+ * @param {!PrintJobInfo} first
+ * @param {!PrintJobInfo} second
  * @return {number}
  */
 function comparePrintJobsChronologically(first, second) {
@@ -152,9 +149,7 @@
       /**
        * Receiver responsible for observing print job updates notification
        * events.
-       * @private {
-       *   ?ash.printing.printingManager.mojom.PrintJobsObserverReceiver
-       * }
+       * @private {?PrintJobsObserverReceiver}
        */
       printJobsObserverReceiver_: {type: Object},
     };
@@ -197,13 +192,11 @@
 
   /** @private */
   startObservingPrintJobs_() {
-    this.printJobsObserverReceiver_ =
-        new ash.printing.printingManager.mojom.PrintJobsObserverReceiver(
-            /**
-             * @type {!ash.printing.printingManager.mojom.
-             *        PrintJobsObserverInterface}
-             */
-            (this));
+    this.printJobsObserverReceiver_ = new PrintJobsObserverReceiver(
+        /**
+         * @type {!PrintJobsObserverInterface}
+         */
+        (this));
     this.mojoInterfaceProvider_.observePrintJobs(
         this.printJobsObserverReceiver_.$.bindNewPipeAndPassRemote())
         .then(() => {
@@ -230,15 +223,15 @@
   }
 
   /**
-   * Overrides ash.printing.printingManager.mojom.PrintJobsObserverInterface
+   * Overrides PrintJobsObserverInterface
    */
   onAllPrintJobsDeleted() {
     this.getPrintJobs_();
   }
 
   /**
-   * Overrides ash.printing.printingManager.mojom.PrintJobsObserverInterface
-   * @param {!ash.printing.printingManager.mojom.PrintJobInfo} job
+   * Overrides PrintJobsObserverInterface
+   * @param {!PrintJobInfo} job
    */
   onPrintJobUpdate(job) {
     // Only update ongoing print jobs.
@@ -257,7 +250,7 @@
     }
 
     if (job.activePrintJobInfo.activeState ===
-        ash.printing.printingManager.mojom.ActivePrintJobState.kDocumentDone) {
+        ActivePrintJobState.kDocumentDone) {
       // This print job is now completed, next step is to update the history
       // list with the recently stored print job.
       this.getPrintJobs_();
diff --git a/ash/webui/print_management/resources/print_management_resources.grd b/ash/webui/print_management/resources/print_management_resources.grd
index e6525e93c..639e273 100644
--- a/ash/webui/print_management/resources/print_management_resources.grd
+++ b/ash/webui/print_management/resources/print_management_resources.grd
@@ -21,7 +21,7 @@
       <include name="IDR_PRINT_MANAGEMENT_SHARED_CSS_JS" file="${root_gen_dir}/ash/webui/print_management/resources/print_management_shared_css.js" resource_path="print_management_shared_css.js" use_base_dir="false" type="BINDATA"/>
       <include name="IDR_PRINT_MANAGEMENT_PRINT_JOB_CLEAR_HISTORY_DIALOG_JS" file="${root_gen_dir}/ash/webui/print_management/resources/print_job_clear_history_dialog.js" resource_path="print_job_clear_history_dialog.js" use_base_dir="false" type="BINDATA"/>
       <include name="IDR_PRINT_MANAGEMENT_ICON" file="print_management_192.png" type="BINDATA"/>
-      <include name="IDR_PRINTING_MANAGER_MOJO_LITE_JS" file="${root_gen_dir}/ash/webui/print_management/mojom/printing_manager.mojom-lite.js" resource_path="printing_manager.mojom-lite.js" use_base_dir="false" type="BINDATA" />
+      <include name="IDR_PRINTING_MANAGER_MOJO_WEBUI_JS" file="${root_gen_dir}/ash/webui/print_management/resources/printing_manager.mojom-webui.js" resource_path="printing_manager.mojom-webui.js" use_base_dir="false" type="BINDATA" />
     </includes>
 
     <structures>
diff --git a/ash/webui/resources/BUILD.gn b/ash/webui/resources/BUILD.gn
index 42ebc2e..a852219 100644
--- a/ash/webui/resources/BUILD.gn
+++ b/ash/webui/resources/BUILD.gn
@@ -271,7 +271,7 @@
       "//ash/webui/print_management/resources/print_management_resources.grd"
 
   deps = [
-    "//ash/webui/print_management/mojom:mojom_js",
+    "//ash/webui/print_management/resources:copy_webui_mojo",
     "//ash/webui/print_management/resources:web_components",
   ]
 
diff --git a/base/check_unittest.cc b/base/check_unittest.cc
index ec8b25a..8feb87b 100644
--- a/base/check_unittest.cc
+++ b/base/check_unittest.cc
@@ -392,8 +392,6 @@
 }
 #endif  // CHECK_WILL_STREAM()
 
-// TODO(crbug.com/1354494): Short term fix by sheriff to get compiling.
-#if !BUILDFLAG(DCHECK_IS_CONFIGURABLE)
 TEST_F(CheckTest, OstreamVsToString) {
   StructWithOstream a, b;
   EXPECT_CHECK("Check failed: a == b (ostream vs. ostream)", CHECK_EQ(a, b));
@@ -408,7 +406,6 @@
   EXPECT_CHECK("Check failed: g == h (ToString+ostream vs. ToString+ostream)",
                CHECK_EQ(g, h));
 }
-#endif
 
 #define EXPECT_LOG_ERROR(expected_line, expr, msg)                             \
   do {                                                                         \
diff --git a/base/memory/weak_ptr_unittest.nc b/base/memory/weak_ptr_unittest.nc
index 96925795..b167fb6 100644
--- a/base/memory/weak_ptr_unittest.nc
+++ b/base/memory/weak_ptr_unittest.nc
@@ -129,8 +129,7 @@
   WeakPtr<Unrelated> ptr = AsWeakPtr(&f);
 }
 
-#elif defined(NCTEST_AMBIGUOUS_ANCESTORS)  // [r"fatal error: (use of undeclared identifier|no matching function for call to) 'AsWeakPtrImpl'"]
-// TODO(crbug.com/1155145): Update expectation after rolling clang.
+#elif defined(NCTEST_AMBIGUOUS_ANCESTORS)  // [r"fatal error: no matching function for call to 'AsWeakPtrImpl'"]
 
 void WontCompile() {
   MultiplyDerivedProducer f;
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index 2aa326b7..846c155 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -379,3 +379,10 @@
     }
   }
 }
+
+# Add this config to link steps in order to compress debug sections. This is
+# especially useful on 32-bit architectures in order to keep file sizes under
+# 4gb.
+config("compress_debug_sections") {
+  ldflags = [ "-gz" ]
+}
diff --git a/build/config/fuchsia/size_optimized_cast_receiver_args.gn b/build/config/fuchsia/size_optimized_cast_receiver_args.gn
new file mode 100644
index 0000000..2ccb1b2
--- /dev/null
+++ b/build/config/fuchsia/size_optimized_cast_receiver_args.gn
@@ -0,0 +1,35 @@
+# 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.
+
+# This file contains feature and optimization overrides that are commonly
+# required or useful for Cast Receiver implementations.
+# It prioritizes size and disables unneeded features that may add size.
+#
+# To use it do one of the following:
+# * Add the following to your `gn args`:
+#   import("//build/config/fuchsia/size_optimized_cast_receiver_args.gn")
+# * Add the following to `gn_args` in a bot recipe:
+#   'args_file': '//build/config/fuchsia/size_optimized_cast_receiver_args.gn'
+
+# There is no reason these values couldn't be used on other platforms, but this
+# file is in a fuchsia/ directory and some refactoring would probably be
+# appropriate before reusing this file.
+# It is not possible to assert the platform because `target_os` is not defined
+# when this file is imported.
+
+enable_basic_printing = false
+enable_cast_receiver = true
+enable_dav1d_decoder = false
+
+# //chrome makes many assumptions that Extensions are enabled.
+# TODO(crbug.com/1352700): Fix theses assumptions or avoid building it.
+# enable_extensions = false
+
+enable_hidpi = false
+enable_library_cdms = false
+enable_logging_override = true
+enable_pdf = false
+enable_plugins = false
+optimize_for_size = true
+optional_trace_events_enabled = false
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java
index abf3e879..0bc74fd 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java
@@ -283,9 +283,10 @@
     /**
      * Synchronously get the processed favicon, assuming it is not recolor allowed.
      * @param icon The favicon that was received.
+     * @param iconUrl The url the favicon came from.
      * @return The processed {@link TabFavicon}.
      */
-    TabFavicon getFaviconFromBitmap(@NonNull Bitmap icon) {
+    TabFavicon getFaviconFromBitmap(@NonNull Bitmap icon, @NonNull GURL iconUrl) {
         return new TabFavicon(processBitmap(icon, mIsTabStrip));
     }
 
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
index 8ebfb7e..3973f2b 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -511,8 +511,8 @@
         }
 
         @Override
-        public void onFaviconUpdated(Tab updatedTab, Bitmap icon) {
-            updateFaviconForTab(PseudoTab.fromTab(updatedTab), icon);
+        public void onFaviconUpdated(Tab updatedTab, Bitmap icon, GURL iconUrl) {
+            updateFaviconForTab(PseudoTab.fromTab(updatedTab), icon, iconUrl);
         }
 
         @Override
@@ -1362,7 +1362,7 @@
 
         setupPersistedTabDataFetcherForTab(pseudoTab, index);
 
-        updateFaviconForTab(pseudoTab, null);
+        updateFaviconForTab(pseudoTab, null, null);
         boolean forceUpdate = isSelected && !quickMode;
         boolean forceUpdateLastSelected =
                 mActionsOnAllRelatedTabs && index == mLastSelectedTabListModelIndex && !quickMode;
@@ -1691,7 +1691,7 @@
 
         setupPersistedTabDataFetcherForTab(pseudoTab, index);
 
-        updateFaviconForTab(pseudoTab, null);
+        updateFaviconForTab(pseudoTab, null, null);
 
         if (mThumbnailProvider != null && mVisible) {
             ThumbnailFetcher callback = new ThumbnailFetcher(mThumbnailProvider, pseudoTab.getId(),
@@ -1870,7 +1870,7 @@
     }
 
     @VisibleForTesting
-    void updateFaviconForTab(PseudoTab pseudoTab, @Nullable Bitmap icon) {
+    void updateFaviconForTab(PseudoTab pseudoTab, @Nullable Bitmap icon, @Nullable GURL iconUrl) {
         int modelIndex = mModel.indexFromId(pseudoTab.getId());
         if (modelIndex == Tab.INVALID_TAB_ID) return;
         List<Tab> relatedTabList = getRelatedTabsForId(pseudoTab.getId());
@@ -1911,8 +1911,8 @@
         }
 
         // If there is an available icon, we fetch favicon synchronously; otherwise asynchronously.
-        if (icon != null) {
-            TabFavicon favicon = mTabListFaviconProvider.getFaviconFromBitmap(icon);
+        if (icon != null && iconUrl != null) {
+            TabFavicon favicon = mTabListFaviconProvider.getFaviconFromBitmap(icon, iconUrl);
             mModel.get(modelIndex).model.set(TabProperties.FAVICON, favicon);
             return;
         }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
index ac93a2dc..8ea8a03 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
@@ -333,6 +333,7 @@
     private String mTab2Domain;
     private String mTab3Domain;
     private String mNewDomain;
+    private GURL mFaviconUrl;
 
     @Before
     public void setUp() {
@@ -352,6 +353,7 @@
         mTab2Domain = TAB2_URL.getHost().replace("www.", "");
         mTab3Domain = TAB3_URL.getHost().replace("www.", "");
         mNewDomain = JUnitTestGURLs.getGURL(NEW_URL).getHost().replace("www.", "");
+        mFaviconUrl = JUnitTestGURLs.getGURL(JUnitTestGURLs.RED_1);
 
         TabUiFeatureUtilities.ENABLE_SEARCH_CHIP.setForTesting(true);
         mTab1 = prepareTab(TAB1_ID, TAB1_TITLE, TAB1_URL);
@@ -394,7 +396,9 @@
         doNothing()
                 .when(mTabListFaviconProvider)
                 .getFaviconForUrlAsync(anyObject(), anyBoolean(), mCallbackCaptor.capture());
-        doReturn(mFavicon).when(mTabListFaviconProvider).getFaviconFromBitmap(any(Bitmap.class));
+        doReturn(mFavicon)
+                .when(mTabListFaviconProvider)
+                .getFaviconFromBitmap(any(Bitmap.class), any(GURL.class));
         doReturn(mTab1).when(mTabModelSelector).getTabById(TAB1_ID);
         doReturn(mTab2).when(mTabModelSelector).getTabById(TAB2_ID);
         doReturn(tabs1).when(mTabGroupModelFilter).getRelatedTabList(TAB1_ID);
@@ -510,7 +514,7 @@
         mModel.get(0).model.set(TabProperties.FAVICON, null);
         assertNull(mModel.get(0).model.get(TabProperties.FAVICON));
 
-        mTabObserverCaptor.getValue().onFaviconUpdated(mTab1, mFaviconBitmap);
+        mTabObserverCaptor.getValue().onFaviconUpdated(mTab1, mFaviconBitmap, mFaviconUrl);
 
         assertNotNull(mModel.get(0).model.get(TabProperties.FAVICON));
     }
@@ -522,7 +526,7 @@
         mModel.get(0).model.set(TabProperties.FAVICON, null);
         assertNull(mModel.get(0).model.get(TabProperties.FAVICON));
 
-        mTabObserverCaptor.getValue().onFaviconUpdated(mTab1, mFaviconBitmap);
+        mTabObserverCaptor.getValue().onFaviconUpdated(mTab1, mFaviconBitmap, mFaviconUrl);
 
         assertNotNull(mModel.get(0).model.get(TabProperties.FAVICON));
     }
@@ -537,7 +541,7 @@
         TabImpl newTab = prepareTab(TAB3_ID, TAB3_TITLE, TAB3_URL);
         doReturn(Arrays.asList(mTab1, newTab)).when(mTabModelFilter).getRelatedTabList(eq(TAB1_ID));
 
-        mTabObserverCaptor.getValue().onFaviconUpdated(mTab1, mFaviconBitmap);
+        mTabObserverCaptor.getValue().onFaviconUpdated(mTab1, mFaviconBitmap, mFaviconUrl);
 
         assertNull(mModel.get(0).model.get(TabProperties.FAVICON));
     }
@@ -548,7 +552,7 @@
         mModel.get(0).model.set(TabProperties.FAVICON, null);
         mModel.get(1).model.set(TabProperties.FAVICON, null);
 
-        mMediator.updateFaviconForTab(PseudoTab.fromTab(mTab2), null);
+        mMediator.updateFaviconForTab(PseudoTab.fromTab(mTab2), null, null);
         assertThat(mModel.indexFromId(TAB2_ID), equalTo(1));
         // Before executing callback, there is a deletion in tab list model which makes the index
         // stale.
@@ -2941,7 +2945,7 @@
         TabImpl tab3 = prepareTab(TAB3_ID, TAB3_TITLE, TAB3_URL);
         List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2, tab3));
         createTabGroup(tabs, TAB1_ID);
-        mTabObserverCaptor.getValue().onFaviconUpdated(mTab1, mFaviconBitmap);
+        mTabObserverCaptor.getValue().onFaviconUpdated(mTab1, mFaviconBitmap, mFaviconUrl);
         List<GURL> urls = new ArrayList<>(Arrays.asList(TAB1_URL, TAB2_URL, TAB3_URL));
         verify(mTabListFaviconProvider).getComposedFaviconImageAsync(eq(urls), anyBoolean(), any());
         mCallbackCaptor.getValue().onResult(mFavicon);
@@ -2953,7 +2957,7 @@
         TabImpl tab5 = prepareTab(1, "tab 5", JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL));
         tabs.addAll(Arrays.asList(tab4, tab5));
         createTabGroup(tabs, TAB2_ID);
-        mTabObserverCaptor.getValue().onFaviconUpdated(mTab2, mFaviconBitmap);
+        mTabObserverCaptor.getValue().onFaviconUpdated(mTab2, mFaviconBitmap, mFaviconUrl);
         urls = new ArrayList<>(Arrays.asList(TAB2_URL, TAB1_URL, TAB3_URL, TAB2_URL));
 
         verify(mTabListFaviconProvider).getComposedFaviconImageAsync(eq(urls), anyBoolean(), any());
@@ -2977,7 +2981,7 @@
         createTabGroup(group1, TAB2_ID);
         assertEquals(1, mModel.indexFromId(TAB2_ID));
 
-        mTabObserverCaptor.getValue().onFaviconUpdated(mTab2, mFaviconBitmap);
+        mTabObserverCaptor.getValue().onFaviconUpdated(mTab2, mFaviconBitmap, mFaviconUrl);
 
         // Simulate selecting another Tab within TabGroup before callback in
         // getComposedFaviconImageAsync triggers
@@ -3004,7 +3008,7 @@
         createTabGroup(group1, TAB2_ID);
         assertEquals(1, mModel.indexFromId(TAB2_ID));
 
-        mTabObserverCaptor.getValue().onFaviconUpdated(mTab2, mFaviconBitmap);
+        mTabObserverCaptor.getValue().onFaviconUpdated(mTab2, mFaviconBitmap, mFaviconUrl);
 
         // Simulate closing mTab1 at index 0 before callback in getComposedFaviconImageAsync
         // triggers.
@@ -3031,7 +3035,7 @@
         createTabGroup(group1, TAB2_ID);
         assertEquals(1, mModel.indexFromId(TAB2_ID));
 
-        mTabObserverCaptor.getValue().onFaviconUpdated(mTab2, mFaviconBitmap);
+        mTabObserverCaptor.getValue().onFaviconUpdated(mTab2, mFaviconBitmap, mFaviconUrl);
 
         // Simulate TabListMediator reset with null before callback in getComposedFaviconImageAsync
         // triggers.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/accessibility_tab_switcher/AccessibilityTabModelListItem.java b/chrome/android/java/src/org/chromium/chrome/browser/accessibility_tab_switcher/AccessibilityTabModelListItem.java
index d711291b..2f144fd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/accessibility_tab_switcher/AccessibilityTabModelListItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/accessibility_tab_switcher/AccessibilityTabModelListItem.java
@@ -41,6 +41,7 @@
 import org.chromium.chrome.browser.tab.TabObserver;
 import org.chromium.components.browser_ui.styles.ChromeColors;
 import org.chromium.components.browser_ui.styles.SemanticColorUtils;
+import org.chromium.url.GURL;
 
 /**
  * A widget that shows a single row of the {@link AccessibilityTabModelListView} list.
@@ -441,7 +442,7 @@
         }
 
         @Override
-        public void onFaviconUpdated(Tab tab, Bitmap icon) {
+        public void onFaviconUpdated(Tab tab, Bitmap icon, GURL iconUrl) {
             updateFavicon();
             notifyTabUpdated(tab);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
index c8cbeec7..17fb03c7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -2576,6 +2576,8 @@
                 RequestDesktopUtils.setRequestDesktopSiteContentSettingsForUrl(
                         profile, currentTab.getUrl(), usingDesktopUserAgent);
                 currentTab.reload();
+                RequestDesktopUtils.maybeShowUserEducationPromptForAppMenuSelection(
+                        Profile.getLastUsedRegularProfile());
             } else {
                 TabUtils.switchUserAgent(currentTab, usingDesktopUserAgent, /* forcedByUser */ true,
                         UseDesktopUserAgentCaller.ON_MENU_OR_KEYBOARD_ACTION);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
index 78db673..31e8150f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
@@ -655,7 +655,7 @@
             }
 
             @Override
-            public void onFaviconUpdated(Tab tab, Bitmap icon) {
+            public void onFaviconUpdated(Tab tab, Bitmap icon, GURL iconUrl) {
                 updateTitleForTab(tab);
             }
         };
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTaskDescriptionHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTaskDescriptionHelper.java
index 10399ea..652d9e0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTaskDescriptionHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTaskDescriptionHelper.java
@@ -170,7 +170,7 @@
                 }
 
                 @Override
-                public void onFaviconUpdated(Tab tab, Bitmap icon) {
+                public void onFaviconUpdated(Tab tab, Bitmap icon, GURL iconUrl) {
                     if (icon == null) return;
                     updateFavicon(icon);
                 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
index 5c7f198..9c45c96 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
@@ -21,6 +21,7 @@
 import org.chromium.components.browser_ui.media.MediaSessionHelper;
 import org.chromium.content_public.browser.BrowserContextHandle;
 import org.chromium.ui.base.WindowAndroid;
+import org.chromium.url.GURL;
 
 /**
  * A tab helper that wraps {@link MediaSessionHelper} and is responsible for Chrome-specific
@@ -40,7 +41,7 @@
         }
 
         @Override
-        public void onFaviconUpdated(Tab tab, Bitmap icon) {
+        public void onFaviconUpdated(Tab tab, Bitmap icon, GURL iconUrl) {
             assert tab == mTab;
             mMediaSessionHelper.updateFavicon(icon);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SignInPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SignInPreference.java
index 68f81a7..789f32a5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SignInPreference.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SignInPreference.java
@@ -13,6 +13,7 @@
 
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.signin.SyncConsentActivityLauncherImpl;
@@ -22,6 +23,7 @@
 import org.chromium.chrome.browser.signin.services.SigninManager.SignInStateObserver;
 import org.chromium.chrome.browser.sync.SyncService;
 import org.chromium.chrome.browser.sync.SyncService.SyncStateChangedListener;
+import org.chromium.chrome.browser.ui.signin.TangibleSyncCoordinator;
 import org.chromium.components.browser_ui.settings.ManagedPreferencesUtils;
 import org.chromium.components.prefs.PrefService;
 import org.chromium.components.signin.AccountManagerFacade;
@@ -32,6 +34,7 @@
 import org.chromium.components.signin.metrics.SigninAccessPoint;
 import org.chromium.components.user_prefs.UserPrefs;
 import org.chromium.ui.base.ViewUtils;
+import org.chromium.ui.modaldialog.ModalDialogManagerHolder;
 
 /**
  * A preference that displays "Sign in to Chrome" when the user is not sign in, and displays
@@ -156,9 +159,18 @@
         setFragment(null);
         setIcon(AppCompatResources.getDrawable(getContext(), R.drawable.logo_avatar_anonymous));
         setViewEnabled(true);
-        setOnPreferenceClickListener(pref
-                -> SyncConsentActivityLauncherImpl.get().launchActivityIfAllowed(
-                        getContext(), SigninAccessPoint.SETTINGS_SYNC_OFF_ROW));
+        setOnPreferenceClickListener(pref -> {
+            if (ChromeFeatureList.isEnabled(ChromeFeatureList.TANGIBLE_SYNC)) {
+                TangibleSyncCoordinator.start(getContext(),
+                        ((ModalDialogManagerHolder) getContext()).getModalDialogManager(),
+                        SyncConsentActivityLauncherImpl.get(),
+                        SigninAccessPoint.SETTINGS_SYNC_OFF_ROW);
+                return true;
+            } else {
+                return SyncConsentActivityLauncherImpl.get().launchActivityIfAllowed(
+                        getContext(), SigninAccessPoint.SETTINGS_SYNC_OFF_ROW);
+            }
+        });
 
         if (!mWasGenericSigninPromoDisplayed) {
             RecordUserAction.record("Signin_Impression_FromSettings");
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/RequestDesktopUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/RequestDesktopUtils.java
index 29c8a892..97ff4ea 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/RequestDesktopUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/RequestDesktopUtils.java
@@ -14,6 +14,7 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.page_info.SiteSettingsHelper;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
@@ -26,6 +27,7 @@
 import org.chromium.components.content_settings.ContentSettingValues;
 import org.chromium.components.content_settings.ContentSettingsType;
 import org.chromium.components.embedder_support.util.UrlUtilities;
+import org.chromium.components.feature_engagement.FeatureConstants;
 import org.chromium.components.messages.MessageBannerProperties;
 import org.chromium.components.messages.MessageDispatcher;
 import org.chromium.components.messages.MessageIdentifier;
@@ -384,6 +386,21 @@
     }
 
     /**
+     * Show a prompt to educate the user about the update in the behavior of the desktop site app
+     * menu setting from a tab-level setting to a site-level setting.
+     * @param profile The current {@link Profile}.
+     * @return Whether the prompt was shown.
+     */
+    public static boolean maybeShowUserEducationPromptForAppMenuSelection(Profile profile) {
+        if (!TrackerFactory.getTrackerForProfile(profile).shouldTriggerHelpUI(
+                    FeatureConstants.REQUEST_DESKTOP_SITE_APP_MENU_FEATURE)) {
+            return false;
+        }
+        // TODO(crbug.com/1353597): Trigger user education dialog for behavior update.
+        return true;
+    }
+
+    /**
      * Updates the desktop site content setting on user request.
      * @param profile The current {@link Profile}.
      * @param requestDesktopSite Whether the user requested for desktop sites globally.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabFavicon.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabFavicon.java
index ddf737e..5dbeab8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabFavicon.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabFavicon.java
@@ -35,7 +35,8 @@
     private Bitmap mFavicon;
     private int mFaviconWidth;
     private int mFaviconHeight;
-    private GURL mFaviconUrl;
+    // The URL of the tab when mFavicon was fetched.
+    private GURL mFaviconTabUrl;
 
     static TabFavicon from(Tab tab) {
         TabFavicon favicon = get(tab);
@@ -91,7 +92,7 @@
         if (mTab.isNativePage() || mTab.getWebContents() == null) return null;
 
         // Use the cached favicon only if the page wasn't changed.
-        if (mFavicon != null && mFaviconUrl != null && mFaviconUrl.equals(mTab.getUrl())) {
+        if (mFavicon != null && mFaviconTabUrl != null && mFaviconTabUrl.equals(mTab.getUrl())) {
             return mFavicon;
         }
 
@@ -129,10 +130,10 @@
 
     @CalledByNative
     @VisibleForTesting
-    void onFaviconAvailable(Bitmap icon) {
+    void onFaviconAvailable(Bitmap icon, GURL iconUrl) {
         if (icon == null) return;
-        GURL url = mTab.getUrl();
-        boolean pageUrlChanged = !url.equals(mFaviconUrl);
+        GURL currentTabUrl = mTab.getUrl();
+        boolean pageUrlChanged = !currentTabUrl.equals(mFaviconTabUrl);
         // This method will be called multiple times if the page has more than one favicon.
         // We are trying to use the |mIdealFaviconSize|x|mIdealFaviconSize| DP icon here, or the
         // first one larger than that received. Bitmap.createScaledBitmap will return the original
@@ -141,17 +142,17 @@
             mFavicon = Bitmap.createScaledBitmap(icon, mIdealFaviconSize, mIdealFaviconSize, true);
             mFaviconWidth = icon.getWidth();
             mFaviconHeight = icon.getHeight();
-            mFaviconUrl = url;
+            mFaviconTabUrl = currentTabUrl;
             if (ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_SCROLL_OPTIMIZATIONS)) {
                 RewindableIterator<TabObserver> observers = mTab.getTabObservers();
-                while (observers.hasNext()) observers.next().onFaviconUpdated(mTab, icon);
+                while (observers.hasNext()) observers.next().onFaviconUpdated(mTab, icon, iconUrl);
             }
         }
 
         if (ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_SCROLL_OPTIMIZATIONS)) return;
         // TODO(yfriedman): Remove this code after ANDROID_SCROLL_OPTIMIZATIONS is fully rolled out.
         RewindableIterator<TabObserver> observers = mTab.getTabObservers();
-        while (observers.hasNext()) observers.next().onFaviconUpdated(mTab, icon);
+        while (observers.hasNext()) observers.next().onFaviconUpdated(mTab, icon, iconUrl);
     }
 
     @NativeMethods
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabFaviconTest.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabFaviconTest.java
index 815fae7..64b63917 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabFaviconTest.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabFaviconTest.java
@@ -101,11 +101,15 @@
         return image;
     }
 
+    private void onFaviconAvailable(Bitmap bitmap) {
+        mTabFavicon.onFaviconAvailable(bitmap, JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL));
+    }
+
     @Test
     public void testOnFaviconAvailable_ReturnsBitmap() {
         Assert.assertNull(TabFavicon.getBitmap(mTab));
 
-        mTabFavicon.onFaviconAvailable(makeBitmap(1, Color.GREEN));
+        onFaviconAvailable(makeBitmap(1, Color.GREEN));
         Bitmap bitmap = TabFavicon.getBitmap(mTab);
         Assert.assertNotNull(bitmap);
         Assert.assertEquals(Color.GREEN, bitmap.getPixel(0, 0));
@@ -113,10 +117,10 @@
 
     @Test
     public void testOnFaviconAvailable_IdealSize() {
-        mTabFavicon.onFaviconAvailable(makeBitmap(1, Color.RED));
-        mTabFavicon.onFaviconAvailable(makeBitmap(IDEAL_SIZE, Color.GREEN));
-        mTabFavicon.onFaviconAvailable(makeBitmap(IDEAL_SIZE / 2, Color.YELLOW));
-        mTabFavicon.onFaviconAvailable(makeBitmap(IDEAL_SIZE * 2, Color.BLUE));
+        onFaviconAvailable(makeBitmap(1, Color.RED));
+        onFaviconAvailable(makeBitmap(IDEAL_SIZE, Color.GREEN));
+        onFaviconAvailable(makeBitmap(IDEAL_SIZE / 2, Color.YELLOW));
+        onFaviconAvailable(makeBitmap(IDEAL_SIZE * 2, Color.BLUE));
 
         Bitmap bitmap = TabFavicon.getBitmap(mTab);
         Assert.assertNotNull(bitmap);
@@ -128,8 +132,8 @@
         // Inspired from https://crbug.com/1352674. Some pages purposefully switch favicons to try
         // to update the current favicon. This will typically result in the same sized favicon being
         // sent. So it's important that we update in this case.
-        mTabFavicon.onFaviconAvailable(makeBitmap(1, Color.RED));
-        mTabFavicon.onFaviconAvailable(makeBitmap(1, Color.GREEN));
+        onFaviconAvailable(makeBitmap(1, Color.RED));
+        onFaviconAvailable(makeBitmap(1, Color.GREEN));
 
         Bitmap bitmap = TabFavicon.getBitmap(mTab);
         Assert.assertNotNull(bitmap);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
index 2e85a8a1..d43af015 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
@@ -1467,7 +1467,7 @@
     private void notifyFaviconChanged() {
         RewindableIterator<TabObserver> observers = getTabObservers();
         while (observers.hasNext()) {
-            observers.next().onFaviconUpdated(this, null);
+            observers.next().onFaviconUpdated(this, null, null);
         }
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarTest.java
index b4f3716..501e11fe 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarTest.java
@@ -592,7 +592,7 @@
                 () -> { mLocationBarCoordinator.setOmniboxEditingText(url); });
 
         onView(withId(R.id.mic_button))
-                .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)));
+                .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)));
         onView(withId(R.id.delete_button))
                 .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)));
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java
index 8bbc9fa2..26ca4a63 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java
@@ -328,6 +328,41 @@
     }
 
     @Test
+    @MediumTest
+    @EnableFeatures(ChromeFeatureList.SYNC_ANDROID_PROMOS_WITH_SINGLE_BUTTON)
+    public void testSigninRowLaunchesSignInFlowForSignedOutAccounts() {
+        // When there are no accounts, sync promo and the signin preference shows the same text.
+        mSyncTestRule.addTestAccount();
+        launchSettingsActivity();
+
+        onView(withText(R.string.sync_promo_turn_on_sync)).perform(click());
+
+        verify(mMockSyncConsentActivityLauncher)
+                .launchActivityIfAllowed(
+                        any(Activity.class), eq(SigninAccessPoint.SETTINGS_SYNC_OFF_ROW));
+    }
+
+    @Test
+    @MediumTest
+    @EnableFeatures({ChromeFeatureList.TANGIBLE_SYNC,
+            ChromeFeatureList.SYNC_ANDROID_PROMOS_WITH_SINGLE_BUTTON})
+    public void
+    testSigninRowLaunchesTangibleSignInFlowForSignedOutAccounts() {
+        // When there are no accounts, sync promo and the signin preference shows the same text.
+        mSyncTestRule.addTestAccount();
+        launchSettingsActivity();
+
+        onView(withText(R.string.sync_promo_turn_on_sync)).perform(click());
+
+        onView(withText(R.string.signin_account_picker_dialog_title))
+                .inRoot(isDialog())
+                .check(matches(isDisplayed()));
+        onView(withText(R.string.signin_add_account_to_device))
+                .inRoot(isDialog())
+                .check(matches(isDisplayed()));
+    }
+
+    @Test
     @SmallTest
     public void testSyncRowLaunchesSignInFlowForSignedInAccounts() {
         CoreAccountInfo accountInfo = mSyncTestRule.setUpAccountAndSignInForTesting();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SyncConsentFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SyncConsentFragmentTest.java
index 78302f5..2393cfc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SyncConsentFragmentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SyncConsentFragmentTest.java
@@ -13,6 +13,10 @@
 import static androidx.test.espresso.matcher.ViewMatchers.withId;
 import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -36,8 +40,8 @@
 
 import org.hamcrest.Matcher;
 import org.junit.After;
-import org.junit.Assert;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TestRule;
@@ -47,6 +51,7 @@
 import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.test.BaseActivityTestRule;
+import org.chromium.base.test.metrics.HistogramTestRule;
 import org.chromium.base.test.util.ApplicationTestUtils;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.CommandLineFlags.Add;
@@ -62,6 +67,7 @@
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
+import org.chromium.chrome.browser.signin.services.SigninMetricsUtils.State;
 import org.chromium.chrome.browser.sync.SyncService;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
@@ -75,6 +81,7 @@
 import org.chromium.components.signin.base.CoreAccountInfo;
 import org.chromium.components.signin.identitymanager.ConsentLevel;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
+import org.chromium.content_public.browser.test.NativeLibraryTestUtils;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.ui.test.util.BlankUiTestActivity;
 
@@ -89,6 +96,7 @@
 public class SyncConsentFragmentTest {
     private static final int RENDER_REVISION = 1;
     private static final String RENDER_DESCRIPTION = "Change button style";
+    private static final String NEW_ACCOUNT_NAME = "new.account@gmail.com";
     /**
      * This class is used to test {@link SyncConsentFirstRunFragment}.
      */
@@ -122,6 +130,9 @@
     public final SigninTestRule mSigninTestRule = new SigninTestRule();
 
     @Rule
+    public final HistogramTestRule mHistogramTestRule = new HistogramTestRule();
+
+    @Rule
     public final ChromeTabbedActivityTestRule mChromeActivityTestRule =
             new ChromeTabbedActivityTestRule();
 
@@ -145,6 +156,14 @@
 
     private SyncConsentActivity mSyncConsentActivity;
 
+    @BeforeClass
+    public static void setUpBeforeActivityLaunched() {
+        // Only needs to be loaded once and needs to be loaded before HistogramTestRule.
+        // TODO(https://crbug.com/1211884): Revise after HistogramTestRule is revised to not require
+        // native loading.
+        NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess();
+    }
+
     @Before
     public void setUp() {
         when(mExternalAuthUtilsMock.canUseGooglePlayServices(any())).thenReturn(true);
@@ -318,7 +337,7 @@
         fragment.setPageDelegate(mFirstRunPageDelegateMock);
 
         launchActivityWithFragment(fragment);
-        Assert.assertEquals(1, startPageHistogram.getDelta());
+        assertEquals(1, startPageHistogram.getDelta());
         mRenderTestRule.render(mActivityTestRule.getActivity().findViewById(android.R.id.content),
                 "fre_sync_consent_fragment_with_no_account");
     }
@@ -338,7 +357,7 @@
         fragment.setPageDelegate(mFirstRunPageDelegateMock);
 
         launchActivityWithFragment(fragment);
-        Assert.assertEquals(1, startPageHistogram.getDelta());
+        assertEquals(1, startPageHistogram.getDelta());
         mRenderTestRule.render(mActivityTestRule.getActivity().findViewById(android.R.id.content),
                 "fre_sync_consent_fragment_with_adult_account");
     }
@@ -358,7 +377,7 @@
         fragment.setPageDelegate(mFirstRunPageDelegateMock);
 
         launchActivityWithFragment(fragment);
-        Assert.assertEquals(1, startPageHistogram.getDelta());
+        assertEquals(1, startPageHistogram.getDelta());
         mRenderTestRule.render(mActivityTestRule.getActivity().findViewById(android.R.id.content),
                 "fre_tangible_sync_consent_fragment_with_adult_account");
     }
@@ -380,7 +399,7 @@
         fragment.setPageDelegate(mFirstRunPageDelegateMock);
 
         launchActivityWithFragment(fragment);
-        Assert.assertEquals(1, startPageHistogram.getDelta());
+        assertEquals(1, startPageHistogram.getDelta());
         // TODO(https://crbug.com/1291903): Rewrite this test when RenderTestRule is integrated with
         // Espresso.
         // We check the button is enabled rather than visible, as it may be off-screen on small
@@ -406,7 +425,7 @@
         fragment.setPageDelegate(mFirstRunPageDelegateMock);
 
         launchActivityWithFragment(fragment);
-        Assert.assertEquals(1, startPageHistogram.getDelta());
+        assertEquals(1, startPageHistogram.getDelta());
         // TODO(https://crbug.com/1291903): Rewrite this test when RenderTestRule is integrated with
         // Espresso.
         // We check the button is enabled rather than visible, as it may be off-screen on small
@@ -433,7 +452,7 @@
         fragment.setPageDelegate(mFirstRunPageDelegateMock);
 
         launchActivityWithFragment(fragment);
-        Assert.assertEquals(1, startPageHistogram.getDelta());
+        assertEquals(1, startPageHistogram.getDelta());
         // TODO(https://crbug.com/1291903): Rewrite this test when RenderTestRule is integrated with
         // Espresso.
         // We check the button is enabled rather than visible, as it may be off-screen on small
@@ -467,7 +486,7 @@
         final CoreAccountInfo defaultAccount =
                 mSigninTestRule.addAccount("test.default.account@gmail.com");
         final CoreAccountInfo primaryAccount = mSigninTestRule.addTestAccountThenSignin();
-        Assert.assertNotEquals(
+        assertNotEquals(
                 "Primary account should be a different account!", defaultAccount, primaryAccount);
         CustomSyncConsentFirstRunFragment fragment = new CustomSyncConsentFirstRunFragment();
         Bundle bundle = new Bundle();
@@ -527,8 +546,8 @@
                     .hasPrimaryAccount(ConsentLevel.SYNC);
         });
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Assert.assertTrue(SyncService.get().isSyncRequested());
-            Assert.assertFalse(SyncService.get().isFirstSetupComplete());
+            assertTrue(SyncService.get().isSyncRequested());
+            assertFalse(SyncService.get().isFirstSetupComplete());
         });
         // Close the SettingsActivity.
         onView(withId(R.id.cancel_button)).perform(click());
@@ -555,8 +574,8 @@
                     .hasPrimaryAccount(ConsentLevel.SYNC);
         });
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Assert.assertTrue(SyncService.get().isSyncRequested());
-            Assert.assertFalse(SyncService.get().isFirstSetupComplete());
+            assertTrue(SyncService.get().isSyncRequested());
+            assertFalse(SyncService.get().isFirstSetupComplete());
         });
         // Close the SettingsActivity.
         onView(withId(R.id.cancel_button)).perform(click());
@@ -611,7 +630,7 @@
                 });
         onView(withId(R.id.positive_button)).check(matches(withText(R.string.signin_add_account)));
         onView(withId(R.id.negative_button)).check(matches(withText(R.string.cancel)));
-        Assert.assertEquals(1, settingsHistogram.getDelta());
+        assertEquals(1, settingsHistogram.getDelta());
     }
 
     @Test
@@ -638,7 +657,211 @@
         // not shown anymore.
         onView(withText(defaultAccountInfo.getEmail())).check(doesNotExist());
         onView(withText(nonDefaultAccountName)).check(matches(isDisplayed()));
-        Assert.assertEquals(1, bookmarkHistogram.getDelta());
+        assertEquals(1, bookmarkHistogram.getDelta());
+    }
+
+    @Test
+    @LargeTest
+    @DisableFeatures({ChromeFeatureList.TANGIBLE_SYNC})
+    public void testSyncConsentFragmentAddAccountFlowSucceeded() {
+        mSigninTestRule.setResultForNextAddAccountFlow(Activity.RESULT_OK, NEW_ACCOUNT_NAME);
+
+        mSyncConsentActivity = ActivityTestUtils.waitForActivity(
+                InstrumentationRegistry.getInstrumentation(), SyncConsentActivity.class, () -> {
+                    SyncConsentActivityLauncherImpl.get().launchActivityForPromoAddAccountFlow(
+                            mChromeActivityTestRule.getActivity(),
+                            SigninAccessPoint.BOOKMARK_MANAGER);
+                });
+
+        onView(withText(NEW_ACCOUNT_NAME)).check(matches(isDisplayed()));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount(
+                        "Signin.AddAccountState", State.REQUESTED));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount("Signin.AddAccountState", State.STARTED));
+        // Poll for this histogram as it's recorded asynchronously.
+        CriteriaHelper.pollUiThread(() -> {
+            return mHistogramTestRule.getHistogramValueCount(
+                           "Signin.AddAccountState", State.SUCCEEDED)
+                    == 1;
+        });
+    }
+
+    @Test
+    @LargeTest
+    @EnableFeatures({ChromeFeatureList.TANGIBLE_SYNC})
+    public void testTangibleSyncConsentFragmentAddAccountFlowSucceeded() {
+        mSigninTestRule.setResultForNextAddAccountFlow(Activity.RESULT_OK, NEW_ACCOUNT_NAME);
+
+        mSyncConsentActivity = ActivityTestUtils.waitForActivity(
+                InstrumentationRegistry.getInstrumentation(), SyncConsentActivity.class, () -> {
+                    SyncConsentActivityLauncherImpl.get().launchActivityForPromoAddAccountFlow(
+                            mChromeActivityTestRule.getActivity(),
+                            SigninAccessPoint.BOOKMARK_MANAGER);
+                });
+
+        // Wait for the added account to be visible.
+        onView(withId(R.id.sync_consent_title)).check(matches(isDisplayed()));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount(
+                        "Signin.AddAccountState", State.REQUESTED));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount("Signin.AddAccountState", State.STARTED));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount(
+                        "Signin.AddAccountState", State.SUCCEEDED));
+        assertEquals(3, mHistogramTestRule.getHistogramTotalCount("Signin.AddAccountState"));
+    }
+
+    @Test
+    @LargeTest
+    @DisableFeatures({ChromeFeatureList.TANGIBLE_SYNC})
+    public void testSyncConsentFragmentAddAccountFlowCancelled() {
+        mSigninTestRule.setResultForNextAddAccountFlow(Activity.RESULT_CANCELED, null);
+
+        mSyncConsentActivity = ActivityTestUtils.waitForActivity(
+                InstrumentationRegistry.getInstrumentation(), SyncConsentActivity.class, () -> {
+                    SyncConsentActivityLauncherImpl.get().launchActivityForPromoAddAccountFlow(
+                            mChromeActivityTestRule.getActivity(),
+                            SigninAccessPoint.BOOKMARK_MANAGER);
+                });
+
+        onView(withText(R.string.signin_add_account)).check(matches(isDisplayed()));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount(
+                        "Signin.AddAccountState", State.REQUESTED));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount("Signin.AddAccountState", State.STARTED));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount(
+                        "Signin.AddAccountState", State.CANCELLED));
+        assertEquals(3, mHistogramTestRule.getHistogramTotalCount("Signin.AddAccountState"));
+    }
+
+    @Test
+    @LargeTest
+    @EnableFeatures({ChromeFeatureList.TANGIBLE_SYNC})
+    public void testTangibleSyncConsentFragmentAddAccountFlowCancelled() {
+        mSigninTestRule.setResultForNextAddAccountFlow(Activity.RESULT_CANCELED, null);
+
+        mSyncConsentActivity = ActivityTestUtils.waitForActivity(
+                InstrumentationRegistry.getInstrumentation(), SyncConsentActivity.class, () -> {
+                    SyncConsentActivityLauncherImpl.get().launchActivityForPromoAddAccountFlow(
+                            mChromeActivityTestRule.getActivity(),
+                            SigninAccessPoint.BOOKMARK_MANAGER);
+                });
+
+        // SyncConsentActivity is destroyed if add account flow is cancelled.
+        ApplicationTestUtils.waitForActivityState(mSyncConsentActivity, Stage.DESTROYED);
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount(
+                        "Signin.AddAccountState", State.REQUESTED));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount("Signin.AddAccountState", State.STARTED));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount(
+                        "Signin.AddAccountState", State.CANCELLED));
+        assertEquals(3, mHistogramTestRule.getHistogramTotalCount("Signin.AddAccountState"));
+    }
+
+    @Test
+    @LargeTest
+    @DisableFeatures({ChromeFeatureList.TANGIBLE_SYNC})
+    public void testSyncConsentFragmentAddAccountFlowFailed() {
+        mSyncConsentActivity = ActivityTestUtils.waitForActivity(
+                InstrumentationRegistry.getInstrumentation(), SyncConsentActivity.class, () -> {
+                    SyncConsentActivityLauncherImpl.get().launchActivityForPromoAddAccountFlow(
+                            mChromeActivityTestRule.getActivity(),
+                            SigninAccessPoint.BOOKMARK_MANAGER);
+                });
+
+        // In this case the sync consent activity will be backgrounded and android settings page
+        // will be shown.
+        ApplicationTestUtils.waitForActivityState(mSyncConsentActivity, Stage.STOPPED);
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount(
+                        "Signin.AddAccountState", State.REQUESTED));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount("Signin.AddAccountState", State.FAILED));
+        assertEquals(2, mHistogramTestRule.getHistogramTotalCount("Signin.AddAccountState"));
+    }
+
+    @Test
+    @LargeTest
+    @EnableFeatures({ChromeFeatureList.TANGIBLE_SYNC})
+    public void testTangibleSyncConsentFragmentAddAccountFlowFailed() {
+        mSyncConsentActivity = ActivityTestUtils.waitForActivity(
+                InstrumentationRegistry.getInstrumentation(), SyncConsentActivity.class, () -> {
+                    SyncConsentActivityLauncherImpl.get().launchActivityForPromoAddAccountFlow(
+                            mChromeActivityTestRule.getActivity(),
+                            SigninAccessPoint.BOOKMARK_MANAGER);
+                });
+
+        // SyncConsentActivity is destroyed if add account flow fails.
+        ApplicationTestUtils.waitForActivityState(mSyncConsentActivity, Stage.DESTROYED);
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount(
+                        "Signin.AddAccountState", State.REQUESTED));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount("Signin.AddAccountState", State.FAILED));
+        assertEquals(2, mHistogramTestRule.getHistogramTotalCount("Signin.AddAccountState"));
+    }
+
+    @Test
+    @LargeTest
+    @DisableFeatures({ChromeFeatureList.TANGIBLE_SYNC})
+    public void testSyncConsentFragmentAddAccountFlowReturnedNullAccountName() {
+        mSigninTestRule.setResultForNextAddAccountFlow(Activity.RESULT_OK, null);
+
+        mSyncConsentActivity = ActivityTestUtils.waitForActivity(
+                InstrumentationRegistry.getInstrumentation(), SyncConsentActivity.class, () -> {
+                    SyncConsentActivityLauncherImpl.get().launchActivityForPromoAddAccountFlow(
+                            mChromeActivityTestRule.getActivity(),
+                            SigninAccessPoint.BOOKMARK_MANAGER);
+                });
+
+        onView(withText(R.string.signin_add_account)).check(matches(isDisplayed()));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount(
+                        "Signin.AddAccountState", State.REQUESTED));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount("Signin.AddAccountState", State.STARTED));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount(
+                        "Signin.AddAccountState", State.SUCCEEDED));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount(
+                        "Signin.AddAccountState", State.NULL_ACCOUNT_NAME));
+        assertEquals(4, mHistogramTestRule.getHistogramTotalCount("Signin.AddAccountState"));
+    }
+
+    @Test
+    @LargeTest
+    @EnableFeatures({ChromeFeatureList.TANGIBLE_SYNC})
+    public void testTangibleSyncConsentFragmentAddAccountFlowReturnedNullAccountName() {
+        mSigninTestRule.setResultForNextAddAccountFlow(Activity.RESULT_OK, null);
+
+        mSyncConsentActivity = ActivityTestUtils.waitForActivity(
+                InstrumentationRegistry.getInstrumentation(), SyncConsentActivity.class, () -> {
+                    SyncConsentActivityLauncherImpl.get().launchActivityForPromoAddAccountFlow(
+                            mChromeActivityTestRule.getActivity(),
+                            SigninAccessPoint.BOOKMARK_MANAGER);
+                });
+
+        // SyncConsentActivity is destroyed if the add account flow returns null account name.
+        ApplicationTestUtils.waitForActivityState(mSyncConsentActivity, Stage.DESTROYED);
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount(
+                        "Signin.AddAccountState", State.REQUESTED));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount("Signin.AddAccountState", State.STARTED));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount(
+                        "Signin.AddAccountState", State.SUCCEEDED));
+        assertEquals(1,
+                mHistogramTestRule.getHistogramValueCount(
+                        "Signin.AddAccountState", State.NULL_ACCOUNT_NAME));
+        assertEquals(4, mHistogramTestRule.getHistogramTotalCount("Signin.AddAccountState"));
     }
 
     private ViewAction clickOnClickableSpan() {
@@ -665,7 +888,7 @@
                             .withRootView(textView)
                             .build();
                 }
-                Assert.assertEquals("There should be only one clickable link", 1, spans.length);
+                assertEquals("There should be only one clickable link", 1, spans.length);
                 spans[0].onClick(view);
             }
         };
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationFaviconTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationFaviconTest.java
index f0405bf..24d9386 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationFaviconTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationFaviconTest.java
@@ -30,6 +30,7 @@
 import org.chromium.components.favicon.IconType;
 import org.chromium.components.favicon.LargeIconBridge;
 import org.chromium.url.GURL;
+import org.chromium.url.JUnitTestGURLs;
 
 /**
  * Test of media notifications to ensure that the favicon is displayed on normal devices and
@@ -46,6 +47,7 @@
             "--" + BaseSwitches.ENABLE_LOW_END_DEVICE_MODE;
 
     private final Bitmap mFavicon = Bitmap.createBitmap(192, 192, Bitmap.Config.ARGB_8888);
+    private GURL mFaviconUrl;
     private MediaNotificationTestTabHolder mTabHolder;
 
     // Mock LargeIconBridge that runs callback using the given favicon.
@@ -81,6 +83,7 @@
                 .when(mMockForegroundServiceUtils)
                 .startForegroundService(any(Intent.class));
         mTabHolder = createMediaNotificationTestTabHolder(TAB_ID_1, "about:blank", "title1");
+        mFaviconUrl = JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL);
     }
 
     @Override
@@ -92,7 +95,7 @@
     @Test
     public void testSetNotificationIcon() {
         mTabHolder.simulateMediaSessionStateChanged(true, false);
-        mTabHolder.simulateFaviconUpdated(mFavicon);
+        mTabHolder.simulateFaviconUpdated(mFavicon, mFaviconUrl);
         assertEquals(mFavicon, getDisplayedIcon());
     }
 
@@ -103,7 +106,7 @@
         CommandLine.init(new String[] {"testcommand", IS_LOW_END_DEVICE_SWITCH});
 
         mTabHolder.simulateMediaSessionStateChanged(true, false);
-        mTabHolder.simulateFaviconUpdated(mFavicon);
+        mTabHolder.simulateFaviconUpdated(mFavicon, mFaviconUrl);
         assertEquals(mFavicon, getDisplayedIcon());
     }
 
@@ -114,14 +117,14 @@
         CommandLine.init(new String[] {"testcommand", IS_LOW_END_DEVICE_SWITCH});
 
         mTabHolder.simulateMediaSessionStateChanged(true, false);
-        mTabHolder.simulateFaviconUpdated(mFavicon);
+        mTabHolder.simulateFaviconUpdated(mFavicon, mFaviconUrl);
         assertEquals(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? null : mFavicon,
                 getDisplayedIcon());
     }
 
     @Test
     public void testGetNullNotificationIcon() {
-        mTabHolder.simulateFaviconUpdated(null);
+        mTabHolder.simulateFaviconUpdated(null, null);
         TestLargeIconBridge largeIconBridge = new TestLargeIconBridge();
         mTabHolder.mMediaSessionTabHelper.mMediaSessionHelper.mLargeIconBridge = largeIconBridge;
 
@@ -133,7 +136,7 @@
         // Since the onFaviconUpdated was never called with valid favicon, the helper does not try
         // to fetch favicon.
         assertFalse(largeIconBridge.getIconCalledAtLeastOnce());
-        mTabHolder.simulateFaviconUpdated(mFavicon);
+        mTabHolder.simulateFaviconUpdated(mFavicon, mFaviconUrl);
 
         mTabHolder.simulateMediaSessionStateChanged(true, false);
         assertEquals(null, getDisplayedIcon());
@@ -145,7 +148,7 @@
 
     @Test
     public void testGetNotificationIcon() {
-        mTabHolder.simulateFaviconUpdated(mFavicon);
+        mTabHolder.simulateFaviconUpdated(mFavicon, mFaviconUrl);
         TestLargeIconBridge largeIconBridge = new TestLargeIconBridge();
         mTabHolder.mMediaSessionTabHelper.mMediaSessionHelper.mLargeIconBridge = largeIconBridge;
 
@@ -159,7 +162,7 @@
 
     @Test
     public void testWillReturnLargeIcon() {
-        mTabHolder.simulateFaviconUpdated(mFavicon);
+        mTabHolder.simulateFaviconUpdated(mFavicon, mFaviconUrl);
         mTabHolder.mMediaSessionTabHelper.mMediaSessionHelper.mLargeIconBridge =
                 new TestLargeIconBridge();
 
@@ -169,7 +172,7 @@
 
     @Test
     public void testNoLargeIcon() {
-        mTabHolder.simulateFaviconUpdated(null);
+        mTabHolder.simulateFaviconUpdated(null, null);
         mTabHolder.simulateMediaSessionStateChanged(true, false);
         assertNotEquals(0, getCurrentNotificationInfo().defaultNotificationLargeIcon);
     }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationTestTabHolder.java b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationTestTabHolder.java
index d9a905b..899c9f0 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationTestTabHolder.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationTestTabHolder.java
@@ -96,8 +96,8 @@
         mMediaSessionTabHelper.mMediaSessionHelper.mWebContentsObserver.titleWasSet(title);
     }
 
-    public void simulateFaviconUpdated(Bitmap icon) {
-        mMediaSessionTabHelper.mTabObserver.onFaviconUpdated(mTab, icon);
+    public void simulateFaviconUpdated(Bitmap icon, GURL iconUrl) {
+        mMediaSessionTabHelper.mTabObserver.onFaviconUpdated(mTab, icon, iconUrl);
     }
 
     public void simulateMediaSessionStateChanged(boolean isControllable, boolean isSuspended) {
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index f582230d..0d240c7 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1455,6 +1455,8 @@
     "profiles/profile_selections.h",
     "profiles/profiles_state.cc",
     "profiles/profiles_state.h",
+    "profiles/refcounted_profile_keyed_service_factory.cc",
+    "profiles/refcounted_profile_keyed_service_factory.h",
     "profiles/renderer_updater.cc",
     "profiles/renderer_updater.h",
     "profiles/renderer_updater_factory.cc",
diff --git a/chrome/browser/android/httpclient/java/src/org/chromium/chrome/browser/android/httpclient/AnnotatedSimpleHttpClient.java b/chrome/browser/android/httpclient/java/src/org/chromium/chrome/browser/android/httpclient/AnnotatedSimpleHttpClient.java
index c7b6449..ecbbcc9 100644
--- a/chrome/browser/android/httpclient/java/src/org/chromium/chrome/browser/android/httpclient/AnnotatedSimpleHttpClient.java
+++ b/chrome/browser/android/httpclient/java/src/org/chromium/chrome/browser/android/httpclient/AnnotatedSimpleHttpClient.java
@@ -18,7 +18,7 @@
  * that does not know about chrome's network stack.
  *
  */
-public class AnnotatedSimpleHttpClient implements HttpClient {
+public class AnnotatedSimpleHttpClient implements ChromeHttpClient {
     private NetworkTrafficAnnotationTag mAnnotation;
 
     public AnnotatedSimpleHttpClient(NetworkTrafficAnnotationTag annotation) {
diff --git a/chrome/browser/android/httpclient/public/BUILD.gn b/chrome/browser/android/httpclient/public/BUILD.gn
index e9112965..dad5439 100644
--- a/chrome/browser/android/httpclient/public/BUILD.gn
+++ b/chrome/browser/android/httpclient/public/BUILD.gn
@@ -6,7 +6,7 @@
 
 android_library("java") {
   sources = [
-    "src/org/chromium/chrome/browser/android/httpclient/HttpClient.java",
+    "src/org/chromium/chrome/browser/android/httpclient/ChromeHttpClient.java",
     "src/org/chromium/chrome/browser/android/httpclient/HttpResponseCallback.java",
   ]
 
diff --git a/chrome/browser/android/httpclient/public/src/org/chromium/chrome/browser/android/httpclient/HttpClient.java b/chrome/browser/android/httpclient/public/src/org/chromium/chrome/browser/android/httpclient/ChromeHttpClient.java
similarity index 92%
rename from chrome/browser/android/httpclient/public/src/org/chromium/chrome/browser/android/httpclient/HttpClient.java
rename to chrome/browser/android/httpclient/public/src/org/chromium/chrome/browser/android/httpclient/ChromeHttpClient.java
index a9796542..cf2c307 100644
--- a/chrome/browser/android/httpclient/public/src/org/chromium/chrome/browser/android/httpclient/HttpClient.java
+++ b/chrome/browser/android/httpclient/public/src/org/chromium/chrome/browser/android/httpclient/ChromeHttpClient.java
@@ -7,7 +7,7 @@
 import java.util.Map;
 
 /** A simple HttpClient interface. */
-public interface HttpClient {
+public interface ChromeHttpClient {
     void send(String url, String requestType, byte[] body, Map<String, String> headers,
             HttpResponseCallback responseCallback);
 }
diff --git a/chrome/browser/android/tab_favicon.cc b/chrome/browser/android/tab_favicon.cc
index 92f0436..08c5616 100644
--- a/chrome/browser/android/tab_favicon.cc
+++ b/chrome/browser/android/tab_favicon.cc
@@ -14,6 +14,7 @@
 #include "ui/gfx/favicon_size.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/image/image_skia_rep.h"
+#include "url/android/gurl_android.h"
 
 using base::android::JavaParamRef;
 using base::android::ScopedJavaLocalRef;
@@ -85,8 +86,10 @@
     return;
 
   JNIEnv* env = base::android::AttachCurrentThread();
-  Java_TabFavicon_onFaviconAvailable(env, jobj_,
-                                     gfx::ConvertToJavaBitmap(favicon));
+  ScopedJavaLocalRef<jobject> j_icon_url =
+      url::GURLAndroid::FromNativeGURL(env, icon_url);
+  Java_TabFavicon_onFaviconAvailable(
+      env, jobj_, gfx::ConvertToJavaBitmap(favicon), j_icon_url);
 }
 
 static jlong JNI_TabFavicon_Init(JNIEnv* env,
diff --git a/chrome/browser/ash/dbus/dlp_files_policy_service_provider.cc b/chrome/browser/ash/dbus/dlp_files_policy_service_provider.cc
index f54b2e9..432d2cf 100644
--- a/chrome/browser/ash/dbus/dlp_files_policy_service_provider.cc
+++ b/chrome/browser/ash/dbus/dlp_files_policy_service_provider.cc
@@ -74,8 +74,16 @@
     return;
   }
 
+  policy::DlpRulesManager* rules_manager =
+      policy::DlpRulesManagerFactory::GetForPrimaryProfile();
+  DCHECK(rules_manager);
+  policy::DlpFilesController* files_controller =
+      rules_manager->GetDlpFilesController();
+
   bool restricted =
-      dlp_files_controller_.IsDlpPolicyMatched(request.source_url());
+      files_controller
+          ? files_controller->IsDlpPolicyMatched(request.source_url())
+          : false;
 
   dlp::IsDlpPolicyMatchedResponse response_proto;
   response_proto.set_restricted(restricted);
@@ -113,13 +121,24 @@
   Profile* profile = ProfileManager::GetPrimaryUserProfile();
   DCHECK(profile);
 
-  dlp_files_controller_.IsFilesTransferRestricted(
-      profile, source_urls, request.destination_url(),
-      policy::DlpWarnDialog::FilesAction::kTransfer,
-      base::BindOnce(
-          &DlpFilesPolicyServiceProvider::RespondWithRestrictedFilesTransfer,
-          weak_ptr_factory_.GetWeakPtr(), method_call,
-          std::move(response_sender)));
+  policy::DlpRulesManager* rules_manager =
+      policy::DlpRulesManagerFactory::GetForPrimaryProfile();
+  DCHECK(rules_manager);
+  policy::DlpFilesController* files_controller =
+      rules_manager->GetDlpFilesController();
+
+  if (files_controller) {
+    files_controller->IsFilesTransferRestricted(
+        profile, source_urls, request.destination_url(),
+        policy::DlpWarnDialog::FilesAction::kTransfer,
+        base::BindOnce(
+            &DlpFilesPolicyServiceProvider::RespondWithRestrictedFilesTransfer,
+            weak_ptr_factory_.GetWeakPtr(), method_call,
+            std::move(response_sender)));
+  } else {
+    RespondWithRestrictedFilesTransfer(method_call, std::move(response_sender),
+                                       std::vector<GURL>());
+  }
 }
 
 void DlpFilesPolicyServiceProvider::RespondWithRestrictedFilesTransfer(
diff --git a/chrome/browser/ash/dbus/dlp_files_policy_service_provider.h b/chrome/browser/ash/dbus/dlp_files_policy_service_provider.h
index 917fbf6c..e95234e 100644
--- a/chrome/browser/ash/dbus/dlp_files_policy_service_provider.h
+++ b/chrome/browser/ash/dbus/dlp_files_policy_service_provider.h
@@ -9,10 +9,11 @@
 
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
-#include "chrome/browser/ash/policy/dlp/dlp_files_controller.h"
 #include "chromeos/ash/components/dbus/services/cros_dbus_service.h"
 #include "dbus/exported_object.h"
 
+class GURL;
+
 namespace dbus {
 class MethodCall;
 }  // namespace dbus
@@ -53,10 +54,6 @@
       dbus::ExportedObject::ResponseSender response_sender,
       const std::vector<GURL>& restricted_sources);
 
-  // DlpFilesController is responsible for checking whether any of the selected
-  // files is restricted according to the DataLeakPrevention policy.
-  policy::DlpFilesController dlp_files_controller_;
-
   base::WeakPtrFactory<DlpFilesPolicyServiceProvider> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/ash/dbus/dlp_files_policy_service_provider_unittest.cc b/chrome/browser/ash/dbus/dlp_files_policy_service_provider_unittest.cc
index 40f3961..e575f6a 100644
--- a/chrome/browser/ash/dbus/dlp_files_policy_service_provider_unittest.cc
+++ b/chrome/browser/ash/dbus/dlp_files_policy_service_provider_unittest.cc
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/dbus/dlp_files_policy_service_provider.h"
+#include <memory>
 
+#include "chrome/browser/ash/dbus/dlp_files_policy_service_provider.h"
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
+#include "chrome/browser/ash/policy/dlp/dlp_files_controller.h"
 #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h"
 #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h"
 #include "chrome/browser/chromeos/policy/dlp/mock_dlp_rules_manager.h"
@@ -100,6 +102,10 @@
     mock_rules_manager_ = dlp_rules_manager.get();
     ON_CALL(*mock_rules_manager_, IsFilesPolicyEnabled)
         .WillByDefault(testing::Return(true));
+
+    files_controller_ =
+        std::make_unique<policy::DlpFilesController>(*mock_rules_manager_);
+
     return dlp_rules_manager;
   }
 
@@ -113,6 +119,8 @@
 
   std::unique_ptr<DlpFilesPolicyServiceProvider> dlp_policy_service_;
   ServiceProviderTestHelper dbus_service_test_helper_;
+
+  std::unique_ptr<policy::DlpFilesController> files_controller_;
 };
 
 INSTANTIATE_TEST_SUITE_P(
@@ -132,6 +140,10 @@
                             policy::DlpRulesManager::Restriction::kFiles))
       .WillOnce(testing::Return(level));
 
+  EXPECT_CALL(*mock_rules_manager_, GetDlpFilesController())
+      .Times(::testing::AnyNumber())
+      .WillOnce(::testing::Return(files_controller_.get()));
+
   auto response =
       CallDlpFilesPolicyServiceMethod<dlp::IsDlpPolicyMatchedResponse>(
           dlp::kDlpFilesPolicyServiceIsDlpPolicyMatchedMethod, request);
diff --git a/chrome/browser/ash/file_manager/file_browser_handlers.cc b/chrome/browser/ash/file_manager/file_browser_handlers.cc
index d87bb2e..ecf9050 100644
--- a/chrome/browser/ash/file_manager/file_browser_handlers.cc
+++ b/chrome/browser/ash/file_manager/file_browser_handlers.cc
@@ -57,55 +57,10 @@
 using file_manager::util::FileDefinitionList;
 using storage::FileSystemURL;
 
-namespace file_manager {
-namespace file_browser_handlers {
+namespace file_manager::file_browser_handlers {
+
 namespace {
 
-std::string EscapedUtf8ToLower(const std::string& str) {
-  std::u16string utf16 = base::UTF8ToUTF16(
-      base::UnescapeURLComponent(str, base::UnescapeRule::NORMAL));
-  return base::EscapeUrlEncodedData(
-      base::UTF16ToUTF8(base::i18n::ToLower(utf16)),
-      false /* do not replace space with plus */);
-}
-
-// Finds file browser handlers that can handle the |selected_file_url|.
-FileBrowserHandlerList FindFileBrowserHandlersForURL(
-    Profile* profile,
-    const GURL& selected_file_url) {
-  extensions::ExtensionRegistry* registry =
-      extensions::ExtensionRegistry::Get(profile);
-  // In unit-tests, we may not have an ExtensionRegistry.
-  if (!registry)
-    return FileBrowserHandlerList();
-
-  // We need case-insensitive matching, and pattern in the handler is already
-  // in lower case.
-  const GURL lowercase_url(EscapedUtf8ToLower(selected_file_url.spec()));
-
-  FileBrowserHandlerList results;
-  for (const scoped_refptr<const Extension>& extension :
-       registry->enabled_extensions()) {
-    if (profile->IsOffTheRecord() &&
-        !extensions::util::IsIncognitoEnabled(extension->id(), profile))
-      continue;
-    FileBrowserHandler::List* handler_list =
-        FileBrowserHandler::GetHandlers(extension.get());
-    if (!handler_list)
-      continue;
-    for (FileBrowserHandler::List::const_iterator handler_iter =
-             handler_list->begin();
-         handler_iter != handler_list->end(); ++handler_iter) {
-      const FileBrowserHandler* handler = handler_iter->get();
-      if (!handler->MatchesURL(lowercase_url))
-        continue;
-
-      results.push_back(handler);
-    }
-  }
-  return results;
-}
-
 // This class is used to execute a file browser handler task. Here's how this
 // works:
 //
@@ -393,43 +348,4 @@
   return true;
 }
 
-FileBrowserHandlerList FindFileBrowserHandlers(
-    Profile* profile,
-    const std::vector<GURL>& file_list) {
-  FileBrowserHandlerList common_handlers;
-  for (std::vector<GURL>::const_iterator it = file_list.begin();
-       it != file_list.end(); ++it) {
-    FileBrowserHandlerList handlers =
-        FindFileBrowserHandlersForURL(profile, *it);
-    // If there is nothing to do for one file, the intersection of handlers
-    // for all files will be empty at the end, so no need to check further.
-    if (handlers.empty())
-      return FileBrowserHandlerList();
-
-    // For the very first file, just copy all the elements.
-    if (it == file_list.begin()) {
-      common_handlers = handlers;
-    } else {
-      // For all additional files, find intersection between the accumulated and
-      // file specific set.
-      FileBrowserHandlerList intersection;
-      std::set<const FileBrowserHandler*> common_handler_set(
-          common_handlers.begin(), common_handlers.end());
-
-      for (FileBrowserHandlerList::const_iterator itr = handlers.begin();
-           itr != handlers.end(); ++itr) {
-        if (base::Contains(common_handler_set, *itr))
-          intersection.push_back(*itr);
-      }
-
-      std::swap(common_handlers, intersection);
-      if (common_handlers.empty())
-        return FileBrowserHandlerList();
-    }
-  }
-
-  return common_handlers;
-}
-
-}  // namespace file_browser_handlers
-}  // namespace file_manager
+}  // namespace file_manager::file_browser_handlers
diff --git a/chrome/browser/ash/file_manager/file_browser_handlers.h b/chrome/browser/ash/file_manager/file_browser_handlers.h
index d0ad6ed..fa21c656 100644
--- a/chrome/browser/ash/file_manager/file_browser_handlers.h
+++ b/chrome/browser/ash/file_manager/file_browser_handlers.h
@@ -14,8 +14,6 @@
 #include "base/callback_forward.h"
 #include "chrome/browser/ash/file_manager/file_tasks.h"
 
-class FileBrowserHandler;
-class GURL;
 class Profile;
 
 namespace extensions {
@@ -26,17 +24,7 @@
 class FileSystemURL;
 }
 
-namespace file_manager {
-namespace file_browser_handlers {
-
-// Tasks are stored as a vector in order of priorities.
-typedef std::vector<const FileBrowserHandler*> FileBrowserHandlerList;
-
-// Returns the list of file browser handlers that can open all files in
-// |file_list|.
-FileBrowserHandlerList FindFileBrowserHandlers(
-    Profile* profile,
-    const std::vector<GURL>& file_list);
+namespace file_manager::file_browser_handlers {
 
 // Executes a file browser handler specified by |extension| of the given
 // action ID for |file_urls|. Returns false if undeclared handlers are
@@ -49,7 +37,6 @@
     const std::vector<storage::FileSystemURL>& file_urls,
     file_tasks::FileTaskFinishedCallback done);
 
-}  // namespace file_browser_handlers
-}  // namespace file_manager
+}  // namespace file_manager::file_browser_handlers
 
 #endif  // CHROME_BROWSER_ASH_FILE_MANAGER_FILE_BROWSER_HANDLERS_H_
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest.cc b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
index da77b98..757b2cff 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include <stddef.h>
+#include <memory>
 
 #include "ash/constants/ash_switches.h"
 #include "ash/public/cpp/keyboard/keyboard_switches.h"
@@ -10,6 +11,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/ash/file_manager/file_manager_browsertest_base.h"
+#include "chrome/browser/ash/policy/dlp/dlp_files_controller.h"
 #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h"
 #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h"
 #include "chrome/browser/chromeos/policy/dlp/mock_dlp_rules_manager.h"
@@ -311,6 +313,12 @@
     mock_rules_manager_ = dlp_rules_manager.get();
     ON_CALL(*mock_rules_manager_, IsFilesPolicyEnabled)
         .WillByDefault(testing::Return(true));
+
+    files_controller_ =
+        std::make_unique<policy::DlpFilesController>(*mock_rules_manager_);
+    ON_CALL(*mock_rules_manager_, GetDlpFilesController)
+        .WillByDefault(testing::Return(files_controller_.get()));
+
     return dlp_rules_manager;
   }
 
@@ -352,6 +360,8 @@
   // MockDlpRulesManager is owned by KeyedService and is guaranteed to outlive
   // this class.
   policy::MockDlpRulesManager* mock_rules_manager_ = nullptr;
+
+  std::unique_ptr<policy::DlpFilesController> files_controller_;
 };
 
 IN_PROC_BROWSER_TEST_P(DlpFilesAppBrowserTest, Test) {
diff --git a/chrome/browser/ash/file_manager/file_tasks.cc b/chrome/browser/ash/file_manager/file_tasks.cc
index 67524a8..86557ba 100644
--- a/chrome/browser/ash/file_manager/file_tasks.cc
+++ b/chrome/browser/ash/file_manager/file_tasks.cc
@@ -765,37 +765,6 @@
   return false;
 }
 
-void FindFileBrowserHandlerTasks(Profile* profile,
-                                 const std::vector<GURL>& file_urls,
-                                 std::vector<FullTaskDescriptor>* result_list) {
-  DCHECK(!file_urls.empty());
-  DCHECK(result_list);
-
-  file_browser_handlers::FileBrowserHandlerList common_tasks =
-      file_browser_handlers::FindFileBrowserHandlers(profile, file_urls);
-  if (common_tasks.empty())
-    return;
-
-  const extensions::ExtensionSet& enabled_extensions =
-      extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
-  for (const FileBrowserHandler* handler : common_tasks) {
-    const std::string extension_id = handler->extension_id();
-    const Extension* extension = enabled_extensions.GetByID(extension_id);
-    DCHECK(extension);
-
-    // TODO(zelidrag): Figure out how to expose icon URL that task defined in
-    // manifest instead of the default extension icon.
-    const GURL icon_url = GetIconURL(profile, *extension);
-
-    result_list->push_back(FullTaskDescriptor(
-        TaskDescriptor(extension_id, file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER,
-                       handler->id()),
-        handler->title(), Verb::VERB_NONE /* no verb for FileBrowserHandler */,
-        icon_url, false /* is_default */, false /* is_generic_file_handler */,
-        false /* is_file_extension_match */));
-  }
-}
-
 void FindExtensionAndAppTasks(
     Profile* profile,
     const std::vector<extensions::EntryInfo>& entries,
diff --git a/chrome/browser/ash/file_manager/file_tasks.h b/chrome/browser/ash/file_manager/file_tasks.h
index 3629acb0..0bf27aa 100644
--- a/chrome/browser/ash/file_manager/file_tasks.h
+++ b/chrome/browser/ash/file_manager/file_tasks.h
@@ -302,13 +302,6 @@
                      const std::vector<storage::FileSystemURL>& file_urls,
                      FileTaskFinishedCallback done);
 
-// Finds the file browser handler tasks (app/extensions declaring
-// "file_browser_handlers" in manifest.json) that can be used with the
-// given files, appending them to the |result_list|.
-void FindFileBrowserHandlerTasks(Profile* profile,
-                                 const std::vector<GURL>& file_urls,
-                                 std::vector<FullTaskDescriptor>* result_list);
-
 // Callback function type for FindAllTypesOfTasks.
 typedef base::OnceCallback<void(
     std::unique_ptr<std::vector<FullTaskDescriptor>> result)>
diff --git a/chrome/browser/ash/file_manager/file_tasks_unittest.cc b/chrome/browser/ash/file_manager/file_tasks_unittest.cc
index c49f1e64..13fd405e 100644
--- a/chrome/browser/ash/file_manager/file_tasks_unittest.cc
+++ b/chrome/browser/ash/file_manager/file_tasks_unittest.cc
@@ -544,96 +544,6 @@
   extensions::ExtensionService* extension_service_;  // Owned by test_profile_;
 };
 
-// The basic logic is similar to a test case for FindFileHandlerTasks above.
-TEST_F(FileManagerFileTasksComplexTest, FindFileBrowserHandlerTasks) {
-  // Copied from FindFileHandlerTasks test above.
-  const char kFooId[] = "hhgbjpmdppecanaaogonaigmmifgpaph";
-  const char kBarId[] = "odlhccgofgkadkkhcmhgnhgahonahoca";
-
-  // Foo.app can handle ".txt" and ".html".
-  // This one is an extension, and has "file_browser_handlers"
-  extensions::ExtensionBuilder foo_app;
-  foo_app.SetManifest(
-      extensions::DictionaryBuilder()
-          .Set("name", "Foo")
-          .Set("version", "1.0.0")
-          .Set("manifest_version", 2)
-          .Set("permissions",
-               extensions::ListBuilder().Append("fileBrowserHandler").Build())
-          .Set("file_browser_handlers",
-               extensions::ListBuilder()
-                   .Append(
-                       extensions::DictionaryBuilder()
-                           .Set("id", "open")
-                           .Set("default_title", "open")
-                           .Set("file_filters", extensions::ListBuilder()
-                                                    .Append("filesystem:*.txt")
-                                                    .Append("filesystem:*.html")
-                                                    .Build())
-                           .Build())
-                   .Build())
-          .Build());
-  foo_app.SetID(kFooId);
-  extension_service_->AddExtension(foo_app.Build().get());
-
-  // Bar.app can only handle ".txt".
-  extensions::ExtensionBuilder bar_app;
-  bar_app.SetManifest(
-      extensions::DictionaryBuilder()
-          .Set("name", "Bar")
-          .Set("version", "1.0.0")
-          .Set("manifest_version", 2)
-          .Set("permissions",
-               extensions::ListBuilder().Append("fileBrowserHandler").Build())
-          .Set("file_browser_handlers",
-               extensions::ListBuilder()
-                   .Append(
-                       extensions::DictionaryBuilder()
-                           .Set("id", "open")
-                           .Set("default_title", "open")
-                           .Set("file_filters", extensions::ListBuilder()
-                                                    .Append("filesystem:*.txt")
-                                                    .Build())
-                           .Build())
-                   .Build())
-          .Build());
-  bar_app.SetID(kBarId);
-  extension_service_->AddExtension(bar_app.Build().get());
-
-  // Find apps for a ".txt" file. Foo.app and Bar.app should be found.
-  std::vector<GURL> file_urls;
-  file_urls.emplace_back("filesystem:chrome-extension://id/dir/foo.txt");
-
-  std::vector<FullTaskDescriptor> tasks;
-  FindFileBrowserHandlerTasks(test_profile_.get(), file_urls, &tasks);
-  ASSERT_EQ(2U, tasks.size());
-  // Sort the app IDs, as the order is not guaranteed.
-  std::vector<std::string> app_ids;
-  app_ids.push_back(tasks[0].task_descriptor.app_id);
-  app_ids.push_back(tasks[1].task_descriptor.app_id);
-  std::sort(app_ids.begin(), app_ids.end());
-  // Confirm that both Foo.app and Bar.app are found.
-  EXPECT_EQ(kFooId, app_ids[0]);
-  EXPECT_EQ(kBarId, app_ids[1]);
-
-  // Find apps for ".txt" and ".html" files. Only Foo.app should be found.
-  file_urls.clear();
-  file_urls.emplace_back("filesystem:chrome-extension://id/dir/foo.txt");
-  file_urls.emplace_back("filesystem:chrome-extension://id/dir/foo.html");
-  tasks.clear();
-  FindFileBrowserHandlerTasks(test_profile_.get(), file_urls, &tasks);
-  ASSERT_EQ(1U, tasks.size());
-  // Confirm that only Foo.app is found.
-  EXPECT_EQ(kFooId, tasks[0].task_descriptor.app_id);
-
-  // Add an ".png" file. No tasks should be found.
-  file_urls.emplace_back("filesystem:chrome-extension://id/dir/foo.png");
-  tasks.clear();
-  FindFileBrowserHandlerTasks(test_profile_.get(), file_urls, &tasks);
-  // Confirm no tasks are found.
-  ASSERT_TRUE(tasks.empty());
-}
-
 // Test using the test extension system, which needs lots of setup.
 class FileManagerFileTasksCrostiniTest
     : public FileManagerFileTasksComplexTest {
diff --git a/chrome/browser/ash/login/session/user_session_initializer.cc b/chrome/browser/ash/login/session/user_session_initializer.cc
index 8ad004a..992e72f 100644
--- a/chrome/browser/ash/login/session/user_session_initializer.cc
+++ b/chrome/browser/ash/login/session/user_session_initializer.cc
@@ -40,6 +40,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/ash/calendar/calendar_keyed_service_factory.h"
 #include "chrome/browser/ui/ash/clipboard_image_model_factory_impl.h"
+#include "chrome/browser/ui/ash/glanceables/chrome_glanceables_delegate.h"
 #include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service_factory.h"
 #include "chrome/browser/ui/ash/media_client_impl.h"
 #include "chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.h"
@@ -252,6 +253,11 @@
   if (is_primary_user) {
     DCHECK_EQ(primary_profile_, profile);
 
+    if (ash::features::AreGlanceablesEnabled()) {
+      // Must be called after CalenderKeyedServiceFactory is initialized.
+      ChromeGlanceablesDelegate::Get()->OnPrimaryUserSessionStarted();
+    }
+
     // Ensure that PhoneHubManager and EcheAppManager are created for the
     // primary profile.
     phonehub::PhoneHubManagerFactory::GetForProfile(profile);
diff --git a/chrome/browser/ash/policy/dlp/data_transfer_dlp_controller_ash_browsertest.cc b/chrome/browser/ash/policy/dlp/data_transfer_dlp_controller_ash_browsertest.cc
index 000bfc0..b727c105 100644
--- a/chrome/browser/ash/policy/dlp/data_transfer_dlp_controller_ash_browsertest.cc
+++ b/chrome/browser/ash/policy/dlp/data_transfer_dlp_controller_ash_browsertest.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/ash/crostini/crostini_util.h"
 #include "chrome/browser/ash/crostini/fake_crostini_features.h"
 #include "chrome/browser/ash/policy/core/user_policy_test_helper.h"
+#include "chrome/browser/ash/policy/dlp/dlp_files_controller.h"
 #include "chrome/browser/ash/policy/login/login_policy_test_base.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.h"
@@ -146,6 +147,7 @@
   ~MockDlpRulesManager() override = default;
 
   MOCK_CONST_METHOD0(GetReportingManager, DlpReportingManager*());
+  MOCK_CONST_METHOD0(GetDlpFilesController, DlpFilesController*());
 };
 
 void SetClipboardText(std::u16string text,
@@ -186,6 +188,10 @@
     ON_CALL(*rules_manager_, GetReportingManager)
         .WillByDefault(::testing::Return(reporting_manager_.get()));
 
+    files_controller_ = std::make_unique<DlpFilesController>(*rules_manager_);
+    ON_CALL(*rules_manager_, GetDlpFilesController)
+        .WillByDefault(::testing::Return(files_controller_.get()));
+
     dlp_controller_ =
         std::make_unique<FakeDlpController>(*rules_manager_, &helper_);
   }
@@ -202,6 +208,7 @@
   void TearDownOnMainThread() override {
     dlp_controller_.reset();
     reporting_manager_.reset();
+    files_controller_.reset();
   }
 
   void SetupCrostini() {
@@ -226,6 +233,7 @@
   std::vector<DlpPolicyEvent> events;
   FakeClipboardNotifier helper_;
   std::unique_ptr<FakeDlpController> dlp_controller_;
+  std::unique_ptr<DlpFilesController> files_controller_;
 };
 
 // Flaky on MSan bots: http://crbug.com/1178328
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_controller.cc b/chrome/browser/ash/policy/dlp/dlp_files_controller.cc
index 897e87790..4bfa04e 100644
--- a/chrome/browser/ash/policy/dlp/dlp_files_controller.cc
+++ b/chrome/browser/ash/policy/dlp/dlp_files_controller.cc
@@ -19,6 +19,7 @@
 #include "base/ranges/algorithm.h"
 #include "chrome/browser/ash/drive/drive_integration_service.h"
 #include "chrome/browser/ash/file_manager/path_util.h"
+#include "chrome/browser/chromeos/policy/dlp/dlp_reporting_manager.h"
 #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h"
 #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h"
 #include "chrome/browser/chromeos/policy/dlp/dlp_warn_dialog.h"
@@ -99,8 +100,9 @@
 DlpFilesController::DlpFileRestrictionDetails::~DlpFileRestrictionDetails() =
     default;
 
-DlpFilesController::DlpFilesController()
-    : warn_notifier_(std::make_unique<DlpWarnNotifier>()) {}
+DlpFilesController::DlpFilesController(const DlpRulesManager& rules_manager)
+    : rules_manager_(rules_manager),
+      warn_notifier_(std::make_unique<DlpWarnNotifier>()) {}
 
 DlpFilesController::~DlpFilesController() = default;
 
@@ -199,12 +201,6 @@
     DlpWarnDialog::FilesAction files_action,
     IsFilesTransferRestrictedCallback result_callback) {
   DCHECK(profile);
-  policy::DlpRulesManager* dlp_rules_manager =
-      policy::DlpRulesManagerFactory::GetForPrimaryProfile();
-  if (!dlp_rules_manager) {
-    std::move(result_callback).Run(std::vector<GURL>());
-    return;
-  }
 
   auto dst_component =
       MapFilePathtoPolicyComponent(profile, base::FilePath(destination));
@@ -213,13 +209,13 @@
   for (const auto& src : files_sources) {
     DlpRulesManager::Level level;
     if (dst_component.has_value()) {
-      level = dlp_rules_manager->IsRestrictedComponent(
+      level = rules_manager_.IsRestrictedComponent(
           src, dst_component.value(), DlpRulesManager::Restriction::kFiles,
           nullptr);
     } else {
       // TODO(crbug.com/1286366): Revisit whether passing files paths here make
       // sense.
-      level = dlp_rules_manager->IsRestrictedDestination(
+      level = rules_manager_.IsRestrictedDestination(
           src, GURL(destination), DlpRulesManager::Restriction::kFiles, nullptr,
           nullptr);
     }
@@ -258,18 +254,12 @@
 
 std::vector<DlpFilesController::DlpFileRestrictionDetails>
 DlpFilesController::GetDlpRestrictionDetails(const std::string& sourceUrl) {
-  policy::DlpRulesManager* dlp_rules_manager =
-      policy::DlpRulesManagerFactory::GetForPrimaryProfile();
-  if (!dlp_rules_manager) {
-    return {};
-  }
-
   const GURL source(sourceUrl);
   const DlpRulesManager::AggregatedDestinations aggregated_destinations =
-      dlp_rules_manager->GetAggregatedDestinations(
+      rules_manager_.GetAggregatedDestinations(
           source, DlpRulesManager::Restriction::kFiles);
   const DlpRulesManager::AggregatedComponents aggregated_components =
-      dlp_rules_manager->GetAggregatedComponents(
+      rules_manager_.GetAggregatedComponents(
           source, DlpRulesManager::Restriction::kFiles);
 
   std::vector<DlpFilesController::DlpFileRestrictionDetails> result;
@@ -307,23 +297,21 @@
 
 bool DlpFilesController::IsDlpPolicyMatched(const std::string& source_url) {
   bool restricted = false;
-  policy::DlpRulesManager* dlp_rules_manager =
-      policy::DlpRulesManagerFactory::GetForPrimaryProfile();
-  if (dlp_rules_manager) {
-    policy::DlpRulesManager::Level level =
-        dlp_rules_manager->IsRestrictedByAnyRule(
-            GURL(source_url), policy::DlpRulesManager::Restriction::kFiles);
 
-    switch (level) {
-      case policy::DlpRulesManager::Level::kBlock:
-        restricted = true;
-        break;
-      case policy::DlpRulesManager::Level::kWarn:
-        // TODO(crbug.com/1172959): Implement Warning mode for Files restriction
-        break;
-      default:;
-    }
+  policy::DlpRulesManager::Level level = rules_manager_.IsRestrictedByAnyRule(
+      GURL(source_url), policy::DlpRulesManager::Restriction::kFiles);
+
+  switch (level) {
+    case policy::DlpRulesManager::Level::kBlock:
+      restricted = true;
+      break;
+    case policy::DlpRulesManager::Level::kWarn:
+      // TODO(crbug.com/1172959): Implement Warning mode for Files restriction
+      break;
+    default:
+      break;
   }
+
   return restricted;
 }
 
@@ -375,22 +363,15 @@
 void DlpFilesController::ReturnDlpMetadata(
     std::vector<absl::optional<ino_t>> inodes,
     GetDlpMetadataCallback result_callback,
-    const dlp::GetFilesSourcesResponse response) {
+    const ::dlp::GetFilesSourcesResponse response) {
   if (response.has_error_message()) {
     LOG(ERROR) << "Failed to get files sources, error: "
                << response.error_message();
   }
 
-  policy::DlpRulesManager* dlp_rules_manager =
-      policy::DlpRulesManagerFactory::GetForPrimaryProfile();
-  if (!dlp_rules_manager) {
-    std::move(result_callback).Run(std::vector<DlpFileMetadata>());
-    return;
-  }
-
   base::flat_map<ino_t, DlpFileMetadata> metadata_map;
   for (const auto& metadata : response.files_metadata()) {
-    DlpRulesManager::Level level = dlp_rules_manager->IsRestrictedByAnyRule(
+    DlpRulesManager::Level level = rules_manager_.IsRestrictedByAnyRule(
         GURL(metadata.source_url()), DlpRulesManager::Restriction::kFiles);
     bool is_dlp_restricted = level != DlpRulesManager::Level::kNotSet &&
                              level != DlpRulesManager::Level::kAllow;
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_controller.h b/chrome/browser/ash/policy/dlp/dlp_files_controller.h
index 55d15fa..1b0976e 100644
--- a/chrome/browser/ash/policy/dlp/dlp_files_controller.h
+++ b/chrome/browser/ash/policy/dlp/dlp_files_controller.h
@@ -81,7 +81,7 @@
   using IsFilesTransferRestrictedCallback =
       base::OnceCallback<void(const std::vector<GURL>&)>;
 
-  DlpFilesController();
+  explicit DlpFilesController(const DlpRulesManager& rules_manager);
   DlpFilesController(const DlpFilesController& other) = delete;
   DlpFilesController& operator=(const DlpFilesController& other) = delete;
 
@@ -143,7 +143,9 @@
       dlp::CheckFilesTransferResponse response);
   void ReturnDlpMetadata(std::vector<absl::optional<ino_t>> inodes,
                          GetDlpMetadataCallback result_callback,
-                         const dlp::GetFilesSourcesResponse response);
+                         const ::dlp::GetFilesSourcesResponse response);
+
+  const DlpRulesManager& rules_manager_;
 
   // Is used for creating and showing the warning dialog.
   std::unique_ptr<DlpWarnNotifier> warn_notifier_;
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_controller_unittest.cc b/chrome/browser/ash/policy/dlp/dlp_files_controller_unittest.cc
index 14031e01..8d462ef0 100644
--- a/chrome/browser/ash/policy/dlp/dlp_files_controller_unittest.cc
+++ b/chrome/browser/ash/policy/dlp/dlp_files_controller_unittest.cc
@@ -125,6 +125,11 @@
       content::BrowserContext* context) {
     auto dlp_rules_manager = std::make_unique<MockDlpRulesManager>();
     rules_manager_ = dlp_rules_manager.get();
+
+    files_controller_ = std::make_unique<DlpFilesController>(*rules_manager_);
+    ON_CALL(*rules_manager_, GetDlpFilesController)
+        .WillByDefault(::testing::Return(files_controller_.get()));
+
     return dlp_rules_manager;
   }
 
@@ -185,7 +190,7 @@
   std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_;
 
   MockDlpRulesManager* rules_manager_ = nullptr;
-  DlpFilesController files_controller_;
+  std::unique_ptr<DlpFilesController> files_controller_;
 
   scoped_refptr<storage::FileSystemContext> file_system_context_;
 
@@ -228,7 +233,12 @@
       base::FilePath("file.rar/path/in/archive"));
 
   base::test::TestFuture<std::vector<storage::FileSystemURL>> future;
-  files_controller_.GetDisallowedTransfers(transferred_files, dst_url,
+
+  ASSERT_TRUE(rules_manager_);
+  DlpFilesController* files_controller =
+      rules_manager_->GetDlpFilesController();
+  ASSERT_TRUE(files_controller);
+  files_controller->GetDisallowedTransfers(transferred_files, dst_url,
                                            future.GetCallback());
   EXPECT_TRUE(future.Wait());
   EXPECT_EQ(disallowed_files, future.Take());
@@ -241,7 +251,11 @@
       {file_url1_, file_url2_, file_url3_});
 
   base::test::TestFuture<std::vector<storage::FileSystemURL>> future;
-  files_controller_.GetDisallowedTransfers(transferred_files,
+  ASSERT_TRUE(rules_manager_);
+  DlpFilesController* files_controller =
+      rules_manager_->GetDlpFilesController();
+  ASSERT_TRUE(files_controller);
+  files_controller->GetDisallowedTransfers(transferred_files,
                                            CreateFileSystemURL("Downloads"),
                                            future.GetCallback());
   EXPECT_EQ(0u, future.Get().size());
@@ -269,7 +283,11 @@
 
   chromeos::DlpClient::Get()->GetTestInterface()->SetIsAlive(false);
   base::test::TestFuture<std::vector<storage::FileSystemURL>> future;
-  files_controller_.GetDisallowedTransfers(transferred_files, dst_url,
+  ASSERT_TRUE(rules_manager_);
+  DlpFilesController* files_controller =
+      rules_manager_->GetDlpFilesController();
+  ASSERT_TRUE(files_controller);
+  files_controller->GetDisallowedTransfers(transferred_files, dst_url,
                                            future.GetCallback());
   EXPECT_EQ(0u, future.Get().size());
 }
@@ -282,7 +300,12 @@
   dlp::CheckFilesTransferResponse check_files_transfer_response;
 
   base::test::TestFuture<std::vector<FileChooserFileInfoPtr>> future;
-  files_controller_.FilterDisallowedUploads(std::move(uploaded_files),
+
+  ASSERT_TRUE(rules_manager_);
+  DlpFilesController* files_controller =
+      rules_manager_->GetDlpFilesController();
+  ASSERT_TRUE(files_controller);
+  files_controller->FilterDisallowedUploads(std::move(uploaded_files),
                                             GURL("https://example.com"),
                                             future.GetCallback());
 
@@ -304,7 +327,11 @@
       FileChooserFileInfo::NewFileSystem(FileSystemFileInfo::New()));
 
   base::test::TestFuture<std::vector<FileChooserFileInfoPtr>> future;
-  files_controller_.FilterDisallowedUploads(std::move(uploaded_files),
+  ASSERT_TRUE(rules_manager_);
+  DlpFilesController* files_controller =
+      rules_manager_->GetDlpFilesController();
+  ASSERT_TRUE(files_controller);
+  files_controller->FilterDisallowedUploads(std::move(uploaded_files),
                                             GURL("https://example.com"),
                                             future.GetCallback());
 
@@ -343,7 +370,11 @@
       check_files_transfer_response);
 
   base::test::TestFuture<std::vector<FileChooserFileInfoPtr>> future;
-  files_controller_.FilterDisallowedUploads(std::move(uploaded_files),
+  ASSERT_TRUE(rules_manager_);
+  DlpFilesController* files_controller =
+      rules_manager_->GetDlpFilesController();
+  ASSERT_TRUE(files_controller);
+  files_controller->FilterDisallowedUploads(std::move(uploaded_files),
                                             GURL("https://example.com"),
                                             future.GetCallback());
 
@@ -376,7 +407,11 @@
 
   base::test::TestFuture<std::vector<DlpFilesController::DlpFileMetadata>>
       future;
-  files_controller_.GetDlpMetadata(files_to_check, future.GetCallback());
+  ASSERT_TRUE(rules_manager_);
+  DlpFilesController* files_controller =
+      rules_manager_->GetDlpFilesController();
+  ASSERT_TRUE(files_controller);
+  files_controller->GetDlpMetadata(files_to_check, future.GetCallback());
   EXPECT_TRUE(future.Wait());
   EXPECT_EQ(dlp_metadata, future.Take());
 }
@@ -392,7 +427,11 @@
 
   base::test::TestFuture<std::vector<DlpFilesController::DlpFileMetadata>>
       future;
-  files_controller_.GetDlpMetadata(files_to_check, future.GetCallback());
+  ASSERT_TRUE(rules_manager_);
+  DlpFilesController* files_controller =
+      rules_manager_->GetDlpFilesController();
+  ASSERT_TRUE(files_controller);
+  files_controller->GetDlpMetadata(files_to_check, future.GetCallback());
   EXPECT_TRUE(future.Wait());
   EXPECT_EQ(dlp_metadata, future.Take());
 }
@@ -413,7 +452,11 @@
   EXPECT_CALL(*rules_manager_, GetAggregatedComponents)
       .WillOnce(testing::Return(components));
 
-  auto result = files_controller_.GetDlpRestrictionDetails(kExample1);
+  ASSERT_TRUE(rules_manager_);
+  DlpFilesController* files_controller =
+      rules_manager_->GetDlpFilesController();
+  ASSERT_TRUE(files_controller);
+  auto result = files_controller->GetDlpRestrictionDetails(kExample1);
 
   ASSERT_EQ(result.size(), 3);
   std::vector<std::string> expected_urls;
@@ -451,7 +494,11 @@
   EXPECT_CALL(*rules_manager_, GetAggregatedComponents)
       .WillOnce(testing::Return(components));
 
-  auto result = files_controller_.GetDlpRestrictionDetails(kExample1);
+  ASSERT_TRUE(rules_manager_);
+  DlpFilesController* files_controller =
+      rules_manager_->GetDlpFilesController();
+  ASSERT_TRUE(files_controller);
+  auto result = files_controller->GetDlpRestrictionDetails(kExample1);
 
   ASSERT_EQ(result.size(), 1);
   std::vector<std::string> expected_urls;
@@ -583,7 +630,7 @@
       blink::StorageKey(), mount_name, base::FilePath(path));
   ASSERT_TRUE(dst_url.is_valid());
 
-  files_controller_.IsFilesTransferRestricted(
+  files_controller_->IsFilesTransferRestricted(
       profile_.get(), files_sources, dst_url.path().value(),
       DlpWarnDialog::FilesAction::kDownload, cb.Get());
 }
@@ -622,7 +669,7 @@
   std::unique_ptr<MockDlpWarnNotifier> wrapper =
       std::make_unique<MockDlpWarnNotifier>(should_proceed);
   MockDlpWarnNotifier* mock_dlp_warn_notifier = wrapper.get();
-  files_controller_.SetWarnNotifierForTesting(std::move(wrapper));
+  files_controller_->SetWarnNotifierForTesting(std::move(wrapper));
 
   EXPECT_CALL(*mock_dlp_warn_notifier, ShowDlpWarningDialog).Times(1);
 
@@ -640,7 +687,7 @@
       base::FilePath("MyUSB/path/in/removable"));
   ASSERT_TRUE(dst_url.is_valid());
 
-  files_controller_.IsFilesTransferRestricted(
+  files_controller_->IsFilesTransferRestricted(
       profile_.get(), files_sources, dst_url.path().value(),
       DlpWarnDialog::FilesAction::kDownload, cb.Get());
 
diff --git a/chrome/browser/autocomplete/shortcuts_backend_factory.cc b/chrome/browser/autocomplete/shortcuts_backend_factory.cc
index 5d1d2f1..1f005bf 100644
--- a/chrome/browser/autocomplete/shortcuts_backend_factory.cc
+++ b/chrome/browser/autocomplete/shortcuts_backend_factory.cc
@@ -10,7 +10,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/omnibox/browser/shortcuts_backend.h"
 #include "components/omnibox/browser/shortcuts_constants.h"
 #include "components/prefs/pref_service.h"
@@ -58,9 +57,7 @@
 }
 
 ShortcutsBackendFactory::ShortcutsBackendFactory()
-    : RefcountedBrowserContextKeyedServiceFactory(
-        "ShortcutsBackend",
-        BrowserContextDependencyManager::GetInstance()) {
+    : RefcountedProfileKeyedServiceFactory("ShortcutsBackend") {
   DependsOn(HistoryServiceFactory::GetInstance());
   DependsOn(TemplateURLServiceFactory::GetInstance());
 }
diff --git a/chrome/browser/autocomplete/shortcuts_backend_factory.h b/chrome/browser/autocomplete/shortcuts_backend_factory.h
index 8401b49..e6d883b 100644
--- a/chrome/browser/autocomplete/shortcuts_backend_factory.h
+++ b/chrome/browser/autocomplete/shortcuts_backend_factory.h
@@ -7,7 +7,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/refcounted_profile_keyed_service_factory.h"
 
 class Profile;
 
@@ -15,8 +15,7 @@
 
 // Singleton that owns all instances of ShortcutsBackend and associates them
 // with Profiles.
-class ShortcutsBackendFactory
-    : public RefcountedBrowserContextKeyedServiceFactory {
+class ShortcutsBackendFactory : public RefcountedProfileKeyedServiceFactory {
  public:
   static scoped_refptr<ShortcutsBackend> GetForProfile(Profile* profile);
 
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
index 1671f56..6df1bdd 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -224,6 +224,7 @@
 #include "ui/views/widget/widget.h"
 #include "ui/wm/core/coordinate_conversion.h"
 #include "ui/wm/core/cursor_manager.h"
+#include "ui/wm/core/window_properties.h"
 #include "ui/wm/core/window_util.h"
 #include "ui/wm/public/activation_client.h"
 #include "url/gurl.h"
@@ -388,7 +389,7 @@
       // TODO(https://crbug.com/1225848): Figure out appropriate behavior for
       // Lacros-hosted chrome-apps.
       return api::autotest_private::AppType::APP_TYPE_NONE;
-    }
+  }
   NOTREACHED();
   return api::autotest_private::AppType::APP_TYPE_NONE;
 }
@@ -1184,8 +1185,7 @@
                                              pressed);
         }
         if (task->flags & ui::EF_BACK_MOUSE_BUTTON) {
-          input_injector_->InjectMouseButton(ui::EF_BACK_MOUSE_BUTTON,
-                                             pressed);
+          input_injector_->InjectMouseButton(ui::EF_BACK_MOUSE_BUTTON, pressed);
         }
         if (task->flags & ui::EF_FORWARD_MOUSE_BUTTON) {
           input_injector_->InjectMouseButton(ui::EF_FORWARD_MOUSE_BUTTON,
@@ -4403,7 +4403,11 @@
     window_info.display_id = base::NumberToString(
         display::Screen::GetScreen()->GetDisplayNearestWindow(window).id());
     window_info.title = base::UTF16ToUTF8(window->GetTitle());
-    window_info.is_animating = window->layer()->GetAnimator()->is_animating();
+    // Check for window hiding animations separately because they pertain to
+    // layers detached from the window.
+    window_info.is_animating =
+        window->layer()->GetAnimator()->is_animating() ||
+        window->GetProperty(wm::kWindowHidingAnimationCountKey) > 0;
     window_info.is_visible = window->IsVisible();
     window_info.target_visibility = window->TargetVisibility();
     window_info.can_focus = window->CanFocus();
@@ -4427,13 +4431,17 @@
                    << " (ID: " << window->GetId()
                    << ") isn't available even though it is an ARC window.";
       }
-
-      std::string* app_id = window->GetProperty(app_restore::kAppIdKey);
-      if (app_id) {
-        window_info.full_restore_window_app_id =
-            std::make_unique<std::string>(*app_id);
-      }
     }
+    std::string* full_restore_window_app_id =
+        window->GetProperty(app_restore::kAppIdKey);
+    if (full_restore_window_app_id) {
+      window_info.full_restore_window_app_id =
+          std::make_unique<std::string>(*full_restore_window_app_id);
+    }
+    std::string* app_id = window->GetProperty(ash::kAppIDKey);
+    if (app_id)
+      window_info.app_id = std::make_unique<std::string>(*app_id);
+
     auto* widget = views::Widget::GetWidgetForNativeWindow(window);
     // Frame information
     auto* immersive_controller =
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc b/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc
index 675201b..25faf28 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/ash/file_manager/volume_manager.h"
 #include "chrome/browser/ash/file_system_provider/icon_set.h"
 #include "chrome/browser/ash/file_system_provider/provided_file_system_info.h"
+#include "chrome/browser/ash/policy/dlp/dlp_files_controller.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/extensions/file_manager/event_router.h"
 #include "chrome/browser/chromeos/extensions/file_manager/event_router_factory.h"
@@ -718,12 +719,19 @@
     mock_rules_manager_ = dlp_rules_manager.get();
     ON_CALL(*mock_rules_manager_, IsFilesPolicyEnabled)
         .WillByDefault(testing::Return(true));
+
+    files_controller_ =
+        std::make_unique<policy::DlpFilesController>(*mock_rules_manager_);
+    ON_CALL(*mock_rules_manager_, GetDlpFilesController)
+        .WillByDefault(testing::Return(files_controller_.get()));
+
     return dlp_rules_manager;
   }
 
  protected:
   base::ScopedTempDir drive_path_;
   policy::MockDlpRulesManager* mock_rules_manager_ = nullptr;
+  std::unique_ptr<policy::DlpFilesController> files_controller_;
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
index 0b879a8..0c4dbe0 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
@@ -1042,7 +1042,8 @@
 
   policy::DlpRulesManager* rules_manager =
       policy::DlpRulesManagerFactory::GetForPrimaryProfile();
-  if (!rules_manager || !rules_manager->IsFilesPolicyEnabled()) {
+  if (!rules_manager || !rules_manager->IsFilesPolicyEnabled() ||
+      !rules_manager->GetDlpFilesController()) {
     return RespondNow(WithArguments(base::Value::List()));
   }
 
@@ -1071,8 +1072,9 @@
     return RespondNow(Error("File URL was invalid"));
   }
 
-  files_controller_ = std::make_unique<policy::DlpFilesController>();
-  files_controller_->GetDisallowedTransfers(
+  policy::DlpFilesController* files_controller =
+      rules_manager->GetDlpFilesController();
+  files_controller->GetDisallowedTransfers(
       source_urls_, destination_url_,
       base::BindOnce(&FileManagerPrivateInternalGetDisallowedTransfersFunction::
                          OnGetDisallowedFiles,
@@ -1129,7 +1131,8 @@
 
   policy::DlpRulesManager* rules_manager =
       policy::DlpRulesManagerFactory::GetForPrimaryProfile();
-  if (!rules_manager || !rules_manager->IsFilesPolicyEnabled()) {
+  if (!rules_manager || !rules_manager->IsFilesPolicyEnabled() ||
+      !rules_manager->GetDlpFilesController()) {
     return RespondNow(WithArguments(base::Value::List()));
   }
 
@@ -1150,8 +1153,9 @@
     source_urls_.push_back(file_system_url);
   }
 
-  files_controller_ = std::make_unique<policy::DlpFilesController>();
-  files_controller_->GetDlpMetadata(
+  policy::DlpFilesController* files_controller =
+      rules_manager->GetDlpFilesController();
+  files_controller->GetDlpMetadata(
       source_urls_,
       base::BindOnce(
           &FileManagerPrivateInternalGetDlpMetadataFunction::OnGetDlpMetadata,
@@ -1191,7 +1195,8 @@
 
   policy::DlpRulesManager* rules_manager =
       policy::DlpRulesManagerFactory::GetForPrimaryProfile();
-  if (!rules_manager || !rules_manager->IsFilesPolicyEnabled()) {
+  if (!rules_manager || !rules_manager->IsFilesPolicyEnabled() ||
+      !rules_manager->GetDlpFilesController()) {
     return RespondNow(WithArguments(base::Value::List()));
   }
 
@@ -1199,8 +1204,8 @@
   const std::unique_ptr<Params> params(Params::Create(args()));
   EXTENSION_FUNCTION_VALIDATE(params);
 
-  std::unique_ptr<policy::DlpFilesController> files_controller =
-      std::make_unique<policy::DlpFilesController>();
+  policy::DlpFilesController* files_controller =
+      rules_manager->GetDlpFilesController();
   const std::vector<policy::DlpFilesController::DlpFileRestrictionDetails>
       dlp_restriction_details =
           files_controller->GetDlpRestrictionDetails(params->source_url);
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h
index 6df0ac7..6f2af51 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h
@@ -313,7 +313,6 @@
 
   Profile* profile_ = nullptr;
 
-  std::unique_ptr<policy::DlpFilesController> files_controller_;
   std::vector<storage::FileSystemURL> source_urls_;
   storage::FileSystemURL destination_url_;
 };
@@ -337,7 +336,6 @@
   void OnGetDlpMetadata(
       std::vector<policy::DlpFilesController::DlpFileMetadata> dlp_metadata);
 
-  std::unique_ptr<policy::DlpFilesController> files_controller_;
   std::vector<storage::FileSystemURL> source_urls_;
 };
 
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h
index ea9fb22..e12cae8f 100644
--- a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h
+++ b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h
@@ -9,6 +9,7 @@
 #include <set>
 #include <string>
 
+#include "build/chromeos_buildflags.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "url/gurl.h"
 
@@ -18,6 +19,10 @@
 
 class DlpReportingManager;
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+class DlpFilesController;
+#endif
+
 // DlpRulesManager parses the rules set by DataLeakPreventionRulesList policy
 // and serves as an available service which can be queried anytime about the
 // restrictions set by the policy.
@@ -161,6 +166,13 @@
   // IsReportingEnabled).
   virtual DlpReportingManager* GetReportingManager() const = 0;
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  // Returns the files controller that is used to perform DLP checks on files.
+  // Should always return a nullptr if there are no file restrictions (and thus
+  // the DLP daemon is not active).
+  virtual DlpFilesController* GetDlpFilesController() const = 0;
+#endif
+
   // Returns the URL pattern that `source_url` is matched against. The returned
   // URL pattern should be configured in a policy rule with the same
   // `restriction` and `level`.
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 b84607f..70bd8ea 100644
--- a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.cc
+++ b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.cc
@@ -15,6 +15,7 @@
 #include "base/containers/fixed_flat_map.h"
 #include "base/feature_list.h"
 #include "base/values.h"
+#include "chrome/browser/ash/policy/dlp/dlp_files_controller.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.h"
 #include "chrome/browser/chromeos/policy/dlp/dlp_histogram_helper.h"
@@ -431,9 +432,8 @@
                           base::Unretained(this)));
   OnPolicyUpdate();
 
-  if (!IsReportingEnabled())
-    return;
-  reporting_manager_ = std::make_unique<DlpReportingManager>();
+  if (IsReportingEnabled())
+    reporting_manager_ = std::make_unique<DlpReportingManager>();
 }
 
 bool DlpRulesManagerImpl::IsReportingEnabled() const {
@@ -445,6 +445,12 @@
   return reporting_manager_.get();
 }
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+DlpFilesController* DlpRulesManagerImpl::GetDlpFilesController() const {
+  return files_controller_.get();
+}
+#endif
+
 std::string DlpRulesManagerImpl::GetSourceUrlPattern(const GURL& source_url,
                                                      Restriction restriction,
                                                      Level level) const {
@@ -499,6 +505,9 @@
   dst_pattterns_mapping_.clear();
   src_conditions_.clear();
   dst_conditions_.clear();
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  files_controller_ = nullptr;
+#endif
 
   if (!base::FeatureList::IsEnabled(features::kDataLeakPreventionPolicy)) {
     return;
@@ -615,6 +624,9 @@
     DlpBooleanHistogram(dlp::kFilesDaemonStartedUMA, true);
     chromeos::DlpClient::Get()->SetDlpFilesPolicy(
         request_to_daemon, base::BindOnce(&OnSetDlpFilesPolicy));
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+    files_controller_ = std::make_unique<DlpFilesController>(*this);
+#endif
   } else if (DlpScopedFileAccessDelegate::HasInstance()) {
     DlpScopedFileAccessDelegate::DeleteInstance();
   }
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 d98d2b38..794c9de 100644
--- a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.h
+++ b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.h
@@ -21,6 +21,10 @@
 
 class DlpReportingManager;
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+class DlpFilesController;
+#endif
+
 class DlpRulesManagerImpl : public DlpRulesManager {
  public:
   using RuleId = int;
@@ -54,6 +58,11 @@
       Restriction restriction) const override;
   bool IsReportingEnabled() const override;
   DlpReportingManager* GetReportingManager() const override;
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  DlpFilesController* GetDlpFilesController() const override;
+#endif
+
   std::string GetSourceUrlPattern(const GURL& source_url,
                                   Restriction restriction,
                                   Level level) const override;
@@ -107,6 +116,11 @@
 
   // System-wide singleton instantiated when required by rules configuration.
   std::unique_ptr<DlpReportingManager> reporting_manager_;
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  // System-wide singleton instantiated when there are rules involving files.
+  std::unique_ptr<DlpFilesController> files_controller_;
+#endif
 };
 
 }  // namespace policy
diff --git a/chrome/browser/chromeos/policy/dlp/mock_dlp_rules_manager.h b/chrome/browser/chromeos/policy/dlp/mock_dlp_rules_manager.h
index 6a3a6b7..224d52de 100644
--- a/chrome/browser/chromeos/policy/dlp/mock_dlp_rules_manager.h
+++ b/chrome/browser/chromeos/policy/dlp/mock_dlp_rules_manager.h
@@ -51,6 +51,10 @@
 
   MOCK_CONST_METHOD0(GetReportingManager, DlpReportingManager*());
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  MOCK_CONST_METHOD0(GetDlpFilesController, DlpFilesController*());
+#endif
+
   MOCK_CONST_METHOD3(GetSourceUrlPattern,
                      std::string(const GURL& source_url,
                                  Restriction restriction,
diff --git a/chrome/browser/content_settings/cookie_settings_factory.cc b/chrome/browser/content_settings/cookie_settings_factory.cc
index f2cc15e6..4ca635b 100644
--- a/chrome/browser/content_settings/cookie_settings_factory.cc
+++ b/chrome/browser/content_settings/cookie_settings_factory.cc
@@ -7,11 +7,9 @@
 #include "base/check_op.h"
 #include "base/metrics/histogram_functions.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "components/content_settings/core/common/pref_names.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_thread.h"
@@ -37,9 +35,11 @@
 }
 
 CookieSettingsFactory::CookieSettingsFactory()
-    : RefcountedBrowserContextKeyedServiceFactory(
+    : RefcountedProfileKeyedServiceFactory(
           "CookieSettings",
-          BrowserContextDependencyManager::GetInstance()) {
+          // The incognito profile has its own content settings map. Therefore,
+          // it should get its own CookieSettings.
+          ProfileSelections::BuildForRegularAndIncognito()) {
   DependsOn(HostContentSettingsMapFactory::GetInstance());
 }
 
@@ -50,13 +50,6 @@
   content_settings::CookieSettings::RegisterProfilePrefs(registry);
 }
 
-content::BrowserContext* CookieSettingsFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  // The incognito profile has its own content settings map. Therefore, it
-  // should get its own CookieSettings.
-  return chrome::GetBrowserContextOwnInstanceInIncognito(context);
-}
-
 scoped_refptr<RefcountedKeyedService>
 CookieSettingsFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
diff --git a/chrome/browser/content_settings/cookie_settings_factory.h b/chrome/browser/content_settings/cookie_settings_factory.h
index 5c67729..ed689d2 100644
--- a/chrome/browser/content_settings/cookie_settings_factory.h
+++ b/chrome/browser/content_settings/cookie_settings_factory.h
@@ -7,7 +7,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/refcounted_profile_keyed_service_factory.h"
 
 namespace content_settings {
 class CookieSettings;
@@ -15,8 +15,7 @@
 
 class Profile;
 
-class CookieSettingsFactory
-    : public RefcountedBrowserContextKeyedServiceFactory {
+class CookieSettingsFactory : public RefcountedProfileKeyedServiceFactory {
  public:
   // Returns the |CookieSettings| associated with the |profile|.
   //
@@ -38,8 +37,6 @@
   // |RefcountedBrowserContextKeyedServiceFactory| methods:
   void RegisterProfilePrefs(
       user_prefs::PrefRegistrySyncable* registry) override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
   scoped_refptr<RefcountedKeyedService> BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
 };
diff --git a/chrome/browser/content_settings/host_content_settings_map_factory.cc b/chrome/browser/content_settings/host_content_settings_map_factory.cc
index 242f244..d5cab75 100644
--- a/chrome/browser/content_settings/host_content_settings_map_factory.cc
+++ b/chrome/browser/content_settings/host_content_settings_map_factory.cc
@@ -17,7 +17,6 @@
 #include "chrome/common/buildflags.h"
 #include "components/content_settings/core/browser/content_settings_pref_provider.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/permissions/features.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/buildflags/buildflags.h"
@@ -47,9 +46,9 @@
 #endif
 
 HostContentSettingsMapFactory::HostContentSettingsMapFactory()
-    : RefcountedBrowserContextKeyedServiceFactory(
-        "HostContentSettingsMap",
-        BrowserContextDependencyManager::GetInstance()) {
+    : RefcountedProfileKeyedServiceFactory(
+          "HostContentSettingsMap",
+          ProfileSelections::BuildForRegularAndIncognito()) {
   DependsOn(LastTabStandingTrackerFactory::GetInstance());
 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
   DependsOn(SupervisedUserSettingsServiceFactory::GetInstance());
@@ -169,8 +168,3 @@
 #endif  // defined (OS_ANDROID)
   return settings_map;
 }
-
-content::BrowserContext* HostContentSettingsMapFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return context;
-}
diff --git a/chrome/browser/content_settings/host_content_settings_map_factory.h b/chrome/browser/content_settings/host_content_settings_map_factory.h
index e11a061..69476a9 100644
--- a/chrome/browser/content_settings/host_content_settings_map_factory.h
+++ b/chrome/browser/content_settings/host_content_settings_map_factory.h
@@ -7,12 +7,12 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/refcounted_profile_keyed_service_factory.h"
 
 class HostContentSettingsMap;
 
 class HostContentSettingsMapFactory
-    : public RefcountedBrowserContextKeyedServiceFactory {
+    : public RefcountedProfileKeyedServiceFactory {
  public:
   static HostContentSettingsMap* GetForProfile(
       content::BrowserContext* browser_context);
@@ -31,8 +31,6 @@
   // RefcountedBrowserContextKeyedServiceFactory methods:
   scoped_refptr<RefcountedKeyedService> BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 };
 
 #endif // CHROME_BROWSER_CONTENT_SETTINGS_HOST_CONTENT_SETTINGS_MAP_FACTORY_H_
diff --git a/chrome/browser/download/download_file_picker.cc b/chrome/browser/download/download_file_picker.cc
index f5845b46..d61546a 100644
--- a/chrome/browser/download/download_file_picker.cc
+++ b/chrome/browser/download/download_file_picker.cc
@@ -22,6 +22,8 @@
 #include "ui/aura/window.h"
 #elif BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/ash/policy/dlp/dlp_files_controller.h"
+#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h"
+#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h"
 #include "chrome/browser/chromeos/policy/dlp/dlp_warn_dialog.h"
 #include "chrome/browser/profiles/profile.h"
 #endif
@@ -116,13 +118,25 @@
           : nullptr;
   if (web_contents && !path.empty()) {
     DCHECK(download_item_);
-    dlp_files_controller_.emplace();
-    dlp_files_controller_->IsFilesTransferRestricted(
-        Profile::FromBrowserContext(web_contents->GetBrowserContext()),
-        {download_item_->GetURL()}, path.value(),
-        policy::DlpWarnDialog::FilesAction::kDownload,
-        base::BindOnce(&DownloadFilePicker::CompleteFileSelection,
-                       base::Unretained(this), path));
+
+    policy::DlpFilesController* files_controller = nullptr;
+    policy::DlpRulesManager* rules_manager =
+        policy::DlpRulesManagerFactory::GetForPrimaryProfile();
+
+    if (rules_manager)
+      files_controller = rules_manager->GetDlpFilesController();
+
+    if (files_controller) {
+      files_controller->IsFilesTransferRestricted(
+          Profile::FromBrowserContext(web_contents->GetBrowserContext()),
+          {download_item_->GetURL()}, path.value(),
+          policy::DlpWarnDialog::FilesAction::kDownload,
+          base::BindOnce(&DownloadFilePicker::CompleteFileSelection,
+                         base::Unretained(this), path));
+    } else {
+      CompleteFileSelection(path, std::vector<GURL>());
+    }
+
     return;
   }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
@@ -135,7 +149,6 @@
     const std::vector<GURL>& restricted_sources) {
   base::FilePath selected_path(path);
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  dlp_files_controller_.reset();
   if (!restricted_sources.empty())
     selected_path.clear();
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/download/download_file_picker.h b/chrome/browser/download/download_file_picker.h
index 12cf00e..d1b3ad1 100644
--- a/chrome/browser/download/download_file_picker.h
+++ b/chrome/browser/download/download_file_picker.h
@@ -11,10 +11,6 @@
 #include "components/download/public/common/download_item.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "chrome/browser/ash/policy/dlp/dlp_files_controller.h"
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-
 namespace base {
 class FilePath;
 }
@@ -79,13 +75,6 @@
 
   // The item to be downloaded.
   raw_ptr<download::DownloadItem> download_item_;
-
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  // DlpFilesController is responsible for checking whether any of the selected
-  // files is restricted according to the DataLeakPrevention policy.
-  absl::optional<policy::DlpFilesController> dlp_files_controller_;
-
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 };
 
 #endif  // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_FILE_PICKER_H_
diff --git a/chrome/browser/extensions/api/media_perception_private/OWNERS b/chrome/browser/extensions/api/media_perception_private/OWNERS
index f55ea18..d063efc 100644
--- a/chrome/browser/extensions/api/media_perception_private/OWNERS
+++ b/chrome/browser/extensions/api/media_perception_private/OWNERS
@@ -1,2 +1 @@
-lasoren@chromium.org
 tbarzic@chromium.org
diff --git a/chrome/browser/extensions/api/recovery_private/OWNERS b/chrome/browser/extensions/api/recovery_private/OWNERS
index 75892dee..ceb83a9 100644
--- a/chrome/browser/extensions/api/recovery_private/OWNERS
+++ b/chrome/browser/extensions/api/recovery_private/OWNERS
@@ -1,2 +1 @@
-haven@chromium.org
 stephenlin@chromium.org
diff --git a/chrome/browser/file_select_helper.cc b/chrome/browser/file_select_helper.cc
index f532c9e..f0622c2 100644
--- a/chrome/browser/file_select_helper.cc
+++ b/chrome/browser/file_select_helper.cc
@@ -21,6 +21,8 @@
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h"
+#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h"
 #include "chrome/browser/enterprise/connectors/common.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/profiles/profile.h"
@@ -50,6 +52,7 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/ash/file_manager/fileapi_util.h"
+#include "chrome/browser/ash/policy/dlp/dlp_files_controller.h"
 #include "content/public/browser/site_instance.h"
 #endif
 
@@ -338,12 +341,22 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   DCHECK(render_frame_host_);
-  dlp_files_controller_.emplace();
-  dlp_files_controller_->FilterDisallowedUploads(
-      std::move(list),
-      render_frame_host_->GetMainFrame()->GetLastCommittedURL(),
-      base::BindOnce(&FileSelectHelper::PerformContentAnalysisIfNeeded,
-                     weak_ptr_factory_.GetWeakPtr()));
+  policy::DlpFilesController* files_controller = nullptr;
+  policy::DlpRulesManager* rules_manager =
+      policy::DlpRulesManagerFactory::GetForPrimaryProfile();
+  if (rules_manager)
+    files_controller = rules_manager->GetDlpFilesController();
+
+  if (files_controller) {
+    files_controller->FilterDisallowedUploads(
+        std::move(list),
+        render_frame_host_->GetMainFrame()->GetLastCommittedURL(),
+        base::BindOnce(&FileSelectHelper::PerformContentAnalysisIfNeeded,
+                       weak_ptr_factory_.GetWeakPtr()));
+  } else {
+    PerformContentAnalysisIfNeeded(std::move(list));
+  }
+
 #else
   PerformContentAnalysisIfNeeded(std::move(list));
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
@@ -351,9 +364,6 @@
 
 void FileSelectHelper::PerformContentAnalysisIfNeeded(
     std::vector<FileChooserFileInfoPtr> list) {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  dlp_files_controller_.reset();
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   if (AbortIfWebContentsDestroyed())
     return;
 
diff --git a/chrome/browser/file_select_helper.h b/chrome/browser/file_select_helper.h
index 8c86774..b15f867 100644
--- a/chrome/browser/file_select_helper.h
+++ b/chrome/browser/file_select_helper.h
@@ -20,14 +20,9 @@
 #include "content/public/browser/render_widget_host_observer.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "net/base/directory_lister.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "chrome/browser/ash/policy/dlp/dlp_files_controller.h"
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-
 #if BUILDFLAG(FULL_SAFE_BROWSING)
 #include "chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.h"
 #endif
@@ -332,10 +327,6 @@
   bool abort_on_missing_web_contents_in_tests_ = true;
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  // DlpFilesController is responsible for checking whether any of the selected
-  // files is restricted according to the DataLeakPrevention policy.
-  absl::optional<policy::DlpFilesController> dlp_files_controller_;
-
   base::WeakPtrFactory<FileSelectHelper> weak_ptr_factory_{this};
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 };
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 22b93fb8..9a4f768 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -925,7 +925,7 @@
   {
     "name": "chrome-whats-new-ui",
     "owners": [ "rbpotter" ],
-    "expiry_milestone": 106
+    "expiry_milestone": 110
   },
   {
     "name": "chrome-wide-echo-cancellation",
@@ -5247,7 +5247,7 @@
   {
     "name": "photo-picker-video-support",
     "owners": [ "finnur" ],
-    "expiry_milestone": 105
+    "expiry_milestone": 110
   },
   {
     "name": "post-quantum-cecpq2",
diff --git a/chrome/browser/history/top_sites_factory.cc b/chrome/browser/history/top_sites_factory.cc
index 3ff9cef..b66ee7a 100644
--- a/chrome/browser/history/top_sites_factory.cc
+++ b/chrome/browser/history/top_sites_factory.cc
@@ -27,7 +27,6 @@
 #include "components/grit/components_scaled_resources.h"
 #include "components/history/core/browser/history_constants.h"
 #include "components/history/core/browser/top_sites_impl.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 #include "components/search/ntp_features.h"
@@ -121,9 +120,7 @@
 }
 
 TopSitesFactory::TopSitesFactory()
-    : RefcountedBrowserContextKeyedServiceFactory(
-          "TopSites",
-          BrowserContextDependencyManager::GetInstance()) {
+    : RefcountedProfileKeyedServiceFactory("TopSites") {
   DependsOn(HistoryServiceFactory::GetInstance());
   DependsOn(TemplateURLServiceFactory::GetInstance());
   // This dependency is only used when the experimental
diff --git a/chrome/browser/history/top_sites_factory.h b/chrome/browser/history/top_sites_factory.h
index a8e3ced..a0f1e4f 100644
--- a/chrome/browser/history/top_sites_factory.h
+++ b/chrome/browser/history/top_sites_factory.h
@@ -8,7 +8,7 @@
 #include <vector>
 
 #include "base/memory/ref_counted.h"
-#include "components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/refcounted_profile_keyed_service_factory.h"
 
 class Profile;
 
@@ -25,7 +25,7 @@
 class Profile;
 
 // Used for creating and fetching a per-profile instance of the TopSites.
-class TopSitesFactory : public RefcountedBrowserContextKeyedServiceFactory {
+class TopSitesFactory : public RefcountedProfileKeyedServiceFactory {
  public:
   // Get the TopSites service for |profile|, creating one if needed.
   static scoped_refptr<history::TopSites> GetForProfile(Profile* profile);
diff --git a/chrome/browser/history_clusters/history_clusters_bridge.cc b/chrome/browser/history_clusters/history_clusters_bridge.cc
index 19ae258..345eaeb 100644
--- a/chrome/browser/history_clusters/history_clusters_bridge.cc
+++ b/chrome/browser/history_clusters/history_clusters_bridge.cc
@@ -121,9 +121,9 @@
       std::vector<ScopedJavaLocalRef<jobject>> duplicated_visit_urls;
       for (const auto& duplicate : visit.duplicate_visits) {
         duplicated_visit_timestamps.push_back(
-            duplicate.annotated_visit.visit_row.visit_time.ToInternalValue());
-        duplicated_visit_urls.push_back(url::GURLAndroid::FromNativeGURL(
-            env, duplicate.annotated_visit.url_row.url()));
+            duplicate.visit_time.ToInternalValue());
+        duplicated_visit_urls.push_back(
+            url::GURLAndroid::FromNativeGURL(env, duplicate.url));
       }
 
       const ScopedJavaLocalRef<jobject>& j_cluster_visit =
diff --git a/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersViewBinder.java b/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersViewBinder.java
index c0bf16fb..a023c00 100644
--- a/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersViewBinder.java
+++ b/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersViewBinder.java
@@ -45,7 +45,7 @@
         if (key == HistoryClustersToolbarProperties.QUERY_STATE) {
             QueryState queryState = model.get(HistoryClustersToolbarProperties.QUERY_STATE);
             if (queryState.isSearching()) {
-                toolbar.showSearchView(false);
+                toolbar.showSearchView(queryState.getQuery().isEmpty());
                 toolbar.setSearchText(queryState.getQuery());
             } else {
                 toolbar.hideSearchView();
diff --git a/chrome/browser/mac/keystone_glue_unittest.mm b/chrome/browser/mac/keystone_glue_unittest.mm
index b19a81d..29d49fb 100644
--- a/chrome/browser/mac/keystone_glue_unittest.mm
+++ b/chrome/browser/mac/keystone_glue_unittest.mm
@@ -3,8 +3,8 @@
 // found in the LICENSE file.
 
 #import <Foundation/Foundation.h>
-#import <objc/objc-class.h>
 
+#import "base/mac/scoped_objc_class_swizzler.h"
 #include "base/test/task_environment.h"
 #import "chrome/browser/mac/keystone_glue.h"
 #import "chrome/browser/mac/keystone_registration.h"
@@ -131,7 +131,8 @@
 
 - (BOOL)loadKeystoneRegistration {
   // The real loadKeystoneRegistration adds a real registration.
-  [self addFakeRegistration];
+  // Add a fake one.
+  _registration.reset([[FakeKeystoneRegistration alloc] init]);
   return YES;
 }
 
@@ -147,10 +148,6 @@
   return _timer ? YES : NO;
 }
 
-- (void)addFakeRegistration {
-  _registration.reset([[FakeKeystoneRegistration alloc] init]);
-}
-
 - (void)fakeAboutWindowCallback:(NSNotification*)notification {
   NSDictionary* dictionary = [notification userInfo];
   AutoupdateStatus status = static_cast<AutoupdateStatus>(
@@ -181,34 +178,17 @@
   base::test::TaskEnvironment task_environment_;
 };
 
-// The test is flaky: crbug.com/1041813.
-TEST_F(KeystoneGlueTest, DISABLED_BasicGlobalCreate) {
-  // Allow creation of a KeystoneGlue by mocking out a few calls
-  SEL ids = @selector(infoDictionary);
-  IMP oldInfoImp_ = [[KeystoneGlue class] instanceMethodForSelector:ids];
-  IMP newInfoImp_ = [[FakeKeystoneGlue class] instanceMethodForSelector:ids];
-  Method infoMethod_ = class_getInstanceMethod([KeystoneGlue class], ids);
-  method_setImplementation(infoMethod_, newInfoImp_);
-
-  SEL lks = @selector(loadKeystoneRegistration);
-  IMP oldLoadImp_ = [[KeystoneGlue class] instanceMethodForSelector:lks];
-  IMP newLoadImp_ = [[FakeKeystoneGlue class] instanceMethodForSelector:lks];
-  Method loadMethod_ = class_getInstanceMethod([KeystoneGlue class], lks);
-  method_setImplementation(loadMethod_, newLoadImp_);
-
-  SEL afr = @selector(addFakeRegistration);
-  IMP oldAddFake_ = [[KeystoneGlue class] instanceMethodForSelector:afr];
-  IMP newAddFake_ = [[FakeKeystoneGlue class] instanceMethodForSelector:afr];
-  Method addMethod_ = class_getInstanceMethod([KeystoneGlue class], afr);
-  method_setImplementation(loadMethod_, newAddFake_);
+TEST_F(KeystoneGlueTest, BasicGlobalCreate) {
+  // Allow creation of a KeystoneGlue by mocking out a couple calls.
+  base::mac::ScopedObjCClassSwizzler infoDictionarySwizzler(
+      [KeystoneGlue class], [FakeKeystoneGlue class],
+      @selector(infoDictionary));
+  base::mac::ScopedObjCClassSwizzler loadRegistrationSwizzler(
+      [KeystoneGlue class], [FakeKeystoneGlue class],
+      @selector(loadKeystoneRegistration));
 
   KeystoneGlue *glue = [KeystoneGlue defaultKeystoneGlue];
   ASSERT_TRUE(glue);
-
-  // Fix back up the class to the way we found it.
-  method_setImplementation(infoMethod_, oldInfoImp_);
-  method_setImplementation(loadMethod_, oldLoadImp_);
-  method_setImplementation(addMethod_, oldAddFake_);
 }
 
 TEST_F(KeystoneGlueTest, BasicUse) {
diff --git a/chrome/browser/page_load_metrics/observers/media_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/media_page_load_metrics_observer.cc
index 5e833971..b1de010 100644
--- a/chrome/browser/page_load_metrics/observers/media_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/media_page_load_metrics_observer.cc
@@ -12,9 +12,9 @@
 const char kHistogramMediaPageLoadNetworkBytes[] =
     "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Network";
 const char kHistogramMediaPageLoadCacheBytes[] =
-    "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Cache";
+    "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Cache2";
 const char kHistogramMediaPageLoadTotalBytes[] =
-    "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Total";
+    "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Total2";
 
 }  // namespace
 
diff --git a/chrome/browser/page_load_metrics/observers/media_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/media_page_load_metrics_observer_unittest.cc
index 47d803d..395f0d3 100644
--- a/chrome/browser/page_load_metrics/observers/media_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/media_page_load_metrics_observer_unittest.cc
@@ -106,9 +106,9 @@
   tester()->histogram_tester().ExpectTotalCount(
       "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Network", 0);
   tester()->histogram_tester().ExpectTotalCount(
-      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Cache", 0);
+      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Cache2", 0);
   tester()->histogram_tester().ExpectTotalCount(
-      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Total", 0);
+      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Total2", 0);
 }
 
 TEST_F(MediaPageLoadMetricsObserverTest, MediaPlayed) {
@@ -124,10 +124,10 @@
       "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Network",
       static_cast<int>(network_bytes_ / 1024), 1);
   tester()->histogram_tester().ExpectUniqueSample(
-      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Cache",
+      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Cache2",
       static_cast<int>(cache_bytes_ / 1024), 1);
   tester()->histogram_tester().ExpectUniqueSample(
-      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Total",
+      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Total2",
       static_cast<int>((network_bytes_ + cache_bytes_) / 1024), 1);
 }
 
@@ -144,10 +144,10 @@
       "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Network",
       static_cast<int>(network_bytes_ / 1024), 1);
   tester()->histogram_tester().ExpectUniqueSample(
-      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Cache",
+      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Cache2",
       static_cast<int>(cache_bytes_ / 1024), 1);
   tester()->histogram_tester().ExpectUniqueSample(
-      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Total",
+      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Total2",
       static_cast<int>((network_bytes_ + cache_bytes_) / 1024), 1);
 }
 
@@ -170,10 +170,10 @@
       "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Network",
       static_cast<int>(network_bytes_ / 1024), 1);
   tester()->histogram_tester().ExpectUniqueSample(
-      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Cache",
+      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Cache2",
       static_cast<int>(cache_bytes_ / 1024), 1);
   tester()->histogram_tester().ExpectUniqueSample(
-      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Total",
+      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Total2",
       static_cast<int>((network_bytes_ + cache_bytes_) / 1024), 1);
 }
 
@@ -196,9 +196,9 @@
       "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Network",
       static_cast<int>(network_bytes_ / 1024), 1);
   tester()->histogram_tester().ExpectUniqueSample(
-      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Cache",
+      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Cache2",
       static_cast<int>(cache_bytes_ / 1024), 1);
   tester()->histogram_tester().ExpectUniqueSample(
-      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Total",
+      "PageLoad.Clients.MediaPageLoad2.Experimental.Bytes.Total2",
       static_cast<int>((network_bytes_ + cache_bytes_) / 1024), 1);
 }
diff --git a/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java b/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
index 87c6f02..03cbefb 100644
--- a/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
+++ b/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
@@ -369,7 +369,7 @@
             Log.w(TAG,
                     "Partner homepage must be HTTP(S) or NewTabPage. "
                             + "Got invalid URL \"%s\"",
-                    url);
+                    url.getPossiblyInvalidSpec());
             return false;
         }
         if (url.getSpec().length() > HOMEPAGE_URL_MAX_LENGTH) {
diff --git a/chrome/browser/password_manager/password_store_factory.cc b/chrome/browser/password_manager/password_store_factory.cc
index 36480b47..8ba7954e 100644
--- a/chrome/browser/password_manager/password_store_factory.cc
+++ b/chrome/browser/password_manager/password_store_factory.cc
@@ -14,12 +14,10 @@
 #include "chrome/browser/password_manager/affiliation_service_factory.h"
 #include "chrome/browser/password_manager/credentials_cleaner_runner_factory.h"
 #include "chrome/browser/password_manager/password_store_utils.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/web_data_service_factory.h"
 #include "chrome/common/chrome_paths_internal.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/password_manager/core/browser/password_manager_constants.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
 #include "components/password_manager/core/browser/password_store.h"
@@ -53,9 +51,9 @@
 }
 
 PasswordStoreFactory::PasswordStoreFactory()
-    : RefcountedBrowserContextKeyedServiceFactory(
+    : RefcountedProfileKeyedServiceFactory(
           "PasswordStore",
-          BrowserContextDependencyManager::GetInstance()) {
+          ProfileSelections::BuildRedirectedInIncognito()) {
   DependsOn(AffiliationServiceFactory::GetInstance());
   DependsOn(WebDataServiceFactory::GetInstance());
 }
@@ -119,11 +117,6 @@
   return ps;
 }
 
-content::BrowserContext* PasswordStoreFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
-
 bool PasswordStoreFactory::ServiceIsNULLWhileTesting() const {
   return true;
 }
diff --git a/chrome/browser/password_manager/password_store_factory.h b/chrome/browser/password_manager/password_store_factory.h
index 81e15a2b..48aff79 100644
--- a/chrome/browser/password_manager/password_store_factory.h
+++ b/chrome/browser/password_manager/password_store_factory.h
@@ -7,7 +7,7 @@
 
 #include "base/memory/singleton.h"
 #include "build/build_config.h"
-#include "components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/refcounted_profile_keyed_service_factory.h"
 #include "components/keyed_service/core/service_access_type.h"
 #include "components/password_manager/core/browser/password_store_interface.h"
 
@@ -15,8 +15,7 @@
 
 // Singleton that owns all PasswordStores and associates them with
 // Profiles.
-class PasswordStoreFactory
-    : public RefcountedBrowserContextKeyedServiceFactory {
+class PasswordStoreFactory : public RefcountedProfileKeyedServiceFactory {
  public:
   static scoped_refptr<password_manager::PasswordStoreInterface> GetForProfile(
       Profile* profile,
@@ -36,8 +35,6 @@
   // RefcountedBrowserContextKeyedServiceFactory:
   scoped_refptr<RefcountedKeyedService> BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
   bool ServiceIsNULLWhileTesting() const override;
 };
 
diff --git a/chrome/browser/plugins/plugin_prefs_factory.cc b/chrome/browser/plugins/plugin_prefs_factory.cc
index 12de545..9c91924 100644
--- a/chrome/browser/plugins/plugin_prefs_factory.cc
+++ b/chrome/browser/plugins/plugin_prefs_factory.cc
@@ -7,11 +7,9 @@
 #include "base/files/file_path.h"
 #include "base/path_service.h"
 #include "chrome/browser/plugins/plugin_prefs.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/pref_names.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
@@ -36,9 +34,9 @@
 }
 
 PluginPrefsFactory::PluginPrefsFactory()
-    : RefcountedBrowserContextKeyedServiceFactory(
-          "PluginPrefs", BrowserContextDependencyManager::GetInstance()) {
-}
+    : RefcountedProfileKeyedServiceFactory(
+          "PluginPrefs",
+          ProfileSelections::BuildRedirectedInIncognito()) {}
 
 PluginPrefsFactory::~PluginPrefsFactory() {}
 
@@ -64,11 +62,6 @@
       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
 }
 
-content::BrowserContext* PluginPrefsFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
-
 bool PluginPrefsFactory::ServiceIsNULLWhileTesting() const {
   return true;
 }
diff --git a/chrome/browser/plugins/plugin_prefs_factory.h b/chrome/browser/plugins/plugin_prefs_factory.h
index a010451..bb8e146 100644
--- a/chrome/browser/plugins/plugin_prefs_factory.h
+++ b/chrome/browser/plugins/plugin_prefs_factory.h
@@ -6,12 +6,12 @@
 #define CHROME_BROWSER_PLUGINS_PLUGIN_PREFS_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/refcounted_profile_keyed_service_factory.h"
 
 class PluginPrefs;
 class Profile;
 
-class PluginPrefsFactory : public RefcountedBrowserContextKeyedServiceFactory {
+class PluginPrefsFactory : public RefcountedProfileKeyedServiceFactory {
  public:
   static scoped_refptr<PluginPrefs> GetPrefsForProfile(Profile* profile);
 
@@ -35,8 +35,6 @@
   // BrowserContextKeyedServiceFactory methods:
   void RegisterProfilePrefs(
       user_prefs::PrefRegistrySyncable* registry) override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
   bool ServiceIsNULLWhileTesting() const override;
   bool ServiceIsCreatedWithBrowserContext() const override;
 };
diff --git a/chrome/browser/profiles/profile_keyed_service_factory.h b/chrome/browser/profiles/profile_keyed_service_factory.h
index c7e3320..908aa31 100644
--- a/chrome/browser/profiles/profile_keyed_service_factory.h
+++ b/chrome/browser/profiles/profile_keyed_service_factory.h
@@ -47,6 +47,8 @@
 //       : ProfileKeyedServiceFactory("MyDefaultKeyedService") {}
 //   }
 // };
+// Any change to this class should also be reflected on
+// `RefcountedProfileKeyedServiceFactory`.
 class ProfileKeyedServiceFactory : public BrowserContextKeyedServiceFactory {
  public:
   ProfileKeyedServiceFactory(const ProfileKeyedServiceFactory&) = delete;
diff --git a/chrome/browser/profiles/profile_keyed_service_factory_unittest.cc b/chrome/browser/profiles/profile_keyed_service_factory_unittest.cc
index 2b0b422..42cf052 100644
--- a/chrome/browser/profiles/profile_keyed_service_factory_unittest.cc
+++ b/chrome/browser/profiles/profile_keyed_service_factory_unittest.cc
@@ -3,11 +3,15 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/profiles/profile_keyed_service_factory.h"
+#include "chrome/browser/profiles/refcounted_profile_keyed_service_factory.h"
 
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_testing_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+// This unittest file contains both tests for `ProfileKeyedServiceFactory` and
+// `RefcountedProfileKeyedServiceFactory` for simplicity.
+
 // Testing implementation for interface `ProfileKeyedServiceFactory`.
 // The method `GetProfileToUseForTesting()` is used to test the protected method
 // `GetBrowserContextToUse()`.
@@ -35,6 +39,31 @@
   }
 };
 
+// Similar testing implementation of `ProfileKeyedServiceFactory` but for Ref
+// counted Services `RefcountedProfileKeyedServiceFactory`
+class RefcountedProfileKeyedServiceFactoryTest
+    : public RefcountedProfileKeyedServiceFactory {
+ public:
+  explicit RefcountedProfileKeyedServiceFactoryTest(const char* name)
+      : RefcountedProfileKeyedServiceFactory(name) {}
+  RefcountedProfileKeyedServiceFactoryTest(const char* name,
+                                           const ProfileSelections& selections)
+      : RefcountedProfileKeyedServiceFactory(name, selections) {}
+
+  // Method used for testing only, calls `GetBrowserContextToUse()` for testing.
+  Profile* GetProfileToUseForTesting(Profile* profile) const {
+    return Profile::FromBrowserContext(GetBrowserContextToUse(profile));
+  }
+
+ protected:
+  // Implementation is not for testing.
+  scoped_refptr<RefcountedKeyedService> BuildServiceInstanceFor(
+      content::BrowserContext* context) const override {
+    NOTREACHED();
+    return nullptr;
+  }
+};
+
 class ProfileKeyedServiceFactoryUnittest : public testing::Test {
  public:
   void SetUp() override {
@@ -43,7 +72,8 @@
   }
 
  protected:
-  void TestProfileToUse(const ProfileKeyedServiceFactoryTest& factory,
+  template <typename ProfileKeyedServiceFactoryTesting>
+  void TestProfileToUse(const ProfileKeyedServiceFactoryTesting& factory,
                         Profile* given_profile,
                         Profile* expected_profile) {
     EXPECT_EQ(factory.GetProfileToUseForTesting(given_profile),
@@ -151,3 +181,51 @@
   TestProfileToUse(factory, system_profile_otr(), nullptr);
 #endif  // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID)
 }
+
+// Factory using default `ProfileKeyedServiceFactory` constructor
+class DefaultRefcountedFactoryTest
+    : public RefcountedProfileKeyedServiceFactoryTest {
+ public:
+  DefaultRefcountedFactoryTest()
+      : RefcountedProfileKeyedServiceFactoryTest(
+            "DefaultRefcountedFactoryTest") {}
+};
+
+TEST_F(ProfileKeyedServiceFactoryUnittest, DefaultRefcountedFactoryTest) {
+  DefaultRefcountedFactoryTest factory;
+  TestProfileToUse(factory, regular_profile(), regular_profile());
+  TestProfileToUse(factory, incognito_profile(), nullptr);
+
+  TestProfileToUse(factory, guest_profile(), guest_profile());
+  TestProfileToUse(factory, guest_profile_otr(), nullptr);
+
+#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID)
+  TestProfileToUse(factory, system_profile(), system_profile());
+  TestProfileToUse(factory, system_profile_otr(), nullptr);
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID)
+}
+
+// Factory using predefined `ProfileSelections` built
+class PredefinedRefcountedProfileSelectionsFactoryTest
+    : public RefcountedProfileKeyedServiceFactoryTest {
+ public:
+  PredefinedRefcountedProfileSelectionsFactoryTest()
+      : RefcountedProfileKeyedServiceFactoryTest(
+            "PredefinedRefcountedProfileSelectionsFactoryTest",
+            ProfileSelections::BuildForRegularAndIncognito()) {}
+};
+
+TEST_F(ProfileKeyedServiceFactoryUnittest,
+       PredefinedRefcountedProfileSelectionsFactoryTest) {
+  PredefinedRefcountedProfileSelectionsFactoryTest factory;
+  TestProfileToUse(factory, regular_profile(), regular_profile());
+  TestProfileToUse(factory, incognito_profile(), incognito_profile());
+
+  TestProfileToUse(factory, guest_profile(), guest_profile());
+  TestProfileToUse(factory, guest_profile_otr(), guest_profile_otr());
+
+#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID)
+  TestProfileToUse(factory, system_profile(), system_profile());
+  TestProfileToUse(factory, system_profile_otr(), system_profile_otr());
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID)
+}
diff --git a/chrome/browser/profiles/refcounted_profile_keyed_service_factory.cc b/chrome/browser/profiles/refcounted_profile_keyed_service_factory.cc
new file mode 100644
index 0000000..de2b824
--- /dev/null
+++ b/chrome/browser/profiles/refcounted_profile_keyed_service_factory.cc
@@ -0,0 +1,31 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/profiles/refcounted_profile_keyed_service_factory.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+
+RefcountedProfileKeyedServiceFactory::RefcountedProfileKeyedServiceFactory(
+    const char* name)
+    : RefcountedProfileKeyedServiceFactory(name,
+                                           ProfileSelections::BuildDefault()) {}
+
+RefcountedProfileKeyedServiceFactory::RefcountedProfileKeyedServiceFactory(
+    const char* name,
+    const ProfileSelections& profile_selections)
+    : RefcountedBrowserContextKeyedServiceFactory(
+          name,
+          BrowserContextDependencyManager::GetInstance()),
+      profile_selections_(profile_selections) {}
+
+RefcountedProfileKeyedServiceFactory::~RefcountedProfileKeyedServiceFactory() =
+    default;
+
+content::BrowserContext*
+RefcountedProfileKeyedServiceFactory::GetBrowserContextToUse(
+    content::BrowserContext* context) const {
+  Profile* profile = Profile::FromBrowserContext(context);
+  return profile_selections_.ApplyProfileSelection(profile);
+}
diff --git a/chrome/browser/profiles/refcounted_profile_keyed_service_factory.h b/chrome/browser/profiles/refcounted_profile_keyed_service_factory.h
new file mode 100644
index 0000000..3a6afb4
--- /dev/null
+++ b/chrome/browser/profiles/refcounted_profile_keyed_service_factory.h
@@ -0,0 +1,50 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PROFILES_REFCOUNTED_PROFILE_KEYED_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_PROFILES_REFCOUNTED_PROFILE_KEYED_SERVICE_FACTORY_H_
+
+#include "components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h"
+
+#include "chrome/browser/profiles/profile_selections.h"
+
+// Similar intermediate class as `ProfileKeyedServiceFactory` but for RefCounted
+// Services.
+// Follow `profile_keyed_service_factory.h` for the documentation and usages.
+// Any change to this class should also be reflected on
+// `ProfileKeyedServiceFactory`.
+// For simplicity the unit tests are found in
+// profile_keyed_service_factory_unittests.cc.
+class RefcountedProfileKeyedServiceFactory
+    : public RefcountedBrowserContextKeyedServiceFactory {
+ public:
+  RefcountedProfileKeyedServiceFactory(
+      const RefcountedProfileKeyedServiceFactory&) = delete;
+  RefcountedProfileKeyedServiceFactory& operator=(
+      const RefcountedProfileKeyedServiceFactory&) = delete;
+
+ protected:
+  // Default constructor, will build the Factory with the default implementation
+  // for `ProfileSelections`.
+  explicit RefcountedProfileKeyedServiceFactory(const char* name);
+  // Constructor taking in the overridden `ProfileSelections` for customized
+  // Profile types service creation. This is the only way to override the
+  // `ProfileSelections` value.
+  RefcountedProfileKeyedServiceFactory(
+      const char* name,
+      const ProfileSelections& profile_selections);
+  ~RefcountedProfileKeyedServiceFactory() override;
+
+  // BrowserContextKeyedServiceFactory:
+  // Final implementation of `GetBrowserContextToUse()`.
+  // Selects the given context to proper context to use based on the
+  // mapping in `ProfileSelections`.
+  content::BrowserContext* GetBrowserContextToUse(
+      content::BrowserContext* context) const final;
+
+ private:
+  const ProfileSelections profile_selections_;
+};
+
+#endif  // !CHROME_BROWSER_PROFILES_REFCOUNTED_PROFILE_KEYED_SERVICE_FACTORY_H_
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/autoclick.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/autoclick.js
index 163ecf2f..e7b592b 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/autoclick.js
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/autoclick.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {EventHandler} from '../../common/event_handler.js';
+
 /**
  * The hex color for the focus rings.
  * @private {string}
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/background.html b/chrome/browser/resources/chromeos/accessibility/accessibility_common/background.html
index 2f1ec524..708ba14 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/background.html
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/background.html
@@ -1,7 +1,2 @@
-<!-- Global scripts. -->
-<script src="/common/chrome_event_handler.js"></script>
-<script src="/common/closure_shim.js"></script>
-<script src="/common/event_handler.js"></script>
-
 <!-- Module entry point. -->
 <script type="module" src="accessibility_common_loader.js"></script>
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/focus_handler.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/focus_handler.js
index 8c457b1..9fb6b4af 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/focus_handler.js
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/focus_handler.js
@@ -7,6 +7,8 @@
 const EventType = chrome.automation.EventType;
 
 import {AutomationPredicate} from '../../common/automation_predicate.js';
+import {EventHandler} from '../../common/event_handler.js';
+
 export class FocusHandler {
   constructor() {
     /** @private {boolean} */
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier.js
index 2c4ab0d..62c6005 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier.js
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {ChromeEventHandler} from '../../common/chrome_event_handler.js';
+import {EventHandler} from '../../common/event_handler.js';
 import {RectUtil} from '../../common/rect_util.js';
 
 const EventType = chrome.automation.EventType;
diff --git a/chrome/browser/resources/chromeos/accessibility/common/chrome_event_handler.js b/chrome/browser/resources/chromeos/accessibility/common/chrome_event_handler.js
index a41cc58..d73bfa1 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/chrome_event_handler.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/chrome_event_handler.js
@@ -6,7 +6,7 @@
  * This class wraps ChromeEvent listeners, adding some convenience
  * functions.
  */
-class ChromeEventHandler {
+export class ChromeEventHandler {
   /**
    * @param {!ChromeEvent} chromeEvent
    * @param {function(...)} callback
diff --git a/chrome/browser/resources/chromeos/accessibility/common/event_handler.js b/chrome/browser/resources/chromeos/accessibility/common/event_handler.js
index 68bf83c..cc29ff5b 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/event_handler.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/event_handler.js
@@ -2,20 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+const AutomationEvent = chrome.automation.AutomationEvent;
+const AutomationNode = chrome.automation.AutomationNode;
+const EventType = chrome.automation.EventType;
+
 /**
  * This class wraps AutomationNode event listeners, adding some convenience
  * functions.
  */
-class EventHandler {
+export class EventHandler {
   /**
-   * @param {!chrome.automation.AutomationNode |
-   *         !Array<!chrome.automation.AutomationNode>} nodes
-   * @param {!chrome.automation.EventType |
-   *     !Array<!chrome.automation.EventType>} types
-   * @param {?function(!chrome.automation.AutomationEvent)} callback
+   * @param {!AutomationNode | !Array<!AutomationNode>} nodes
+   * @param {!EventType | !Array<!EventType>} types
+   * @param {?function(!AutomationEvent)} callback
    * @param {{capture: (boolean|undefined), exactMatch: (boolean|undefined),
    *     listenOnce: (boolean|undefined), predicate:
-   *     ((function(chrome.automation.AutomationEvent): boolean)|undefined)}}
+   *     ((function(AutomationEvent): boolean)|undefined)}}
    *     options
    *   exactMatch Whether to ignore events where the target is not the provided
    *       node.
@@ -26,13 +28,13 @@
    *   predicate A predicate for what events will be processed.
    */
   constructor(nodes, types, callback, options = {}) {
-    /** @private {!Array<!chrome.automation.AutomationNode>} */
+    /** @private {!Array<!AutomationNode>} */
     this.nodes_ = nodes instanceof Array ? nodes : [nodes];
 
-    /** @private {!Array<!chrome.automation.EventType>} */
+    /** @private {!Array<!EventType>} */
     this.types_ = types instanceof Array ? types : [types];
 
-    /** @private {?function(!chrome.automation.AutomationEvent)} */
+    /** @private {?function(!AutomationEvent)} */
     this.callback_ = callback;
 
     /** @private {boolean} */
@@ -46,14 +48,14 @@
 
     /**
      * Default is a function that always returns true.
-     * @private {!function(chrome.automation.AutomationEvent): boolean}
+     * @private {!function(AutomationEvent): boolean}
      */
     this.predicate_ = options.predicate || (e => true);
 
     /** @private {boolean} */
     this.listening_ = false;
 
-    /** @private {!function(chrome.automation.AutomationEvent)} */
+    /** @private {!function(AutomationEvent)} */
     this.handler_ = event => this.handleEvent_(event);
   }
 
@@ -81,7 +83,7 @@
     this.listening_ = false;
   }
 
-  /** @param {?function(!chrome.automation.AutomationEvent)} callback */
+  /** @param {?function(!AutomationEvent)} callback */
   setCallback(callback) {
     this.callback_ = callback;
   }
@@ -89,8 +91,7 @@
   /**
    * Changes what nodes are being listened to. Removes listeners from existing
    *     nodes before adding listeners on new nodes.
-   * @param {!chrome.automation.AutomationNode |
-   *     !Array<!chrome.automation.AutomationNode>} nodes
+   * @param {!AutomationNode | !Array<!AutomationNode>} nodes
    */
   setNodes(nodes) {
     const wasListening = this.listening_;
@@ -103,7 +104,7 @@
 
   /**
    * Adds another node to the set of nodes being listened to.
-   * @param {!chrome.automation.AutomationNode} node
+   * @param {!AutomationNode} node
    */
   addNode(node) {
     this.nodes_.push(node);
@@ -117,7 +118,7 @@
 
   /**
    * Removes a specific node from the set of nodes being listened to.
-   * @param {!chrome.automation.AutomationNode} node
+   * @param {!AutomationNode} node
    */
   removeNode(node) {
     this.nodes_ = this.nodes_.filter(n => n !== node);
diff --git a/chrome/browser/resources/chromeos/accessibility/common/repeated_event_handler.js b/chrome/browser/resources/chromeos/accessibility/common/repeated_event_handler.js
index bfd40f6..d6cc48c 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/repeated_event_handler.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/repeated_event_handler.js
@@ -6,7 +6,7 @@
  * This class assists with processing repeated events in nontrivial ways by
  * allowing only the most recent event to be processed.
  */
-class RepeatedEventHandler {
+export class RepeatedEventHandler {
   /**
    * @param {!chrome.automation.AutomationNode |
    *     !Array<!chrome.automation.AutomationNode>} nodes
diff --git a/chrome/browser/resources/chromeos/accessibility/common/repeated_event_handler_test.js b/chrome/browser/resources/chromeos/accessibility/common/repeated_event_handler_test.js
index 680684b6..ebd816e7 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/repeated_event_handler_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/repeated_event_handler_test.js
@@ -5,11 +5,16 @@
 // Include test fixture.
 GEN_INCLUDE([
   '../select_to_speak/select_to_speak_e2e_test_base.js',
-  'repeated_event_handler.js',
 ]);
 
 /** Test fixture for array_util.js. */
-RepeatedEventHandlerTest = class extends SelectToSpeakE2ETest {};
+RepeatedEventHandlerTest = class extends SelectToSpeakE2ETest {
+  /** @override */
+  async setUpDeferred() {
+    await importModule(
+        'RepeatedEventHandler', '/common/repeated_event_handler.js');
+  }
+};
 
 AX_TEST_F(
     'RepeatedEventHandlerTest', 'RepeatedEventHandledOnce', async function() {
diff --git a/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler.js b/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler.js
index f9ca297..100ccc7 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler.js
@@ -6,7 +6,7 @@
  * This class assists with processing repeated tree changes in nontrivial ways
  * by allowing only the most recent tree change to be processed.
  */
-class RepeatedTreeChangeHandler {
+export class RepeatedTreeChangeHandler {
   /**
    * @param {!chrome.automation.TreeChangeObserverFilter} filter
    * @param {!function(!chrome.automation.TreeChange)} callback
diff --git a/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler_test.js b/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler_test.js
index c48c6e7..63b3660 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler_test.js
@@ -5,11 +5,16 @@
 // Include test fixture.
 GEN_INCLUDE([
   '../select_to_speak/select_to_speak_e2e_test_base.js',
-  'repeated_tree_change_handler.js',
 ]);
 
 /** Test fixture for array_util.js. */
-RepeatedTreeChangeHandlerTest = class extends SelectToSpeakE2ETest {};
+RepeatedTreeChangeHandlerTest = class extends SelectToSpeakE2ETest {
+  /** @override */
+  async setUpDeferred() {
+    await importModule(
+        'RepeatedTreeChangeHandler', '/common/repeated_tree_change_handler.js');
+  }
+};
 
 TEST_F(
     'RepeatedTreeChangeHandlerTest', 'RepeatedTreeChangeHandledOnce',
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/background.html b/chrome/browser/resources/chromeos/accessibility/switch_access/background.html
index 86cf4c57..f15fb31 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/background.html
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/background.html
@@ -1,8 +1,2 @@
-<!-- Global scripts. -->
-<script src="/common/closure_shim.js"></script>
-<script src="/common/event_handler.js"></script>
-<script src="/common/repeated_event_handler.js"></script>
-<script src="/common/repeated_tree_change_handler.js"></script>
-
 <!-- Module entry point. -->
 <script type="module" src="/switch_access/background.js"></script>
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/item_scan_manager.js b/chrome/browser/resources/chromeos/accessibility/switch_access/item_scan_manager.js
index 423b623..78e46ae 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/item_scan_manager.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/item_scan_manager.js
@@ -4,7 +4,10 @@
 
 import {AutomationUtil} from '../common/automation_util.js';
 import {EventGenerator} from '../common/event_generator.js';
+import {EventHandler} from '../common/event_handler.js';
 import {RectUtil} from '../common/rect_util.js';
+import {RepeatedEventHandler} from '../common/repeated_event_handler.js';
+import {RepeatedTreeChangeHandler} from '../common/repeated_tree_change_handler.js';
 
 import {ActionManager} from './action_manager.js';
 import {AutoScanManager} from './auto_scan_manager.js';
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/menu_manager.js b/chrome/browser/resources/chromeos/accessibility/switch_access/menu_manager.js
index 26578af..7e83a214 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/menu_manager.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/menu_manager.js
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import {ArrayUtil} from '../common/array_util.js';
+import {EventHandler} from '../common/event_handler.js';
 
 import {ActionManager} from './action_manager.js';
 import {Navigator} from './navigator.js';
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/back_button_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/back_button_node.js
index 697608c..2005384 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/back_button_node.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/back_button_node.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {EventHandler} from '../../common/event_handler.js';
+import {RepeatedEventHandler} from '../../common/repeated_event_handler.js';
 import {ActionManager} from '../action_manager.js';
 import {FocusRingManager} from '../focus_ring_manager.js';
 import {MenuManager} from '../menu_manager.js';
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node.js
index 41ba1fb..80d9c08 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node.js
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import {constants} from '../../common/constants.js';
+import {RepeatedEventHandler} from '../../common/repeated_event_handler.js';
 import {AutomationTreeWalker} from '../../common/tree_walker.js';
 import {SACache} from '../cache.js';
 import {FocusRingManager} from '../focus_ring_manager.js';
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/combo_box_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/combo_box_node.js
index 4498456..1c970fc33 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/combo_box_node.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/combo_box_node.js
@@ -5,6 +5,7 @@
 import {AutomationPredicate} from '../../common/automation_predicate.js';
 import {EventGenerator} from '../../common/event_generator.js';
 import {KeyCode} from '../../common/key_code.js';
+import {RepeatedEventHandler} from '../../common/repeated_event_handler.js';
 import {Navigator} from '../navigator.js';
 import {SAConstants, SwitchAccessMenuAction} from '../switch_access_constants.js';
 
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/editable_text_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/editable_text_node.js
index 7c4356e..2069179 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/editable_text_node.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/editable_text_node.js
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import {EventGenerator} from '../../common/event_generator.js';
+import {EventHandler} from '../../common/event_handler.js';
 import {KeyCode} from '../../common/key_code.js';
 import {Navigator} from '../navigator.js';
 import {SwitchAccess} from '../switch_access.js';
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/keyboard_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/keyboard_node.js
index 17f0058..c5c246d 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/keyboard_node.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/keyboard_node.js
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import {EventGenerator} from '../../common/event_generator.js';
+import {EventHandler} from '../../common/event_handler.js';
 import {RectUtil} from '../../common/rect_util.js';
 import {AutoScanManager} from '../auto_scan_manager.js';
 import {Navigator} from '../navigator.js';
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js
index 67cfd32..11d980e4d 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {EventHandler} from '../common/event_handler.js';
+
 import {Commands} from './commands.js';
 import {Navigator} from './navigator.js';
 import {KeyboardRootNode} from './nodes/keyboard_node.js';
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/text_navigation_manager.js b/chrome/browser/resources/chromeos/accessibility/switch_access/text_navigation_manager.js
index ae0ff02..db41be8 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/text_navigation_manager.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/text_navigation_manager.js
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import {EventGenerator} from '../common/event_generator.js';
+import {EventHandler} from '../common/event_handler.js';
 import {KeyCode} from '../common/key_code.js';
 
 import {ActionManager} from './action_manager.js';
diff --git a/chrome/browser/resources/chromeos/input_method/OWNERS b/chrome/browser/resources/chromeos/input_method/OWNERS
index e24a43f..338c0e0e 100644
--- a/chrome/browser/resources/chromeos/input_method/OWNERS
+++ b/chrome/browser/resources/chromeos/input_method/OWNERS
@@ -1,6 +1,3 @@
 shend@chromium.org
 dvallet@chromium.org
 shuchen@chromium.org
-fengyuan@chromium.org
-wuyingbing@chromium.org
-zhangchi@chromium.org
diff --git a/chrome/browser/resources/inspect/OWNERS b/chrome/browser/resources/inspect/OWNERS
index 9dabc36..a2df980 100644
--- a/chrome/browser/resources/inspect/OWNERS
+++ b/chrome/browser/resources/inspect/OWNERS
@@ -1,4 +1,3 @@
 dgozman@chromium.org
 dsv@chromium.org
-pfeldman@chromium.org
 yangguo@chromium.org
diff --git a/chrome/browser/resources/side_panel/read_anything/app.ts b/chrome/browser/resources/side_panel/read_anything/app.ts
index b1d3fd1..5f87a65 100644
--- a/chrome/browser/resources/side_panel/read_anything/app.ts
+++ b/chrome/browser/resources/side_panel/read_anything/app.ts
@@ -81,6 +81,10 @@
     if (url) {
       element.setAttribute('href', url);
     }
+    const language = chrome.readAnything.getLanguage(nodeId);
+    if (language) {
+      element.setAttribute('lang', language);
+    }
     this.appendChildNodes_(element, nodeId);
     return element;
   }
diff --git a/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts b/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts
index 1bcccbf..7b197e3f 100644
--- a/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts
+++ b/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts
@@ -27,6 +27,9 @@
     // Returns the HTML tag of the AXNode for the provided AXNodeID.
     function getHtmlTag(nodeId: number): string;
 
+    // Returns the language of the AXNode for the provided AXNodeID.
+    function getLanguage(nodeId: number): string;
+
     // Returns the text content of the AXNode for the provided AXNodeID.
     function getTextContent(nodeId: number): string;
 
diff --git a/chrome/browser/resources/welcome/landing_view.html b/chrome/browser/resources/welcome/landing_view.html
index 1ca3da3..bc2c4ee 100644
--- a/chrome/browser/resources/welcome/landing_view.html
+++ b/chrome/browser/resources/welcome/landing_view.html
@@ -19,8 +19,10 @@
   <onboarding-background id="background" class="fade-in">
   </onboarding-background>
   <div id="text">
-    <h2 class="fade-in">$i18n{landingDescription}</h2>
-    <h1 class="fade-in" tabindex="-1">$i18n{landingTitle}</h1>
+    <div class="header">
+      <h1 class="fade-in" tabindex="-1">$i18n{landingTitle}</h1>
+      <div class="subheading fade-in">$i18n{landingDescription}</div>
+    </div>
     <cr-button class="action-button fade-in" on-click="onNewUserClick_">
       $i18n{landingNewUser}
     </cr-button>
diff --git a/chrome/browser/resources/welcome/shared/splash_pages_shared.css b/chrome/browser/resources/welcome/shared/splash_pages_shared.css
index 7072216..2097f6e 100644
--- a/chrome/browser/resources/welcome/shared/splash_pages_shared.css
+++ b/chrome/browser/resources/welcome/shared/splash_pages_shared.css
@@ -29,21 +29,28 @@
   flex-direction: column;
 }
 
+.header {
+  display: flex;
+  flex-direction: column;
+}
+
 h1 {
   color: var(--cr-primary-text-color);
   font-size: 4rem;
   margin-bottom: 40px;
   margin-top: 16px;
+  order: 2;
   text-align: center;
 }
 
-h2 {
+.subheading {
   color: var(--cr-secondary-text-color);
   font-size: 1.5rem;
   font-weight: 500;
   line-height: 2.25rem;
   margin: 0;
   opacity: 0.8;
+  order: 1;
   text-align: center;
 }
 
diff --git a/chrome/browser/resources/welcome/signin_view.html b/chrome/browser/resources/welcome/signin_view.html
index 1473e57..016b6ea4 100644
--- a/chrome/browser/resources/welcome/signin_view.html
+++ b/chrome/browser/resources/welcome/signin_view.html
@@ -14,8 +14,10 @@
   <onboarding-background id="background" class="fade-in">
   </onboarding-background>
   <div id="text">
-    <h2>$i18n{signInSubHeader}</h2>
-    <h1 tabindex="-1">$i18n{signInHeader}</h1>
+    <div class="header">
+      <h1 tabindex="-1">$i18n{signInHeader}</h1>
+      <div class="subheading">$i18n{signInSubHeader}</div>
+    </div>
     <cr-button class="action-button" on-click="onSignInClick_">
       $i18n{signIn}
     </cr-button>
diff --git a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/SigninMetricsUtils.java b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/SigninMetricsUtils.java
index ed8d7073..11a6cd0 100644
--- a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/SigninMetricsUtils.java
+++ b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/SigninMetricsUtils.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.signin.services;
 
+import androidx.annotation.IntDef;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.annotations.NativeMethods;
@@ -13,10 +14,26 @@
 import org.chromium.components.signin.metrics.AccountConsistencyPromoAction;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Util methods for signin metrics logging.
  */
 public class SigninMetricsUtils {
+    /** Used to record Signin.AddAccountState histogram. Do not change existing values. */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({State.REQUESTED, State.STARTED, State.SUCCEEDED, State.FAILED, State.CANCELLED,
+            State.NULL_ACCOUNT_NAME, State.NUM_STATES})
+    public @interface State {
+        int REQUESTED = 0;
+        int STARTED = 1;
+        int SUCCEEDED = 2;
+        int FAILED = 3;
+        int CANCELLED = 4;
+        int NULL_ACCOUNT_NAME = 5;
+        int NUM_STATES = 6;
+    }
     /**
      * Logs a {@link ProfileAccountManagementMetrics} for a given {@link GAIAServiceType}.
      */
@@ -56,6 +73,12 @@
         }
     }
 
+    /** Logs Signin.AddAccountState histogram. */
+    public static void logAddAccountStateHistogram(@State int state) {
+        RecordHistogram.recordEnumeratedHistogram(
+                "Signin.AddAccountState", state, State.NUM_STATES);
+    }
+
     @VisibleForTesting
     @NativeMethods
     public interface Natives {
diff --git a/chrome/browser/sync/bookmark_sync_service_factory.cc b/chrome/browser/sync/bookmark_sync_service_factory.cc
index 7612f5db..43ef55b 100644
--- a/chrome/browser/sync/bookmark_sync_service_factory.cc
+++ b/chrome/browser/sync/bookmark_sync_service_factory.cc
@@ -4,10 +4,8 @@
 
 #include "chrome/browser/sync/bookmark_sync_service_factory.h"
 
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/undo/bookmark_undo_service_factory.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/sync_bookmarks/bookmark_sync_service.h"
 
 // static
@@ -23,9 +21,9 @@
 }
 
 BookmarkSyncServiceFactory::BookmarkSyncServiceFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "BookmarkSyncServiceFactory",
-          BrowserContextDependencyManager::GetInstance()) {
+          ProfileSelections::BuildRedirectedInIncognito()) {
   DependsOn(BookmarkUndoServiceFactory::GetInstance());
 }
 
@@ -37,8 +35,3 @@
   return new sync_bookmarks::BookmarkSyncService(
       BookmarkUndoServiceFactory::GetForProfileIfExists(profile));
 }
-
-content::BrowserContext* BookmarkSyncServiceFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
diff --git a/chrome/browser/sync/bookmark_sync_service_factory.h b/chrome/browser/sync/bookmark_sync_service_factory.h
index 66368c6..db622597 100644
--- a/chrome/browser/sync/bookmark_sync_service_factory.h
+++ b/chrome/browser/sync/bookmark_sync_service_factory.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_SYNC_BOOKMARK_SYNC_SERVICE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 
@@ -15,7 +15,7 @@
 }
 
 // Singleton that owns the bookmark sync service.
-class BookmarkSyncServiceFactory : public BrowserContextKeyedServiceFactory {
+class BookmarkSyncServiceFactory : public ProfileKeyedServiceFactory {
  public:
   // Returns the instance of BookmarkSyncService associated with this profile
   // (creating one if none exists).
@@ -37,8 +37,6 @@
   // BrowserContextKeyedServiceFactory implementation.
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* profile) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 };
 
 #endif  // CHROME_BROWSER_SYNC_BOOKMARK_SYNC_SERVICE_FACTORY_H_
diff --git a/chrome/browser/sync/desk_sync_service_factory.cc b/chrome/browser/sync/desk_sync_service_factory.cc
index 12aed4e..9adff35 100644
--- a/chrome/browser/sync/desk_sync_service_factory.cc
+++ b/chrome/browser/sync/desk_sync_service_factory.cc
@@ -10,7 +10,6 @@
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
 #include "chrome/common/channel_info.h"
 #include "components/desks_storage/core/desk_sync_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/sync/model/model_type_store_service.h"
 
 // static
@@ -26,9 +25,7 @@
 }
 
 DeskSyncServiceFactory::DeskSyncServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "DeskSyncService",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("DeskSyncService") {
   DependsOn(ModelTypeStoreServiceFactory::GetInstance());
 }
 
diff --git a/chrome/browser/sync/desk_sync_service_factory.h b/chrome/browser/sync/desk_sync_service_factory.h
index 43db64e..faf089c8 100644
--- a/chrome/browser/sync/desk_sync_service_factory.h
+++ b/chrome/browser/sync/desk_sync_service_factory.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_SYNC_DESK_SYNC_SERVICE_FACTORY_H_
 #define CHROME_BROWSER_SYNC_DESK_SYNC_SERVICE_FACTORY_H_
 
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 
@@ -19,7 +19,7 @@
 }  // namespace desks_storage
 
 // A factory to create DeskSyncService for a given browser context.
-class DeskSyncServiceFactory : public BrowserContextKeyedServiceFactory {
+class DeskSyncServiceFactory : public ProfileKeyedServiceFactory {
  public:
   static desks_storage::DeskSyncService* GetForProfile(Profile* profile);
   static DeskSyncServiceFactory* GetInstance();
diff --git a/chrome/browser/sync/device_info_sync_service_factory.cc b/chrome/browser/sync/device_info_sync_service_factory.cc
index 246a276..464eddff 100644
--- a/chrome/browser/sync/device_info_sync_service_factory.cc
+++ b/chrome/browser/sync/device_info_sync_service_factory.cc
@@ -21,7 +21,6 @@
 #include "chrome/browser/sync/model_type_store_service_factory.h"
 #include "chrome/browser/sync/sync_invalidations_service_factory.h"
 #include "chrome/common/channel_info.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/sync/invalidations/sync_invalidations_service.h"
 #include "components/sync/model/model_type_store_service.h"
 #include "components/sync_device_info/device_info_prefs.h"
@@ -62,9 +61,7 @@
 }
 
 DeviceInfoSyncServiceFactory::DeviceInfoSyncServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "DeviceInfoSyncService",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("DeviceInfoSyncService") {
   DependsOn(ModelTypeStoreServiceFactory::GetInstance());
   DependsOn(SyncInvalidationsServiceFactory::GetInstance());
 }
diff --git a/chrome/browser/sync/device_info_sync_service_factory.h b/chrome/browser/sync/device_info_sync_service_factory.h
index 5083fa3..0639be5 100644
--- a/chrome/browser/sync/device_info_sync_service_factory.h
+++ b/chrome/browser/sync/device_info_sync_service_factory.h
@@ -7,7 +7,7 @@
 
 #include <vector>
 
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 
@@ -21,7 +21,7 @@
 class DeviceInfoTracker;
 }  // namespace syncer
 
-class DeviceInfoSyncServiceFactory : public BrowserContextKeyedServiceFactory {
+class DeviceInfoSyncServiceFactory : public ProfileKeyedServiceFactory {
  public:
   static syncer::DeviceInfoSyncService* GetForProfile(Profile* profile);
   static DeviceInfoSyncServiceFactory* GetInstance();
diff --git a/chrome/browser/sync/model_type_store_service_factory.cc b/chrome/browser/sync/model_type_store_service_factory.cc
index 541e411..bf4158e 100644
--- a/chrome/browser/sync/model_type_store_service_factory.cc
+++ b/chrome/browser/sync/model_type_store_service_factory.cc
@@ -4,9 +4,7 @@
 
 #include "chrome/browser/sync/model_type_store_service_factory.h"
 
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/sync/model/model_type_store_service_impl.h"
 
 // static
@@ -22,9 +20,9 @@
 }
 
 ModelTypeStoreServiceFactory::ModelTypeStoreServiceFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "ModelTypeStoreService",
-          BrowserContextDependencyManager::GetInstance()) {}
+          ProfileSelections::BuildRedirectedInIncognito()) {}
 
 ModelTypeStoreServiceFactory::~ModelTypeStoreServiceFactory() = default;
 
@@ -33,8 +31,3 @@
   Profile* profile = Profile::FromBrowserContext(context);
   return new syncer::ModelTypeStoreServiceImpl(profile->GetPath());
 }
-
-content::BrowserContext* ModelTypeStoreServiceFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
diff --git a/chrome/browser/sync/model_type_store_service_factory.h b/chrome/browser/sync/model_type_store_service_factory.h
index ba06e6e..914f853 100644
--- a/chrome/browser/sync/model_type_store_service_factory.h
+++ b/chrome/browser/sync/model_type_store_service_factory.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_SYNC_MODEL_TYPE_STORE_SERVICE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 
@@ -14,7 +14,7 @@
 class ModelTypeStoreService;
 }  // namespace syncer
 
-class ModelTypeStoreServiceFactory : public BrowserContextKeyedServiceFactory {
+class ModelTypeStoreServiceFactory : public ProfileKeyedServiceFactory {
  public:
   static syncer::ModelTypeStoreService* GetForProfile(Profile* profile);
   static ModelTypeStoreServiceFactory* GetInstance();
@@ -32,8 +32,6 @@
   // BrowserContextKeyedServiceFactory:
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 };
 
 #endif  // CHROME_BROWSER_SYNC_MODEL_TYPE_STORE_SERVICE_FACTORY_H_
diff --git a/chrome/browser/sync/send_tab_to_self_sync_service_factory.cc b/chrome/browser/sync/send_tab_to_self_sync_service_factory.cc
index 86532f47..03d1950 100644
--- a/chrome/browser/sync/send_tab_to_self_sync_service_factory.cc
+++ b/chrome/browser/sync/send_tab_to_self_sync_service_factory.cc
@@ -11,7 +11,6 @@
 #include "chrome/browser/sync/device_info_sync_service_factory.h"
 #include "chrome/browser/sync/model_type_store_service_factory.h"
 #include "chrome/common/channel_info.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/send_tab_to_self/send_tab_to_self_sync_service.h"
 #include "components/sync/model/model_type_store_service.h"
 #include "components/sync_device_info/device_info_sync_service.h"
@@ -30,9 +29,7 @@
 }
 
 SendTabToSelfSyncServiceFactory::SendTabToSelfSyncServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "SendTabToSelfSyncService",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("SendTabToSelfSyncService") {
   DependsOn(ModelTypeStoreServiceFactory::GetInstance());
   DependsOn(HistoryServiceFactory::GetInstance());
   DependsOn(DeviceInfoSyncServiceFactory::GetInstance());
diff --git a/chrome/browser/sync/send_tab_to_self_sync_service_factory.h b/chrome/browser/sync/send_tab_to_self_sync_service_factory.h
index 01991a1..d1ae82a 100644
--- a/chrome/browser/sync/send_tab_to_self_sync_service_factory.h
+++ b/chrome/browser/sync/send_tab_to_self_sync_service_factory.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_SYNC_SEND_TAB_TO_SELF_SYNC_SERVICE_FACTORY_H_
 #define CHROME_BROWSER_SYNC_SEND_TAB_TO_SELF_SYNC_SERVICE_FACTORY_H_
 
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 
@@ -18,8 +18,7 @@
 class SendTabToSelfSyncService;
 }  // namespace send_tab_to_self
 
-class SendTabToSelfSyncServiceFactory
-    : public BrowserContextKeyedServiceFactory {
+class SendTabToSelfSyncServiceFactory : public ProfileKeyedServiceFactory {
  public:
   static send_tab_to_self::SendTabToSelfSyncService* GetForProfile(
       Profile* profile);
diff --git a/chrome/browser/sync/session_sync_service_factory.cc b/chrome/browser/sync/session_sync_service_factory.cc
index a83f2b6c..3ddbfc4 100644
--- a/chrome/browser/sync/session_sync_service_factory.cc
+++ b/chrome/browser/sync/session_sync_service_factory.cc
@@ -20,7 +20,6 @@
 #include "chrome/common/url_constants.h"
 #include "components/dom_distiller/core/url_constants.h"
 #include "components/history/core/browser/history_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/sync/model/model_type_store_service.h"
 #include "components/sync_device_info/device_info_sync_service.h"
 #include "components/sync_device_info/device_info_tracker.h"
@@ -143,9 +142,7 @@
 }
 
 SessionSyncServiceFactory::SessionSyncServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "SessionSyncService",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("SessionSyncService") {
   DependsOn(FaviconServiceFactory::GetInstance());
   DependsOn(HistoryServiceFactory::GetInstance());
   DependsOn(ModelTypeStoreServiceFactory::GetInstance());
diff --git a/chrome/browser/sync/session_sync_service_factory.h b/chrome/browser/sync/session_sync_service_factory.h
index 2427b3b..820f07a 100644
--- a/chrome/browser/sync/session_sync_service_factory.h
+++ b/chrome/browser/sync/session_sync_service_factory.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_SYNC_SESSION_SYNC_SERVICE_FACTORY_H_
 #define CHROME_BROWSER_SYNC_SESSION_SYNC_SERVICE_FACTORY_H_
 
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class GURL;
 class Profile;
@@ -19,7 +19,7 @@
 class SessionSyncService;
 }  // namespace sync_sessions
 
-class SessionSyncServiceFactory : public BrowserContextKeyedServiceFactory {
+class SessionSyncServiceFactory : public ProfileKeyedServiceFactory {
  public:
   static sync_sessions::SessionSyncService* GetForProfile(Profile* profile);
   static SessionSyncServiceFactory* GetInstance();
diff --git a/chrome/browser/sync/sessions/sync_sessions_web_contents_router_factory.cc b/chrome/browser/sync/sessions/sync_sessions_web_contents_router_factory.cc
index b4bc449..e31a9d3 100644
--- a/chrome/browser/sync/sessions/sync_sessions_web_contents_router_factory.cc
+++ b/chrome/browser/sync/sessions/sync_sessions_web_contents_router_factory.cc
@@ -7,8 +7,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/sessions/sync_sessions_web_contents_router.h"
 
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-
 namespace sync_sessions {
 
 // static
@@ -25,9 +23,7 @@
 }
 
 SyncSessionsWebContentsRouterFactory::SyncSessionsWebContentsRouterFactory()
-    : BrowserContextKeyedServiceFactory(
-          "SyncSessionsWebContentsRouter",
-          BrowserContextDependencyManager::GetInstance()) {}
+    : ProfileKeyedServiceFactory("SyncSessionsWebContentsRouter") {}
 
 SyncSessionsWebContentsRouterFactory::~SyncSessionsWebContentsRouterFactory() =
     default;
diff --git a/chrome/browser/sync/sessions/sync_sessions_web_contents_router_factory.h b/chrome/browser/sync/sessions/sync_sessions_web_contents_router_factory.h
index 7031ead..0864116 100644
--- a/chrome/browser/sync/sessions/sync_sessions_web_contents_router_factory.h
+++ b/chrome/browser/sync/sessions/sync_sessions_web_contents_router_factory.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_SYNC_SESSIONS_SYNC_SESSIONS_WEB_CONTENTS_ROUTER_FACTORY_H_
 #define CHROME_BROWSER_SYNC_SESSIONS_SYNC_SESSIONS_WEB_CONTENTS_ROUTER_FACTORY_H_
 
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 
@@ -18,8 +18,7 @@
 
 class SyncSessionsWebContentsRouter;
 
-class SyncSessionsWebContentsRouterFactory
-    : public BrowserContextKeyedServiceFactory {
+class SyncSessionsWebContentsRouterFactory : public ProfileKeyedServiceFactory {
  public:
   // Get the SyncSessionsWebContentsRouter service for |profile|, creating one
   // if needed.
diff --git a/chrome/browser/sync/sync_invalidations_service_factory.cc b/chrome/browser/sync/sync_invalidations_service_factory.cc
index 845e2aa..06a160c 100644
--- a/chrome/browser/sync/sync_invalidations_service_factory.cc
+++ b/chrome/browser/sync/sync_invalidations_service_factory.cc
@@ -10,7 +10,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "components/gcm_driver/gcm_profile_service.h"
 #include "components/gcm_driver/instance_id/instance_id_profile_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/sync/base/features.h"
 #include "components/sync/invalidations/sync_invalidations_service_impl.h"
 
@@ -27,9 +26,7 @@
 }
 
 SyncInvalidationsServiceFactory::SyncInvalidationsServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "SyncInvalidationsService",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("SyncInvalidationsService") {
   DependsOn(gcm::GCMProfileServiceFactory::GetInstance());
   DependsOn(instance_id::InstanceIDProfileServiceFactory::GetInstance());
 }
diff --git a/chrome/browser/sync/sync_invalidations_service_factory.h b/chrome/browser/sync/sync_invalidations_service_factory.h
index 2edd651..3cc3e532 100644
--- a/chrome/browser/sync/sync_invalidations_service_factory.h
+++ b/chrome/browser/sync/sync_invalidations_service_factory.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_SYNC_SYNC_INVALIDATIONS_SERVICE_FACTORY_H_
 #define CHROME_BROWSER_SYNC_SYNC_INVALIDATIONS_SERVICE_FACTORY_H_
 
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 #include "base/no_destructor.h"
 
@@ -15,8 +15,7 @@
 class SyncInvalidationsService;
 }  // namespace syncer
 
-class SyncInvalidationsServiceFactory
-    : public BrowserContextKeyedServiceFactory {
+class SyncInvalidationsServiceFactory : public ProfileKeyedServiceFactory {
  public:
   SyncInvalidationsServiceFactory(const SyncInvalidationsServiceFactory&) =
       delete;
diff --git a/chrome/browser/sync/sync_service_factory.cc b/chrome/browser/sync/sync_service_factory.cc
index 1df51b2..d9406dd6 100644
--- a/chrome/browser/sync/sync_service_factory.cc
+++ b/chrome/browser/sync/sync_service_factory.cc
@@ -48,7 +48,6 @@
 #include "chrome/common/buildflags.h"
 #include "chrome/common/channel_info.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/network_time/network_time_tracker.h"
 #include "components/sync/base/command_line_switches.h"
 #include "components/sync/driver/sync_service_impl.h"
@@ -199,9 +198,7 @@
 }
 
 SyncServiceFactory::SyncServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "SyncService",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("SyncService") {
   // The SyncServiceImpl depends on various SyncableServices being around
   // when it is shut down.  Specify those dependencies here to build the proper
   // destruction order. Note that some of the dependencies are listed here but
diff --git a/chrome/browser/sync/sync_service_factory.h b/chrome/browser/sync/sync_service_factory.h
index 361edf1..bfbd29c 100644
--- a/chrome/browser/sync/sync_service_factory.h
+++ b/chrome/browser/sync/sync_service_factory.h
@@ -8,7 +8,7 @@
 #include <memory>
 #include <vector>
 
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 
@@ -22,7 +22,7 @@
 class SyncService;
 }  // namespace syncer
 
-class SyncServiceFactory : public BrowserContextKeyedServiceFactory {
+class SyncServiceFactory : public ProfileKeyedServiceFactory {
  public:
   // Returns the SyncService for the given profile.
   static syncer::SyncService* GetForProfile(Profile* profile);
diff --git a/chrome/browser/sync/user_event_service_factory.cc b/chrome/browser/sync/user_event_service_factory.cc
index c5b0557..080e2b9 100644
--- a/chrome/browser/sync/user_event_service_factory.cc
+++ b/chrome/browser/sync/user_event_service_factory.cc
@@ -8,12 +8,10 @@
 #include <utility>
 
 #include "base/bind.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/model_type_store_service_factory.h"
 #include "chrome/browser/sync/session_sync_service_factory.h"
 #include "chrome/common/channel_info.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/base/report_unrecoverable_error.h"
 #include "components/sync/driver/sync_service.h"
@@ -39,9 +37,9 @@
 }
 
 UserEventServiceFactory::UserEventServiceFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "UserEventService",
-          BrowserContextDependencyManager::GetInstance()) {
+          ProfileSelections::BuildForRegularAndIncognito()) {
   DependsOn(ModelTypeStoreServiceFactory::GetInstance());
   DependsOn(SessionSyncServiceFactory::GetInstance());
 }
@@ -69,9 +67,4 @@
   return new syncer::UserEventServiceImpl(std::move(bridge));
 }
 
-content::BrowserContext* UserEventServiceFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextOwnInstanceInIncognito(context);
-}
-
 }  // namespace browser_sync
diff --git a/chrome/browser/sync/user_event_service_factory.h b/chrome/browser/sync/user_event_service_factory.h
index e7464bf..bf19a51 100644
--- a/chrome/browser/sync/user_event_service_factory.h
+++ b/chrome/browser/sync/user_event_service_factory.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_SYNC_USER_EVENT_SERVICE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 
@@ -16,7 +16,7 @@
 
 namespace browser_sync {
 
-class UserEventServiceFactory : public BrowserContextKeyedServiceFactory {
+class UserEventServiceFactory : public ProfileKeyedServiceFactory {
  public:
   static syncer::UserEventService* GetForProfile(Profile* profile);
   static UserEventServiceFactory* GetInstance();
@@ -33,8 +33,6 @@
   // BrowserContextKeyedServiceFactory:
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 };
 
 }  // namespace browser_sync
diff --git a/chrome/browser/sync/wifi_configuration_sync_service_factory.cc b/chrome/browser/sync/wifi_configuration_sync_service_factory.cc
index 6eed1f9..378496c5 100644
--- a/chrome/browser/sync/wifi_configuration_sync_service_factory.cc
+++ b/chrome/browser/sync/wifi_configuration_sync_service_factory.cc
@@ -13,7 +13,6 @@
 #include "chromeos/ash/components/sync_wifi/pending_network_configuration_tracker_impl.h"
 #include "chromeos/ash/components/sync_wifi/wifi_configuration_bridge.h"
 #include "chromeos/ash/components/sync_wifi/wifi_configuration_sync_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/sync/model/model_type_store_service.h"
 
@@ -45,9 +44,7 @@
 }
 
 WifiConfigurationSyncServiceFactory::WifiConfigurationSyncServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "WifiConfigurationSyncService",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("WifiConfigurationSyncService") {
   DependsOn(ModelTypeStoreServiceFactory::GetInstance());
 }
 
diff --git a/chrome/browser/sync/wifi_configuration_sync_service_factory.h b/chrome/browser/sync/wifi_configuration_sync_service_factory.h
index 40c8d091..6e1ad36 100644
--- a/chrome/browser/sync/wifi_configuration_sync_service_factory.h
+++ b/chrome/browser/sync/wifi_configuration_sync_service_factory.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_SYNC_WIFI_CONFIGURATION_SYNC_SERVICE_FACTORY_H_
 #define CHROME_BROWSER_SYNC_WIFI_CONFIGURATION_SYNC_SERVICE_FACTORY_H_
 
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 
@@ -18,8 +18,7 @@
 struct DefaultSingletonTraits;
 }  // namespace base
 
-class WifiConfigurationSyncServiceFactory
-    : public BrowserContextKeyedServiceFactory {
+class WifiConfigurationSyncServiceFactory : public ProfileKeyedServiceFactory {
  public:
   static ash::sync_wifi::WifiConfigurationSyncService* GetForProfile(
       Profile* profile,
diff --git a/chrome/browser/sync_file_system/sync_file_system_service_factory.cc b/chrome/browser/sync_file_system/sync_file_system_service_factory.cc
index f65579e..913d19e 100644
--- a/chrome/browser/sync_file_system/sync_file_system_service_factory.cc
+++ b/chrome/browser/sync_file_system/sync_file_system_service_factory.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/sync_file_system/local/local_file_sync_service.h"
 #include "chrome/browser/sync_file_system/sync_file_system_service.h"
 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "extensions/browser/extension_registry_factory.h"
 
 namespace sync_file_system {
@@ -40,9 +39,7 @@
 }
 
 SyncFileSystemServiceFactory::SyncFileSystemServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-        "SyncFileSystemService",
-        BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("SyncFileSystemService") {
   typedef std::set<BrowserContextKeyedServiceFactory*> FactorySet;
   FactorySet factories;
   factories.insert(extensions::ExtensionRegistryFactory::GetInstance());
diff --git a/chrome/browser/sync_file_system/sync_file_system_service_factory.h b/chrome/browser/sync_file_system/sync_file_system_service_factory.h
index 122fec9a..d5eafc91 100644
--- a/chrome/browser/sync_file_system/sync_file_system_service_factory.h
+++ b/chrome/browser/sync_file_system/sync_file_system_service_factory.h
@@ -8,7 +8,7 @@
 #include <memory>
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 
@@ -18,7 +18,7 @@
 class RemoteFileSyncService;
 class SyncFileSystemService;
 
-class SyncFileSystemServiceFactory : public BrowserContextKeyedServiceFactory {
+class SyncFileSystemServiceFactory : public ProfileKeyedServiceFactory {
  public:
   static SyncFileSystemService* GetForProfile(Profile* profile);
   static SyncFileSystemServiceFactory* GetInstance();
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java
index 1d31dc6..42e61c5 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java
@@ -57,7 +57,7 @@
     public void onRestoreFailed(Tab tab) {}
 
     @Override
-    public void onFaviconUpdated(Tab tab, Bitmap icon) {}
+    public void onFaviconUpdated(Tab tab, Bitmap icon, GURL iconUrl) {}
 
     @Override
     public void onTitleUpdated(Tab tab) {}
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabObserver.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabObserver.java
index 0333875e..1326f62e 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabObserver.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabObserver.java
@@ -106,8 +106,9 @@
      * Called when the favicon of a {@link Tab} has been updated.
      * @param tab The notifying {@link Tab}.
      * @param icon The favicon that was received.
+     * @param iconUrl The URL that the icon was fetched from.
      */
-    void onFaviconUpdated(Tab tab, Bitmap icon);
+    void onFaviconUpdated(Tab tab, Bitmap icon, GURL iconUrl);
 
     /**
      * Called when the title of a {@link Tab} changes.
diff --git a/chrome/browser/themes/theme_service_factory.cc b/chrome/browser/themes/theme_service_factory.cc
index 47184cef..a4aad78 100644
--- a/chrome/browser/themes/theme_service_factory.cc
+++ b/chrome/browser/themes/theme_service_factory.cc
@@ -8,11 +8,9 @@
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/extensions/extension_system_factory.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/themes/theme_service.h"
 #include "chrome/common/pref_names.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 #include "extensions/browser/extension_prefs_factory.h"
@@ -71,9 +69,9 @@
 }
 
 ThemeServiceFactory::ThemeServiceFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "ThemeService",
-          BrowserContextDependencyManager::GetInstance()) {
+          ProfileSelections::BuildRedirectedInIncognito()) {
   DependsOn(extensions::ExtensionRegistryFactory::GetInstance());
   DependsOn(extensions::ExtensionPrefsFactory::GetInstance());
   DependsOn(extensions::ExtensionSystemFactory::GetInstance());
@@ -117,11 +115,6 @@
   registry->RegisterIntegerPref(prefs::kPolicyThemeColor, SK_ColorTRANSPARENT);
 }
 
-content::BrowserContext* ThemeServiceFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
-
 bool ThemeServiceFactory::ServiceIsCreatedWithBrowserContext() const {
   return true;
 }
diff --git a/chrome/browser/themes/theme_service_factory.h b/chrome/browser/themes/theme_service_factory.h
index ec7d340..cfd1148 100644
--- a/chrome/browser/themes/theme_service_factory.h
+++ b/chrome/browser/themes/theme_service_factory.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_THEMES_THEME_SERVICE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 class ThemeService;
@@ -18,7 +18,7 @@
 // Singleton that owns all ThemeServices and associates them with
 // Profiles. Listens for the Profile's destruction notification and cleans up
 // the associated ThemeService.
-class ThemeServiceFactory : public BrowserContextKeyedServiceFactory {
+class ThemeServiceFactory : public ProfileKeyedServiceFactory {
  public:
   // Returns the ThemeService that provides theming resources for
   // |profile|. Note that even if a Profile doesn't have a theme installed, it
@@ -46,8 +46,6 @@
       content::BrowserContext* profile) const override;
   void RegisterProfilePrefs(
       user_prefs::PrefRegistrySyncable* registry) override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
   bool ServiceIsCreatedWithBrowserContext() const override;
 };
 
diff --git a/chrome/browser/translate/translate_model_service_factory.cc b/chrome/browser/translate/translate_model_service_factory.cc
index e310385e..d7539ca8 100644
--- a/chrome/browser/translate/translate_model_service_factory.cc
+++ b/chrome/browser/translate/translate_model_service_factory.cc
@@ -11,9 +11,7 @@
 #include "base/task/thread_pool.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/translate/core/browser/translate_model_service.h"
 #include "components/translate/core/common/translate_util.h"
 
@@ -31,9 +29,9 @@
 }
 
 TranslateModelServiceFactory::TranslateModelServiceFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "TranslateModelService",
-          BrowserContextDependencyManager::GetInstance()) {
+          ProfileSelections::BuildForRegularAndIncognito()) {
   if (translate::IsTFLiteLanguageDetectionEnabled())
     DependsOn(OptimizationGuideKeyedServiceFactory::GetInstance());
 }
@@ -59,8 +57,3 @@
   }
   return nullptr;
 }
-
-content::BrowserContext* TranslateModelServiceFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextOwnInstanceInIncognito(context);
-}
diff --git a/chrome/browser/translate/translate_model_service_factory.h b/chrome/browser/translate/translate_model_service_factory.h
index 98833686..ed1beba 100644
--- a/chrome/browser/translate/translate_model_service_factory.h
+++ b/chrome/browser/translate/translate_model_service_factory.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_TRANSLATE_TRANSLATE_MODEL_SERVICE_FACTORY_H_
 
 #include "base/no_destructor.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 #include "components/translate/core/browser/translate_model_service.h"
 
 namespace content {
@@ -17,7 +17,7 @@
 
 // LazyInstance that owns all TranslateModelService(s) and associates
 // them with Profiles.
-class TranslateModelServiceFactory : public BrowserContextKeyedServiceFactory {
+class TranslateModelServiceFactory : public ProfileKeyedServiceFactory {
  public:
   // Gets the TranslateModelService for the profile.
   //
@@ -38,8 +38,6 @@
   // BrowserContextKeyedServiceFactory:
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 };
 
 #endif  //  CHROME_BROWSER_TRANSLATE_TRANSLATE_MODEL_SERVICE_FACTORY_H_
diff --git a/chrome/browser/translate/translate_ranker_factory.cc b/chrome/browser/translate/translate_ranker_factory.cc
index d6d181b..9dad68c9 100644
--- a/chrome/browser/translate/translate_ranker_factory.cc
+++ b/chrome/browser/translate/translate_ranker_factory.cc
@@ -5,8 +5,6 @@
 #include "chrome/browser/translate/translate_ranker_factory.h"
 
 #include "base/files/file_path.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/translate/core/browser/translate_ranker_impl.h"
 #include "content/public/browser/browser_context.h"
@@ -27,9 +25,9 @@
 }
 
 TranslateRankerFactory::TranslateRankerFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "TranslateRanker",
-          BrowserContextDependencyManager::GetInstance()) {}
+          ProfileSelections::BuildRedirectedInIncognito()) {}
 
 TranslateRankerFactory::~TranslateRankerFactory() {}
 
@@ -40,9 +38,4 @@
       TranslateRankerImpl::GetModelURL(), ukm::UkmRecorder::Get());
 }
 
-content::BrowserContext* TranslateRankerFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
-
 }  // namespace translate
diff --git a/chrome/browser/translate/translate_ranker_factory.h b/chrome/browser/translate/translate_ranker_factory.h
index e6c31a4..32be3c0 100644
--- a/chrome/browser/translate/translate_ranker_factory.h
+++ b/chrome/browser/translate/translate_ranker_factory.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_TRANSLATE_TRANSLATE_RANKER_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 namespace content {
 class BrowserContext;
@@ -16,7 +16,7 @@
 
 class TranslateRanker;
 
-class TranslateRankerFactory : public BrowserContextKeyedServiceFactory {
+class TranslateRankerFactory : public ProfileKeyedServiceFactory {
  public:
   static TranslateRankerFactory* GetInstance();
   static translate::TranslateRanker* GetForBrowserContext(
@@ -34,8 +34,6 @@
   // BrowserContextKeyedServiceFactory:
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 };
 
 }  // namespace translate
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java
index ea710e7..2709c35 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java
@@ -1047,6 +1047,7 @@
     }
 
     private boolean shouldShowMicButton() {
+        if (shouldShowDeleteButton()) return false;
         if (!mNativeInitialized || mVoiceRecognitionHandler == null
                 || !mVoiceRecognitionHandler.isVoiceSearchEnabled()) {
             return false;
@@ -1055,9 +1056,8 @@
         if (mIsTablet && mShouldShowButtonsWhenUnfocused) {
             return !isToolbarMicEnabled && (mUrlHasFocus || mIsUrlFocusChangeInProgress);
         } else {
-            boolean deleteButtonVisible = shouldShowDeleteButton();
             boolean canShowMicButton = !mIsTablet || !isToolbarMicEnabled;
-            return canShowMicButton && !deleteButtonVisible
+            return canShowMicButton
                     && (mUrlHasFocus || mIsUrlFocusChangeInProgress
                             || mIsLocationBarFocusedFromNtpScroll
                             || mShouldShowMicButtonWhenUnfocused);
@@ -1065,6 +1065,8 @@
     }
 
     private boolean shouldShowLensButton() {
+        if (shouldShowDeleteButton()) return false;
+
         // When this method is called on UI inflation, return false as the native is not ready.
         if (!mNativeInitialized) {
             return false;
@@ -1085,9 +1087,8 @@
             return (mUrlHasFocus || mIsUrlFocusChangeInProgress) && isLensOnOmniboxEnabled();
         }
 
-        return !shouldShowDeleteButton()
-                && (mUrlHasFocus || mIsUrlFocusChangeInProgress
-                        || mIsLocationBarFocusedFromNtpScroll || mShouldShowLensButtonWhenUnfocused)
+        return (mUrlHasFocus || mIsUrlFocusChangeInProgress || mIsLocationBarFocusedFromNtpScroll
+                       || mShouldShowLensButtonWhenUnfocused)
                 && isLensOnOmniboxEnabled();
     }
 
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java
index 32fffd5..e060539 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java
@@ -1052,8 +1052,9 @@
 
     @Test
     public void testLensButtonVisibility_lensEnabledWithInputText_tablet() {
+        // Do not show lens when the omnibox already has input.
         doReturn(true).when(mLensController).isLensEnabled(any());
-        verifyLensButtonVisibilityWhenFocusChanges(true, "text");
+        verifyLensButtonVisibilityWhenFocusChanges(false, "text");
     }
 
     private void verifyLensButtonVisibilityWhenFocusChanges(
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SyncConsentFragmentBase.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SyncConsentFragmentBase.java
index 79a16f2..b0513b1a 100644
--- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SyncConsentFragmentBase.java
+++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SyncConsentFragmentBase.java
@@ -35,6 +35,7 @@
 import org.chromium.chrome.browser.signin.services.ProfileDataCache;
 import org.chromium.chrome.browser.signin.services.SigninManager;
 import org.chromium.chrome.browser.signin.services.SigninMetricsUtils;
+import org.chromium.chrome.browser.signin.services.SigninMetricsUtils.State;
 import org.chromium.chrome.browser.signin.services.UnifiedConsentServiceBridge;
 import org.chromium.chrome.browser.sync.SyncService;
 import org.chromium.chrome.browser.ui.signin.account_picker.AccountPickerCoordinator;
@@ -217,6 +218,7 @@
 
     /**
      * Called if signinAndEnableSync() succeeds.
+     *
      * @param settingsClicked Whether the user requested to see their sync settings
      */
     protected abstract void closeAndMaybeOpenSyncSettings(boolean settingsClicked);
@@ -446,8 +448,8 @@
     }
 
     /**
-     * Account picker is hidden if there are no accounts on the device. Also, accept button
-     * becomes "Add account" button in this case.
+     * Account picker is hidden if there are no accounts on the device. Also, accept button becomes
+     * "Add account" button in this case.
      */
     private void setHasAccounts(boolean hasAccounts) {
         assert mSigninView != null;
@@ -703,16 +705,17 @@
     @Override
     public void addAccount() {
         mIsAccountAdditionInProgress = true;
+        SigninMetricsUtils.logAddAccountStateHistogram(State.REQUESTED);
         mAccountManagerFacade.createAddAccountIntent((@Nullable Intent intent) -> {
             if (intent != null) {
+                SigninMetricsUtils.logAddAccountStateHistogram(State.STARTED);
                 startActivityForResult(intent, ADD_ACCOUNT_REQUEST_CODE);
                 return;
             }
 
             // AccountManagerFacade couldn't create intent, use SigninUtils to open settings
             // instead.
-            // TODO(https://crbug.com/1351315): Add histogram to check if this flow is triggered
-            // in user devices.
+            SigninMetricsUtils.logAddAccountStateHistogram(State.FAILED);
             SigninUtils.openSettingsForAllAccounts(getActivity());
             mIsAccountAdditionInProgress = false;
             if (showTangibleSyncConsentView()) {
@@ -732,15 +735,20 @@
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
         if (requestCode == ADD_ACCOUNT_REQUEST_CODE) {
             if (resultCode == Activity.RESULT_OK && data != null) {
+                SigninMetricsUtils.logAddAccountStateHistogram(State.SUCCEEDED);
                 String addedAccountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
                 if (addedAccountName != null) {
                     mSelectedAccountName = addedAccountName;
+                } else {
+                    SigninMetricsUtils.logAddAccountStateHistogram(State.NULL_ACCOUNT_NAME);
                 }
+            } else {
+                SigninMetricsUtils.logAddAccountStateHistogram(State.CANCELLED);
             }
             if (showTangibleSyncConsentView()) {
                 mIsAccountAdditionInProgress = false;
-                mAccountManagerFacade.getAccounts().then(this::updateAccounts);
             }
+            mAccountManagerFacade.getAccounts().then(this::updateAccounts);
         }
     }
 
@@ -828,4 +836,4 @@
         }
         selectAccount(defaultAccount);
     }
-}
+}
\ No newline at end of file
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service_factory.cc b/chrome/browser/ui/app_list/app_list_syncable_service_factory.cc
index a5ae7bb..4296292 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service_factory.cc
+++ b/chrome/browser/ui/app_list/app_list_syncable_service_factory.cc
@@ -9,11 +9,9 @@
 #include "build/build_config.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/prefs/pref_service.h"
 #include "extensions/browser/extension_system_provider.h"
 #include "extensions/browser/extensions_browser_client.h"
@@ -43,6 +41,18 @@
   if (!ash::ProfileHelper::IsRegularProfile(profile)) {
     return nullptr;
   }
+
+  // No service for sign in profile.
+  if (ash::ProfileHelper::IsSigninProfile(profile))
+    return nullptr;
+
+  // This condition still needs to be explicitly stated here despite having
+  // ProfileKeyedService logic implemented because `IsGuestSession()` and
+  // `IsRegularProfile()` are not yet mutually exclusive in ASH and Lacros.
+  // TODO(rsult): remove this condition when `IsGuestSession() is fixed.
+  if (profile->IsGuestSession() && !profile->IsOffTheRecord())
+    return nullptr;
+
   VLOG(1) << "BuildInstanceFor: " << profile->GetDebugName()
           << " (" << profile << ")";
   return std::make_unique<AppListSyncableService>(profile);
@@ -54,9 +64,15 @@
 }
 
 AppListSyncableServiceFactory::AppListSyncableServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-        "AppListSyncableService",
-        BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory(
+          "AppListSyncableService",
+          ProfileSelections::Builder()
+              .WithRegular(ProfileSelection::kRedirectedToOriginal)
+              // Use OTR profile for Guest Session.
+              .WithGuest(ProfileSelection::kOffTheRecordOnly)
+              // No service for system profile.
+              .WithSystem(ProfileSelection::kNone)
+              .Build()) {
   VLOG(1) << "AppListSyncableServiceFactory()";
   typedef std::set<BrowserContextKeyedServiceFactory*> FactorySet;
   FactorySet dependent_factories;
@@ -83,33 +99,6 @@
     user_prefs::PrefRegistrySyncable* registry) {
 }
 
-content::BrowserContext* AppListSyncableServiceFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  Profile* const profile = Profile::FromBrowserContext(context);
-  // No service if |context| is not a profile.
-  if (!profile)
-    return nullptr;
-
-  // No service for system profile.
-  if (profile->IsSystemProfile())
-    return nullptr;
-
-  // No service for sign in profile.
-  if (ash::ProfileHelper::IsSigninProfile(profile))
-    return nullptr;
-
-  // Use OTR profile for Guest Session.
-  if (profile->IsGuestSession()) {
-    return profile->IsOffTheRecord()
-               ? chrome::GetBrowserContextOwnInstanceInIncognito(context)
-               : nullptr;
-  }
-
-  // This matches the logic in ExtensionSyncServiceFactory, which uses the
-  // orginal browser context.
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
-
 bool AppListSyncableServiceFactory::ServiceIsCreatedWithBrowserContext() const {
   // Start AppListSyncableService early so that the app list positions are
   // available before the app list is opened.
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service_factory.h b/chrome/browser/ui/app_list/app_list_syncable_service_factory.h
index 5f1cc7f..4466404 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service_factory.h
+++ b/chrome/browser/ui/app_list/app_list_syncable_service_factory.h
@@ -8,7 +8,7 @@
 #include <memory>
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 
@@ -19,7 +19,7 @@
 // Singleton that owns all AppListSyncableServices and associates them with
 // Profiles. Listens for the Profile's destruction notification and cleans up
 // the associated AppListSyncableService.
-class AppListSyncableServiceFactory : public BrowserContextKeyedServiceFactory {
+class AppListSyncableServiceFactory : public ProfileKeyedServiceFactory {
  public:
   static AppListSyncableService* GetForProfile(Profile* profile);
 
@@ -46,8 +46,6 @@
       content::BrowserContext* profile) const override;
   void RegisterProfilePrefs(
       user_prefs::PrefRegistrySyncable* registry) override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
   bool ServiceIsCreatedWithBrowserContext() const override;
   bool ServiceIsNULLWhileTesting() const override;
 };
diff --git a/chrome/browser/ui/app_list/app_sync_ui_state_factory.cc b/chrome/browser/ui/app_list/app_sync_ui_state_factory.cc
index eb977be..3b2640c3 100644
--- a/chrome/browser/ui/app_list/app_sync_ui_state_factory.cc
+++ b/chrome/browser/ui/app_list/app_sync_ui_state_factory.cc
@@ -7,7 +7,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/sync_service_factory.h"
 #include "chrome/browser/ui/app_list/app_sync_ui_state.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "extensions/browser/extension_registry_factory.h"
 
 // static
@@ -25,9 +24,7 @@
 }
 
 AppSyncUIStateFactory::AppSyncUIStateFactory()
-    : BrowserContextKeyedServiceFactory(
-          "AppSyncUIState",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("AppSyncUIState") {
   DependsOn(extensions::ExtensionRegistryFactory::GetInstance());
   DependsOn(SyncServiceFactory::GetInstance());
 }
diff --git a/chrome/browser/ui/app_list/app_sync_ui_state_factory.h b/chrome/browser/ui/app_list/app_sync_ui_state_factory.h
index 71e19b8b..63586d8 100644
--- a/chrome/browser/ui/app_list/app_sync_ui_state_factory.h
+++ b/chrome/browser/ui/app_list/app_sync_ui_state_factory.h
@@ -6,13 +6,13 @@
 #define CHROME_BROWSER_UI_APP_LIST_APP_SYNC_UI_STATE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class AppSyncUIState;
 class Profile;
 
 // Singleton that owns all AppSyncUIStates and associates them with profiles.
-class AppSyncUIStateFactory : public BrowserContextKeyedServiceFactory {
+class AppSyncUIStateFactory : public ProfileKeyedServiceFactory {
  public:
   AppSyncUIStateFactory(const AppSyncUIStateFactory&) = delete;
   AppSyncUIStateFactory& operator=(const AppSyncUIStateFactory&) = delete;
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.cc
index 7e347d1..1e7ede6 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.cc
@@ -8,10 +8,8 @@
 #include "ash/components/arc/session/arc_service_manager.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/notifications/notification_display_service_factory.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "content/public/browser/browser_context.h"
 
 bool ArcAppListPrefsFactory::is_sync_test_ = false;
@@ -45,9 +43,11 @@
 }
 
 ArcAppListPrefsFactory::ArcAppListPrefsFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "ArcAppListPrefs",
-          BrowserContextDependencyManager::GetInstance()) {
+          // This matches the logic in ExtensionSyncServiceFactory, which uses
+          // the original browser context.
+          ProfileSelections::BuildRedirectedInIncognito()) {
   DependsOn(NotificationDisplayServiceFactory::GetInstance());
 }
 
@@ -74,10 +74,3 @@
 
   return ArcAppListPrefs::Create(profile);
 }
-
-content::BrowserContext* ArcAppListPrefsFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  // This matches the logic in ExtensionSyncServiceFactory, which uses the
-  // orginal browser context.
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h b/chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h
index 9cc8600..713597b7 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h
@@ -11,11 +11,11 @@
 #include "ash/components/arc/mojom/app.mojom-forward.h"
 #include "ash/components/arc/session/connection_holder.h"
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class ArcAppListPrefs;
 
-class ArcAppListPrefsFactory : public BrowserContextKeyedServiceFactory {
+class ArcAppListPrefsFactory : public ProfileKeyedServiceFactory {
  public:
   static ArcAppListPrefs* GetForBrowserContext(
       content::BrowserContext* context);
@@ -36,8 +36,6 @@
 
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 
   static bool is_sync_test_;
 
diff --git a/chrome/browser/ui/app_list/arc/arc_package_syncable_service_factory.cc b/chrome/browser/ui/app_list/arc/arc_package_syncable_service_factory.cc
index 3aac917..49b4434 100644
--- a/chrome/browser/ui/app_list/arc/arc_package_syncable_service_factory.cc
+++ b/chrome/browser/ui/app_list/arc/arc_package_syncable_service_factory.cc
@@ -4,11 +4,9 @@
 
 #include "chrome/browser/ui/app_list/arc/arc_package_syncable_service_factory.h"
 
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
 #include "chrome/browser/ui/app_list/arc/arc_package_syncable_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_context.h"
 
@@ -29,9 +27,11 @@
 }
 
 ArcPackageSyncableServiceFactory::ArcPackageSyncableServiceFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "ArcPackageSyncableService",
-          BrowserContextDependencyManager::GetInstance()) {
+          // This matches the logic in ExtensionSyncServiceFactory, which uses
+          // the original browser context.
+          ProfileSelections::BuildRedirectedInIncognito()) {
   DependsOn(ArcAppListPrefsFactory::GetInstance());
 }
 
@@ -46,12 +46,4 @@
                                            ArcAppListPrefs::Get(profile));
 }
 
-content::BrowserContext*
-ArcPackageSyncableServiceFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  // This matches the logic in ExtensionSyncServiceFactory, which uses the
-  // orginal browser context.
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
-
 }  // namespace arc
diff --git a/chrome/browser/ui/app_list/arc/arc_package_syncable_service_factory.h b/chrome/browser/ui/app_list/arc/arc_package_syncable_service_factory.h
index 1ad2053..96ad785 100644
--- a/chrome/browser/ui/app_list/arc/arc_package_syncable_service_factory.h
+++ b/chrome/browser/ui/app_list/arc/arc_package_syncable_service_factory.h
@@ -6,14 +6,13 @@
 #define CHROME_BROWSER_UI_APP_LIST_ARC_ARC_PACKAGE_SYNCABLE_SERVICE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 namespace arc {
 
 class ArcPackageSyncableService;
 
-class ArcPackageSyncableServiceFactory
-    : public BrowserContextKeyedServiceFactory {
+class ArcPackageSyncableServiceFactory : public ProfileKeyedServiceFactory {
  public:
   ArcPackageSyncableServiceFactory(const ArcPackageSyncableServiceFactory&) =
       delete;
@@ -33,8 +32,6 @@
 
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 };
 
 }  // namespace arc
diff --git a/chrome/browser/ui/app_list/arc/arc_usb_host_permission_manager_factory.cc b/chrome/browser/ui/app_list/arc/arc_usb_host_permission_manager_factory.cc
index 2009f298..9122109 100644
--- a/chrome/browser/ui/app_list/arc/arc_usb_host_permission_manager_factory.cc
+++ b/chrome/browser/ui/app_list/arc/arc_usb_host_permission_manager_factory.cc
@@ -5,10 +5,8 @@
 #include "chrome/browser/ui/app_list/arc/arc_usb_host_permission_manager_factory.h"
 
 #include "ash/components/arc/usb/usb_host_bridge.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
 #include "chrome/browser/ui/app_list/arc/arc_usb_host_permission_manager.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "content/public/browser/browser_context.h"
 
 namespace arc {
@@ -28,9 +26,11 @@
 }
 
 ArcUsbHostPermissionManagerFactory::ArcUsbHostPermissionManagerFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "ArcUsbHostPermissionManager",
-          BrowserContextDependencyManager::GetInstance()) {
+          // This matches the logic in ExtensionSyncServiceFactory, which uses
+          // the original browser context.
+          ProfileSelections::BuildRedirectedInIncognito()) {
   DependsOn(ArcAppListPrefsFactory::GetInstance());
   DependsOn(ArcUsbHostBridge::GetFactory());
 }
@@ -42,12 +42,4 @@
   return ArcUsbHostPermissionManager::Create(context);
 }
 
-content::BrowserContext*
-ArcUsbHostPermissionManagerFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  // This matches the logic in ExtensionSyncServiceFactory, which uses the
-  // orginal browser context.
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
-
 }  // namespace arc
diff --git a/chrome/browser/ui/app_list/arc/arc_usb_host_permission_manager_factory.h b/chrome/browser/ui/app_list/arc/arc_usb_host_permission_manager_factory.h
index 4c4625b7..f34fa2b 100644
--- a/chrome/browser/ui/app_list/arc/arc_usb_host_permission_manager_factory.h
+++ b/chrome/browser/ui/app_list/arc/arc_usb_host_permission_manager_factory.h
@@ -6,14 +6,13 @@
 #define CHROME_BROWSER_UI_APP_LIST_ARC_ARC_USB_HOST_PERMISSION_MANAGER_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 namespace arc {
 
 class ArcUsbHostPermissionManager;
 
-class ArcUsbHostPermissionManagerFactory
-    : public BrowserContextKeyedServiceFactory {
+class ArcUsbHostPermissionManagerFactory : public ProfileKeyedServiceFactory {
  public:
   ArcUsbHostPermissionManagerFactory(
       const ArcUsbHostPermissionManagerFactory&) = delete;
@@ -34,8 +33,6 @@
 
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 };
 
 }  // namespace arc
diff --git a/chrome/browser/ui/app_list/arc/arc_vpn_provider_manager_factory.cc b/chrome/browser/ui/app_list/arc/arc_vpn_provider_manager_factory.cc
index 8be5f24a..d72bcd1 100644
--- a/chrome/browser/ui/app_list/arc/arc_vpn_provider_manager_factory.cc
+++ b/chrome/browser/ui/app_list/arc/arc_vpn_provider_manager_factory.cc
@@ -4,10 +4,8 @@
 
 #include "chrome/browser/ui/app_list/arc/arc_vpn_provider_manager_factory.h"
 
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
 #include "chrome/browser/ui/app_list/arc/arc_vpn_provider_manager.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "content/public/browser/browser_context.h"
 
 namespace app_list {
@@ -25,9 +23,11 @@
 }
 
 ArcVpnProviderManagerFactory::ArcVpnProviderManagerFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "ArcVpnProviderManager",
-          BrowserContextDependencyManager::GetInstance()) {
+          // This matches the logic in ExtensionSyncServiceFactory, which uses
+          // the original browser context.
+          ProfileSelections::BuildRedirectedInIncognito()) {
   DependsOn(ArcAppListPrefsFactory::GetInstance());
 }
 
@@ -38,11 +38,4 @@
   return ArcVpnProviderManager::Create(context);
 }
 
-content::BrowserContext* ArcVpnProviderManagerFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  // This matches the logic in ExtensionSyncServiceFactory, which uses the
-  // orginal browser context.
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
-
 }  // namespace app_list
diff --git a/chrome/browser/ui/app_list/arc/arc_vpn_provider_manager_factory.h b/chrome/browser/ui/app_list/arc/arc_vpn_provider_manager_factory.h
index 895b8ef..ea4eef0 100644
--- a/chrome/browser/ui/app_list/arc/arc_vpn_provider_manager_factory.h
+++ b/chrome/browser/ui/app_list/arc/arc_vpn_provider_manager_factory.h
@@ -6,13 +6,13 @@
 #define CHROME_BROWSER_UI_APP_LIST_ARC_ARC_VPN_PROVIDER_MANAGER_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 namespace app_list {
 
 class ArcVpnProviderManager;
 
-class ArcVpnProviderManagerFactory : public BrowserContextKeyedServiceFactory {
+class ArcVpnProviderManagerFactory : public ProfileKeyedServiceFactory {
  public:
   ArcVpnProviderManagerFactory(const ArcVpnProviderManagerFactory&) = delete;
   ArcVpnProviderManagerFactory& operator=(const ArcVpnProviderManagerFactory&) =
@@ -31,8 +31,6 @@
 
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 };
 
 }  // namespace app_list
diff --git a/chrome/browser/ui/ash/calendar/calendar_keyed_service_factory.cc b/chrome/browser/ui/ash/calendar/calendar_keyed_service_factory.cc
index bcba7089..443aeef 100644
--- a/chrome/browser/ui/ash/calendar/calendar_keyed_service_factory.cc
+++ b/chrome/browser/ui/ash/calendar/calendar_keyed_service_factory.cc
@@ -9,7 +9,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/ui/ash/calendar/calendar_keyed_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/user_manager/user.h"
 
 namespace ash {
@@ -21,9 +20,7 @@
 }
 
 CalendarKeyedServiceFactory::CalendarKeyedServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "CalendarKeyedService",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("CalendarKeyedService") {
   DependsOn(IdentityManagerFactory::GetInstance());
 }
 
diff --git a/chrome/browser/ui/ash/calendar/calendar_keyed_service_factory.h b/chrome/browser/ui/ash/calendar/calendar_keyed_service_factory.h
index 589ef17..2bce550 100644
--- a/chrome/browser/ui/ash/calendar/calendar_keyed_service_factory.h
+++ b/chrome/browser/ui/ash/calendar/calendar_keyed_service_factory.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_ASH_CALENDAR_CALENDAR_KEYED_SERVICE_FACTORY_H_
 
 #include "base/no_destructor.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 namespace content {
 class BrowserContext;
@@ -19,7 +19,7 @@
 // Factory class for browser context keyed calendar services. Only builds
 // service instance for `user->HasGaiaAccount()` and returns `nullptr` for the
 // other user types.
-class CalendarKeyedServiceFactory : public BrowserContextKeyedServiceFactory {
+class CalendarKeyedServiceFactory : public ProfileKeyedServiceFactory {
  public:
   static CalendarKeyedServiceFactory* GetInstance();
 
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index 0d58653..b85b77d 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -117,8 +117,9 @@
 }
 
 std::unique_ptr<ash::GlanceablesDelegate>
-ChromeShellDelegate::CreateGlanceablesDelegate() const {
-  return std::make_unique<ChromeGlanceablesDelegate>();
+ChromeShellDelegate::CreateGlanceablesDelegate(
+    ash::GlanceablesController* controller) const {
+  return std::make_unique<ChromeGlanceablesDelegate>(controller);
 }
 
 ash::AccessibilityDelegate* ChromeShellDelegate::CreateAccessibilityDelegate() {
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.h b/chrome/browser/ui/ash/chrome_shell_delegate.h
index df0cbda..e8fdcffb 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.h
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.h
@@ -25,8 +25,8 @@
   bool CanShowWindowForUser(const aura::Window* window) const override;
   std::unique_ptr<ash::CaptureModeDelegate> CreateCaptureModeDelegate()
       const override;
-  std::unique_ptr<ash::GlanceablesDelegate> CreateGlanceablesDelegate()
-      const override;
+  std::unique_ptr<ash::GlanceablesDelegate> CreateGlanceablesDelegate(
+      ash::GlanceablesController* controller) const override;
   ash::AccessibilityDelegate* CreateAccessibilityDelegate() override;
   std::unique_ptr<ash::BackGestureContextualNudgeDelegate>
   CreateBackGestureContextualNudgeDelegate(
diff --git a/chrome/browser/ui/ash/glanceables/chrome_glanceables_delegate.cc b/chrome/browser/ui/ash/glanceables/chrome_glanceables_delegate.cc
index 92406802..9ce8098e 100644
--- a/chrome/browser/ui/ash/glanceables/chrome_glanceables_delegate.cc
+++ b/chrome/browser/ui/ash/glanceables/chrome_glanceables_delegate.cc
@@ -4,14 +4,55 @@
 
 #include "chrome/browser/ui/ash/glanceables/chrome_glanceables_delegate.h"
 
+#include "ash/glanceables/glanceables_controller.h"
+#include "base/check.h"
+#include "base/check_op.h"
+#include "base/command_line.h"
 #include "base/notreached.h"
+#include "chrome/common/chrome_switches.h"
 
-ChromeGlanceablesDelegate::ChromeGlanceablesDelegate() = default;
+namespace {
+ChromeGlanceablesDelegate* g_instance = nullptr;
+}  // namespace
 
-ChromeGlanceablesDelegate::~ChromeGlanceablesDelegate() = default;
+ChromeGlanceablesDelegate::ChromeGlanceablesDelegate(
+    ash::GlanceablesController* controller)
+    : controller_(controller) {
+  DCHECK(controller_);
+
+  DCHECK(!g_instance);
+  g_instance = this;
+}
+
+ChromeGlanceablesDelegate::~ChromeGlanceablesDelegate() {
+  DCHECK_EQ(g_instance, this);
+  g_instance = nullptr;
+}
+
+// static
+ChromeGlanceablesDelegate* ChromeGlanceablesDelegate::Get() {
+  return g_instance;
+}
+
+void ChromeGlanceablesDelegate::OnPrimaryUserSessionStarted() {
+  if (ShouldShowOnLogin())
+    controller_->ShowOnLogin();
+}
 
 void ChromeGlanceablesDelegate::RestoreSession() {
   // TODO(crbug.com/1353119): Use the FullRestoreService to trigger session
   // restore.
   NOTIMPLEMENTED();
 }
+
+bool ChromeGlanceablesDelegate::ShouldShowOnLogin() const {
+  // Skip glanceables when --no-first-run is passed. This prevents glanceables
+  // from interfering with existing browser tests (they pass this switch) and is
+  // also helpful when bisecting.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoFirstRun))
+    return false;
+
+  // TODO(crbug.com/1353119): Use logic from FullRestoreService to decide
+  // whether or not to show.
+  return true;
+}
diff --git a/chrome/browser/ui/ash/glanceables/chrome_glanceables_delegate.h b/chrome/browser/ui/ash/glanceables/chrome_glanceables_delegate.h
index 9358623..aa6e454 100644
--- a/chrome/browser/ui/ash/glanceables/chrome_glanceables_delegate.h
+++ b/chrome/browser/ui/ash/glanceables/chrome_glanceables_delegate.h
@@ -7,18 +7,34 @@
 
 #include "ash/glanceables/glanceables_delegate.h"
 
+namespace ash {
+class GlanceablesController;
+}  // namespace ash
+
 // Implements the GlanceablesDelegate interface, allowing access to
 // functionality in the //chrome/browser layer.
 class ChromeGlanceablesDelegate : public ash::GlanceablesDelegate {
  public:
-  ChromeGlanceablesDelegate();
+  explicit ChromeGlanceablesDelegate(ash::GlanceablesController* controller);
   ChromeGlanceablesDelegate(const ChromeGlanceablesDelegate&) = delete;
   ChromeGlanceablesDelegate& operator=(const ChromeGlanceablesDelegate&) =
       delete;
   ~ChromeGlanceablesDelegate() override;
 
+  static ChromeGlanceablesDelegate* Get();
+
+  // Called when the primary user logs in, after various KeyedServices are
+  // created.
+  void OnPrimaryUserSessionStarted();
+
   // ash::GlanceablesDelegate:
   void RestoreSession() override;
+
+ private:
+  // Returns true if glanceables should be show for the current login.
+  bool ShouldShowOnLogin() const;
+
+  ash::GlanceablesController* const controller_;
 };
 
 #endif  // CHROME_BROWSER_UI_ASH_GLANCEABLES_CHROME_GLANCEABLES_DELEGATE_H_
diff --git a/chrome/browser/ui/ash/glanceables/glanceables_browsertest.cc b/chrome/browser/ui/ash/glanceables/glanceables_browsertest.cc
new file mode 100644
index 0000000..c57f292
--- /dev/null
+++ b/chrome/browser/ui/ash/glanceables/glanceables_browsertest.cc
@@ -0,0 +1,29 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/constants/ash_features.h"
+#include "ash/glanceables/glanceables_controller.h"
+#include "ash/shell.h"
+#include "base/test/scoped_feature_list.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "content/public/test/browser_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Tests for the glanceables feature, which adds a "welcome back" screen on
+// some logins.
+class GlanceablesBrowserTest : public InProcessBrowserTest {
+ public:
+  void SetUpDefaultCommandLine(base::CommandLine* command_line) override {
+    // The test harness adds --no-first-run. Remove it so glanceables show up.
+    command_line->RemoveSwitch(switches::kNoFirstRun);
+  }
+
+ protected:
+  base::test::ScopedFeatureList features_{ash::features::kGlanceables};
+};
+
+IN_PROC_BROWSER_TEST_F(GlanceablesBrowserTest, ShowsOnLogin) {
+  EXPECT_TRUE(ash::Shell::Get()->glanceables_controller()->IsShowing());
+}
diff --git a/chrome/browser/ui/ash/global_media_controls/cast_media_notification_producer_keyed_service_factory.cc b/chrome/browser/ui/ash/global_media_controls/cast_media_notification_producer_keyed_service_factory.cc
index 318a298..55e696d 100644
--- a/chrome/browser/ui/ash/global_media_controls/cast_media_notification_producer_keyed_service_factory.cc
+++ b/chrome/browser/ui/ash/global_media_controls/cast_media_notification_producer_keyed_service_factory.cc
@@ -9,15 +9,12 @@
 #include "chrome/browser/media/router/media_router_feature.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/ash/global_media_controls/cast_media_notification_producer_keyed_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/user_manager/user_manager.h"
 #include "media/base/media_switches.h"
 
 CastMediaNotificationProducerKeyedServiceFactory::
     CastMediaNotificationProducerKeyedServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "CastMediaNotificationProducerKeyedService",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("CastMediaNotificationProducerKeyedService") {
   DependsOn(media_router::ChromeMediaRouterFactory::GetInstance());
 }
 CastMediaNotificationProducerKeyedServiceFactory::
diff --git a/chrome/browser/ui/ash/global_media_controls/cast_media_notification_producer_keyed_service_factory.h b/chrome/browser/ui/ash/global_media_controls/cast_media_notification_producer_keyed_service_factory.h
index ebeba2c..17f8ab8 100644
--- a/chrome/browser/ui/ash/global_media_controls/cast_media_notification_producer_keyed_service_factory.h
+++ b/chrome/browser/ui/ash/global_media_controls/cast_media_notification_producer_keyed_service_factory.h
@@ -5,14 +5,14 @@
 #ifndef CHROME_BROWSER_UI_ASH_GLOBAL_MEDIA_CONTROLS_CAST_MEDIA_NOTIFICATION_PRODUCER_KEYED_SERVICE_FACTORY_H_
 #define CHROME_BROWSER_UI_ASH_GLOBAL_MEDIA_CONTROLS_CAST_MEDIA_NOTIFICATION_PRODUCER_KEYED_SERVICE_FACTORY_H_
 
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 namespace content {
 class BrowserContext;
 }
 
 class CastMediaNotificationProducerKeyedServiceFactory
-    : public BrowserContextKeyedServiceFactory {
+    : public ProfileKeyedServiceFactory {
  public:
   CastMediaNotificationProducerKeyedServiceFactory();
   CastMediaNotificationProducerKeyedServiceFactory(
diff --git a/chrome/browser/ui/cocoa/screentime/history_bridge_factory.h b/chrome/browser/ui/cocoa/screentime/history_bridge_factory.h
index d42577e..e3f6083a 100644
--- a/chrome/browser/ui/cocoa/screentime/history_bridge_factory.h
+++ b/chrome/browser/ui/cocoa/screentime/history_bridge_factory.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_COCOA_SCREENTIME_HISTORY_BRIDGE_FACTORY_H_
 #define CHROME_BROWSER_UI_COCOA_SCREENTIME_HISTORY_BRIDGE_FACTORY_H_
 
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 namespace screentime {
 
@@ -13,7 +13,7 @@
 // HistoryBridge instance for each loaded Profile. The HistoryBridge instance is
 // created when the Profile is initially created, so there's no explicit
 // creation step.
-class HistoryBridgeFactory : public BrowserContextKeyedServiceFactory {
+class HistoryBridgeFactory : public ProfileKeyedServiceFactory {
  public:
   HistoryBridgeFactory();
   ~HistoryBridgeFactory() override;
diff --git a/chrome/browser/ui/cocoa/screentime/history_bridge_factory.mm b/chrome/browser/ui/cocoa/screentime/history_bridge_factory.mm
index 962cabe9..f65bbbf5 100644
--- a/chrome/browser/ui/cocoa/screentime/history_bridge_factory.mm
+++ b/chrome/browser/ui/cocoa/screentime/history_bridge_factory.mm
@@ -10,7 +10,6 @@
 #include "chrome/browser/ui/cocoa/screentime/history_bridge.h"
 #include "chrome/browser/ui/cocoa/screentime/history_deleter_impl.h"
 #include "chrome/browser/ui/cocoa/screentime/screentime_features.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 namespace screentime {
 
@@ -21,9 +20,7 @@
 }
 
 HistoryBridgeFactory::HistoryBridgeFactory()
-    : BrowserContextKeyedServiceFactory(
-          "screentime::HistoryBridge",
-          BrowserContextDependencyManager::GetInstance()) {}
+    : ProfileKeyedServiceFactory("screentime::HistoryBridge") {}
 HistoryBridgeFactory::~HistoryBridgeFactory() = default;
 
 // static
diff --git a/chrome/browser/ui/cookie_controls/cookie_controls_service_factory.cc b/chrome/browser/ui/cookie_controls/cookie_controls_service_factory.cc
index b28cc3f..32252744 100644
--- a/chrome/browser/ui/cookie_controls/cookie_controls_service_factory.cc
+++ b/chrome/browser/ui/cookie_controls/cookie_controls_service_factory.cc
@@ -4,11 +4,9 @@
 
 #include "chrome/browser/ui/cookie_controls/cookie_controls_service_factory.h"
 
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/cookie_controls/cookie_controls_service.h"
 #include "components/content_settings/core/common/cookie_controls_enforcement.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 // static
 CookieControlsService* CookieControlsServiceFactory::GetForProfile(
@@ -28,19 +26,14 @@
 }
 
 CookieControlsServiceFactory::CookieControlsServiceFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "CookieControlsService",
-          BrowserContextDependencyManager::GetInstance()) {}
+          // The incognito profile has its own CookieSettings. Therefore, it
+          // should get its own CookieControlsService.
+          ProfileSelections::BuildForRegularAndIncognito()) {}
 
 CookieControlsServiceFactory::~CookieControlsServiceFactory() = default;
 
-content::BrowserContext* CookieControlsServiceFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  // The incognito profile has its own CookieSettings. Therefore, it should
-  // get its own CookieControlsService.
-  return chrome::GetBrowserContextOwnInstanceInIncognito(context);
-}
-
 KeyedService* CookieControlsServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* profile) const {
   return BuildInstanceFor(Profile::FromBrowserContext(profile));
diff --git a/chrome/browser/ui/cookie_controls/cookie_controls_service_factory.h b/chrome/browser/ui/cookie_controls/cookie_controls_service_factory.h
index 4225b7e..326946e 100644
--- a/chrome/browser/ui/cookie_controls/cookie_controls_service_factory.h
+++ b/chrome/browser/ui/cookie_controls/cookie_controls_service_factory.h
@@ -6,14 +6,14 @@
 #define CHROME_BROWSER_UI_COOKIE_CONTROLS_COOKIE_CONTROLS_SERVICE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 class CookieControlsService;
 
 // Factory to get or create an instance of CookieControlsService from
 // a Profile.
-class CookieControlsServiceFactory : public BrowserContextKeyedServiceFactory {
+class CookieControlsServiceFactory : public ProfileKeyedServiceFactory {
  public:
   static CookieControlsService* GetForProfile(Profile* profile);
 
@@ -29,8 +29,6 @@
   ~CookieControlsServiceFactory() override;
 
   // BrowserContextKeyedServiceFactory:
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* profile) const override;
 };
diff --git a/chrome/browser/ui/find_bar/find_bar_state_factory.cc b/chrome/browser/ui/find_bar/find_bar_state_factory.cc
index 3c3c2af7..10ecbcd 100644
--- a/chrome/browser/ui/find_bar/find_bar_state_factory.cc
+++ b/chrome/browser/ui/find_bar/find_bar_state_factory.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/ui/find_bar/find_bar_state_factory.h"
 
 #include "chrome/browser/ui/find_bar/find_bar_state.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 // static
 FindBarState* FindBarStateFactory::GetForBrowserContext(
@@ -20,9 +19,10 @@
 }
 
 FindBarStateFactory::FindBarStateFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "FindBarState",
-          BrowserContextDependencyManager::GetInstance()) {}
+          // Separate instance in incognito.
+          ProfileSelections::BuildForRegularAndIncognito()) {}
 
 FindBarStateFactory::~FindBarStateFactory() = default;
 
@@ -30,9 +30,3 @@
     content::BrowserContext* context) const {
   return new FindBarState(context);
 }
-
-content::BrowserContext* FindBarStateFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  // Separate instance in incognito.
-  return context;
-}
diff --git a/chrome/browser/ui/find_bar/find_bar_state_factory.h b/chrome/browser/ui/find_bar/find_bar_state_factory.h
index 7ec21a3..d698d31 100644
--- a/chrome/browser/ui/find_bar/find_bar_state_factory.h
+++ b/chrome/browser/ui/find_bar/find_bar_state_factory.h
@@ -6,11 +6,11 @@
 #define CHROME_BROWSER_UI_FIND_BAR_FIND_BAR_STATE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class FindBarState;
 
-class FindBarStateFactory : public BrowserContextKeyedServiceFactory {
+class FindBarStateFactory : public ProfileKeyedServiceFactory {
  public:
   FindBarStateFactory(const FindBarStateFactory&) = delete;
   FindBarStateFactory& operator=(const FindBarStateFactory&) = delete;
@@ -28,8 +28,6 @@
   // BrowserContextKeyedServiceFactory:
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 };
 
 #endif  // CHROME_BROWSER_UI_FIND_BAR_FIND_BAR_STATE_FACTORY_H_
diff --git a/chrome/browser/ui/global_error/global_error_service_factory.cc b/chrome/browser/ui/global_error/global_error_service_factory.cc
index 9e30886..53f3725 100644
--- a/chrome/browser/ui/global_error/global_error_service_factory.cc
+++ b/chrome/browser/ui/global_error/global_error_service_factory.cc
@@ -4,10 +4,8 @@
 
 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
 
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/global_error/global_error_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 // static
 GlobalErrorService* GlobalErrorServiceFactory::GetForProfile(Profile* profile) {
@@ -21,9 +19,9 @@
 }
 
 GlobalErrorServiceFactory::GlobalErrorServiceFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "GlobalErrorService",
-          BrowserContextDependencyManager::GetInstance()) {}
+          ProfileSelections::BuildRedirectedInIncognito()) {}
 
 GlobalErrorServiceFactory::~GlobalErrorServiceFactory() = default;
 
@@ -31,8 +29,3 @@
     content::BrowserContext* profile) const {
   return new GlobalErrorService();
 }
-
-content::BrowserContext* GlobalErrorServiceFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
diff --git a/chrome/browser/ui/global_error/global_error_service_factory.h b/chrome/browser/ui/global_error/global_error_service_factory.h
index 3d76abe..3bb2af0 100644
--- a/chrome/browser/ui/global_error/global_error_service_factory.h
+++ b/chrome/browser/ui/global_error/global_error_service_factory.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_GLOBAL_ERROR_GLOBAL_ERROR_SERVICE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class GlobalErrorService;
 class Profile;
@@ -14,7 +14,7 @@
 // Singleton that owns all GlobalErrorService and associates them with
 // Profiles. Listens for the Profile's destruction notification and cleans up
 // the associated GlobalErrorService.
-class GlobalErrorServiceFactory : public BrowserContextKeyedServiceFactory {
+class GlobalErrorServiceFactory : public ProfileKeyedServiceFactory {
  public:
   GlobalErrorServiceFactory(const GlobalErrorServiceFactory&) = delete;
   GlobalErrorServiceFactory& operator=(const GlobalErrorServiceFactory&) =
@@ -33,8 +33,6 @@
   // BrowserContextKeyedServiceFactory:
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* profile) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 };
 
 #endif  // CHROME_BROWSER_UI_GLOBAL_ERROR_GLOBAL_ERROR_SERVICE_FACTORY_H_
diff --git a/chrome/browser/ui/global_media_controls/media_notification_service_factory.cc b/chrome/browser/ui/global_media_controls/media_notification_service_factory.cc
index 31dd097..430cf5c 100644
--- a/chrome/browser/ui/global_media_controls/media_notification_service_factory.cc
+++ b/chrome/browser/ui/global_media_controls/media_notification_service_factory.cc
@@ -8,15 +8,13 @@
 
 #include "base/memory/singleton.h"
 #include "build/chromeos_buildflags.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/global_media_controls/media_notification_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 MediaNotificationServiceFactory::MediaNotificationServiceFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "MediaNotificationService",
-          BrowserContextDependencyManager::GetInstance()) {}
+          ProfileSelections::BuildForRegularAndIncognito()) {}
 
 MediaNotificationServiceFactory::~MediaNotificationServiceFactory() {}
 
@@ -42,9 +40,3 @@
   return new MediaNotificationService(Profile::FromBrowserContext(context),
                                       show_from_all_profiles);
 }
-
-content::BrowserContext*
-MediaNotificationServiceFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextOwnInstanceInIncognito(context);
-}
diff --git a/chrome/browser/ui/global_media_controls/media_notification_service_factory.h b/chrome/browser/ui/global_media_controls/media_notification_service_factory.h
index ecf0ad1..332100d 100644
--- a/chrome/browser/ui/global_media_controls/media_notification_service_factory.h
+++ b/chrome/browser/ui/global_media_controls/media_notification_service_factory.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_SERVICE_FACTORY_H_
 #define CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_SERVICE_FACTORY_H_
 
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 
@@ -20,8 +20,7 @@
 
 class MediaNotificationService;
 
-class MediaNotificationServiceFactory
-    : public BrowserContextKeyedServiceFactory {
+class MediaNotificationServiceFactory : public ProfileKeyedServiceFactory {
  public:
   MediaNotificationServiceFactory(const MediaNotificationServiceFactory&) =
       delete;
@@ -41,8 +40,6 @@
   // BrowserContextKeyedServiceFactory overrides:
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 };
 
 #endif  // CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_SERVICE_FACTORY_H_
diff --git a/chrome/browser/ui/hats/hats_service_factory.cc b/chrome/browser/ui/hats/hats_service_factory.cc
index 0c9fbc0..c22d8db8 100644
--- a/chrome/browser/ui/hats/hats_service_factory.cc
+++ b/chrome/browser/ui/hats/hats_service_factory.cc
@@ -8,7 +8,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/ui/hats/hats_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 // static
 HatsService* HatsServiceFactory::GetForProfile(Profile* profile,
@@ -23,20 +22,15 @@
 }
 
 HatsServiceFactory::HatsServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "HatsService",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("HatsService",
+                                 ProfileSelections::BuildForRegularProfile()) {
   DependsOn(IdentityManagerFactory::GetInstance());
 }
 
 KeyedService* HatsServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
   Profile* profile = Profile::FromBrowserContext(context);
-
-  return (profile->IsOffTheRecord() || profile->IsGuestSession() ||
-          profile->IsSystemProfile())
-             ? nullptr
-             : new HatsService(profile);
+  return new HatsService(profile);
 }
 
 HatsServiceFactory::~HatsServiceFactory() = default;
diff --git a/chrome/browser/ui/hats/hats_service_factory.h b/chrome/browser/ui/hats/hats_service_factory.h
index e44a2cd..c06a0d6 100644
--- a/chrome/browser/ui/hats/hats_service_factory.h
+++ b/chrome/browser/ui/hats/hats_service_factory.h
@@ -6,12 +6,12 @@
 #define CHROME_BROWSER_UI_HATS_HATS_SERVICE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class HatsService;
 class Profile;
 
-class HatsServiceFactory : public BrowserContextKeyedServiceFactory {
+class HatsServiceFactory : public ProfileKeyedServiceFactory {
  public:
   HatsServiceFactory(const HatsServiceFactory&) = delete;
   HatsServiceFactory& operator=(const HatsServiceFactory&) = delete;
diff --git a/chrome/browser/ui/hats/trust_safety_sentiment_service_factory.cc b/chrome/browser/ui/hats/trust_safety_sentiment_service_factory.cc
index a364939..f74eef9 100644
--- a/chrome/browser/ui/hats/trust_safety_sentiment_service_factory.cc
+++ b/chrome/browser/ui/hats/trust_safety_sentiment_service_factory.cc
@@ -7,13 +7,10 @@
 #include "chrome/browser/ui/hats/hats_service.h"
 #include "chrome/browser/ui/hats/hats_service_factory.h"
 #include "chrome/common/chrome_features.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "content/public/browser/browser_context.h"
 
 TrustSafetySentimentServiceFactory::TrustSafetySentimentServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "TrustSafetySentimentService",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("TrustSafetySentimentService") {
   DependsOn(HatsServiceFactory::GetInstance());
   DependsOn(HostContentSettingsMapFactory::GetInstance());
 }
diff --git a/chrome/browser/ui/hats/trust_safety_sentiment_service_factory.h b/chrome/browser/ui/hats/trust_safety_sentiment_service_factory.h
index f77da6a..67c26241 100644
--- a/chrome/browser/ui/hats/trust_safety_sentiment_service_factory.h
+++ b/chrome/browser/ui/hats/trust_safety_sentiment_service_factory.h
@@ -6,11 +6,10 @@
 #define CHROME_BROWSER_UI_HATS_TRUST_SAFETY_SENTIMENT_SERVICE_FACTORY_H_
 
 #include "base/memory/singleton.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 #include "chrome/browser/ui/hats/trust_safety_sentiment_service.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
-class TrustSafetySentimentServiceFactory
-    : public BrowserContextKeyedServiceFactory {
+class TrustSafetySentimentServiceFactory : public ProfileKeyedServiceFactory {
  public:
   static TrustSafetySentimentServiceFactory* GetInstance();
   static TrustSafetySentimentService* GetForProfile(Profile* profile);
diff --git a/chrome/browser/ui/media_router/media_router_ui_service_factory.cc b/chrome/browser/ui/media_router/media_router_ui_service_factory.cc
index 604ed5fe..05ad2a06 100644
--- a/chrome/browser/ui/media_router/media_router_ui_service_factory.cc
+++ b/chrome/browser/ui/media_router/media_router_ui_service_factory.cc
@@ -9,7 +9,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/media_router/media_router_ui_service.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_model_factory.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 using content::BrowserContext;
 
@@ -29,9 +28,9 @@
 }
 
 MediaRouterUIServiceFactory::MediaRouterUIServiceFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "MediaRouterUIService",
-          BrowserContextDependencyManager::GetInstance()) {
+          ProfileSelections::BuildForRegularAndIncognito()) {
   DependsOn(ChromeMediaRouterFactory::GetInstance());
   // MediaRouterUIService owns a MediaRouterActionController that depends on
   // ToolbarActionsModel.
@@ -40,11 +39,6 @@
 
 MediaRouterUIServiceFactory::~MediaRouterUIServiceFactory() {}
 
-BrowserContext* MediaRouterUIServiceFactory::GetBrowserContextToUse(
-    BrowserContext* context) const {
-  return context;
-}
-
 KeyedService* MediaRouterUIServiceFactory::BuildServiceInstanceFor(
     BrowserContext* context) const {
   return new MediaRouterUIService(Profile::FromBrowserContext(context));
diff --git a/chrome/browser/ui/media_router/media_router_ui_service_factory.h b/chrome/browser/ui/media_router/media_router_ui_service_factory.h
index 1a92e0d..d0e61d7 100644
--- a/chrome/browser/ui/media_router/media_router_ui_service_factory.h
+++ b/chrome/browser/ui/media_router/media_router_ui_service_factory.h
@@ -8,7 +8,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/singleton.h"
 #include "build/build_config.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 namespace content {
 class BrowserContext;
@@ -18,7 +18,7 @@
 
 class MediaRouterUIService;
 
-class MediaRouterUIServiceFactory : public BrowserContextKeyedServiceFactory {
+class MediaRouterUIServiceFactory : public ProfileKeyedServiceFactory {
  public:
   MediaRouterUIServiceFactory(const MediaRouterUIServiceFactory&) = delete;
   MediaRouterUIServiceFactory& operator=(const MediaRouterUIServiceFactory&) =
@@ -41,8 +41,6 @@
   ~MediaRouterUIServiceFactory() override;
 
   // BrowserContextKeyedServiceFactory interface.
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
 #if !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/ui/prefs/pref_watcher.cc b/chrome/browser/ui/prefs/pref_watcher.cc
index a7dbd620..7afd512 100644
--- a/chrome/browser/ui/prefs/pref_watcher.cc
+++ b/chrome/browser/ui/prefs/pref_watcher.cc
@@ -8,12 +8,10 @@
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_preferences_util.h"
 #include "chrome/browser/ui/prefs/prefs_tab_helper.h"
 #include "chrome/common/pref_names.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/live_caption/pref_names.h"
 #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
@@ -167,9 +165,9 @@
 }
 
 PrefWatcherFactory::PrefWatcherFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "PrefWatcher",
-          BrowserContextDependencyManager::GetInstance()) {}
+          ProfileSelections::BuildForRegularAndIncognito()) {}
 
 PrefWatcherFactory::~PrefWatcherFactory() = default;
 
@@ -178,11 +176,6 @@
   return new PrefWatcher(Profile::FromBrowserContext(browser_context));
 }
 
-content::BrowserContext* PrefWatcherFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextOwnInstanceInIncognito(context);
-}
-
 // static
 PrefWatcher* PrefWatcher::Get(Profile* profile) {
   return PrefWatcherFactory::GetForProfile(profile);
diff --git a/chrome/browser/ui/prefs/pref_watcher.h b/chrome/browser/ui/prefs/pref_watcher.h
index 8d9cc4fd..376c2d42 100644
--- a/chrome/browser/ui/prefs/pref_watcher.h
+++ b/chrome/browser/ui/prefs/pref_watcher.h
@@ -7,7 +7,7 @@
 
 #include "base/memory/raw_ptr.h"
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "mojo/public/cpp/bindings/remote_set.h"
@@ -53,7 +53,7 @@
       renderer_preference_watchers_;
 };
 
-class PrefWatcherFactory : public BrowserContextKeyedServiceFactory {
+class PrefWatcherFactory : public ProfileKeyedServiceFactory {
  public:
   static PrefWatcher* GetForProfile(Profile* profile);
   static PrefWatcherFactory* GetInstance();
@@ -67,9 +67,6 @@
   // BrowserContextKeyedServiceFactory:
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* browser_context) const override;
-
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 };
 
 #endif  // CHROME_BROWSER_UI_PREFS_PREF_WATCHER_H_
diff --git a/chrome/browser/ui/read_later/reading_list_model_factory.cc b/chrome/browser/ui/read_later/reading_list_model_factory.cc
index d89231d..20799bcc 100644
--- a/chrome/browser/ui/read_later/reading_list_model_factory.cc
+++ b/chrome/browser/ui/read_later/reading_list_model_factory.cc
@@ -13,12 +13,10 @@
 #include "base/time/default_clock.h"
 #include "base/values.h"
 #include "build/build_config.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/model_type_store_service_factory.h"
 #include "chrome/common/channel_info.h"
 #include "chrome/common/chrome_switches.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 #include "components/reading_list/core/reading_list_model.h"
@@ -71,9 +69,9 @@
 }
 
 ReadingListModelFactory::ReadingListModelFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "ReadingListModel",
-          BrowserContextDependencyManager::GetInstance()) {
+          ProfileSelections::BuildRedirectedInIncognito()) {
   DependsOn(ModelTypeStoreServiceFactory::GetInstance());
 }
 
@@ -96,11 +94,6 @@
 #endif  // !BUILDFLAG(IS_ANDROID)
 }
 
-content::BrowserContext* ReadingListModelFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
-
 bool ReadingListModelFactory::ServiceIsNULLWhileTesting() const {
   return true;
 }
diff --git a/chrome/browser/ui/read_later/reading_list_model_factory.h b/chrome/browser/ui/read_later/reading_list_model_factory.h
index 112e7c5..3a6883b 100644
--- a/chrome/browser/ui/read_later/reading_list_model_factory.h
+++ b/chrome/browser/ui/read_later/reading_list_model_factory.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_READ_LATER_READING_LIST_MODEL_FACTORY_H_
 #define CHROME_BROWSER_UI_READ_LATER_READING_LIST_MODEL_FACTORY_H_
 
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 namespace base {
 template <typename T>
@@ -16,7 +16,7 @@
 
 // Singleton that owns all ReadingListModels and associates them with
 // BrowserContexts.
-class ReadingListModelFactory : public BrowserContextKeyedServiceFactory {
+class ReadingListModelFactory : public ProfileKeyedServiceFactory {
  public:
   ReadingListModelFactory(const ReadingListModelFactory&) = delete;
   ReadingListModelFactory& operator=(const ReadingListModelFactory&) = delete;
@@ -40,8 +40,6 @@
       content::BrowserContext* context) const override;
   void RegisterProfilePrefs(
       user_prefs::PrefRegistrySyncable* registry) override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
   bool ServiceIsNULLWhileTesting() const override;
 };
 
diff --git a/chrome/browser/ui/startup/lacros_first_run_service.cc b/chrome/browser/ui/startup/lacros_first_run_service.cc
index 703eca5..f17871a56 100644
--- a/chrome/browser/ui/startup/lacros_first_run_service.cc
+++ b/chrome/browser/ui/startup/lacros_first_run_service.cc
@@ -33,7 +33,6 @@
 #include "chrome/browser/ui/webui/signin/turn_sync_on_helper.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/public/base/consent_level.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
@@ -325,9 +324,10 @@
 // LacrosFirstRunServiceFactory ------------------------------------------------
 
 LacrosFirstRunServiceFactory::LacrosFirstRunServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "LacrosFirstRunServiceFactory",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("LacrosFirstRunServiceFactory",
+                                 ProfileSelections::Builder()
+                                     .WithGuest(ProfileSelection::kNone)
+                                     .Build()) {
   // Used for checking Sync consent level.
   DependsOn(IdentityManagerFactory::GetInstance());
 }
diff --git a/chrome/browser/ui/startup/lacros_first_run_service.h b/chrome/browser/ui/startup/lacros_first_run_service.h
index bdbaf3b..e12739bc 100644
--- a/chrome/browser/ui/startup/lacros_first_run_service.h
+++ b/chrome/browser/ui/startup/lacros_first_run_service.h
@@ -11,7 +11,7 @@
 #include "base/no_destructor.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -93,7 +93,7 @@
   base::WeakPtrFactory<LacrosFirstRunService> weak_ptr_factory_{this};
 };
 
-class LacrosFirstRunServiceFactory : public BrowserContextKeyedServiceFactory {
+class LacrosFirstRunServiceFactory : public ProfileKeyedServiceFactory {
  public:
   LacrosFirstRunServiceFactory(const LacrosFirstRunServiceFactory&) = delete;
   LacrosFirstRunServiceFactory& operator=(const LacrosFirstRunServiceFactory&) =
diff --git a/chrome/browser/ui/tabs/pinned_tab_service_factory.cc b/chrome/browser/ui/tabs/pinned_tab_service_factory.cc
index 9c124105..94a3896 100644
--- a/chrome/browser/ui/tabs/pinned_tab_service_factory.cc
+++ b/chrome/browser/ui/tabs/pinned_tab_service_factory.cc
@@ -6,7 +6,6 @@
 
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/tabs/pinned_tab_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 // static
 PinnedTabService* PinnedTabServiceFactory::GetForProfile(
@@ -20,10 +19,7 @@
 }
 
 PinnedTabServiceFactory::PinnedTabServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-        "PinnedTabService",
-        BrowserContextDependencyManager::GetInstance()) {
-}
+    : ProfileKeyedServiceFactory("PinnedTabService") {}
 
 PinnedTabServiceFactory::~PinnedTabServiceFactory() {
 }
diff --git a/chrome/browser/ui/tabs/pinned_tab_service_factory.h b/chrome/browser/ui/tabs/pinned_tab_service_factory.h
index 74423a3..fb83ae6a 100644
--- a/chrome/browser/ui/tabs/pinned_tab_service_factory.h
+++ b/chrome/browser/ui/tabs/pinned_tab_service_factory.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_TABS_PINNED_TAB_SERVICE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class PinnedTabService;
 class Profile;
@@ -14,7 +14,7 @@
 // Singleton that owns all PinnedTabServices and associates them with Profiles.
 // Listens for the Profile's destruction notification and cleans up the
 // associated PinnedTabService.
-class PinnedTabServiceFactory : public BrowserContextKeyedServiceFactory {
+class PinnedTabServiceFactory : public ProfileKeyedServiceFactory {
  public:
   // Returns the PinnedTabService that tracks pinning changes for |profile|.
   static PinnedTabService* GetForProfile(Profile* profile);
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_service_factory.cc b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_service_factory.cc
index 079a85c..57da28af 100644
--- a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_service_factory.cc
+++ b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_service_factory.cc
@@ -8,7 +8,6 @@
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_keyed_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 SavedTabGroupServiceFactory& SavedTabGroupServiceFactory::GetInstance() {
   static base::NoDestructor<SavedTabGroupServiceFactory> instance;
@@ -23,9 +22,7 @@
 }
 
 SavedTabGroupServiceFactory::SavedTabGroupServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "SavedTabGroupKeyedService",
-          BrowserContextDependencyManager::GetInstance()) {}
+    : ProfileKeyedServiceFactory("SavedTabGroupKeyedService") {}
 
 SavedTabGroupServiceFactory::~SavedTabGroupServiceFactory() = default;
 
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_service_factory.h b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_service_factory.h
index 6ac98ff4..3f77132 100644
--- a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_service_factory.h
+++ b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_service_factory.h
@@ -6,12 +6,12 @@
 #define CHROME_BROWSER_UI_TABS_SAVED_TAB_GROUPS_SAVED_TAB_GROUP_SERVICE_FACTORY_H_
 
 #include "base/memory/singleton.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 #include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_keyed_service.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
 class Profile;
 
-class SavedTabGroupServiceFactory : public BrowserContextKeyedServiceFactory {
+class SavedTabGroupServiceFactory : public ProfileKeyedServiceFactory {
  public:
   SavedTabGroupServiceFactory();
   SavedTabGroupServiceFactory(const SavedTabGroupServiceFactory&) = delete;
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model_factory.cc b/chrome/browser/ui/toolbar/toolbar_actions_model_factory.cc
index ae765e3..072b3f9 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_model_factory.cc
+++ b/chrome/browser/ui/toolbar/toolbar_actions_model_factory.cc
@@ -9,7 +9,6 @@
 #include "chrome/browser/extensions/extension_system_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_model.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_prefs_factory.h"
 #include "extensions/browser/extension_registry_factory.h"
@@ -29,9 +28,9 @@
 }
 
 ToolbarActionsModelFactory::ToolbarActionsModelFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "ToolbarActionsModel",
-          BrowserContextDependencyManager::GetInstance()) {
+          ProfileSelections::BuildForRegularAndIncognito()) {
   DependsOn(extensions::ExtensionActionAPI::GetFactoryInstance());
   DependsOn(extensions::ExtensionPrefsFactory::GetInstance());
   DependsOn(extensions::ExtensionRegistryFactory::GetInstance());
@@ -49,11 +48,6 @@
       extensions::ExtensionPrefsFactory::GetForBrowserContext(context));
 }
 
-content::BrowserContext* ToolbarActionsModelFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return context;
-}
-
 bool ToolbarActionsModelFactory::ServiceIsCreatedWithBrowserContext() const {
   return true;
 }
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model_factory.h b/chrome/browser/ui/toolbar/toolbar_actions_model_factory.h
index bf2e0b7..6c282c6d 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_model_factory.h
+++ b/chrome/browser/ui/toolbar/toolbar_actions_model_factory.h
@@ -6,13 +6,13 @@
 #define CHROME_BROWSER_UI_TOOLBAR_TOOLBAR_ACTIONS_MODEL_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 
 class ToolbarActionsModel;
 
-class ToolbarActionsModelFactory : public BrowserContextKeyedServiceFactory {
+class ToolbarActionsModelFactory : public ProfileKeyedServiceFactory {
  public:
   static ToolbarActionsModel* GetForProfile(Profile* profile);
 
@@ -26,8 +26,6 @@
 
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* profile) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
   bool ServiceIsCreatedWithBrowserContext() const override;
   bool ServiceIsNULLWhileTesting() const override;
 };
diff --git a/chrome/browser/ui/user_education/reopen_tab_in_product_help_factory.cc b/chrome/browser/ui/user_education/reopen_tab_in_product_help_factory.cc
index 87c7e5a..6641293b 100644
--- a/chrome/browser/ui/user_education/reopen_tab_in_product_help_factory.cc
+++ b/chrome/browser/ui/user_education/reopen_tab_in_product_help_factory.cc
@@ -9,15 +9,13 @@
 #include "base/memory/singleton.h"
 #include "base/time/default_tick_clock.h"
 #include "chrome/browser/feature_engagement/tracker_factory.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/user_education/reopen_tab_in_product_help.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 ReopenTabInProductHelpFactory::ReopenTabInProductHelpFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "ReopenTabInProductHelp",
-          BrowserContextDependencyManager::GetInstance()) {
+          ProfileSelections::BuildRedirectedInIncognito()) {
   DependsOn(feature_engagement::TrackerFactory::GetInstance());
 }
 
@@ -40,8 +38,3 @@
   return new ReopenTabInProductHelp(Profile::FromBrowserContext(context),
                                     base::DefaultTickClock::GetInstance());
 }
-
-content::BrowserContext* ReopenTabInProductHelpFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
diff --git a/chrome/browser/ui/user_education/reopen_tab_in_product_help_factory.h b/chrome/browser/ui/user_education/reopen_tab_in_product_help_factory.h
index b1d4cda..20e44cd 100644
--- a/chrome/browser/ui/user_education/reopen_tab_in_product_help_factory.h
+++ b/chrome/browser/ui/user_education/reopen_tab_in_product_help_factory.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_USER_EDUCATION_REOPEN_TAB_IN_PRODUCT_HELP_FACTORY_H_
 #define CHROME_BROWSER_UI_USER_EDUCATION_REOPEN_TAB_IN_PRODUCT_HELP_FACTORY_H_
 
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 
@@ -20,7 +20,7 @@
 
 class ReopenTabInProductHelp;
 
-class ReopenTabInProductHelpFactory : public BrowserContextKeyedServiceFactory {
+class ReopenTabInProductHelpFactory : public ProfileKeyedServiceFactory {
  public:
   ReopenTabInProductHelpFactory(const ReopenTabInProductHelpFactory&) = delete;
   ReopenTabInProductHelpFactory& operator=(
@@ -37,8 +37,6 @@
   // BrowserContextKeyedServiceFactory overrides:
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 
   friend struct base::DefaultSingletonTraits<ReopenTabInProductHelpFactory>;
 };
diff --git a/chrome/browser/ui/user_education/user_education_service_factory.cc b/chrome/browser/ui/user_education/user_education_service_factory.cc
index 7909963..c981e31 100644
--- a/chrome/browser/ui/user_education/user_education_service_factory.cc
+++ b/chrome/browser/ui/user_education/user_education_service_factory.cc
@@ -21,9 +21,7 @@
 }
 
 UserEducationServiceFactory::UserEducationServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "UserEducationService",
-          BrowserContextDependencyManager::GetInstance()) {}
+    : ProfileKeyedServiceFactory("UserEducationService") {}
 
 UserEducationServiceFactory::~UserEducationServiceFactory() = default;
 
diff --git a/chrome/browser/ui/user_education/user_education_service_factory.h b/chrome/browser/ui/user_education/user_education_service_factory.h
index 1f675d9..fca9f33 100644
--- a/chrome/browser/ui/user_education/user_education_service_factory.h
+++ b/chrome/browser/ui/user_education/user_education_service_factory.h
@@ -6,12 +6,12 @@
 #define CHROME_BROWSER_UI_USER_EDUCATION_USER_EDUCATION_SERVICE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 class UserEducationService;
 
-class UserEducationServiceFactory : public BrowserContextKeyedServiceFactory {
+class UserEducationServiceFactory : public ProfileKeyedServiceFactory {
  public:
   // Disallow copy/assign.
   UserEducationServiceFactory(const UserEducationServiceFactory&) = delete;
diff --git a/chrome/browser/ui/views/bubble/bubble_contents_wrapper_service_factory.cc b/chrome/browser/ui/views/bubble/bubble_contents_wrapper_service_factory.cc
index ea816ea..c36a159 100644
--- a/chrome/browser/ui/views/bubble/bubble_contents_wrapper_service_factory.cc
+++ b/chrome/browser/ui/views/bubble/bubble_contents_wrapper_service_factory.cc
@@ -8,7 +8,6 @@
 #include "base/no_destructor.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/views/bubble/bubble_contents_wrapper_service.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 // static
 BubbleContentsWrapperService*
@@ -26,9 +25,7 @@
 }
 
 BubbleContentsWrapperServiceFactory::BubbleContentsWrapperServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "BubbleContentsWrapperService",
-          BrowserContextDependencyManager::GetInstance()) {}
+    : ProfileKeyedServiceFactory("BubbleContentsWrapperService") {}
 
 KeyedService* BubbleContentsWrapperServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
diff --git a/chrome/browser/ui/views/bubble/bubble_contents_wrapper_service_factory.h b/chrome/browser/ui/views/bubble/bubble_contents_wrapper_service_factory.h
index 9a9930a..694a3c16 100644
--- a/chrome/browser/ui/views/bubble/bubble_contents_wrapper_service_factory.h
+++ b/chrome/browser/ui/views/bubble/bubble_contents_wrapper_service_factory.h
@@ -6,13 +6,12 @@
 #define CHROME_BROWSER_UI_VIEWS_BUBBLE_BUBBLE_CONTENTS_WRAPPER_SERVICE_FACTORY_H_
 
 #include "base/no_destructor.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class BubbleContentsWrapperService;
 class Profile;
 
-class BubbleContentsWrapperServiceFactory
-    : public BrowserContextKeyedServiceFactory {
+class BubbleContentsWrapperServiceFactory : public ProfileKeyedServiceFactory {
  public:
   static BubbleContentsWrapperService* GetForProfile(Profile* profile,
                                                      bool create_if_necessary);
diff --git a/chrome/browser/ui/webid/identity_dialog_controller.cc b/chrome/browser/ui/webid/identity_dialog_controller.cc
index 0952b5d..bbc27f9 100644
--- a/chrome/browser/ui/webid/identity_dialog_controller.cc
+++ b/chrome/browser/ui/webid/identity_dialog_controller.cc
@@ -47,13 +47,19 @@
 
 void IdentityDialogController::ShowAccountsDialog(
     content::WebContents* rp_web_contents,
-    const GURL& idp_url,
-    base::span<const content::IdentityRequestAccount> accounts,
-    const content::IdentityProviderMetadata& idp_metadata,
-    const content::ClientIdData& client_data,
+    const std::vector<content::IdentityProviderData>& identity_provider_data,
     content::IdentityRequestAccount::SignInMode sign_in_mode,
     AccountSelectionCallback on_selected,
     DismissCallback dismiss_callback) {
+  // TODO(crbug.com/1348262): Temporarily support only the first IDP, extend to
+  // support multiple IDPs.
+  GURL idp_url = identity_provider_data[0].idp_config_url;
+  base::span<const content::IdentityRequestAccount> accounts =
+      identity_provider_data[0].accounts;
+  content::IdentityProviderMetadata idp_metadata =
+      identity_provider_data[0].idp_metadata;
+  content::ClientIdData client_data = identity_provider_data[0].client_id_data;
+
   // IDP scheme is expected to always be `https://`.
   CHECK(idp_url.SchemeIs(url::kHttpsScheme));
   rp_web_contents_ = rp_web_contents;
diff --git a/chrome/browser/ui/webid/identity_dialog_controller.h b/chrome/browser/ui/webid/identity_dialog_controller.h
index 9013144..7c3661c 100644
--- a/chrome/browser/ui/webid/identity_dialog_controller.h
+++ b/chrome/browser/ui/webid/identity_dialog_controller.h
@@ -16,8 +16,6 @@
 #include "content/public/browser/web_contents.h"
 #include "ui/gfx/native_widget_types.h"
 
-class GURL;
-
 using AccountSelectionCallback =
     content::IdentityRequestDialogController::AccountSelectionCallback;
 using DismissCallback =
@@ -42,10 +40,7 @@
 
   void ShowAccountsDialog(
       content::WebContents* rp_web_contents,
-      const GURL& idp_url,
-      base::span<const content::IdentityRequestAccount> accounts,
-      const content::IdentityProviderMetadata& idp_metadata,
-      const content::ClientIdData& client_data,
+      const std::vector<content::IdentityProviderData>& identity_provider_data,
       content::IdentityRequestAccount::SignInMode sign_in_mode,
       AccountSelectionCallback on_selected,
       DismissCallback dismiss_callback) override;
diff --git a/chrome/browser/ui/webui/access_code_cast/OWNERS b/chrome/browser/ui/webui/access_code_cast/OWNERS
index 1c4f5ce..dcfbbde 100644
--- a/chrome/browser/ui/webui/access_code_cast/OWNERS
+++ b/chrome/browser/ui/webui/access_code_cast/OWNERS
@@ -1,7 +1,6 @@
 gbj@google.com
 bmalcolm@chromium.org
 bzielinski@google.com
-jacqueli@google.com
 
 per-file *.mojom=set noparent
 per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc b/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc
index 902d8df..6177943 100644
--- a/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc
+++ b/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc
@@ -127,9 +127,8 @@
   visit_mojom->raw_visit_data = mojom::RawVisitData::New(
       annotated_visit.url_row.url(), annotated_visit.visit_row.visit_time);
   for (const auto& duplicate : visit.duplicate_visits) {
-    visit_mojom->duplicates.push_back(mojom::RawVisitData::New(
-        duplicate.annotated_visit.url_row.url(),
-        duplicate.annotated_visit.visit_row.visit_time));
+    visit_mojom->duplicates.push_back(
+        mojom::RawVisitData::New(duplicate.url, duplicate.visit_time));
   }
 
   visit_mojom->page_title = base::UTF16ToUTF8(annotated_visit.url_row.title());
diff --git a/chrome/browser/ui/webui/ntp/app_resource_cache_factory.cc b/chrome/browser/ui/webui/ntp/app_resource_cache_factory.cc
index 7049709..9cde460 100644
--- a/chrome/browser/ui/webui/ntp/app_resource_cache_factory.cc
+++ b/chrome/browser/ui/webui/ntp/app_resource_cache_factory.cc
@@ -4,11 +4,9 @@
 
 #include "chrome/browser/ui/webui/ntp/app_resource_cache_factory.h"
 
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/themes/theme_service_factory.h"
 #include "chrome/browser/ui/webui/ntp/ntp_resource_cache.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 // static
 NTPResourceCache* AppResourceCacheFactory::GetForProfile(Profile* profile) {
@@ -22,9 +20,9 @@
 }
 
 AppResourceCacheFactory::AppResourceCacheFactory()
-    : BrowserContextKeyedServiceFactory(
-        "AppResourceCache",
-        BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory(
+          "AppResourceCache",
+          ProfileSelections::BuildRedirectedInIncognito()) {
   DependsOn(ThemeServiceFactory::GetInstance());
 }
 
@@ -34,8 +32,3 @@
     content::BrowserContext* profile) const {
   return new NTPResourceCache(static_cast<Profile*>(profile));
 }
-
-content::BrowserContext* AppResourceCacheFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
diff --git a/chrome/browser/ui/webui/ntp/app_resource_cache_factory.h b/chrome/browser/ui/webui/ntp/app_resource_cache_factory.h
index fc4b5f9..3a433f1 100644
--- a/chrome/browser/ui/webui/ntp/app_resource_cache_factory.h
+++ b/chrome/browser/ui/webui/ntp/app_resource_cache_factory.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_WEBUI_NTP_APP_RESOURCE_CACHE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class NTPResourceCache;
 class Profile;
@@ -14,7 +14,7 @@
 // Singleton that owns NTPResourceCaches used by the apps launcher page and
 // associates them with Profiles. Listens for the Profile's destruction
 // notification and cleans up the associated ThemeService.
-class AppResourceCacheFactory : public BrowserContextKeyedServiceFactory {
+class AppResourceCacheFactory : public ProfileKeyedServiceFactory {
  public:
   static NTPResourceCache* GetForProfile(Profile* profile);
 
@@ -29,8 +29,6 @@
   // BrowserContextKeyedServiceFactory:
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* profile) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 };
 
 #endif  // CHROME_BROWSER_UI_WEBUI_NTP_APP_RESOURCE_CACHE_FACTORY_H_
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache_factory.cc b/chrome/browser/ui/webui/ntp/ntp_resource_cache_factory.cc
index cdd8d43..862c41c 100644
--- a/chrome/browser/ui/webui/ntp/ntp_resource_cache_factory.cc
+++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache_factory.cc
@@ -4,12 +4,10 @@
 
 #include "chrome/browser/ui/webui/ntp/ntp_resource_cache_factory.h"
 
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/themes/theme_service_factory.h"
 #include "chrome/browser/ui/webui/ntp/ntp_resource_cache.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 // static
 NTPResourceCache* NTPResourceCacheFactory::GetForProfile(Profile* profile) {
@@ -23,9 +21,9 @@
 }
 
 NTPResourceCacheFactory::NTPResourceCacheFactory()
-    : BrowserContextKeyedServiceFactory(
-        "NTPResourceCache",
-        BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory(
+          "NTPResourceCache",
+          ProfileSelections::BuildRedirectedInIncognito()) {
   DependsOn(IdentityManagerFactory::GetInstance());
   DependsOn(ThemeServiceFactory::GetInstance());
 }
@@ -36,8 +34,3 @@
     content::BrowserContext* profile) const {
   return new NTPResourceCache(static_cast<Profile*>(profile));
 }
-
-content::BrowserContext* NTPResourceCacheFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache_factory.h b/chrome/browser/ui/webui/ntp/ntp_resource_cache_factory.h
index ecb7dc0..71649ed 100644
--- a/chrome/browser/ui/webui/ntp/ntp_resource_cache_factory.h
+++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache_factory.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_WEBUI_NTP_NTP_RESOURCE_CACHE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class NTPResourceCache;
 class Profile;
@@ -14,7 +14,7 @@
 // Singleton that owns the NTPResourceCaches used by the NTP and associates them
 // with Profiles. Listens for the Profile's destruction notification and cleans
 // up the associated ThemeService.
-class NTPResourceCacheFactory : public BrowserContextKeyedServiceFactory {
+class NTPResourceCacheFactory : public ProfileKeyedServiceFactory {
  public:
   static NTPResourceCache* GetForProfile(Profile* profile);
 
@@ -29,8 +29,6 @@
   // BrowserContextKeyedServiceFactory:
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* profile) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 };
 
 #endif  // CHROME_BROWSER_UI_WEBUI_NTP_NTP_RESOURCE_CACHE_FACTORY_H_
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.cc b/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.cc
index 2cd73306..9321d25 100644
--- a/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/ash/multidevice_setup/multidevice_setup_client_factory.h"
 #include "chrome/browser/ash/phonehub/phone_hub_manager_factory.h"
 #include "chrome/browser/ash/printing/cups_printers_manager_factory.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
@@ -20,7 +19,6 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
 #include "chrome/browser/ui/webui/settings/chromeos/os_settings_manager.h"
 #include "chromeos/ash/components/local_search_service/public/cpp/local_search_service_proxy_factory.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 namespace chromeos {
 namespace settings {
@@ -38,9 +36,9 @@
 }
 
 OsSettingsManagerFactory::OsSettingsManagerFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "OsSettingsManager",
-          BrowserContextDependencyManager::GetInstance()) {
+          ProfileSelections::BuildForRegularAndIncognito()) {
   DependsOn(
       local_search_service::LocalSearchServiceProxyFactory::GetInstance());
   DependsOn(multidevice_setup::MultiDeviceSetupClientFactory::GetInstance());
@@ -83,10 +81,5 @@
   return true;
 }
 
-content::BrowserContext* OsSettingsManagerFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextOwnInstanceInIncognito(context);
-}
-
 }  // namespace settings
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.h b/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.h
index 3370635..1fb0926 100644
--- a/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.h
+++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_MANAGER_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 
@@ -15,7 +15,7 @@
 
 class OsSettingsManager;
 
-class OsSettingsManagerFactory : public BrowserContextKeyedServiceFactory {
+class OsSettingsManagerFactory : public ProfileKeyedServiceFactory {
  public:
   static OsSettingsManager* GetForProfile(Profile* profile);
   static OsSettingsManagerFactory* GetInstance();
@@ -33,8 +33,6 @@
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
   bool ServiceIsNULLWhileTesting() const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 };
 
 }  // namespace settings
diff --git a/chrome/browser/ui/webui/signin/login_ui_service_factory.cc b/chrome/browser/ui/webui/signin/login_ui_service_factory.cc
index e9ed077..ccd16e3 100644
--- a/chrome/browser/ui/webui/signin/login_ui_service_factory.cc
+++ b/chrome/browser/ui/webui/signin/login_ui_service_factory.cc
@@ -8,12 +8,9 @@
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
 #include "chrome/browser/unified_consent/unified_consent_service_factory.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 LoginUIServiceFactory::LoginUIServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-        "LoginUIServiceFactory",
-        BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("LoginUIServiceFactory") {
   DependsOn(IdentityManagerFactory::GetInstance());
   DependsOn(UnifiedConsentServiceFactory::GetInstance());
 }
diff --git a/chrome/browser/ui/webui/signin/login_ui_service_factory.h b/chrome/browser/ui/webui/signin/login_ui_service_factory.h
index 54a1e7ec..c43f0b7b 100644
--- a/chrome/browser/ui/webui/signin/login_ui_service_factory.h
+++ b/chrome/browser/ui/webui/signin/login_ui_service_factory.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_WEBUI_SIGNIN_LOGIN_UI_SERVICE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class LoginUIService;
 class Profile;
@@ -14,7 +14,7 @@
 // Singleton that owns all LoginUIServices and associates them with
 // Profiles. Listens for the Profile's destruction notification and cleans up
 // the associated LoginUIService.
-class LoginUIServiceFactory : public BrowserContextKeyedServiceFactory {
+class LoginUIServiceFactory : public ProfileKeyedServiceFactory {
  public:
   LoginUIServiceFactory(const LoginUIServiceFactory&) = delete;
   LoginUIServiceFactory& operator=(const LoginUIServiceFactory&) = delete;
diff --git a/chrome/browser/ui/webui/web_app_internals/web_app_internals_source.cc b/chrome/browser/ui/webui/web_app_internals/web_app_internals_source.cc
index e6f9e32..2afafcd 100644
--- a/chrome/browser/ui/webui/web_app_internals/web_app_internals_source.cc
+++ b/chrome/browser/ui/webui/web_app_internals/web_app_internals_source.cc
@@ -36,8 +36,8 @@
 // New fields must be added to BuildIndexJson().
 constexpr char kInstalledWebApps[] = "InstalledWebApps";
 constexpr char kPreinstalledWebAppConfigs[] = "PreinstalledWebAppConfigs";
-constexpr char kPreinstalledAppsUninstalledByUserConfigs[] =
-    "PreinstalledAppsUninstalledByUserConfigs";
+constexpr char kUserUninstalledPreinstalledWebAppPrefs[] =
+    "UserUninstalledPreinstalledWebAppPrefs";
 constexpr char kExternallyManagedWebAppPrefs[] = "ExternallyManagedWebAppPrefs";
 constexpr char kCommandManager[] = "CommandManager";
 constexpr char kIconErrorLog[] = "IconErrorLog";
@@ -65,7 +65,7 @@
 
   index.Append(kInstalledWebApps);
   index.Append(kPreinstalledWebAppConfigs);
-  index.Append(kPreinstalledAppsUninstalledByUserConfigs);
+  index.Append(kUserUninstalledPreinstalledWebAppPrefs);
   index.Append(kExternallyManagedWebAppPrefs);
   index.Append(kCommandManager);
   index.Append(kIconErrorLog);
@@ -194,9 +194,9 @@
   return root;
 }
 
-base::Value BuildPreinstalledAppsUninstalledByUserJson(Profile* profile) {
+base::Value BuildUserUninstalledPreinstalledWebAppPrefsJson(Profile* profile) {
   base::Value::Dict root;
-  root.Set(kPreinstalledAppsUninstalledByUserConfigs,
+  root.Set(kUserUninstalledPreinstalledWebAppPrefs,
            profile->GetPrefs()
                ->GetValueDict(prefs::kUserUninstalledPreinstalledWebAppPref)
                .Clone());
@@ -327,8 +327,8 @@
   root.Append(BuildIndexJson());
   root.Append(BuildInstalledWebAppsJson(*provider));
   root.Append(BuildPreinstalledWebAppConfigsJson(*provider));
+  root.Append(BuildUserUninstalledPreinstalledWebAppPrefsJson(profile));
   root.Append(BuildExternallyManagedWebAppPrefsJson(profile));
-  root.Append(BuildPreinstalledAppsUninstalledByUserJson(profile));
   root.Append(BuildCommandManagerJson(*provider));
   root.Append(BuildIconErrorLogJson(*provider));
   root.Append(BuildInstallProcessErrorLogJson(*provider));
diff --git a/chrome/browser/undo/bookmark_undo_service_factory.cc b/chrome/browser/undo/bookmark_undo_service_factory.cc
index dcece8a7..0a1f6b7 100644
--- a/chrome/browser/undo/bookmark_undo_service_factory.cc
+++ b/chrome/browser/undo/bookmark_undo_service_factory.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/undo/bookmark_undo_service_factory.h"
 
 #include "chrome/browser/profiles/profile.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/undo/bookmark_undo_service.h"
 
 // static
@@ -28,10 +27,7 @@
 }
 
 BookmarkUndoServiceFactory::BookmarkUndoServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-        "BookmarkUndoService",
-        BrowserContextDependencyManager::GetInstance()) {
-}
+    : ProfileKeyedServiceFactory("BookmarkUndoService") {}
 
 BookmarkUndoServiceFactory::~BookmarkUndoServiceFactory() {
 }
diff --git a/chrome/browser/undo/bookmark_undo_service_factory.h b/chrome/browser/undo/bookmark_undo_service_factory.h
index f69dfd6..96273048 100644
--- a/chrome/browser/undo/bookmark_undo_service_factory.h
+++ b/chrome/browser/undo/bookmark_undo_service_factory.h
@@ -6,12 +6,12 @@
 #define CHROME_BROWSER_UNDO_BOOKMARK_UNDO_SERVICE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class BookmarkUndoService;
 class Profile;
 
-class BookmarkUndoServiceFactory : public BrowserContextKeyedServiceFactory {
+class BookmarkUndoServiceFactory : public ProfileKeyedServiceFactory {
  public:
   static BookmarkUndoService* GetForProfile(Profile* profile);
 
diff --git a/chrome/browser/unified_consent/unified_consent_service_factory.cc b/chrome/browser/unified_consent/unified_consent_service_factory.cc
index 708e6d4..1aa37f6 100644
--- a/chrome/browser/unified_consent/unified_consent_service_factory.cc
+++ b/chrome/browser/unified_consent/unified_consent_service_factory.cc
@@ -11,7 +11,6 @@
 #include "chrome/browser/sync/sync_service_factory.h"
 #include "chrome/common/pref_names.h"
 #include "components/embedder_support/pref_names.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
 #include "components/spellcheck/browser/pref_names.h"
@@ -46,9 +45,7 @@
 }  // namespace
 
 UnifiedConsentServiceFactory::UnifiedConsentServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "UnifiedConsentService",
-          BrowserContextDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactory("UnifiedConsentService") {
   DependsOn(IdentityManagerFactory::GetInstance());
   DependsOn(SyncServiceFactory::GetInstance());
 }
diff --git a/chrome/browser/unified_consent/unified_consent_service_factory.h b/chrome/browser/unified_consent/unified_consent_service_factory.h
index e8e247b..8e47f14 100644
--- a/chrome/browser/unified_consent/unified_consent_service_factory.h
+++ b/chrome/browser/unified_consent/unified_consent_service_factory.h
@@ -6,14 +6,14 @@
 #define CHROME_BROWSER_UNIFIED_CONSENT_UNIFIED_CONSENT_SERVICE_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 namespace unified_consent {
 class UnifiedConsentService;
 }
 
-class UnifiedConsentServiceFactory : public BrowserContextKeyedServiceFactory {
+class UnifiedConsentServiceFactory : public ProfileKeyedServiceFactory {
  public:
   // Returns the instance of UnifiedConsentService associated with |profile|
   // (creating one if none exists). Returns nullptr if this profile cannot have
diff --git a/chrome/browser/usb/usb_chooser_context_factory.cc b/chrome/browser/usb/usb_chooser_context_factory.cc
index ac08491..2aec2cc 100644
--- a/chrome/browser/usb/usb_chooser_context_factory.cc
+++ b/chrome/browser/usb/usb_chooser_context_factory.cc
@@ -5,15 +5,13 @@
 #include "chrome/browser/usb/usb_chooser_context_factory.h"
 
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/usb/usb_chooser_context.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 UsbChooserContextFactory::UsbChooserContextFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "UsbChooserContext",
-          BrowserContextDependencyManager::GetInstance()) {
+          ProfileSelections::BuildForRegularAndIncognito()) {
   DependsOn(HostContentSettingsMapFactory::GetInstance());
 }
 
@@ -41,11 +39,6 @@
       GetInstance()->GetServiceForBrowserContext(profile, /*create=*/false));
 }
 
-content::BrowserContext* UsbChooserContextFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextOwnInstanceInIncognito(context);
-}
-
 void UsbChooserContextFactory::BrowserContextShutdown(
     content::BrowserContext* context) {
   auto* usb_chooser_context =
diff --git a/chrome/browser/usb/usb_chooser_context_factory.h b/chrome/browser/usb/usb_chooser_context_factory.h
index e38812c..b2b2f81 100644
--- a/chrome/browser/usb/usb_chooser_context_factory.h
+++ b/chrome/browser/usb/usb_chooser_context_factory.h
@@ -6,12 +6,12 @@
 #define CHROME_BROWSER_USB_USB_CHOOSER_CONTEXT_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class UsbChooserContext;
 class Profile;
 
-class UsbChooserContextFactory : public BrowserContextKeyedServiceFactory {
+class UsbChooserContextFactory : public ProfileKeyedServiceFactory {
  public:
   static UsbChooserContext* GetForProfile(Profile* profile);
   static UsbChooserContext* GetForProfileIfExists(Profile* profile);
@@ -29,8 +29,6 @@
   // BrowserContextKeyedServiceFactory methods:
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* profile) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
   void BrowserContextShutdown(content::BrowserContext* context) override;
 };
 
diff --git a/chrome/browser/user_notes/user_note_service_factory.cc b/chrome/browser/user_notes/user_note_service_factory.cc
index 4c576fc8..25b92690 100644
--- a/chrome/browser/user_notes/user_note_service_factory.cc
+++ b/chrome/browser/user_notes/user_note_service_factory.cc
@@ -9,7 +9,6 @@
 #include "base/memory/singleton.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/user_notes/user_note_service_delegate_impl.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/user_notes/browser/user_note_service.h"
 #include "components/user_notes/storage/user_note_storage_impl.h"
 #include "components/user_notes/user_notes_features.h"
@@ -40,9 +39,10 @@
 }
 
 UserNoteServiceFactory::UserNoteServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "UserNoteService",
-          BrowserContextDependencyManager::GetInstance()) {}
+    // For now, the feature is not supported in Incognito mode.
+    // TODO(crbug.com/1313967): This will need to be changed if User Notes are
+    // to be available in Incognito.
+    : ProfileKeyedServiceFactory("UserNoteService") {}
 
 UserNoteServiceFactory::~UserNoteServiceFactory() = default;
 
@@ -55,16 +55,4 @@
       std::make_unique<UserNoteStorageImpl>(context->GetPath()));
 }
 
-content::BrowserContext* UserNoteServiceFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  // For now, the feature is not supported in Incognito mode.
-  // TODO(crbug.com/1313967): This will need to be changed if User Notes are to
-  // be available in Incognito.
-  if (context->IsOffTheRecord()) {
-    return nullptr;
-  }
-
-  return context;
-}
-
 }  // namespace user_notes
diff --git a/chrome/browser/user_notes/user_note_service_factory.h b/chrome/browser/user_notes/user_note_service_factory.h
index afa9936..34741bc 100644
--- a/chrome/browser/user_notes/user_note_service_factory.h
+++ b/chrome/browser/user_notes/user_note_service_factory.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_USER_NOTES_USER_NOTE_SERVICE_FACTORY_H_
 #define CHROME_BROWSER_USER_NOTES_USER_NOTE_SERVICE_FACTORY_H_
 
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 #include <memory>
 
@@ -20,7 +20,7 @@
 
 // Factory to get or create a UserNoteService instance for the current browser
 // context.
-class UserNoteServiceFactory : public BrowserContextKeyedServiceFactory {
+class UserNoteServiceFactory : public ProfileKeyedServiceFactory {
  public:
   static UserNoteService* GetForContext(content::BrowserContext* context);
 
@@ -42,8 +42,6 @@
   // BrowserContextKeyedServiceFactory implementation.
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
 
   std::unique_ptr<UserNoteService> service_for_testing_;
 };
diff --git a/chrome/browser/web_applications/app_shim_registry_mac.cc b/chrome/browser/web_applications/app_shim_registry_mac.cc
index f3e9ce9d..591c5ca 100644
--- a/chrome/browser/web_applications/app_shim_registry_mac.cc
+++ b/chrome/browser/web_applications/app_shim_registry_mac.cc
@@ -80,7 +80,13 @@
   if (installed_profiles.count(profile))
     return;
   installed_profiles.insert(profile);
-  SetAppInfo(app_id, &installed_profiles, nullptr);
+  // Also add the profile to the last active profiles. This way the next time
+  // the app is launched, it will at least launch in the most recently
+  // installed profile.
+  std::set<base::FilePath> last_active_profiles =
+      GetLastActiveProfilesForApp(app_id);
+  last_active_profiles.insert(profile);
+  SetAppInfo(app_id, &installed_profiles, &last_active_profiles);
 }
 
 bool AppShimRegistry::OnAppUninstalledForProfile(
diff --git a/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.mm b/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.mm
index 8c64ff1..cc10f9b 100644
--- a/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.mm
+++ b/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.mm
@@ -17,6 +17,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/extension_ui_util.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/web_applications/app_shim_registry_mac.h"
 #include "chrome/browser/web_applications/extensions/web_app_extension_shortcut.h"
 #include "chrome/browser/web_applications/os_integration/web_app_shortcut_mac.h"
 #include "chrome/browser/web_applications/web_app_id.h"
@@ -166,6 +167,12 @@
   CreateShortcutsForWebApp(web_app::SHORTCUT_CREATION_BY_USER,
                            web_app::ShortcutLocations(), profile, app_id,
                            base::BindOnce(std::move(close_callback)));
+  // Also inform AppShimRegistry about the created shortcut. For anything other
+  // than default apps this is a no-op, as you can't create shortcuts without
+  // the app already having been installed (at which point AppShimRegistry would
+  // have been informed). But for default apps this is required to make sure the
+  // created shortcut opens the app in the correct profile.
+  AppShimRegistry::Get()->OnAppInstalledForProfile(app_id, profile->GetPath());
 }
 
 }  // namespace chrome
diff --git a/chrome/browser/web_applications/os_integration/os_integration_manager.cc b/chrome/browser/web_applications/os_integration/os_integration_manager.cc
index 45d8fa84..5c654c2 100644
--- a/chrome/browser/web_applications/os_integration/os_integration_manager.cc
+++ b/chrome/browser/web_applications/os_integration/os_integration_manager.cc
@@ -152,8 +152,10 @@
   // been registered).
   std::vector<AppId> app_ids = registrar_->GetAppIds();
   for (const auto& app_id : app_ids) {
-    AppShimRegistry::Get()->OnAppInstalledForProfile(app_id,
-                                                     profile_->GetPath());
+    if (!registrar_->WasInstalledByDefaultOnly(app_id)) {
+      AppShimRegistry::Get()->OnAppInstalledForProfile(app_id,
+                                                       profile_->GetPath());
+    }
   }
 #endif
   file_handler_manager_->Start();
diff --git a/chrome/browser/webid/federated_identity_active_session_permission_context_factory.cc b/chrome/browser/webid/federated_identity_active_session_permission_context_factory.cc
index d109855..8fac545 100644
--- a/chrome/browser/webid/federated_identity_active_session_permission_context_factory.cc
+++ b/chrome/browser/webid/federated_identity_active_session_permission_context_factory.cc
@@ -6,10 +6,8 @@
 
 #include "base/no_destructor.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/webid/federated_identity_active_session_permission_context.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 // static
 FederatedIdentityActiveSessionPermissionContext*
@@ -30,21 +28,15 @@
 
 FederatedIdentityActiveSessionPermissionContextFactory::
     FederatedIdentityActiveSessionPermissionContextFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "FederatedIdentityActiveSessionPermissionContext",
-          BrowserContextDependencyManager::GetInstance()) {
+          ProfileSelections::BuildForRegularAndIncognito()) {
   DependsOn(HostContentSettingsMapFactory::GetInstance());
 }
 
 FederatedIdentityActiveSessionPermissionContextFactory::
     ~FederatedIdentityActiveSessionPermissionContextFactory() = default;
 
-content::BrowserContext*
-FederatedIdentityActiveSessionPermissionContextFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextOwnInstanceInIncognito(context);
-}
-
 KeyedService*
 FederatedIdentityActiveSessionPermissionContextFactory::BuildServiceInstanceFor(
     content::BrowserContext* profile) const {
diff --git a/chrome/browser/webid/federated_identity_active_session_permission_context_factory.h b/chrome/browser/webid/federated_identity_active_session_permission_context_factory.h
index a636350a..60de452 100644
--- a/chrome/browser/webid/federated_identity_active_session_permission_context_factory.h
+++ b/chrome/browser/webid/federated_identity_active_session_permission_context_factory.h
@@ -6,14 +6,14 @@
 #define CHROME_BROWSER_WEBID_FEDERATED_IDENTITY_ACTIVE_SESSION_PERMISSION_CONTEXT_FACTORY_H_
 
 #include "base/no_destructor.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class FederatedIdentityActiveSessionPermissionContext;
 
 // Factory to get or create an instance of
 // FederatedIdentityActiveSessionPermissionContext from a Profile.
 class FederatedIdentityActiveSessionPermissionContextFactory
-    : public BrowserContextKeyedServiceFactory {
+    : public ProfileKeyedServiceFactory {
  public:
   static FederatedIdentityActiveSessionPermissionContext* GetForProfile(
       content::BrowserContext* profile);
@@ -27,8 +27,6 @@
   ~FederatedIdentityActiveSessionPermissionContextFactory() override;
 
   // BrowserContextKeyedServiceFactory:
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* profile) const override;
   void BrowserContextShutdown(content::BrowserContext* context) override;
diff --git a/chrome/browser/webid/federated_identity_api_permission_context_factory.cc b/chrome/browser/webid/federated_identity_api_permission_context_factory.cc
index 3135bc2..a5d0f04 100644
--- a/chrome/browser/webid/federated_identity_api_permission_context_factory.cc
+++ b/chrome/browser/webid/federated_identity_api_permission_context_factory.cc
@@ -6,10 +6,8 @@
 
 #include "base/no_destructor.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/webid/federated_identity_api_permission_context.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 // static
 FederatedIdentityApiPermissionContext*
@@ -29,21 +27,15 @@
 
 FederatedIdentityApiPermissionContextFactory::
     FederatedIdentityApiPermissionContextFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "FederatedIdentityApiPermissionContext",
-          BrowserContextDependencyManager::GetInstance()) {
+          ProfileSelections::BuildForRegularAndIncognito()) {
   DependsOn(HostContentSettingsMapFactory::GetInstance());
 }
 
 FederatedIdentityApiPermissionContextFactory::
     ~FederatedIdentityApiPermissionContextFactory() = default;
 
-content::BrowserContext*
-FederatedIdentityApiPermissionContextFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextOwnInstanceInIncognito(context);
-}
-
 KeyedService*
 FederatedIdentityApiPermissionContextFactory::BuildServiceInstanceFor(
     content::BrowserContext* profile) const {
diff --git a/chrome/browser/webid/federated_identity_api_permission_context_factory.h b/chrome/browser/webid/federated_identity_api_permission_context_factory.h
index 8a773ed..becc095e 100644
--- a/chrome/browser/webid/federated_identity_api_permission_context_factory.h
+++ b/chrome/browser/webid/federated_identity_api_permission_context_factory.h
@@ -6,14 +6,14 @@
 #define CHROME_BROWSER_WEBID_FEDERATED_IDENTITY_API_PERMISSION_CONTEXT_FACTORY_H_
 
 #include "base/no_destructor.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class FederatedIdentityApiPermissionContext;
 
 // Factory to get or create an instance of FederatedIdentityApiPermissionContext
 // from a Profile.
 class FederatedIdentityApiPermissionContextFactory
-    : public BrowserContextKeyedServiceFactory {
+    : public ProfileKeyedServiceFactory {
  public:
   static FederatedIdentityApiPermissionContext* GetForProfile(
       content::BrowserContext* profile);
@@ -26,8 +26,6 @@
   ~FederatedIdentityApiPermissionContextFactory() override;
 
   // BrowserContextKeyedServiceFactory:
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* profile) const override;
 };
diff --git a/chrome/browser/webid/federated_identity_sharing_permission_context_factory.cc b/chrome/browser/webid/federated_identity_sharing_permission_context_factory.cc
index 6731f2c..25ce84a 100644
--- a/chrome/browser/webid/federated_identity_sharing_permission_context_factory.cc
+++ b/chrome/browser/webid/federated_identity_sharing_permission_context_factory.cc
@@ -6,10 +6,8 @@
 
 #include "base/no_destructor.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/webid/federated_identity_sharing_permission_context.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 // static
 FederatedIdentitySharingPermissionContext*
@@ -29,21 +27,15 @@
 
 FederatedIdentitySharingPermissionContextFactory::
     FederatedIdentitySharingPermissionContextFactory()
-    : BrowserContextKeyedServiceFactory(
+    : ProfileKeyedServiceFactory(
           "FederatedIdentitySharingPermissionContext",
-          BrowserContextDependencyManager::GetInstance()) {
+          ProfileSelections::BuildForRegularAndIncognito()) {
   DependsOn(HostContentSettingsMapFactory::GetInstance());
 }
 
 FederatedIdentitySharingPermissionContextFactory::
     ~FederatedIdentitySharingPermissionContextFactory() = default;
 
-content::BrowserContext*
-FederatedIdentitySharingPermissionContextFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextOwnInstanceInIncognito(context);
-}
-
 KeyedService*
 FederatedIdentitySharingPermissionContextFactory::BuildServiceInstanceFor(
     content::BrowserContext* profile) const {
diff --git a/chrome/browser/webid/federated_identity_sharing_permission_context_factory.h b/chrome/browser/webid/federated_identity_sharing_permission_context_factory.h
index 40afa25..2192673 100644
--- a/chrome/browser/webid/federated_identity_sharing_permission_context_factory.h
+++ b/chrome/browser/webid/federated_identity_sharing_permission_context_factory.h
@@ -6,14 +6,14 @@
 #define CHROME_BROWSER_WEBID_FEDERATED_IDENTITY_SHARING_PERMISSION_CONTEXT_FACTORY_H_
 
 #include "base/no_destructor.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class FederatedIdentitySharingPermissionContext;
 
 // Factory to get or create an instance of
 // FederatedIdentitySharingPermissionContext from a Profile.
 class FederatedIdentitySharingPermissionContextFactory
-    : public BrowserContextKeyedServiceFactory {
+    : public ProfileKeyedServiceFactory {
  public:
   static FederatedIdentitySharingPermissionContext* GetForProfile(
       content::BrowserContext* profile);
@@ -27,8 +27,6 @@
   ~FederatedIdentitySharingPermissionContextFactory() override;
 
   // BrowserContextKeyedServiceFactory:
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* profile) const override;
   void BrowserContextShutdown(content::BrowserContext* context) override;
diff --git a/chrome/browser/win/jumplist_factory.cc b/chrome/browser/win/jumplist_factory.cc
index 66e6fe0..a47832ea 100644
--- a/chrome/browser/win/jumplist_factory.cc
+++ b/chrome/browser/win/jumplist_factory.cc
@@ -9,7 +9,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sessions/tab_restore_service_factory.h"
 #include "chrome/browser/win/jumplist.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 // static
 JumpList* JumpListFactory::GetForProfile(Profile* profile) {
@@ -22,10 +21,7 @@
   return base::Singleton<JumpListFactory>::get();
 }
 
-JumpListFactory::JumpListFactory()
-    : BrowserContextKeyedServiceFactory(
-          "JumpList",
-          BrowserContextDependencyManager::GetInstance()) {
+JumpListFactory::JumpListFactory() : ProfileKeyedServiceFactory("JumpList") {
   DependsOn(TabRestoreServiceFactory::GetInstance());
   DependsOn(TopSitesFactory::GetInstance());
   DependsOn(FaviconServiceFactory::GetInstance());
diff --git a/chrome/browser/win/jumplist_factory.h b/chrome/browser/win/jumplist_factory.h
index 7155c80..4f74678 100644
--- a/chrome/browser/win/jumplist_factory.h
+++ b/chrome/browser/win/jumplist_factory.h
@@ -6,12 +6,12 @@
 #define CHROME_BROWSER_WIN_JUMPLIST_FACTORY_H_
 
 #include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
 class Profile;
 class JumpList;
 
-class JumpListFactory : public BrowserContextKeyedServiceFactory {
+class JumpListFactory : public ProfileKeyedServiceFactory {
  public:
   static JumpList* GetForProfile(Profile* profile);
 
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index ce83e603..d737809 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1661169344-717addf9885f8e053ed41c1753d05e56e994c2ec.profdata
+chrome-win64-main-1661180252-3e2773d67569e0f26c164885b5560954d41dd115.profdata
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index 0a12b55..36e38b7 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -35,6 +35,7 @@
   header = "buildflags.h"
   flags = [
     "BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED=$builtin_cert_verifier_policy_supported",
+    "CHROME_ENABLE_LOGGING_BY_DEFAULT=$chrome_enable_logging_by_default",
     "CHROME_ROOT_STORE_POLICY_SUPPORTED=$chrome_root_store_policy_supported",
     "ENABLE_BACKGROUND_MODE=$enable_background_mode",
     "ENABLE_BACKGROUND_CONTENTS=$enable_background_contents",
diff --git a/chrome/common/extensions/api/autotest_private.idl b/chrome/common/extensions/api/autotest_private.idl
index d59be2a..a78c955 100644
--- a/chrome/common/extensions/api/autotest_private.idl
+++ b/chrome/common/extensions/api/autotest_private.idl
@@ -543,7 +543,13 @@
 
     OverviewInfo? overviewInfo;
 
+    // The identifier of the app associated with the window that was launched
+    // from full restore. This should be same as |appId| when the window was
+    // restored from full restore, otherwise null.
     DOMString? fullRestoreWindowAppId;
+
+    // The identifier of the app associated with the window.
+    DOMString? appId;
   };
 
   dictionary Accelerator {
diff --git a/chrome/common/extensions/api/devtools/OWNERS b/chrome/common/extensions/api/devtools/OWNERS
index bc362ba..3e398966 100644
--- a/chrome/common/extensions/api/devtools/OWNERS
+++ b/chrome/common/extensions/api/devtools/OWNERS
@@ -1,2 +1 @@
 caseq@chromium.org
-pfeldman@chromium.org
diff --git a/chrome/common/extensions/image_writer/OWNERS b/chrome/common/extensions/image_writer/OWNERS
deleted file mode 100644
index 22549ad..0000000
--- a/chrome/common/extensions/image_writer/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-haven@chromium.org
diff --git a/chrome/common/features.gni b/chrome/common/features.gni
index b413609..d493906 100644
--- a/chrome/common/features.gni
+++ b/chrome/common/features.gni
@@ -33,6 +33,10 @@
   # unconditionally enabled on all platforms.
   builtin_cert_verifier_policy_supported = is_mac
 
+  # Enables the build to have logging enabled by default.
+  # This is intended for use only in developer builds.
+  chrome_enable_logging_by_default = is_debug
+
   # Platforms where the ChromeRootStoreEnabled enterprise policy is
   # supported. This must must match the supported_on/future_on list of the
   # policy in policy_templates.json and be a subset of the
@@ -78,6 +82,12 @@
   # optimize_webui was moved to ui/base/ui_features.gni
 }
 
+# Logging must be disabled by default in all official builds (including special
+# DCHECK-enabled builds). Logging is enabled by default for debug builds, and
+# may be selectively enabled by default for release builds.
+assert(!chrome_enable_logging_by_default || !is_official_build,
+       "Logging must be disabled by default in Official builds")
+
 # Enables supervision for Family Link users.
 # Supervision is only supported on Chrome OS and Android.
 enable_supervised_users = is_chromeos || is_android
diff --git a/chrome/common/logging_chrome.cc b/chrome/common/logging_chrome.cc
index 2bf9783e..d40956a 100644
--- a/chrome/common/logging_chrome.cc
+++ b/chrome/common/logging_chrome.cc
@@ -48,6 +48,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/chromeos_buildflags.h"
+#include "chrome/common/buildflags.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
@@ -134,21 +135,25 @@
 LoggingDestination DetermineLoggingDestination(
     const base::CommandLine& command_line) {
 #if BUILDFLAG(IS_FUCHSIA)
-  // On Fuchsia, the default logging mode is the system log in both debug and
-  // release mode.
+  // Fuchsia provides a system log that can be filtered for logs from specific
+  // components (e.g. Chrome), and which is easier to access than logs in a
+  // file in the component's namespace would be, so always use the system log
+  // by default.
   const LoggingDestination kDefaultLoggingMode = LOG_TO_SYSTEM_DEBUG_LOG;
-#elif NDEBUG
+#elif defined(NDEBUG)
+  // In Release builds, log only to the log file.
   const LoggingDestination kDefaultLoggingMode = LOG_TO_FILE;
 #else
+  // In Debug builds log to all destinations, for ease of discovery.
   const LoggingDestination kDefaultLoggingMode = LOG_TO_ALL;
 #endif  // BUILDFLAG(IS_FUCHSIA)
 
-#ifdef NDEBUG
-  bool enable_logging = false;
-  const char* kInvertLoggingSwitch = switches::kEnableLogging;
-#else
+#if BUILDFLAG(CHROME_ENABLE_LOGGING_BY_DEFAULT)
   bool enable_logging = true;
-  const char* kInvertLoggingSwitch = switches::kDisableLogging;
+  const char* const kInvertLoggingSwitch = switches::kDisableLogging;
+#else
+  bool enable_logging = false;
+  const char* const kInvertLoggingSwitch = switches::kEnableLogging;
 #endif
 
   if (command_line.HasSwitch(kInvertLoggingSwitch))
diff --git a/chrome/renderer/accessibility/read_anything_app_controller.cc b/chrome/renderer/accessibility/read_anything_app_controller.cc
index 4501738..3d58fbb 100644
--- a/chrome/renderer/accessibility/read_anything_app_controller.cc
+++ b/chrome/renderer/accessibility/read_anything_app_controller.cc
@@ -52,6 +52,17 @@
   gin::ConvertFromV8(isolate, v8_id, &ax_node_data->id);
 }
 
+void SetAXNodeDataLanguage(v8::Isolate* isolate,
+                           gin::Dictionary* v8_dict,
+                           ui::AXNodeData* ax_node_data) {
+  v8::Local<v8::Value> v8_language;
+  v8_dict->Get("language", &v8_language);
+  std::string language;
+  gin::ConvertFromV8(isolate, v8_language, &language);
+  ax_node_data->AddStringAttribute(ax::mojom::StringAttribute::kLanguage,
+                                   language);
+}
+
 void SetAXNodeDataName(v8::Isolate* isolate,
                        gin::Dictionary* v8_dict,
                        ui::AXNodeData* ax_node_data) {
@@ -135,6 +146,7 @@
     SetAXNodeDataName(isolate, &v8_node_dict, &ax_node_data);
     SetAXNodeDataChildIds(isolate, &v8_node_dict, &ax_node_data);
     SetAXNodeDataHtmlTag(isolate, &v8_node_dict, &ax_node_data);
+    SetAXNodeDataLanguage(isolate, &v8_node_dict, &ax_node_data);
     SetAXNodeDataUrl(isolate, &v8_node_dict, &ax_node_data);
     snapshot.nodes.push_back(ax_node_data);
   }
@@ -224,6 +236,7 @@
                    &ReadAnythingAppController::BackgroundColor)
       .SetMethod("getChildren", &ReadAnythingAppController::GetChildren)
       .SetMethod("getHtmlTag", &ReadAnythingAppController::GetHtmlTag)
+      .SetMethod("getLanguage", &ReadAnythingAppController::GetLanguage)
       .SetMethod("getTextContent", &ReadAnythingAppController::GetTextContent)
       .SetMethod("getUrl", &ReadAnythingAppController::GetUrl)
       .SetMethod("onConnected", &ReadAnythingAppController::OnConnected)
@@ -273,6 +286,13 @@
   return ax_node->GetStringAttribute(ax::mojom::StringAttribute::kHtmlTag);
 }
 
+std::string ReadAnythingAppController::GetLanguage(ui::AXNodeID ax_node_id) {
+  ui::AXNode* ax_node = GetAXNode(ax_node_id);
+  if (!ax_node)
+    return std::string();
+  return ax_node->GetLanguage();
+}
+
 std::string ReadAnythingAppController::GetTextContent(ui::AXNodeID ax_node_id) {
   ui::AXNode* ax_node = GetAXNode(ax_node_id);
   if (!ax_node)
diff --git a/chrome/renderer/accessibility/read_anything_app_controller.h b/chrome/renderer/accessibility/read_anything_app_controller.h
index 488c583..7eacf36 100644
--- a/chrome/renderer/accessibility/read_anything_app_controller.h
+++ b/chrome/renderer/accessibility/read_anything_app_controller.h
@@ -78,6 +78,7 @@
   SkColor BackgroundColor();
   std::vector<ui::AXNodeID> GetChildren(ui::AXNodeID ax_node_id);
   std::string GetHtmlTag(ui::AXNodeID ax_node_id);
+  std::string GetLanguage(ui::AXNodeID ax_node_id);
   std::string GetTextContent(ui::AXNodeID ax_node_id);
   std::string GetUrl(ui::AXNodeID ax_node_id);
   void OnConnected();
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 698b2f2..cc82cb6 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3949,6 +3949,7 @@
         "../browser/ui/ash/desks/desks_client_browsertest.cc",
         "../browser/ui/ash/device_scheduled_reboot/reboot_notification_controller_browsertest.cc",
         "../browser/ui/ash/feature_discovery_duration_reporter_browsertest.cc",
+        "../browser/ui/ash/glanceables/glanceables_browsertest.cc",
         "../browser/ui/ash/keyboard/keyboard_controller_browsertest.cc",
         "../browser/ui/ash/keyboard/keyboard_end_to_end_browsertest.cc",
         "../browser/ui/ash/multi_user/test_multi_user_window_manager.cc",
diff --git a/chrome/test/data/extensions/api_test/autotest_private/test.js b/chrome/test/data/extensions/api_test/autotest_private/test.js
index 25ade28..28dedf4 100644
--- a/chrome/test/data/extensions/api_test/autotest_private/test.js
+++ b/chrome/test/data/extensions/api_test/autotest_private/test.js
@@ -806,6 +806,8 @@
         chrome.test.assertEq('Normal', window.frameMode);
         chrome.test.assertTrue(window.isFrameVisible);
         chrome.test.assertFalse(window.hasOwnProperty('overviewInfo'));
+        chrome.test.assertEq(null, window.fullRestoreWindowAppId);
+        chrome.test.assertEq('mgndgikekgjfcpckkfioiadnlibdjbkf', window.appId);
 
         var change = new Object();
         change.eventType = 'WMEventFullscreen';
diff --git a/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js b/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js
index 8993a96..1c2d68f3 100644
--- a/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js
+++ b/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js
@@ -632,11 +632,19 @@
         assertEq({
           ConnectionState: ConnectionStateType.NOT_CONNECTED,
           GUID: 'stub_wifi2',
+          IPAddressConfigType: {
+            Active: 'DHCP',
+            Effective: 'UserPolicy'
+          },
           Name: {
             Active: 'wifi2_PSK',
             Effective: 'UserPolicy',
             UserPolicy: 'My WiFi Network'
           },
+          NameServersConfigType: {
+            Active: 'DHCP',
+            Effective: 'UserPolicy'
+          },
           ProxySettings: {
             Type: {
               Active: 'Direct',
@@ -644,20 +652,15 @@
               UserPolicy: 'Direct'
             }
           },
-          IPAddressConfigType: {
-            Active: 'DHCP',
-            Effective: 'UserPolicy'
-          },
-          NameServersConfigType: {
-            Active: 'DHCP',
-            Effective: 'UserPolicy'
-          },
           Source: 'UserPolicy',
           Type: NetworkType.WI_FI,
           WiFi: {
             AutoConnect: {
-              UserEditable: true
+              UserEditable: true,
+              UserPolicy: false
             },
+            Frequency: 5000,
+            FrequencyList: [2400, 5000],
             HexSSID: {
               Active: '77696669325F50534B', // 'wifi2_PSK'
               Effective: 'UserPolicy',
@@ -668,8 +671,6 @@
               Effective: 'UserPolicy',
               UserPolicy: false,
             },
-            Frequency: 5000,
-            FrequencyList: [2400, 5000],
             Passphrase: {
               Effective: 'UserSetting',
               UserEditable: true,
diff --git a/chrome/test/data/webui/chromeos/print_management/print_management_test.js b/chrome/test/data/webui/chromeos/print_management/print_management_test.js
index ca7824b..c689915 100644
--- a/chrome/test/data/webui/chromeos/print_management/print_management_test.js
+++ b/chrome/test/data/webui/chromeos/print_management/print_management_test.js
@@ -2,44 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// TODO(jimmyxgong): use es6 module for mojo binding crbug/1004256
-import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
 import 'chrome://print-management/print_management.js';
 
 import {setMetadataProviderForTesting} from 'chrome://print-management/mojo_interface_provider.js';
+import {ActivePrintJobState, CompletedPrintJobInfo, PrinterErrorCode, PrintingMetadataProviderRemote, PrintJobCompletionStatus, PrintJobInfo, PrintJobsObserverRemote} from 'chrome://print-management/printing_manager.mojom-webui.js';
 import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {flushTasks} from 'chrome://test/test_util.js';
 
-const CompletionStatus = {
-  FAILED: 0,
-  CANCELED: 1,
-  PRINTED: 2,
-};
-
-const ActivePrintJobState =
-    ash.printing.printingManager.mojom.ActivePrintJobState;
-
-const PrinterErrorCode = {
-  NO_ERROR: ash.printing.printingManager.mojom.PrinterErrorCode.kNoError,
-  PAPER_JAM: ash.printing.printingManager.mojom.PrinterErrorCode.kPaperJam,
-  OUT_OF_PAPER: ash.printing.printingManager.mojom.PrinterErrorCode.kOutOfPaper,
-  OUT_OF_INK: ash.printing.printingManager.mojom.PrinterErrorCode.kOutOfPaper,
-  DOOR_OPEN: ash.printing.printingManager.mojom.PrinterErrorCode.kDoorOpen,
-  PRINTER_UNREACHABLE:
-      ash.printing.printingManager.mojom.PrinterErrorCode.kPrinterUnreachable,
-  TRAY_MISSING:
-      ash.printing.printingManager.mojom.PrinterErrorCode.kTrayMissing,
-  OUTPUT_FULL: ash.printing.printingManager.mojom.PrinterErrorCode.kOutputFull,
-  STOPPED: ash.printing.printingManager.mojom.PrinterErrorCode.kStopped,
-  FILTER_FAILED:
-      ash.printing.printingManager.mojom.PrinterErrorCode.kFilterFailed,
-  UNKNOWN_ERROR:
-      ash.printing.printingManager.mojom.PrinterErrorCode.kUnknownError,
-  CLIENT_UNAUTHORIZED:
-      ash.printing.printingManager.mojom.PrinterErrorCode.kClientUnauthorized,
-};
-
 /**
  * Converts a JS string to mojo_base::mojom::String16 object.
  * @param {string} str
@@ -79,9 +49,9 @@
  * @param {string} title
  * @param {number} date
  * @param {number} printerErrorCode
- * @param {?ash.printing.printingManager.mojom.CompletedPrintJobInfo}
+ * @param {?CompletedPrintJobInfo}
  *     completedInfo
- * @param {?ash.printing.printingManager.mojom.ActivePrintJobInfo}
+ * @param {?ActivePrintJobInfo}
  *     activeInfo
  * @return {!Object}
  */
@@ -111,7 +81,7 @@
 
 /**
  * @param {number} completionStatus
- * @return {!ash.printing.printingManager.mojom.CompletedPrintJobInfo}
+ * @return {!CompletedPrintJobInfo}
  */
 function createCompletedPrintJobInfo(completionStatus) {
   const completedInfo = {'completionStatus': completionStatus};
@@ -121,9 +91,9 @@
 /**
  *
  * @param {number} printedPages
- * @param {!ash.printing.printingManager.mojom.ActivePrintJobState}
+ * @param {!ActivePrintJobState}
  *     activeState
- * @return {!ash.printing.printingManager.mojom.ActivePrintJobInfo}
+ * @return {!ActivePrintJobInfo}
  */
 function createOngoingPrintJobInfo(printedPages, activeState) {
   const activeInfo = {
@@ -134,7 +104,7 @@
 }
 
 /**
- * @param{!Array<!ash.printing.printingManager.mojom.PrintJobInfo>}
+ * @param{!Array<!PrintJobInfo>}
  *     expected
  * @param{!Array<!HTMLElement>} actual
  */
@@ -196,7 +166,7 @@
     this.resolverMap_ = new Map();
 
     /**
-     * @private {!Array<ash.printing.printingManager.mojom.PrintJobInfo>}
+     * @private {!Array<PrintJobInfo>}
      */
     this.printJobs_ = [];
 
@@ -206,7 +176,7 @@
 
     /**
      * @private
-     *     {?ash.printing.printingManager.mojom.PrintJobsObserverRemote}
+     *     {?PrintJobsObserverRemote}
      */
     this.printJobsObserverRemote_;
 
@@ -266,14 +236,14 @@
 
   /**
    * @return
-   *      {ash.printing.printingManager.mojom.PrintJobsObserverRemote}
+   *      {PrintJobsObserverRemote}
    */
   getObserverRemote() {
     return this.printJobsObserverRemote_;
   }
 
   /**
-   * @param {?Array<!ash.printing.printingManager.mojom.PrintJobInfo>}
+   * @param {?Array<!PrintJobInfo>}
    *     printJobs
    */
   setPrintJobs(printJobs) {
@@ -300,7 +270,7 @@
   }
 
   /**
-   * @param {ash.printing.printingManager.mojom.PrintJobInfo} job
+   * @param {PrintJobInfo} job
    */
   addPrintJob(job) {
     this.printJobs_ = this.printJobs_.concat(job);
@@ -312,7 +282,7 @@
   }
 
   /**
-   * @param {ash.printing.printingManager.mojom.PrintJobInfo} job
+   * @param {PrintJobInfo} job
    */
   simulateUpdatePrintJob(job) {
     if (job.activePrintJobInfo.activeState ===
@@ -321,7 +291,7 @@
       const updatedJob = Object.assign({}, job);
       updatedJob.activePrintJobInfo = null;
       updatedJob.completedInfo =
-          createCompletedPrintJobInfo(CompletionStatus.PRINTED);
+          createCompletedPrintJobInfo(PrintJobCompletionStatus.kPrinted);
       // Replace with updated print job.
       const idx =
           this.printJobs_.findIndex(arr_job => arr_job.id === updatedJob.id);
@@ -336,7 +306,7 @@
 
   /**
    * @return {!Promise<{printJobs:
-   *     !Array<ash.printing.printingManager.mojom.PrintJobInfo>}>}
+   *     !Array<PrintJobInfo>}>}
    */
   getPrintJobs() {
     return new Promise(resolve => {
@@ -386,7 +356,7 @@
 
   /**
    * @param
-   * {!ash.printing.printingManager.mojom.PrintJobsObserverRemote} remote
+   * {!PrintJobsObserverRemote} remote
    * @return {!Promise}
    */
   observePrintJobs(remote) {
@@ -403,9 +373,7 @@
   let page = null;
 
   /**
-   * @type {
-   *    ?ash.printing.printingManager.mojom.PrintingMetadataProviderRemote
-   *  }
+   * @type {?PrintingMetadataProviderRemote}
    */
   let mojoApi_;
 
@@ -425,7 +393,7 @@
   });
 
   /**
-   * @param {?Array<!ash.printing.printingManager.mojom.PrintJobInfo>}
+   * @param {?Array<!PrintJobInfo>}
    *     printJobs
    * @return {!Promise}
    */
@@ -442,7 +410,7 @@
    * @param {!HtmlElement} jobEntryElement
    * @param {FakePrintingMetadataProvider} mojoApi
    * @param {boolean} shouldAttemptCancel
-   * @param {?Array<!ash.printing.printingManager.mojom.PrintJobInfo>}
+   * @param {?Array<!PrintJobInfo>}
    *    expectedHistoryList
    * @return {!Promise}
    */
@@ -457,7 +425,7 @@
       const updatedJob = Object.assign({}, jobEntryElement.jobEntry);
       updatedJob.activePrintJobInfo = createOngoingPrintJobInfo(
           /*printedPages=*/ 0, ActivePrintJobState.kDocumentDone,
-          PrinterErrorCode.NO_ERROR);
+          PrinterErrorCode.kNoError);
       // Simulate print jobs cancelled notification update sent.
       mojoApi.getObserverRemote().onPrintJobUpdate(updatedJob);
 
@@ -467,13 +435,14 @@
     });
   }
   test('PrintJobHistoryExpirationPeriodOneDay', () => {
-    const completedInfo = createCompletedPrintJobInfo(CompletionStatus.PRINTED);
+    const completedInfo =
+        createCompletedPrintJobInfo(PrintJobCompletionStatus.kPrinted);
     const expectedText = 'Print jobs older than 1 day will be removed';
     const expectedArr = [
       createJobEntry(
           'newest', 'titleA',
           convertToMojoTime(new Date(Date.UTC(2020, 3, 1, 1, 1, 1))),
-          PrinterErrorCode.NO_ERROR, completedInfo, /*activeInfo=*/ null),
+          PrinterErrorCode.kNoError, completedInfo, /*activeInfo=*/ null),
     ];
     // Print job metadata will be stored for 1 day.
     mojoApi_.setExpirationPeriod(1);
@@ -492,13 +461,14 @@
   });
 
   test('PrintJobHistoryExpirationPeriodDefault', () => {
-    const completedInfo = createCompletedPrintJobInfo(CompletionStatus.PRINTED);
+    const completedInfo =
+        createCompletedPrintJobInfo(PrintJobCompletionStatus.kPrinted);
     const expectedText = 'Print jobs older than 90 days will be removed';
     const expectedArr = [
       createJobEntry(
           'newest', 'titleA',
           convertToMojoTime(new Date(Date.UTC(2020, 3, 1, 1, 1, 1))),
-          PrinterErrorCode.NO_ERROR, completedInfo, /*activeInfo=*/ null),
+          PrinterErrorCode.kNoError, completedInfo, /*activeInfo=*/ null),
     ];
 
     // Print job metadata will be stored for 90 days which is the default
@@ -519,14 +489,15 @@
   });
 
   test('PrintJobHistoryExpirationPeriodIndefinte', () => {
-    const completedInfo = createCompletedPrintJobInfo(CompletionStatus.PRINTED);
+    const completedInfo =
+        createCompletedPrintJobInfo(PrintJobCompletionStatus.kPrinted);
     const expectedText = 'Print jobs will appear in history unless they are ' +
         'removed manually';
     const expectedArr = [
       createJobEntry(
           'newest', 'titleA',
           convertToMojoTime(new Date(Date.UTC(2020, 3, 1, 1, 1, 1))),
-          PrinterErrorCode.NO_ERROR, completedInfo, /*activeInfo=*/ null),
+          PrinterErrorCode.kNoError, completedInfo, /*activeInfo=*/ null),
     ];
 
     // When this policy is set to a value of -1, the print jobs metadata is
@@ -547,13 +518,14 @@
   });
 
   test('PrintJobHistoryExpirationPeriodNDays', () => {
-    const completedInfo = createCompletedPrintJobInfo(CompletionStatus.PRINTED);
+    const completedInfo =
+        createCompletedPrintJobInfo(PrintJobCompletionStatus.kPrinted);
     const expectedText = 'Print jobs older than 4 days will be removed';
     const expectedArr = [
       createJobEntry(
           'newest', 'titleA',
           convertToMojoTime(new Date(Date.UTC(2020, 3, 1, 1, 1, 1))),
-          PrinterErrorCode.NO_ERROR, completedInfo, /*activeInfo=*/ null),
+          PrinterErrorCode.kNoError, completedInfo, /*activeInfo=*/ null),
     ];
 
     // Print job metadata will be stored for 4 days.
@@ -573,20 +545,21 @@
   });
 
   test('PrintHistoryListIsSortedReverseChronologically', () => {
-    const completedInfo = createCompletedPrintJobInfo(CompletionStatus.PRINTED);
+    const completedInfo =
+        createCompletedPrintJobInfo(PrintJobCompletionStatus.kPrinted);
     const expectedArr = [
       createJobEntry(
           'newest', 'titleA',
           convertToMojoTime(new Date(Date.UTC(2020, 3, 1, 1, 1, 1))),
-          PrinterErrorCode.NO_ERROR, completedInfo, /*activeInfo=*/ null),
+          PrinterErrorCode.kNoError, completedInfo, /*activeInfo=*/ null),
       createJobEntry(
           'middle', 'titleB',
           convertToMojoTime(new Date(Date.UTC(2020, 2, 1, 1, 1, 1))),
-          PrinterErrorCode.NO_ERROR, completedInfo, /*activeInfo=*/ null),
+          PrinterErrorCode.kNoError, completedInfo, /*activeInfo=*/ null),
       createJobEntry(
           'oldest', 'titleC',
           convertToMojoTime(new Date(Date.UTC(2020, 1, 1, 1, 1, 1))),
-          PrinterErrorCode.NO_ERROR, completedInfo, /*activeInfo=*/ null),
+          PrinterErrorCode.kNoError, completedInfo, /*activeInfo=*/ null),
     ];
 
     // Initialize with a reversed array of |expectedArr|, since we expect the
@@ -620,8 +593,8 @@
     const expectedArr = [createJobEntry(
         'newest', 'titleA',
         convertToMojoTime(new Date(Date.UTC(2020, 3, 1, 1, 1, 1))),
-        PrinterErrorCode.NO_ERROR,
-        createCompletedPrintJobInfo(CompletionStatus.PRINTED),
+        PrinterErrorCode.kNoError,
+        createCompletedPrintJobInfo(PrintJobCompletionStatus.kPrinted),
         /*activeInfo=*/ null)];
     // Set policy to prevent user from deleting history.
     mojoApi_.setDeletePrintJobPolicy(/*isAllowedByPolicy=*/ false);
@@ -637,20 +610,21 @@
   });
 
   test('ClearAllPrintHistory', () => {
-    const completedInfo = createCompletedPrintJobInfo(CompletionStatus.PRINTED);
+    const completedInfo =
+        createCompletedPrintJobInfo(PrintJobCompletionStatus.kPrinted);
     const expectedArr = [
       createJobEntry(
           'fileA', 'titleA',
           convertToMojoTime(new Date(Date('February 5, 2020 03:24:00'))),
-          PrinterErrorCode.NO_ERROR, completedInfo, /*activeInfo=*/ null),
+          PrinterErrorCode.kNoError, completedInfo, /*activeInfo=*/ null),
       createJobEntry(
           'fileB', 'titleB',
           convertToMojoTime(new Date(Date('February 5, 2020 03:24:00'))),
-          PrinterErrorCode.NO_ERROR, completedInfo, /*activeInfo=*/ null),
+          PrinterErrorCode.kNoError, completedInfo, /*activeInfo=*/ null),
       createJobEntry(
           'fileC', 'titleC',
           convertToMojoTime(new Date(Date('February 5, 2020 03:24:00'))),
-          PrinterErrorCode.NO_ERROR, completedInfo, /*activeInfo=*/ null),
+          PrinterErrorCode.kNoError, completedInfo, /*activeInfo=*/ null),
     ];
 
     return initializePrintManagementApp(expectedArr)
@@ -688,20 +662,21 @@
   });
 
   test('PrintJobDeletesFromObserver', () => {
-    const completedInfo = createCompletedPrintJobInfo(CompletionStatus.PRINTED);
+    const completedInfo =
+        createCompletedPrintJobInfo(PrintJobCompletionStatus.kPrinted);
     const expectedArr = [
       createJobEntry(
           'fileA', 'titleA',
           convertToMojoTime(new Date(Date('February 5, 2020 03:24:00'))),
-          PrinterErrorCode.NO_ERROR, completedInfo, /*activeInfo=*/ null),
+          PrinterErrorCode.kNoError, completedInfo, /*activeInfo=*/ null),
       createJobEntry(
           'fileB', 'titleB',
           convertToMojoTime(new Date(Date('February 6, 2020 03:24:00'))),
-          PrinterErrorCode.NO_ERROR, completedInfo, /*activeInfo=*/ null),
+          PrinterErrorCode.kNoError, completedInfo, /*activeInfo=*/ null),
       createJobEntry(
           'fileC', 'titleC',
           convertToMojoTime(new Date(Date('February 7, 2020 03:24:00'))),
-          PrinterErrorCode.NO_ERROR, completedInfo, /*activeInfo=*/ null),
+          PrinterErrorCode.kNoError, completedInfo, /*activeInfo=*/ null),
     ];
 
     return initializePrintManagementApp(expectedArr)
@@ -749,11 +724,11 @@
       createJobEntry(
           'fileA', 'titleA',
           convertToMojoTime(new Date(Date('February 5, 2020 03:23:00'))),
-          PrinterErrorCode.NO_ERROR, /*completedInfo=*/ null, activeInfo1),
+          PrinterErrorCode.kNoError, /*completedInfo=*/ null, activeInfo1),
       createJobEntry(
           'fileB', 'titleB',
           convertToMojoTime(new Date(Date('February 5, 2020 03:24:00'))),
-          PrinterErrorCode.NO_ERROR, /*completedInfo=*/ null, activeInfo2),
+          PrinterErrorCode.kNoError, /*completedInfo=*/ null, activeInfo2),
     ];
 
     return initializePrintManagementApp(expectedArr)
@@ -771,7 +746,7 @@
       createJobEntry(
           'fileA', 'titleA',
           convertToMojoTime(new Date('February 5, 2020 03:24:00')),
-          PrinterErrorCode.NO_ERROR, /*completedInfo=*/ null,
+          PrinterErrorCode.kNoError, /*completedInfo=*/ null,
           createOngoingPrintJobInfo(
               /*printedPages=*/ 0, ActivePrintJobState.kStarted)),
     ];
@@ -782,7 +757,7 @@
       createJobEntry(
           'fileA', 'titleA',
           convertToMojoTime(new Date(Date('February 5, 2020 03:24:00'))),
-          PrinterErrorCode.NO_ERROR, /*completedInfo=*/ null, activeInfo2),
+          PrinterErrorCode.kNoError, /*completedInfo=*/ null, activeInfo2),
     ];
 
     return initializePrintManagementApp(expectedArr)
@@ -806,7 +781,7 @@
       createJobEntry(
           'fileA', 'titleA',
           convertToMojoTime(new Date('February 5, 2020 03:24:00')),
-          PrinterErrorCode.NO_ERROR, /*completedInfo=*/ null,
+          PrinterErrorCode.kNoError, /*completedInfo=*/ null,
           createOngoingPrintJobInfo(
               /*printedPages=*/ 0, ActivePrintJobState.kStarted)),
     ];
@@ -817,7 +792,7 @@
       createJobEntry(
           'fileA', 'titleA',
           convertToMojoTime(new Date('February 5, 2020 03:24:00')),
-          PrinterErrorCode.OUT_OF_PAPER, /*completedInfo=*/ null, activeInfo2),
+          PrinterErrorCode.kOutOfPaper, /*completedInfo=*/ null, activeInfo2),
     ];
 
     return initializePrintManagementApp(expectedArr)
@@ -840,14 +815,14 @@
     const initialJob = [createJobEntry(
         'fileA', 'titleA',
         convertToMojoTime(new Date('February 5, 2020 03:24:00')),
-        PrinterErrorCode.NO_ERROR, /*completedInfo=*/ null,
+        PrinterErrorCode.kNoError, /*completedInfo=*/ null,
         createOngoingPrintJobInfo(
             /*printedPages=*/ 0, ActivePrintJobState.kStarted))];
 
     const newOngoingJob = createJobEntry(
         'fileB', 'titleB',
         convertToMojoTime(new Date(Date('February 5, 2020 03:25:00'))),
-        PrinterErrorCode.NO_ERROR, /*completedInfo=*/ null,
+        PrinterErrorCode.kNoError, /*completedInfo=*/ null,
         createOngoingPrintJobInfo(
             /*printedPages=*/ 1, ActivePrintJobState.kStarted));
 
@@ -874,13 +849,13 @@
     const date = convertToMojoTime(new Date(Date('February 5, 2020 03:24:00')));
 
     const activeJob = createJobEntry(
-        id, title, date, PrinterErrorCode.NO_ERROR, /*completedInfo=*/ null,
+        id, title, date, PrinterErrorCode.kNoError, /*completedInfo=*/ null,
         createOngoingPrintJobInfo(
             /*printedPages=*/ 0, ActivePrintJobState.kStarted));
 
     const expectedPrintJobArr = [createJobEntry(
-        id, title, date, PrinterErrorCode.NO_ERROR,
-        createCompletedPrintJobInfo(CompletionStatus.PRINTED),
+        id, title, date, PrinterErrorCode.kNoError,
+        createCompletedPrintJobInfo(PrintJobCompletionStatus.kPrinted),
         /*activeInfo=*/ '')];
 
     return initializePrintManagementApp([activeJob])
@@ -924,15 +899,15 @@
         convertToMojoTime(new Date(Date('February 5, 2020 03:23:00')));
     const expectedArr = [
       createJobEntry(
-          kId, kTitle, kTime, PrinterErrorCode.NO_ERROR,
+          kId, kTitle, kTime, PrinterErrorCode.kNoError,
           /*completedInfo=*/ null,
           createOngoingPrintJobInfo(
               /*printedPages=*/ 0, ActivePrintJobState.STARTED)),
     ];
 
     const expectedHistoryList = [createJobEntry(
-        kId, kTitle, kTime, PrinterErrorCode.NO_ERROR,
-        createCompletedPrintJobInfo(CompletionStatus.CANCELED))];
+        kId, kTitle, kTime, PrinterErrorCode.kNoError,
+        createCompletedPrintJobInfo(PrintJobCompletionStatus.kCanceled))];
 
     return initializePrintManagementApp(expectedArr)
         .then(() => {
@@ -964,15 +939,15 @@
 
     const expectedArr = [
       createJobEntry(
-          kId, kTitle, kTime, PrinterErrorCode.NO_ERROR,
+          kId, kTitle, kTime, PrinterErrorCode.kNoError,
           /*completedInfo=*/ null,
           createOngoingPrintJobInfo(
               /*printedPages=*/ 0, ActivePrintJobState.STARTED)),
     ];
 
     const expectedHistoryList = [createJobEntry(
-        kId, kTitle, kTime, PrinterErrorCode.NO_ERROR,
-        createCompletedPrintJobInfo(CompletionStatus.CANCELED))];
+        kId, kTitle, kTime, PrinterErrorCode.kNoError,
+        createCompletedPrintJobInfo(PrintJobCompletionStatus.kCanceled))];
 
     return initializePrintManagementApp(expectedArr)
         .then(() => {
@@ -1003,9 +978,7 @@
   let jobEntryTestElement = null;
 
   /**
-   * @type {
-   *    ?ash.printing.printingManager.mojom.PrintingMetadataProviderRemote
-   *  }
+   * @type {?PrintingMetadataProviderRemote}
    */
   let mojoApi_;
 
@@ -1038,8 +1011,8 @@
 
   test('initializeJobEntry', () => {
     const expectedTitle = 'title.pdf';
-    const expectedStatus = CompletionStatus.PRINTED;
-    const expectedPrinterError = PrinterErrorCode.NO_ERROR;
+    const expectedStatus = PrintJobCompletionStatus.kPrinted;
+    const expectedPrinterError = PrinterErrorCode.kNoError;
     const expectedCreationTime = convertToMojoTime(new Date());
 
     const completedInfo = createCompletedPrintJobInfo(expectedStatus);
@@ -1074,8 +1047,8 @@
     jobEntryTestElement.jobEntry = createJobEntry(
         /*id=*/ '1', expectedTitle,
         convertToMojoTime(new Date('February 5, 2020 03:24:00')),
-        PrinterErrorCode.OUT_OF_PAPER,
-        createCompletedPrintJobInfo(CompletionStatus.FAILED),
+        PrinterErrorCode.kOutOfPaper,
+        createCompletedPrintJobInfo(PrintJobCompletionStatus.kFailed),
         /*activeInfo=*/ null);
 
     flush();
@@ -1102,7 +1075,7 @@
 
     jobEntryTestElement.jobEntry = createJobEntry(
         /*id=*/ '1', expectedTitle, expectedCreationTime,
-        PrinterErrorCode.NO_ERROR, /*completedInfo=*/ null,
+        PrinterErrorCode.kNoError, /*completedInfo=*/ null,
         createOngoingPrintJobInfo(/*printedPages=*/ 1, expectedPrinterError));
 
     flush();
@@ -1125,7 +1098,7 @@
     const expectedCreationTime =
         convertToMojoTime(new Date('February 5, 2020 03:24:00'));
     const expectedPrinterError = ActivePrintJobState.kStarted;
-    const expectedOngoingError = PrinterErrorCode.OUT_OF_PAPER;
+    const expectedOngoingError = PrinterErrorCode.kOutOfPaper;
 
     jobEntryTestElement.jobEntry = createJobEntry(
         /*id=*/ '1', expectedTitle, expectedCreationTime, expectedOngoingError,
@@ -1152,7 +1125,7 @@
     jobEntryTestElement.jobEntry = createJobEntry(
         /*id=*/ '1', /*fileName=*/ '.test - Google Docs',
         /*date=*/ convertToMojoTime(new Date('February 5, 2020 03:24:00')),
-        PrinterErrorCode.NO_ERROR, /*completedInfo=*/ null,
+        PrinterErrorCode.kNoError, /*completedInfo=*/ null,
         createOngoingPrintJobInfo(
             /*printedPages=*/ 1,
             /*printerError=*/ ActivePrintJobState.kStarted));
@@ -1167,7 +1140,7 @@
     jobEntryTestElement.jobEntry = createJobEntry(
         /*id=*/ '1', /*fileName=*/ '.test',
         /*date=*/ convertToMojoTime(new Date('February 5, 2020 03:24:00')),
-        PrinterErrorCode.NO_ERROR, /*completedInfo=*/ null,
+        PrinterErrorCode.kNoError, /*completedInfo=*/ null,
         createOngoingPrintJobInfo(
             /*printedPages=*/ 1,
             /*printerError=*/ ActivePrintJobState.kStarted));
@@ -1183,7 +1156,7 @@
     jobEntryTestElement.jobEntry = createJobEntry(
         /*id=*/ '1', /*fileName=*/ '.test',
         /*date=*/ convertToMojoTime(new Date('February 5, 2020 03:24:00')),
-        PrinterErrorCode.NO_ERROR, /*completedInfo=*/ null,
+        PrinterErrorCode.kNoError, /*completedInfo=*/ null,
         createOngoingPrintJobInfo(
             /*printedPages=*/ 1,
             /*printerError=*/ ActivePrintJobState.kStarted));
@@ -1194,7 +1167,7 @@
     jobEntryTestElement.jobEntry = createJobEntry(
         /*id=*/ '1', /*fileName=*/ '.doc',
         /*date=*/ convertToMojoTime(new Date('February 5, 2020 03:24:00')),
-        PrinterErrorCode.NO_ERROR, /*completedInfo=*/ null,
+        PrinterErrorCode.kNoError, /*completedInfo=*/ null,
         createOngoingPrintJobInfo(
             /*printedPages=*/ 1,
             /*printerError=*/ ActivePrintJobState.kStarted));
@@ -1205,7 +1178,7 @@
     jobEntryTestElement.jobEntry = createJobEntry(
         /*id=*/ '1', /*fileName=*/ ' - Google Drawings',
         /*date=*/ convertToMojoTime(new Date('February 5, 2020 03:24:00')),
-        PrinterErrorCode.NO_ERROR, /*completedInfo=*/ null,
+        PrinterErrorCode.kNoError, /*completedInfo=*/ null,
         createOngoingPrintJobInfo(
             /*printedPages=*/ 1,
             /*printerError=*/ ActivePrintJobState.kStarted));
@@ -1216,7 +1189,7 @@
     jobEntryTestElement.jobEntry = createJobEntry(
         /*id=*/ '1', /*fileName=*/ '.xlsx',
         /*date=*/ convertToMojoTime(new Date('February 5, 2020 03:24:00')),
-        PrinterErrorCode.NO_ERROR, /*completedInfo=*/ null,
+        PrinterErrorCode.kNoError, /*completedInfo=*/ null,
         createOngoingPrintJobInfo(
             /*printedPages=*/ 1,
             /*printerError=*/ ActivePrintJobState.kStarted));
@@ -1227,7 +1200,7 @@
     jobEntryTestElement.jobEntry = createJobEntry(
         /*id=*/ '1', /*fileName=*/ ' - Google Slides',
         /*date=*/ convertToMojoTime(new Date('February 5, 2020 03:24:00')),
-        PrinterErrorCode.NO_ERROR, /*completedInfo=*/ null,
+        PrinterErrorCode.kNoError, /*completedInfo=*/ null,
         createOngoingPrintJobInfo(
             /*printedPages=*/ 1,
             /*printerError=*/ ActivePrintJobState.kStarted));
diff --git a/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts b/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts
index fe48eba..c12b59d 100644
--- a/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts
+++ b/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts
@@ -129,6 +129,115 @@
     assertContainerInnerHTML(expected);
   });
 
+  test('updateContent language childNodeDiffLang', () => {
+    // root htmlTag='#document' id=1
+    // ++paragraph htmlTag='p' id=2 language='en'
+    // ++++staticText name='This is in English' id=3
+    // ++paragraph htmlTag='p' id=4 language='es'
+    // ++++staticText name='Esto es en español' id=5
+    // ++++link htmlTag='a' url='http://www.google.cn/' id=6 language='zh'
+    // ++++++staticText name='This is a link in Chinese' id=7
+    const axTree = {
+      rootId: 1,
+      nodes: [
+        {
+          id: 1,
+          role: 'rootWebArea',
+          htmlTag: '#document',
+          childIds: [2, 4],
+        },
+        {
+          id: 2,
+          role: 'paragraph',
+          htmlTag: 'p',
+          language: 'en',
+          childIds: [3],
+        },
+        {
+          id: 3,
+          role: 'staticText',
+          name: 'This is in English',
+        },
+        {
+          id: 4,
+          role: 'paragraph',
+          htmlTag: 'p',
+          language: 'es',
+          childIds: [5, 6],
+        },
+        {
+          id: 5,
+          role: 'staticText',
+          name: 'Esto es en español',
+        },
+        {
+          id: 6,
+          role: 'link',
+          htmlTag: 'a',
+          language: 'zh',
+          url: 'http://www.google.cn/',
+          childIds: [7],
+        },
+        {
+          id: 7,
+          role: 'staticText',
+          name: 'This is a link in Chinese',
+        },
+      ],
+    };
+    chrome.readAnything.setContentForTesting(axTree, [2, 4]);
+    const expected: string =
+        '<p lang="en">This is in English</p><p lang="es">Esto es en español<a href="http://www.google.cn/" lang="zh">This is a link in Chinese</a></p>';
+    assertContainerInnerHTML(expected);
+  });
+
+  test('updateContent language parentLangSet', () => {
+    // root htmlTag='#document' id=1
+    // ++paragraph htmlTag='p' id=2 language='en'
+    // ++++staticText name='This is in English' id=3
+    // ++++link htmlTag='a' url='http://www.google.cn/' id=4
+    // ++++++staticText name='This link has no language set' id=5
+    const axTree = {
+      rootId: 1,
+      nodes: [
+        {
+          id: 1,
+          role: 'rootWebArea',
+          htmlTag: '#document',
+          childIds: [2],
+        },
+        {
+          id: 2,
+          role: 'paragraph',
+          htmlTag: 'p',
+          language: 'en',
+          childIds: [3, 4],
+        },
+        {
+          id: 3,
+          role: 'staticText',
+          name: 'This is in English',
+        },
+        {
+          id: 4,
+          role: 'link',
+          htmlTag: 'a',
+          url: 'http://www.google.com/',
+          childIds: [5],
+        },
+        {
+          id: 5,
+          role: 'staticText',
+          name: 'This link has no language set',
+        },
+      ],
+    };
+    chrome.readAnything.setContentForTesting(axTree, [2]);
+    const expected: string =
+        '<p lang="en">This is in English<a href="http://www.google.com/">This link has no language set</a></p>';
+    assertContainerInnerHTML(expected);
+  });
+
   test('updateContent heading', () => {
     // Fake chrome.readAnything methods for the following AXTree
     // root htmlTag='#document' id=1
diff --git a/chrome/updater/app/server/win/com_classes_legacy.cc b/chrome/updater/app/server/win/com_classes_legacy.cc
index 3352494..7763704 100644
--- a/chrome/updater/app/server/win/com_classes_legacy.cc
+++ b/chrome/updater/app/server/win/com_classes_legacy.cc
@@ -869,6 +869,42 @@
   virtual ~LastCheckedTimeResult() = default;
 };
 
+// Holds the result of the IPC to retrieve PolicyService data.
+template <typename T>
+class PolicyStatusResult
+    : public base::RefCountedThreadSafe<PolicyStatusResult<T>> {
+ public:
+  using ValueGetter = base::RepeatingCallback<bool(PolicyStatus<T>*, T*)>;
+
+  static auto Get(ValueGetter value_getter) {
+    auto result = base::WrapRefCounted(new PolicyStatusResult<T>(value_getter));
+    AppServerSingletonInstance()->main_task_runner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&PolicyStatusResult::GetValueOnSequence, result));
+    result->completion_event.TimedWait(base::Seconds(60));
+    return result->value;
+  }
+
+ private:
+  friend base::RefCountedThreadSafe<PolicyStatusResult<T>>;
+  virtual ~PolicyStatusResult() = default;
+
+  explicit PolicyStatusResult(ValueGetter value_getter)
+      : value_getter(value_getter) {}
+
+  void GetValueOnSequence() {
+    PolicyStatus<T> policy_status;
+    if (value_getter.Run(&policy_status, nullptr)) {
+      value = policy_status;
+    }
+    completion_event.Signal();
+  }
+
+  ValueGetter value_getter;
+  absl::optional<PolicyStatus<T>> value;
+  base::WaitableEvent completion_event;
+};
+
 }  // namespace
 
 STDMETHODIMP PolicyStatusImpl::get_lastCheckedTime(DATE* last_checked) {
@@ -926,17 +962,16 @@
                          AppServerSingletonInstance()->config(),
                          AppServerSingletonInstance()->main_task_runner()),
                      base::DoNothing()));
-
   return S_OK;
 }
 
 STDMETHODIMP PolicyStatusImpl::get_lastCheckPeriodMinutes(
     IPolicyStatusValue** value) {
   DCHECK(value);
-
-  PolicyStatus<int> policy_status;
-  return policy_service_->GetLastCheckPeriodMinutes(&policy_status, nullptr)
-             ? PolicyStatusValueImpl::Create(policy_status, value)
+  auto policy_status = PolicyStatusResult<int>::Get(base::BindRepeating(
+      &PolicyService::GetLastCheckPeriodMinutes, policy_service_));
+  return policy_status.has_value()
+             ? PolicyStatusValueImpl::Create(*policy_status, value)
              : E_FAIL;
 }
 
@@ -946,80 +981,77 @@
   DCHECK(value);
   DCHECK(are_updates_suppressed);
 
-  UpdatesSuppressedTimes updates_suppressed_times;
-  PolicyStatus<UpdatesSuppressedTimes> policy_status;
-  if (!policy_service_->GetUpdatesSuppressedTimes(&policy_status,
-                                                  &updates_suppressed_times) ||
-      !updates_suppressed_times.valid()) {
+  auto policy_status =
+      PolicyStatusResult<UpdatesSuppressedTimes>::Get(base::BindRepeating(
+          &PolicyService::GetUpdatesSuppressedTimes, policy_service_));
+  if (!policy_status.has_value())
     return E_FAIL;
-  }
-
+  const UpdatesSuppressedTimes updates_suppressed_times =
+      policy_status->effective_policy()->policy;
+  if (!updates_suppressed_times.valid())
+    return E_FAIL;
   base::Time::Exploded now;
   base::Time::Now().LocalExplode(&now);
   *are_updates_suppressed =
       updates_suppressed_times.contains(now.hour, now.minute) ? VARIANT_TRUE
                                                               : VARIANT_FALSE;
-
-  return PolicyStatusValueImpl::Create(policy_status, value);
+  return PolicyStatusValueImpl::Create(*policy_status, value);
 }
 
 STDMETHODIMP PolicyStatusImpl::get_downloadPreferenceGroupPolicy(
     IPolicyStatusValue** value) {
   DCHECK(value);
-
-  PolicyStatus<std::string> policy_status;
-  return policy_service_->GetDownloadPreferenceGroupPolicy(&policy_status,
-                                                           nullptr)
-             ? PolicyStatusValueImpl::Create(policy_status, value)
+  auto policy_status = PolicyStatusResult<std::string>::Get(base::BindRepeating(
+      &PolicyService::GetDownloadPreferenceGroupPolicy, policy_service_));
+  return policy_status.has_value()
+             ? PolicyStatusValueImpl::Create(*policy_status, value)
              : E_FAIL;
 }
 
 STDMETHODIMP PolicyStatusImpl::get_packageCacheSizeLimitMBytes(
     IPolicyStatusValue** value) {
   DCHECK(value);
-
-  PolicyStatus<int> policy_status;
-  return policy_service_->GetPackageCacheSizeLimitMBytes(&policy_status,
-                                                         nullptr)
-             ? PolicyStatusValueImpl::Create(policy_status, value)
+  auto policy_status = PolicyStatusResult<int>::Get(base::BindRepeating(
+      &PolicyService::GetPackageCacheSizeLimitMBytes, policy_service_));
+  return policy_status.has_value()
+             ? PolicyStatusValueImpl::Create(*policy_status, value)
              : E_FAIL;
 }
 
 STDMETHODIMP PolicyStatusImpl::get_packageCacheExpirationTimeDays(
     IPolicyStatusValue** value) {
   DCHECK(value);
-
-  PolicyStatus<int> policy_status;
-  return policy_service_->GetPackageCacheExpirationTimeDays(&policy_status,
-                                                            nullptr)
-             ? PolicyStatusValueImpl::Create(policy_status, value)
+  auto policy_status = PolicyStatusResult<int>::Get(base::BindRepeating(
+      &PolicyService::GetPackageCacheExpirationTimeDays, policy_service_));
+  return policy_status.has_value()
+             ? PolicyStatusValueImpl::Create(*policy_status, value)
              : E_FAIL;
 }
 
 STDMETHODIMP PolicyStatusImpl::get_proxyMode(IPolicyStatusValue** value) {
   DCHECK(value);
-
-  PolicyStatus<std::string> policy_status;
-  return policy_service_->GetProxyMode(&policy_status, nullptr)
-             ? PolicyStatusValueImpl::Create(policy_status, value)
+  auto policy_status = PolicyStatusResult<std::string>::Get(
+      base::BindRepeating(&PolicyService::GetProxyMode, policy_service_));
+  return policy_status.has_value()
+             ? PolicyStatusValueImpl::Create(*policy_status, value)
              : E_FAIL;
 }
 
 STDMETHODIMP PolicyStatusImpl::get_proxyPacUrl(IPolicyStatusValue** value) {
   DCHECK(value);
-
-  PolicyStatus<std::string> policy_status;
-  return policy_service_->GetProxyPacUrl(&policy_status, nullptr)
-             ? PolicyStatusValueImpl::Create(policy_status, value)
+  auto policy_status = PolicyStatusResult<std::string>::Get(
+      base::BindRepeating(&PolicyService::GetProxyPacUrl, policy_service_));
+  return policy_status.has_value()
+             ? PolicyStatusValueImpl::Create(*policy_status, value)
              : E_FAIL;
 }
 
 STDMETHODIMP PolicyStatusImpl::get_proxyServer(IPolicyStatusValue** value) {
   DCHECK(value);
-
-  PolicyStatus<std::string> policy_status;
-  return policy_service_->GetProxyServer(&policy_status, nullptr)
-             ? PolicyStatusValueImpl::Create(policy_status, value)
+  auto policy_status = PolicyStatusResult<std::string>::Get(
+      base::BindRepeating(&PolicyService::GetProxyServer, policy_service_));
+  return policy_status.has_value()
+             ? PolicyStatusValueImpl::Create(*policy_status, value)
              : E_FAIL;
 }
 
@@ -1027,11 +1059,11 @@
     BSTR app_id,
     IPolicyStatusValue** value) {
   DCHECK(value);
-
-  PolicyStatus<int> policy_status;
-  return policy_service_->GetEffectivePolicyForAppInstalls(
-             base::WideToASCII(app_id), &policy_status, nullptr)
-             ? PolicyStatusValueImpl::Create(policy_status, value)
+  auto policy_status = PolicyStatusResult<int>::Get(
+      base::BindRepeating(&PolicyService::GetEffectivePolicyForAppInstalls,
+                          policy_service_, base::WideToASCII(app_id)));
+  return policy_status.has_value()
+             ? PolicyStatusValueImpl::Create(*policy_status, value)
              : E_FAIL;
 }
 
@@ -1039,11 +1071,11 @@
     BSTR app_id,
     IPolicyStatusValue** value) {
   DCHECK(value);
-
-  PolicyStatus<int> policy_status;
-  return policy_service_->GetEffectivePolicyForAppUpdates(
-             base::WideToASCII(app_id), &policy_status, nullptr)
-             ? PolicyStatusValueImpl::Create(policy_status, value)
+  auto policy_status = PolicyStatusResult<int>::Get(
+      base::BindRepeating(&PolicyService::GetEffectivePolicyForAppUpdates,
+                          policy_service_, base::WideToASCII(app_id)));
+  return policy_status.has_value()
+             ? PolicyStatusValueImpl::Create(*policy_status, value)
              : E_FAIL;
 }
 
@@ -1051,11 +1083,11 @@
     BSTR app_id,
     IPolicyStatusValue** value) {
   DCHECK(value);
-
-  PolicyStatus<std::string> policy_status;
-  return policy_service_->GetTargetVersionPrefix(base::WideToASCII(app_id),
-                                                 &policy_status, nullptr)
-             ? PolicyStatusValueImpl::Create(policy_status, value)
+  auto policy_status = PolicyStatusResult<std::string>::Get(
+      base::BindRepeating(&PolicyService::GetTargetVersionPrefix,
+                          policy_service_, base::WideToASCII(app_id)));
+  return policy_status.has_value()
+             ? PolicyStatusValueImpl::Create(*policy_status, value)
              : E_FAIL;
 }
 
@@ -1063,22 +1095,22 @@
     BSTR app_id,
     IPolicyStatusValue** value) {
   DCHECK(value);
-
-  PolicyStatus<bool> policy_status;
-  return policy_service_->IsRollbackToTargetVersionAllowed(
-             base::WideToASCII(app_id), &policy_status, nullptr)
-             ? PolicyStatusValueImpl::Create(policy_status, value)
+  auto policy_status = PolicyStatusResult<bool>::Get(
+      base::BindRepeating(&PolicyService::IsRollbackToTargetVersionAllowed,
+                          policy_service_, base::WideToASCII(app_id)));
+  return policy_status.has_value()
+             ? PolicyStatusValueImpl::Create(*policy_status, value)
              : E_FAIL;
 }
 
 STDMETHODIMP PolicyStatusImpl::get_targetChannel(BSTR app_id,
                                                  IPolicyStatusValue** value) {
   DCHECK(value);
-
-  PolicyStatus<std::string> policy_status;
-  return policy_service_->GetTargetChannel(base::WideToASCII(app_id),
-                                           &policy_status, nullptr)
-             ? PolicyStatusValueImpl::Create(policy_status, value)
+  auto policy_status = PolicyStatusResult<std::string>::Get(
+      base::BindRepeating(&PolicyService::GetTargetChannel, policy_service_,
+                          base::WideToASCII(app_id)));
+  return policy_status.has_value()
+             ? PolicyStatusValueImpl::Create(*policy_status, value)
              : E_FAIL;
 }
 
@@ -1086,10 +1118,11 @@
     VARIANT_BOOL is_machine,
     IPolicyStatusValue** value) {
   DCHECK(value);
-
-  PolicyStatus<std::vector<std::string>> policy_status;
-  return policy_service_->GetForceInstallApps(&policy_status, nullptr)
-             ? PolicyStatusValueImpl::Create(policy_status, value)
+  auto policy_status =
+      PolicyStatusResult<std::vector<std::string>>::Get(base::BindRepeating(
+          &PolicyService::GetForceInstallApps, policy_service_));
+  return policy_status.has_value()
+             ? PolicyStatusValueImpl::Create(*policy_status, value)
              : E_FAIL;
 }
 
diff --git a/chrome/updater/configurator.h b/chrome/updater/configurator.h
index 443498af..6896ea1 100644
--- a/chrome/updater/configurator.h
+++ b/chrome/updater/configurator.h
@@ -39,6 +39,8 @@
 class PolicyService;
 class UpdaterPrefs;
 
+// This class is free-threaded. Its instance is shared by multiple sequences and
+// it can't be mutated.
 class Configurator : public update_client::Configurator {
  public:
   Configurator(scoped_refptr<UpdaterPrefs> prefs,
@@ -82,6 +84,8 @@
   crx_file::VerifierFormat GetCrxVerifierFormat() const;
 
   // This reloads the policy managers.
+  // TODO(crbug.com/1353925) - eliminate this function because the instance
+  // of the `Configurator` can't be mutated.
   void ResetPolicyService();
 
  private:
diff --git a/chrome/updater/win/win_util.h b/chrome/updater/win/win_util.h
index 3018626..2221c5a 100644
--- a/chrome/updater/win/win_util.h
+++ b/chrome/updater/win/win_util.h
@@ -81,19 +81,6 @@
 // NO_ERROR to E_FAIL.
 HRESULT HRESULTFromLastError();
 
-// Returns an HRESULT with a custom facility code representing an updater error.
-// The updater error should be a small positive or a small negative 16-bit
-// integral value.
-template <typename Error>
-HRESULT HRESULTFromUpdaterError(Error error) {
-  constexpr ULONG kSeverityError = 0x80000000;
-  constexpr ULONG kCustomerBit = 0x20000000;
-  constexpr ULONG kFacilityOmaha = 67;
-  return static_cast<HRESULT>(kSeverityError | kCustomerBit |
-                              (kFacilityOmaha << 16) |
-                              static_cast<ULONG>(error));
-}
-
 // Checks whether a process is running with the image |executable|. Returns true
 // if a process is found.
 bool IsProcessRunning(const wchar_t* executable);
diff --git a/chrome/updater/win/win_util_unittest.cc b/chrome/updater/win/win_util_unittest.cc
index 6a2a503..4788f79 100644
--- a/chrome/updater/win/win_util_unittest.cc
+++ b/chrome/updater/win/win_util_unittest.cc
@@ -29,23 +29,6 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace updater {
-namespace {
-
-// Converts an unsigned long integral to an HRESULT to avoid the
-// warning about a narrowing conversion.
-HRESULT MakeHRESULT(unsigned long x) {
-  return static_cast<HRESULT>(x);
-}
-
-}  // namespace
-
-TEST(WinUtil, HRESULTFromUpdaterError) {
-  EXPECT_EQ(HRESULTFromUpdaterError(0), MakeHRESULT(0xa0430000L));
-  EXPECT_EQ(HRESULTFromUpdaterError(ERROR_ACCESS_DENIED),
-            MakeHRESULT(0xa0430005));
-  EXPECT_EQ(HRESULTFromUpdaterError(-1), -1);
-  EXPECT_EQ(HRESULTFromUpdaterError(-10), -10);
-}
 
 TEST(WinUtil, GetDownloadProgress) {
   EXPECT_EQ(GetDownloadProgress(0, 50), 0);
diff --git a/chromeos/ash/components/network/onc/onc_merger.cc b/chromeos/ash/components/network/onc/onc_merger.cc
index a4c2795d..029d6225 100644
--- a/chromeos/ash/components/network/onc/onc_merger.cc
+++ b/chromeos/ash/components/network/onc/onc_merger.cc
@@ -9,12 +9,15 @@
 #include <utility>
 #include <vector>
 
+#include "base/check.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/notreached.h"
 #include "base/values.h"
 #include "chromeos/ash/components/network/policy_util.h"
 #include "chromeos/components/onc/onc_signature.h"
 #include "components/onc/onc_constants.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace ash::onc {
 namespace {
@@ -57,6 +60,17 @@
   }
 }
 
+// Returns the default value for ONC field specified by |field|.
+base::Value GetDefaultValue(const OncFieldSignature* field) {
+  if (field->default_value_setter)
+    return field->default_value_setter();
+
+  DCHECK(field->value_signature);
+
+  // Return the default base::Value for the field type.
+  return base::Value(field->value_signature->onc_type);
+}
+
 // Returns a dictionary which contains |true| at each path that is editable by
 // the user. No other fields are set.
 base::Value GetEditableFlags(const base::Value& policy) {
@@ -427,13 +441,32 @@
       augmented_value.SetKey(::onc::kAugmentationSharedSetting,
                              values.shared_setting->Clone());
     }
+
+    base::Value::Dict& augmented_value_dict = augmented_value.GetDict();
+
     if (HasUserPolicy() && values.user_editable) {
       augmented_value.SetKey(::onc::kAugmentationUserEditable,
                              base::Value(true));
+
+      // Ensure that a property that is editable and has a user policy (which
+      // indicates that the policy recommends a value) always has the
+      // appropriate default user policy value provided.
+      if (!augmented_value_dict.Find(::onc::kAugmentationUserPolicy)) {
+        augmented_value_dict.Set(::onc::kAugmentationUserPolicy,
+                                 GetDefaultValue(field));
+      }
     }
     if (HasDevicePolicy() && values.device_editable) {
       augmented_value.SetKey(::onc::kAugmentationDeviceEditable,
                              base::Value(true));
+
+      // Ensure that a property that is editable and has a device policy (which
+      // indicates that the policy recommends a value) always has the
+      // appropriate default device policy value provided.
+      if (!augmented_value_dict.Find(::onc::kAugmentationDevicePolicy)) {
+        augmented_value_dict.Set(::onc::kAugmentationDevicePolicy,
+                                 GetDefaultValue(field));
+      }
     }
     if (!augmented_value.DictEmpty())
       return augmented_value;
diff --git a/chromeos/components/test/data/onc/augmented_merge.json b/chromeos/components/test/data/onc/augmented_merge.json
index 1c4f07d9..5bf82f3 100644
--- a/chromeos/components/test/data/onc/augmented_merge.json
+++ b/chromeos/components/test/data/onc/augmented_merge.json
@@ -20,6 +20,12 @@
      "Effective": "UserPolicy",
      "UserSetting": "Static"
    },
+   "NameServersConfigType": {
+      "DeviceEditable": true,
+      "DevicePolicy": "DHCP",
+      "UserEditable": true,
+      "UserPolicy": "DHCP"
+   },
    "StaticIPConfig": {
       "IPAddress": {
          "DevicePolicy": "127.0.0.1",
@@ -27,6 +33,10 @@
          "UserPolicy": "127.0.0.1",
          "UserSetting": "1.2.3.4"
       },
+      "NameServers": {
+         "Effective": "UserPolicy",
+         "UserPolicy": [  ]
+      },
       "RoutingPrefix": {
          "Effective": "UserPolicy",
          "UserPolicy": 32
@@ -84,7 +94,9 @@
          "ClientCertPattern": {
             "EnrollmentURI": {
                "DeviceEditable": true,
-               "UserEditable": true
+               "DevicePolicy": [  ],
+               "UserEditable": true,
+               "UserPolicy": [  ]
             },
             "IssuerCARef": {
                "DeviceEditable": true,
@@ -101,8 +113,10 @@
          },
          "Password": {
             "DeviceEditable": true,
+            "DevicePolicy": "",
             "Effective": "UserSetting",
             "UserEditable": true,
+            "UserPolicy": "",
             "UserSetting": "users password"
          },
          "Port": {
diff --git a/chromeos/components/test/data/onc/device_policy.onc b/chromeos/components/test/data/onc/device_policy.onc
index 201a2c78..6365d45 100644
--- a/chromeos/components/test/data/onc/device_policy.onc
+++ b/chromeos/components/test/data/onc/device_policy.onc
@@ -23,5 +23,10 @@
     "IPsec": {
       "PSK": "sharedkey"
     }
-  }
+  },
+  // We explicitly do not provide a policy value for this property, but still
+  // consider it recommended, to verify that we still provide the correct
+  // default (which is different than the default value for a string) in the
+  // final augmented ONC.
+  "Recommended": [ "NameServersConfigType" ]
 }
diff --git a/chromeos/components/test/data/onc/managed_vpn.onc b/chromeos/components/test/data/onc/managed_vpn.onc
index d90338a..fe074e3 100644
--- a/chromeos/components/test/data/onc/managed_vpn.onc
+++ b/chromeos/components/test/data/onc/managed_vpn.onc
@@ -4,11 +4,12 @@
   "StaticIPConfig": {
     "Type": "IPv4",
     "IPAddress": "127.0.0.1",
+    "NameServers": [  ],
     "RoutingPrefix": 32
   },
   "VPN": {
     "Host": "policys host",
-    "Recommended": ["Host"],
+    "Recommended": [ "Host" ],
     "Type": "OpenVPN",
     "OpenVPN": {
       "Port": 1194,
@@ -19,12 +20,17 @@
         "IssuerCARef": [ "openvpn-test-ca" ],
         "Recommended": [ "EnrollmentURI", "IssuerCARef" ]
       },
-      "ServerCARefs": ["ref1", "ref2"]
+      "ServerCARefs": [ "ref1", "ref2" ]
     },
     "IPsec": {
       "AuthenticationType": "PSK",
       "PSK": "sharedkey",
       "IKEVersion": 1
     }
-  }
+  },
+  // We explicitly do not provide a policy value for this property, but still
+  // consider it recommended, to verify that we still provide the correct
+  // default (which is different than the default value for a string) in the
+  // final augmented ONC.
+  "Recommended": [ "NameServersConfigType" ]
 }
diff --git a/chromeos/components/test/data/onc/managed_vpn_without_recommended.onc b/chromeos/components/test/data/onc/managed_vpn_without_recommended.onc
index eaa6795d..83c57a9 100644
--- a/chromeos/components/test/data/onc/managed_vpn_without_recommended.onc
+++ b/chromeos/components/test/data/onc/managed_vpn_without_recommended.onc
@@ -4,6 +4,7 @@
   "StaticIPConfig": {
     "Type": "IPv4",
     "IPAddress": "127.0.0.1",
+    "NameServers": [  ],
     "RoutingPrefix": 32
   },
   "VPN": {
diff --git a/components/assist_ranker/OWNERS b/components/assist_ranker/OWNERS
index e6ccec7b..e263b86 100644
--- a/components/assist_ranker/OWNERS
+++ b/components/assist_ranker/OWNERS
@@ -1,2 +1 @@
 charleszhao@chromium.org
-jiameng@chromium.org
diff --git a/components/autofill_payments_strings.grdp b/components/autofill_payments_strings.grdp
index 651d8ed1..9e6b90dd 100644
--- a/components/autofill_payments_strings.grdp
+++ b/components/autofill_payments_strings.grdp
@@ -357,6 +357,12 @@
     <message name="IDS_AUTOFILL_CARD_UNMASK_PROMPT_INSTRUCTIONS_EXPIRED_LOCAL_CARD" desc="Text explaining what the user should do in the card unmasking dialog to update an expired card.  Appears specifically for local cards already stored on the device.">
       Enter the expiration date and CVC for <ph name="CREDIT_CARD">$1<ex>Visa - 5679</ex></ph> to update your card details. Once you confirm, your card details will be shared with this site.
     </message>
+    <message name="IDS_AUTOFILL_CARD_UNMASK_PROMPT_CVC_FIELD_TITLE" desc="The name of the field for credit card verification code in the card unmasking dialog. The text field where this is presented can be very narrow, so please prefer to translate this to the most common abbreviated form. [CHAR_LIMIT=4]">
+      CVC
+    </message>
+    <message name="IDS_AUTOFILL_CARD_UNMASK_PROMPT_UPDATE_CARD_MESSAGE_LINK" desc="Text explaining the user they can update their credit card expiration date if they received a new card after the old one expired. The text also contains a link that when tapped displays the form to update the expiration date.">
+      New card? <ph name="BEGIN_LINK">BEGIN_LINK</ph>Enter Card Details<ph name="END_LINK">END_LINK</ph>
+    </message>
   </if>
   <if expr="is_ios">
     <if expr="_google_chrome">
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_CARD_UNMASK_PROMPT_CVC_FIELD_TITLE.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_CARD_UNMASK_PROMPT_CVC_FIELD_TITLE.png.sha1
new file mode 100644
index 0000000..b1a45c1
--- /dev/null
+++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_CARD_UNMASK_PROMPT_CVC_FIELD_TITLE.png.sha1
@@ -0,0 +1 @@
+4a9f1eca313f5578e0398674b34741d403a4d10d
\ No newline at end of file
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_CARD_UNMASK_PROMPT_UPDATE_CARD_MESSAGE_LINK.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_CARD_UNMASK_PROMPT_UPDATE_CARD_MESSAGE_LINK.png.sha1
new file mode 100644
index 0000000..21bd40c
--- /dev/null
+++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_CARD_UNMASK_PROMPT_UPDATE_CARD_MESSAGE_LINK.png.sha1
@@ -0,0 +1 @@
+03928bd33b856d43addcff0f9915ff6a7c5454b6
\ No newline at end of file
diff --git a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java
index b12ebca..aca1788 100644
--- a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java
+++ b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java
@@ -63,8 +63,9 @@
         FeatureConstants.READ_LATER_APP_MENU_BOOKMARK_THIS_PAGE_FEATURE,
         FeatureConstants.READ_LATER_APP_MENU_BOOKMARKS_FEATURE,
         FeatureConstants.READ_LATER_BOTTOM_SHEET_FEATURE,
-        FeatureConstants.READ_LATER_CONTEXT_MENU_FEATURE, FeatureConstants.IPH_MIC_TOOLBAR_FEATURE,
-        FeatureConstants.IPH_SHARE_SCREENSHOT_FEATURE,
+        FeatureConstants.READ_LATER_CONTEXT_MENU_FEATURE,
+        FeatureConstants.REQUEST_DESKTOP_SITE_APP_MENU_FEATURE,
+        FeatureConstants.IPH_MIC_TOOLBAR_FEATURE, FeatureConstants.IPH_SHARE_SCREENSHOT_FEATURE,
         FeatureConstants.IPH_SHARING_HUB_LINK_TOGGLE_FEATURE,
         FeatureConstants.IPH_WEB_FEED_FOLLOW_FEATURE,
         FeatureConstants.IPH_WEB_FEED_POST_FOLLOW_DIALOG_FEATURE,
@@ -118,6 +119,7 @@
     String READ_LATER_APP_MENU_BOOKMARK_THIS_PAGE_FEATURE = "IPH_ReadLaterAppMenuBookmarkThisPage";
     String READ_LATER_APP_MENU_BOOKMARKS_FEATURE = "IPH_ReadLaterAppMenuBookmarks";
     String READ_LATER_BOTTOM_SHEET_FEATURE = "IPH_ReadLaterBottomSheet";
+    String REQUEST_DESKTOP_SITE_APP_MENU_FEATURE = "IPH_RequestDesktopSiteAppMenu";
 
     /**
      * An IPH feature indicating to users that there are settings for downloads and they are
diff --git a/components/feature_engagement/public/feature_configurations.cc b/components/feature_engagement/public/feature_configurations.cc
index 1769f91..ab84cf33 100644
--- a/components/feature_engagement/public/feature_configurations.cc
+++ b/components/feature_engagement/public/feature_configurations.cc
@@ -884,6 +884,23 @@
                                Comparator(EQUAL, 0), 60, 60);
     return config;
   }
+
+  if (kIPHRequestDesktopSiteAppMenuFeature.name == feature->name) {
+    // A config that allows the RDS site-level setting user education prompt to
+    // be shown:
+    // * If the user has used the RDS (tab-level) setting on the app menu at
+    // least once.
+    // * If the prompt has never been shown before.
+    absl::optional<FeatureConfig> config = FeatureConfig();
+    config->valid = true;
+    config->availability = Comparator(ANY, 0);
+    config->session_rate = Comparator(ANY, 0);
+    config->used = EventConfig("app_menu_desktop_site_for_tab_clicked",
+                               Comparator(GREATER_THAN_OR_EQUAL, 1), 180, 180);
+    config->trigger = EventConfig("request_desktop_site_app_menu_iph_trigger",
+                                  Comparator(EQUAL, 0), 180, 180);
+    return config;
+  }
 #endif  // BUILDFLAG(IS_ANDROID)
 
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || \
diff --git a/components/feature_engagement/public/feature_constants.cc b/components/feature_engagement/public/feature_constants.cc
index a4d93e4..e31968e 100644
--- a/components/feature_engagement/public/feature_constants.cc
+++ b/components/feature_engagement/public/feature_constants.cc
@@ -130,6 +130,8 @@
     "IPH_ReadLaterAppMenuBookmarks", base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kIPHReadLaterBottomSheetFeature{
     "IPH_ReadLaterBottomSheet", base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kIPHRequestDesktopSiteAppMenuFeature{
+    "IPH_RequestDesktopSiteAppMenu", base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kIPHShoppingListSaveFlowFeature{
     "IPH_ShoppingListSaveFlow", base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kIPHEphemeralTabFeature{"IPH_EphemeralTab",
diff --git a/components/feature_engagement/public/feature_constants.h b/components/feature_engagement/public/feature_constants.h
index ac36621..1e177c4 100644
--- a/components/feature_engagement/public/feature_constants.h
+++ b/components/feature_engagement/public/feature_constants.h
@@ -131,6 +131,7 @@
 extern const base::Feature kIPHReadLaterAppMenuBookmarkThisPageFeature;
 extern const base::Feature kIPHReadLaterAppMenuBookmarksFeature;
 extern const base::Feature kIPHReadLaterBottomSheetFeature;
+extern const base::Feature kIPHRequestDesktopSiteAppMenuFeature;
 extern const base::Feature kIPHShoppingListMenuItemFeature;
 extern const base::Feature kIPHShoppingListSaveFlowFeature;
 extern const base::Feature kIPHTabGroupsQuicklyComparePagesFeature;
diff --git a/components/feature_engagement/public/feature_list.cc b/components/feature_engagement/public/feature_list.cc
index 3561886..52f48cbf 100644
--- a/components/feature_engagement/public/feature_list.cc
+++ b/components/feature_engagement/public/feature_list.cc
@@ -76,6 +76,7 @@
     &kIPHReadLaterAppMenuBookmarkThisPageFeature,
     &kIPHReadLaterAppMenuBookmarksFeature,
     &kIPHReadLaterBottomSheetFeature,
+    &kIPHRequestDesktopSiteAppMenuFeature,
     &kIPHShoppingListMenuItemFeature,
     &kIPHShoppingListSaveFlowFeature,
     &kIPHTabGroupsQuicklyComparePagesFeature,
diff --git a/components/feature_engagement/public/feature_list.h b/components/feature_engagement/public/feature_list.h
index 209361e8..0b98431 100644
--- a/components/feature_engagement/public/feature_list.h
+++ b/components/feature_engagement/public/feature_list.h
@@ -148,6 +148,8 @@
                        "IPH_ReadLaterAppMenuBookmarks");
 DEFINE_VARIATION_PARAM(kIPHReadLaterBottomSheetFeature,
                        "IPH_ReadLaterBottomSheet");
+DEFINE_VARIATION_PARAM(kIPHRequestDesktopSiteAppMenuFeature,
+                       "IPH_RequestDesktopSiteAppMenu");
 DEFINE_VARIATION_PARAM(kIPHShoppingListMenuItemFeature,
                        "IPH_ShoppingListMenuItem");
 DEFINE_VARIATION_PARAM(kIPHShoppingListSaveFlowFeature,
@@ -310,6 +312,7 @@
         VARIATION_ENTRY(kIPHReadLaterAppMenuBookmarkThisPageFeature),
         VARIATION_ENTRY(kIPHReadLaterAppMenuBookmarksFeature),
         VARIATION_ENTRY(kIPHReadLaterBottomSheetFeature),
+        VARIATION_ENTRY(kIPHRequestDesktopSiteAppMenuFeature),
         VARIATION_ENTRY(kIPHShoppingListMenuItemFeature),
         VARIATION_ENTRY(kIPHShoppingListSaveFlowFeature),
         VARIATION_ENTRY(kIPHTabGroupsQuicklyComparePagesFeature),
diff --git a/components/history/core/browser/history_types.h b/components/history/core/browser/history_types.h
index 3ce2d10..bacb75bf 100644
--- a/components/history/core/browser/history_types.h
+++ b/components/history/core/browser/history_types.h
@@ -816,6 +816,19 @@
   VisitSource source;
 };
 
+// `ClusterVisit` tracks duplicate visits to propagate deletes. Only the
+// duplicate's URL and visit time are needed to delete it, hence doesn't contain
+// all the information contained in e.g. `ClusterVisit`.
+struct DuplicateClusterVisit {
+  VisitID visit_id;
+
+  // Not persisted; derived from visit_id.
+  GURL url;
+
+  // Not persisted; derived from visit_id.
+  base::Time visit_time;
+};
+
 // An `AnnotatedVisit` associated with some other metadata from clustering.
 struct ClusterVisit {
   ClusterVisit();
@@ -838,9 +851,9 @@
 
   // A list of visits that have been de-duplicated into this visit. The parent
   // visit is considered the best visit among all the duplicates, and the worse
-  // visits are now contained here.
-  // TODO(manukh): Persist to db.
-  std::vector<ClusterVisit> duplicate_visits;
+  // visits are now contained here. Used for deletions; when the parent visit is
+  // deleted, the duplicate visits are deleted as well.
+  std::vector<DuplicateClusterVisit> duplicate_visits;
 
   // The site engagement score of the URL associated with this visit. This
   // should not be used by the UI.
diff --git a/components/history_clusters/core/clustering_test_utils.cc b/components/history_clusters/core/clustering_test_utils.cc
index 0e7da82..d9aa050 100644
--- a/components/history_clusters/core/clustering_test_utils.cc
+++ b/components/history_clusters/core/clustering_test_utils.cc
@@ -4,18 +4,27 @@
 
 #include "components/history_clusters/core/clustering_test_utils.h"
 
+#include "base/ranges/algorithm.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/history_clusters/core/history_clusters_util.h"
 
-namespace history_clusters {
-namespace testing {
+namespace history_clusters::testing {
 
-VisitResult::VisitResult(int visit_id,
-                         float score,
-                         const std::vector<VisitResult>& duplicate_visits,
-                         std::u16string search_terms)
+std::vector<history::VisitID> ExtractDuplicateVisitIds(
+    std::vector<history::DuplicateClusterVisit> duplicate_visits) {
+  std::vector<history::VisitID> ids;
+  base::ranges::transform(duplicate_visits, std::back_inserter(ids),
+                          [](const auto& visit) { return visit.visit_id; });
+  return ids;
+}
+
+VisitResult::VisitResult(
+    int visit_id,
+    float score,
+    const std::vector<history::DuplicateClusterVisit>& duplicate_visits,
+    std::u16string search_terms)
     : visit_id_(visit_id),
       score_(score),
       duplicate_visits_(duplicate_visits),
@@ -23,33 +32,24 @@
 VisitResult::VisitResult(const history::ClusterVisit& visit)
     : visit_id_(visit.annotated_visit.visit_row.visit_id),
       score_(visit.score),
-      search_terms_(visit.annotated_visit.content_annotations.search_terms) {
-  for (const auto& duplicate : visit.duplicate_visits) {
-    duplicate_visits_.emplace_back(duplicate);
-  }
-}
+      duplicate_visits_(visit.duplicate_visits),
+      search_terms_(visit.annotated_visit.content_annotations.search_terms) {}
 
 VisitResult::VisitResult(const VisitResult& other) = default;
 VisitResult::~VisitResult() = default;
 
 std::string VisitResult::ToString() const {
-  std::string duplicate_visits_string = "{}";
-  if (!duplicate_visits_.empty()) {
-    std::vector<std::string> duplicate_visits_strings;
-    for (const auto& dup_visit : duplicate_visits_) {
-      // In case of multiple layers of nesting, indent inner layers a bit more.
-      std::string dup_visit_string = dup_visit.ToString();
-      base::ReplaceChars(dup_visit_string, "\n", "\n  ", &dup_visit_string);
-      duplicate_visits_strings.push_back(dup_visit_string);
-    }
-    duplicate_visits_string = base::StringPrintf(
-        "{\n  %s\n}",
-        base::JoinString(duplicate_visits_strings, "\n  ").c_str());
-  }
+  std::vector<std::string> duplicate_visits_strings;
+  base::ranges::transform(duplicate_visits_,
+                          std::back_inserter(duplicate_visits_strings),
+                          [&](const auto& duplicate_visit) {
+                            return std::to_string(duplicate_visit.visit_id);
+                          });
   return base::StringPrintf(
-      "VisitResult(visit_id=%d, score=%f, duplicate_visits=%s, "
+      "VisitResult(visit_id=%d, score=%f, duplicate_visits=[%s], "
       "search_terms=%s)",
-      visit_id_, score_, duplicate_visits_string.c_str(),
+      visit_id_, score_,
+      base::JoinString(duplicate_visits_strings, ",  ").c_str(),
       base::UTF16ToUTF8(search_terms_).c_str());
 }
 
@@ -62,10 +62,24 @@
   constexpr const double kScoreTolerance = 1e-6;
   return visit_id_ == rhs.visit_id_ &&
          abs(score_ - rhs.score_) <= kScoreTolerance &&
-         duplicate_visits_ == rhs.duplicate_visits_ &&
+         ExtractDuplicateVisitIds(duplicate_visits_) ==
+             ExtractDuplicateVisitIds(rhs.duplicate_visits_) &&
          search_terms_ == rhs.search_terms_;
 }
 
+std::vector<std::vector<testing::VisitResult>> ToVisitResults(
+    const std::vector<history::Cluster>& clusters) {
+  std::vector<std::vector<testing::VisitResult>> clusters_results;
+  for (const auto& cluster : clusters) {
+    std::vector<testing::VisitResult> visit_results;
+    for (const auto& visit : cluster.visits) {
+      visit_results.push_back(testing::VisitResult(visit));
+    }
+    clusters_results.push_back(visit_results);
+  }
+  return clusters_results;
+}
+
 history::AnnotatedVisit CreateDefaultAnnotatedVisit(int visit_id,
                                                     const GURL& url,
                                                     base::Time visit_time) {
@@ -93,18 +107,11 @@
   return cluster_visit;
 }
 
-std::vector<std::vector<testing::VisitResult>> ToVisitResults(
-    const std::vector<history::Cluster>& clusters) {
-  std::vector<std::vector<testing::VisitResult>> clusters_results;
-  for (const auto& cluster : clusters) {
-    std::vector<testing::VisitResult> visit_results;
-    for (const auto& visit : cluster.visits) {
-      visit_results.push_back(testing::VisitResult(visit));
-    }
-    clusters_results.push_back(visit_results);
-  }
-  return clusters_results;
+history::DuplicateClusterVisit ClusterVisitToDuplicateClusterVisit(
+    history::ClusterVisit cluster_visit) {
+  return {cluster_visit.annotated_visit.visit_row.visit_id,
+          cluster_visit.annotated_visit.url_row.url(),
+          cluster_visit.annotated_visit.visit_row.visit_time};
 }
 
-}  // namespace testing
-}  // namespace history_clusters
+}  // namespace history_clusters::testing
diff --git a/components/history_clusters/core/clustering_test_utils.h b/components/history_clusters/core/clustering_test_utils.h
index 87c95f10..5b634e7 100644
--- a/components/history_clusters/core/clustering_test_utils.h
+++ b/components/history_clusters/core/clustering_test_utils.h
@@ -11,17 +11,17 @@
 #include "base/time/time.h"
 #include "components/history/core/browser/history_types.h"
 
-namespace history_clusters {
-namespace testing {
+namespace history_clusters::testing {
 
 // A helper object that contains the elements to validate that
 // the result visits of clusters are correct.
 class VisitResult {
  public:
-  VisitResult(int visit_id,
-              float score,
-              const std::vector<VisitResult>& duplicate_visits = {},
-              std::u16string search_terms = u"");
+  VisitResult(
+      int visit_id,
+      float score,
+      const std::vector<history::DuplicateClusterVisit>& duplicate_visits = {},
+      std::u16string search_terms = u"");
   explicit VisitResult(const history::ClusterVisit& visit);
   VisitResult(const VisitResult& other);
   ~VisitResult();
@@ -35,7 +35,7 @@
 
   const int visit_id_;
   const float score_;
-  std::vector<VisitResult> duplicate_visits_;
+  std::vector<history::DuplicateClusterVisit> duplicate_visits_;
   const std::u16string search_terms_;
 };
 
@@ -59,7 +59,9 @@
     absl::optional<GURL> normalized_url = absl::nullopt,
     float score = 1.0);
 
-}  // namespace testing
-}  // namespace history_clusters
+history::DuplicateClusterVisit ClusterVisitToDuplicateClusterVisit(
+    history::ClusterVisit cluster_visit);
+
+}  // namespace history_clusters::testing
 
 #endif  // COMPONENTS_HISTORY_CLUSTERS_CORE_CLUSTERING_TEST_UTILS_H_
diff --git a/components/history_clusters/core/history_clusters_debug_jsons.cc b/components/history_clusters/core/history_clusters_debug_jsons.cc
index e62a88e..54e2b2c 100644
--- a/components/history_clusters/core/history_clusters_debug_jsons.cc
+++ b/components/history_clusters/core/history_clusters_debug_jsons.cc
@@ -106,10 +106,8 @@
       debug_visit.Set("site_engagement_score", visit.engagement_score);
 
       base::Value::List debug_duplicate_visits;
-      for (const auto& duplicate_visit : visit.duplicate_visits) {
-        debug_duplicate_visits.Append(static_cast<int>(
-            duplicate_visit.annotated_visit.visit_row.visit_id));
-      }
+      for (const auto& duplicate_visit : visit.duplicate_visits)
+        debug_duplicate_visits.Append(duplicate_visit.url.spec());
       debug_visit.Set("duplicate_visits", std::move(debug_duplicate_visits));
 
       debug_visits.Append(std::move(debug_visit));
diff --git a/components/history_clusters/core/keyword_cluster_finalizer_unittest.cc b/components/history_clusters/core/keyword_cluster_finalizer_unittest.cc
index 94c6120..3e0e2c7 100644
--- a/components/history_clusters/core/keyword_cluster_finalizer_unittest.cc
+++ b/components/history_clusters/core/keyword_cluster_finalizer_unittest.cc
@@ -72,7 +72,8 @@
 
   history::ClusterVisit visit3 = testing::CreateClusterVisit(
       testing::CreateDefaultAnnotatedVisit(3, GURL("https://baz.com/")));
-  visit3.duplicate_visits.push_back(visit);
+  visit3.duplicate_visits.push_back(
+      testing::ClusterVisitToDuplicateClusterVisit(visit));
   visit3.engagement_score = 1.0;
   visit3.annotated_visit.content_annotations.model_annotations.entities = {
       {"github", 1},
@@ -144,7 +145,8 @@
 
   history::ClusterVisit visit3 = testing::CreateClusterVisit(
       testing::CreateDefaultAnnotatedVisit(2, GURL("https://baz.com/")));
-  visit3.duplicate_visits.push_back(visit);
+  visit3.duplicate_visits.push_back(
+      testing::ClusterVisitToDuplicateClusterVisit(visit));
   visit3.engagement_score = 1.0;
   visit3.annotated_visit.content_annotations.model_annotations.entities = {
       {"github", 1}, {"otherentity", 1}, {"baz", 1}, {"search", 1}};
diff --git a/components/history_clusters/core/label_cluster_finalizer_unittest.cc b/components/history_clusters/core/label_cluster_finalizer_unittest.cc
index 398748fe..1ffa9a09 100644
--- a/components/history_clusters/core/label_cluster_finalizer_unittest.cc
+++ b/components/history_clusters/core/label_cluster_finalizer_unittest.cc
@@ -48,7 +48,8 @@
 
   history::ClusterVisit visit3 = testing::CreateClusterVisit(
       testing::CreateDefaultAnnotatedVisit(3, GURL("https://baz.com/")));
-  visit3.duplicate_visits.push_back(visit);
+  visit3.duplicate_visits.push_back(
+      testing::ClusterVisitToDuplicateClusterVisit(visit));
   visit3.score = 0.8;
   visit3.annotated_visit.content_annotations.model_annotations.entities = {
       {"chosenlabel", 25}, {"someotherentity", 10}};
diff --git a/components/history_clusters/core/metrics_cluster_finalizer_unittest.cc b/components/history_clusters/core/metrics_cluster_finalizer_unittest.cc
index b106162d..873ca3c 100644
--- a/components/history_clusters/core/metrics_cluster_finalizer_unittest.cc
+++ b/components/history_clusters/core/metrics_cluster_finalizer_unittest.cc
@@ -41,7 +41,8 @@
 
   history::ClusterVisit visit2 = testing::CreateClusterVisit(
       testing::CreateDefaultAnnotatedVisit(2, GURL("https://bar.com/")));
-  visit2.duplicate_visits.push_back(visit);
+  visit2.duplicate_visits.push_back(
+      testing::ClusterVisitToDuplicateClusterVisit(visit));
   visit2.engagement_score = 25.0;
   visit2.annotated_visit.content_annotations.search_terms = u"bar";
 
@@ -67,7 +68,8 @@
 
   history::ClusterVisit visit2 = testing::CreateClusterVisit(
       testing::CreateDefaultAnnotatedVisit(2, GURL("https://bar.com/")));
-  visit2.duplicate_visits.push_back(visit);
+  visit2.duplicate_visits.push_back(
+      testing::ClusterVisitToDuplicateClusterVisit(visit));
   visit2.engagement_score = 25.0;
 
   history::Cluster cluster;
diff --git a/components/history_clusters/core/noisy_cluster_finalizer.cc b/components/history_clusters/core/noisy_cluster_finalizer.cc
index 2f6dc0f..710c0e08 100644
--- a/components/history_clusters/core/noisy_cluster_finalizer.cc
+++ b/components/history_clusters/core/noisy_cluster_finalizer.cc
@@ -29,7 +29,7 @@
   }
 
   // If we check all the visits in the cluster and all have high engagement
-  // scores, then its probably not interesting so we can hide it.
+  // scores, then it's probably not interesting so we can hide it.
   cluster.should_show_on_prominent_ui_surfaces = false;
   metrics_recorder.set_was_filtered(true);
 }
diff --git a/components/history_clusters/core/noisy_cluster_finalizer_unittest.cc b/components/history_clusters/core/noisy_cluster_finalizer_unittest.cc
index 3620a53..a0497eac 100644
--- a/components/history_clusters/core/noisy_cluster_finalizer_unittest.cc
+++ b/components/history_clusters/core/noisy_cluster_finalizer_unittest.cc
@@ -45,7 +45,8 @@
 
   history::ClusterVisit visit2 = testing::CreateClusterVisit(
       testing::CreateDefaultAnnotatedVisit(2, GURL("https://bar.com/")));
-  visit2.duplicate_visits.push_back(visit);
+  visit2.duplicate_visits.push_back(
+      testing::ClusterVisitToDuplicateClusterVisit(visit));
   visit2.engagement_score = 25.0;
 
   history::Cluster cluster;
@@ -62,7 +63,8 @@
 
   history::ClusterVisit visit2 = testing::CreateClusterVisit(
       testing::CreateDefaultAnnotatedVisit(2, GURL("https://bar.com/")));
-  visit2.duplicate_visits.push_back(visit);
+  visit2.duplicate_visits.push_back(
+      testing::ClusterVisitToDuplicateClusterVisit(visit));
   visit2.engagement_score = 25.0;
 
   history::Cluster cluster;
@@ -85,7 +87,8 @@
 
   history::ClusterVisit visit3 = testing::CreateClusterVisit(
       testing::CreateDefaultAnnotatedVisit(3, GURL("https://foo.com/")));
-  visit3.duplicate_visits.push_back(visit);
+  visit3.duplicate_visits.push_back(
+      testing::ClusterVisitToDuplicateClusterVisit(visit));
   visit3.engagement_score = 5.0;
 
   history::Cluster cluster;
diff --git a/components/history_clusters/core/on_device_clustering_backend_unittest.cc b/components/history_clusters/core/on_device_clustering_backend_unittest.cc
index 688b472..fc078b4 100644
--- a/components/history_clusters/core/on_device_clustering_backend_unittest.cc
+++ b/components/history_clusters/core/on_device_clustering_backend_unittest.cc
@@ -291,7 +291,7 @@
       ClusterVisits(ClusteringRequestSource::kJourneysPage, visits);
   EXPECT_THAT(testing::ToVisitResults(result_clusters),
               ElementsAre(ElementsAre(testing::VisitResult(
-                  2, 1.0, {testing::VisitResult(1, 0.0)}))));
+                  2, 1.0, {history::DuplicateClusterVisit{1}}))));
   histogram_tester.ExpectUniqueSample(
       "History.Clusters.Backend.ClusterSize.Min", 1, 1);
   histogram_tester.ExpectUniqueSample(
@@ -318,7 +318,7 @@
       ClusterVisits(ClusteringRequestSource::kJourneysPage, visits);
   EXPECT_THAT(testing::ToVisitResults(result_clusters),
               ElementsAre(ElementsAre(testing::VisitResult(
-                  2, 1.0, {testing::VisitResult(1, 0.0)}))));
+                  2, 1.0, {history::DuplicateClusterVisit{1}}))));
 }
 
 TEST_F(OnDeviceClusteringWithoutContentBackendTest,
@@ -385,7 +385,7 @@
       testing::ToVisitResults(result_clusters),
       ElementsAre(ElementsAre(testing::VisitResult(10, 1.0)),
                   ElementsAre(testing::VisitResult(
-                                  4, 1.0, {testing::VisitResult(1, 0.0)}),
+                                  4, 1.0, {history::DuplicateClusterVisit{1}}),
                               testing::VisitResult(2, 1.0)),
                   ElementsAre(testing::VisitResult(3, 1.0))));
   histogram_tester.ExpectUniqueSample(
@@ -527,7 +527,7 @@
   EXPECT_THAT(
       testing::ToVisitResults(result_clusters),
       ElementsAre(ElementsAre(
-          testing::VisitResult(4, 1.0, {testing::VisitResult(1, 0.0)}),
+          testing::VisitResult(4, 1.0, {history::DuplicateClusterVisit{1}}),
           testing::VisitResult(2, 1.0), testing::VisitResult(10, 0.5))));
 }
 
@@ -577,7 +577,7 @@
       testing::ToVisitResults(result_clusters),
       ElementsAre(ElementsAre(testing::VisitResult(10, 1.0)),
                   ElementsAre(testing::VisitResult(
-                                  4, 1.0, {testing::VisitResult(1, 0.0)}),
+                                  4, 1.0, {history::DuplicateClusterVisit{1}}),
                               testing::VisitResult(2, 1.0))));
   histogram_tester.ExpectUniqueSample(
       "History.Clusters.Backend.ClusterSize.Min", 1, 1);
@@ -704,10 +704,9 @@
       ClusterVisits(ClusteringRequestSource::kJourneysPage, visits);
   EXPECT_THAT(
       testing::ToVisitResults(result_clusters),
-      ElementsAre(
-          ElementsAre(testing::VisitResult(3, 1.0, {}, u"nometadata")),
-          ElementsAre(testing::VisitResult(
-              2, 1.0, {testing::VisitResult(1, 0.0, {}, u"foo")}, u"foo"))));
+      ElementsAre(ElementsAre(testing::VisitResult(3, 1.0, {}, u"nometadata")),
+                  ElementsAre(testing::VisitResult(
+                      2, 1.0, {history::DuplicateClusterVisit{1}}, u"foo"))));
   // Make sure visits are normalized.
   history::Cluster cluster = result_clusters.at(0);
   ASSERT_EQ(cluster.visits.size(), 1u);
@@ -743,14 +742,9 @@
   EXPECT_THAT(better_visit.annotated_visit.content_annotations.model_annotations
                   .visibility_score,
               FloatEq(0.5));
-  // The second visit should have a normalized URL, but be the worse duplicate.
-  EXPECT_EQ(cluster2.visits.at(0).duplicate_visits.at(0).normalized_url,
-            GURL("http://default-engine.com/?q=foo"));
-  EXPECT_THAT(cluster2.visits.at(0)
-                  .duplicate_visits.at(0)
-                  .annotated_visit.content_annotations.model_annotations
-                  .visibility_score,
-              FloatEq(0.5));
+  // The second visit should have a URL.
+  EXPECT_EQ(cluster2.visits.at(0).duplicate_visits.at(0).url,
+            GURL("http://default-engine.com/?q=foo&otherstuff"));
   // Cluster should have 3 keywords.
   EXPECT_THAT(
       cluster2.GetKeywords(),
diff --git a/components/history_clusters/core/on_device_clustering_util.cc b/components/history_clusters/core/on_device_clustering_util.cc
index faf9a8d..f056009 100644
--- a/components/history_clusters/core/on_device_clustering_util.cc
+++ b/components/history_clusters/core/on_device_clustering_util.cc
@@ -76,7 +76,10 @@
       std::max(canonical_visit.annotated_visit.visit_row.visit_time,
                duplicate_visit.annotated_visit.visit_row.visit_time);
 
-  canonical_visit.duplicate_visits.push_back(std::move(duplicate_visit));
+  canonical_visit.duplicate_visits.push_back(
+      {duplicate_visit.annotated_visit.visit_row.visit_id,
+       duplicate_visit.annotated_visit.url_row.url(),
+       duplicate_visit.annotated_visit.visit_row.visit_time});
 }
 
 void SortClusters(std::vector<history::Cluster>* clusters) {
diff --git a/components/history_clusters/core/ranking_cluster_finalizer.cc b/components/history_clusters/core/ranking_cluster_finalizer.cc
index 782f438..b243d994 100644
--- a/components/history_clusters/core/ranking_cluster_finalizer.cc
+++ b/components/history_clusters/core/ranking_cluster_finalizer.cc
@@ -121,16 +121,6 @@
     base::flat_map<history::VisitID, VisitScores>& url_visit_scores) {
   float max_score = -1.0;
   for (history::ClusterVisit& visit : base::Reversed(cluster.visits)) {
-    // Only canonical visits should have scores > 0.0.
-    for (auto& duplicate_visit : visit.duplicate_visits) {
-      // Check that no individual scores have been given a visit that is not
-      // canonical a score.
-      DCHECK(url_visit_scores.find(
-                 duplicate_visit.annotated_visit.visit_row.visit_id) ==
-             url_visit_scores.end());
-      duplicate_visit.score = 0.0;
-    }
-
     // Determine the max score to use for normalizing all the scores.
     auto visit_scores_it =
         url_visit_scores.find(visit.annotated_visit.visit_row.visit_id);
@@ -144,7 +134,7 @@
   if (max_score <= 0.0)
     return;
 
-  // Now normalize the score by `max_score` so they values are all between 0
+  // Now normalize the score by `max_score` so the values are all between 0
   // and 1.
   for (history::ClusterVisit& visit : base::Reversed(cluster.visits)) {
     visit.score = visit.score / max_score;
diff --git a/components/history_clusters/core/ranking_cluster_finalizer_unittest.cc b/components/history_clusters/core/ranking_cluster_finalizer_unittest.cc
index 3af63959..8f21621 100644
--- a/components/history_clusters/core/ranking_cluster_finalizer_unittest.cc
+++ b/components/history_clusters/core/ranking_cluster_finalizer_unittest.cc
@@ -38,14 +38,15 @@
 
   history::ClusterVisit visit2 = testing::CreateClusterVisit(
       testing::CreateDefaultAnnotatedVisit(2, GURL("https://bar.com/")));
-  visit2.duplicate_visits.push_back(visit);
+  visit2.duplicate_visits.push_back(
+      testing::ClusterVisitToDuplicateClusterVisit(visit));
 
   history::Cluster cluster;
   cluster.visits = {visit2};
   FinalizeCluster(cluster);
   EXPECT_THAT(testing::ToVisitResults({cluster}),
               ElementsAre(ElementsAre(testing::VisitResult(
-                  2, 1.0, {testing::VisitResult(1, 0.0)}))));
+                  2, 1.0, {history::DuplicateClusterVisit{1}}))));
 }
 
 TEST_F(RankingClusterFinalizerTest, ScoreTwoVisitsDifferentURLs) {
@@ -73,14 +74,15 @@
   history::ClusterVisit visit2 =
       testing::CreateClusterVisit(testing::CreateDefaultAnnotatedVisit(
           2, GURL("https://example.com/normalized")));
-  visit2.duplicate_visits.push_back(visit);
+  visit2.duplicate_visits.push_back(
+      testing::ClusterVisitToDuplicateClusterVisit(visit));
 
   history::Cluster cluster;
   cluster.visits = {visit2};
   FinalizeCluster(cluster);
   EXPECT_THAT(testing::ToVisitResults({cluster}),
               ElementsAre(ElementsAre(testing::VisitResult(
-                  2, 1.0, {testing::VisitResult(1, 0.0)}))));
+                  2, 1.0, {history::DuplicateClusterVisit{1}}))));
 }
 
 TEST_F(RankingClusterFinalizerTest, ScoreMultipleVisitsDifferentDurations) {
@@ -98,7 +100,8 @@
   history::ClusterVisit visit4 = testing::CreateClusterVisit(
       testing::CreateDefaultAnnotatedVisit(4, GURL("https://github.com/")));
   visit4.annotated_visit.visit_row.visit_duration = base::Seconds(20);
-  visit4.duplicate_visits.push_back(visit);
+  visit4.duplicate_visits.push_back(
+      testing::ClusterVisitToDuplicateClusterVisit(visit));
 
   history::ClusterVisit visit5 =
       testing::CreateClusterVisit(testing::CreateDefaultAnnotatedVisit(
@@ -109,11 +112,12 @@
   history::Cluster cluster;
   cluster.visits = {visit2, visit4, visit5};
   FinalizeCluster(cluster);
-  EXPECT_THAT(testing::ToVisitResults({cluster}),
-              ElementsAre(ElementsAre(
-                  testing::VisitResult(2, 1.0),
-                  testing::VisitResult(4, 1.0, {testing::VisitResult(1, 0.0)}),
-                  testing::VisitResult(10, 0.5))));
+  EXPECT_THAT(
+      testing::ToVisitResults({cluster}),
+      ElementsAre(ElementsAre(
+          testing::VisitResult(2, 1.0),
+          testing::VisitResult(4, 1.0, {history::DuplicateClusterVisit{1}}),
+          testing::VisitResult(10, 0.5))));
 }
 
 TEST_F(RankingClusterFinalizerTest, ScoreTwoVisitsSameURLBookmarked) {
@@ -124,14 +128,15 @@
 
   history::ClusterVisit visit2 = testing::CreateClusterVisit(
       testing::CreateDefaultAnnotatedVisit(2, GURL("https://bar.com/")));
-  visit2.duplicate_visits.push_back(visit);
+  visit2.duplicate_visits.push_back(
+      testing::ClusterVisitToDuplicateClusterVisit(visit));
 
   history::Cluster cluster;
   cluster.visits = {visit2};
   FinalizeCluster(cluster);
   EXPECT_THAT(testing::ToVisitResults({cluster}),
               ElementsAre(ElementsAre(testing::VisitResult(
-                  2, 1.0, {testing::VisitResult(1, 0.0)}))));
+                  2, 1.0, {history::DuplicateClusterVisit{1}}))));
 }
 
 TEST_F(RankingClusterFinalizerTest, ScoreTwoVisitsWithBookmarksAndDuration) {
@@ -219,16 +224,16 @@
       testing::CreateDefaultAnnotatedVisit(
           1, GURL("https://google.com/search?q=whatever#abc")),
       GURL("https://google.com/search?q=whatever"));
-  visit.duplicate_visits = {visit2};
+  visit.duplicate_visits = {
+      testing::ClusterVisitToDuplicateClusterVisit(visit2)};
   visit.annotated_visit.content_annotations.search_terms = u"whatever";
 
   history::Cluster cluster;
   cluster.visits = {visit};
   FinalizeCluster(cluster);
-  EXPECT_THAT(
-      testing::ToVisitResults({cluster}),
-      ElementsAre(ElementsAre(testing::VisitResult(
-          1, 1.0, {testing::VisitResult(2, 0.0, {}, u"bar")}, u"whatever"))));
+  EXPECT_THAT(testing::ToVisitResults({cluster}),
+              ElementsAre(ElementsAre(testing::VisitResult(
+                  1, 1.0, {history::DuplicateClusterVisit{2}}, u"whatever"))));
 }
 
 TEST_F(RankingClusterFinalizerTest, ScoreVisitsOnHasPageTitle) {
diff --git a/components/history_clusters/core/similar_visit_deduper_cluster_finalizer_unittest.cc b/components/history_clusters/core/similar_visit_deduper_cluster_finalizer_unittest.cc
index 9b4dd074..f871082 100644
--- a/components/history_clusters/core/similar_visit_deduper_cluster_finalizer_unittest.cc
+++ b/components/history_clusters/core/similar_visit_deduper_cluster_finalizer_unittest.cc
@@ -52,7 +52,7 @@
   FinalizeCluster(cluster);
   EXPECT_THAT(testing::ToVisitResults({cluster}),
               ElementsAre(ElementsAre(testing::VisitResult(
-                  2, 1.0, {testing::VisitResult(1, 1.0)}))));
+                  2, 1.0, {history::DuplicateClusterVisit{1}}))));
   const auto& actual_canonical_visit = cluster.visits.at(0);
   // Make sure total foreground duration is updated correctly even if some don't
   // have the field populated.
@@ -124,7 +124,7 @@
   FinalizeCluster(cluster);
   EXPECT_THAT(testing::ToVisitResults({cluster}),
               ElementsAre(ElementsAre(testing::VisitResult(
-                  2, 1.0, {testing::VisitResult(1, 1.0)}))));
+                  2, 1.0, {history::DuplicateClusterVisit{1}}))));
   const auto& actual_canonical_visit = cluster.visits.at(0);
   EXPECT_TRUE(actual_canonical_visit.annotated_visit.context_annotations
                   .omnibox_url_copied);
diff --git a/components/history_clusters/core/single_visit_cluster_finalizer_unittest.cc b/components/history_clusters/core/single_visit_cluster_finalizer_unittest.cc
index 9f83fd6..b0c9fa9 100644
--- a/components/history_clusters/core/single_visit_cluster_finalizer_unittest.cc
+++ b/components/history_clusters/core/single_visit_cluster_finalizer_unittest.cc
@@ -77,7 +77,8 @@
       testing::CreateDefaultAnnotatedVisit(1, GURL("https://google.com/")));
   history::ClusterVisit visit2 = testing::CreateClusterVisit(
       testing::CreateDefaultAnnotatedVisit(2, GURL("https://foo.com/")));
-  visit2.duplicate_visits = {visit};
+  visit2.duplicate_visits = {
+      testing::ClusterVisitToDuplicateClusterVisit(visit)};
 
   history::Cluster cluster;
   cluster.visits = {visit2};
diff --git a/components/media_router/browser/android/OWNERS b/components/media_router/browser/android/OWNERS
index 5a2a426..5549f0c8 100644
--- a/components/media_router/browser/android/OWNERS
+++ b/components/media_router/browser/android/OWNERS
@@ -1,5 +1,4 @@
 # primary reviewers
-zqzhang@chromium.org
 tguilbert@chromium.org
 
 # backup reviewers
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc
index 218f6fc..9e8f804 100644
--- a/components/omnibox/browser/omnibox_field_trial.cc
+++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -359,11 +359,13 @@
 }
 
 size_t OmniboxFieldTrial::GetMaxURLMatches() {
-#if !BUILDFLAG(IS_ANDROID)
-  constexpr size_t kDefaultMaxURLMatches = 7;
-#else   // BUILDFLAG(IS_ANDROID)
+#if BUILDFLAG(IS_ANDROID)
   constexpr size_t kDefaultMaxURLMatches = 5;
-#endif  // BUILDFLAG(IS_ANDROID)
+#elif BUILDFLAG(IS_IOS)
+  constexpr size_t kDefaultMaxURLMatches = 6;
+#else
+  constexpr size_t kDefaultMaxURLMatches = 7;
+#endif
   return base::GetFieldTrialParamByFeatureAsInt(
       omnibox::kOmniboxMaxURLMatches,
       OmniboxFieldTrial::kOmniboxMaxURLMatchesParam, kDefaultMaxURLMatches);
diff --git a/components/optimization_guide/core/model_util.cc b/components/optimization_guide/core/model_util.cc
index c0bebd3..47fcb22 100644
--- a/components/optimization_guide/core/model_util.cc
+++ b/components/optimization_guide/core/model_util.cc
@@ -73,6 +73,8 @@
       return "ContextualPageActionPriceTracking";
     case proto::OPTIMIZATION_TARGET_TEXT_CLASSIFIER:
       return "TextClassifier";
+    case proto::OPTIMIZATION_TARGET_SEGMENTATION_SHOPPING_USER:
+      return "SegmentationShoppingUser";
       // Whenever a new value is added, make sure to add it to the OptTarget
       // variant list in
       // //tools/metrics/histograms/metadata/optimization/histograms.xml.
diff --git a/components/optimization_guide/proto/models.proto b/components/optimization_guide/proto/models.proto
index 0a101b2..8f614b2 100644
--- a/components/optimization_guide/proto/models.proto
+++ b/components/optimization_guide/proto/models.proto
@@ -240,6 +240,8 @@
 
 // The scenarios for which the optimization guide has models for.
 enum OptimizationTarget {
+  reserved 20;
+
   OPTIMIZATION_TARGET_UNKNOWN = 0;
   // Should only be applied when the page load is predicted to be painful.
   OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD = 1;
@@ -282,6 +284,8 @@
   OPTIMIZATION_TARGET_CONTEXTUAL_PAGE_ACTION_PRICE_TRACKING = 18;
   // Target for smart text selection and entity extraction.
   OPTIMIZATION_TARGET_TEXT_CLASSIFIER = 19;
+  // Target for segmentation: Determine users who are interested in shopping.
+  OPTIMIZATION_TARGET_SEGMENTATION_SHOPPING_USER = 21;
 }
 
 // The model engine versions that can be used to do model inference.
diff --git a/components/password_manager/core/browser/import/password_importer.cc b/components/password_manager/core/browser/import/password_importer.cc
index c4d7e74d..cdf0262 100644
--- a/components/password_manager/core/browser/import/password_importer.cc
+++ b/components/password_manager/core/browser/import/password_importer.cc
@@ -34,19 +34,19 @@
 
 // Reads and returns a status and the contents of the file at |path| as a
 // optional string. The string will be present if the status is SUCCESS.
-base::expected<std::string, PasswordImporter::Status> ReadFileToString(
+base::expected<std::string, ImportResults::Status> ReadFileToString(
     const base::FilePath& path) {
   int64_t file_size;
 
   if (GetFileSize(path, &file_size)) {
     base::UmaHistogramCounts1M("PasswordManager.ImportFileSize", file_size);
     if (file_size > kMaxFileSizeBytes)
-      return base::unexpected(PasswordImporter::Status::LARGE_FILE);
+      return base::unexpected(ImportResults::Status::MAX_FILE_SIZE);
   }
 
   std::string contents;
   if (!base::ReadFileToString(path, &contents))
-    return base::unexpected(PasswordImporter::Status::IO_ERROR);
+    return base::unexpected(ImportResults::Status::IO_ERROR);
 
   return std::move(contents);
 }
@@ -150,11 +150,18 @@
 
   UMA_HISTOGRAM_COUNTS_1M("PasswordManager.ImportedPasswordsPerUserInCSV",
                           import_results.number_imported);
+  for (const ImportEntry& entry : import_results.failed_imports) {
+    base::UmaHistogramEnumeration("PasswordManager.ImportEntryStatus",
+                                  entry.status);
+  }
 
   base::UmaHistogramLongTimes("PasswordManager.ImportDuration",
                               base::Time::Now() - start_time);
 
   import_results.status = password_manager::ImportResults::Status::SUCCESS;
+  base::UmaHistogramEnumeration("PasswordManager.ImportResultsStatus",
+                                import_results.status);
+
   std::move(import_results_callback).Run(std::move(import_results));
 }
 
@@ -173,19 +180,16 @@
   return parser_;
 }
 
-PasswordImporter::Status PasswordImporter::GetStatus() const {
-  return status_;
-}
-
 void PasswordImporter::ParseCSVPasswordsInSandbox(
     PasswordImporter::CompletionCallback completion,
-    base::expected<std::string, PasswordImporter::Status> result) {
+    base::expected<std::string, ImportResults::Status> result) {
   // Currently, CSV is the only supported format.
   if (!result.has_value()) {
     this->status_ = result.error();
+    base::UmaHistogramEnumeration("PasswordManager.ImportResultsStatus",
+                                  this->status_);
     std::move(completion).Run(nullptr);
   } else {
-    this->status_ = PasswordImporter::Status::SUCCESS;
     GetParser()->ParseCSV(std::move(result.value()), std::move(completion));
   }
 }
@@ -211,18 +215,27 @@
     std::string file_name,
     password_manager::PasswordForm::Store store,
     password_manager::mojom::CSVPasswordSequencePtr seq) {
-  password_manager::ImportResults results;
+  ImportResults results;
   results.file_name = std::move(file_name);
+  results.status = status_;
+
   if (!seq) {
-    results.status = password_manager::ImportResults::Status::BAD_FORMAT;
+    // A nullptr returned by the parser means a bad format.
+    if (results.status == ImportResults::Status::NONE) {
+      results.status = password_manager::ImportResults::Status::BAD_FORMAT;
+      base::UmaHistogramEnumeration("PasswordManager.ImportResultsStatus",
+                                    results.status);
+    }
+
     std::move(results_callback_).Run(std::move(results));
     return;
   }
   if (seq->csv_passwords.size() > MAX_PASSWORDS_PER_IMPORT) {
     results.status =
         password_manager::ImportResults::Status::NUM_PASSWORDS_EXCEEDED;
+    base::UmaHistogramEnumeration("PasswordManager.ImportResultsStatus",
+                                  results.status);
     std::move(results_callback_).Run(results);
-    // TODO(crbug/1325290): log to a histogram.
     return;
   }
 
diff --git a/components/password_manager/core/browser/import/password_importer.h b/components/password_manager/core/browser/import/password_importer.h
index 98530db..be59175b 100644
--- a/components/password_manager/core/browser/import/password_importer.h
+++ b/components/password_manager/core/browser/import/password_importer.h
@@ -23,16 +23,6 @@
 // performed using a utility SandBox process.
 class PasswordImporter {
  public:
-  enum Status {
-    NONE,
-    SUCCESS,
-    IO_ERROR,
-    SYNTAX_ERROR,
-    SEMANTIC_ERROR,
-    LARGE_FILE,
-    MAX_STATUS
-  };
-
   static constexpr size_t MAX_PASSWORDS_PER_IMPORT = 3000;
 
   // CompletionCallback is the type of the processing function for parsed
@@ -63,9 +53,6 @@
   void SetServiceForTesting(
       mojo::PendingRemote<mojom::CSVPasswordParser> parser);
 
-  // Returns the import status.
-  Status GetStatus() const;
-
   bool IsRunning() const { return !results_callback_.is_null(); }
 
  private:
@@ -73,7 +60,7 @@
   // asynchronously calls |completion| with the results.
   void ParseCSVPasswordsInSandbox(
       CompletionCallback completion,
-      base::expected<std::string, PasswordImporter::Status> result);
+      base::expected<std::string, ImportResults::Status> result);
 
   void ConsumePasswords(std::string file_name,
                         password_manager::PasswordForm::Store store,
@@ -83,7 +70,7 @@
 
   mojo::Remote<mojom::CSVPasswordParser> parser_;
 
-  Status status_{Status::NONE};
+  ImportResults::Status status_ = ImportResults::Status::NONE;
 
   ImportResultsCallback results_callback_;
 
diff --git a/components/password_manager/core/browser/import/password_importer_unittest.cc b/components/password_manager/core/browser/import/password_importer_unittest.cc
index 684f901..996fdbf 100644
--- a/components/password_manager/core/browser/import/password_importer_unittest.cc
+++ b/components/password_manager/core/browser/import/password_importer_unittest.cc
@@ -23,7 +23,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 using testing::IsEmpty;
-
 namespace password_manager {
 
 namespace {
@@ -107,9 +106,6 @@
     return result;
   }
 
-  PasswordImporter::Status GetImportStatus() const {
-    return importer_.GetStatus();
-  }
   ImportResults::Status GetResultsStatus() const {
     return import_results_.status;
   }
@@ -153,6 +149,8 @@
             base::WriteFile(input_path, kTestCSVInput, strlen(kTestCSVInput)));
   ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(input_path));
 
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportResultsStatus",
+                                      ImportResults::Status::SUCCESS, 1);
   histogram_tester.ExpectTotalCount("PasswordManager.ImportDuration", 1);
   histogram_tester.ExpectUniqueSample(
       "PasswordManager.ImportedPasswordsPerUserInCSV", 1, 1);
@@ -180,6 +178,8 @@
             base::WriteFile(input_path, kTestCSVInput, strlen(kTestCSVInput)));
   ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(input_path));
 
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportResultsStatus",
+                                      ImportResults::Status::BAD_FORMAT, 1);
   histogram_tester.ExpectTotalCount("PasswordManager.ImportDuration", 0);
   histogram_tester.ExpectTotalCount(
       "PasswordManager.ImportedPasswordsPerUserInCSV", 0);
@@ -217,6 +217,10 @@
             base::WriteFile(input_path, kTestCSVInput, strlen(kTestCSVInput)));
   ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(input_path));
 
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportResultsStatus",
+                                      ImportResults::Status::SUCCESS, 1);
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportEntryStatus",
+                                      ImportEntry::Status::CONFLICT_PROFILE, 1);
   histogram_tester.ExpectTotalCount("PasswordManager.ImportDuration", 1);
   histogram_tester.ExpectUniqueSample(
       "PasswordManager.ImportedPasswordsPerUserInCSV", 1, 1);
@@ -262,6 +266,10 @@
   ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(
       input_path, password_manager::PasswordForm::Store::kAccountStore));
 
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportResultsStatus",
+                                      ImportResults::Status::SUCCESS, 1);
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportEntryStatus",
+                                      ImportEntry::Status::CONFLICT_ACCOUNT, 1);
   histogram_tester.ExpectTotalCount("PasswordManager.ImportDuration", 1);
   histogram_tester.ExpectUniqueSample(
       "PasswordManager.ImportedPasswordsPerUserInCSV", 1, 1);
@@ -275,6 +283,7 @@
   EXPECT_EQ(password_manager::ImportEntry::Status::CONFLICT_ACCOUNT,
             results.failed_imports[0].status);
 
+  EXPECT_EQ(password_manager::ImportResults::Status::SUCCESS, results.status);
   EXPECT_EQ(1u, results.number_imported);
   ASSERT_EQ(2u, stored_passwords().size());
   EXPECT_EQ(GURL("https://test2.com"), stored_passwords()[1].url);
@@ -308,6 +317,10 @@
   ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(
       input_path, password_manager::PasswordForm::Store::kAccountStore));
 
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportResultsStatus",
+                                      ImportResults::Status::SUCCESS, 1);
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportEntryStatus",
+                                      ImportEntry::Status::CONFLICT_ACCOUNT, 1);
   histogram_tester.ExpectTotalCount("PasswordManager.ImportDuration", 1);
   histogram_tester.ExpectUniqueSample(
       "PasswordManager.ImportedPasswordsPerUserInCSV", 1, 1);
@@ -321,6 +334,7 @@
   EXPECT_EQ(password_manager::ImportEntry::Status::CONFLICT_ACCOUNT,
             results.failed_imports[0].status);
 
+  EXPECT_EQ(password_manager::ImportResults::Status::SUCCESS, results.status);
   EXPECT_EQ(1u, results.number_imported);
   ASSERT_EQ(2u, stored_passwords().size());
   EXPECT_EQ(GURL("https://test2.com"), stored_passwords()[1].url);
@@ -341,15 +355,19 @@
             base::WriteFile(input_path, kTestCSVInput, strlen(kTestCSVInput)));
   ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(input_path));
 
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportResultsStatus",
+                                      ImportResults::Status::SUCCESS, 1);
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportEntryStatus",
+                                      ImportEntry::Status::MISSING_PASSWORD, 1);
   histogram_tester.ExpectTotalCount("PasswordManager.ImportDuration", 1);
   histogram_tester.ExpectUniqueSample(
       "PasswordManager.ImportedPasswordsPerUserInCSV", 0, 1);
 
   const password_manager::ImportResults& results = GetImportResults();
 
-  ASSERT_EQ(0u, results.number_imported);
-  ASSERT_EQ(0u, stored_passwords().size());
-  ASSERT_EQ(password_manager::ImportResults::Status::SUCCESS, results.status);
+  EXPECT_EQ(password_manager::ImportResults::Status::SUCCESS, results.status);
+  EXPECT_EQ(0u, results.number_imported);
+  EXPECT_EQ(0u, stored_passwords().size());
   ASSERT_EQ(1u, results.failed_imports.size());
   EXPECT_EQ(password_manager::ImportEntry::Status::MISSING_PASSWORD,
             results.failed_imports[0].status);
@@ -370,14 +388,18 @@
             base::WriteFile(input_path, kTestCSVInput, strlen(kTestCSVInput)));
   ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(input_path));
 
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportResultsStatus",
+                                      ImportResults::Status::SUCCESS, 1);
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportEntryStatus",
+                                      ImportEntry::Status::MISSING_URL, 1);
   histogram_tester.ExpectTotalCount("PasswordManager.ImportDuration", 1);
-
   histogram_tester.ExpectUniqueSample(
       "PasswordManager.ImportedPasswordsPerUserInCSV", 0, 1);
 
   ASSERT_EQ(0u, stored_passwords().size());
 
   const password_manager::ImportResults results = GetImportResults();
+  EXPECT_EQ(password_manager::ImportResults::Status::SUCCESS, results.status);
   ASSERT_EQ(1u, results.failed_imports.size());
   EXPECT_EQ(password_manager::ImportEntry::Status::MISSING_URL,
             results.failed_imports[0].status);
@@ -398,14 +420,19 @@
                             kTestCSVInput.length()));
   ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(input_path));
 
-  histogram_tester.ExpectTotalCount("PasswordManager.ImportDuration", 1);
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportResultsStatus",
+                                      ImportResults::Status::SUCCESS, 1);
 
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportEntryStatus",
+                                      ImportEntry::Status::LONG_URL, 1);
+  histogram_tester.ExpectTotalCount("PasswordManager.ImportDuration", 1);
   histogram_tester.ExpectUniqueSample(
       "PasswordManager.ImportedPasswordsPerUserInCSV", 0, 1);
 
   ASSERT_EQ(0u, stored_passwords().size());
 
   const password_manager::ImportResults results = GetImportResults();
+  EXPECT_EQ(password_manager::ImportResults::Status::SUCCESS, results.status);
   ASSERT_EQ(1u, results.failed_imports.size());
   EXPECT_EQ(password_manager::ImportEntry::Status::LONG_URL,
             results.failed_imports[0].status);
@@ -429,14 +456,18 @@
                             kTestCSVInput.length()));
   ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(input_path));
 
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportResultsStatus",
+                                      ImportResults::Status::SUCCESS, 1);
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportEntryStatus",
+                                      ImportEntry::Status::LONG_PASSWORD, 1);
   histogram_tester.ExpectTotalCount("PasswordManager.ImportDuration", 1);
-
   histogram_tester.ExpectUniqueSample(
       "PasswordManager.ImportedPasswordsPerUserInCSV", 0, 1);
 
   ASSERT_EQ(0u, stored_passwords().size());
 
   const password_manager::ImportResults results = GetImportResults();
+  EXPECT_EQ(password_manager::ImportResults::Status::SUCCESS, results.status);
   ASSERT_EQ(1u, results.failed_imports.size());
   EXPECT_EQ(password_manager::ImportEntry::Status::LONG_PASSWORD,
             results.failed_imports[0].status);
@@ -459,14 +490,18 @@
                             kTestCSVInput.length()));
   ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(input_path));
 
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportResultsStatus",
+                                      ImportResults::Status::SUCCESS, 1);
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportEntryStatus",
+                                      ImportEntry::Status::LONG_USERNAME, 1);
   histogram_tester.ExpectTotalCount("PasswordManager.ImportDuration", 1);
-
   histogram_tester.ExpectUniqueSample(
       "PasswordManager.ImportedPasswordsPerUserInCSV", 0, 1);
 
   ASSERT_EQ(0u, stored_passwords().size());
 
   const password_manager::ImportResults results = GetImportResults();
+  EXPECT_EQ(password_manager::ImportResults::Status::SUCCESS, results.status);
   ASSERT_EQ(1u, results.failed_imports.size());
   EXPECT_EQ(password_manager::ImportEntry::Status::LONG_USERNAME,
             results.failed_imports[0].status);
@@ -487,14 +522,18 @@
             base::WriteFile(input_path, kTestCSVInput, strlen(kTestCSVInput)));
   ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(input_path));
 
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportResultsStatus",
+                                      ImportResults::Status::SUCCESS, 1);
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportEntryStatus",
+                                      ImportEntry::Status::INVALID_URL, 1);
   histogram_tester.ExpectTotalCount("PasswordManager.ImportDuration", 1);
-
   histogram_tester.ExpectUniqueSample(
       "PasswordManager.ImportedPasswordsPerUserInCSV", 0, 1);
 
   ASSERT_EQ(0u, stored_passwords().size());
 
   const password_manager::ImportResults results = GetImportResults();
+  EXPECT_EQ(password_manager::ImportResults::Status::SUCCESS, results.status);
   ASSERT_EQ(1u, results.failed_imports.size());
   EXPECT_EQ(password_manager::ImportEntry::Status::INVALID_URL,
             results.failed_imports[0].status);
@@ -516,14 +555,18 @@
             base::WriteFile(input_path, kTestCSVInput, strlen(kTestCSVInput)));
   ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(input_path));
 
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportResultsStatus",
+                                      ImportResults::Status::SUCCESS, 1);
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportEntryStatus",
+                                      ImportEntry::Status::NON_ASCII_URL, 1);
   histogram_tester.ExpectTotalCount("PasswordManager.ImportDuration", 1);
-
   histogram_tester.ExpectUniqueSample(
       "PasswordManager.ImportedPasswordsPerUserInCSV", 0, 1);
 
   ASSERT_EQ(0u, stored_passwords().size());
 
   const password_manager::ImportResults results = GetImportResults();
+  EXPECT_EQ(password_manager::ImportResults::Status::SUCCESS, results.status);
   ASSERT_EQ(1u, results.failed_imports.size());
   EXPECT_EQ(password_manager::ImportEntry::Status::NON_ASCII_URL,
             results.failed_imports[0].status);
@@ -547,14 +590,18 @@
             base::WriteFile(input_path, kTestCSVInput, strlen(kTestCSVInput)));
   ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(input_path));
 
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportResultsStatus",
+                                      ImportResults::Status::SUCCESS, 1);
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportEntryStatus",
+                                      ImportEntry::Status::MISSING_URL, 1);
   histogram_tester.ExpectTotalCount("PasswordManager.ImportDuration", 1);
-
   histogram_tester.ExpectUniqueSample(
       "PasswordManager.ImportedPasswordsPerUserInCSV", 1, 1);
 
   ASSERT_EQ(1u, stored_passwords().size());
 
   const password_manager::ImportResults results = GetImportResults();
+  EXPECT_EQ(password_manager::ImportResults::Status::SUCCESS, results.status);
   EXPECT_EQ(1u, results.number_imported);
   ASSERT_EQ(1u, results.failed_imports.size());
   EXPECT_EQ(password_manager::ImportEntry::Status::MISSING_URL,
@@ -578,6 +625,10 @@
             base::WriteFile(input_path, kTestCSVInput, strlen(kTestCSVInput)));
   ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(input_path));
 
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportResultsStatus",
+                                      ImportResults::Status::SUCCESS, 1);
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportEntryStatus",
+                                      ImportEntry::Status::MISSING_URL, 1);
   histogram_tester.ExpectUniqueSample("PasswordManager.ImportFileSize",
                                       /*sample=*/105,
                                       /*expected_bucket_count=*/1);
@@ -593,6 +644,7 @@
 
   const password_manager::ImportResults& results = GetImportResults();
 
+  EXPECT_EQ(password_manager::ImportResults::Status::SUCCESS, results.status);
   ASSERT_EQ(1u, results.failed_imports.size());
   EXPECT_EQ(password_manager::ImportEntry::Status::MISSING_URL,
             results.failed_imports[0].status);
@@ -611,6 +663,9 @@
   ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(temp_file_path));
 
   EXPECT_THAT(stored_passwords(), IsEmpty());
+
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportResultsStatus",
+                                      ImportResults::Status::MAX_FILE_SIZE, 1);
   histogram_tester.ExpectUniqueSample("PasswordManager.ImportFileSize",
                                       /*sample=*/153700,
                                       /*expected_bucket_count=*/1);
@@ -618,11 +673,14 @@
   histogram_tester.ExpectTotalCount(
       "PasswordManager.ImportedPasswordsPerUserInCSV", 0);
 
-  EXPECT_EQ(PasswordImporter::Status::LARGE_FILE, GetImportStatus());
+  const password_manager::ImportResults& results = GetImportResults();
+  EXPECT_EQ(ImportResults::Status::MAX_FILE_SIZE, results.status);
+
   base::DeleteFile(temp_file_path);
 }
 
 TEST_F(PasswordImporterTest, CSVImportHitMaxPasswordsLimit) {
+  base::HistogramTester histogram_tester;
   std::string content = "url,login,password\n";
   std::string row = "http://a.b,c,d\n";
   const size_t EXCEEDS_LIMIT = PasswordImporter::MAX_PASSWORDS_PER_IMPORT + 1;
@@ -636,6 +694,10 @@
 
   ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(temp_file_path));
 
+  histogram_tester.ExpectUniqueSample(
+      "PasswordManager.ImportResultsStatus",
+      ImportResults::Status::NUM_PASSWORDS_EXCEEDED, 1);
+
   EXPECT_THAT(stored_passwords(), IsEmpty());
   EXPECT_EQ(ImportResults::Status::NUM_PASSWORDS_EXCEEDED, GetResultsStatus());
   base::DeleteFile(temp_file_path);
@@ -652,13 +714,15 @@
 
   ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(input_path));
 
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportResultsStatus",
+                                      ImportResults::Status::IO_ERROR, 1);
   histogram_tester.ExpectTotalCount("PasswordManager.ImportFileSize", 0);
   histogram_tester.ExpectTotalCount("PasswordManager.ImportDuration", 0);
   histogram_tester.ExpectTotalCount(
       "PasswordManager.ImportedPasswordsPerUserInCSV", 0);
   EXPECT_THAT(GetImportResults().failed_imports, IsEmpty());
   EXPECT_THAT(stored_passwords(), IsEmpty());
-  EXPECT_EQ(PasswordImporter::Status::IO_ERROR, GetImportStatus());
+  EXPECT_EQ(ImportResults::Status::IO_ERROR, GetResultsStatus());
 }
 
 TEST_F(PasswordImporterTest, ImportIOErrorDueToUnreadableFile) {
@@ -667,12 +731,15 @@
   ASSERT_NO_FATAL_FAILURE(
       StartImportAndWaitForCompletion(non_existent_input_file));
 
+  histogram_tester.ExpectUniqueSample("PasswordManager.ImportResultsStatus",
+                                      ImportResults::Status::IO_ERROR, 1);
   histogram_tester.ExpectTotalCount("PasswordManager.ImportFileSize", 0);
   histogram_tester.ExpectTotalCount("PasswordManager.ImportDuration", 0);
   histogram_tester.ExpectTotalCount(
       "PasswordManager.ImportedPasswordsPerUserInCSV", 0);
   EXPECT_THAT(GetImportResults().failed_imports, IsEmpty());
   EXPECT_THAT(stored_passwords(), IsEmpty());
+  EXPECT_EQ(ImportResults::Status::IO_ERROR, GetResultsStatus());
 }
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/ui/import_results.h b/components/password_manager/core/browser/ui/import_results.h
index 95080df9..00fade2d0 100644
--- a/components/password_manager/core/browser/ui/import_results.h
+++ b/components/password_manager/core/browser/ui/import_results.h
@@ -14,27 +14,28 @@
   // Matches api::passwords_private::ImportEntryStatus.
   enum Status {
     // Should not be used.
-    NONE,
+    NONE = 0,
     // Any other error state.
-    UNKNOWN_ERROR,
+    UNKNOWN_ERROR = 1,
     // Missing password field.
-    MISSING_PASSWORD,
+    MISSING_PASSWORD = 2,
     // Missing url field.
-    MISSING_URL,
+    MISSING_URL = 3,
     // Bad url formatting.
-    INVALID_URL,
+    INVALID_URL = 4,
     // URL contains non-ASCII chars.
-    NON_ASCII_URL,
+    NON_ASCII_URL = 5,
     // URL is too long.
-    LONG_URL,
+    LONG_URL = 6,
     // Password is too long.
-    LONG_PASSWORD,
+    LONG_PASSWORD = 7,
     // Username is too long.
-    LONG_USERNAME,
+    LONG_USERNAME = 8,
     // Credential is already stored in profile store.
-    CONFLICT_PROFILE,
+    CONFLICT_PROFILE = 9,
     // Credential is already stored in account store.
-    CONFLICT_ACCOUNT
+    CONFLICT_ACCOUNT = 10,
+    kMaxValue = CONFLICT_ACCOUNT
   };
 
   // The status of parsing for individual row that represents a credential
@@ -60,23 +61,24 @@
   // Matches api::passwords_private::ImportResultsStatus.
   enum Status {
     // Should not be used.
-    NONE,
+    NONE = 0,
     // Any other error state.
-    UNKNOWN_ERROR,
+    UNKNOWN_ERROR = 1,
     // Data was fully or partially imported.
-    SUCCESS,
+    SUCCESS = 2,
     // Failed to read provided file.
-    IO_ERROR,
+    IO_ERROR = 3,
     // Header is missing, invalid or could not be read.
-    BAD_FORMAT,
+    BAD_FORMAT = 4,
     // File selection dismissed.
-    DISMISSED,
+    DISMISSED = 5,
     // Size of the chosen file exceeds the limit.
-    MAX_FILE_SIZE,
+    MAX_FILE_SIZE = 6,
     // User has already started the import flow in a different window.
-    IMPORT_ALREADY_ACTIVE,
+    IMPORT_ALREADY_ACTIVE = 7,
     // User tried to import too many passwords from one file.
-    NUM_PASSWORDS_EXCEEDED
+    NUM_PASSWORDS_EXCEEDED = 8,
+    kMaxValue = NUM_PASSWORDS_EXCEEDED
   };
 
   // General status of the triggered password import process.
diff --git a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h
index 77662e8..cfbb9f0 100644
--- a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h
+++ b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h
@@ -57,6 +57,11 @@
 // https://crbug.com/960904
 - (void)enforceNeverMadeVisible;
 
+// Order window for all cases, including for children windows that
+// -[NSWindow orderWindow:] can't properly handle.
+- (void)reallyOrderWindow:(NSWindowOrderingMode)place
+               relativeTo:(NSInteger)otherWin;
+
 // Order the window to the front (space switch if necessary), and ensure that
 // the window maintains its key state. A space switch will normally activate a
 // window, so this function prevents that if the window is currently inactive.
diff --git a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
index 949fb64..96e401e9 100644
--- a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
+++ b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
@@ -164,7 +164,6 @@
   BOOL _willUpdateRestorableState;
   BOOL _isEnforcingNeverMadeVisible;
   BOOL _preventKeyWindow;
-  BOOL _isAddingChildWindow;
   BOOL _isTooltip;
 }
 @synthesize bridgedNativeWidgetId = _bridgedNativeWidgetId;
@@ -182,7 +181,6 @@
                                    defer:deferCreation])) {
     _commandDispatcher.reset([[CommandDispatcher alloc] initWithOwner:self]);
   }
-  _isAddingChildWindow = NO;
   return self;
 }
 
@@ -199,7 +197,6 @@
 }
 
 - (void)addChildWindow:(NSWindow*)childWin ordered:(NSWindowOrderingMode)place {
-  base::AutoReset<BOOL> isAddingChildWindow(&_isAddingChildWindow, YES);
   // Attaching a window to be a child window resets the window level, so
   // restore the window level afterwards.
   NSInteger level = childWin.level;
@@ -426,44 +423,39 @@
   [super sendEvent:event];
 }
 
-// Override window order functions to
-// 1. Intercept other visibility changes
-//    This is needed in addition to the -[NSWindow display] override because
-//    Cocoa hardly ever calls display, and reports -[NSWindow isVisible]
-//    incorrectly when ordering in a window for the first time.
-// 2. Handle child windows
-//    -[NSWindow orderWindow] does not work for child windows. To order
-//    children, we need to detach them from thier parent and re-attach them
-//    in our desire order.
-- (void)orderWindow:(NSWindowOrderingMode)orderingMode
-         relativeTo:(NSInteger)otherWindowNumber {
+- (void)reallyOrderWindow:(NSWindowOrderingMode)orderingMode
+               relativeTo:(NSInteger)otherWindowNumber {
   NativeWidgetMacNSWindow* parent =
       static_cast<NativeWidgetMacNSWindow*>([self parentWindow]);
-  // Cocoa will call -[NSWindow orderWindow] during -[NSWindow addChildWindow].
-  // To prevent re-entrancy, skip re-parenting if adding children.
-  if (parent && parent->_isAddingChildWindow) {
-    [super orderWindow:orderingMode relativeTo:otherWindowNumber];
-    [[self viewsNSWindowDelegate] onWindowOrderChanged:nil];
+
+  // This is not a child window. No need to patch.
+  if (!parent) {
+    [self orderWindow:orderingMode relativeTo:otherWindowNumber];
     return;
   }
 
   // `otherWindow` is nil if `otherWindowNumber` is 0. In this case, place
   // `self` at the top / bottom, depending on `orderingMode`.
   NSWindow* otherWindow = [NSApp windowWithWindowNumber:otherWindowNumber];
-
-  // For unknown reason chrome will freeze during startup without this line.
-  [super orderWindow:orderingMode relativeTo:otherWindowNumber];
-
-  // During shutdown the parent may have changed at this point, so reacquire
-  // `parent`.
-  parent = static_cast<NativeWidgetMacNSWindow*>([self parentWindow]);
-  if (parent && (otherWindow == nullptr ||
-                 parent == [otherWindow parentWindow] || parent == otherWindow))
+  if (otherWindow == nullptr || parent == [otherWindow parentWindow] ||
+      parent == otherWindow)
     OrderChildWindow(self, otherWindow, orderingMode);
 
   [[self viewsNSWindowDelegate] onWindowOrderChanged:nil];
 }
 
+// Override window order functions to intercept other visibility changes. This
+// is needed in addition to the -[NSWindow display] override because Cocoa
+// hardly ever calls display, and reports -[NSWindow isVisible] incorrectly
+// when ordering in a window for the first time.
+// Note that this methods has no effect for children windows. Use
+// -reallyOrderWindow:relativeTo: instead.
+- (void)orderWindow:(NSWindowOrderingMode)orderingMode
+         relativeTo:(NSInteger)otherWindowNumber {
+  [super orderWindow:orderingMode relativeTo:otherWindowNumber];
+  [[self viewsNSWindowDelegate] onWindowOrderChanged:nil];
+}
+
 // NSResponder implementation.
 
 - (BOOL)performKeyEquivalent:(NSEvent*)event {
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
index 0a2a8ff..85a3c64f9 100644
--- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
+++ b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
@@ -403,11 +403,11 @@
   DCHECK(sibling_bridge);
 
   NSInteger sibling = sibling_bridge->ns_window().windowNumber;
-  [window_ orderWindow:NSWindowAbove relativeTo:sibling];
+  [window_ reallyOrderWindow:NSWindowAbove relativeTo:sibling];
 }
 
 void NativeWidgetNSWindowBridge::StackAtTop() {
-  [window_ orderWindow:NSWindowAbove relativeTo:0];
+  [window_ reallyOrderWindow:NSWindowAbove relativeTo:0];
 }
 
 void NativeWidgetNSWindowBridge::ShowEmojiPanel() {
diff --git a/components/segmentation_platform/public/proto/segmentation_platform.proto b/components/segmentation_platform/public/proto/segmentation_platform.proto
index a591046..9054db6a7 100644
--- a/components/segmentation_platform/public/proto/segmentation_platform.proto
+++ b/components/segmentation_platform/public/proto/segmentation_platform.proto
@@ -14,6 +14,8 @@
 // OptimizationTarget. If the segment only uses default model, then the segment
 // should have a value higher than `MAX_OPTIMIZATION_TARGET`.
 enum SegmentId {
+  reserved 20;
+  
   OPTIMIZATION_TARGET_UNKNOWN = 0;
   // Should only be applied when the page load is predicted to be painful.
   OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD = 1;
@@ -53,8 +55,10 @@
   OPTIMIZATION_TARGET_SEGMENTATION_FEED_USER = 17;
   // Target for price tracking action when shown as a contextual page action.
   OPTIMIZATION_TARGET_CONTEXTUAL_PAGE_ACTION_PRICE_TRACKING = 18;
+  // Target for smart text selection and entity extraction.
+  OPTIMIZATION_TARGET_TEXT_CLASSIFIER = 19;
   // Target for segmentation: Determine users who are interested in shopping.
-  OPTIMIZATION_TARGET_SEGMENTATION_SHOPPING_USER = 19;
+  OPTIMIZATION_TARGET_SEGMENTATION_SHOPPING_USER = 21;
   // Add new entries to OptimizationTarget proto.
 
   // New entries should start from a 1000 if OptimizationTarget does not
diff --git a/content/browser/accessibility/one_shot_accessibility_tree_search.cc b/content/browser/accessibility/one_shot_accessibility_tree_search.cc
index fc45dca..bb7f104 100644
--- a/content/browser/accessibility/one_shot_accessibility_tree_search.cc
+++ b/content/browser/accessibility/one_shot_accessibility_tree_search.cc
@@ -370,6 +370,9 @@
     case ax::mojom::Role::kBanner:
     case ax::mojom::Role::kComplementary:
     case ax::mojom::Role::kContentInfo:
+    case ax::mojom::Role::kFooter:
+    case ax::mojom::Role::kForm:
+    case ax::mojom::Role::kHeader:
     case ax::mojom::Role::kMain:
     case ax::mojom::Role::kNavigation:
     case ax::mojom::Role::kRegion:
diff --git a/content/browser/attribution_reporting/attribution_aggregation_keys.cc b/content/browser/attribution_reporting/attribution_aggregation_keys.cc
index 0f1672e..05fb0b8 100644
--- a/content/browser/attribution_reporting/attribution_aggregation_keys.cc
+++ b/content/browser/attribution_reporting/attribution_aggregation_keys.cc
@@ -50,11 +50,11 @@
   Keys::container_type keys;
   keys.reserve(num_keys);
 
-  for (auto [key_id, value] : *dict) {
+  for (auto [key_id, maybe_string_value] : *dict) {
     if (key_id.size() > blink::kMaxBytesPerAttributionAggregationKeyId)
       return absl::nullopt;
 
-    const std::string* s = value.GetIfString();
+    const std::string* s = maybe_string_value.GetIfString();
     if (!s)
       return absl::nullopt;
 
diff --git a/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc b/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
index d04903b..00e049b 100644
--- a/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
+++ b/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
@@ -505,20 +505,20 @@
   event_triggers.reserve(data->event_triggers.size());
 
   for (auto& event_trigger : data->event_triggers) {
-    absl::optional<AttributionFilterData> filters =
+    absl::optional<AttributionFilterData> event_filters =
         AttributionFilterData::FromTriggerFilterValues(
             std::move(event_trigger->filters->filter_values));
-    if (!filters.has_value()) {
+    if (!event_filters.has_value()) {
       RecordTriggerDataHandleStatus(DataHandleStatus::kInvalidData);
       mojo::ReportBadMessage(
           "AttributionDataHost: Invalid event-trigger filters.");
       return;
     }
 
-    absl::optional<AttributionFilterData> not_filters =
+    absl::optional<AttributionFilterData> not_event_filters =
         AttributionFilterData::FromTriggerFilterValues(
             std::move(event_trigger->not_filters->filter_values));
-    if (!not_filters.has_value()) {
+    if (!not_event_filters.has_value()) {
       RecordTriggerDataHandleStatus(DataHandleStatus::kInvalidData);
       mojo::ReportBadMessage(
           "AttributionDataHost: Invalid event-trigger not_filters.");
@@ -530,7 +530,7 @@
         event_trigger->dedup_key
             ? absl::make_optional(event_trigger->dedup_key->value)
             : absl::nullopt,
-        std::move(*filters), std::move(*not_filters));
+        std::move(*event_filters), std::move(*not_event_filters));
   }
 
   absl::optional<std::vector<AttributionAggregatableTriggerData>>
diff --git a/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc b/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc
index 36f10d4..4eda3eb 100644
--- a/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc
@@ -833,7 +833,7 @@
     attribution_manager_->ClearData(
         start, start + base::Minutes(1),
         base::BindLambdaForTesting(
-            [match_url](const blink::StorageKey& _) { return match_url; }),
+            [match_url](const blink::StorageKey&) { return match_url; }),
         /*delete_rate_limit_data=*/true, run_loop.QuitClosure());
     run_loop.Run();
 
@@ -1197,7 +1197,7 @@
   base::RunLoop run_loop;
   attribution_manager_->ClearData(
       base::Time::Min(), base::Time::Max(),
-      base::BindRepeating([](const blink::StorageKey& _) { return false; }),
+      base::BindRepeating([](const blink::StorageKey&) { return false; }),
       /*delete_rate_limit_data=*/true, run_loop.QuitClosure());
   run_loop.Run();
 }
diff --git a/content/browser/attribution_reporting/rate_limit_table_unittest.cc b/content/browser/attribution_reporting/rate_limit_table_unittest.cc
index 94d26d9..defb5324 100644
--- a/content/browser/attribution_reporting/rate_limit_table_unittest.cc
+++ b/content/browser/attribution_reporting/rate_limit_table_unittest.cc
@@ -598,7 +598,7 @@
                                  "https://d.r.test", now + base::Days(1))},
     };
 
-    for (const auto& [_, row] : rows) {
+    for (const auto& [key, row] : rows) {
       switch (row.scope) {
         case RateLimitScope::kSource:
           ASSERT_TRUE(AddRateLimitForSource(row)) << row;
diff --git a/content/browser/fenced_frame/fenced_frame_browsertest.cc b/content/browser/fenced_frame/fenced_frame_browsertest.cc
index 536fa78..2edfc5f 100644
--- a/content/browser/fenced_frame/fenced_frame_browsertest.cc
+++ b/content/browser/fenced_frame/fenced_frame_browsertest.cc
@@ -2132,9 +2132,9 @@
 
   EXPECT_TRUE(url_mapping.HasObserverForTesting(urn_uuid, request));
 
-  auto* budget_metadata =
+  auto budget_metadata =
       fenced_frame_root_node->FindSharedStorageBudgetMetadata();
-  EXPECT_FALSE(budget_metadata);
+  EXPECT_FALSE(budget_metadata.has_value());
 
   // Trigger the mapping to resume the deferred navigation.
   SimulateSharedStorageURNMappingComplete(
@@ -2151,10 +2151,10 @@
       fenced_frame_root_node->current_frame_host()->GetLastCommittedURL());
 
   budget_metadata = fenced_frame_root_node->FindSharedStorageBudgetMetadata();
-  EXPECT_TRUE(budget_metadata);
-  EXPECT_EQ(budget_metadata->origin,
+  EXPECT_TRUE(budget_metadata.has_value());
+  EXPECT_EQ((*budget_metadata)->origin,
             url::Origin::Create(GURL("https://bar.com")));
-  EXPECT_DOUBLE_EQ(budget_metadata->budget_to_charge, 2.0);
+  EXPECT_DOUBLE_EQ((*budget_metadata)->budget_to_charge, 2.0);
 }
 
 // Test the scenario where the FF navigation is deferred and then resumed, and
@@ -2223,8 +2223,9 @@
   observer.Wait();
   EXPECT_EQ(observer.last_net_error_code(), net::ERR_BLOCKED_BY_RESPONSE);
 
-  auto* metadata = fenced_frame_root_node->FindSharedStorageBudgetMetadata();
-  EXPECT_FALSE(metadata);
+  // Despite the error, the budget metadata should be valid.
+  auto metadata = fenced_frame_root_node->FindSharedStorageBudgetMetadata();
+  EXPECT_TRUE(metadata);
 }
 
 IN_PROC_BROWSER_TEST_P(
diff --git a/content/browser/fenced_frame/fenced_frame_url_mapping.cc b/content/browser/fenced_frame/fenced_frame_url_mapping.cc
index 8a82cdc..9013d177 100644
--- a/content/browser/fenced_frame/fenced_frame_url_mapping.cc
+++ b/content/browser/fenced_frame/fenced_frame_url_mapping.cc
@@ -160,8 +160,12 @@
     : mapped_url(map_info.mapped_url),
       ad_auction_data(map_info.ad_auction_data),
       pending_ad_components_map(absl::nullopt),
-      shared_storage_budget_metadata(map_info.shared_storage_budget_metadata),
+      shared_storage_budget_metadata(absl::nullopt),
       reporting_metadata(map_info.reporting_metadata) {
+  if (map_info.shared_storage_budget_metadata) {
+    shared_storage_budget_metadata =
+        &map_info.shared_storage_budget_metadata.value();
+  }
   if (map_info.ad_component_urls) {
     pending_ad_components_map =
         PendingAdComponentsMap(*map_info.ad_component_urls);
@@ -262,8 +266,8 @@
 void FencedFrameURLMapping::OnSharedStorageURNMappingResultDetermined(
     const GURL& urn_uuid,
     const SharedStorageURNMappingResult& mapping_result) {
-  auto it = pending_urn_uuid_to_url_map_.find(urn_uuid);
-  DCHECK(it != pending_urn_uuid_to_url_map_.end());
+  auto pending_it = pending_urn_uuid_to_url_map_.find(urn_uuid);
+  DCHECK(pending_it != pending_urn_uuid_to_url_map_.end());
 
   DCHECK(!IsMapped(urn_uuid));
 
@@ -289,17 +293,19 @@
     urn_uuid_to_url_map_.emplace(urn_uuid, *config);
   }
 
-  std::set<raw_ptr<MappingResultObserver>>& observers = it->second;
+  std::set<raw_ptr<MappingResultObserver>>& observers = pending_it->second;
 
   absl::optional<FencedFrameProperties> properties = absl::nullopt;
-  if (config)
-    properties = FencedFrameProperties(*config);
+  auto final_it = urn_uuid_to_url_map_.find(urn_uuid);
+  if (final_it != urn_uuid_to_url_map_.end()) {
+    properties = FencedFrameProperties(final_it->second);
+  }
 
   for (raw_ptr<MappingResultObserver> observer : observers) {
     observer->OnFencedFrameURLMappingComplete(properties);
   }
 
-  pending_urn_uuid_to_url_map_.erase(it);
+  pending_urn_uuid_to_url_map_.erase(pending_it);
 }
 
 FencedFrameURLMapping::SharedStorageBudgetMetadata*
diff --git a/content/browser/fenced_frame/fenced_frame_url_mapping.h b/content/browser/fenced_frame/fenced_frame_url_mapping.h
index b131493..6b147e3f 100644
--- a/content/browser/fenced_frame/fenced_frame_url_mapping.h
+++ b/content/browser/fenced_frame/fenced_frame_url_mapping.h
@@ -43,7 +43,7 @@
   // the `FencedFrameURLMapping`.
   struct CONTENT_EXPORT SharedStorageBudgetMetadata {
     url::Origin origin;
-    double budget_to_charge = 0;
+    mutable double budget_to_charge = 0;
   };
 
   // The runURLSelectionOperation's url mapping result. It contains the mapped
@@ -161,8 +161,12 @@
   // urn:uuid navigation time according to a fenced frame configuration,
   // specified by `MapInfo` above.
   // Most of these are copied from `MapInfo` directly, but some are generated
-  // by another transformation (e.g. `pending_ad_components_map` generates urn
-  // mappings for the specified `ad_component_urls`).
+  // by another transformation, e.g.:
+  // * We generate urns for the urls in `ad_component_urls` and store them in
+  // `pending_ad_components_map`.
+  // * We generate a pointer to `shared_storage_budget_metadata` and store it in
+  //   `shared_storage_budget_metadata`, because it should only take effect once
+  //   across all fenced frames navigated to a particular configuration.
   // These `FencedFrameProperties` are stored in the fenced frame root
   // `FrameTreeNode`, and live between embedder-initiated fenced frame
   // navigations.
@@ -176,9 +180,26 @@
     FencedFrameProperties& operator=(FencedFrameProperties&&);
 
     GURL mapped_url;
+
     absl::optional<AdAuctionData> ad_auction_data;
+
+    // urn/url mappings for ad components. These are inserted into the
+    // fenced frame page's urn/url mapping when the urn navigation commits.
     absl::optional<PendingAdComponentsMap> pending_ad_components_map;
-    absl::optional<SharedStorageBudgetMetadata> shared_storage_budget_metadata;
+
+    // This can only be possibly set for the outermost fenced frame root,
+    // because selectURL() is disallowed inside fenced frame, and the URN
+    // generated outside the a fenced frame cannot be recognized from inside,
+    // so a nested fenced frame can never navigate to a shared storage
+    // generated URN.
+    //
+    // This pointer to the outermost page's FencedFrameURLMapping is copied
+    // into the fenced frame root's FrameTreeNode. This is safe because a page
+    // will outlive any NavigationRequest occurring in fenced frames in the
+    // page.
+    absl::optional<raw_ptr<const SharedStorageBudgetMetadata>>
+        shared_storage_budget_metadata;
+
     ReportingMetadata reporting_metadata;
   };
 
diff --git a/content/browser/file_system_access/file_system_chooser.cc b/content/browser/file_system_access/file_system_chooser.cc
index c357a20..695cba7 100644
--- a/content/browser/file_system_access/file_system_chooser.cc
+++ b/content/browser/file_system_access/file_system_chooser.cc
@@ -4,23 +4,18 @@
 
 #include "content/browser/file_system_access/file_system_chooser.h"
 
-#include "base/bind.h"
 #include "base/files/file_path.h"
-#include "base/files/file_util.h"
 #include "base/i18n/file_util_icu.h"
 #include "base/i18n/rtl.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
-#include "content/browser/file_system_access/file_system_access_directory_handle_impl.h"
 #include "content/browser/file_system_access/file_system_access_error.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/child_process_security_policy.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_client.h"
-#include "net/base/filename_util.h"
 #include "net/base/mime_util.h"
 #include "ui/gfx/text_elider.h"
 #include "ui/shell_dialogs/select_file_policy.h"
@@ -36,6 +31,10 @@
 // size and underlying platform all influence how many characters will actually
 // be visible. As such this can be adjusted as needed.
 constexpr int kMaxDescriptionLength = 64;
+// The maximum number of unicode code points the extension of a file is
+// allowed to be. Any longer extensions will be stripped. This value should be
+// kept in sync with the extension length checks in the renderer.
+constexpr int kMaxExtensionLength = 16;
 
 std::string TypeToString(ui::SelectFileDialog::Type type) {
   switch (type) {
@@ -214,6 +213,12 @@
 
   auto suggested_extension = suggested_name.Extension();
 
+  if (suggested_extension.size() > kMaxExtensionLength) {
+    // Sanitize extensions longer than 16 characters.
+    file_types.include_all_files = true;
+    return suggested_name.RemoveExtension();
+  }
+
   if (file_types.extensions.empty() || suggested_extension.empty()) {
     file_types.include_all_files = true;
     return suggested_name;
diff --git a/content/browser/file_system_access/file_system_chooser_browsertest.cc b/content/browser/file_system_access/file_system_chooser_browsertest.cc
index d0e728ac..410b6b8 100644
--- a/content/browser/file_system_access/file_system_chooser_browsertest.cc
+++ b/content/browser/file_system_access/file_system_chooser_browsertest.cc
@@ -1620,6 +1620,12 @@
                         true, "dangerous_extension.scf.png", true});
   name_infos.push_back({"dangerous_extension.url.png", ListValueOf(".png"),
                         true, "dangerous_extension.url.png", true});
+  // Extensions longer than 16 characters should be stripped.
+  name_infos.push_back({"long_extension.len10plus123456",
+                        ListValueOf(".len10plus123456"), true,
+                        "long_extension.len10plus123456", true});
+  name_infos.push_back({"long_extension.len10plus1234567", ListValueOf(".nope"),
+                        true, "long_extension", false});
   // Invalid characters should be sanitized.
   name_infos.push_back({R"(inv*l:d\\ch%rבאמת!a<ters🤓.txt)",
                         ListValueOf(".txt"), true,
diff --git a/content/browser/renderer_host/frame_tree_node.cc b/content/browser/renderer_host/frame_tree_node.cc
index a90baf0c..442a7df 100644
--- a/content/browser/renderer_host/frame_tree_node.cc
+++ b/content/browser/renderer_host/frame_tree_node.cc
@@ -990,14 +990,15 @@
   srcdoc_value_ = srcdoc_value;
 }
 
-FencedFrameURLMapping::SharedStorageBudgetMetadata*
+absl::optional<const FencedFrameURLMapping::SharedStorageBudgetMetadata*>
 FrameTreeNode::FindSharedStorageBudgetMetadata() {
   FrameTreeNode* node = this;
 
   while (true) {
-    if (node->shared_storage_budget_metadata()) {
+    if (node->fenced_frame_properties_ &&
+        node->fenced_frame_properties_->shared_storage_budget_metadata) {
       DCHECK(node->IsFencedFrameRoot());
-      return node->shared_storage_budget_metadata();
+      return node->fenced_frame_properties_->shared_storage_budget_metadata;
     }
 
     if (node->GetParentOrOuterDocument()) {
@@ -1007,7 +1008,7 @@
     }
   }
 
-  return nullptr;
+  return absl::nullopt;
 }
 
 const scoped_refptr<BrowsingContextState>&
diff --git a/content/browser/renderer_host/frame_tree_node.h b/content/browser/renderer_host/frame_tree_node.h
index 1a11970..ffb45a5c 100644
--- a/content/browser/renderer_host/frame_tree_node.h
+++ b/content/browser/renderer_host/frame_tree_node.h
@@ -532,8 +532,10 @@
   void set_fenced_frame_properties(
       absl::optional<FencedFrameURLMapping::FencedFrameProperties>&
           fenced_frame_properties) {
-    DCHECK_EQ(fenced_frame_status_,
-              RenderFrameHostImpl::FencedFrameStatus::kFencedFrameRoot);
+    // TODO(crbug.com/1262022): Reenable this DCHECK once ShadowDOM and
+    // loading urns in iframes (for FLEDGE OT) are gone.
+    // DCHECK_EQ(fenced_frame_status_,
+    //          RenderFrameHostImpl::FencedFrameStatus::kFencedFrameRoot);
     fenced_frame_properties_ = fenced_frame_properties;
   }
 
@@ -542,25 +544,12 @@
     return fenced_frame_properties_;
   }
 
-  void set_shared_storage_budget_metadata(
-      FencedFrameURLMapping::SharedStorageBudgetMetadata*
-          shared_storage_budget_metadata) {
-    DCHECK_EQ(fenced_frame_status_,
-              RenderFrameHostImpl::FencedFrameStatus::kFencedFrameRoot);
-    shared_storage_budget_metadata_ = shared_storage_budget_metadata;
-  }
-
-  FencedFrameURLMapping::SharedStorageBudgetMetadata*
-  shared_storage_budget_metadata() const {
-    return shared_storage_budget_metadata_;
-  }
-
   // Traverse up from this node. The `shared_storage_budget_metadata()` of the
   // first seen node with a non-null budget metadata will be returned (i.e. this
   // node inherits that budget metadata), and this node is expected to be an
   // outermost fenced frame root. Return nullptr if not found (i.e. this node is
   // not subjected to shared storage budgeting).
-  FencedFrameURLMapping::SharedStorageBudgetMetadata*
+  absl::optional<const FencedFrameURLMapping::SharedStorageBudgetMetadata*>
   FindSharedStorageBudgetMetadata();
 
   // Accessor to BrowsingContextState for subframes only. Only main frame
@@ -787,26 +776,9 @@
 
   // If this is a fenced frame resulting from a urn:uuid navigation, this
   // contains all the metadata specifying the resulting context.
-  // TODO(crbug.com/1347953): Replace redundant variables in this file with
-  // accesses to the fields of this object.
   absl::optional<FencedFrameURLMapping::FencedFrameProperties>
       fenced_frame_properties_;
 
-  // If this is a fenced frame resulting from a shared storage url selection
-  // operation, this contains the metadata for shared storage budget charging.
-  // This metadata will persist across self navigations, or be replaced by a new
-  // metadata if this gets navigated to another shared storage generated URN.
-  //
-  // This can only be possibly set for the outermost fenced frame root, because
-  // selectURL() is disallowed inside fenced frame, and the URN generated
-  // outside the a fenced frame cannot be recognized from inside, so a nested
-  // fenced frame can never navigate to a shared storage generated URN.
-  //
-  // This metadata is stored to the outermost page's FencedFrameURLMapping, thus
-  // `shared_storage_budget_metadata_` must outlive `this`.
-  raw_ptr<FencedFrameURLMapping::SharedStorageBudgetMetadata>
-      shared_storage_budget_metadata_ = nullptr;
-
   // Manages creation and swapping of RenderFrameHosts for this frame.
   //
   // This field needs to be declared last, because destruction of
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 37434a2..971a14a 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -2053,14 +2053,29 @@
   if (frame_tree_node_->IsFencedFrameRoot()) {
     if (blink::features::IsFencedFramesMPArchBased()) {
       // Once ShadowDOM and loading urns in iframes are disabled, this should
-      // be the only case that remains.
+      // be the only case that remains. The other cases are a bit hacky, but we
+      // expect them to go away soon.
       return is_embedder_initiated_fenced_frame_opaque_url_navigation_;
     } else {
-      return blink::IsValidUrnUuidURL(common_params_->url);
+      // In ShadowDOM, embedder-initiated navigations can take different paths
+      // for local or remote Frames, so we detect it here.
+      // Any urn:uuid navigation is assumed to be initiated by the embedder,
+      // even though we know this is not necessarily the case in ShadowDOM.
+      // But it is true in all intended use cases.
+      is_embedder_initiated_fenced_frame_navigation_ =
+          blink::IsValidUrnUuidURL(common_params_->url);
+      return is_embedder_initiated_fenced_frame_navigation_;
     }
   } else if (!frame_tree_node_->IsMainFrame() &&
              blink::features::IsAllowURNsInIframeEnabled()) {
-    return blink::IsValidUrnUuidURL(common_params_->url);
+    // In iframes, we want to ensure that fenced frame properties are respected
+    // after urn navigations.
+    // Any urn:uuid navigation is assumed to be initiated by the embedder,
+    // even though we know this is not necessarily the case in iframes.
+    // But it is true in all intended use cases.
+    is_embedder_initiated_fenced_frame_navigation_ =
+        blink::IsValidUrnUuidURL(common_params_->url);
+    return is_embedder_initiated_fenced_frame_navigation_;
   }
   return false;
 }
@@ -2071,26 +2086,15 @@
   is_deferred_on_fenced_frame_url_mapping_ = false;
 
   if (properties) {
-    // The URN mapping can happen on regular iframes if the feature
-    // `AllowURNsInIframes` is enabled. We will ignore the leakage via iframe,
-    // and will only track the shared storage budget for fenced frame.
-    if (frame_tree_node_->IsFencedFrameRoot()) {
-      shared_storage_budget_metadata_ =
-          GetFencedFrameURLMap().GetSharedStorageBudgetMetadata(
-              common_params_->url);
-    }
-
-    fenced_frame_properties_ = properties;
     common_params_->url = properties->mapped_url;
     commit_params_->original_url = properties->mapped_url;
-    ad_auction_data_ = properties->ad_auction_data;
     // TODO(crbug/1281643): move into commit_params_->ad_auction_components
     // directly.
-    pending_ad_components_map_ = properties->pending_ad_components_map;
     if (!properties->reporting_metadata.metadata.empty()) {
       commit_params_->fenced_frame_reporting_metadata =
           properties->reporting_metadata.Clone();
     }
+    fenced_frame_properties_ = properties;
   } else {
     if (frame_tree_node_->IsFencedFrameRoot() &&
         frame_tree_node_->frame_tree()->IsFencedFramesMPArchBased()) {
@@ -4948,9 +4952,10 @@
 
   // If this is a result of an ad auction, need to pass its ad component URLs to
   // the renderer.
-  if (pending_ad_components_map_) {
+  if (fenced_frame_properties_ &&
+      fenced_frame_properties_->pending_ad_components_map) {
     commit_params_->ad_auction_components =
-        pending_ad_components_map_->GetURNs();
+        fenced_frame_properties_->pending_ad_components_map->GetURNs();
   }
 
   if (!IsSameDocument()) {
@@ -6114,48 +6119,6 @@
     frame_tree_node()->set_fenced_frame_properties(fenced_frame_properties_);
   }
 
-  // Same-document navigations won't affect budget metadata.
-  if (!DidEncounterError() && !IsSameDocument()) {
-    FencedFrameURLMapping::SharedStorageBudgetMetadata*
-        original_budget_metadata =
-            frame_tree_node()->shared_storage_budget_metadata();
-    if (original_budget_metadata) {
-      // Clear the previous shared_storage_budget_metadata on the
-      // `FrameTreeNode` if this navigation is not initiated from itself. In
-      // this case (including the case when `initiator_render_frame_host` is
-      // gone), this navigation had to be initiated from outside the fenced
-      // frame because a frame inside a fenced frame is not allowed to navigate
-      // ancestors, so the previous knowledge from inside the fenced frame can
-      // never be transferred.
-      RenderFrameHostImpl* initiator_render_frame_host = nullptr;
-      if (GetInitiatorFrameToken()) {
-        initiator_render_frame_host = RenderFrameHostImpl::FromFrameToken(
-            GetInitiatorProcessID(), GetInitiatorFrameToken().value());
-      }
-
-      if (!initiator_render_frame_host ||
-          initiator_render_frame_host->frame_tree_node() !=
-              render_frame_host_->frame_tree_node()) {
-        // The policy of disallowing a frame inside a fenced frame to navigate
-        // ancestors should've already been enforced in BeginNavigation().
-        CHECK(!initiator_render_frame_host ||
-              !initiator_render_frame_host->IsNestedWithinFencedFrame());
-
-        render_frame_host_->frame_tree_node()
-            ->set_shared_storage_budget_metadata(nullptr);
-      }
-    }
-
-    // If this is a load to a new URN, update the shared_storage_budget_metadata
-    // on the `FrameTreeNode`. Note that explicit clearing of budget metadata
-    // above is still needed for cases where a fenced frame is navigated from a
-    // URN to a non-URN URL.
-    if (shared_storage_budget_metadata_) {
-      frame_tree_node()->set_shared_storage_budget_metadata(
-          shared_storage_budget_metadata_);
-    }
-  }
-
   // It should be kept in sync with the check in
   // RenderFrameHostImpl::TakeNewDocumentPropertiesFromNavigation.
   if (DidEncounterError()) {
diff --git a/content/browser/renderer_host/navigation_request.h b/content/browser/renderer_host/navigation_request.h
index e7fd7ab2..569dfb6 100644
--- a/content/browser/renderer_host/navigation_request.h
+++ b/content/browser/renderer_host/navigation_request.h
@@ -928,13 +928,9 @@
     return prerender_frame_tree_node_id_.value();
   }
 
-  const absl::optional<FencedFrameURLMapping::PendingAdComponentsMap>&
-  pending_ad_components_map() const {
-    return pending_ad_components_map_;
-  }
-
-  const absl::optional<AdAuctionData>& ad_auction_data() const {
-    return ad_auction_data_;
+  const absl::optional<FencedFrameURLMapping::FencedFrameProperties>&
+  fenced_frame_properties() const {
+    return fenced_frame_properties_;
   }
 
   void RenderFallbackContentForObjectTag();
@@ -2082,20 +2078,18 @@
   // Indicates that this navigation is for PDF content in a renderer.
   bool is_pdf_ = false;
 
-  // Only for fenced frames based on MPArch:
   // Indicates that this navigation is an embedder-initiated navigation of a
   // fenced frame root. That is to say, the navigation is caused by a `src`
   // attribute mutation on the <fencedframe> element, which cannot be performed
   // from inside the fenced frame tree.
-  const bool is_embedder_initiated_fenced_frame_navigation_ = false;
+  // TODO(crbug.com/1262022): Make this `const` again once ShadowDOM is gone.
+  bool is_embedder_initiated_fenced_frame_navigation_ = false;
 
-  // Only for fenced frames based on MPArch:
   // Indicates that this navigation is to an opaque url (urn:uuid). This value
   // may only be true when `is_embedder_initiated_fenced_frame_navigation` is
   // true.
   const bool is_embedder_initiated_fenced_frame_opaque_url_navigation_ = false;
 
-  // Only for fenced frames based on MPArch:
   // Indicates that the target of this navigation is the root of a fenced frame
   // tree whose most recent embedder-initiated navigation was to an opaque URL
   // (urn:uuid). The most recent navigation may be the current
@@ -2115,27 +2109,6 @@
   absl::optional<FencedFrameURLMapping::FencedFrameProperties>
       fenced_frame_properties_;
 
-  // If this navigation is a load in a fenced frame of a URN URL that resulted
-  // from an interest group auction, this contains some information about the
-  // auction that should be attached to the renderer as AdAuctionDocumentData.
-  absl::optional<AdAuctionData> ad_auction_data_;
-
-  // If this navigation is a load in a fenced frame of a URN URL that resulted
-  // from an interest group auction, this contains the ad component URLs
-  // associated with that auction's winning bid, and the corresponding URNs that
-  // will be mapped to them.
-  absl::optional<FencedFrameURLMapping::PendingAdComponentsMap>
-      pending_ad_components_map_;
-
-  // If this navigation is a load in a fenced frame of a URN URL that resulted
-  // from a shared storage url selection operation, this contains the metadata
-  // for shared storage budget charging. A non-null pointer will stay valid
-  // during the `FencedFrameURLMapping`'s (thus the page's) lifetime, and a page
-  // will outlive any NavigationRequest occurring in fenced frames in the page,
-  // thus it's safe for this NavigationRequest to store this pointer.
-  raw_ptr<FencedFrameURLMapping::SharedStorageBudgetMetadata>
-      shared_storage_budget_metadata_ = nullptr;
-
   // Prerender2:
   // The type to trigger prerendering. The value is valid only when Prerender2
   // is enabled.
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index eae80e3..38e6b7b 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -11789,18 +11789,23 @@
       document_associated_data_.emplace(*this);
     }
 
-    // This may only be done after creating the DocumentAssociatedData for the
-    // new document, if appropriate, since `fenced_frame_urls_map` hangs off of
-    // that.
-    if (navigation_request->pending_ad_components_map()) {
-      navigation_request->pending_ad_components_map()->ExportToMapping(
-          GetPage().fenced_frame_urls_map());
-    }
+    const absl::optional<FencedFrameURLMapping::FencedFrameProperties>&
+        fenced_frame_properties = navigation_request->fenced_frame_properties();
+    if (fenced_frame_properties) {
+      // This may only be done after creating the DocumentAssociatedData for the
+      // new document, if appropriate, since `fenced_frame_urls_map` hangs off
+      // of that.
+      if (fenced_frame_properties->pending_ad_components_map.has_value()) {
+        fenced_frame_properties->pending_ad_components_map->ExportToMapping(
+            GetPage().fenced_frame_urls_map());
+      }
 
-    if (navigation_request->ad_auction_data()) {
-      AdAuctionDocumentData::CreateForCurrentDocument(
-          this, navigation_request->ad_auction_data()->interest_group_owner,
-          navigation_request->ad_auction_data()->interest_group_name);
+      if (fenced_frame_properties->ad_auction_data.has_value()) {
+        AdAuctionDocumentData::CreateForCurrentDocument(
+            this,
+            fenced_frame_properties->ad_auction_data->interest_group_owner,
+            fenced_frame_properties->ad_auction_data->interest_group_name);
+      }
     }
 
     // Continue observing the events for the committed navigation.
diff --git a/content/browser/resources/gpu/OWNERS b/content/browser/resources/gpu/OWNERS
index dc09913..713de61 100644
--- a/content/browser/resources/gpu/OWNERS
+++ b/content/browser/resources/gpu/OWNERS
@@ -1,4 +1,3 @@
-nduca@chromium.org
 kbr@chromium.org
 zmo@chromium.org
 
diff --git a/content/browser/shared_storage/shared_storage_browsertest.cc b/content/browser/shared_storage/shared_storage_browsertest.cc
index af2a82c..8888e932 100644
--- a/content/browser/shared_storage/shared_storage_browsertest.cc
+++ b/content/browser/shared_storage/shared_storage_browsertest.cc
@@ -2392,6 +2392,13 @@
       JsReplace("window.open($1, '_unfencedTop')", new_page_url.spec())));
   top_navigation_observer.Wait();
 
+  // In ShadowDOM, transparent URL navigations don't reset the shared storage
+  // budget metadata for implementation convenience.
+  if (GetParam() ==
+      blink::features::FencedFramesImplementationType::kShadowDOM) {
+    return;
+  }
+
   // No budget withdrawal as the initial fenced frame was navigated away by its
   // parent before it triggers a top navigation.
   EXPECT_DOUBLE_EQ(GetRemainingBudget(shared_storage_origin), kBudgetAllowed);
diff --git a/content/browser/shared_storage/shared_storage_budget_charger.cc b/content/browser/shared_storage/shared_storage_budget_charger.cc
index baad9f0..8b101d3 100644
--- a/content/browser/shared_storage/shared_storage_budget_charger.cc
+++ b/content/browser/shared_storage/shared_storage_budget_charger.cc
@@ -53,22 +53,26 @@
   if (!initiator_frame_host)
     return;
 
-  FencedFrameURLMapping::SharedStorageBudgetMetadata*
+  absl::optional<const FencedFrameURLMapping::SharedStorageBudgetMetadata*>
       shared_storage_budget_metadata = initiator_frame_host->frame_tree_node()
                                            ->FindSharedStorageBudgetMetadata();
 
   // Skip if the initiator frame is not originated from shared storage.
-  if (!shared_storage_budget_metadata)
+  if (!shared_storage_budget_metadata.has_value())
     return;
 
-  if (shared_storage_budget_metadata->budget_to_charge > 0) {
+  if ((*shared_storage_budget_metadata)->budget_to_charge > 0) {
     storage::SharedStorageManager* shared_storage_manager =
         initiator_frame_host->GetStoragePartition()->GetSharedStorageManager();
     shared_storage_manager->MakeBudgetWithdrawal(
-        shared_storage_budget_metadata->origin,
-        shared_storage_budget_metadata->budget_to_charge, base::DoNothing());
+        (*shared_storage_budget_metadata)->origin,
+        (*shared_storage_budget_metadata)->budget_to_charge, base::DoNothing());
 
-    shared_storage_budget_metadata->budget_to_charge = 0;
+    // We only want to charge the budget the first time a navigation leaves the
+    // fenced frame, across all fenced frames navigated to the same urn.
+    // We can do this even though the pointer is const because
+    // `budget_to_charge` is a mutable field of `SharedStorageBudgetMetadata`.
+    (*shared_storage_budget_metadata)->budget_to_charge = 0;
   }
 }
 
diff --git a/content/browser/webid/fake_identity_request_dialog_controller.cc b/content/browser/webid/fake_identity_request_dialog_controller.cc
index c7e6002..ffe27f7f 100644
--- a/content/browser/webid/fake_identity_request_dialog_controller.cc
+++ b/content/browser/webid/fake_identity_request_dialog_controller.cc
@@ -15,13 +15,14 @@
 
 void FakeIdentityRequestDialogController::ShowAccountsDialog(
     content::WebContents* rp_web_contents,
-    const GURL& idp_signin_url,
-    base::span<const IdentityRequestAccount> accounts,
-    const IdentityProviderMetadata& idp_metadata,
-    const ClientIdData& client_id_data,
+    const std::vector<content::IdentityProviderData>& identity_provider_data,
     IdentityRequestAccount::SignInMode sign_in_mode,
     AccountSelectionCallback on_selected,
     DismissCallback dismiss_callback) {
+  // TODO(crbug.com/1348262): Temporarily support only the first IDP, extend to
+  // support multiple IDPs.
+  base::span<const IdentityRequestAccount> accounts =
+      identity_provider_data[0].accounts;
   DCHECK_GT(accounts.size(), 0ul);
   // Use the provided account, if any. Otherwise use the first one.
   std::move(on_selected)
diff --git a/content/browser/webid/fake_identity_request_dialog_controller.h b/content/browser/webid/fake_identity_request_dialog_controller.h
index 907f23e..35489e6 100644
--- a/content/browser/webid/fake_identity_request_dialog_controller.h
+++ b/content/browser/webid/fake_identity_request_dialog_controller.h
@@ -22,14 +22,12 @@
       absl::optional<std::string> selected_account);
   ~FakeIdentityRequestDialogController() override;
 
-  void ShowAccountsDialog(content::WebContents* rp_web_contents,
-                          const GURL& idp_signin_url,
-                          base::span<const IdentityRequestAccount> accounts,
-                          const IdentityProviderMetadata& idp_metadata,
-                          const ClientIdData& client_id_data,
-                          IdentityRequestAccount::SignInMode sign_in_mode,
-                          AccountSelectionCallback on_selected,
-                          DismissCallback dismmiss_callback) override;
+  void ShowAccountsDialog(
+      content::WebContents* rp_web_contents,
+      const std::vector<content::IdentityProviderData>& identity_provider_data,
+      IdentityRequestAccount::SignInMode sign_in_mode,
+      AccountSelectionCallback on_selected,
+      DismissCallback dismmiss_callback) override;
 
  private:
   absl::optional<std::string> selected_account_;
diff --git a/content/browser/webid/federated_auth_request_impl.cc b/content/browser/webid/federated_auth_request_impl.cc
index 26e57f0..527e0bb7 100644
--- a/content/browser/webid/federated_auth_request_impl.cc
+++ b/content/browser/webid/federated_auth_request_impl.cc
@@ -292,7 +292,7 @@
 }
 
 void FederatedAuthRequestImpl::RequestToken(
-    std::vector<blink::mojom::IdentityProviderPtr> identity_provider_ptrs,
+    std::vector<IdentityProviderPtr> identity_provider_ptrs,
     bool prefer_auto_sign_in,
     RequestTokenCallback callback) {
   // TODO(crbug.com/1348262): Temporarily support only the first IDP, extend to
@@ -726,16 +726,21 @@
                              accounts[0].login_state == LoginState::kSignIn &&
                              !screen_reader_is_on;
       // TODO(cbiesinger): Check that the URLs are valid.
-      ClientIdData data{GURL(client_metadata_.terms_of_service_url),
-                        GURL(client_metadata_.privacy_policy_url)};
+      ClientIdData client_id_data{GURL(client_metadata_.terms_of_service_url),
+                                  GURL(client_metadata_.privacy_policy_url)};
 
       show_accounts_dialog_time_ = base::TimeTicks::Now();
       fedcm_metrics_->RecordShowAccountsDialogTime(show_accounts_dialog_time_ -
                                                    start_time_);
 
+      std::vector<IdentityProviderData> identity_providers_data;
+      IdentityProviderData identity_provider_data(
+          identity_provider.config_url, accounts, idp_metadata, client_id_data);
+      identity_providers_data.push_back(identity_provider_data);
+
       request_dialog_controller_->ShowAccountsDialog(
-          rp_web_contents, identity_provider.config_url, accounts, idp_metadata,
-          data, is_auto_sign_in ? SignInMode::kAuto : SignInMode::kExplicit,
+          rp_web_contents, identity_providers_data,
+          is_auto_sign_in ? SignInMode::kAuto : SignInMode::kExplicit,
           base::BindOnce(&FederatedAuthRequestImpl::OnAccountSelected,
                          weak_ptr_factory_.GetWeakPtr(), identity_provider),
           base::BindOnce(&FederatedAuthRequestImpl::OnDialogDismissed,
diff --git a/content/browser/webid/federated_auth_request_impl_unittest.cc b/content/browser/webid/federated_auth_request_impl_unittest.cc
index 48c690a..ff24b54 100644
--- a/content/browser/webid/federated_auth_request_impl_unittest.cc
+++ b/content/browser/webid/federated_auth_request_impl_unittest.cc
@@ -124,11 +124,15 @@
 
 static const std::set<std::string> kManifestList{kProviderUrlFull};
 
-// Parameters for a call to RequestToken.
-struct RequestParameters {
+struct IdentityProviderParameters {
   const char* provider;
   const char* client_id;
   const char* nonce;
+};
+
+// Parameters for a call to RequestToken.
+struct RequestParameters {
+  std::vector<IdentityProviderParameters> identity_providers;
   bool prefer_auto_sign_in;
 };
 
@@ -191,8 +195,12 @@
 static const MockClientIdConfiguration kDefaultClientMetadata{
     FetchStatus::kSuccess, kPrivacyPolicyUrl, kTermsOfServiceUrl};
 
+static const IdentityProviderParameters kDefaultIdentityProvider{
+    kProviderUrlFull, kClientId, kNonce};
+
 static const RequestParameters kDefaultRequestParameters{
-    kProviderUrlFull, kClientId, kNonce, /*prefer_auto_sign_in=*/false};
+    std::vector<IdentityProviderParameters>{kDefaultIdentityProvider},
+    /*prefer_auto_sign_in=*/false};
 
 static const MockConfiguration kConfigurationValid{
     kToken,
@@ -606,10 +614,20 @@
                    const MockConfiguration& configuration) {
     test_network_request_manager_->SetTestConfig(configuration);
     SetMockExpectations(request_parameters, expectation, configuration);
-    auto auth_response = PerformAuthRequest(
-        GURL(request_parameters.provider), request_parameters.client_id,
-        request_parameters.nonce, request_parameters.prefer_auto_sign_in,
-        configuration.wait_for_callback);
+    std::vector<blink::mojom::IdentityProviderPtr> identity_provider_ptrs;
+    for (const auto& identity_provider :
+         request_parameters.identity_providers) {
+      blink::mojom::IdentityProviderPtr identity_provider_ptr =
+          blink::mojom::IdentityProvider::New(GURL(identity_provider.provider),
+                                              identity_provider.client_id,
+                                              identity_provider.nonce);
+      identity_provider_ptrs.push_back(std::move(identity_provider_ptr));
+    }
+
+    auto auth_response =
+        PerformAuthRequest(std::move(identity_provider_ptrs),
+                           request_parameters.prefer_auto_sign_in,
+                           configuration.wait_for_callback);
     ASSERT_EQ(auth_response.first, expectation.return_status);
     if (auth_response.first == RequestTokenStatus::kSuccess) {
       EXPECT_EQ(configuration.token, auth_response.second);
@@ -695,16 +713,10 @@
   }
 
   std::pair<absl::optional<RequestTokenStatus>, absl::optional<std::string>>
-  PerformAuthRequest(const GURL& provider,
-                     const std::string& client_id,
-                     const std::string& nonce,
-                     bool prefer_auto_sign_in,
-                     bool wait_for_callback) {
-    std::vector<blink::mojom::IdentityProviderPtr> identity_provider_ptrs;
-    blink::mojom::IdentityProviderPtr identity_provider_ptr =
-        blink::mojom::IdentityProvider::New(provider, client_id, nonce);
-    identity_provider_ptrs.push_back(std::move(identity_provider_ptr));
-
+  PerformAuthRequest(
+      std::vector<blink::mojom::IdentityProviderPtr> identity_provider_ptrs,
+      bool prefer_auto_sign_in,
+      bool wait_for_callback) {
     request_remote_->RequestToken(std::move(identity_provider_ptrs),
                                   prefer_auto_sign_in, auth_helper_.callback());
 
@@ -746,18 +758,18 @@
         // even though the bit is set we may not exercise the AutoSignIn flow.
         // e.g. for sign up flow, multiple accounts, user opt-out etc. In this
         // case, it's up to the test to expect this mock function call.
-        EXPECT_CALL(*mock_dialog_controller_,
-                    ShowAccountsDialog(_, _, _, _, _, _, _, _))
+        EXPECT_CALL(*mock_dialog_controller_, ShowAccountsDialog(_, _, _, _, _))
             .WillOnce(Invoke(
                 [&](content::WebContents* rp_web_contents,
-                    const GURL& idp_signin_url,
-                    base::span<const content::IdentityRequestAccount> accounts,
-                    const IdentityProviderMetadata& idp_metadata,
-                    const ClientIdData& client_id_data, SignInMode sign_in_mode,
+                    const std::vector<IdentityProviderData>&
+                        identity_provider_data,
+                    SignInMode sign_in_mode,
                     IdentityRequestDialogController::AccountSelectionCallback
                         on_selected,
                     IdentityRequestDialogController::DismissCallback
                         dismiss_callback) {
+                  base::span<const content::IdentityRequestAccount> accounts =
+                      identity_provider_data[0].accounts;
                   displayed_accounts_ =
                       AccountList(accounts.begin(), accounts.end());
                   base::SequencedTaskRunnerHandle::Get()->PostTask(
@@ -768,8 +780,7 @@
                 }));
       }
     } else {
-      EXPECT_CALL(*mock_dialog_controller_,
-                  ShowAccountsDialog(_, _, _, _, _, _, _, _))
+      EXPECT_CALL(*mock_dialog_controller_, ShowAccountsDialog(_, _, _, _, _))
           .Times(0);
     }
   }
@@ -927,8 +938,9 @@
   // to IdpNetworkRequestManager methods.
   std::unique_ptr<IdpNetworkRequestManagerParamChecker> checker =
       std::make_unique<IdpNetworkRequestManagerParamChecker>();
-  checker->SetExpectations(kDefaultRequestParameters.client_id,
-                           kConfigurationValid.accounts[0].id);
+  checker->SetExpectations(
+      kDefaultRequestParameters.identity_providers[0].client_id,
+      kConfigurationValid.accounts[0].id);
   SetNetworkRequestManager(std::move(checker));
 
   RunAuthTest(kDefaultRequestParameters, kExpectationSuccess,
@@ -944,8 +956,9 @@
   // to IdpNetworkRequestManager methods.
   std::unique_ptr<IdpNetworkRequestManagerParamChecker> checker =
       std::make_unique<IdpNetworkRequestManagerParamChecker>();
-  checker->SetExpectations(kDefaultRequestParameters.client_id,
-                           kConfigurationValid.accounts[0].id);
+  checker->SetExpectations(
+      kDefaultRequestParameters.identity_providers[0].client_id,
+      kConfigurationValid.accounts[0].id);
   SetNetworkRequestManager(std::move(checker));
 
   RunAuthTest(kDefaultRequestParameters, kExpectationSuccess,
@@ -962,8 +975,11 @@
       FederatedAuthRequestResult::kErrorManifestNotInManifestList,
       FetchedEndpoint::MANIFEST_LIST | FetchedEndpoint::MANIFEST};
 
-  RequestParameters parameters{"https://not-in-list.example", kClientId, kNonce,
-                               /*prefer_auto_sign_in=*/false};
+  IdentityProviderParameters identity_provider{"https://not-in-list.example",
+                                               kClientId, kNonce};
+  RequestParameters parameters{
+      std::vector<IdentityProviderParameters>{identity_provider},
+      /*prefer_auto_sign_in=*/false};
   RunAuthTest(parameters, request_not_in_list, kConfigurationValid);
 }
 
@@ -972,8 +988,11 @@
   base::test::ScopedFeatureList list;
   list.InitAndEnableFeature(features::kFedCmManifestValidation);
 
-  RequestParameters parameters{"https://idp.example/foo", kClientId, kNonce,
-                               /*prefer_auto_sign_in=*/false};
+  IdentityProviderParameters identity_provider{"https://idp.example/foo",
+                                               kClientId, kNonce};
+  RequestParameters parameters{
+      std::vector<IdentityProviderParameters>{identity_provider},
+      /*prefer_auto_sign_in=*/false};
   MockConfiguration config{kConfigurationValid};
   config.manifest_list.provider_urls =
       std::set<std::string>{GURL(kProviderUrlFull).GetWithoutFilename().spec()};
@@ -1051,8 +1070,11 @@
 
 // Test that request fails if the idp is not https.
 TEST_F(FederatedAuthRequestImplTest, ProviderNotTrustworthy) {
-  RequestParameters request = kDefaultRequestParameters;
-  request.provider = "http://idp.example/fedcm.json";
+  IdentityProviderParameters identity_provider{"http://idp.example/fedcm.json",
+                                               kClientId, kNonce};
+  RequestParameters request{
+      std::vector<IdentityProviderParameters>{identity_provider},
+      /*prefer_auto_sign_in=*/false};
   MockConfiguration configuration = kConfigurationValid;
   RequestExpectations expectations = {RequestTokenStatus::kError,
                                       FederatedAuthRequestResult::kError,
@@ -1264,18 +1286,18 @@
                            OriginFromString(kProviderUrlFull), kAccountId))
       .WillOnce(Return(true));
 
-  EXPECT_CALL(*mock_dialog_controller(),
-              ShowAccountsDialog(_, _, _, _, _, _, _, _))
+  EXPECT_CALL(*mock_dialog_controller(), ShowAccountsDialog(_, _, _, _, _))
       .WillOnce(Invoke(
-          [&](content::WebContents* rp_web_contents, const GURL& idp_signin_url,
-              base::span<const content::IdentityRequestAccount> accounts,
-              const IdentityProviderMetadata& idp_metadata,
-              const ClientIdData& client_id_data, SignInMode sign_in_mode,
+          [&](content::WebContents* rp_web_contents,
+              const std::vector<IdentityProviderData>& identity_provider_data,
+              SignInMode sign_in_mode,
               IdentityRequestDialogController::AccountSelectionCallback
                   on_selected,
               IdentityRequestDialogController::DismissCallback
                   dismiss_callback) {
             EXPECT_EQ(sign_in_mode, SignInMode::kAuto);
+            base::span<const content::IdentityRequestAccount> accounts =
+                identity_provider_data[0].accounts;
             displayed_accounts = AccountList(accounts.begin(), accounts.end());
             std::move(on_selected).Run(accounts[0].id, /*is_sign_in=*/true);
           }));
@@ -1296,18 +1318,18 @@
       {{features::kFedCmAutoSigninFieldTrialParamName, "true"}});
 
   AccountList displayed_accounts;
-  EXPECT_CALL(*mock_dialog_controller(),
-              ShowAccountsDialog(_, _, _, _, _, _, _, _))
+  EXPECT_CALL(*mock_dialog_controller(), ShowAccountsDialog(_, _, _, _, _))
       .WillOnce(Invoke(
-          [&](content::WebContents* rp_web_contents, const GURL& idp_signin_url,
-              base::span<const content::IdentityRequestAccount> accounts,
-              const IdentityProviderMetadata& idp_metadata,
-              const ClientIdData& client_id_data, SignInMode sign_in_mode,
+          [&](content::WebContents* rp_web_contents,
+              const std::vector<IdentityProviderData>& identity_provider_data,
+              SignInMode sign_in_mode,
               IdentityRequestDialogController::AccountSelectionCallback
                   on_selected,
               IdentityRequestDialogController::DismissCallback
                   dismiss_callback) {
             EXPECT_EQ(sign_in_mode, SignInMode::kExplicit);
+            base::span<const content::IdentityRequestAccount> accounts =
+                identity_provider_data[0].accounts;
             displayed_accounts = AccountList(accounts.begin(), accounts.end());
             std::move(on_selected).Run(accounts[0].id, /*is_sign_in=*/true);
           }));
@@ -1338,19 +1360,19 @@
                            OriginFromString(kProviderUrlFull), kAccountId))
       .WillOnce(Return(true));
 
-  EXPECT_CALL(*mock_dialog_controller(),
-              ShowAccountsDialog(_, _, _, _, _, _, _, _))
+  EXPECT_CALL(*mock_dialog_controller(), ShowAccountsDialog(_, _, _, _, _))
       .WillOnce(Invoke(
-          [&](content::WebContents* rp_web_contents, const GURL& idp_signin_url,
-              base::span<const content::IdentityRequestAccount> accounts,
-              const IdentityProviderMetadata& idp_metadata,
-              const ClientIdData& client_id_data, SignInMode sign_in_mode,
+          [&](content::WebContents* rp_web_contents,
+              const std::vector<IdentityProviderData>& identity_provider_data,
+              SignInMode sign_in_mode,
               IdentityRequestDialogController::AccountSelectionCallback
                   on_selected,
               IdentityRequestDialogController::DismissCallback
                   dismiss_callback) {
             // Auto sign in replaced by explicit sign in if screen reader is on.
             EXPECT_EQ(sign_in_mode, SignInMode::kExplicit);
+            base::span<const content::IdentityRequestAccount> accounts =
+                identity_provider_data[0].accounts;
             displayed_accounts = AccountList(accounts.begin(), accounts.end());
             std::move(on_selected).Run(accounts[0].id, /*is_sign_in=*/true);
           }));
@@ -1408,17 +1430,17 @@
   base::HistogramTester histogram_tester_;
 
   AccountList displayed_accounts;
-  EXPECT_CALL(*mock_dialog_controller(),
-              ShowAccountsDialog(_, _, _, _, _, _, _, _))
+  EXPECT_CALL(*mock_dialog_controller(), ShowAccountsDialog(_, _, _, _, _))
       .WillOnce(Invoke(
-          [&](content::WebContents* rp_web_contents, const GURL& idp_signin_url,
-              base::span<const content::IdentityRequestAccount> accounts,
-              const IdentityProviderMetadata& idp_metadata,
-              const ClientIdData& client_id_data, SignInMode sign_in_mode,
+          [&](content::WebContents* rp_web_contents,
+              const std::vector<IdentityProviderData>& identity_provider_data,
+              SignInMode sign_in_mode,
               IdentityRequestDialogController::AccountSelectionCallback
                   on_selected,
               IdentityRequestDialogController::DismissCallback
                   dismiss_callback) {
+            base::span<const content::IdentityRequestAccount> accounts =
+                identity_provider_data[0].accounts;
             displayed_accounts = AccountList(accounts.begin(), accounts.end());
             // Pretends that the user did not select any account.
             std::move(dismiss_callback).Run(DismissReason::CLOSE_BUTTON);
@@ -1470,17 +1492,17 @@
   EXPECT_CALL(*mock_dialog_controller(), DestructorCalled()).Times(0);
 
   AccountList displayed_accounts;
-  EXPECT_CALL(*mock_dialog_controller(),
-              ShowAccountsDialog(_, _, _, _, _, _, _, _))
+  EXPECT_CALL(*mock_dialog_controller(), ShowAccountsDialog(_, _, _, _, _))
       .WillOnce(Invoke(
-          [&](content::WebContents* rp_web_contents, const GURL& idp_signin_url,
-              base::span<const content::IdentityRequestAccount> accounts,
-              const IdentityProviderMetadata& idp_metadata,
-              const ClientIdData& client_id_data, SignInMode sign_in_mode,
+          [&](content::WebContents* rp_web_contents,
+              const std::vector<IdentityProviderData>& identity_provider_data,
+              SignInMode sign_in_mode,
               IdentityRequestDialogController::AccountSelectionCallback
                   on_selected,
               IdentityRequestDialogController::DismissCallback
                   dismiss_callback) {
+            base::span<const content::IdentityRequestAccount> accounts =
+                identity_provider_data[0].accounts;
             displayed_accounts = AccountList(accounts.begin(), accounts.end());
             // Pretends that the user ignored the UI by not selecting an
             // account.
@@ -1760,17 +1782,17 @@
   MockConfiguration configuration = kConfigurationValid;
   configuration.customized_dialog = true;
 
-  EXPECT_CALL(*mock_dialog_controller(),
-              ShowAccountsDialog(_, _, _, _, _, _, _, _))
+  EXPECT_CALL(*mock_dialog_controller(), ShowAccountsDialog(_, _, _, _, _))
       .WillOnce(Invoke(
-          [&](content::WebContents* rp_web_contents, const GURL& idp_signin_url,
-              base::span<const content::IdentityRequestAccount> accounts,
-              const IdentityProviderMetadata& idp_metadata,
-              const ClientIdData& client_id_data, SignInMode sign_in_mode,
+          [&](content::WebContents* rp_web_contents,
+              const std::vector<IdentityProviderData>& identity_provider_data,
+              SignInMode sign_in_mode,
               IdentityRequestDialogController::AccountSelectionCallback
                   on_selected,
               IdentityRequestDialogController::DismissCallback
                   dismiss_callback) {
+            base::span<const content::IdentityRequestAccount> accounts =
+                identity_provider_data[0].accounts;
             displayed_accounts_ = AccountList(accounts.begin(), accounts.end());
             std::move(dismiss_callback).Run(DismissReason::CLOSE_BUTTON);
           }));
@@ -1857,13 +1879,11 @@
 TEST_F(FederatedAuthRequestImplTest, ApiDisabledAfterAccountsDialogShown) {
   base::HistogramTester histogram_tester_;
 
-  EXPECT_CALL(*mock_dialog_controller(),
-              ShowAccountsDialog(_, _, _, _, _, _, _, _))
+  EXPECT_CALL(*mock_dialog_controller(), ShowAccountsDialog(_, _, _, _, _))
       .WillOnce(Invoke(
-          [&](content::WebContents* rp_web_contents, const GURL& idp_signin_url,
-              base::span<const content::IdentityRequestAccount> accounts,
-              const IdentityProviderMetadata& idp_metadata,
-              const ClientIdData& client_id_data, SignInMode sign_in_mode,
+          [&](content::WebContents* rp_web_contents,
+              const std::vector<IdentityProviderData>& identity_provider_data,
+              SignInMode sign_in_mode,
               IdentityRequestDialogController::AccountSelectionCallback
                   on_selected,
               IdentityRequestDialogController::DismissCallback
@@ -1873,6 +1893,8 @@
                 std::make_pair(main_test_rfh()->GetLastCommittedOrigin(),
                                ApiPermissionStatus::BLOCKED_SETTINGS);
 
+            base::span<const content::IdentityRequestAccount> accounts =
+                identity_provider_data[0].accounts;
             std::move(on_selected).Run(accounts[0].id, /*is_sign_in=*/false);
           }));
 
@@ -2010,8 +2032,7 @@
       std::make_unique<IdpNetworkRequestManagerAccountListTaskRunner>(
           base::BindOnce(&NavigateToUrl, web_contents(), GURL(kRpOtherUrl))));
 
-  EXPECT_CALL(*mock_dialog_controller_,
-              ShowAccountsDialog(_, _, _, _, _, _, _, _))
+  EXPECT_CALL(*mock_dialog_controller_, ShowAccountsDialog(_, _, _, _, _))
       .Times(0);
   MockConfiguration configuration = kConfigurationValid;
   configuration.customized_dialog = true;
@@ -2036,8 +2057,7 @@
       std::make_unique<IdpNetworkRequestManagerAccountListTaskRunner>(
           base::BindOnce(&NavigateToUrl, web_contents(), GURL(kRpOtherUrl))));
 
-  EXPECT_CALL(*mock_dialog_controller_,
-              ShowAccountsDialog(_, _, _, _, _, _, _, _))
+  EXPECT_CALL(*mock_dialog_controller_, ShowAccountsDialog(_, _, _, _, _))
       .Times(0);
   MockConfiguration configuration = kConfigurationValid;
   configuration.customized_dialog = true;
diff --git a/content/browser/webid/test/mock_identity_request_dialog_controller.h b/content/browser/webid/test/mock_identity_request_dialog_controller.h
index c813b4ac..2cfc527 100644
--- a/content/browser/webid/test/mock_identity_request_dialog_controller.h
+++ b/content/browser/webid/test/mock_identity_request_dialog_controller.h
@@ -24,12 +24,9 @@
   MockIdentityRequestDialogController& operator=(
       const MockIdentityRequestDialogController&) = delete;
 
-  MOCK_METHOD8(ShowAccountsDialog,
+  MOCK_METHOD5(ShowAccountsDialog,
                void(WebContents*,
-                    const GURL&,
-                    base::span<const content::IdentityRequestAccount> accounts,
-                    const IdentityProviderMetadata&,
-                    const ClientIdData&,
+                    const std::vector<content::IdentityProviderData>&,
                     IdentityRequestAccount::SignInMode,
                     AccountSelectionCallback,
                     DismissCallback));
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityState.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityState.java
index eb267ba9..13fac305 100644
--- a/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityState.java
+++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityState.java
@@ -200,6 +200,7 @@
         ArrayList<String> runningServiceNames = new ArrayList<String>();
         int i = 0;
         for (AccessibilityServiceInfo service : services) {
+            if (service == null) continue;
             sEventTypeMask |= service.eventTypes;
             sFeedbackTypeMask |= service.feedbackType;
             sFlagsMask |= service.flags;
diff --git a/content/public/browser/identity_request_dialog_controller.cc b/content/public/browser/identity_request_dialog_controller.cc
index 25868cd..e48ef322 100644
--- a/content/public/browser/identity_request_dialog_controller.cc
+++ b/content/public/browser/identity_request_dialog_controller.cc
@@ -50,6 +50,20 @@
 IdentityProviderMetadata::IdentityProviderMetadata(
     const IdentityProviderMetadata& other) = default;
 
+IdentityProviderData::IdentityProviderData(
+    const GURL& idp_config_url,
+    base::span<const IdentityRequestAccount> accounts,
+    const IdentityProviderMetadata& idp_metadata,
+    const ClientIdData& client_id_data)
+    : idp_config_url{idp_config_url},
+      accounts{accounts},
+      idp_metadata{idp_metadata},
+      client_id_data{client_id_data} {}
+
+IdentityProviderData::IdentityProviderData(const IdentityProviderData& other) =
+    default;
+IdentityProviderData::~IdentityProviderData() = default;
+
 int IdentityRequestDialogController::GetBrandIconIdealSize() {
   return 0;
 }
@@ -60,10 +74,7 @@
 
 void IdentityRequestDialogController::ShowAccountsDialog(
     content::WebContents* rp_web_contents,
-    const GURL& idp_signin_url,
-    base::span<const IdentityRequestAccount> accounts,
-    const IdentityProviderMetadata& idp_metadata,
-    const ClientIdData& client_id_data,
+    const std::vector<IdentityProviderData>& identity_provider_data,
     IdentityRequestAccount::SignInMode sign_in_mode,
     AccountSelectionCallback on_selected,
     DismissCallback dismiss_callback) {
diff --git a/content/public/browser/identity_request_dialog_controller.h b/content/public/browser/identity_request_dialog_controller.h
index 77c669f..e022ffd 100644
--- a/content/public/browser/identity_request_dialog_controller.h
+++ b/content/public/browser/identity_request_dialog_controller.h
@@ -84,6 +84,20 @@
   GURL brand_icon_url;
 };
 
+struct CONTENT_EXPORT IdentityProviderData {
+  IdentityProviderData(const GURL& idp_config_url,
+                       base::span<const IdentityRequestAccount> accounts,
+                       const IdentityProviderMetadata& idp_metadata,
+                       const ClientIdData& client_id_data);
+  IdentityProviderData(const IdentityProviderData& other);
+  ~IdentityProviderData();
+
+  GURL idp_config_url;
+  base::span<const IdentityRequestAccount> accounts;
+  IdentityProviderMetadata idp_metadata;
+  ClientIdData client_id_data;
+};
+
 // IdentityRequestDialogController is in interface for control of the UI
 // surfaces that are displayed to intermediate the exchange of ID tokens.
 class CONTENT_EXPORT IdentityRequestDialogController {
@@ -129,10 +143,7 @@
   // |sign_in_mode| represents whether this is an auto sign in flow.
   virtual void ShowAccountsDialog(
       content::WebContents* rp_web_contents,
-      const GURL& idp_signin_url,
-      base::span<const IdentityRequestAccount> accounts,
-      const IdentityProviderMetadata& idp_metadata,
-      const ClientIdData& client_id_data,
+      const std::vector<IdentityProviderData>& identity_provider_data,
       IdentityRequestAccount::SignInMode sign_in_mode,
       AccountSelectionCallback on_selected,
       DismissCallback dismiss_callback);
diff --git a/content/test/data/accessibility/aria/aria-description-expected-mac.txt b/content/test/data/accessibility/aria/aria-description-expected-mac.txt
new file mode 100644
index 0000000..6eaf489
--- /dev/null
+++ b/content/test/data/accessibility/aria/aria-description-expected-mac.txt
@@ -0,0 +1,5 @@
+AXWebArea
+++AXGroup AXDescription='description' AXHelp='Text-description'
+++AXGroup AXDescription='both' AXHelp='Description from describedby'
+++AXGroup AXSubrole=AXUserInterfaceTooltip AXTitle='Description from describedby'
+++++AXStaticText AXValue='Description from describedby'
diff --git a/content/test/data/accessibility/aria/aria-description.html b/content/test/data/accessibility/aria/aria-description.html
index d83d35c0..9cf0010 100644
--- a/content/test/data/accessibility/aria/aria-description.html
+++ b/content/test/data/accessibility/aria/aria-description.html
@@ -3,6 +3,7 @@
 @BLINK-ALLOW:desc*
 @WIN-ALLOW:desc*
 @AURALINUX-ALLOW:desc*
+@MAC-ALLOW:AXHelp*
 -->
 <!--
 Note, in the IA2/ATK output, the description property and object attribute are different.
diff --git a/extensions/browser/api/media_perception_private/OWNERS b/extensions/browser/api/media_perception_private/OWNERS
index f55ea18..d063efc 100644
--- a/extensions/browser/api/media_perception_private/OWNERS
+++ b/extensions/browser/api/media_perception_private/OWNERS
@@ -1,2 +1 @@
-lasoren@chromium.org
 tbarzic@chromium.org
diff --git a/gpu/command_buffer/OWNERS b/gpu/command_buffer/OWNERS
index a9bdcc7..aad54b3 100644
--- a/gpu/command_buffer/OWNERS
+++ b/gpu/command_buffer/OWNERS
@@ -2,7 +2,6 @@
 geofflang@chromium.org
 vmiura@chromium.org
 zmo@chromium.org
-jdarpinian@chromium.org
 
 # GPU memory buffer tests.
 per-file *gpu_memory_buffer*=dcastagna@chromium.org
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc
index 89fb5f2..fbaf589 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc
@@ -554,17 +554,11 @@
 bool D3DImageBackingFactory::CanImportGpuMemoryBuffer(
     gfx::GpuMemoryBufferType gmb_type,
     viz::ResourceFormat format) {
-  if (gmb_type == gfx::DXGI_SHARED_HANDLE) {
-    // If we had gfx::BufferFormat in IsSupported() we could verify it will work
-    // with GetDXGIFormat().
-    return true;
-  } else if (gmb_type == gfx::SHARED_MEMORY_BUFFER) {
-    // YUV_420_BIPLANAR will end up as RED_8 for Y and RG_88 for UV planes.
-    return format == viz::YUV_420_BIPLANAR ||
-           GetSupportedRGBAFormat(format).has_value();
-  }
-
-  return false;
+  return gmb_type == gfx::DXGI_SHARED_HANDLE ||
+         // Only allow single NV12 shared memory GMBs for now. This excludes
+         // dual shared memory GMBs used by software video decoder.
+         (gmb_type == gfx::SHARED_MEMORY_BUFFER &&
+          format == viz::YUV_420_BIPLANAR);
 }
 
 bool D3DImageBackingFactory::IsSupported(uint32_t usage,
diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc
index 802930a..fa3a5e3 100644
--- a/gpu/ipc/in_process_command_buffer.cc
+++ b/gpu/ipc/in_process_command_buffer.cc
@@ -332,47 +332,11 @@
     }
     decoder_ = std::move(webgpu_decoder);
   } else {
-    // TODO(khushalsagar): A lot of this initialization code is duplicated in
-    // GpuChannelManager. Pull it into a common util method.
-    scoped_refptr<gl::GLContext> real_context =
-        use_virtualized_gl_context_ ? gl_share_group_->shared_context()
-                                    : nullptr;
-    if (real_context &&
-        (!real_context->MakeCurrent(surface_.get()) ||
-         real_context->CheckStickyGraphicsResetStatus() != GL_NO_ERROR)) {
-      real_context = nullptr;
-    }
-    if (!real_context) {
-      real_context = gl::init::CreateGLContext(
-          gl_share_group_.get(), surface_.get(),
-          GenerateGLContextAttribs(params.attribs, context_group_.get()));
-      if (!real_context) {
-        // TODO(piman): This might not be fatal, we could recurse into
-        // CreateGLContext to get more info, tho it should be exceedingly
-        // rare and may not be recoverable anyway.
-        DestroyOnGpuThread();
-        LOG(ERROR) << "ContextResult::kFatalFailure: "
-                      "Failed to create shared context for virtualization.";
-        return gpu::ContextResult::kFatalFailure;
-      }
-      // Ensure that context creation did not lose track of the intended share
-      // group.
-      DCHECK(real_context->share_group() == gl_share_group_.get());
-      task_executor_->gpu_feature_info().ApplyToGLContext(real_context.get());
-
-      if (use_virtualized_gl_context_)
-        gl_share_group_->SetSharedContext(real_context.get());
-    }
-
-    if (!real_context->MakeCurrent(surface_.get())) {
-      LOG(ERROR)
-          << "ContextResult::kTransientFailure, failed to make context current";
-      DestroyOnGpuThread();
-      return ContextResult::kTransientFailure;
-    }
-
     if (params.attribs.enable_raster_interface &&
         !params.attribs.enable_gles2_interface) {
+      // RasterDecoder uses the shared context.
+      use_virtualized_gl_context_ = false;
+
       gr_shader_cache_ = params.gr_shader_cache;
 
       if (!context_state_ ||
@@ -396,6 +360,45 @@
           task_executor_->shared_image_manager(), params.image_factory,
           context_state_, true /*is_privileged*/));
     } else {
+      // TODO(khushalsagar): A lot of this initialization code is duplicated in
+      // GpuChannelManager. Pull it into a common util method.
+      scoped_refptr<gl::GLContext> real_context =
+          use_virtualized_gl_context_ ? gl_share_group_->shared_context()
+                                      : nullptr;
+      if (real_context &&
+          (!real_context->MakeCurrent(surface_.get()) ||
+           real_context->CheckStickyGraphicsResetStatus() != GL_NO_ERROR)) {
+        real_context = nullptr;
+      }
+      if (!real_context) {
+        real_context = gl::init::CreateGLContext(
+            gl_share_group_.get(), surface_.get(),
+            GenerateGLContextAttribs(params.attribs, context_group_.get()));
+        if (!real_context) {
+          // TODO(piman): This might not be fatal, we could recurse into
+          // CreateGLContext to get more info, tho it should be exceedingly
+          // rare and may not be recoverable anyway.
+          DestroyOnGpuThread();
+          LOG(ERROR) << "ContextResult::kFatalFailure: "
+                        "Failed to create shared context for virtualization.";
+          return gpu::ContextResult::kFatalFailure;
+        }
+        // Ensure that context creation did not lose track of the intended share
+        // group.
+        DCHECK(real_context->share_group() == gl_share_group_.get());
+        task_executor_->gpu_feature_info().ApplyToGLContext(real_context.get());
+
+        if (use_virtualized_gl_context_)
+          gl_share_group_->SetSharedContext(real_context.get());
+      }
+
+      if (!real_context->MakeCurrent(surface_.get())) {
+        LOG(ERROR) << "ContextResult::kTransientFailure, failed to make "
+                      "context current";
+        DestroyOnGpuThread();
+        return ContextResult::kTransientFailure;
+      }
+
       decoder_.reset(gles2::GLES2Decoder::Create(this, command_buffer_.get(),
                                                  task_executor_->outputter(),
                                                  context_group_.get()));
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.fuchsia.star b/infra/config/subprojects/chromium/try/tryserver.chromium.fuchsia.star
index f79aafab..72f6d86 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.fuchsia.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.fuchsia.star
@@ -47,7 +47,7 @@
     name = "fuchsia-binary-size",
     branch_selector = branches.FUCHSIA_LTS_MILESTONE,
     builderless = not settings.is_main,
-    cores = 16,
+    cores = 16 if settings.is_main else 8,
     executable = "recipe:binary_size_fuchsia_trybot",
     goma_jobs = goma.jobs.J150,
     properties = {
diff --git a/infra/orchestrator/BUILD.gn b/infra/orchestrator/BUILD.gn
index 5c6b2dc..e86122955 100644
--- a/infra/orchestrator/BUILD.gn
+++ b/infra/orchestrator/BUILD.gn
@@ -28,6 +28,10 @@
     # the root vpython spec files.
     "//.vpython3",
 
+    # Used if the orchestrator needs to run recipe_module.chromium.get_version()
+    # to get the Chrome milestone being tested.
+    "//chrome/VERSION",
+
     # Test specs the Orchestrator needs to trigger swarming tests
     "//testing/buildbot/*.json",
   ]
@@ -80,7 +84,7 @@
   # them, build/print_python_deps.py doesn't detect them. So to appease
   # telemetry, just add the needed dirs directly.
   data = [
-      "//third_party/catapult/telemetry/third_party/",
-      "//third_party/catapult/third_party/six/",
+    "//third_party/catapult/telemetry/third_party/",
+    "//third_party/catapult/third_party/six/",
   ]
 }
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index bb46624..73d33ab7 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -869,16 +869,30 @@
 
 - (void)initializePrefObservers {
   // Track changes to local state prefs.
-  _localStatePrefChangeRegistrar.Init(GetApplicationContext()->GetLocalState());
+  PrefService* localState = GetApplicationContext()->GetLocalState();
+  _localStatePrefChangeRegistrar.Init(localState);
   _localStatePrefObserverBridge = std::make_unique<PrefObserverBridge>(self);
   _localStatePrefObserverBridge->ObserveChangesForPreference(
       metrics::prefs::kMetricsReportingEnabled,
       &_localStatePrefChangeRegistrar);
 
-  // Calls the onPreferenceChanged function in case there was
-  // a change to the observed preferences before the observer
-  // bridge was set up.
-  [self onPreferenceChanged:metrics::prefs::kMetricsReportingEnabled];
+  // Calls the onPreferenceChanged function in case there was a change to the
+  // observed preferences before the observer bridge was set up. However, if the
+  // metrics reporting pref is still unset (has default value), then do not
+  // call. This likely means that the user is still on the welcome screen during
+  // the first run experience (FRE), and calling onPreferenceChanged here would
+  // clear the provisional client ID (in
+  // MetricsMediator::updateMetricsPrefsOnPermissionChange). The provisional
+  // client ID is crucial for field trial assignment consistency between the
+  // first session and follow-up sessions, and is promoted to be the real client
+  // ID if the user enables metrics reporting in the FRE. Otherwise, it is
+  // discarded, as would happen here if onPreferenceChanged was called while the
+  // user was still on the welcome screen and did yet enable/disable metrics
+  // reporting.
+  if (!localState->FindPreference(metrics::prefs::kMetricsReportingEnabled)
+           ->IsDefaultValue()) {
+    [self onPreferenceChanged:metrics::prefs::kMetricsReportingEnabled];
+  }
 
   // Track changes to default search engine.
   TemplateURLService* service =
diff --git a/ios/chrome/browser/ui/autofill/BUILD.gn b/ios/chrome/browser/ui/autofill/BUILD.gn
index 3d4acdb..207182d4 100644
--- a/ios/chrome/browser/ui/autofill/BUILD.gn
+++ b/ios/chrome/browser/ui/autofill/BUILD.gn
@@ -85,6 +85,7 @@
     "//base",
     "//components/autofill/core/browser",
     "//components/strings",
+    "//ios/chrome/browser/net:crurl",
     "//ios/chrome/browser/ui/autofill/cells",
     "//ios/chrome/browser/ui/collection_view/cells",
     "//ios/chrome/browser/ui/list_model",
@@ -95,6 +96,7 @@
     "//ios/third_party/material_components_ios",
     "//ios/web",
     "//ui/base",
+    "//url",
   ]
   public_deps = [
     "//ios/chrome/browser/ui/collection_view",
diff --git a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_controller.mm b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_controller.mm
index e8600cc6..11807ee 100644
--- a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_controller.mm
+++ b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_controller.mm
@@ -4,14 +4,21 @@
 
 #import "ios/chrome/browser/ui/autofill/card_unmask_prompt_view_controller.h"
 
+#import "base/mac/foundation_util.h"
 #import "base/strings/sys_string_conversions.h"
 #import "components/autofill/core/browser/ui/payments/card_unmask_prompt_controller.h"
 #import "components/strings/grit/components_strings.h"
+#import "ios/chrome/browser/net/crurl.h"
 #import "ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.h"
 #import "ios/chrome/browser/ui/autofill/cells/cvc_header_item.h"
+#import "ios/chrome/browser/ui/table_view/cells/table_view_link_header_footer_item.h"
+#import "ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.h"
+#import "ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item_delegate.h"
 #import "ios/chrome/browser/ui/table_view/table_view_utils.h"
+#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
 #import "ui/base/l10n/l10n_util.h"
+#import "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -23,21 +30,42 @@
 namespace {
 
 typedef NS_ENUM(NSInteger, SectionIdentifier) {
-  SectionIdentifierMain = kSectionIdentifierEnumZero,
+  SectionIdentifierHeader = kSectionIdentifierEnumZero,
+  SectionIdentifierInputs,
 };
 
 typedef NS_ENUM(NSInteger, ItemType) {
   ItemTypeHeader = kItemTypeEnumZero,
+  ItemTypeCVCInput,
+  ItemTypeFooter,
 };
 
+// Empty space on top of the input section. This value added up to the gPay
+// badge bottom padding achieves the mock's vertical spacing between the gPay
+// badge in the header.
+const CGFloat kInputsSectionTopSpacing = 18;
+// When the inputs section doesn't display a footer, an empty one is displayed
+// with this height to provide spacing to the bottom of the tableView.
+const CGFloat kEmptyFooterHeight = 10;
+// Estimated height of the header/footer, used to speed the constraints.
+const CGFloat kEstimatedHeaderFooterHeight = 50;
+// Dummy URL used as target of the link in the footer.
+const char kFooterDummyLinkTarget[] = "about:blank";
+
 }  // namespace
 
-@interface CardUnmaskPromptViewController () {
+@interface CardUnmaskPromptViewController () <
+    TableViewTextEditItemDelegate,
+    TableViewLinkHeaderFooterItemDelegate> {
   // Button displayed on the right side of the navigation bar.
   // Tapping it sends the data in the prompt for verification.
   UIBarButtonItem* _confirmButton;
   // Owns `self`.
   autofill::CardUnmaskPromptViewBridge* _bridge;  // weak
+  // Model of the cvc input cell.
+  TableViewTextEditItem* _CVCInputItem;
+  // Model of the footer.
+  TableViewLinkHeaderFooterItem* _footerItem;
 }
 
 @end
@@ -63,11 +91,15 @@
   self.title =
       base::SysUTF16ToNSString(_bridge->GetController()->GetWindowTitle());
 
+  // Disable selection.
+  self.tableView.allowsSelection = NO;
+
+  self.tableView.estimatedSectionFooterHeight = kEstimatedHeaderFooterHeight;
+  self.tableView.estimatedSectionHeaderHeight = kEstimatedHeaderFooterHeight;
+
   self.navigationItem.leftBarButtonItem = [self createCancelButton];
+
   _confirmButton = [self createConfirmButton];
-  // Disable confirm button by default. It will be enabled after valid data is
-  // entered in the prompt.
-  _confirmButton.enabled = NO;
   self.navigationItem.rightBarButtonItem = _confirmButton;
 
   [self loadModel];
@@ -77,10 +109,20 @@
   [super loadModel];
 
   TableViewModel* model = self.tableViewModel;
-  [model addSectionWithIdentifier:SectionIdentifierMain];
+  [model addSectionWithIdentifier:SectionIdentifierHeader];
 
   [model setHeader:[self createHeaderItem]
-      forSectionWithIdentifier:SectionIdentifierMain];
+      forSectionWithIdentifier:SectionIdentifierHeader];
+
+  [model addSectionWithIdentifier:SectionIdentifierInputs];
+
+  _CVCInputItem = [self createCVCInputItem];
+  [self.tableViewModel addItem:_CVCInputItem
+       toSectionWithIdentifier:SectionIdentifierInputs];
+
+  _footerItem = [self createFooterItem];
+  [self.tableViewModel setFooter:_footerItem
+        forSectionWithIdentifier:SectionIdentifierInputs];
 }
 
 #pragma mark - UIAdaptivePresentationControllerDelegate
@@ -104,7 +146,7 @@
 
 #pragma mark - Private
 
-// Returns a newly created item for the footer of the section.
+// Returns a newly created item for the header of the section.
 - (CVCHeaderItem*)createHeaderItem {
   autofill::CardUnmaskPromptController* controller = _bridge->GetController();
   NSString* instructions =
@@ -148,4 +190,103 @@
   return confirmButton;
 }
 
+// Returns the model for the cvc input cell.
+- (TableViewTextEditItem*)createCVCInputItem {
+  autofill::CardUnmaskPromptController* controller = _bridge->GetController();
+
+  TableViewTextEditItem* cvcInputItem =
+      [[TableViewTextEditItem alloc] initWithType:ItemTypeCVCInput];
+  cvcInputItem.delegate = self;
+  cvcInputItem.textFieldName =
+      l10n_util::GetNSString(IDS_AUTOFILL_CARD_UNMASK_PROMPT_CVC_FIELD_TITLE);
+  cvcInputItem.keyboardType = UIKeyboardTypeNumberPad;
+  cvcInputItem.hideIcon = YES;
+  cvcInputItem.textFieldEnabled = YES;
+  cvcInputItem.identifyingIcon = NativeImage(controller->GetCvcImageRid());
+
+  return cvcInputItem;
+}
+
+// Returns a newly created item for the footer of the section.
+- (TableViewLinkHeaderFooterItem*)createFooterItem {
+  TableViewLinkHeaderFooterItem* footer =
+      [[TableViewLinkHeaderFooterItem alloc] initWithType:ItemTypeFooter];
+  footer.text = l10n_util::GetNSString(
+      IDS_AUTOFILL_CARD_UNMASK_PROMPT_UPDATE_CARD_MESSAGE_LINK);
+  // Using a dummy target for the link in the footer.
+  // The link target is ignored and taps on it are handled by `didTapLinkURL`.
+  footer.urls = @[ [[CrURL alloc] initWithGURL:GURL(kFooterDummyLinkTarget)] ];
+  return footer;
+}
+
+#pragma mark - TableViewTextEditItemDelegate
+
+- (void)tableViewItemDidChange:(TableViewTextEditItem*)tableViewItem {
+  NOTIMPLEMENTED();
+}
+
+- (void)tableViewItemDidBeginEditing:(TableViewTextEditItem*)tableViewItem {
+  NOTIMPLEMENTED();
+}
+
+- (void)tableViewItemDidEndEditing:(TableViewTextEditItem*)tableViewItem {
+  NOTIMPLEMENTED();
+}
+
+#pragma mark - UITableViewDelegate
+
+- (CGFloat)tableView:(UITableView*)tableView
+    heightForHeaderInSection:(NSInteger)section {
+  // Adding space on top of the inputs section to match the mocks' spacing.
+  NSInteger inputsSection =
+      [self.tableViewModel sectionForSectionIdentifier:SectionIdentifierInputs];
+  if (section == inputsSection) {
+    return kInputsSectionTopSpacing;
+  }
+  return UITableViewAutomaticDimension;
+}
+
+- (CGFloat)tableView:(UITableView*)tableView
+    heightForFooterInSection:(NSInteger)section {
+  // The header section doesn't need a footer, settings its height to zero to
+  // avoid extra spacing between sections.
+  NSInteger headerSection =
+      [self.tableViewModel sectionForSectionIdentifier:SectionIdentifierHeader];
+  if (section == headerSection) {
+    return 0;
+  }
+  // Let Autolayout calculate calculate the footer's height if any.
+  if ([self.tableViewModel footerForSectionIndex:section]) {
+    return UITableViewAutomaticDimension;
+  }
+  // Default spacing when no footer.
+  return kEmptyFooterHeight;
+}
+
+#pragma mark - UITableViewDataSource
+
+- (UIView*)tableView:(UITableView*)tableView
+    viewForFooterInSection:(NSInteger)section {
+  UIView* view = [super tableView:tableView viewForFooterInSection:section];
+  NSInteger sectionIdentifier =
+      [self.tableViewModel sectionIdentifierForSectionIndex:section];
+
+  // Set `self` as delegate for the inputs section footer to handle taps on the
+  // Update Card link.
+  if (sectionIdentifier == SectionIdentifierInputs) {
+    TableViewLinkHeaderFooterView* footerView =
+        base::mac::ObjCCast<TableViewLinkHeaderFooterView>(view);
+    footerView.delegate = self;
+  }
+
+  return view;
+}
+
+#pragma mark - TableViewLinkHeaderFooterDelegate
+
+- (void)view:(TableViewLinkHeaderFooterView*)view didTapLinkURL:(CrURL*)URL {
+  // Handle taps on the Update Card link.
+  NOTIMPLEMENTED();
+}
+
 @end
diff --git a/ios/chrome/browser/ui/open_in/open_in_controller_egtest.mm b/ios/chrome/browser/ui/open_in/open_in_controller_egtest.mm
index 6845663..c0aaac1 100644
--- a/ios/chrome/browser/ui/open_in/open_in_controller_egtest.mm
+++ b/ios/chrome/browser/ui/open_in/open_in_controller_egtest.mm
@@ -134,10 +134,6 @@
 
 // Tests that open in button do not appears when opening a MOV file.
 - (void)testOpenInMOV {
-  // TODO(crbug.com/1346136): Opening this mov is crashing WebContent on iOS16.
-  if (@available(iOS 16, *)) {
-    EARL_GREY_TEST_DISABLED(@"testOpenInMOV crashing WebContent on iOS16");
-  }
   [ChromeEarlGrey loadURL:self.testServer->GetURL(kMOVPath)];
   [[EarlGrey selectElementWithMatcher:chrome_test_util::OpenInButton()]
       assertWithMatcher:grey_nil()];
diff --git a/ios/chrome/browser/ui/settings/password/BUILD.gn b/ios/chrome/browser/ui/settings/password/BUILD.gn
index bc9f1619..00ebc04 100644
--- a/ios/chrome/browser/ui/settings/password/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/password/BUILD.gn
@@ -36,6 +36,7 @@
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
     "//ios/chrome/browser/ui/settings/password/password_details",
+    "//ios/chrome/browser/ui/settings/password/password_settings",
     "//ios/chrome/browser/ui/settings/password/passwords_in_other_apps",
     "//ios/chrome/browser/ui/settings/utils",
     "//ios/chrome/browser/ui/table_view",
diff --git a/ios/chrome/browser/ui/settings/password/password_manager_egtest.mm b/ios/chrome/browser/ui/settings/password/password_manager_egtest.mm
index 269d417..a78baa2 100644
--- a/ios/chrome/browser/ui/settings/password/password_manager_egtest.mm
+++ b/ios/chrome/browser/ui/settings/password/password_manager_egtest.mm
@@ -310,6 +310,10 @@
   return grey_accessibilityID(kSettingsToolbarEditDoneButtonId);
 }
 
+id<GREYMatcher> ToolbarSettingsSubmenuButton() {
+  return grey_accessibilityID(kSettingsToolbarSettingsButtonId);
+}
+
 // Saves an example form in the store.
 void SaveExamplePasswordForm() {
   GREYAssert(
@@ -344,7 +348,7 @@
 }
 
 // Opens the passwords page from the NTP. It requires no menus to be open.
-void OpenPasswordSettings() {
+void OpenPasswordManager() {
   [ChromeEarlGreyUI openSettingsMenu];
   [ChromeEarlGreyUI
       tapSettingsMenuButton:chrome_test_util::SettingsMenuPasswordsButton()];
@@ -430,7 +434,7 @@
 // Verifies that a signed out account has no option related to
 // on device encryption.
 - (void)testNoOndeviceEncryptionWithoutFlag {
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   // Check that the menus related to on-device encryptions are not displayed.
   [OptedInTrustedVaultLink() assertWithMatcher:grey_nil()];
@@ -442,7 +446,7 @@
 // Check that a user which is not logged in any account do not get
 // offered to use trusted vault.
 - (void)testNoOndeviceEncryptionSetupWhenSignedOut {
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   // Check that the menus related to on-device encryptions are not displayed.
   [OptedInTrustedVaultLink() assertWithMatcher:grey_nil()];
@@ -456,7 +460,7 @@
   // Saving a form is needed for using the "password details" view.
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
   [ChromeEarlGrey verifyAccessibilityForCurrentScreen];
 
   TapEdit();
@@ -483,7 +487,7 @@
   // Saving a form is needed for using the "password details" view.
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       performAction:grey_tap()];
@@ -527,7 +531,7 @@
   // Saving a form is needed for using the "password details" view.
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       performAction:grey_tap()];
@@ -557,7 +561,7 @@
   // Saving a form is needed for using the "password details" view.
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       performAction:grey_tap()];
@@ -591,7 +595,7 @@
   // Saving a form is needed for using the "password details" view.
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       performAction:grey_tap()];
@@ -616,7 +620,7 @@
   // Saving a form is needed for using the "password details" view.
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       performAction:grey_tap()];
@@ -643,7 +647,7 @@
   // Save form to be deleted later.
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       performAction:grey_tap()];
@@ -704,7 +708,7 @@
                               origin:@"https://example.com/example"],
              @"Stored form was not found in the PasswordStore results.");
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       performAction:grey_tap()];
@@ -758,7 +762,7 @@
                  saveExampleBlockedOrigin:@"https://blocked.com"],
              @"Stored form was not found in the PasswordStore results.");
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"blocked.com") performAction:grey_tap()];
 
@@ -804,7 +808,7 @@
   // Save form to be deleted later.
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       performAction:grey_tap()];
@@ -853,7 +857,7 @@
   // Save a form to have something to tap on.
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   TapEdit();
 
@@ -877,7 +881,7 @@
   // Saving a form is needed for using the "password details" view.
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       performAction:grey_tap()];
@@ -922,7 +926,7 @@
                                      origin:@"https://example.com"],
              @"Stored form was not found in the PasswordStore results.");
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, federated username")
       performAction:grey_tap()];
@@ -964,7 +968,7 @@
 - (void)testLayoutNormal {
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       performAction:grey_tap()];
@@ -1000,7 +1004,7 @@
                  saveExampleBlockedOrigin:@"https://example.com"],
              @"Stored form was not found in the PasswordStore results.");
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com") performAction:grey_tap()];
 
@@ -1030,7 +1034,7 @@
                                      origin:@"https://example.com"],
              @"Stored form was not found in the PasswordStore results.");
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, federated username")
       performAction:grey_tap()];
@@ -1062,7 +1066,7 @@
   // Save a password to be deleted later.
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   TapEdit();
 
@@ -1092,7 +1096,7 @@
   // Saving a form is needed for using the "password details" view.
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       performAction:grey_tap()];
@@ -1122,7 +1126,7 @@
   // Saving a form is needed for using the "password details" view.
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       performAction:grey_tap()];
@@ -1184,7 +1188,7 @@
                   [PasswordSettingsAppInterface passwordStoreResultsCount],
                   @"Unexpected PasswordStore results.");
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   // Wait for the loading indicator to disappear, and the sections to be on
   // screen, before scrolling.
@@ -1225,7 +1229,7 @@
   // Save a password to be deleted later.
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   TapEdit();
 
@@ -1252,7 +1256,7 @@
   // Saving a form is needed for exporting passwords.
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [PasswordSettingsAppInterface setUpMockReauthenticationModuleForExport];
   [PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult:
@@ -1324,7 +1328,7 @@
   SaveExamplePasswordForms();
   SaveExampleBlockedForms();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example11.com, user1")
       assertWithMatcher:grey_notNil()];
@@ -1365,7 +1369,7 @@
   SaveExamplePasswordForms();
   SaveExampleBlockedForms();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   // TODO(crbug.com/922511): Comment out because currently activating the search
   // bar will hide the "Edit" button in the top toolbar. Recover this when the
@@ -1407,7 +1411,7 @@
 - (void)testCantSearchPasswordsWhileInEditMode {
   SaveExamplePasswordForms();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
   TapEdit();
 
   // Verify search bar is disabled.
@@ -1418,7 +1422,7 @@
 // Test that the user can edit a password that is part of search results.
 - (void)testCanEditPasswordsFromASearch {
   SaveExamplePasswordForms();
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   // TODO(crbug.com/922511): Comment out because currently activating the search
   // bar will hide the "Edit" button in the top toolbar. Recover this when the
@@ -1464,7 +1468,7 @@
 - (void)testEditPassword {
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       performAction:grey_tap()];
@@ -1515,7 +1519,7 @@
 - (void)testEditUsername {
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       performAction:grey_tap()];
@@ -1584,7 +1588,7 @@
                                                  origin:@"https://example.com"],
       @"Stored form was not found in the PasswordStore results.");
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, concrete username1")
       performAction:grey_tap()];
@@ -1625,7 +1629,7 @@
 - (void)testCancelDuringEditing {
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       performAction:grey_tap()];
@@ -1665,7 +1669,7 @@
   // Send the passwords to the queue to be added to the PasswordStore.
   [PasswordSettingsAppInterface saveExamplePasswordWithCount:kPasswordsCount];
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
   [ChromeEarlGrey verifyAccessibilityForCurrentScreen];
 
   TapEdit();
@@ -1704,7 +1708,7 @@
 // Checks that the "Add" button is not shown on Edit.
 - (void)testAddButtonDisabledInEditMode {
   SaveExamplePasswordForm();
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   TapEdit();
 
@@ -1718,7 +1722,7 @@
 
 // Tests the add password flow.
 - (void)testAddNewPasswordCredential {
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   // Press "Add".
   [[EarlGrey selectElementWithMatcher:AddPasswordButton()]
@@ -1774,7 +1778,7 @@
                @"Stored form was not found in the PasswordStore results.");
   }
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   // Press "Add".
   [[EarlGrey selectElementWithMatcher:AddPasswordButton()]
@@ -1815,7 +1819,7 @@
   }
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
   [PasswordSettingsAppInterface setUpMockReauthenticationModuleForExport];
   [PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult:
                                     ReauthenticationResult::kSuccess];
@@ -1876,7 +1880,7 @@
   if (@available(iOS 16, *)) {
     EARL_GREY_TEST_DISABLED(@"Test consistently failing to tap save.");
   }
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [[EarlGrey selectElementWithMatcher:AddPasswordButton()]
       performAction:grey_tap()];
@@ -1934,7 +1938,7 @@
 // Tests that the error message is shown when the top-level domain is missing
 // when adding a new credential.
 - (void)testTLDMissingMessage {
-  OpenPasswordSettings();
+  OpenPasswordManager();
   [PasswordSettingsAppInterface setUpMockReauthenticationModuleForExport];
   [PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult:
                                     ReauthenticationResult::kSuccess];
@@ -1969,7 +1973,7 @@
                                origin:@"https://example.com"],
              @"Stored form was not found in the PasswordStore results.");
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   NSString* text = l10n_util::GetNSString(IDS_IOS_CHECK_PASSWORDS);
   NSString* detailText =
@@ -2013,7 +2017,7 @@
 - (void)testShowHidePassword {
   SaveExamplePasswordForm();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       performAction:grey_tap()];
@@ -2045,7 +2049,7 @@
   // Add passwords for the user.
   SaveExamplePasswordForms();
 
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   // Make sure the cell is loaded properly before tapping on it.
   ConditionBlock condition = ^{
@@ -2120,7 +2124,7 @@
 // Tests that the favicons for the password managers metrics are logged
 // properly when there are no password.
 - (void)testLogFaviconsForPasswordsMetricsNoPassword {
-  OpenPasswordSettings();
+  OpenPasswordManager();
 
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -2160,4 +2164,24 @@
   }
 }
 
+- (void)testOpenPasswordSettingsSubmenu {
+  if (![ChromeEarlGrey isIPadIdiom]) {
+    // TODO(crbug.com/1335156): On small phones this test fails because the
+    // original menu peeks out underneath the submenu that covers it. This will
+    // be fixed when this test is updated to check for content on the submenu.
+    EARL_GREY_TEST_DISABLED(@"Disabled for phones.");
+  }
+
+  OpenPasswordManager();
+
+  [[EarlGrey selectElementWithMatcher:ToolbarSettingsSubmenuButton()]
+      performAction:grey_tap()];
+
+  // The submenu doesn't currently have any content, so just ensure that the
+  // underlying window isn't visible anymore.
+  [[EarlGrey
+      selectElementWithMatcher:grey_accessibilityID(kPasswordsTableViewId)]
+      assertWithMatcher:grey_notVisible()];
+}
+
 @end
diff --git a/ios/chrome/browser/ui/settings/password/password_manager_view_controller.mm b/ios/chrome/browser/ui/settings/password/password_manager_view_controller.mm
index 10426d3..34ce5938 100644
--- a/ios/chrome/browser/ui/settings/password/password_manager_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/password/password_manager_view_controller.mm
@@ -414,8 +414,9 @@
   if (ShouldShowSettingsUI() && [self allowsAddPassword]) {
     self.shouldShowAddButtonInToolbar = YES;
     self.addButtonInToolbar.enabled = YES;
-  } else {
-    self.shouldShowAddButtonInToolbar = NO;
+  } else if (!ShouldShowSettingsUI()) {
+    self.shouldShowSettingsButtonInToolbar = YES;
+    self.settingsButtonInToolbar.enabled = YES;
   }
 
   [self loadModel];
@@ -725,6 +726,10 @@
   [self.handler showAddPasswordSheet];
 }
 
+- (void)settingsButtonCallback {
+  [self.presentationDelegate showPasswordSettingsSubmenu];
+}
+
 - (void)editButtonPressed {
   // Disable search bar if the user is bulk editing (edit mode). (Reverse logic
   // because parent method -editButtonPressed is calling setEditing to change
diff --git a/ios/chrome/browser/ui/settings/password/password_manager_view_controller_presentation_delegate.h b/ios/chrome/browser/ui/settings/password/password_manager_view_controller_presentation_delegate.h
index 8abee6c5..76d6829 100644
--- a/ios/chrome/browser/ui/settings/password/password_manager_view_controller_presentation_delegate.h
+++ b/ios/chrome/browser/ui/settings/password/password_manager_view_controller_presentation_delegate.h
@@ -13,6 +13,10 @@
 // Called when `PasswordManagerViewController` is dismissed.
 - (void)PasswordManagerViewControllerDismissed;
 
+// Called when the user has requested that the Password Settings submenu be
+// presented.
+- (void)showPasswordSettingsSubmenu;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_MANAGER_VIEW_CONTROLLER_PRESENTATION_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_settings/BUILD.gn b/ios/chrome/browser/ui/settings/password/password_settings/BUILD.gn
new file mode 100644
index 0000000..0265347
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_settings/BUILD.gn
@@ -0,0 +1,19 @@
+# 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.
+
+source_set("password_settings") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "password_settings_coordinator.h",
+    "password_settings_coordinator.mm",
+    "password_settings_coordinator_delegate.h",
+    "password_settings_view_controller.h",
+    "password_settings_view_controller.mm",
+  ]
+  deps = [
+    "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
+    "//ios/chrome/browser/ui/table_view",
+    "//ios/chrome/browser/ui/table_view:utils",
+  ]
+}
diff --git a/ios/chrome/browser/ui/settings/password/password_settings/password_settings_coordinator.h b/ios/chrome/browser/ui/settings/password/password_settings/password_settings_coordinator.h
new file mode 100644
index 0000000..948e8bc
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_settings/password_settings_coordinator.h
@@ -0,0 +1,24 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_SETTINGS_PASSWORD_SETTINGS_COORDINATOR_H_
+#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_SETTINGS_PASSWORD_SETTINGS_COORDINATOR_H_
+
+#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
+
+@protocol PasswordSettingsCoordinatorDelegate;
+
+// This coordinator presents settings related to the Password Manager.
+@interface PasswordSettingsCoordinator : ChromeCoordinator
+
+- (instancetype)initWithBaseViewController:(UIViewController*)viewController
+                                   browser:(Browser*)browser
+    NS_DESIGNATED_INITIALIZER;
+
+// Delegate.
+@property(nonatomic, weak) id<PasswordSettingsCoordinatorDelegate> delegate;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_SETTINGS_PASSWORD_SETTINGS_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_settings/password_settings_coordinator.mm b/ios/chrome/browser/ui/settings/password/password_settings/password_settings_coordinator.mm
new file mode 100644
index 0000000..fd05d89d
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_settings/password_settings_coordinator.mm
@@ -0,0 +1,56 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/settings/password/password_settings/password_settings_coordinator.h"
+
+#import <UIKit/UIKit.h>
+
+#import "ios/chrome/browser/ui/settings/password/password_settings/password_settings_coordinator_delegate.h"
+#import "ios/chrome/browser/ui/settings/password/password_settings/password_settings_view_controller.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@interface PasswordSettingsCoordinator () <PasswordSettingsPresentationDelegate>
+
+// Main view controller for this coordinator.
+@property(nonatomic, strong)
+    PasswordSettingsViewController* passwordSettingsViewController;
+
+@end
+
+@implementation PasswordSettingsCoordinator
+
+- (instancetype)initWithBaseViewController:(UIViewController*)viewController
+                                   browser:(Browser*)browser {
+  self = [super initWithBaseViewController:viewController browser:browser];
+  return self;
+}
+
+#pragma mark - ChromeCoordinator
+
+- (void)start {
+  self.passwordSettingsViewController =
+      [[PasswordSettingsViewController alloc] init];
+
+  self.passwordSettingsViewController.presentationDelegate = self;
+
+  [self.baseViewController
+      presentViewController:self.passwordSettingsViewController
+                   animated:YES
+                 completion:nil];
+}
+
+- (void)stop {
+  self.passwordSettingsViewController = nil;
+}
+
+#pragma mark - PasswordSettingsPresentationDelegate
+
+- (void)passwordSettingsViewControllerDidDismiss {
+  [self.delegate passwordSettingsCoordinatorDidRemove:self];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/settings/password/password_settings/password_settings_coordinator_delegate.h b/ios/chrome/browser/ui/settings/password/password_settings/password_settings_coordinator_delegate.h
new file mode 100644
index 0000000..3d63afe
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_settings/password_settings_coordinator_delegate.h
@@ -0,0 +1,19 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_SETTINGS_PASSWORD_SETTINGS_COORDINATOR_DELEGATE_H_
+#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_SETTINGS_PASSWORD_SETTINGS_COORDINATOR_DELEGATE_H_
+
+@class PasswordSettingsCoordinator;
+
+// Delegate for PasswordSettingsCoordinator.
+@protocol PasswordSettingsCoordinatorDelegate
+
+// Called when the view controller was removed from navigation controller.
+- (void)passwordSettingsCoordinatorDidRemove:
+    (PasswordSettingsCoordinator*)coordinator;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_SETTINGS_PASSWORD_SETTINGS_COORDINATOR_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_settings/password_settings_view_controller.h b/ios/chrome/browser/ui/settings/password/password_settings/password_settings_view_controller.h
new file mode 100644
index 0000000..94387c1
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_settings/password_settings_view_controller.h
@@ -0,0 +1,29 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_SETTINGS_PASSWORD_SETTINGS_VIEW_CONTROLLER_H_
+#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_SETTINGS_PASSWORD_SETTINGS_VIEW_CONTROLLER_H_
+
+#import <UIKit/UIKit.h>
+
+#import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h"
+
+// Protocol used to display Passwords Settings.
+@protocol PasswordSettingsPresentationDelegate
+
+// Method invoked when the page is dismissed.
+- (void)passwordSettingsViewControllerDidDismiss;
+
+@end
+
+@interface PasswordSettingsViewController : ChromeTableViewController
+
+@property(nonatomic, weak) id<PasswordSettingsPresentationDelegate>
+    presentationDelegate;
+
+- (instancetype)init;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_SETTINGS_PASSWORD_SETTINGS_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_settings/password_settings_view_controller.mm b/ios/chrome/browser/ui/settings/password/password_settings/password_settings_view_controller.mm
new file mode 100644
index 0000000..0678d73e
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_settings/password_settings_view_controller.mm
@@ -0,0 +1,26 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/settings/password/password_settings/password_settings_view_controller.h"
+
+#import "ios/chrome/browser/ui/table_view/table_view_utils.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@implementation PasswordSettingsViewController
+
+- (instancetype)init {
+  self = [super initWithStyle:ChromeTableViewStyle()];
+  return self;
+}
+
+#pragma mark - UIViewController
+
+- (void)viewWillDisappear:(BOOL)animated {
+  [self.presentationDelegate passwordSettingsViewControllerDidDismiss];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/settings/password/passwords_coordinator.mm b/ios/chrome/browser/ui/settings/password/passwords_coordinator.mm
index 65e24bf..29a078a 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_coordinator.mm
+++ b/ios/chrome/browser/ui/settings/password/passwords_coordinator.mm
@@ -26,6 +26,8 @@
 #import "ios/chrome/browser/ui/settings/password/password_issues_coordinator.h"
 #import "ios/chrome/browser/ui/settings/password/password_manager_view_controller.h"
 #import "ios/chrome/browser/ui/settings/password/password_manager_view_controller_presentation_delegate.h"
+#import "ios/chrome/browser/ui/settings/password/password_settings/password_settings_coordinator.h"
+#import "ios/chrome/browser/ui/settings/password/password_settings/password_settings_coordinator_delegate.h"
 #import "ios/chrome/browser/ui/settings/password/passwords_consumer.h"
 #import "ios/chrome/browser/ui/settings/password/passwords_in_other_apps/passwords_in_other_apps_coordinator.h"
 #import "ios/chrome/browser/ui/settings/password/passwords_mediator.h"
@@ -41,6 +43,7 @@
     PasswordDetailsCoordinatorDelegate,
     PasswordIssuesCoordinatorDelegate,
     PasswordsInOtherAppsCoordinatorDelegate,
+    PasswordSettingsCoordinatorDelegate,
     PasswordsSettingsCommands,
     PasswordManagerViewControllerPresentationDelegate>
 
@@ -74,6 +77,9 @@
 @property(nonatomic, strong)
     PasswordsInOtherAppsCoordinator* passwordsInOtherAppsCoordinator;
 
+@property(nonatomic, strong)
+    PasswordSettingsCoordinator* passwordSettingsCoordinator;
+
 @end
 
 @implementation PasswordsCoordinator
@@ -212,6 +218,15 @@
   [self.delegate passwordsCoordinatorDidRemove:self];
 }
 
+- (void)showPasswordSettingsSubmenu {
+  DCHECK(!self.passwordSettingsCoordinator);
+  self.passwordSettingsCoordinator = [[PasswordSettingsCoordinator alloc]
+      initWithBaseViewController:self.viewController
+                         browser:self.browser];
+  self.passwordSettingsCoordinator.delegate = self;
+  [self.passwordSettingsCoordinator start];
+}
+
 #pragma mark - PasswordIssuesCoordinatorDelegate
 
 - (void)passwordIssuesCoordinatorDidRemove:
@@ -284,6 +299,16 @@
   self.passwordsInOtherAppsCoordinator = nil;
 }
 
+#pragma mark - PasswordSettingsCoordinatorDelegate
+
+- (void)passwordSettingsCoordinatorDidRemove:
+    (PasswordSettingsCoordinator*)coordinator {
+  DCHECK_EQ(self.passwordSettingsCoordinator, coordinator);
+  [self.passwordSettingsCoordinator stop];
+  self.passwordSettingsCoordinator.delegate = nil;
+  self.passwordSettingsCoordinator = nil;
+}
+
 #pragma mark Private
 
 - (scoped_refptr<IOSChromePasswordCheckManager>)passwordCheckManager {
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.h b/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.h
index e638a29..80c88c1 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.h
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.h
@@ -44,6 +44,7 @@
 @property(nonatomic, copy) NSString* identifyingIconAccessibilityLabel;
 
 // Whether to hide or display the trailing icon.
+// Changing this value can change the text color for the text field.
 @property(nonatomic, assign) BOOL hideIcon;
 
 // Whether this field is required. If YES, an "*" is appended to the name of the
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.mm
index c9a86ce..0740589 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.mm
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.mm
@@ -87,9 +87,8 @@
   cell.textField.enabled = self.textFieldEnabled;
 
   if (self.hideIcon) {
-    cell.textField.textColor = self.textFieldEnabled
-                                   ? [UIColor colorNamed:kBlueColor]
-                                   : [UIColor colorNamed:kTextPrimaryColor];
+    cell.textField.textColor = [UIColor colorNamed:kTextPrimaryColor];
+
     [cell setIcon:TableViewTextEditItemIconTypeNone];
   } else {
     if (self.hasValidText) {
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item_unittest.mm b/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item_unittest.mm
index 23eafde0..16d3244 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item_unittest.mm
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item_unittest.mm
@@ -5,9 +5,10 @@
 #import "ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.h"
 
 #import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h"
-#include "testing/gtest/include/gtest/gtest.h"
+#import "ios/chrome/common/ui/colors/semantic_color_names.h"
+#import "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
-#include "testing/platform_test.h"
+#import "testing/platform_test.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn
index 2431feb..5a476c9 100644
--- a/ios/chrome/test/earl_grey/BUILD.gn
+++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -13,8 +13,11 @@
   sources = [ "device_check_egtest.mm" ]
   deps = [
     ":eg_test_support+eg2",
+    "//components/strings",
     "//ios/testing/earl_grey:eg_test_support+eg2",
     "//ios/third_party/earl_grey2:test_lib",
+    "//ios/web/public/test:element_selector",
+    "//ui/base",
     "//url",
   ]
   frameworks = [ "UIKit.framework" ]
diff --git a/ios/chrome/test/earl_grey/device_check_egtest.mm b/ios/chrome/test/earl_grey/device_check_egtest.mm
index 6354489..aea74fa 100644
--- a/ios/chrome/test/earl_grey/device_check_egtest.mm
+++ b/ios/chrome/test/earl_grey/device_check_egtest.mm
@@ -2,9 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#import "components/strings/grit/components_strings.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/testing/earl_grey/earl_grey_test.h"
+#import "ios/web/public/test/element_selector.h"
+#import "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -17,11 +20,17 @@
 
 @implementation DeviceCheckTestCase
 
-// Verifies Internet connectivity by navigating to browsingtest.appspot.com.
+// Verifies Internet connectivity by navigating to google.com
+// and asserting that the chrome dino page is not shown
 - (void)testNetworkConnection {
+  [ChromeEarlGrey loadURL:GURL("http://google.com")];
   [ChromeEarlGrey
-      loadURL:GURL("http://browsingtest.appspot.com/googleLogoPage.html")];
-  [ChromeEarlGrey waitForWebStateContainingText:"some text"];
+      waitForWebStateNotContainingElement:
+          [ElementSelector
+              selectorWithCSSSelector:"[title='" +
+                                      l10n_util::GetStringUTF8(
+                                          IDS_ERRORPAGE_DINO_ARIA_LABEL) +
+                                      "']"]];
 }
 
 @end
diff --git a/ios/chrome/test/xcuitest/device_check_xctest.mm b/ios/chrome/test/xcuitest/device_check_xctest.mm
index 89b77a9..d05a5ec 100644
--- a/ios/chrome/test/xcuitest/device_check_xctest.mm
+++ b/ios/chrome/test/xcuitest/device_check_xctest.mm
@@ -88,7 +88,7 @@
   XCTAssert(HandleSystemAlertsIfVisible(), @"Unhandled system alert.");
 }
 
-// Verifies Internet connectivity by navigating to browsingtest.appspot.com.
+// Verifies Internet connectivity by navigating to google.com.
 - (void)testNetworkConnection {
   XCUIApplication* app = [[XCUIApplication alloc] init];
 
@@ -97,15 +97,15 @@
   XCTAssert([app.keyboards.firstMatch
                 waitForExistenceWithTimeout:kWaitForUIElementTimeout],
             @"Keyboard didn't appear!");
-  [app typeText:@"http://browsingtest.appspot.com/googleLogoPage.html"];
+  [app typeText:@"http://google.com"];
   [app typeText:XCUIKeyboardKeyReturn];
 
-  ConditionBlock waitForWebContents = ^{
-    return ElementStaticTextContainsText(app.webViews.firstMatch, @"some text");
-  };
   XCTAssert(
-      WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, waitForWebContents),
-      @"Failed to find desired text in web page!");
+      // verify chrome is not showing offline dino page
+      ![[[app.webViews.firstMatch descendantsMatchingType:XCUIElementTypeAny]
+            matchingIdentifier:@"Dino game, play"]
+              .firstMatch waitForExistenceWithTimeout:kWaitForPageLoadTimeout],
+      @"Showing chrome dino page!");
 }
 
 @end
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 386990e..0819c68 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 @@
-3114e8446d2ad74ddbc14117f4470948b6793d97
\ No newline at end of file
+a569341be5fcdc9586d02bde970a975c229ebb96
\ 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 1d1f28f..d367b58 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 @@
-46c2a19d470a6221ad8f57c4612a0ba352b447b4
\ No newline at end of file
+8235617bc8255bde79cfb19d1d7739c26df23c18
\ 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 f6fc865..105950f 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 @@
-510e3f4bf08c6b12e3b5d7faccf90159b2c7b923
\ No newline at end of file
+2af083fb9c2769146f04429ae8b802f6c17fe830
\ 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 8a5f5fd..f9edfd3 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 @@
-eaf2355708265bb2de9b4fac723a2ca01d578c41
\ No newline at end of file
+f2e3c7d870b13a099b520709f778bd652b9bacda
\ 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 3c82f82..42a3ce2 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 @@
-9e0505db1e769778606c6e104f45b8e8a4270a3c
\ No newline at end of file
+80ee833128b7238c1fa0e91c32e7b18ec19f1723
\ 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 61383e1..7292e3fc 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 @@
-2b06e7ba8ab2e303d576060dba1b77e2001922c5
\ No newline at end of file
+336d295b728eb4f04a8268eb4bba51192b9edfef
\ 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 bd91493..f4288d2 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 @@
-11c5f1ebb0eac5b2b9acd13f8928742026a5d0b5
\ No newline at end of file
+c947b7662a0459447c6ebc2c958ca69803587370
\ 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 c351f11e..65757e1 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 @@
-e439aefd24a3246b24f9bf323603b38b9a0dcc46
\ No newline at end of file
+cb41feebae11dc201fa42b9e28db2ec3493e388f
\ 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 2cbaa85..653ebbf8 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 @@
-243f00d27022ff942897c9af22887e7a8b0a37e5
\ No newline at end of file
+13100cd70292cb30ec8182ba9cadf9e8cb3e5546
\ 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 ba74418..b93ac82a 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 @@
-6d17f9f938c4932c98707bc6748013d689ff0c33
\ No newline at end of file
+1ae806557c801bbd78558321ba4a3a80c29dc041
\ No newline at end of file
diff --git a/ios/testing/earl_grey/app_launch_manager.mm b/ios/testing/earl_grey/app_launch_manager.mm
index 201cc72..4a89f04 100644
--- a/ios/testing/earl_grey/app_launch_manager.mm
+++ b/ios/testing/earl_grey/app_launch_manager.mm
@@ -252,6 +252,11 @@
     if (@available(iOS 14, *)) {
       [BaseEarlGreyTestCaseAppInterface enableFastAnimation];
     }
+
+    // Wait for application to settle before continuing on with test.
+    GREYWaitForAppToIdle(@"App failed to idle BEFORE test body started.\n\n"
+                         @"**** Check that the prior test left the app in a"
+                         @"clean state. ****");
   }
 }
 
diff --git a/ipc/BUILD.gn b/ipc/BUILD.gn
index 084b6e88..a202c1df4 100644
--- a/ipc/BUILD.gn
+++ b/ipc/BUILD.gn
@@ -296,6 +296,7 @@
       "//base:i18n",
       "//base/test:test_support",
       "//crypto",
+      "//mojo/core:driver_for_ipcz_tests",
       "//mojo/core/test:test_support",
       "//testing/gtest",
       "//third_party/ipcz/src:ipcz_tests_sources_chromium",
diff --git a/mojo/core/BUILD.gn b/mojo/core/BUILD.gn
index ee2fc71..935295d 100644
--- a/mojo/core/BUILD.gn
+++ b/mojo/core/BUILD.gn
@@ -17,6 +17,7 @@
   output_name = "mojo_core_embedder_internal"
   public_deps = [ ":impl_for_embedder" ]
   visibility = [
+    ":driver_for_ipcz_tests",
     ":test_sources",
     "//mojo:*",
     "//mojo/core/embedder",
@@ -211,6 +212,17 @@
   for_shared_library = false
 }
 
+source_set("driver_for_ipcz_tests") {
+  testonly = true
+  sources = [ "ipcz_driver/driver_for_ipcz_tests.cc" ]
+  deps = [
+    ":embedder_internal",
+    "//base",
+    "//base/test:test_support",
+    "//third_party/ipcz/src:ipcz_test_support_chromium",
+  ]
+}
+
 if (is_win) {
   process_version_rc_template("mojo_core_version") {
     sources = [ "mojo_core.ver" ]
diff --git a/mojo/core/ipcz_driver/driver.cc b/mojo/core/ipcz_driver/driver.cc
index 04021da..bd6c851 100644
--- a/mojo/core/ipcz_driver/driver.cc
+++ b/mojo/core/ipcz_driver/driver.cc
@@ -7,11 +7,18 @@
 #include <cstddef>
 #include <cstdint>
 #include <tuple>
+#include <utility>
 
 #include "base/containers/span.h"
 #include "base/containers/stack_container.h"
+#include "base/memory/unsafe_shared_memory_region.h"
 #include "base/rand_util.h"
 #include "mojo/core/ipcz_driver/object.h"
+#include "mojo/core/ipcz_driver/shared_buffer.h"
+#include "mojo/core/ipcz_driver/shared_buffer_mapping.h"
+#include "mojo/core/ipcz_driver/transmissible_platform_handle.h"
+#include "mojo/core/ipcz_driver/transport.h"
+#include "mojo/public/cpp/platform/platform_handle.h"
 #include "third_party/ipcz/include/ipcz/ipcz.h"
 
 namespace mojo::core::ipcz_driver {
@@ -37,7 +44,25 @@
                               size_t* num_bytes,
                               IpczDriverHandle* handles,
                               size_t* num_handles) {
-  return IPCZ_RESULT_UNIMPLEMENTED;
+  ObjectBase* object = ObjectBase::FromHandle(handle);
+  Transport* transport = Transport::FromHandle(transport_handle);
+  if (!object || !object->IsSerializable()) {
+    return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  if (!transport) {
+    return IPCZ_RESULT_ABORTED;
+  }
+
+  const IpczResult result = transport->SerializeObject(*object, data, num_bytes,
+                                                       handles, num_handles);
+  if (result != IPCZ_RESULT_OK) {
+    return result;
+  }
+
+  // On success we consume the object reference owned by the input handle.
+  std::ignore = ObjectBase::TakeFromHandle(handle);
+  return IPCZ_RESULT_OK;
 }
 
 IpczResult IPCZ_API Deserialize(const void* data,
@@ -48,62 +73,127 @@
                                 uint32_t flags,
                                 const void* options,
                                 IpczDriverHandle* driver_handle) {
-  return IPCZ_RESULT_UNIMPLEMENTED;
+  Transport* transport = Transport::FromHandle(transport_handle);
+  if (!transport || !driver_handle) {
+    return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  scoped_refptr<ObjectBase> object;
+  const IpczResult result = transport->DeserializeObject(
+      base::make_span(static_cast<const uint8_t*>(data), num_bytes),
+      base::make_span(handles, num_handles), object);
+  if (result != IPCZ_RESULT_OK) {
+    return result;
+  }
+
+  *driver_handle = ObjectBase::ReleaseAsHandle(std::move(object));
+  return IPCZ_RESULT_OK;
 }
 
-IpczResult IPCZ_API CreateTransports(IpczDriverHandle transport0,
-                                     IpczDriverHandle transport1,
+IpczResult IPCZ_API CreateTransports(IpczDriverHandle transport0_handle,
+                                     IpczDriverHandle transport1_handle,
                                      uint32_t flags,
                                      const void* options,
                                      IpczDriverHandle* new_transport0,
                                      IpczDriverHandle* new_transport1) {
-  return IPCZ_RESULT_UNIMPLEMENTED;
+  Transport* transport0 = Transport::FromHandle(transport0_handle);
+  Transport* transport1 = Transport::FromHandle(transport1_handle);
+  if (!transport0 || !transport1) {
+    return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+  auto [one, two] = Transport::CreatePair(transport0->destination(),
+                                          transport1->destination());
+  *new_transport0 = ObjectBase::ReleaseAsHandle(std::move(one));
+  *new_transport1 = ObjectBase::ReleaseAsHandle(std::move(two));
+  return IPCZ_RESULT_OK;
 }
 
 IpczResult IPCZ_API
-ActivateTransport(IpczDriverHandle driver_transport,
+ActivateTransport(IpczDriverHandle transport_handle,
                   IpczHandle ipcz_transport,
                   IpczTransportActivityHandler activity_handler,
                   uint32_t flags,
                   const void* options) {
-  return IPCZ_RESULT_UNIMPLEMENTED;
+  Transport* transport = Transport::FromHandle(transport_handle);
+  if (!transport) {
+    return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  transport->Activate(ipcz_transport, activity_handler);
+  return IPCZ_RESULT_OK;
 }
 
-IpczResult IPCZ_API DeactivateTransport(IpczDriverHandle driver_transport,
+IpczResult IPCZ_API DeactivateTransport(IpczDriverHandle transport_handle,
                                         uint32_t flags,
                                         const void* options) {
-  return IPCZ_RESULT_UNIMPLEMENTED;
+  Transport* transport = Transport::FromHandle(transport_handle);
+  if (!transport) {
+    return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  transport->Deactivate();
+  return IPCZ_RESULT_OK;
 }
 
-IpczResult IPCZ_API Transmit(IpczDriverHandle driver_transport,
+IpczResult IPCZ_API Transmit(IpczDriverHandle transport_handle,
                              const void* data,
                              size_t num_bytes,
                              const IpczDriverHandle* handles,
                              size_t num_handles,
                              uint32_t flags,
                              const void* options) {
-  return IPCZ_RESULT_UNIMPLEMENTED;
+  Transport* transport = Transport::FromHandle(transport_handle);
+  if (!transport) {
+    return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  transport->Transmit(
+      base::make_span(static_cast<const uint8_t*>(data), num_bytes),
+      base::make_span(handles, num_handles));
+  return IPCZ_RESULT_OK;
 }
 
 IpczResult IPCZ_API AllocateSharedMemory(size_t num_bytes,
                                          uint32_t flags,
                                          const void* options,
                                          IpczDriverHandle* driver_memory) {
-  return IPCZ_RESULT_UNIMPLEMENTED;
+  auto region = base::UnsafeSharedMemoryRegion::Create(num_bytes);
+  *driver_memory = SharedBuffer::ReleaseAsHandle(
+      SharedBuffer::MakeForRegion(std::move(region)));
+  return IPCZ_RESULT_OK;
 }
 
 IpczResult IPCZ_API GetSharedMemoryInfo(IpczDriverHandle driver_memory,
                                         uint32_t flags,
                                         const void* options,
                                         IpczSharedMemoryInfo* info) {
-  return IPCZ_RESULT_UNIMPLEMENTED;
+  SharedBuffer* buffer = SharedBuffer::FromHandle(driver_memory);
+  if (!buffer || !info || info->size < sizeof(*info)) {
+    return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  info->region_num_bytes = buffer->region().GetSize();
+  return IPCZ_RESULT_OK;
 }
 
 IpczResult IPCZ_API DuplicateSharedMemory(IpczDriverHandle driver_memory,
                                           uint32_t flags,
                                           const void* options,
                                           IpczDriverHandle* new_driver_memory) {
-  return IPCZ_RESULT_UNIMPLEMENTED;
+  SharedBuffer* buffer = SharedBuffer::FromHandle(driver_memory);
+  if (!buffer || !new_driver_memory) {
+    return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  base::UnsafeSharedMemoryRegion new_region =
+      base::UnsafeSharedMemoryRegion::Deserialize(buffer->region().Duplicate());
+  if (!new_region.IsValid()) {
+    return IPCZ_RESULT_RESOURCE_EXHAUSTED;
+  }
+
+  *new_driver_memory = SharedBuffer::ReleaseAsHandle(
+      SharedBuffer::MakeForRegion(std::move(new_region)));
+  return IPCZ_RESULT_OK;
 }
 
 IpczResult IPCZ_API MapSharedMemory(IpczDriverHandle driver_memory,
@@ -111,7 +201,20 @@
                                     const void* options,
                                     void** address,
                                     IpczDriverHandle* driver_mapping) {
-  return IPCZ_RESULT_UNIMPLEMENTED;
+  SharedBuffer* buffer = SharedBuffer::FromHandle(driver_memory);
+  if (!buffer || !driver_mapping) {
+    return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  scoped_refptr<SharedBufferMapping> mapping =
+      SharedBufferMapping::Create(buffer->region());
+  if (!mapping) {
+    return IPCZ_RESULT_RESOURCE_EXHAUSTED;
+  }
+
+  *address = mapping->memory();
+  *driver_mapping = SharedBufferMapping::ReleaseAsHandle(std::move(mapping));
+  return IPCZ_RESULT_OK;
 }
 
 IpczResult IPCZ_API GenerateRandomBytes(size_t num_bytes,
diff --git a/mojo/core/ipcz_driver/driver_for_ipcz_tests.cc b/mojo/core/ipcz_driver/driver_for_ipcz_tests.cc
new file mode 100644
index 0000000..7f84cc0ae
--- /dev/null
+++ b/mojo/core/ipcz_driver/driver_for_ipcz_tests.cc
@@ -0,0 +1,229 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <set>
+#include <string>
+#include <utility>
+
+#include "base/base_switches.h"
+#include "base/check.h"
+#include "base/command_line.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/process/process.h"
+#include "base/strings/strcat.h"
+#include "base/test/multiprocess_test.h"
+#include "base/test/test_timeouts.h"
+#include "base/threading/simple_thread.h"
+#include "build/build_config.h"
+#include "mojo/core/ipcz_driver/driver.h"
+#include "mojo/core/ipcz_driver/transport.h"
+#include "mojo/public/cpp/platform/platform_channel.h"
+#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
+#include "third_party/ipcz/src/test/multinode_test.h"
+
+namespace mojo::core::ipcz_driver {
+namespace {
+
+const char kMojoIpczInProcessTestDriverName[] = "MojoIpczInProcess";
+const char kMojoIpczMultiprocessTestDriverName[] = "MojoIpczMultiprocess";
+
+class MojoIpczInProcessTestNodeController
+    : public ipcz::test::TestNode::TestNodeController {
+ public:
+  class NodeThreadDelegate : public base::DelegateSimpleThread::Delegate {
+   public:
+    NodeThreadDelegate(std::unique_ptr<ipcz::test::TestNode> node,
+                       ipcz::test::TestDriver* driver)
+        : node_(std::move(node)), driver_(driver) {}
+
+    // base::DelegateSimpleThread::Delegate:
+    void Run() override {
+      node_->Initialize(driver_);
+      node_->NodeBody();
+      node_.reset();
+    }
+
+   private:
+    std::unique_ptr<ipcz::test::TestNode> node_;
+    ipcz::test::TestDriver* const driver_;
+  };
+
+  MojoIpczInProcessTestNodeController(
+      const std::string& node_name,
+      std::unique_ptr<ipcz::test::TestNode> test_node,
+      ipcz::test::TestDriver* test_driver)
+      : node_thread_delegate_(std::move(test_node), test_driver),
+        node_thread_(&node_thread_delegate_, node_name) {
+    node_thread_.StartAsync();
+  }
+
+  // TestNode::TestNodeController:
+  bool WaitForShutdown() override {
+    if (!node_thread_.HasBeenJoined()) {
+      node_thread_.Join();
+    }
+    return true;
+  }
+
+ private:
+  ~MojoIpczInProcessTestNodeController() override {
+    CHECK(node_thread_.HasBeenJoined());
+  }
+
+  NodeThreadDelegate node_thread_delegate_;
+  base::DelegateSimpleThread node_thread_;
+};
+
+class MojoIpczChildTestNodeController
+    : public ipcz::test::TestNode::TestNodeController {
+ public:
+  explicit MojoIpczChildTestNodeController(base::Process process)
+      : process_(std::move(process)) {}
+
+  // ipcz::test::TestNode::TestNodeController:
+  bool WaitForShutdown() override {
+    if (!process_.IsValid()) {
+      DCHECK(result_);
+      return *result_;
+    }
+
+    int rv = -1;
+    base::WaitForMultiprocessTestChildExit(process_,
+                                           TestTimeouts::action_timeout(), &rv);
+    process_.Close();
+    result_ = (rv == 0);
+    return *result_;
+  }
+
+ private:
+  ~MojoIpczChildTestNodeController() override { DCHECK(result_.has_value()); }
+
+  base::Process process_;
+  absl::optional<bool> result_;
+};
+
+// TestDriver implementation for the mojo-ipcz driver to have coverage in ipcz'
+// multinode tests.
+class MojoIpczTestDriver : public ipcz::test::TestDriver {
+ public:
+  enum Mode {
+    kInProcess,
+    kMultiprocess,
+  };
+  explicit MojoIpczTestDriver(Mode mode) : mode_(mode) {}
+
+  const IpczDriver& GetIpczDriver() const override { return kDriver; }
+
+  const char* GetName() const override {
+    if (mode_ == kInProcess) {
+      return kMojoIpczInProcessTestDriverName;
+    }
+    return kMojoIpczMultiprocessTestDriverName;
+  }
+
+  ipcz::test::TestNode::TransportPair CreateTransports(
+      ipcz::test::TestNode& source) const override {
+    auto [ours, theirs] =
+        Transport::CreatePair(Transport::kToNonBroker, Transport::kToBroker);
+    return {
+        .ours = Transport::ReleaseAsHandle(std::move(ours)),
+        .theirs = Transport::ReleaseAsHandle(std::move(theirs)),
+    };
+  }
+
+  ipcz::Ref<ipcz::test::TestNode::TestNodeController> SpawnTestNode(
+      ipcz::test::TestNode& source,
+      const ipcz::test::TestNodeDetails& details,
+      IpczDriverHandle our_transport,
+      IpczDriverHandle their_transport) override {
+    if (mode_ == kInProcess) {
+      return SpawnTestNodeThread(source, details, our_transport,
+                                 their_transport);
+    }
+    return SpawnTestNodeProcess(source, details, our_transport,
+                                their_transport);
+  }
+
+  IpczConnectNodeFlags GetExtraClientConnectNodeFlags() const override {
+    return IPCZ_NO_FLAGS;
+  }
+
+  IpczDriverHandle GetClientTestNodeTransport() override {
+    PlatformChannelEndpoint endpoint =
+        PlatformChannelEndpoint::RecoverFromString(
+            base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+                PlatformChannel::kHandleSwitch));
+    return Transport::ReleaseAsHandle(base::MakeRefCounted<Transport>(
+        Transport::kToBroker, std::move(endpoint)));
+  }
+
+ private:
+  ipcz::Ref<ipcz::test::TestNode::TestNodeController> SpawnTestNodeThread(
+      ipcz::test::TestNode& source,
+      const ipcz::test::TestNodeDetails& details,
+      IpczDriverHandle our_transport,
+      IpczDriverHandle their_transport) {
+    std::unique_ptr<ipcz::test::TestNode> node = details.factory();
+    node->SetTransport(their_transport);
+    Transport::FromHandle(our_transport)
+        ->set_remote_process(base::Process::Current());
+    return ipcz::MakeRefCounted<MojoIpczInProcessTestNodeController>(
+        std::string(details.name.begin(), details.name.end()), std::move(node),
+        this);
+  }
+
+  ipcz::Ref<ipcz::test::TestNode::TestNodeController> SpawnTestNodeProcess(
+      ipcz::test::TestNode& source,
+      const ipcz::test::TestNodeDetails& details,
+      IpczDriverHandle our_transport,
+      IpczDriverHandle their_transport) {
+    const std::string test_child_main = base::StrCat(
+        {details.name.data(), "/", kMojoIpczMultiprocessTestDriverName});
+    base::CommandLine command_line(
+        base::GetMultiProcessTestChildBaseCommandLine().GetProgram());
+
+    std::set<std::string> uninherited_args;
+    uninherited_args.insert(PlatformChannel::kHandleSwitch);
+    uninherited_args.insert(switches::kTestChildProcess);
+
+    // Copy commandline switches from the parent process, except for the
+    // multiprocess client name and mojo message pipe handle; this allows test
+    // clients to spawn other test clients.
+    for (const auto& entry :
+         base::CommandLine::ForCurrentProcess()->GetSwitches()) {
+      if (uninherited_args.find(entry.first) == uninherited_args.end())
+        command_line.AppendSwitchNative(entry.first, entry.second);
+    }
+
+    base::LaunchOptions options;
+    scoped_refptr<Transport> transport =
+        Transport::TakeFromHandle(their_transport);
+    PlatformChannelEndpoint endpoint = transport->TakeEndpoint();
+    endpoint.PrepareToPass(options, command_line);
+#if BUILDFLAG(IS_WIN)
+    options.start_hidden = true;
+#endif
+
+    base::Process child = base::SpawnMultiProcessTestChild(
+        test_child_main, command_line, options);
+    endpoint.ProcessLaunchAttempted();
+    Transport::FromHandle(our_transport)->set_remote_process(child.Duplicate());
+    return ipcz::MakeRefCounted<MojoIpczChildTestNodeController>(
+        std::move(child));
+  }
+
+  const Mode mode_;
+};
+
+ipcz::test::TestDriverRegistration<MojoIpczTestDriver> kRegisterInProcessDriver{
+    MojoIpczTestDriver::kInProcess};
+
+#if !BUILDFLAG(IS_IOS)
+ipcz::test::TestDriverRegistration<MojoIpczTestDriver>
+    kRegisterMultiprocessDriver{MojoIpczTestDriver::kMultiprocess};
+#endif
+
+}  // namespace
+}  // namespace mojo::core::ipcz_driver
diff --git a/mojo/core/ipcz_driver/transport.cc b/mojo/core/ipcz_driver/transport.cc
index 98ea0f2d..069778fc 100644
--- a/mojo/core/ipcz_driver/transport.cc
+++ b/mojo/core/ipcz_driver/transport.cc
@@ -491,7 +491,7 @@
 bool Transport::ShouldSerializeProcessHandle(Transport& transmitter) const {
 #if BUILDFLAG(IS_WIN)
   return remote_process_.IsValid() && !remote_process_.is_current() &&
-         destination_ == kToBroker;
+         transmitter.destination() == kToBroker;
 #else
   // We have no need for the process handle on other platforms.
   return false;
diff --git a/mojo/core/ipcz_driver/transport.h b/mojo/core/ipcz_driver/transport.h
index eae0922..af37560 100644
--- a/mojo/core/ipcz_driver/transport.h
+++ b/mojo/core/ipcz_driver/transport.h
@@ -9,8 +9,10 @@
 #include <cstdint>
 #include <utility>
 
+#include "base/check.h"
 #include "base/containers/span.h"
 #include "base/memory/scoped_refptr.h"
+#include "base/process/process.h"
 #include "base/synchronization/lock.h"
 #include "base/task/single_thread_task_runner.h"
 #include "mojo/core/channel.h"
@@ -45,6 +47,20 @@
   Destination destination() const { return destination_; }
   const base::Process& remote_process() const { return remote_process_; }
 
+  // Provides a handle to the remote process on the other end of this transport.
+  // If this is called, it must be before the Transport is activated.
+  void set_remote_process(base::Process process) {
+    DCHECK(!remote_process_.IsValid());
+    remote_process_ = std::move(process);
+  }
+
+  // Takes ownership of the Transport's underlying channel endpoint, effectively
+  // invalidating the transport. May only be called on a Transport which has not
+  // yet been activated.
+  PlatformChannelEndpoint TakeEndpoint() {
+    return std::move(inactive_endpoint_);
+  }
+
   // Activates this transport by creating and starting the underlying Channel
   // instance.
   bool Activate(IpczHandle transport,
@@ -123,7 +139,7 @@
   bool ShouldSerializeProcessHandle(Transport& transmitter) const;
 
   const Destination destination_;
-  const base::Process remote_process_;
+  base::Process remote_process_;
 
   // The channel endpoint which will be used by this Transport to construct and
   // start its underlying Channel instance once activated. Not guarded by a lock
diff --git a/mojo/public/cpp/platform/platform_channel.cc b/mojo/public/cpp/platform/platform_channel.cc
index c27084b9..c3428468 100644
--- a/mojo/public/cpp/platform/platform_channel.cc
+++ b/mojo/public/cpp/platform/platform_channel.cc
@@ -13,8 +13,6 @@
 #include "base/logging.h"
 #include "base/numerics/clamped_math.h"
 #include "base/rand_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
@@ -123,24 +121,6 @@
   *remote_endpoint = PlatformHandle(std::move(receive));
 }
 #elif BUILDFLAG(IS_POSIX)
-
-#if BUILDFLAG(IS_ANDROID)
-// Leave room for any other descriptors defined in content for example.
-// TODO(https://crbug.com/676442): Consider changing base::GlobalDescriptors to
-// generate a key when setting the file descriptor.
-constexpr int kAndroidClientHandleDescriptor =
-    base::GlobalDescriptors::kBaseDescriptor + 10000;
-#else
-bool IsTargetDescriptorUsed(const base::FileHandleMappingVector& mapping,
-                            int target_fd) {
-  for (size_t i = 0; i < mapping.size(); ++i) {
-    if (mapping[i].second == target_fd)
-      return true;
-  }
-  return false;
-}
-#endif
-
 void CreateChannel(PlatformHandle* local_endpoint,
                    PlatformHandle* remote_endpoint) {
   int fds[2];
@@ -194,142 +174,29 @@
 
 void PlatformChannel::PrepareToPassRemoteEndpoint(HandlePassingInfo* info,
                                                   std::string* value) {
-  DCHECK(value);
-  DCHECK(remote_endpoint_.is_valid());
-
-#if BUILDFLAG(IS_WIN)
-  info->push_back(remote_endpoint_.platform_handle().GetHandle().Get());
-  *value = base::NumberToString(
-      HandleToLong(remote_endpoint_.platform_handle().GetHandle().Get()));
-#elif BUILDFLAG(IS_FUCHSIA)
-  const uint32_t id = base::LaunchOptions::AddHandleToTransfer(
-      info, remote_endpoint_.platform_handle().GetHandle().get());
-  *value = base::NumberToString(id);
-#elif BUILDFLAG(IS_ANDROID)
-  int fd = remote_endpoint_.platform_handle().GetFD().get();
-  int mapped_fd = kAndroidClientHandleDescriptor + info->size();
-  info->emplace_back(fd, mapped_fd);
-  *value = base::NumberToString(mapped_fd);
-#elif BUILDFLAG(IS_MAC)
-  DCHECK(remote_endpoint_.platform_handle().is_mach_receive());
-  base::mac::ScopedMachReceiveRight receive_right =
-      remote_endpoint_.TakePlatformHandle().TakeMachReceiveRight();
-  base::MachPortsForRendezvous::key_type rendezvous_key = 0;
-  do {
-    rendezvous_key = static_cast<decltype(rendezvous_key)>(base::RandUint64());
-  } while (info->find(rendezvous_key) != info->end());
-  auto it = info->insert(std::make_pair(
-      rendezvous_key, base::MachRendezvousPort(std::move(receive_right))));
-  DCHECK(it.second) << "Failed to insert port for rendezvous.";
-  *value = base::NumberToString(rendezvous_key);
-#elif BUILDFLAG(IS_POSIX)
-  // Arbitrary sanity check to ensure the loop below terminates reasonably
-  // quickly.
-  CHECK_LT(info->size(), 1000u);
-
-  // Find a suitable FD to map the remote endpoint handle to in the child
-  // process. This has quadratic time complexity in the size of |*info|, but
-  // |*info| should be very small and is usually empty.
-  int target_fd = base::GlobalDescriptors::kBaseDescriptor;
-  while (IsTargetDescriptorUsed(*info, target_fd))
-    ++target_fd;
-  info->emplace_back(remote_endpoint_.platform_handle().GetFD().get(),
-                     target_fd);
-  *value = base::NumberToString(target_fd);
-#endif
+  remote_endpoint_.PrepareToPass(*info, *value);
 }
 
 void PlatformChannel::PrepareToPassRemoteEndpoint(
     HandlePassingInfo* info,
     base::CommandLine* command_line) {
-  std::string value;
-  PrepareToPassRemoteEndpoint(info, &value);
-  if (!value.empty())
-    command_line->AppendSwitchASCII(kHandleSwitch, value);
+  remote_endpoint_.PrepareToPass(*info, *command_line);
 }
 
 void PlatformChannel::PrepareToPassRemoteEndpoint(
     base::LaunchOptions* options,
     base::CommandLine* command_line) {
-#if BUILDFLAG(IS_WIN)
-  PrepareToPassRemoteEndpoint(&options->handles_to_inherit, command_line);
-#elif BUILDFLAG(IS_FUCHSIA)
-  PrepareToPassRemoteEndpoint(&options->handles_to_transfer, command_line);
-#elif BUILDFLAG(IS_MAC)
-  PrepareToPassRemoteEndpoint(&options->mach_ports_for_rendezvous,
-                              command_line);
-#elif BUILDFLAG(IS_POSIX)
-  PrepareToPassRemoteEndpoint(&options->fds_to_remap, command_line);
-#else
-#error "Platform not supported."
-#endif
+  remote_endpoint_.PrepareToPass(*options, *command_line);
 }
 
 void PlatformChannel::RemoteProcessLaunchAttempted() {
-#if BUILDFLAG(IS_FUCHSIA)
-  // Unlike other platforms, Fuchsia transfers handle ownership to the new
-  // process, rather than duplicating it. For consistency the process-launch
-  // call will have consumed the handle regardless of whether launch succeeded.
-  DCHECK(remote_endpoint_.platform_handle().is_valid_handle());
-  std::ignore = remote_endpoint_.TakePlatformHandle().ReleaseHandle();
-#else
-  remote_endpoint_.reset();
-#endif
+  remote_endpoint_.ProcessLaunchAttempted();
 }
 
 // static
 PlatformChannelEndpoint PlatformChannel::RecoverPassedEndpointFromString(
     base::StringPiece value) {
-#if BUILDFLAG(IS_WIN)
-  int handle_value = 0;
-  if (value.empty() || !base::StringToInt(value, &handle_value)) {
-    DLOG(ERROR) << "Invalid PlatformChannel endpoint string.";
-    return PlatformChannelEndpoint();
-  }
-  return PlatformChannelEndpoint(
-      PlatformHandle(base::win::ScopedHandle(LongToHandle(handle_value))));
-#elif BUILDFLAG(IS_FUCHSIA)
-  unsigned int handle_value = 0;
-  if (value.empty() || !base::StringToUint(value, &handle_value)) {
-    DLOG(ERROR) << "Invalid PlatformChannel endpoint string.";
-    return PlatformChannelEndpoint();
-  }
-  return PlatformChannelEndpoint(PlatformHandle(zx::handle(
-      zx_take_startup_handle(base::checked_cast<uint32_t>(handle_value)))));
-#elif BUILDFLAG(IS_ANDROID)
-  base::GlobalDescriptors::Key key = -1;
-  if (value.empty() || !base::StringToUint(value, &key)) {
-    DLOG(ERROR) << "Invalid PlatformChannel endpoint string.";
-    return PlatformChannelEndpoint();
-  }
-  return PlatformChannelEndpoint(PlatformHandle(
-      base::ScopedFD(base::GlobalDescriptors::GetInstance()->Get(key))));
-#elif BUILDFLAG(IS_MAC)
-  auto* client = base::MachPortRendezvousClient::GetInstance();
-  if (!client) {
-    DLOG(ERROR) << "Mach rendezvous failed.";
-    return PlatformChannelEndpoint();
-  }
-  uint32_t rendezvous_key = 0;
-  if (value.empty() || !base::StringToUint(value, &rendezvous_key)) {
-    DLOG(ERROR) << "Invalid PlatformChannel rendezvous key.";
-    return PlatformChannelEndpoint();
-  }
-  auto receive = client->TakeReceiveRight(rendezvous_key);
-  if (!receive.is_valid()) {
-    DLOG(ERROR) << "Invalid PlatformChannel receive right.";
-    return PlatformChannelEndpoint();
-  }
-  return PlatformChannelEndpoint(PlatformHandle(std::move(receive)));
-#elif BUILDFLAG(IS_POSIX)
-  int fd = -1;
-  if (value.empty() || !base::StringToInt(value, &fd) ||
-      fd < base::GlobalDescriptors::kBaseDescriptor) {
-    DLOG(ERROR) << "Invalid PlatformChannel endpoint string.";
-    return PlatformChannelEndpoint();
-  }
-  return PlatformChannelEndpoint(PlatformHandle(base::ScopedFD(fd)));
-#endif
+  return PlatformChannelEndpoint::RecoverFromString(value);
 }
 
 // static
diff --git a/mojo/public/cpp/platform/platform_channel.h b/mojo/public/cpp/platform/platform_channel.h
index 33f8e6f6..91ba682 100644
--- a/mojo/public/cpp/platform/platform_channel.h
+++ b/mojo/public/cpp/platform/platform_channel.h
@@ -34,19 +34,7 @@
   // command line when the relevant methods are used on this class.
   static const char kHandleSwitch[];
 
-// Unfortunately base process support code has no unified handle-passing
-// data pipe, so we have this.
-#if BUILDFLAG(IS_WIN)
-  using HandlePassingInfo = base::HandlesToInheritVector;
-#elif BUILDFLAG(IS_FUCHSIA)
-  using HandlePassingInfo = base::HandlesToTransferVector;
-#elif BUILDFLAG(IS_MAC)
-  using HandlePassingInfo = base::MachPortsForRendezvous;
-#elif BUILDFLAG(IS_POSIX)
-  using HandlePassingInfo = base::FileHandleMappingVector;
-#else
-#error "Unsupported platform."
-#endif
+  using HandlePassingInfo = PlatformChannelEndpoint::HandlePassingInfo;
 
   PlatformChannel();
   PlatformChannel(PlatformChannel&& other);
diff --git a/mojo/public/cpp/platform/platform_channel_endpoint.cc b/mojo/public/cpp/platform/platform_channel_endpoint.cc
index 0ebc133..652364ee 100644
--- a/mojo/public/cpp/platform/platform_channel_endpoint.cc
+++ b/mojo/public/cpp/platform/platform_channel_endpoint.cc
@@ -4,8 +4,55 @@
 
 #include "mojo/public/cpp/platform/platform_channel_endpoint.h"
 
+#include <string>
+#include <tuple>
+#include <utility>
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/rand_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "build/build_config.h"
+#include "mojo/public/cpp/platform/platform_channel.h"
+
+#if BUILDFLAG(IS_MAC)
+#include <mach/port.h>
+
+#include "base/mac/scoped_mach_port.h"
+#elif BUILDFLAG(IS_FUCHSIA)
+#include <lib/zx/handle.h>
+#elif BUILDFLAG(IS_POSIX)
+#include "base/files/scoped_file.h"
+#include "base/posix/global_descriptors.h"
+#elif BUILDFLAG(IS_WIN)
+#include <windows.h>
+
+#include "base/win/scoped_handle.h"
+#endif
+
 namespace mojo {
 
+namespace {
+
+#if BUILDFLAG(IS_ANDROID)
+// Leave room for any other descriptors defined in content for example.
+// TODO(https://crbug.com/676442): Consider changing base::GlobalDescriptors to
+// generate a key when setting the file descriptor.
+constexpr int kAndroidClientHandleDescriptor =
+    base::GlobalDescriptors::kBaseDescriptor + 10000;
+#elif BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
+bool IsTargetDescriptorUsed(const base::FileHandleMappingVector& mapping,
+                            int target_fd) {
+  for (auto& [i, fd] : mapping) {
+    if (fd == target_fd)
+      return true;
+  }
+  return false;
+}
+#endif
+
+}  // namespace
+
 PlatformChannelEndpoint::PlatformChannelEndpoint() = default;
 
 PlatformChannelEndpoint::PlatformChannelEndpoint(
@@ -27,4 +74,140 @@
   return PlatformChannelEndpoint(handle_.Clone());
 }
 
+void PlatformChannelEndpoint::PrepareToPass(HandlePassingInfo& info,
+                                            base::CommandLine& command_line) {
+  std::string value;
+  PrepareToPass(info, value);
+  if (!value.empty()) {
+    command_line.AppendSwitchASCII(PlatformChannel::kHandleSwitch, value);
+  }
+}
+
+void PlatformChannelEndpoint::PrepareToPass(HandlePassingInfo& info,
+                                            std::string& value) {
+  DCHECK(is_valid());
+#if BUILDFLAG(IS_WIN)
+  info.push_back(platform_handle().GetHandle().Get());
+  value =
+      base::NumberToString(HandleToLong(platform_handle().GetHandle().Get()));
+#elif BUILDFLAG(IS_FUCHSIA)
+  const uint32_t id = base::LaunchOptions::AddHandleToTransfer(
+      &info, platform_handle().GetHandle().get());
+  value = base::NumberToString(id);
+#elif BUILDFLAG(IS_ANDROID)
+  int fd = platform_handle().GetFD().get();
+  int mapped_fd = kAndroidClientHandleDescriptor + info.size();
+  info.emplace_back(fd, mapped_fd);
+  value = base::NumberToString(mapped_fd);
+#elif BUILDFLAG(IS_MAC)
+  DCHECK(platform_handle().is_mach_receive());
+  base::mac::ScopedMachReceiveRight receive_right =
+      TakePlatformHandle().TakeMachReceiveRight();
+  base::MachPortsForRendezvous::key_type rendezvous_key = 0;
+  do {
+    rendezvous_key = static_cast<decltype(rendezvous_key)>(base::RandUint64());
+  } while (info.find(rendezvous_key) != info.end());
+  auto it = info.insert(std::make_pair(
+      rendezvous_key, base::MachRendezvousPort(std::move(receive_right))));
+  DCHECK(it.second) << "Failed to insert port for rendezvous.";
+  value = base::NumberToString(rendezvous_key);
+#elif BUILDFLAG(IS_POSIX)
+  // Arbitrary sanity check to ensure the loop below terminates reasonably
+  // quickly.
+  CHECK_LT(info.size(), 1000u);
+
+  // Find a suitable FD to map the remote endpoint handle to in the child
+  // process. This has quadratic time complexity in the size of |*info|, but
+  // |*info| should be very small and is usually empty.
+  int target_fd = base::GlobalDescriptors::kBaseDescriptor;
+  while (IsTargetDescriptorUsed(info, target_fd)) {
+    ++target_fd;
+  }
+  info.emplace_back(platform_handle().GetFD().get(), target_fd);
+  value = base::NumberToString(target_fd);
+#endif
+}
+
+void PlatformChannelEndpoint::PrepareToPass(base::LaunchOptions& options,
+                                            base::CommandLine& command_line) {
+#if BUILDFLAG(IS_WIN)
+  PrepareToPass(options.handles_to_inherit, command_line);
+#elif BUILDFLAG(IS_FUCHSIA)
+  PrepareToPass(options.handles_to_transfer, command_line);
+#elif BUILDFLAG(IS_MAC)
+  PrepareToPass(options.mach_ports_for_rendezvous, command_line);
+#elif BUILDFLAG(IS_POSIX)
+  PrepareToPass(options.fds_to_remap, command_line);
+#else
+#error "Platform not supported."
+#endif
+}
+
+void PlatformChannelEndpoint::ProcessLaunchAttempted() {
+#if BUILDFLAG(IS_FUCHSIA)
+  // Unlike other platforms, Fuchsia transfers handle ownership to the new
+  // process, rather than duplicating it. For consistency the process-launch
+  // call will have consumed the handle regardless of whether launch succeeded.
+  DCHECK(platform_handle().is_valid_handle());
+  std::ignore = TakePlatformHandle().ReleaseHandle();
+#else
+  reset();
+#endif
+}
+
+// static
+PlatformChannelEndpoint PlatformChannelEndpoint::RecoverFromString(
+    base::StringPiece value) {
+#if BUILDFLAG(IS_WIN)
+  int handle_value = 0;
+  if (value.empty() || !base::StringToInt(value, &handle_value)) {
+    DLOG(ERROR) << "Invalid PlatformChannel endpoint string.";
+    return PlatformChannelEndpoint();
+  }
+  return PlatformChannelEndpoint(
+      PlatformHandle(base::win::ScopedHandle(LongToHandle(handle_value))));
+#elif BUILDFLAG(IS_FUCHSIA)
+  unsigned int handle_value = 0;
+  if (value.empty() || !base::StringToUint(value, &handle_value)) {
+    DLOG(ERROR) << "Invalid PlatformChannel endpoint string.";
+    return PlatformChannelEndpoint();
+  }
+  return PlatformChannelEndpoint(PlatformHandle(zx::handle(
+      zx_take_startup_handle(base::checked_cast<uint32_t>(handle_value)))));
+#elif BUILDFLAG(IS_ANDROID)
+  base::GlobalDescriptors::Key key = -1;
+  if (value.empty() || !base::StringToUint(value, &key)) {
+    DLOG(ERROR) << "Invalid PlatformChannel endpoint string.";
+    return PlatformChannelEndpoint();
+  }
+  return PlatformChannelEndpoint(PlatformHandle(
+      base::ScopedFD(base::GlobalDescriptors::GetInstance()->Get(key))));
+#elif BUILDFLAG(IS_MAC)
+  auto* client = base::MachPortRendezvousClient::GetInstance();
+  if (!client) {
+    DLOG(ERROR) << "Mach rendezvous failed.";
+    return PlatformChannelEndpoint();
+  }
+  uint32_t rendezvous_key = 0;
+  if (value.empty() || !base::StringToUint(value, &rendezvous_key)) {
+    DLOG(ERROR) << "Invalid PlatformChannel rendezvous key.";
+    return PlatformChannelEndpoint();
+  }
+  auto receive = client->TakeReceiveRight(rendezvous_key);
+  if (!receive.is_valid()) {
+    DLOG(ERROR) << "Invalid PlatformChannel receive right.";
+    return PlatformChannelEndpoint();
+  }
+  return PlatformChannelEndpoint(PlatformHandle(std::move(receive)));
+#elif BUILDFLAG(IS_POSIX)
+  int fd = -1;
+  if (value.empty() || !base::StringToInt(value, &fd) ||
+      fd < base::GlobalDescriptors::kBaseDescriptor) {
+    DLOG(ERROR) << "Invalid PlatformChannel endpoint string.";
+    return PlatformChannelEndpoint();
+  }
+  return PlatformChannelEndpoint(PlatformHandle(base::ScopedFD(fd)));
+#endif
+}
+
 }  // namespace mojo
diff --git a/mojo/public/cpp/platform/platform_channel_endpoint.h b/mojo/public/cpp/platform/platform_channel_endpoint.h
index 69abce9..8346454 100644
--- a/mojo/public/cpp/platform/platform_channel_endpoint.h
+++ b/mojo/public/cpp/platform/platform_channel_endpoint.h
@@ -5,7 +5,11 @@
 #ifndef MOJO_PUBLIC_CPP_PLATFORM_PLATFORM_CHANNEL_ENDPOINT_H_
 #define MOJO_PUBLIC_CPP_PLATFORM_PLATFORM_CHANNEL_ENDPOINT_H_
 
+#include "base/command_line.h"
 #include "base/component_export.h"
+#include "base/process/launch.h"
+#include "base/strings/string_piece.h"
+#include "build/build_config.h"
 #include "mojo/public/cpp/platform/platform_handle.h"
 
 namespace mojo {
@@ -16,6 +20,20 @@
 // PlatformChannelEndpoint.
 class COMPONENT_EXPORT(MOJO_CPP_PLATFORM) PlatformChannelEndpoint {
  public:
+// Unfortunately base process support code has no unified handle-passing
+// data pipe, so we have this.
+#if BUILDFLAG(IS_WIN)
+  using HandlePassingInfo = base::HandlesToInheritVector;
+#elif BUILDFLAG(IS_FUCHSIA)
+  using HandlePassingInfo = base::HandlesToTransferVector;
+#elif BUILDFLAG(IS_MAC)
+  using HandlePassingInfo = base::MachPortsForRendezvous;
+#elif BUILDFLAG(IS_POSIX)
+  using HandlePassingInfo = base::FileHandleMappingVector;
+#else
+#error "Unsupported platform."
+#endif
+
   PlatformChannelEndpoint();
   PlatformChannelEndpoint(PlatformChannelEndpoint&& other);
   explicit PlatformChannelEndpoint(PlatformHandle handle);
@@ -37,6 +55,34 @@
     return std::move(handle_);
   }
 
+  // Prepares to pass this endpoint handle to a process that will soon be
+  // launched. Returns a string that can be used in the remote process with
+  // RecoverFromString() (see below). The string can be passed on the new
+  // process's command line.
+  //
+  // NOTE: If this method is called it is important to also call
+  // ProcessLaunchAttempted() on this endpoint *after* attempting to launch
+  // the new process, regardless of whether the attempt succeeded. Failing to do
+  // so can result in leaked handles on some platforms.
+  void PrepareToPass(HandlePassingInfo& info, std::string& value);
+
+  // Like above but modifies `command_line` to include the endpoint string
+  // via the PlatformChannel::kHandleSwitch flag.
+  void PrepareToPass(HandlePassingInfo& info, base::CommandLine& command_line);
+
+  // Like above but adds handle-passing information directly to
+  // `launch_options`, eliminating the potential need for callers to write
+  // platform-specific code to do the same.
+  void PrepareToPass(base::LaunchOptions& options,
+                     base::CommandLine& command_line);
+
+  // Must be called after the corresponding process launch attempt if
+  // PrepareToPass() was called.
+  void ProcessLaunchAttempted();
+
+  [[nodiscard]] static PlatformChannelEndpoint RecoverFromString(
+      base::StringPiece value);
+
  private:
   PlatformHandle handle_;
 };
diff --git a/native_client_sdk/src/doc/OWNERS b/native_client_sdk/src/doc/OWNERS
index 61fe60d..73b8761 100644
--- a/native_client_sdk/src/doc/OWNERS
+++ b/native_client_sdk/src/doc/OWNERS
@@ -1,3 +1,2 @@
-binji@chromium.org
 bradnelson@chromium.org
 sbc@chromium.org
diff --git a/net/base/features.cc b/net/base/features.cc
index a43cca4..539ba96b9 100644
--- a/net/base/features.cc
+++ b/net/base/features.cc
@@ -344,4 +344,10 @@
 // by the top level site to reduce fingerprinting.
 const base::Feature kThirdPartyStoragePartitioning{
     "ThirdPartyStoragePartitioning", base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kAlpsParsing{"AlpsParsing",
+                                 base::FEATURE_ENABLED_BY_DEFAULT};
+
+const base::Feature kAlpsClientHintParsing{"AlpsClientHintParsing",
+                                           base::FEATURE_ENABLED_BY_DEFAULT};
 }  // namespace net::features
diff --git a/net/base/features.h b/net/base/features.h
index 6729475..b73a9aa65 100644
--- a/net/base/features.h
+++ b/net/base/features.h
@@ -487,6 +487,12 @@
 
 NET_EXPORT extern const base::Feature kThirdPartyStoragePartitioning;
 
+// Whether ALPS parsing is on for any type of frame.
+NET_EXPORT extern const base::Feature kAlpsParsing;
+
+// Whether ALPS parsing is on for client hint parsing specifically.
+NET_EXPORT extern const base::Feature kAlpsClientHintParsing;
+
 }  // namespace net::features
 
 #endif  // NET_BASE_FEATURES_H_
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index fc53e0b..25273db5 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -370,6 +370,8 @@
 }
 
 int HttpCache::Transaction::TransitionToReadingState() {
+  transaction_state_at_transition_to_reading_state_ =
+      TransactionState::kUnknown;
   if (!entry_) {
     if (network_trans_) {
       // This can happen when the request should be handled exclusively by
@@ -379,6 +381,9 @@
       // is reading the auth response from the network.
       // TODO(http://crbug.com/740947) to get rid of this state in future.
       next_state_ = STATE_NETWORK_READ;
+
+      transaction_state_at_transition_to_reading_state_ =
+          TransactionState::kNetwork;
       return OK;
     }
 
@@ -386,6 +391,8 @@
     // from.
     next_state_ = STATE_NONE;
 
+    transaction_state_at_transition_to_reading_state_ =
+        TransactionState::kUnknown;
     // An error state should be set for the next read, else this transaction
     // should have been terminated once it reached this state. To assert we
     // could dcheck that shared_writing_error_ is set to a valid error value but
@@ -399,12 +406,16 @@
   if (!InWriters()) {
     // Since transaction is not a writer and we are in Read(), it must be a
     // reader.
-    DCHECK(entry_->TransactionInReaders(this));
+    CHECK(entry_->TransactionInReaders(this));
     DCHECK(mode_ == READ || (mode_ == READ_WRITE && partial_));
     next_state_ = STATE_CACHE_READ_DATA;
+    transaction_state_at_transition_to_reading_state_ =
+        TransactionState::kAsReader;
     return OK;
   }
 
+  transaction_state_at_transition_to_reading_state_ =
+      TransactionState::kAsWriter;
   DCHECK(mode_ & WRITE || mode_ == NONE);
 
   // If it's a writer and it is partial then it may need to read from the cache
@@ -2462,6 +2473,11 @@
 }
 
 int HttpCache::Transaction::DoCacheReadData() {
+  SCOPED_CRASH_KEY_STRING32(
+      "net", "transaction state",
+      ToString(transaction_state_at_transition_to_reading_state_));
+  CHECK(InWriters() || entry_->TransactionInReaders(this));
+
   TRACE_EVENT_WITH_FLOW2(
       "net", "HttpCacheTransaction::DoCacheReadData", TRACE_ID_LOCAL(trace_id_),
       TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "read_offset",
@@ -2487,6 +2503,11 @@
 }
 
 int HttpCache::Transaction::DoCacheReadDataComplete(int result) {
+  SCOPED_CRASH_KEY_STRING32(
+      "net", "transaction state",
+      ToString(transaction_state_at_transition_to_reading_state_));
+  CHECK(InWriters() || entry_->TransactionInReaders(this));
+
   TRACE_EVENT_WITH_FLOW1("net", "HttpCacheTransaction::DoCacheReadDataComplete",
                          TRACE_ID_LOCAL(trace_id_),
                          TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
@@ -3957,6 +3978,19 @@
   return;
 }
 
+const char* HttpCache::Transaction::ToString(TransactionState state) {
+  switch (state) {
+    case TransactionState::kUnknown:
+      return "unknown";
+    case TransactionState::kNetwork:
+      return "network";
+    case TransactionState::kAsWriter:
+      return "writer";
+    case TransactionState::kAsReader:
+      return "reader";
+  }
+}
+
 void HttpCache::Transaction::ChecksumHeaders() {
   DCHECK(use_single_keyed_cache_);
   DCHECK(!checksum_);
diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h
index 0a937a3..554ac878 100644
--- a/net/http/http_cache_transaction.h
+++ b/net/http/http_cache_transaction.h
@@ -317,6 +317,18 @@
     HINT_UNUSABLE_PER_CACHING_HEADERS = (1 << 0),
   };
 
+  // An enum representing the state of this transaction. This is for debugging.
+  enum class TransactionState : uint8_t {
+    // Unknown state.
+    kUnknown,
+    // This transaction is directly talking to the network.
+    kNetwork,
+    // This transaction is held by a cache entry as a writer.
+    kAsWriter,
+    // This transaction is held by a cache entry as a reader.
+    kAsReader,
+  };
+
   // Runs the state transition loop. Resets and calls |callback_| on exit,
   // unless the return value is ERR_IO_PENDING.
   int DoLoop(int result);
@@ -608,6 +620,8 @@
   // forwarded might need to set these headers again to avoid being blocked.
   void UpdateSecurityHeadersBeforeForwarding();
 
+  static const char* ToString(TransactionState state);
+
   State next_state_{STATE_NONE};
 
   // Used for tracing.
@@ -740,6 +754,10 @@
   // True if the Transaction is currently processing the DoLoop.
   bool in_do_loop_ = false;
 
+  // The transaction state at TransitionToReadingState. This is for debugging.
+  TransactionState transaction_state_at_transition_to_reading_state_ =
+      TransactionState::kUnknown;
+
   base::WeakPtrFactory<Transaction> weak_factory_{this};
 };
 
diff --git a/net/spdy/alps_decoder.cc b/net/spdy/alps_decoder.cc
index 69c8b71..f07a6670 100644
--- a/net/spdy/alps_decoder.cc
+++ b/net/spdy/alps_decoder.cc
@@ -4,6 +4,9 @@
 
 #include "net/spdy/alps_decoder.h"
 
+#include "base/feature_list.h"
+#include "net/base/features.h"
+
 namespace net {
 namespace {
 
@@ -101,23 +104,34 @@
                                                 size_t length,
                                                 uint8_t type,
                                                 uint8_t flags) {
-  if (type != static_cast<uint8_t>(spdy::SpdyFrameType::ACCEPT_CH) ||
-      error_ != Error::kNoError) {
-    // Ignore every frame except for ACCEPT_CH.
-    // Ignore data after an error has occurred.
-    // Returning false causes Http2DecoderAdapter not to call OnFramePayload().
+  // Ignore data after an error has occurred.
+  if (error_ != Error::kNoError)
     return false;
-  }
-  if (stream_id != 0) {
-    error_ = Error::kAcceptChInvalidStream;
+  // Stop all alps parsing if it's disabled.
+  if (!base::FeatureList::IsEnabled(features::kAlpsParsing))
     return false;
+  // Handle per-type parsing.
+  switch (type) {
+    case static_cast<uint8_t>(spdy::SpdyFrameType::ACCEPT_CH): {
+      // Stop alps client hint parsing if it's disabled.
+      if (!base::FeatureList::IsEnabled(features::kAlpsClientHintParsing))
+        return false;
+      // Check for issues with the frame.
+      if (stream_id != 0) {
+        error_ = Error::kAcceptChInvalidStream;
+        return false;
+      }
+      if (flags != 0) {
+        error_ = Error::kAcceptChWithFlags;
+        return false;
+      }
+      // This frame can be parsed in OnFramePayload.
+      return true;
+    }
+    default:
+      // Ignore all other types.
+      return false;
   }
-  if (flags != 0) {
-    error_ = Error::kAcceptChWithFlags;
-    return false;
-  }
-
-  return true;
 }
 
 void AlpsDecoder::AcceptChParser::OnFramePayload(const char* data, size_t len) {
diff --git a/net/spdy/alps_decoder_test.cc b/net/spdy/alps_decoder_test.cc
index 80c98c3a..e2aba3c3 100644
--- a/net/spdy/alps_decoder_test.cc
+++ b/net/spdy/alps_decoder_test.cc
@@ -4,6 +4,8 @@
 
 #include "net/spdy/alps_decoder.h"
 
+#include "base/test/scoped_feature_list.h"
+#include "net/base/features.h"
 #include "net/base/hex_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -123,6 +125,58 @@
                                                   accept_ch_tokens}));
 }
 
+TEST(AlpsDecoderTest, DisableAlpsParsing) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(features::kAlpsParsing);
+  AlpsDecoder decoder;
+  AlpsDecoder::Error error = decoder.Decode(HexDecode(
+      // ACCEPT_CH frame
+      "00003d"                    // length
+      "89"                        // type ACCEPT_CH
+      "00"                        // flags
+      "00000000"                  // stream ID
+      "0017"                      // origin length
+      "68747470733a2f2f7777772e"  //
+      "6578616d706c652e636f6d"    // origin "https://www.example.com"
+      "0003"                      // value length
+      "666f6f"                    // value "foo"
+      "0018"                      // origin length
+      "68747470733a2f2f6d61696c"  //
+      "2e6578616d706c652e636f6d"  // origin "https://mail.example.com"
+      "0003"                      // value length
+      "626172"                    // value "bar"
+      ));
+
+  EXPECT_EQ(AlpsDecoder::Error::kNoError, error);
+  EXPECT_THAT(decoder.GetAcceptCh(), IsEmpty());
+}
+
+TEST(AlpsDecoderTest, DisableAlpsClientHintParsing) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(features::kAlpsClientHintParsing);
+  AlpsDecoder decoder;
+  AlpsDecoder::Error error = decoder.Decode(HexDecode(
+      // ACCEPT_CH frame
+      "00003d"                    // length
+      "89"                        // type ACCEPT_CH
+      "00"                        // flags
+      "00000000"                  // stream ID
+      "0017"                      // origin length
+      "68747470733a2f2f7777772e"  //
+      "6578616d706c652e636f6d"    // origin "https://www.example.com"
+      "0003"                      // value length
+      "666f6f"                    // value "foo"
+      "0018"                      // origin length
+      "68747470733a2f2f6d61696c"  //
+      "2e6578616d706c652e636f6d"  // origin "https://mail.example.com"
+      "0003"                      // value length
+      "626172"                    // value "bar"
+      ));
+
+  EXPECT_EQ(AlpsDecoder::Error::kNoError, error);
+  EXPECT_THAT(decoder.GetAcceptCh(), IsEmpty());
+}
+
 TEST(AlpsDecoderTest, IncompleteFrame) {
   AlpsDecoder decoder;
   AlpsDecoder::Error error =
diff --git a/services/shape_detection/face_detection_impl_mac_unittest.mm b/services/shape_detection/face_detection_impl_mac_unittest.mm
index 4dc41ad..b3fcc33 100644
--- a/services/shape_detection/face_detection_impl_mac_unittest.mm
+++ b/services/shape_detection/face_detection_impl_mac_unittest.mm
@@ -54,43 +54,26 @@
   int image_height;
   const char* image_path;
   size_t num_faces;
-  size_t num_landmarks;
-  size_t num_mouth_points;
+  size_t min_num_landmarks;
+  size_t min_num_mouth_points;
   FaceDetectorFactory factory;
 };
 
 std::vector<TestParams> GetTestParams() {
-  if (@available(macOS 10.14, *)) {
-    return {
-        {false, 120, 120, "services/test/data/mona_lisa.jpg", 1, 3, 1,
-         base::BindRepeating(&CreateFaceDetectorImplMac)},
-        {true, 120, 120, "services/test/data/mona_lisa.jpg", 1, 3, 1,
-         base::BindRepeating(&CreateFaceDetectorImplMac)},
-        {false, 120, 120, "services/test/data/mona_lisa.jpg", 1, 4, 10,
-         base::BindRepeating(&CreateFaceDetectorImplMacVision)},
-        {false, 240, 240, "services/test/data/the_beatles.jpg", 4, 3, 1,
-         base::BindRepeating(&CreateFaceDetectorImplMac)},
-        {true, 240, 240, "services/test/data/the_beatles.jpg", 4, 3, 1,
-         base::BindRepeating(&CreateFaceDetectorImplMac)},
-        {false, 240, 240, "services/test/data/the_beatles.jpg", 4, 4, 10,
-         base::BindRepeating(&CreateFaceDetectorImplMacVision)},
-    };
-  } else {
-    return {
-        {false, 120, 120, "services/test/data/mona_lisa.jpg", 1, 3, 1,
-         base::BindRepeating(&CreateFaceDetectorImplMac)},
-        {true, 120, 120, "services/test/data/mona_lisa.jpg", 1, 3, 1,
-         base::BindRepeating(&CreateFaceDetectorImplMac)},
-        {false, 120, 120, "services/test/data/mona_lisa.jpg", 1, 4, 10,
-         base::BindRepeating(&CreateFaceDetectorImplMacVision)},
-        {false, 240, 240, "services/test/data/the_beatles.jpg", 3, 3, 1,
-         base::BindRepeating(&CreateFaceDetectorImplMac)},
-        {true, 240, 240, "services/test/data/the_beatles.jpg", 3, 3, 1,
-         base::BindRepeating(&CreateFaceDetectorImplMac)},
-        {false, 240, 240, "services/test/data/the_beatles.jpg", 4, 4, 10,
-         base::BindRepeating(&CreateFaceDetectorImplMacVision)},
-    };
-  }
+  return {
+      {false, 120, 120, "services/test/data/mona_lisa.jpg", 1, 3, 1,
+       base::BindRepeating(&CreateFaceDetectorImplMac)},
+      {true, 120, 120, "services/test/data/mona_lisa.jpg", 1, 3, 1,
+       base::BindRepeating(&CreateFaceDetectorImplMac)},
+      {false, 120, 120, "services/test/data/mona_lisa.jpg", 1, 4, 10,
+       base::BindRepeating(&CreateFaceDetectorImplMacVision)},
+      {false, 240, 240, "services/test/data/the_beatles.jpg", 4, 3, 1,
+       base::BindRepeating(&CreateFaceDetectorImplMac)},
+      {true, 240, 240, "services/test/data/the_beatles.jpg", 4, 3, 1,
+       base::BindRepeating(&CreateFaceDetectorImplMac)},
+      {false, 240, 240, "services/test/data/the_beatles.jpg", 4, 4, 10,
+       base::BindRepeating(&CreateFaceDetectorImplMacVision)},
+  };
 }
 
 }  // anonymous namespace
@@ -100,16 +83,19 @@
   ~FaceDetectionImplMacTest() override = default;
 
   void DetectCallback(size_t num_faces,
-                      size_t num_landmarks,
-                      size_t num_mouth_points,
+                      size_t min_num_landmarks,
+                      size_t min_num_mouth_points,
                       std::vector<mojom::FaceDetectionResultPtr> results) {
     EXPECT_EQ(num_faces, results.size());
     for (const auto& face : results) {
-      EXPECT_EQ(num_landmarks, face->landmarks.size());
+      // Relying on the OS for detection means evolving results as the OS
+      // improves. Do an "at least as many" check against landmarks and mouth
+      // points to adapt.
+      EXPECT_LE(min_num_landmarks, face->landmarks.size());
       EXPECT_EQ(mojom::LandmarkType::EYE, face->landmarks[0]->type);
       EXPECT_EQ(mojom::LandmarkType::EYE, face->landmarks[1]->type);
       EXPECT_EQ(mojom::LandmarkType::MOUTH, face->landmarks[2]->type);
-      EXPECT_EQ(num_mouth_points, face->landmarks[2]->locations.size());
+      EXPECT_LE(min_num_mouth_points, face->landmarks[2]->locations.size());
     }
     Detection();
   }
@@ -123,8 +109,7 @@
   impl_ = GetParam().factory.Run(mojom::FaceDetectorOptions::New());
 }
 
-// Flakily fails on multiple configurations. https://crbug.com/1107962
-TEST_P(FaceDetectionImplMacTest, DISABLED_ScanOneFace) {
+TEST_P(FaceDetectionImplMacTest, ScanOneFace) {
   // Face detection test needs a GPU.
   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kUseGpuInTests)) {
@@ -158,11 +143,11 @@
   // Send the image to Detect() and expect the response in callback.
   EXPECT_CALL(*this, Detection())
       .WillOnce(RunOnceClosure(run_loop.QuitClosure()));
-  impl_->Detect(
-      *image,
-      base::BindOnce(&FaceDetectionImplMacTest::DetectCallback,
-                     base::Unretained(this), GetParam().num_faces,
-                     GetParam().num_landmarks, GetParam().num_mouth_points));
+  impl_->Detect(*image,
+                base::BindOnce(&FaceDetectionImplMacTest::DetectCallback,
+                               base::Unretained(this), GetParam().num_faces,
+                               GetParam().min_num_landmarks,
+                               GetParam().min_num_mouth_points));
 
   run_loop.Run();
 }
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index 14e5c776..ceed4ba 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -589,6 +589,7 @@
     }
     if (enable_vulkan) {
       sources += skia_vk_sources
+      sources += skia_shared_vk_sources
     }
     deps += [ "//gpu/config:workaround_list" ]
   }
diff --git a/testing/OWNERS b/testing/OWNERS
index 2c027bc..4585370 100644
--- a/testing/OWNERS
+++ b/testing/OWNERS
@@ -1,2 +1,5 @@
 bpastene@chromium.org
 johnchen@chromium.org
+
+per-file BUILD.gn=file://build/OWNERS
+per-file *.gni=file://build/OWNERS
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index a2abdd9..0c3426dd 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -1368,6 +1368,38 @@
       },
       {
         "args": [
+          "--board=eve",
+          "--flash"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "lacros_all_tast_tests eve",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_type": "eve",
+              "os": "ChromeOS"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "lacros_all_tast_tests",
+        "test_id_prefix": "ninja://chromeos/lacros:lacros_all_tast_tests/",
+        "trigger_script": {
+          "script": "//testing/trigger_scripts/chromeos_device_trigger.py"
+        },
+        "variant_id": "eve"
+      },
+      {
+        "args": [
           "--board=amd64-generic",
           "--use-vm"
         ],
@@ -5646,21 +5678,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.83/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.105/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.83",
+        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.105",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.83",
-              "revision": "version:104.0.5112.83"
+              "location": "lacros_version_skew_tests_v104.0.5112.105",
+              "revision": "version:104.0.5112.105"
             }
           ],
           "dimension_sets": [
@@ -5673,7 +5705,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.83"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.105"
       },
       {
         "args": [
@@ -5742,21 +5774,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5248.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5254.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5248.0",
-              "revision": "version:106.0.5248.0"
+              "location": "lacros_version_skew_tests_v107.0.5254.0",
+              "revision": "version:107.0.5254.0"
             }
           ],
           "dimension_sets": [
@@ -5769,7 +5801,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5248.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
       },
       {
         "isolate_profile_data": true,
@@ -5814,21 +5846,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.83/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.105/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.83",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.105",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.83",
-              "revision": "version:104.0.5112.83"
+              "location": "lacros_version_skew_tests_v104.0.5112.105",
+              "revision": "version:104.0.5112.105"
             }
           ],
           "dimension_sets": [
@@ -5840,7 +5872,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.83"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.105"
       },
       {
         "args": [
@@ -5907,21 +5939,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 106.0.5248.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 107.0.5254.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5248.0",
-              "revision": "version:106.0.5248.0"
+              "location": "lacros_version_skew_tests_v107.0.5254.0",
+              "revision": "version:107.0.5254.0"
             }
           ],
           "dimension_sets": [
@@ -5933,7 +5965,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5248.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
       },
       {
         "args": [
@@ -5960,21 +5992,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.83/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.105/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.83",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.105",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.83",
-              "revision": "version:104.0.5112.83"
+              "location": "lacros_version_skew_tests_v104.0.5112.105",
+              "revision": "version:104.0.5112.105"
             }
           ],
           "dimension_sets": [
@@ -5986,7 +6018,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.83"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.105"
       },
       {
         "args": [
@@ -6053,21 +6085,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 106.0.5248.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 107.0.5254.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5248.0",
-              "revision": "version:106.0.5248.0"
+              "location": "lacros_version_skew_tests_v107.0.5254.0",
+              "revision": "version:107.0.5254.0"
             }
           ],
           "dimension_sets": [
@@ -6079,7 +6111,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 106.0.5248.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
       },
       {
         "isolate_profile_data": true,
@@ -6312,6 +6344,24 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
+        "test": "ozone_unittests",
+        "test_id_prefix": "ninja://ui/ozone:ozone_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
         "test": "pdf_unittests",
         "test_id_prefix": "ninja://pdf:pdf_unittests/"
       },
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index e73e4f3..e205cf8 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -99140,21 +99140,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.83/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.105/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.83",
+        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.105",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.83",
-              "revision": "version:104.0.5112.83"
+              "location": "lacros_version_skew_tests_v104.0.5112.105",
+              "revision": "version:104.0.5112.105"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -99162,7 +99162,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.83"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.105"
       },
       {
         "args": [
@@ -99221,21 +99221,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5248.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5254.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5248.0",
-              "revision": "version:106.0.5248.0"
+              "location": "lacros_version_skew_tests_v107.0.5254.0",
+              "revision": "version:107.0.5254.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -99243,7 +99243,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5248.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
       },
       {
         "isolate_profile_data": true,
@@ -99278,28 +99278,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.83/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.105/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.83",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.105",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.83",
-              "revision": "version:104.0.5112.83"
+              "location": "lacros_version_skew_tests_v104.0.5112.105",
+              "revision": "version:104.0.5112.105"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.83"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.105"
       },
       {
         "args": [
@@ -99356,28 +99356,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 106.0.5248.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 107.0.5254.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5248.0",
-              "revision": "version:106.0.5248.0"
+              "location": "lacros_version_skew_tests_v107.0.5254.0",
+              "revision": "version:107.0.5254.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5248.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
       },
       {
         "args": [
@@ -99399,28 +99399,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.83/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.105/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.83",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.105",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.83",
-              "revision": "version:104.0.5112.83"
+              "location": "lacros_version_skew_tests_v104.0.5112.105",
+              "revision": "version:104.0.5112.105"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.83"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.105"
       },
       {
         "args": [
@@ -99477,28 +99477,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 106.0.5248.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 107.0.5254.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5248.0",
-              "revision": "version:106.0.5248.0"
+              "location": "lacros_version_skew_tests_v107.0.5254.0",
+              "revision": "version:107.0.5254.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 106.0.5248.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
       },
       {
         "isolate_profile_data": true,
@@ -99666,6 +99666,19 @@
           "can_use_on_swarming_builders": true,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
+        "test": "ozone_unittests",
+        "test_id_prefix": "ninja://ui/ozone:ozone_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
         "test": "pdf_unittests",
         "test_id_prefix": "ninja://pdf:pdf_unittests/"
       },
@@ -100722,20 +100735,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.83/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.105/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.83",
+        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.105",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.83",
-              "revision": "version:104.0.5112.83"
+              "location": "lacros_version_skew_tests_v104.0.5112.105",
+              "revision": "version:104.0.5112.105"
             }
           ],
           "dimension_sets": [
@@ -100749,7 +100762,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.83"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.105"
       },
       {
         "args": [
@@ -100818,20 +100831,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5248.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5254.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5248.0",
-              "revision": "version:106.0.5248.0"
+              "location": "lacros_version_skew_tests_v107.0.5254.0",
+              "revision": "version:107.0.5254.0"
             }
           ],
           "dimension_sets": [
@@ -100845,7 +100858,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5248.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
       },
       {
         "merge": {
@@ -100890,20 +100903,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.83/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.105/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.83",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.105",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.83",
-              "revision": "version:104.0.5112.83"
+              "location": "lacros_version_skew_tests_v104.0.5112.105",
+              "revision": "version:104.0.5112.105"
             }
           ],
           "dimension_sets": [
@@ -100916,7 +100929,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.83"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.105"
       },
       {
         "args": [
@@ -100983,20 +100996,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 106.0.5248.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 107.0.5254.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5248.0",
-              "revision": "version:106.0.5248.0"
+              "location": "lacros_version_skew_tests_v107.0.5254.0",
+              "revision": "version:107.0.5254.0"
             }
           ],
           "dimension_sets": [
@@ -101009,7 +101022,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5248.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
       },
       {
         "args": [
@@ -101036,20 +101049,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.83/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.105/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.83",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.105",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.83",
-              "revision": "version:104.0.5112.83"
+              "location": "lacros_version_skew_tests_v104.0.5112.105",
+              "revision": "version:104.0.5112.105"
             }
           ],
           "dimension_sets": [
@@ -101062,7 +101075,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.83"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.105"
       },
       {
         "args": [
@@ -101129,20 +101142,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 106.0.5248.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 107.0.5254.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5248.0",
-              "revision": "version:106.0.5248.0"
+              "location": "lacros_version_skew_tests_v107.0.5254.0",
+              "revision": "version:107.0.5254.0"
             }
           ],
           "dimension_sets": [
@@ -101155,7 +101168,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 106.0.5248.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
       },
       {
         "merge": {
@@ -101388,6 +101401,24 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
+        "test": "ozone_unittests",
+        "test_id_prefix": "ninja://ui/ozone:ozone_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04",
+              "ssd": "0"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
         "test": "pdf_unittests",
         "test_id_prefix": "ninja://pdf:pdf_unittests/"
       },
@@ -102549,20 +102580,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.83/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.105/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.83",
+        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.105",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.83",
-              "revision": "version:104.0.5112.83"
+              "location": "lacros_version_skew_tests_v104.0.5112.105",
+              "revision": "version:104.0.5112.105"
             }
           ],
           "dimension_sets": [
@@ -102576,7 +102607,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.83"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.105"
       },
       {
         "args": [
@@ -102645,20 +102676,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5248.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5254.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5248.0",
-              "revision": "version:106.0.5248.0"
+              "location": "lacros_version_skew_tests_v107.0.5254.0",
+              "revision": "version:107.0.5254.0"
             }
           ],
           "dimension_sets": [
@@ -102672,7 +102703,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5248.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
       },
       {
         "merge": {
@@ -102717,20 +102748,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.83/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.105/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.83",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.105",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.83",
-              "revision": "version:104.0.5112.83"
+              "location": "lacros_version_skew_tests_v104.0.5112.105",
+              "revision": "version:104.0.5112.105"
             }
           ],
           "dimension_sets": [
@@ -102743,7 +102774,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.83"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.105"
       },
       {
         "args": [
@@ -102810,20 +102841,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 106.0.5248.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 107.0.5254.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5248.0",
-              "revision": "version:106.0.5248.0"
+              "location": "lacros_version_skew_tests_v107.0.5254.0",
+              "revision": "version:107.0.5254.0"
             }
           ],
           "dimension_sets": [
@@ -102836,7 +102867,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5248.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
       },
       {
         "args": [
@@ -102863,20 +102894,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.83/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.105/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.83",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.105",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.83",
-              "revision": "version:104.0.5112.83"
+              "location": "lacros_version_skew_tests_v104.0.5112.105",
+              "revision": "version:104.0.5112.105"
             }
           ],
           "dimension_sets": [
@@ -102889,7 +102920,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.83"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.105"
       },
       {
         "args": [
@@ -102956,20 +102987,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 106.0.5248.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 107.0.5254.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5248.0",
-              "revision": "version:106.0.5248.0"
+              "location": "lacros_version_skew_tests_v107.0.5254.0",
+              "revision": "version:107.0.5254.0"
             }
           ],
           "dimension_sets": [
@@ -102982,7 +103013,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 106.0.5248.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
       },
       {
         "merge": {
@@ -103215,6 +103246,24 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
+        "test": "ozone_unittests",
+        "test_id_prefix": "ninja://ui/ozone:ozone_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04",
+              "ssd": "0"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
         "test": "pdf_unittests",
         "test_id_prefix": "ninja://pdf:pdf_unittests/"
       },
@@ -103624,20 +103673,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.83/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.105/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.83",
+        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.105",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.83",
-              "revision": "version:104.0.5112.83"
+              "location": "lacros_version_skew_tests_v104.0.5112.105",
+              "revision": "version:104.0.5112.105"
             }
           ],
           "dimension_sets": [
@@ -103650,7 +103699,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.83"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.105"
       },
       {
         "args": [
@@ -103717,20 +103766,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5248.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5254.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5248.0",
-              "revision": "version:106.0.5248.0"
+              "location": "lacros_version_skew_tests_v107.0.5254.0",
+              "revision": "version:107.0.5254.0"
             }
           ],
           "dimension_sets": [
@@ -103743,7 +103792,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5248.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
       }
     ]
   },
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index aca138f..f505cb4 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -20767,21 +20767,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.83/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.105/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.83",
+        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.105",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.83",
-              "revision": "version:104.0.5112.83"
+              "location": "lacros_version_skew_tests_v104.0.5112.105",
+              "revision": "version:104.0.5112.105"
             }
           ],
           "dimension_sets": [
@@ -20794,7 +20794,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.83"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.105"
       },
       {
         "args": [
@@ -20863,21 +20863,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5248.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 107.0.5254.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5248.0",
-              "revision": "version:106.0.5248.0"
+              "location": "lacros_version_skew_tests_v107.0.5254.0",
+              "revision": "version:107.0.5254.0"
             }
           ],
           "dimension_sets": [
@@ -20890,7 +20890,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5248.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
       },
       {
         "isolate_profile_data": true,
@@ -20935,21 +20935,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.83/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.105/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.83",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.105",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.83",
-              "revision": "version:104.0.5112.83"
+              "location": "lacros_version_skew_tests_v104.0.5112.105",
+              "revision": "version:104.0.5112.105"
             }
           ],
           "dimension_sets": [
@@ -20961,7 +20961,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.83"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.105"
       },
       {
         "args": [
@@ -21028,21 +21028,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 106.0.5248.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 107.0.5254.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5248.0",
-              "revision": "version:106.0.5248.0"
+              "location": "lacros_version_skew_tests_v107.0.5254.0",
+              "revision": "version:107.0.5254.0"
             }
           ],
           "dimension_sets": [
@@ -21054,7 +21054,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5248.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
       },
       {
         "args": [
@@ -21081,21 +21081,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.83/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.105/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.83",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.105",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.83",
-              "revision": "version:104.0.5112.83"
+              "location": "lacros_version_skew_tests_v104.0.5112.105",
+              "revision": "version:104.0.5112.105"
             }
           ],
           "dimension_sets": [
@@ -21107,7 +21107,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.83"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.105"
       },
       {
         "args": [
@@ -21174,21 +21174,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5248.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 106.0.5248.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 107.0.5254.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5248.0",
-              "revision": "version:106.0.5248.0"
+              "location": "lacros_version_skew_tests_v107.0.5254.0",
+              "revision": "version:107.0.5254.0"
             }
           ],
           "dimension_sets": [
@@ -21200,7 +21200,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 106.0.5248.0"
+        "variant_id": "Lacros version skew testing ash 107.0.5254.0"
       },
       {
         "isolate_profile_data": true,
@@ -21433,6 +21433,24 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
+        "test": "ozone_unittests",
+        "test_id_prefix": "ninja://ui/ozone:ozone_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
         "test": "pdf_unittests",
         "test_id_prefix": "ninja://pdf:pdf_unittests/"
       },
diff --git a/testing/buildbot/filters/android.emulator_11_12.media_unittests.filter b/testing/buildbot/filters/android.emulator_11_12.media_unittests.filter
index 576eae8..33612d2 100644
--- a/testing/buildbot/filters/android.emulator_11_12.media_unittests.filter
+++ b/testing/buildbot/filters/android.emulator_11_12.media_unittests.filter
@@ -3,13 +3,3 @@
 -PaintCanvasVideoRendererWithGLTest.CopyVideoFrameTexturesToGLTexture*
 -PaintCanvasVideoRendererWithGLTest.CopyVideoFrameYUVDataToGLTexture*
 -PaintCanvasVideoRendererWithGLTest.Paint*
-
-# Tests are flaky.
-# https://crbug.com/1352098
--PaintCanvasVideoRendererWithGLTest.CopyVideoFrameToWebGLTextureRGBA
--PaintCanvasVideoRendererWithGLTest.CopyVideoFrameToWebGLTexture_FlipY
--PaintCanvasVideoRendererWithGLTest.CopyVideoFrameToWebGLTextureRGBA_ReadLockFence
--PaintCanvasVideoRendererWithGLTest.CopyVideoFrameToWebGLTextureI420
--PaintCanvasVideoRendererWithGLTest.CopyVideoFrameToWebGLTexture
--PaintCanvasVideoRendererWithGLTest.CopyVideoFrameToWebGLTextureNV12
-
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 238b657..6a4985c6 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -2470,11 +2470,6 @@
       },
     },
   },
-  'lacros_all_tast_tests eve': {
-    'remove_from': [
-      'lacros-amd64-generic-rel',
-    ]
-  },
   'lacros_all_tast_tests jacuzzi': {
     'modifications': {
       'lacros-arm-generic-rel': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index c99ff03..a311938 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -3870,6 +3870,7 @@
 
     'linux_lacros_specific_gtests': {
       'lacros_chrome_unittests': {},
+      'ozone_unittests': {},
     },
 
     'linux_specific_chromium_isolated_scripts': {
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 6cee794..99b5365 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -22,15 +22,15 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5248.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v107.0.5254.0/test_ash_chrome',
     ],
-    'identifier': 'Lacros version skew testing ash 106.0.5248.0',
+    'identifier': 'Lacros version skew testing ash 107.0.5254.0',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v106.0.5248.0',
-          'revision': 'version:106.0.5248.0',
+          'location': 'lacros_version_skew_tests_v107.0.5254.0',
+          'revision': 'version:107.0.5254.0',
         },
       ],
     },
@@ -67,15 +67,15 @@
   },
   'LACROS_VERSION_SKEW_STABLE': {
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.83/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.105/test_ash_chrome',
     ],
-    'identifier': 'Lacros version skew testing ash 104.0.5112.83',
+    'identifier': 'Lacros version skew testing ash 104.0.5112.105',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v104.0.5112.83',
-          'revision': 'version:104.0.5112.83',
+          'location': 'lacros_version_skew_tests_v104.0.5112.105',
+          'revision': 'version:104.0.5112.105',
         },
       ],
     },
diff --git a/testing/clusterfuzz/OWNERS b/testing/clusterfuzz/OWNERS
index 47caed4..bc960c08 100644
--- a/testing/clusterfuzz/OWNERS
+++ b/testing/clusterfuzz/OWNERS
@@ -1,2 +1 @@
 bookholt@chromium.org
-tiszka@chromium.org
diff --git a/testing/scripts/run_finch_smoke_tests_android.py b/testing/scripts/run_finch_smoke_tests_android.py
index 0f7c34f..192790d5 100755
--- a/testing/scripts/run_finch_smoke_tests_android.py
+++ b/testing/scripts/run_finch_smoke_tests_android.py
@@ -166,6 +166,8 @@
 
   @contextlib.contextmanager
   def _archive_logcat(self, filename, endpoint_name):
+    start_point = 'START {}'.format(endpoint_name)
+    end_point = 'END {}'.format(endpoint_name)
     with logcat_monitor.LogcatMonitor(
         self._device.adb,
         filter_specs=LOGCAT_FILTERS,
@@ -173,14 +175,30 @@
         check_error=False):
       try:
         self._device.RunShellCommand(['log', '-p', 'i', '-t', LOGCAT_TAG,
-                                      'START {}'.format(endpoint_name)],
+                                      start_point],
                                      check_return=True)
         yield
       finally:
         self._device.RunShellCommand(['log', '-p', 'i', '-t', LOGCAT_TAG,
-                                      'END {}'.format(endpoint_name)],
+                                      end_point],
                                      check_return=True)
 
+    with open(filename, 'r+') as logcat_file:
+      logcat_lines = []
+      store_line = False
+      for line in logcat_file.readlines():
+        if start_point in line:
+          store_line = True
+        elif end_point in line:
+          store_line = False
+          logcat_lines.append(line)
+
+        if store_line:
+          logcat_lines.append(line)
+
+    with open(filename, 'w') as logcat_file:
+      logcat_file.write(''.join(logcat_lines))
+
   def parse_args(self, args=None):
     super(FinchTestCase, self).parse_args(args)
     if (not self.options.finch_seed_path or
diff --git a/testing/test.gni b/testing/test.gni
index 0ef71de..4e95eb5 100644
--- a/testing/test.gni
+++ b/testing/test.gni
@@ -1105,6 +1105,13 @@
     configs = default_shared_library_configs
     configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
     configs += [ "//build/config/android:hide_all_but_jni" ]
+
+    # Compress sections to stay under 4gb hard limit on 32-bit current_cpu.
+    # https://crbug.com/1354616
+    if (symbol_level == 2 && !use_debug_fission &&
+        (current_cpu == "arm" || current_cpu == "x86")) {
+      configs += [ "//build/config:compress_debug_sections" ]
+    }
   } else {
     configs = default_executable_configs
     if (is_mac) {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 099b7603..667296d 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -230,6 +230,22 @@
             ]
         }
     ],
+    "AndroidFrameDeadline": [
+        {
+            "platforms": [
+                "android"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "AndroidFrameDeadline"
+                    ],
+                    "min_os_version": "13.0.0"
+                }
+            ]
+        }
+    ],
     "AndroidHatsNext": [
         {
             "platforms": [
@@ -3384,21 +3400,6 @@
             ]
         }
     ],
-    "CrosDeviceActiveCountingMonthlyCheckMembership": [
-        {
-            "platforms": [
-                "chromeos"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "DeviceActiveClientMonthlyCheckMembership"
-                    ]
-                }
-            ]
-        }
-    ],
     "CrosLazyLoginWebUI": [
         {
             "platforms": [
diff --git a/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
index 4cc6e27..e2a3883 100644
--- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc
+++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -2098,7 +2098,7 @@
       CompositorAnimations::kNoFailure);
 
   // Setting to CompositingReasonNone should produce false.
-  UpdateDummyTransformNode(properties, CompositingReason::kNone);
+  UpdateDummyTransformNode(properties, CompositingReason::kNoCompositingReason);
   EXPECT_TRUE(
       CheckCanStartElementOnCompositor(*element, *keyframe_animation_effect2_) &
       CompositorAnimations::kTargetHasInvalidCompositingState);
@@ -2133,7 +2133,7 @@
       CompositorAnimations::kNoFailure);
 
   // Setting to CompositingReasonNone should produce false.
-  UpdateDummyEffectNode(properties, CompositingReason::kNone);
+  UpdateDummyEffectNode(properties, CompositingReason::kNoCompositingReason);
   EXPECT_TRUE(
       CheckCanStartElementOnCompositor(*element, *keyframe_animation_effect2_) &
       CompositorAnimations::kTargetHasInvalidCompositingState);
diff --git a/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc b/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc
index e45d22a..32fcbf8 100644
--- a/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc
+++ b/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc
@@ -51,7 +51,7 @@
       last_chunk_index_(kInvalidChunkIndex),
       needs_more_invocation_for_testing_(false) {}
 
-bool ColdModeSpellCheckRequester::FullyChecked() const {
+bool ColdModeSpellCheckRequester::FullyCheckedCurrentRootEditable() const {
   if (needs_more_invocation_for_testing_) {
     needs_more_invocation_for_testing_ = false;
     return false;
@@ -124,8 +124,8 @@
   }
 
   while (deadline->timeRemaining() > 0) {
-    if (FullyChecked() || !RequestCheckingForNextChunk()) {
-      SetHasFullyChecked();
+    if (FullyCheckedCurrentRootEditable() || !RequestCheckingForNextChunk()) {
+      SetHasFullyCheckedCurrentRootEditable();
       return;
     }
   }
@@ -145,7 +145,7 @@
   fully_checked_root_editables_.clear();
 }
 
-void ColdModeSpellCheckRequester::SetHasFullyChecked() {
+void ColdModeSpellCheckRequester::SetHasFullyCheckedCurrentRootEditable() {
   DCHECK(root_editable_);
   DCHECK(!fully_checked_root_editables_.Contains(root_editable_));
 
@@ -161,7 +161,7 @@
 
 bool ColdModeSpellCheckRequester::RequestCheckingForNextChunk() {
   DCHECK(root_editable_);
-  DCHECK(!FullyChecked());
+  DCHECK(!FullyCheckedCurrentRootEditable());
 
   const EphemeralRange remaining_range(remaining_check_range_);
   const int remaining_length = TextIterator::RangeLength(
diff --git a/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.h b/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.h
index 72585a5..e7518f2 100644
--- a/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.h
+++ b/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.h
@@ -42,8 +42,11 @@
   // Called when document is detached or spellchecking is globally disabled.
   void Deactivate();
 
-  bool FullyChecked() const;
+  bool FullyCheckedCurrentRootEditable() const;
 
+  bool HasFullyChecked(const Element& element) const {
+    return fully_checked_root_editables_.Contains(&element);
+  }
   void RemoveFromFullyChecked(const Element& element) {
     fully_checked_root_editables_.erase(&element);
   }
@@ -65,7 +68,7 @@
 
   // Returns true if there's anything remaining to check, false otherwise
   bool RequestCheckingForNextChunk();
-  void SetHasFullyChecked();
+  void SetHasFullyCheckedCurrentRootEditable();
 
   // The window this cold mode checker belongs to.
   const Member<LocalDOMWindow> window_;
diff --git a/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc b/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc
index a02e7230..68c30af 100644
--- a/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc
+++ b/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc
@@ -70,9 +70,7 @@
     LocalDOMWindow& window,
     SpellCheckRequester& requester)
     : ExecutionContextLifecycleObserver(&window),
-      state_(State::kInactive),
       idle_callback_handle_(kInvalidHandle),
-      last_processed_undo_step_sequence_(0),
       cold_mode_requester_(
           MakeGarbageCollected<ColdModeSpellCheckRequester>(window)),
       spell_check_requeseter_(requester) {}
@@ -108,12 +106,39 @@
   spell_check_requeseter_->Deactivate();
 }
 
-void IdleSpellCheckController::SetNeedsInvocation() {
+void IdleSpellCheckController::RespondToChangedSelection() {
   if (!IsSpellCheckingEnabled()) {
     Deactivate();
     return;
   }
 
+  needs_invocation_for_changed_selection_ = true;
+  SetNeedsInvocation();
+}
+
+void IdleSpellCheckController::RespondToChangedContents() {
+  if (!IsSpellCheckingEnabled()) {
+    Deactivate();
+    return;
+  }
+
+  needs_invocation_for_changed_contents_ = true;
+  SetNeedsInvocation();
+}
+
+void IdleSpellCheckController::RespondToChangedEnablement() {
+  if (!IsSpellCheckingEnabled()) {
+    Deactivate();
+    return;
+  }
+
+  needs_invocation_for_changed_enablement_ = true;
+  SetNeedsInvocation();
+}
+
+void IdleSpellCheckController::SetNeedsInvocation() {
+  DCHECK(IsSpellCheckingEnabled());
+
   if (state_ == State::kHotModeRequested)
     return;
 
@@ -165,6 +190,24 @@
   state_ = State::kColdModeRequested;
 }
 
+bool IdleSpellCheckController::NeedsHotModeCheckingUnderCurrentSelection()
+    const {
+  if (needs_invocation_for_changed_contents_ ||
+      needs_invocation_for_changed_enablement_) {
+    return true;
+  }
+
+  // If there's only selection movement, we skip hot mode if cold mode has
+  // already fully checked the current element.
+  DCHECK(needs_invocation_for_changed_selection_);
+  const Position& position =
+      GetWindow().GetFrame()->Selection().GetSelectionInDOMTree().Extent();
+  const auto* element = DynamicTo<Element>(HighestEditableRoot(position));
+  if (!element || !element->isConnected())
+    return false;
+  return !cold_mode_requester_->HasFullyChecked(*element);
+}
+
 void IdleSpellCheckController::HotModeInvocation(IdleDeadline* deadline) {
   TRACE_EVENT0("blink", "IdleSpellCheckController::hotModeInvocation");
 
@@ -173,8 +216,10 @@
 
   HotModeSpellCheckRequester requester(*spell_check_requeseter_);
 
-  requester.CheckSpellingAt(
-      GetWindow().GetFrame()->Selection().GetSelectionInDOMTree().Extent());
+  if (NeedsHotModeCheckingUnderCurrentSelection()) {
+    requester.CheckSpellingAt(
+        GetWindow().GetFrame()->Selection().GetSelectionInDOMTree().Extent());
+  }
 
   const uint64_t watermark = last_processed_undo_step_sequence_;
   for (const UndoStep* step :
@@ -192,6 +237,10 @@
       continue;
     requester.CheckSpellingAt(step->EndingSelection().Extent());
   }
+
+  needs_invocation_for_changed_selection_ = false;
+  needs_invocation_for_changed_contents_ = false;
+  needs_invocation_for_changed_enablement_ = false;
 }
 
 void IdleSpellCheckController::Invoke(IdleDeadline* deadline) {
@@ -210,7 +259,7 @@
   } else if (state_ == State::kColdModeRequested) {
     state_ = State::kInColdModeInvocation;
     cold_mode_requester_->Invoke(deadline);
-    if (cold_mode_requester_->FullyChecked())
+    if (cold_mode_requester_->FullyCheckedCurrentRootEditable())
       state_ = State::kInactive;
     else
       SetNeedsColdModeInvocation();
diff --git a/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h b/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h
index ff09de3..c4f63fe8 100644
--- a/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h
+++ b/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h
@@ -48,7 +48,9 @@
 
   // Transit to HotModeRequested, if possible. Called by operations that need
   // spell checker to follow up.
-  void SetNeedsInvocation();
+  void RespondToChangedSelection();
+  void RespondToChangedContents();
+  void RespondToChangedEnablement();
 
   // Cleans everything up and makes the callback inactive. Should be called when
   // document is detached or spellchecking is globally disabled.
@@ -78,11 +80,15 @@
   // Returns whether spell checking is globally enabled.
   bool IsSpellCheckingEnabled() const;
 
+  // Called by RespondTo*() functions to transit to HotModeRequested state.
+  void SetNeedsInvocation();
+
   // Called at idle time as entrance function.
   void Invoke(IdleDeadline*);
 
   // Functions for hot mode.
   void HotModeInvocation(IdleDeadline*);
+  bool NeedsHotModeCheckingUnderCurrentSelection() const;
 
   // Transit to ColdModeTimerStarted, if possible. Sets up a timer, and requests
   // cold mode invocation if no critical operation occurs before timer firing.
@@ -97,13 +103,17 @@
 
   void DisposeIdleCallback();
 
-  State state_;
+  State state_ = State::kInactive;
   int idle_callback_handle_;
-  uint64_t last_processed_undo_step_sequence_;
+  uint64_t last_processed_undo_step_sequence_ = 0;
   const Member<ColdModeSpellCheckRequester> cold_mode_requester_;
   Member<SpellCheckRequester> spell_check_requeseter_;
   TaskHandle cold_mode_timer_;
 
+  bool needs_invocation_for_changed_selection_ = false;
+  bool needs_invocation_for_changed_contents_ = false;
+  bool needs_invocation_for_changed_enablement_ = false;
+
   friend class IdleSpellCheckControllerTest;
 };
 
diff --git a/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller_test.cc b/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller_test.cc
index e13e1c2..965d920 100644
--- a/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller_test.cc
+++ b/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller_test.cc
@@ -36,7 +36,7 @@
         IdleChecker().Deactivate();
         break;
       case State::kHotModeRequested:
-        IdleChecker().SetNeedsInvocation();
+        IdleChecker().RespondToChangedContents();
         break;
       case State::kColdModeTimerStarted:
         break;
@@ -58,7 +58,7 @@
 
 TEST_F(IdleSpellCheckControllerTest, RequestWhenInactive) {
   TransitTo(State::kInactive);
-  IdleChecker().SetNeedsInvocation();
+  IdleChecker().RespondToChangedContents();
   EXPECT_EQ(State::kHotModeRequested, IdleChecker().GetState());
   EXPECT_NE(-1, IdleChecker().IdleCallbackHandle());
 }
@@ -66,7 +66,7 @@
 TEST_F(IdleSpellCheckControllerTest, RequestWhenHotModeRequested) {
   TransitTo(State::kHotModeRequested);
   int handle = IdleChecker().IdleCallbackHandle();
-  IdleChecker().SetNeedsInvocation();
+  IdleChecker().RespondToChangedContents();
   EXPECT_EQ(State::kHotModeRequested, IdleChecker().GetState());
   EXPECT_EQ(handle, IdleChecker().IdleCallbackHandle());
   EXPECT_NE(-1, IdleChecker().IdleCallbackHandle());
@@ -74,7 +74,7 @@
 
 TEST_F(IdleSpellCheckControllerTest, RequestWhenColdModeTimerStarted) {
   TransitTo(State::kColdModeTimerStarted);
-  IdleChecker().SetNeedsInvocation();
+  IdleChecker().RespondToChangedContents();
   EXPECT_EQ(State::kHotModeRequested, IdleChecker().GetState());
   EXPECT_NE(-1, IdleChecker().IdleCallbackHandle());
 }
@@ -82,7 +82,7 @@
 TEST_F(IdleSpellCheckControllerTest, RequestWhenColdModeRequested) {
   TransitTo(State::kColdModeRequested);
   int handle = IdleChecker().IdleCallbackHandle();
-  IdleChecker().SetNeedsInvocation();
+  IdleChecker().RespondToChangedContents();
   EXPECT_EQ(State::kHotModeRequested, IdleChecker().GetState());
   EXPECT_NE(handle, IdleChecker().IdleCallbackHandle());
   EXPECT_NE(-1, IdleChecker().IdleCallbackHandle());
diff --git a/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc b/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
index 85f81638d..a3fe411f 100644
--- a/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
+++ b/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
@@ -496,17 +496,17 @@
 }
 
 void SpellChecker::RespondToChangedSelection() {
-  idle_spell_check_controller_->SetNeedsInvocation();
+  idle_spell_check_controller_->RespondToChangedSelection();
 }
 
 void SpellChecker::RespondToChangedContents() {
-  idle_spell_check_controller_->SetNeedsInvocation();
+  idle_spell_check_controller_->RespondToChangedContents();
 }
 
 void SpellChecker::RespondToChangedEnablement(const HTMLElement& element,
                                               bool enabled) {
   if (enabled) {
-    idle_spell_check_controller_->SetNeedsInvocation();
+    idle_spell_check_controller_->RespondToChangedEnablement();
   } else {
     RemoveSpellingAndGrammarMarkers(element);
     idle_spell_check_controller_->SetSpellCheckingDisabled(element);
diff --git a/third_party/blink/renderer/core/frame/frame_view_auto_size_info.cc b/third_party/blink/renderer/core/frame/frame_view_auto_size_info.cc
index bc3e1b40e..18db217 100644
--- a/third_party/blink/renderer/core/frame/frame_view_auto_size_info.cc
+++ b/third_party/blink/renderer/core/frame/frame_view_auto_size_info.cc
@@ -122,8 +122,7 @@
     vertical_scrollbar_mode = mojom::blink::ScrollbarMode::kAlwaysOn;
   }
 
-  if (new_size == size)
-    return false;
+  bool change_size = (new_size != size);
 
   // While loading only allow the size to increase (to avoid twitching during
   // intermediate smaller states) unless autoresize has just been turned on or
@@ -132,18 +131,23 @@
       size.width() <= max_auto_size_.width() &&
       !frame_view_->GetFrame().GetDocument()->LoadEventFinished() &&
       (new_size.height() < size.height() || new_size.width() < size.width())) {
-    return false;
+    change_size = false;
   }
 
-  frame_view_->Resize(new_size.width(), new_size.height());
+  if (change_size)
+    frame_view_->Resize(new_size.width(), new_size.height());
+
   // Force the scrollbar state to avoid the scrollbar code adding them and
   // causing them to be needed. For example, a vertical scrollbar may cause
   // text to wrap and thus increase the height (which is the only reason the
   // scollbar is needed).
+  //
+  // Note: since the overflow may have changed, we need to do this even if the
+  // size of the frame isn't changing.
   frame_view_->GetLayoutView()->SetAutosizeScrollbarModes(
       horizontal_scrollbar_mode, vertical_scrollbar_mode);
 
-  return true;
+  return change_size;
 }
 
 void FrameViewAutoSizeInfo::Clear() {
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index c2d4551..cb2b900 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -1336,10 +1336,12 @@
 }
 
 void HTMLCanvasElement::UpdateSuspendOffscreenCanvasAnimation() {
-  SetSuspendOffscreenCanvasAnimation(
-      GetPage()->GetVisibilityState() ==
-          mojom::blink::PageVisibilityState::kHidden &&
-      !HasCanvasCapture());
+  if (GetPage()) {
+    SetSuspendOffscreenCanvasAnimation(
+        GetPage()->GetVisibilityState() ==
+            mojom::blink::PageVisibilityState::kHidden &&
+        !HasCanvasCapture());
+  }
 }
 
 void HTMLCanvasElement::PageVisibilityChanged() {
diff --git a/third_party/blink/renderer/core/layout/hit_test_result.cc b/third_party/blink/renderer/core/layout/hit_test_result.cc
index 400d4795..6c14b33a7 100644
--- a/third_party/blink/renderer/core/layout/hit_test_result.cc
+++ b/third_party/blink/renderer/core/layout/hit_test_result.cc
@@ -261,7 +261,7 @@
   // browser control movement and overscroll glow.
   while (cur_box) {
     if (cur_box->IsGlobalRootScroller() ||
-        cur_box->NeedsScrollNode(CompositingReason::kNone)) {
+        cur_box->NeedsScrollNode(CompositingReason::kNoCompositingReason)) {
       return CompositorElementIdFromUniqueObjectId(
           cur_box->UniqueId(), CompositorElementIdNamespace::kScroll);
     }
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index c500683..8327eed 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -3888,7 +3888,7 @@
 
 CompositingReasons LayoutObject::AdditionalCompositingReasons() const {
   NOT_DESTROYED();
-  return CompositingReason::kNone;
+  return CompositingReason::kNoCompositingReason;
 }
 
 bool LayoutObject::HitTestAllPhases(HitTestResult& result,
diff --git a/third_party/blink/renderer/core/layout/layout_video.cc b/third_party/blink/renderer/core/layout/layout_video.cc
index 0cef90f..7992bcd1 100644
--- a/third_party/blink/renderer/core/layout/layout_video.cc
+++ b/third_party/blink/renderer/core/layout/layout_video.cc
@@ -228,7 +228,7 @@
   if (GetDisplayMode() == kVideo && SupportsAcceleratedRendering())
     return CompositingReason::kVideo;
 
-  return CompositingReason::kNone;
+  return CompositingReason::kNoCompositingReason;
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_view.cc b/third_party/blink/renderer/core/layout/layout_view.cc
index b5c2e5d..40610a4 100644
--- a/third_party/blink/renderer/core/layout/layout_view.cc
+++ b/third_party/blink/renderer/core/layout/layout_view.cc
@@ -920,7 +920,7 @@
   const LocalFrame& frame = frame_view_->GetFrame();
   if (frame.OwnerLayoutObject() && frame.IsCrossOriginToParentOrOuterDocument())
     return CompositingReason::kIFrame;
-  return CompositingReason::kNone;
+  return CompositingReason::kNoCompositingReason;
 }
 
 void LayoutView::UpdateMarkersAndCountersAfterStyleChange(
diff --git a/third_party/blink/renderer/core/layout/scrollbars_test.cc b/third_party/blink/renderer/core/layout/scrollbars_test.cc
index 672b7b4..995e5316 100644
--- a/third_party/blink/renderer/core/layout/scrollbars_test.cc
+++ b/third_party/blink/renderer/core/layout/scrollbars_test.cc
@@ -2161,6 +2161,37 @@
   }
 }
 
+TEST_P(ScrollbarsTest, AutosizeExpandingContentScrollable) {
+  ENABLE_OVERLAY_SCROLLBARS(true);
+
+  SimRequest resource("https://example.com/test.html", "text/html");
+  LoadURL("https://example.com/test.html");
+  resource.Complete(R"HTML(
+    <style>
+    body { margin: 0 }
+    #spacer { width: 100px; height: 100px; }
+    </style>
+    <div id="spacer"></div>
+  )HTML");
+  test::RunPendingTasks();
+
+  LocalFrameView* frame_view = WebView().MainFrameImpl()->GetFrameView();
+  ScrollableArea* layout_viewport = frame_view->LayoutViewport();
+
+  WebView().EnableAutoResizeMode(gfx::Size(800, 600), gfx::Size(800, 600));
+  Compositor().BeginFrame();
+
+  // Not scrollable due to no overflow.
+  EXPECT_FALSE(layout_viewport->UserInputScrollable(kVerticalScrollbar));
+
+  GetDocument().getElementById("spacer")->setAttribute(html_names::kStyleAttr,
+                                                       "height: 900px");
+  Compositor().BeginFrame();
+
+  // Now scrollable due to overflow.
+  EXPECT_TRUE(layout_viewport->UserInputScrollable(kVerticalScrollbar));
+}
+
 TEST_P(ScrollbarsTest,
        HideTheOverlayScrollbarNotCrashAfterPLSADisposedPaintLayer) {
   // This test is specifically checking the behavior when overlay scrollbars
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
index 58e70c0..9ac8baa 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
@@ -32,7 +32,7 @@
     return object &&
            CompositingReasonFinder::
                    DirectReasonsForPaintPropertiesExceptScrolling(*object) !=
-               CompositingReason::kNone;
+               CompositingReason::kNoCompositingReason;
   };
   if (has_direct_compositing_reasons(
           layout_view.GetFrame()->OwnerLayoutObject()))
@@ -58,12 +58,12 @@
         return CompositingReason::kBackfaceInvisibility3DAncestor;
     }
   }
-  return CompositingReason::kNone;
+  return CompositingReason::kNoCompositingReason;
 }
 
 static CompositingReasons CompositingReasonsForWillChange(
     const ComputedStyle& style) {
-  CompositingReasons reasons = CompositingReason::kNone;
+  CompositingReasons reasons = CompositingReason::kNoCompositingReason;
   if (style.SubtreeWillChangeContents())
     return reasons;
 
@@ -84,7 +84,7 @@
 
   // kWillChangeOther is needed only when none of the explicit kWillChange*
   // reasons are set.
-  if (reasons == CompositingReason::kNone &&
+  if (reasons == CompositingReason::kNoCompositingReason &&
       style.HasWillChangeCompositingHint())
     reasons |= CompositingReason::kWillChangeOther;
 
@@ -97,7 +97,7 @@
   // may have transforms, but the layoutObject may be an inline that doesn't
   // support them.
   if (!layout_object.HasTransformRelatedProperty())
-    return CompositingReason::kNone;
+    return CompositingReason::kNoCompositingReason;
   return CompositingReasonFinder::PotentialCompositingReasonsFor3DTransform(
       layout_object.StyleRef());
 }
@@ -123,7 +123,7 @@
     // A LayoutNGBR is both IsText() and IsForElement(), but we shouldn't
     // produce compositing reasons if IsText() is true.  Since we only need
     // this for objects that have interesting descendants, we can just return.
-    return CompositingReason::kNone;
+    return CompositingReason::kNoCompositingReason;
   }
 
   if (layout_object.IsForElement() && !layout_object.StyleRef().Preserves3D()) {
@@ -134,14 +134,14 @@
     }
   }
 
-  return CompositingReason::kNone;
+  return CompositingReason::kNoCompositingReason;
 }
 
 static CompositingReasons DirectReasonsForSVGChildPaintProperties(
     const LayoutObject& object) {
   DCHECK(object.IsSVGChild());
   if (object.IsText())
-    return CompositingReason::kNone;
+    return CompositingReason::kNoCompositingReason;
 
   // Even though SVG doesn't support 3D transforms, it might be the leaf of a 3D
   // scene that contains it.
@@ -164,12 +164,12 @@
 static CompositingReasons CompositingReasonsForViewportScrollEffect(
     const LayoutObject& layout_object) {
   if (!layout_object.IsBox())
-    return CompositingReason::kNone;
+    return CompositingReason::kNoCompositingReason;
 
   // The viewport scroll effect should never apply to objects inside an
   // embedded frame tree.
   if (!layout_object.GetFrame()->Tree().Top().IsOutermostMainFrame())
-    return CompositingReason::kNone;
+    return CompositingReason::kNoCompositingReason;
 
   DCHECK_EQ(layout_object.GetFrame()->IsMainFrame(),
             layout_object.GetFrame()->IsOutermostMainFrame());
@@ -181,12 +181,12 @@
   if (!layout_object.GetFrame()->IsMainFrame() &&
       layout_object.GetFrame()->GetDocument() !=
           controller.GlobalRootScroller())
-    return CompositingReason::kNone;
+    return CompositingReason::kNoCompositingReason;
 
   if (!To<LayoutBox>(layout_object).IsFixedToView())
-    return CompositingReason::kNone;
+    return CompositingReason::kNoCompositingReason;
 
-  CompositingReasons reasons = CompositingReason::kNone;
+  CompositingReasons reasons = CompositingReason::kNoCompositingReason;
   // This ensures that the scroll_translation_for_fixed will be initialized in
   // FragmentPaintPropertyTreeBuilder::UpdatePaintOffsetTranslation which in
   // turn ensures that a TransformNode is created (for fixed elements) in cc.
@@ -207,7 +207,7 @@
 CompositingReasonFinder::DirectReasonsForPaintPropertiesExceptScrolling(
     const LayoutObject& object) {
   if (object.GetDocument().Printing())
-    return CompositingReason::kNone;
+    return CompositingReason::kNoCompositingReason;
 
   auto reasons = CompositingReasonsFor3DSceneLeaf(object);
 
@@ -282,7 +282,7 @@
   DCHECK_EQ(reasons_except_scrolling,
             DirectReasonsForPaintPropertiesExceptScrolling(object));
 
-  if (reasons_except_scrolling != CompositingReason::kNone)
+  if (reasons_except_scrolling != CompositingReason::kNoCompositingReason)
     return true;
 
   if (object.StyleRef().WillChangeScrollPosition())
@@ -322,7 +322,7 @@
 CompositingReasons
 CompositingReasonFinder::PotentialCompositingReasonsFor3DTransform(
     const ComputedStyle& style) {
-  CompositingReasons reasons = CompositingReason::kNone;
+  CompositingReasons reasons = CompositingReason::kNoCompositingReason;
 
   if (Platform::Current()->IsLowEndDevice()) {
     // Don't composite "trivial" 3D transforms such as translateZ(0).
@@ -365,7 +365,7 @@
 
 CompositingReasons CompositingReasonFinder::CompositingReasonsForAnimation(
     const LayoutObject& object) {
-  CompositingReasons reasons = CompositingReason::kNone;
+  CompositingReasons reasons = CompositingReason::kNoCompositingReason;
   const auto& style = object.StyleRef();
   if (style.SubtreeWillChangeContents())
     return reasons;
@@ -407,7 +407,7 @@
 CompositingReasons
 CompositingReasonFinder::CompositingReasonsForScrollDependentPosition(
     const PaintLayer& layer) {
-  CompositingReasons reasons = CompositingReason::kNone;
+  CompositingReasons reasons = CompositingReason::kNoCompositingReason;
   // Don't promote fixed position elements that are descendants of a non-view
   // container, e.g. transformed elements.  They will stay fixed wrt the
   // container rather than the enclosing frame.
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
index 32ffd402..c524445 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
@@ -88,7 +88,7 @@
   )HTML");
 
   EXPECT_REASONS(
-      CompositingReason::kNone,
+      CompositingReason::kNoCompositingReason,
       DirectReasonsForPaintProperties(*GetLayoutObjectByElementId("target")));
 }
 
@@ -129,7 +129,7 @@
   EXPECT_REASONS(CompositingReason::kStickyPosition,
                  DirectReasonsForPaintProperties(
                      *GetLayoutObjectByElementId("sticky-top")));
-  EXPECT_REASONS(CompositingReason::kNone,
+  EXPECT_REASONS(CompositingReason::kNoCompositingReason,
                  DirectReasonsForPaintProperties(
                      *GetLayoutObjectByElementId("sticky-no-anchor")));
 }
@@ -182,7 +182,7 @@
           *GetPaintLayerByElementId("sticky-scrolling")));
 
   EXPECT_REASONS(
-      CompositingReason::kNone,
+      CompositingReason::kNoCompositingReason,
       CompositingReasonFinder::CompositingReasonsForScrollDependentPosition(
           *GetPaintLayerByElementId("sticky-no-scrolling")));
 
@@ -192,12 +192,12 @@
           *GetPaintLayerByElementId("overflow-hidden-scrolling")));
 
   EXPECT_REASONS(
-      CompositingReason::kNone,
+      CompositingReason::kNoCompositingReason,
       CompositingReasonFinder::CompositingReasonsForScrollDependentPosition(
           *GetPaintLayerByElementId("overflow-hidden-no-scrolling")));
 
   EXPECT_REASONS(
-      CompositingReason::kNone,
+      CompositingReason::kNoCompositingReason,
       CompositingReasonFinder::CompositingReasonsForScrollDependentPosition(
           *GetPaintLayerByElementId("under-fixed")));
 }
@@ -219,10 +219,10 @@
   object->SetStyle(style);
 
   EXPECT_REASONS(
-      CompositingReason::kNone,
+      CompositingReason::kNoCompositingReason,
       CompositingReasonFinder::CompositingReasonsForAnimation(*object));
 
-  CompositingReasons expected_reason = CompositingReason::kNone;
+  CompositingReasons expected_reason = CompositingReason::kNoCompositingReason;
 
   style->SetHasCurrentTransformAnimation(true);
   if (supports_transform_animation)
@@ -311,7 +311,7 @@
   PaintLayer* iframe_layer = iframe_layout_view->Layer();
   ASSERT_TRUE(iframe_layer);
   EXPECT_FALSE(iframe_layer->GetScrollableArea()->NeedsCompositedScrolling());
-  EXPECT_REASONS(CompositingReason::kNone,
+  EXPECT_REASONS(CompositingReason::kNoCompositingReason,
                  DirectReasonsForPaintProperties(*iframe_layout_view));
 
   SetBodyInnerHTML(R"HTML(
@@ -422,7 +422,7 @@
                  DirectReasonsForPaintProperties(
                      *GetLayoutObjectByElementId("intermediate")));
   EXPECT_REASONS(
-      CompositingReason::kNone,
+      CompositingReason::kNoCompositingReason,
       DirectReasonsForPaintProperties(*GetLayoutObjectByElementId("target")));
 }
 
@@ -441,7 +441,7 @@
   )HTML");
 
   EXPECT_REASONS(
-      CompositingReason::kNone,
+      CompositingReason::kNoCompositingReason,
       DirectReasonsForPaintProperties(*GetLayoutObjectByElementId("target")));
 }
 
@@ -459,7 +459,7 @@
   )HTML");
 
   EXPECT_REASONS(
-      CompositingReason::kNone,
+      CompositingReason::kNoCompositingReason,
       DirectReasonsForPaintProperties(*GetLayoutObjectByElementId("target")));
 }
 
@@ -475,7 +475,7 @@
             DirectReasonsForPaintProperties(*svg_text));
   auto* text = svg_text->SlowFirstChild();
   ASSERT_TRUE(text->IsText());
-  EXPECT_REASONS(CompositingReason::kNone,
+  EXPECT_REASONS(CompositingReason::kNoCompositingReason,
                  DirectReasonsForPaintProperties(*text));
 }
 
@@ -500,7 +500,7 @@
   )HTML");
 
   auto* defs = GetLayoutObjectByElementId("defs");
-  EXPECT_REASONS(CompositingReason::kNone,
+  EXPECT_REASONS(CompositingReason::kNoCompositingReason,
                  DirectReasonsForPaintProperties(*defs));
 
   auto* text = GetLayoutObjectByElementId("text");
@@ -509,20 +509,20 @@
 
   auto* text_content = text->SlowFirstChild();
   ASSERT_TRUE(text_content->IsText());
-  EXPECT_EQ(CompositingReason::kNone,
+  EXPECT_EQ(CompositingReason::kNoCompositingReason,
             DirectReasonsForPaintProperties(*text_content));
 
   auto* tspan = GetLayoutObjectByElementId("tspan");
-  EXPECT_REASONS(CompositingReason::kNone,
+  EXPECT_REASONS(CompositingReason::kNoCompositingReason,
                  DirectReasonsForPaintProperties(*tspan));
 
   auto* tspan_content = tspan->SlowFirstChild();
   ASSERT_TRUE(tspan_content->IsText());
-  EXPECT_EQ(CompositingReason::kNone,
+  EXPECT_EQ(CompositingReason::kNoCompositingReason,
             DirectReasonsForPaintProperties(*tspan_content));
 
   auto* feBlend = GetLayoutObjectByElementId("feBlend");
-  EXPECT_REASONS(CompositingReason::kNone,
+  EXPECT_REASONS(CompositingReason::kNoCompositingReason,
                  DirectReasonsForPaintProperties(*feBlend));
 }
 
@@ -536,7 +536,7 @@
 
   auto* target = GetLayoutObjectByElementId("target");
   EXPECT_TRUE(CompositingReasonFinder::ShouldForcePreferCompositingToLCDText(
-      *target, CompositingReason::kNone));
+      *target, CompositingReason::kNoCompositingReason));
   EXPECT_REASONS(CompositingReason::kOverflowScrolling,
                  DirectReasonsForPaintProperties(*target));
 
@@ -544,8 +544,8 @@
       CSSPropertyID::kWillChange);
   UpdateAllLifecyclePhasesForTest();
   EXPECT_FALSE(CompositingReasonFinder::ShouldForcePreferCompositingToLCDText(
-      *target, CompositingReason::kNone));
-  EXPECT_REASONS(CompositingReason::kNone,
+      *target, CompositingReason::kNoCompositingReason));
+  EXPECT_REASONS(CompositingReason::kNoCompositingReason,
                  DirectReasonsForPaintProperties(*target));
 }
 
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h
index d2c4955..36def655 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.h
+++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -528,7 +528,7 @@
 
   CompositingReasons GetCompositingReasons() const {
     // TODO(pdr): Remove this.
-    return CompositingReason::kNone;
+    return CompositingReason::kNoCompositingReason;
   }
 
   void UpdateDescendantDependentFlags();
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
index 8e9537f..b46ff65 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -521,7 +521,7 @@
   // very likely that the object will be composited, so a paint offset
   // translation will be beneficial.
   bool has_paint_offset_compositing_reason =
-      direct_compositing_reasons != CompositingReason::kNone ||
+      direct_compositing_reasons != CompositingReason::kNoCompositingReason ||
       box_model.StyleRef().BackfaceVisibility() == EBackfaceVisibility::kHidden;
   if (has_paint_offset_compositing_reason) {
     // Don't let paint offset cross composited layer boundaries when possible,
@@ -604,8 +604,10 @@
 
   ResetPaintOffset(subpixel_accumulation);
 
-  if (full_context_.direct_compositing_reasons == CompositingReason::kNone)
+  if (full_context_.direct_compositing_reasons ==
+      CompositingReason::kNoCompositingReason) {
     return;
+  }
 
   if (paint_offset_translation && properties_ &&
       properties_->PaintOffsetTranslation()) {
@@ -1008,7 +1010,7 @@
 static bool NeedsOffset(const LayoutObject& object,
                         CompositingReasons direct_compositing_reasons) {
   return NeedsIndividualTransform(
-      object, CompositingReason::kNone,
+      object, CompositingReason::kNoCompositingReason,
       [](const ComputedStyle& style) { return style.HasOffset(); });
 }
 
@@ -1161,7 +1163,7 @@
           state.backface_visibility =
               TransformPaintPropertyNode::BackfaceVisibility::kHidden;
         } else if (state.direct_compositing_reasons !=
-                   CompositingReason::kNone) {
+                   CompositingReason::kNoCompositingReason) {
           // The above condition fixes a CompositeAfterPaint regression
           // (crbug.com/1260603) by letting non-directly-composited transforms
           // inherit parent's backface visibility.
@@ -1279,7 +1281,8 @@
             ComputedStyle::kIncludeMotionPath,
             ComputedStyle::kExcludeIndependentTransformProperties);
       },
-      CompositingReason::kNone, CompositingReason::kNone,
+      CompositingReason::kNoCompositingReason,
+      CompositingReason::kNoCompositingReason,
       // TODO(dbaron): When we support animating offset on the
       // compositor, we need to use an element ID specific to offset.
       // This is currently unused.
@@ -1574,7 +1577,7 @@
           full_context_.direct_compositing_reasons &
                   CompositingReason::kDirectReasonsForBackdropFilter
               ? CompositingReason::kBackdropFilterMask
-              : CompositingReason::kNone;
+              : CompositingReason::kNoCompositingReason;
 
       if (mask_clip) {
         EffectPaintPropertyNode::State mask_state;
@@ -4041,7 +4044,8 @@
       ObjectTypeMightNeedMultipleFragmentData()) {
     UpdateFragments();
   } else {
-    DCHECK_EQ(context_.direct_compositing_reasons, CompositingReason::kNone);
+    DCHECK_EQ(context_.direct_compositing_reasons,
+              CompositingReason::kNoCompositingReason);
     if (!IsInNGFragmentTraversal())
       object_.GetMutableForPainting().FirstFragment().ClearNextFragment();
   }
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.h b/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
index 945fc10..fc56bf9 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
@@ -258,7 +258,8 @@
 
   // This is always recalculated in PaintPropertyTreeBuilder::UpdateForSelf()
   // which overrides the inherited value.
-  CompositingReasons direct_compositing_reasons = CompositingReason::kNone;
+  CompositingReasons direct_compositing_reasons =
+      CompositingReason::kNoCompositingReason;
 };
 
 class VisualViewportPaintPropertyTreeBuilder {
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc b/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
index bb7b658..63a3ade 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
+++ b/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
@@ -540,8 +540,6 @@
 }
 
 void OnRequestToken(ScriptPromiseResolver* resolver,
-                    const KURL& provider_url,
-                    const String& client_id,
                     const CredentialRequestOptions* options,
                     RequestTokenStatus status,
                     const WTF::String& token) {
@@ -1179,32 +1177,45 @@
       resolver->Detach();
       return ScriptPromise();
     }
-    if (options->identity()->providers().size() > 1) {
+    if (!RuntimeEnabledFeatures::FedCmMultipleIdentityProvidersEnabled() &&
+        options->identity()->providers().size() > 1) {
       exception_state.ThrowTypeError(
-          "More than one provider is not supported.");
+          "Multiple providers specified but FedCmMultipleIdentityProviders "
+          "flag is disabled.");
       resolver->Detach();
       return ScriptPromise();
     }
-    IdentityProvider* provider = options->identity()->providers()[0];
+
     // Log the UseCounter only when the WebID flag is enabled.
     UseCounter::Count(context, WebFeature::kFederatedCredentialManagement);
-    // TODO(kenrb): Add some renderer-side validation here, such as
-    // validating |provider|, and making sure the calling context is legal.
-    // Some of this has not been spec'd yet.
-    KURL provider_url(provider->configURL());
-    String client_id = provider->clientId();
 
-    if (!provider_url.IsValid() || client_id == "") {
-      resolver->Reject(MakeGarbageCollected<DOMException>(
-          DOMExceptionCode::kInvalidStateError,
-          "Provider information is incomplete."));
-      return promise;
-    }
-    // We disallow redirects (in idp_network_request_manager.cc), so it is
-    // enough to check the initial URL here.
-    if (IdentityCredential::IsRejectingPromiseDueToCSP(policy, resolver,
-                                                       provider_url)) {
-      return promise;
+    int provider_index = 0;
+    Vector<mojom::blink::IdentityProviderPtr> identity_provider_ptrs;
+    for (const auto& provider : options->identity()->providers()) {
+      // TODO(kenrb): Add some renderer-side validation here, such as
+      // validating |provider|, and making sure the calling context is legal.
+      // Some of this has not been spec'd yet.
+      KURL provider_url(provider->configURL());
+      String client_id = provider->clientId();
+
+      ++provider_index;
+      if (!provider_url.IsValid() || client_id == "") {
+        resolver->Reject(MakeGarbageCollected<DOMException>(
+            DOMExceptionCode::kInvalidStateError,
+            String::Format("Provider %i information is incomplete.",
+                           provider_index)));
+        return promise;
+      }
+      // We disallow redirects (in idp_network_request_manager.cc), so it is
+      // enough to check the initial URL here.
+      if (IdentityCredential::IsRejectingPromiseDueToCSP(policy, resolver,
+                                                         provider_url)) {
+        return promise;
+      }
+
+      mojom::blink::IdentityProviderPtr identity_provider =
+          blink::mojom::blink::IdentityProvider::From(*provider);
+      identity_provider_ptrs.push_back(std::move(identity_provider));
     }
 
     DCHECK(options->identity()->hasPreferAutoSignIn());
@@ -1218,20 +1229,13 @@
                                                 WrapPersistent(script_state)));
     }
 
-    Vector<mojom::blink::IdentityProviderPtr> identity_provider_ptrs;
-    for (const auto& provider : options->identity()->providers()) {
-      mojom::blink::IdentityProviderPtr identity_provider =
-          blink::mojom::blink::IdentityProvider::From(*provider);
-      identity_provider_ptrs.push_back(std::move(identity_provider));
-    }
     bool prefer_auto_sign_in = options->identity()->preferAutoSignIn();
     auto* auth_request =
         CredentialManagerProxy::From(script_state)->FederatedAuthRequest();
-
     auth_request->RequestToken(
         std::move(identity_provider_ptrs), prefer_auto_sign_in,
-        WTF::Bind(&OnRequestToken, WrapPersistent(resolver), provider_url,
-                  client_id, WrapPersistent(options)));
+        WTF::Bind(&OnRequestToken, WrapPersistent(resolver),
+                  WrapPersistent(options)));
 
     return promise;
   }
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
index 7cf671ac5..a5f30fc 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -1014,7 +1014,7 @@
     }
   }
 
-  CompositingReasons reasons = CompositingReason::kNone;
+  CompositingReasons reasons = CompositingReason::kNoCompositingReason;
   if (!previous_layer ||
       &layer.GetPropertyTreeState().Transform() !=
           &previous_layer->GetPropertyTreeState().Transform()) {
@@ -1032,7 +1032,7 @@
     const auto& effect = layer.GetPropertyTreeState().Effect();
     if (effect.HasDirectCompositingReasons())
       reasons |= effect.DirectCompositingReasonsForDebugging();
-    if (reasons == CompositingReason::kNone &&
+    if (reasons == CompositingReason::kNoCompositingReason &&
         layer.GetCompositingType() == PendingLayer::kOther) {
       if (effect.Opacity() != 1.0f)
         reasons |= CompositingReason::kOpacityWithCompositedDescendants;
@@ -1045,7 +1045,7 @@
     }
   }
 
-  if (reasons == CompositingReason::kNone &&
+  if (reasons == CompositingReason::kNoCompositingReason &&
       layer.GetCompositingType() == PendingLayer::kOverlap)
     reasons = CompositingReason::kOverlap;
 
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
index 79d9f54..9b8277f 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
@@ -1114,8 +1114,8 @@
 }
 
 TEST_P(PaintArtifactCompositorTest, OneScrollNodeNonComposited) {
-  auto scroll_state =
-      ScrollState1(PropertyTreeState::Root(), CompositingReason::kNone);
+  auto scroll_state = ScrollState1(PropertyTreeState::Root(),
+                                   CompositingReason::kNoCompositingReason);
   TestPaintArtifact artifact;
   CreateScrollableChunk(artifact, scroll_state);
   artifact.Chunk(scroll_state)
@@ -1306,9 +1306,10 @@
 TEST_P(PaintArtifactCompositorTest, AncestorScrollNodes) {
   auto scroll_state_a = ScrollState1();
   auto& scroll_a = *scroll_state_a.Transform().ScrollNode();
-  auto scroll_state_b = ScrollState2(
-      scroll_state_a.GetPropertyTreeState(), CompositingReason::kNone,
-      cc::MainThreadScrollingReason::kNotOpaqueForTextAndLCDText);
+  auto scroll_state_b =
+      ScrollState2(scroll_state_a.GetPropertyTreeState(),
+                   CompositingReason::kNoCompositingReason,
+                   cc::MainThreadScrollingReason::kNotOpaqueForTextAndLCDText);
 
   TestPaintArtifact artifact;
   CreateScrollableChunk(artifact, scroll_state_a);
diff --git a/third_party/blink/renderer/platform/graphics/compositing/pending_layer_test.cc b/third_party/blink/renderer/platform/graphics/compositing/pending_layer_test.cc
index e6c6f40..66f9e253 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/pending_layer_test.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/pending_layer_test.cc
@@ -169,7 +169,8 @@
   TestPaintArtifact artifact;
   auto t1 = Create2DTranslation(t0(), 20, 25);
   auto t2 = Create2DTranslation(t0(), 1000, 1000);
-  auto e1 = CreateOpacityEffect(e0(), 1.0f, CompositingReason::kNone);
+  auto e1 =
+      CreateOpacityEffect(e0(), 1.0f, CompositingReason::kNoCompositingReason);
   artifact.Chunk(*t1, c0(), *e1).Bounds(gfx::Rect(0, 0, 30, 40));
   artifact.Chunk(*t2, c0(), *e1).Bounds(gfx::Rect(0, 0, 50, 60));
   PaintChunkSubset chunks(artifact.Build());
diff --git a/third_party/blink/renderer/platform/graphics/compositing_reasons.cc b/third_party/blink/renderer/platform/graphics/compositing_reasons.cc
index 349b5f3..5e2919b 100644
--- a/third_party/blink/renderer/platform/graphics/compositing_reasons.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing_reasons.cc
@@ -139,7 +139,7 @@
 #undef V
 
   std::vector<const char*> result;
-  if (reasons == kNone)
+  if (reasons == kNoCompositingReason)
     return result;
   for (auto& map : kCompositingReasonsStringMap) {
     if (reasons & map.reason)
@@ -151,7 +151,7 @@
 std::vector<const char*> CompositingReason::Descriptions(
     CompositingReasons reasons) {
   std::vector<const char*> result;
-  if (reasons == kNone)
+  if (reasons == kNoCompositingReason)
     return result;
   for (auto& map : kCompositingReasonsStringMap) {
     if (reasons & map.reason)
diff --git a/third_party/blink/renderer/platform/graphics/compositing_reasons.h b/third_party/blink/renderer/platform/graphics/compositing_reasons.h
index 900aa582..f452fd5 100644
--- a/third_party/blink/renderer/platform/graphics/compositing_reasons.h
+++ b/third_party/blink/renderer/platform/graphics/compositing_reasons.h
@@ -111,7 +111,7 @@
   static String ToString(CompositingReasons);
 
   enum : CompositingReasons {
-    kNone = 0,
+    kNoCompositingReason = 0,
     kAll = ~static_cast<CompositingReasons>(0),
 #define V(name) k##name = UINT64_C(1) << kE##name,
     FOR_EACH_COMPOSITING_REASON(V)
diff --git a/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.cc b/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.cc
index 26eee0c..05ae36df 100644
--- a/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.cc
@@ -168,7 +168,8 @@
     json->SetDouble("opacity", state_.opacity);
   if (state_.blend_mode != SkBlendMode::kSrcOver)
     json->SetString("blendMode", SkBlendMode_Name(state_.blend_mode));
-  if (state_.direct_compositing_reasons != CompositingReason::kNone) {
+  if (state_.direct_compositing_reasons !=
+      CompositingReason::kNoCompositingReason) {
     json->SetString(
         "directCompositingReasons",
         CompositingReason::ToString(state_.direct_compositing_reasons));
diff --git a/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h b/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h
index 57678f0..de8b8ba 100644
--- a/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h
+++ b/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h
@@ -111,7 +111,8 @@
     float opacity = 1;
     SkBlendMode blend_mode = SkBlendMode::kSrcOver;
     // === End of effects ===
-    CompositingReasons direct_compositing_reasons = CompositingReason::kNone;
+    CompositingReasons direct_compositing_reasons =
+        CompositingReason::kNoCompositingReason;
     CompositorElementId compositor_element_id;
 
     // An identifier for a document transition shared element. `id.valid()`
@@ -207,7 +208,8 @@
   gfx::RectF MapRect(const gfx::RectF& input_rect) const;
 
   bool HasDirectCompositingReasons() const {
-    return state_.direct_compositing_reasons != CompositingReason::kNone;
+    return state_.direct_compositing_reasons !=
+           CompositingReason::kNoCompositingReason;
   }
   bool RequiresCompositingForBackdropFilterMask() const {
     return state_.direct_compositing_reasons &
diff --git a/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc b/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc
index 6f4dda4..aff7076 100644
--- a/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc
@@ -155,7 +155,8 @@
     json->SetString("renderingContextId",
                     String::Format("%x", state_.rendering_context_id));
   }
-  if (state_.direct_compositing_reasons != CompositingReason::kNone) {
+  if (state_.direct_compositing_reasons !=
+      CompositingReason::kNoCompositingReason) {
     json->SetString(
         "directCompositingReasons",
         CompositingReason::ToString(state_.direct_compositing_reasons));
diff --git a/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h b/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h
index 65ea494..c837e49 100644
--- a/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h
+++ b/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h
@@ -204,7 +204,8 @@
     } flags = {false, true, false, false, false, false};
     BackfaceVisibility backface_visibility = BackfaceVisibility::kInherited;
     unsigned rendering_context_id = 0;
-    CompositingReasons direct_compositing_reasons = CompositingReason::kNone;
+    CompositingReasons direct_compositing_reasons =
+        CompositingReason::kNoCompositingReason;
     CompositorElementId compositor_element_id;
     std::unique_ptr<CompositorStickyConstraint> sticky_constraint;
     std::unique_ptr<AnchorScrollContainersData> anchor_scroll_containers_data;
@@ -353,7 +354,8 @@
   }
 
   bool HasDirectCompositingReasons() const {
-    return DirectCompositingReasons() != CompositingReason::kNone;
+    return DirectCompositingReasons() !=
+           CompositingReason::kNoCompositingReason;
   }
 
   bool HasDirectCompositingReasonsOtherThan3dTransform() const {
diff --git a/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h b/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h
index e1eca78..abe4b31 100644
--- a/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h
+++ b/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h
@@ -36,7 +36,8 @@
     const TransformPaintPropertyNodeOrAlias& local_transform_space,
     const ClipPaintPropertyNodeOrAlias* output_clip,
     float opacity,
-    CompositingReasons compositing_reasons = CompositingReason::kNone) {
+    CompositingReasons compositing_reasons =
+        CompositingReason::kNoCompositingReason) {
   EffectPaintPropertyNode::State state;
   state.local_transform_space = &local_transform_space;
   state.output_clip = output_clip;
@@ -50,7 +51,8 @@
 inline scoped_refptr<EffectPaintPropertyNode> CreateOpacityEffect(
     const EffectPaintPropertyNodeOrAlias& parent,
     float opacity,
-    CompositingReasons compositing_reasons = CompositingReason::kNone) {
+    CompositingReasons compositing_reasons =
+        CompositingReason::kNoCompositingReason) {
   return CreateOpacityEffect(parent, parent.Unalias().LocalTransformSpace(),
                              parent.Unalias().OutputClip(), opacity,
                              compositing_reasons);
@@ -75,7 +77,8 @@
     const TransformPaintPropertyNodeOrAlias& local_transform_space,
     const ClipPaintPropertyNodeOrAlias* output_clip,
     CompositorFilterOperations filter,
-    CompositingReasons compositing_reasons = CompositingReason::kNone) {
+    CompositingReasons compositing_reasons =
+        CompositingReason::kNoCompositingReason) {
   EffectPaintPropertyNode::State state;
   state.local_transform_space = &local_transform_space;
   state.output_clip = output_clip;
@@ -89,7 +92,8 @@
 inline scoped_refptr<EffectPaintPropertyNode> CreateFilterEffect(
     const EffectPaintPropertyNodeOrAlias& parent,
     CompositorFilterOperations filter,
-    CompositingReasons compositing_reasons = CompositingReason::kNone) {
+    CompositingReasons compositing_reasons =
+        CompositingReason::kNoCompositingReason) {
   return CreateFilterEffect(parent, parent.Unalias().LocalTransformSpace(),
                             parent.Unalias().OutputClip(), filter,
                             compositing_reasons);
@@ -234,7 +238,8 @@
     const TransformPaintPropertyNodeOrAlias& parent,
     const TransformationMatrix& matrix,
     const gfx::Point3F& origin = gfx::Point3F(),
-    CompositingReasons compositing_reasons = CompositingReason::kNone) {
+    CompositingReasons compositing_reasons =
+        CompositingReason::kNoCompositingReason) {
   TransformPaintPropertyNode::State state{{matrix, origin}};
   state.direct_compositing_reasons = compositing_reasons;
   return TransformPaintPropertyNode::Create(parent, std::move(state));
@@ -257,7 +262,8 @@
     float offset_x,
     float offset_y,
     const ScrollPaintPropertyNode& scroll,
-    CompositingReasons compositing_reasons = CompositingReason::kNone) {
+    CompositingReasons compositing_reasons =
+        CompositingReason::kNoCompositingReason) {
   TransformPaintPropertyNode::State state{gfx::Vector2dF(offset_x, offset_y)};
   state.direct_compositing_reasons = compositing_reasons;
   state.scroll = &scroll;
@@ -271,7 +277,8 @@
     const gfx::Rect& container_rect,
     const gfx::Size& contents_size,
     const ClipPaintPropertyNode* overflow_clip,
-    CompositingReasons compositing_reasons = CompositingReason::kNone,
+    CompositingReasons compositing_reasons =
+        CompositingReason::kNoCompositingReason,
     MainThreadScrollingReasons main_thread_reasons =
         cc::MainThreadScrollingReason::kNotOpaqueForTextAndLCDText) {
   const auto* parent_scroll_translation = &parent.Unalias();
@@ -324,7 +331,8 @@
     float offset_y,
     const gfx::Rect& container_rect,
     const gfx::Size& contents_size,
-    CompositingReasons compositing_reasons = CompositingReason::kNone,
+    CompositingReasons compositing_reasons =
+        CompositingReason::kNoCompositingReason,
     MainThreadScrollingReasons main_thread_reasons =
         cc::MainThreadScrollingReason::kNotOpaqueForTextAndLCDText) {
   RefCountedPropertyTreeState state(PropertyTreeState::Root());
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 54626bb7..db948df5 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1466,7 +1466,7 @@
 
 # external/wpt/css/css-fonts/... tests triaged away from the default WPT bug ID
 crbug.com/1211460 external/wpt/css/css-fonts/alternates-order.html [ Failure ]
-crbug.com/1240186 [ Mac ] external/wpt/css/css-fonts/font-family-name-025.html [ Failure ]
+crbug.com/641861 [ Mac ] external/wpt/css/css-fonts/font-family-name-025.html [ Failure ]
 crbug.com/443467 external/wpt/css/css-fonts/font-feature-settings-descriptor-01.html [ Failure ]
 crbug.com/819816 external/wpt/css/css-fonts/font-kerning-03.html [ Failure ]
 crbug.com/1219875 external/wpt/css/css-fonts/font-size-adjust-009.html [ Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index e04b8f3..44d330d 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -130,15 +130,6 @@
              "--disable-blink-features=DecodeJpeg420ImagesToYUV"]
   },
   {
-    "prefix": "v8-off-thread-finalization",
-    "platforms": ["Linux", "Mac", "Win"],
-    "bases": [
-      "external/wpt/html/semantics/scripting-1",
-      "fast/dom"
-    ],
-    "args": ["--enable-features=V8OffThreadFinalization,SmallScriptStreaming,SharedArrayBuffer"]
-  },
-  {
     "prefix": "exotic-color-space",
     "platforms": ["Linux", "Mac", "Win"],
     "bases": ["images"],
diff --git a/third_party/blink/web_tests/editing/spelling/cold_mode_no_repeated_full_testing.html b/third_party/blink/web_tests/editing/spelling/cold_mode_no_repeated_full_testing.html
index e50c9c0..01a96cf9 100644
--- a/third_party/blink/web_tests/editing/spelling/cold_mode_no_repeated_full_testing.html
+++ b/third_party/blink/web_tests/editing/spelling/cold_mode_no_repeated_full_testing.html
@@ -50,11 +50,11 @@
     () => {
       let recheckedTextLength =
           internals.spellCheckedTextLength(sample.document) - checkedTextLengthBefore;
-      assert_less_than_equal(recheckedTextLength, text.length);
+      assert_equals(recheckedTextLength, 0);
     },
     `<div contenteditable>${checkedMarkup.repeat(n)}</div>`,
     {
-      title: 'Step 3: Spell checker does not recheck more than one line',
+      title: 'Step 3: Spell checker does not recheck a fully-checked contenteditable on selection move',
       callback: step4,
     }
 );
@@ -62,12 +62,41 @@
 const step4 = sample => spellcheck_test(
     sample,
     () => {
+      checkedTextLengthBefore =
+        internals.spellCheckedTextLength(sample.document);
+      sample.selection.modify('extend', 'forward', 'line');
+      sample.document.execCommand('delete')
+    },
+    `<div contenteditable>${checkedMarkup.repeat(n - 1)}</div>`,
+    {
+      title: 'Step 4: Minor modification - delete one paragraph of text',
+      callback: step5,
+    }
+);
+
+const step5 = sample => spellcheck_test(
+    sample,
+    () => {
+      let recheckedTextLength =
+          internals.spellCheckedTextLength(sample.document) - checkedTextLengthBefore;
+      assert_less_than_equal(recheckedTextLength, text.length);
+    },
+    `<div contenteditable>${checkedMarkup.repeat(n - 1)}</div>`,
+    {
+      title: 'Step 5: Hot mode does not recheck more than one paragraph',
+      callback: step6,
+    }
+);
+
+const step6 = sample => spellcheck_test(
+    sample,
+    () => {
       const document = sample.document;
       document.execCommand('InsertText', false, (text + '\n').repeat(n));
     },
-    `<div contenteditable>${checkedMarkup.repeat(n * 2)}</div>`,
+    `<div contenteditable>${checkedMarkup.repeat(n * 2 - 1)}</div>`,
     {
-      title: 'Step 4: Spell checker rechecks text in full after significant changes',
+      title: 'Step 6: Spell checker rechecks text in full after significant changes',
       needsFullCheck: true,
     }
 );
diff --git a/third_party/blink/web_tests/external/OWNERS b/third_party/blink/web_tests/external/OWNERS
index dbb818c9..60be535 100644
--- a/third_party/blink/web_tests/external/OWNERS
+++ b/third_party/blink/web_tests/external/OWNERS
@@ -2,4 +2,4 @@
 
 foolip@chromium.org
 smcgruer@chromium.org
-weizhong@chromium.org
+weizhong@google.com
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version
index 74c9c9ede..694375c 100644
--- a/third_party/blink/web_tests/external/Version
+++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@
-Version: 69249a1305be98f163ccaeca33062d3b415d602a
+Version: ba9d74cbfd10ea809d5099a636043e257bc76a24
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 79053998..068940c 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
@@ -375937,6 +375937,13 @@
         {}
        ]
       ],
+      "background-shorthand-serialization.html": [
+       "5212303784bc0ed9086837dd8cf5db51b1eb1db3",
+       [
+        null,
+        {}
+       ]
+      ],
       "background-size-computed.html": [
        "2c6e340edd08787d46103ac234ef1d86ac05e688",
        [
@@ -391325,6 +391332,20 @@
         {}
        ]
       ],
+      "auto-006.html": [
+       "d88f51ba5eaad0b8cef23e5e32644797b4346338",
+       [
+        null,
+        {}
+       ]
+      ],
+      "auto-007.html": [
+       "02501264c8c2fe08fc28419f3cf3f48e03330657",
+       [
+        null,
+        {}
+       ]
+      ],
       "contain-intrinsic-size-028.html": [
        "15e8e0e89108b112bc113d6090946307379f53e7",
        [
@@ -498088,7 +498109,7 @@
      ]
     ],
     "MediaStreamTrack-iframe-transfer.https.html": [
-     "28ff506b9e7c0d222bd7e7097191a70f344e0a28",
+     "1dfc872e5ab4241de0a87682eb5c529af413d894",
      [
       null,
       {}
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/background-shorthand-serialization.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/background-shorthand-serialization.html
new file mode 100644
index 0000000..52123037
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/background-shorthand-serialization.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Background Shorthand Serialization Test: background shorthand should only serialize non-initial values</title>
+<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#background">
+<meta name="assert" content="background shorthand should only serialize non-initial values">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+  const element = document.createElement('div');
+
+  test((t) => {
+    element.style = 'background: yellow;';
+    assert_equals(element.style.background , 'yellow');
+  }, "single value");
+
+  test((t) => {
+    element.style = 'background: no-repeat url(/favicon.ico);';
+    assert_equals(element.style.background , 'url("/favicon.ico") no-repeat');
+  }, "multiple values");
+
+  test((t) => {
+    element.style = 'background: url(/favicon.ico) no-repeat, url(/favicon.ico) no-repeat;';
+    assert_equals(element.style.background , 'url("/favicon.ico") no-repeat, url("/favicon.ico") no-repeat');
+  }, "multiple backgrounds");
+
+  test((t) => {
+    element.style = 'background: url("/favicon.ico") 0% 0% / 10rem;';
+    assert_equals(element.style.background , 'url("/favicon.ico") 0% 0% / 10rem');
+  }, "background-size with non-initial background-position");
+
+  test((t) => {
+    element.style = `background: url(/favicon.ico) top left no-repeat,
+        url(/favicon.ico) center / 100% 100% no-repeat,
+        url(/favicon.ico) white;`;
+    assert_equals(element.style.background , 'url("/favicon.ico") left top no-repeat, url("/favicon.ico") center center / 100% 100% no-repeat, white url("/favicon.ico")');
+  }, "multiple backgrounds with varying values");
+
+  test((t) => {
+    element.style = `background: padding-box border-box;`;
+    assert_equals(element.style.background , 'none');
+  }, "all initial values");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/contain-intrinsic-size/auto-006.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/contain-intrinsic-size/auto-006.html
new file mode 100644
index 0000000..d88f51ba
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/contain-intrinsic-size/auto-006.html
@@ -0,0 +1,343 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Last remembered size</title>
+<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#last-remembered">
+<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#intrinsic-size-override">
+<link rel="help" href="https://drafts.csswg.org/css-contain-2/#content-visibility">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/6220">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7527">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7532">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7539">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7564">
+<meta name="assert" content="Tests that the last remembered size is properly updated or removed" />
+
+<style>
+#target {
+  width: max-content;
+  height: max-content;
+}
+.cis-auto {
+  contain-intrinsic-size: auto 1px auto 2px;
+}
+.skip-contents {
+  content-visibility: hidden;
+}
+.size-100-50 {
+  width: 100px;
+  height: 50px;
+}
+.size-75-25 {
+  width: 75px;
+  height: 25px;
+}
+.vertical {
+  writing-mode: vertical-lr;
+}
+.hidden {
+  display: none;
+}
+.flex {
+  display: flex;
+}
+</style>
+
+<div id="log"></div>
+
+<div id="parent">
+  <div id="target">
+    <div id="contents"></div>
+  </div>
+</div>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+const parent = document.getElementById("parent");
+const target = document.getElementById("target");
+const contents = document.getElementById("contents");
+
+function checkSize(expectedWidth, expectedHeight, msg) {
+  assert_equals(target.clientWidth, expectedWidth, msg + " - clientWidth");
+  assert_equals(target.clientHeight, expectedHeight, msg + " - clientHeight");
+}
+
+function nextRendering() {
+  return new Promise(resolve => {
+    requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
+  });
+}
+
+function cleanup() {
+  parent.className = "";
+  target.className = "";
+  contents.className = "";
+}
+
+promise_test(async function() {
+  this.add_cleanup(cleanup);
+  target.className = "cis-auto skip-contents";
+  contents.classList.add("size-100-50");
+  checkSize(1, 2, "Size containment with no last remembered size");
+
+  target.classList.remove("skip-contents");
+  checkSize(100, 50, "Sizing normally");
+
+  await nextRendering();
+  target.classList.add("skip-contents");
+  checkSize(100, 50, "Using last remembered size");
+
+  contents.classList.remove("size-100-50");
+  contents.classList.add("size-75-25");
+  checkSize(100, 50, "Still using last remembered size");
+
+  target.classList.remove("skip-contents");
+  checkSize(75, 25, "Sizing normally with different size");
+
+  target.classList.add("skip-contents");
+  checkSize(100, 50, "Going back to last remembered size");
+
+  target.classList.remove("skip-contents");
+  await nextRendering();
+  target.classList.add("skip-contents");
+  checkSize(75, 25, "Using the new last remembered size");
+}, "Basic usage");
+
+promise_test(async function() {
+  this.add_cleanup(cleanup);
+  target.classList.add("cis-auto");
+  checkSize(0, 0, "Sizing normally");
+
+  await nextRendering();
+  target.classList.add("skip-contents");
+  contents.classList.add("size-100-50");
+  checkSize(0, 0, "Using last remembered size");
+}, "Last remembered size can be 0");
+
+promise_test(async function() {
+  this.add_cleanup(cleanup);
+  target.classList.add("cis-auto");
+  contents.classList.add("size-100-50");
+  checkSize(100, 50, "Sizing normally");
+
+  await nextRendering();
+  target.classList.add("skip-contents");
+  contents.classList.remove("size-100-50");
+  checkSize(100, 50, "Using last remembered size");
+
+  target.classList.add("vertical");
+  checkSize(50, 100, "Last remembered size is logical");
+}, "Last remembered size is logical");
+
+promise_test(async function() {
+  this.add_cleanup(cleanup);
+  target.classList.add("cis-auto");
+  contents.classList.add("size-100-50");
+  checkSize(100, 50, "Sizing normally");
+
+  await nextRendering();
+  target.classList.add("skip-contents");
+  checkSize(100, 50, "Using last remembered size");
+
+  parent.classList.add("hidden");
+  checkSize(0, 0, "No box");
+
+  await nextRendering();
+  parent.classList.remove("hidden");
+  contents.classList.remove("size-100-50");
+  checkSize(100, 50, "Still using last remembered size");
+}, "Last remembered size survives box destruction");
+
+promise_test(async function() {
+  this.add_cleanup(cleanup);
+  target.classList.add("cis-auto");
+  contents.classList.add("size-100-50");
+  checkSize(100, 50, "Sizing normally");
+
+  await nextRendering();
+  target.classList.add("skip-contents");
+  contents.classList.remove("size-100-50");
+  checkSize(100, 50, "Using last remembered size");
+
+  target.classList.add("flex");
+  checkSize(100, 50, "Still using last remembered size");
+}, "Last remembered size survives display type changes");
+
+promise_test(async function() {
+  this.add_cleanup(cleanup);
+  target.classList.add("cis-auto");
+  contents.classList.add("size-100-50");
+  checkSize(100, 50, "Sizing normally");
+
+  await nextRendering();
+  target.classList.add("skip-contents");
+  checkSize(100, 50, "Using last remembered size");
+
+  target.classList.remove("cis-auto");
+  checkSize(0, 0, "Basic size containment");
+
+  await nextRendering();
+  target.classList.add("cis-auto");
+  checkSize(1, 2, "Size containment with no last remembered size");
+}, "Losing cis:auto removes last remembered size");
+
+promise_test(async function() {
+  this.add_cleanup(cleanup);
+  target.classList.add("cis-auto");
+  contents.classList.add("size-100-50");
+  checkSize(100, 50, "Sizing normally");
+
+  await nextRendering();
+  target.classList.remove("cis-auto");
+  checkSize(100, 50, "Sizing normally again");
+
+  await nextRendering();
+  target.classList.add("cis-auto");
+  target.classList.add("skip-contents");
+  checkSize(1, 2, "Size containment with no last remembered size");
+}, "Losing cis:auto removes last remembered size even if size doesn't change");
+
+promise_test(async function() {
+  this.add_cleanup(cleanup);
+  target.classList.add("cis-auto");
+  contents.classList.add("size-100-50");
+  checkSize(100, 50, "Sizing normally");
+
+  await nextRendering();
+  target.classList.add("skip-contents");
+  checkSize(100, 50, "Using last remembered size");
+
+  target.classList.remove("cis-auto");
+  checkSize(0, 0, "Basic size containment");
+
+  target.classList.add("cis-auto");
+  checkSize(1, 2, "Size containment with no last remembered size");
+}, "Losing cis:auto removes last remembered size immediately");
+
+promise_test(async function() {
+  this.add_cleanup(cleanup);
+  target.classList.add("cis-auto");
+  contents.classList.add("size-100-50");
+  checkSize(100, 50, "Sizing normally");
+
+  await nextRendering();
+  target.classList.add("skip-contents");
+  contents.classList.remove("size-100-50");
+  contents.classList.add("size-75-25");
+  checkSize(100, 50, "Using last remembered size");
+
+  parent.classList.add("hidden");
+  target.classList.remove("cis-auto");
+  target.classList.remove("skip-contents");
+  checkSize(0, 0, "No box");
+
+  await nextRendering();
+  parent.classList.remove("hidden");
+  target.classList.add("cis-auto");
+  contents.classList.remove("size-100-50");
+  contents.classList.add("size-75-25");
+  checkSize(75, 25, "Sizing normally with different size");
+
+  target.classList.add("skip-contents");
+  checkSize(100, 50, "Going back to last remembered size");
+}, "Losing cis:auto during display:none doesn't remove last remembered size");
+
+promise_test(async function() {
+  this.add_cleanup(cleanup);
+  target.classList.add("cis-auto");
+  contents.classList.add("size-100-50");
+  checkSize(100, 50, "Sizing normally");
+
+  await nextRendering();
+  target.classList.add("skip-contents");
+  contents.classList.remove("size-100-50");
+  contents.classList.add("size-75-25");
+  checkSize(100, 50, "Using last remembered size");
+
+  parent.classList.add("hidden");
+  checkSize(0, 0, "No box");
+
+  await nextRendering();
+  parent.classList.remove("hidden");
+  target.classList.remove("cis-auto");
+  checkSize(0, 0, "Basic size containment");
+
+  target.classList.add("cis-auto");
+  checkSize(1, 2, "Size containment with no last remembered size");
+}, "Lack of cis:auto during box creation removes last remembered size");
+
+promise_test(async function() {
+  this.add_cleanup(cleanup);
+  target.classList.add("cis-auto");
+  contents.classList.add("size-100-50");
+  checkSize(100, 50, "Sizing normally");
+
+  await nextRendering();
+  target.classList.add("skip-contents");
+  contents.classList.remove("size-100-50");
+  contents.classList.add("size-75-25");
+  checkSize(100, 50, "Using last remembered size");
+
+  parent.classList.add("hidden");
+  target.classList.remove("cis-auto");
+  checkSize(0, 0, "No box");
+
+  parent.classList.remove("hidden");
+  checkSize(0, 0, "Basic size containment");
+
+  target.classList.add("cis-auto");
+  checkSize(1, 2, "Size containment with no last remembered size");
+}, "Last remembered size can be removed synchronously");
+
+promise_test(async function() {
+  this.add_cleanup(cleanup);
+  target.classList.add("cis-auto");
+  contents.classList.add("size-100-50");
+  checkSize(100, 50, "Sizing normally");
+
+  await nextRendering();
+  target.classList.add("skip-contents");
+  checkSize(100, 50, "Using last remembered size");
+
+  target.remove();
+  checkSize(0, 0, "No box");
+
+  parent.appendChild(target);
+  checkSize(100, 50, "Still using last remembered size");
+}, "Disconnected element can briefly keep last remembered size");
+
+promise_test(async function() {
+  this.add_cleanup(cleanup);
+  target.classList.add("cis-auto");
+  contents.classList.add("size-100-50");
+  checkSize(100, 50, "Sizing normally");
+
+  await nextRendering();
+  target.classList.add("skip-contents");
+  contents.classList.remove("size-100-50");
+  contents.classList.add("size-75-25");
+  checkSize(100, 50, "Using last remembered size");
+
+  target.remove();
+  checkSize(0, 0, "No box");
+
+  await nextRendering();
+  parent.appendChild(target);
+  checkSize(1, 2, "Size containment with no last remembered size");
+}, "Disconnected element ends up losing last remembered size");
+
+promise_test(async function() {
+  this.add_cleanup(cleanup);
+  target.classList.add("cis-auto");
+  checkSize(0, 0, "Sizing normally");
+
+  await nextRendering();
+  target.classList.add("skip-contents");
+  target.remove();
+  checkSize(0, 0, "No box");
+
+  await nextRendering();
+  parent.appendChild(target);
+  checkSize(1, 2, "Size containment with no last remembered size");
+}, "Disconnected element ends up losing last remembered size even if size was 0x0");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/contain-intrinsic-size/auto-007.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/contain-intrinsic-size/auto-007.html
new file mode 100644
index 0000000..0250126
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/contain-intrinsic-size/auto-007.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Last remembered size</title>
+<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#last-remembered">
+<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#intrinsic-size-override">
+<link rel="help" href="https://drafts.csswg.org/css-contain-2/#content-visibility">
+<meta name="assert" content="Tests that the last remembered size works well in a variety of different elements or boxes." />
+
+<style>
+.test {
+  width: max-content;
+  height: max-content;
+  border: 1px solid;
+}
+.test::before {
+  content: "";
+  display: block;
+  width: 320px;
+  height: 240px;
+}
+.contain-size {
+  contain: size;
+}
+.auto-width {
+  contain-intrinsic-width: auto 1px;
+}
+.auto-height {
+  contain-intrinsic-height: auto 2px;
+}
+.auto-both {
+  contain-intrinsic-size: auto 3px auto 4px;
+}
+.skip-contents .test {
+  content-visibility: hidden;
+}
+.scroll {
+  overflow: scroll;
+}
+.columns {
+  columns: 60px 2;
+}
+.grid {
+  display: grid;
+}
+.flex {
+  display: flex;
+}
+</style>
+
+<div id="log"></div>
+
+<div id="tests">
+  <div></div>
+  <div class="scroll"></div>
+  <div class="columns"></div>
+  <div class="grid"></div>
+  <div class="flex"></div>
+  <fieldset></fieldset>
+  <img src="resources/dice.png">
+  <svg></svg>
+  <canvas></canvas>
+  <iframe></iframe>
+  <video></video>
+  <button></button>
+  <select><option>Lorem ipsum</option></select>
+  <select multiple><option>Lorem ipsum</option></select>
+</div>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<script>
+function nextRendering() {
+  return new Promise(resolve => {
+    requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
+  });
+}
+addEventListener("load", async function() {
+  const wrapper = document.getElementById("tests");
+  const tests = new DocumentFragment();
+  for (let template of wrapper.children) {
+    template.classList.add("test");
+    const autoWidthTest = template.cloneNode(true);
+    const autoHeightTest = template.cloneNode(true);
+    const autoBothTest = template.cloneNode(true);
+    autoWidthTest.classList.add("auto-width");
+    autoHeightTest.classList.add("auto-height");
+    autoBothTest.classList.add("auto-both");
+
+    const normalWidth = template.clientWidth;
+    const normalHeight = template.clientHeight;
+    template.classList.add("contain-size");
+    const containedWidth = template.clientWidth;
+    const containedHeight = template.clientHeight;
+
+    autoWidthTest.dataset.expectedClientWidth = normalWidth;
+    autoWidthTest.dataset.expectedClientHeight = containedHeight;
+    autoHeightTest.dataset.expectedClientWidth = containedWidth;
+    autoHeightTest.dataset.expectedClientHeight = normalHeight;
+    autoBothTest.dataset.expectedClientWidth = normalWidth;
+    autoBothTest.dataset.expectedClientHeight = normalHeight;
+
+    tests.append(autoWidthTest, autoHeightTest, autoBothTest);
+  }
+  wrapper.textContent = "";
+  wrapper.appendChild(tests);
+
+  // Wait so that the last remembered size can be stored.
+  await nextRendering();
+
+  wrapper.classList.add("skip-contents");
+  checkLayout(".test");
+});
+</script>
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-sizing/contain-intrinsic-size/auto-007-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-sizing/contain-intrinsic-size/auto-007-expected.txt
new file mode 100644
index 0000000..fc8a486
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-sizing/contain-intrinsic-size/auto-007-expected.txt
@@ -0,0 +1,65 @@
+This is a testharness.js-based test.
+PASS .test 1
+PASS .test 2
+PASS .test 3
+PASS .test 4
+FAIL .test 5 assert_equals: 
+<div class="scroll test auto-height" data-expected-client-width="0" data-expected-client-height="255"></div>
+clientHeight expected 255 but got 270
+FAIL .test 6 assert_equals: 
+<div class="scroll test auto-both" data-expected-client-width="320" data-expected-client-height="255"></div>
+clientHeight expected 255 but got 270
+FAIL .test 7 assert_equals: 
+<div class="columns test auto-width" data-expected-client-width="656" data-expected-client-height="0"></div>
+clientWidth expected 656 but got 1328
+PASS .test 8
+FAIL .test 9 assert_equals: 
+<div class="columns test auto-both" data-expected-client-width="656" data-expected-client-height="120"></div>
+clientWidth expected 656 but got 1328
+PASS .test 10
+PASS .test 11
+PASS .test 12
+PASS .test 13
+PASS .test 14
+PASS .test 15
+PASS .test 16
+PASS .test 17
+PASS .test 18
+PASS .test 19
+PASS .test 20
+PASS .test 21
+FAIL .test 22 assert_equals: 
+<svg class="test auto-width" data-expected-client-width="300" data-expected-client-height="0"></svg>
+clientWidth expected 300 but got 1
+FAIL .test 23 assert_equals: 
+<svg class="test auto-height" data-expected-client-width="0" data-expected-client-height="150"></svg>
+clientHeight expected 150 but got 2
+FAIL .test 24 assert_equals: 
+<svg class="test auto-both" data-expected-client-width="300" data-expected-client-height="150"></svg>
+clientWidth expected 300 but got 3
+FAIL .test 25 assert_equals: 
+<canvas class="test auto-width" data-expected-client-width="300" data-expected-client-height="0"></canvas>
+clientWidth expected 300 but got 1
+FAIL .test 26 assert_equals: 
+<canvas class="test auto-height" data-expected-client-width="0" data-expected-client-height="150"></canvas>
+clientHeight expected 150 but got 2
+FAIL .test 27 assert_equals: 
+<canvas class="test auto-both" data-expected-client-width="300" data-expected-client-height="150"></canvas>
+clientWidth expected 300 but got 3
+PASS .test 28
+PASS .test 29
+PASS .test 30
+PASS .test 31
+PASS .test 32
+PASS .test 33
+PASS .test 34
+PASS .test 35
+PASS .test 36
+PASS .test 37
+PASS .test 38
+PASS .test 39
+PASS .test 40
+PASS .test 41
+PASS .test 42
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/v8-off-thread-finalization/fast/dom/HTMLMeterElement/meter-optimums-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/v8-off-thread-finalization/fast/dom/HTMLMeterElement/meter-optimums-expected.png
deleted file mode 100644
index 2e3da26..0000000
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/v8-off-thread-finalization/fast/dom/HTMLMeterElement/meter-optimums-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/css/css-backgrounds/parsing/background-shorthand-serialization-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/css/css-backgrounds/parsing/background-shorthand-serialization-expected.txt
new file mode 100644
index 0000000..72b3686b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/generic/external/wpt/css/css-backgrounds/parsing/background-shorthand-serialization-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+PASS single value
+PASS multiple values
+PASS multiple backgrounds
+PASS background-size with non-initial background-position
+FAIL multiple backgrounds with varying values assert_equals: expected "url(\"/favicon.ico\") left top no-repeat, url(\"/favicon.ico\") center center / 100% 100% no-repeat, white url(\"/favicon.ico\")" but got "url(\"/favicon.ico\") left top no-repeat, url(\"/favicon.ico\") center center / 100% 100% no-repeat, url(\"/favicon.ico\") white"
+FAIL all initial values assert_equals: expected "none" but got "padding-box border-box"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/css/css-sizing/contain-intrinsic-size/auto-006-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/css/css-sizing/contain-intrinsic-size/auto-006-expected.txt
new file mode 100644
index 0000000..de0af677
--- /dev/null
+++ b/third_party/blink/web_tests/platform/generic/external/wpt/css/css-sizing/contain-intrinsic-size/auto-006-expected.txt
@@ -0,0 +1,17 @@
+This is a testharness.js-based test.
+PASS Basic usage
+FAIL Last remembered size can be 0 assert_equals: Using last remembered size - clientWidth expected 0 but got 75
+PASS Last remembered size is logical
+PASS Last remembered size survives box destruction
+PASS Last remembered size survives display type changes
+FAIL Losing cis:auto removes last remembered size assert_equals: Size containment with no last remembered size - clientWidth expected 1 but got 100
+FAIL Losing cis:auto removes last remembered size even if size doesn't change assert_equals: Size containment with no last remembered size - clientWidth expected 1 but got 100
+FAIL Losing cis:auto removes last remembered size immediately assert_equals: Size containment with no last remembered size - clientWidth expected 1 but got 100
+PASS Losing cis:auto during display:none doesn't remove last remembered size
+FAIL Lack of cis:auto during box creation removes last remembered size assert_equals: Size containment with no last remembered size - clientWidth expected 1 but got 100
+FAIL Last remembered size can be removed synchronously assert_equals: Size containment with no last remembered size - clientWidth expected 1 but got 100
+PASS Disconnected element can briefly keep last remembered size
+FAIL Disconnected element ends up losing last remembered size assert_equals: Size containment with no last remembered size - clientWidth expected 1 but got 100
+FAIL Disconnected element ends up losing last remembered size even if size was 0x0 assert_equals: Size containment with no last remembered size - clientWidth expected 1 but got 100
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/css/css-sizing/contain-intrinsic-size/auto-007-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/css/css-sizing/contain-intrinsic-size/auto-007-expected.txt
new file mode 100644
index 0000000..da58f52
--- /dev/null
+++ b/third_party/blink/web_tests/platform/generic/external/wpt/css/css-sizing/contain-intrinsic-size/auto-007-expected.txt
@@ -0,0 +1,61 @@
+This is a testharness.js-based test.
+PASS .test 1
+PASS .test 2
+PASS .test 3
+PASS .test 4
+PASS .test 5
+PASS .test 6
+FAIL .test 7 assert_equals: 
+<div class="columns test auto-width" data-expected-client-width="656" data-expected-client-height="0"></div>
+clientWidth expected 656 but got 1328
+PASS .test 8
+FAIL .test 9 assert_equals: 
+<div class="columns test auto-both" data-expected-client-width="656" data-expected-client-height="120"></div>
+clientWidth expected 656 but got 1328
+PASS .test 10
+PASS .test 11
+PASS .test 12
+PASS .test 13
+PASS .test 14
+PASS .test 15
+PASS .test 16
+PASS .test 17
+PASS .test 18
+PASS .test 19
+PASS .test 20
+PASS .test 21
+FAIL .test 22 assert_equals: 
+<svg class="test auto-width" data-expected-client-width="300" data-expected-client-height="0"></svg>
+clientWidth expected 300 but got 1
+FAIL .test 23 assert_equals: 
+<svg class="test auto-height" data-expected-client-width="0" data-expected-client-height="150"></svg>
+clientHeight expected 150 but got 2
+FAIL .test 24 assert_equals: 
+<svg class="test auto-both" data-expected-client-width="300" data-expected-client-height="150"></svg>
+clientWidth expected 300 but got 3
+FAIL .test 25 assert_equals: 
+<canvas class="test auto-width" data-expected-client-width="300" data-expected-client-height="0"></canvas>
+clientWidth expected 300 but got 1
+FAIL .test 26 assert_equals: 
+<canvas class="test auto-height" data-expected-client-width="0" data-expected-client-height="150"></canvas>
+clientHeight expected 150 but got 2
+FAIL .test 27 assert_equals: 
+<canvas class="test auto-both" data-expected-client-width="300" data-expected-client-height="150"></canvas>
+clientWidth expected 300 but got 3
+PASS .test 28
+PASS .test 29
+PASS .test 30
+PASS .test 31
+PASS .test 32
+PASS .test 33
+PASS .test 34
+PASS .test 35
+PASS .test 36
+PASS .test 37
+PASS .test 38
+PASS .test 39
+PASS .test 40
+PASS .test 41
+PASS .test 42
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/generic/virtual/v8-off-thread-finalization/fast/dom/geometry-interfaces-dom-matrix-rotate-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/v8-off-thread-finalization/fast/dom/geometry-interfaces-dom-matrix-rotate-expected.txt
deleted file mode 100644
index 9245a30..0000000
--- a/third_party/blink/web_tests/platform/generic/virtual/v8-off-thread-finalization/fast/dom/geometry-interfaces-dom-matrix-rotate-expected.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = 1 duplicate test name: "DOMMatrix 3d - rotateAxisAngleSelf()"
-PASS DOMMatrix 2d - rotate(rotX) and rotateSelf(rotX)
-PASS DOMMatrix 3d - rotate(rotX) and rotateSelf(rotX)
-PASS DOMMatrix 2d - rotate(rotX, rotY) and rotateSelf(rotX, rotY)
-PASS DOMMatrix 3d - rotate(rotX, rotY) and rotateSelf(rotX, rotY)
-PASS DOMMatrix 2d - rotate(rotX, rotY, rotX) and rotateSelf(rotX, rotY, rotX)
-PASS DOMMatrix 3d - rotate(rotX, rotY, rotX) and rotateSelf(rotX, rotY, rotX)
-PASS DOMMatrix 2d - rotateFromVector(x, y) and rotateFromVectorSelf(x, y)
-PASS DOMMatrix 3d - rotateFromVector(x, y) rotateFromVectorSelf(x, y)
-PASS DOMMatrix 2d - rotateAxisAngleSelf()
-PASS DOMMatrix 2d - rotateAxisAngleSelf(0, 0, 1)
-PASS DOMMatrix 2d - rotateAxisAngleSelf(1, 1, 1, 0)
-PASS DOMMatrix 2d - rotateAxisAngleSelf(1, 0, 0, 10)
-PASS DOMMatrix 2d - rotateAxisAngleSelf(0, 1, 0, 27)
-PASS DOMMatrix 2d - rotateAxisAngleSelf(0, 0, 1, 38)
-PASS DOMMatrix 2d - rotateAxisAngleSelf(1, 1, 1, 45)
-PASS DOMMatrix 3d - rotateAxisAngleSelf()
-PASS DOMMatrix 3d - rotateAxisAngleSelf(0, 0, 1)
-PASS DOMMatrix 3d - rotateAxisAngleSelf(0, 0, 1, 0)
-PASS DOMMatrix 3d - rotateAxisAngleSelf(1, 0, 0, 19)
-PASS DOMMatrix 3d - rotateAxisAngleSelf(0, 1, 0, 46)
-PASS DOMMatrix 3d - rotateAxisAngleSelf(0, 0, 1, 65)
-PASS DOMMatrix 3d - rotateAxisAngleSelf(1, 1, 1, 67)
-PASS DOMMatrixReadOnly 2d - rotateAxisAngle()
-PASS DOMMatrixReadOnly 2d - rotateAxisAngle(0, 0, 1)
-PASS DOMMatrixReadOnly 2d - rotateAxisAngle(1, 1, 1, 0)
-PASS DOMMatrixReadOnly 2d - rotateAxisAngle(1, 0, 0, 21)
-PASS DOMMatrixReadOnly 2d - rotateAxisAngle(0, 1, 0, 35)
-PASS DOMMatrixReadOnly 2d - rotateAxisAngle(0, 0, 1, 55)
-PASS DOMMatrixReadOnly 2d - rotateAxisAngle(1, 1, 1, 75)
-PASS DOMMatrixReadOnly 3d - rotateAxisAngle()
-PASS DOMMatrixReadOnly 3d - rotateAxisAngle(0, 0, 1)
-PASS DOMMatrixReadOnly 3d - rotateAxisAngle(0, 0, 1, 0)
-PASS DOMMatrixReadOnly 3d - rotateAxisAngle(1, 1, 1, 0)
-PASS DOMMatrixReadOnly 3d - rotateAxisAngle(1, 0, 0, 105)
-PASS DOMMatrixReadOnly 3d - rotateAxisAngle(0, 1, 0, 45)
-PASS DOMMatrixReadOnly 3d - rotateAxisAngle(0, 0, 1, 65)
-PASS DOMMatrixReadOnly 3d - rotateAxisAngle(1, 1, 1, 78)
-PASS DOMMatrix 2d - rotateAxisAngleSelf() - do rotate +90,-90
-PASS DOMMatrix 2d - rotateAxisAngle() - do rotate -180,+180
-PASS DOMMatrix 3d - rotateAxisAngleSelf() - do rotate +90,-90
-PASS DOMMatrix 3d - rotateAxisAngle() - do rotate -180,+180
-PASS DOMMatrix 3d - rotateAxisAngle()
-PASS DOMMatrix 3d - rotateAxisAngleSelf()
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/virtual/v8-off-thread-finalization/fast/dom/HTMLMeterElement/meter-optimums-expected.png b/third_party/blink/web_tests/platform/linux/virtual/v8-off-thread-finalization/fast/dom/HTMLMeterElement/meter-optimums-expected.png
deleted file mode 100644
index 2e3da26..0000000
--- a/third_party/blink/web_tests/platform/linux/virtual/v8-off-thread-finalization/fast/dom/HTMLMeterElement/meter-optimums-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/v8-off-thread-finalization/fast/dom/focus-contenteditable-expected.png b/third_party/blink/web_tests/platform/linux/virtual/v8-off-thread-finalization/fast/dom/focus-contenteditable-expected.png
deleted file mode 100644
index 7e60871..0000000
--- a/third_party/blink/web_tests/platform/linux/virtual/v8-off-thread-finalization/fast/dom/focus-contenteditable-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/v8-off-thread-finalization/fast/dom/HTMLMeterElement/meter-styles-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/v8-off-thread-finalization/fast/dom/HTMLMeterElement/meter-styles-expected.png
deleted file mode 100644
index fb98b90..0000000
--- a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/v8-off-thread-finalization/fast/dom/HTMLMeterElement/meter-styles-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/v8-off-thread-finalization/fast/dom/HTMLMeterElement/meter-styles-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/v8-off-thread-finalization/fast/dom/HTMLMeterElement/meter-styles-expected.png
deleted file mode 100644
index fb98b90..0000000
--- a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/v8-off-thread-finalization/fast/dom/HTMLMeterElement/meter-styles-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/v8-off-thread-finalization/fast/dom/geometry-interfaces-dom-matrix-rotate-expected.txt b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/v8-off-thread-finalization/fast/dom/geometry-interfaces-dom-matrix-rotate-expected.txt
deleted file mode 100644
index 874ee5a8..0000000
--- a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/v8-off-thread-finalization/fast/dom/geometry-interfaces-dom-matrix-rotate-expected.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = 1 duplicate test name: "DOMMatrix 3d - rotateAxisAngleSelf()"
-PASS DOMMatrix 2d - rotate(rotX) and rotateSelf(rotX)
-PASS DOMMatrix 3d - rotate(rotX) and rotateSelf(rotX)
-PASS DOMMatrix 2d - rotate(rotX, rotY) and rotateSelf(rotX, rotY)
-PASS DOMMatrix 3d - rotate(rotX, rotY) and rotateSelf(rotX, rotY)
-PASS DOMMatrix 2d - rotate(rotX, rotY, rotX) and rotateSelf(rotX, rotY, rotX)
-PASS DOMMatrix 3d - rotate(rotX, rotY, rotX) and rotateSelf(rotX, rotY, rotX)
-PASS DOMMatrix 2d - rotateFromVector(x, y) and rotateFromVectorSelf(x, y)
-PASS DOMMatrix 3d - rotateFromVector(x, y) rotateFromVectorSelf(x, y)
-PASS DOMMatrix 2d - rotateAxisAngleSelf()
-PASS DOMMatrix 2d - rotateAxisAngleSelf(0, 0, 1)
-PASS DOMMatrix 2d - rotateAxisAngleSelf(1, 1, 1, 0)
-PASS DOMMatrix 2d - rotateAxisAngleSelf(1, 0, 0, 10)
-PASS DOMMatrix 2d - rotateAxisAngleSelf(0, 1, 0, 27)
-PASS DOMMatrix 2d - rotateAxisAngleSelf(0, 0, 1, 38)
-PASS DOMMatrix 2d - rotateAxisAngleSelf(1, 1, 1, 45)
-PASS DOMMatrix 3d - rotateAxisAngleSelf()
-PASS DOMMatrix 3d - rotateAxisAngleSelf(0, 0, 1)
-PASS DOMMatrix 3d - rotateAxisAngleSelf(0, 0, 1, 0)
-PASS DOMMatrix 3d - rotateAxisAngleSelf(1, 0, 0, 19)
-PASS DOMMatrix 3d - rotateAxisAngleSelf(0, 1, 0, 46)
-PASS DOMMatrix 3d - rotateAxisAngleSelf(0, 0, 1, 65)
-PASS DOMMatrix 3d - rotateAxisAngleSelf(1, 1, 1, 67)
-PASS DOMMatrixReadOnly 2d - rotateAxisAngle()
-PASS DOMMatrixReadOnly 2d - rotateAxisAngle(0, 0, 1)
-PASS DOMMatrixReadOnly 2d - rotateAxisAngle(1, 1, 1, 0)
-PASS DOMMatrixReadOnly 2d - rotateAxisAngle(1, 0, 0, 21)
-PASS DOMMatrixReadOnly 2d - rotateAxisAngle(0, 1, 0, 35)
-PASS DOMMatrixReadOnly 2d - rotateAxisAngle(0, 0, 1, 55)
-PASS DOMMatrixReadOnly 2d - rotateAxisAngle(1, 1, 1, 75)
-PASS DOMMatrixReadOnly 3d - rotateAxisAngle()
-PASS DOMMatrixReadOnly 3d - rotateAxisAngle(0, 0, 1)
-PASS DOMMatrixReadOnly 3d - rotateAxisAngle(0, 0, 1, 0)
-PASS DOMMatrixReadOnly 3d - rotateAxisAngle(1, 1, 1, 0)
-PASS DOMMatrixReadOnly 3d - rotateAxisAngle(1, 0, 0, 105)
-PASS DOMMatrixReadOnly 3d - rotateAxisAngle(0, 1, 0, 45)
-PASS DOMMatrixReadOnly 3d - rotateAxisAngle(0, 0, 1, 65)
-PASS DOMMatrixReadOnly 3d - rotateAxisAngle(1, 1, 1, 78)
-FAIL DOMMatrix 2d - rotateAxisAngleSelf() - do rotate +90,-90 assert_equals: expected "0.0000000000" but got "-0.0000000000"
-PASS DOMMatrix 2d - rotateAxisAngle() - do rotate -180,+180
-PASS DOMMatrix 3d - rotateAxisAngleSelf() - do rotate +90,-90
-PASS DOMMatrix 3d - rotateAxisAngle() - do rotate -180,+180
-PASS DOMMatrix 3d - rotateAxisAngle()
-PASS DOMMatrix 3d - rotateAxisAngleSelf()
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/win10/external/wpt/html/browsers/the-window-object/window-properties.https-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/html/browsers/the-window-object/window-properties.https-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/win10/external/wpt/html/browsers/the-window-object/window-properties.https-expected.txt
rename to third_party/blink/web_tests/platform/win/external/wpt/html/browsers/the-window-object/window-properties.https-expected.txt
diff --git a/third_party/blink/web_tests/virtual/v8-off-thread-finalization/README.txt b/third_party/blink/web_tests/virtual/v8-off-thread-finalization/README.txt
deleted file mode 100644
index 2ecd845..0000000
--- a/third_party/blink/web_tests/virtual/v8-off-thread-finalization/README.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Virtual test suite for testing background finalization and streaming
-of small scripts.
diff --git a/third_party/blink/web_tests/virtual/v8-off-thread-finalization/external/wpt/html/semantics/scripting-1/README.txt b/third_party/blink/web_tests/virtual/v8-off-thread-finalization/external/wpt/html/semantics/scripting-1/README.txt
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/virtual/v8-off-thread-finalization/external/wpt/html/semantics/scripting-1/README.txt
+++ /dev/null
diff --git a/third_party/blink/web_tests/virtual/v8-off-thread-finalization/fast/dom/README.txt b/third_party/blink/web_tests/virtual/v8-off-thread-finalization/fast/dom/README.txt
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/virtual/v8-off-thread-finalization/fast/dom/README.txt
+++ /dev/null
diff --git a/third_party/blink/web_tests/virtual/v8-off-thread-finalization/http/tests/devtools/isolated-code-cache/README.txt b/third_party/blink/web_tests/virtual/v8-off-thread-finalization/http/tests/devtools/isolated-code-cache/README.txt
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/virtual/v8-off-thread-finalization/http/tests/devtools/isolated-code-cache/README.txt
+++ /dev/null
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium
index d427a4a..ecb3bcd 100644
--- a/third_party/crashpad/README.chromium
+++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@
 Short Name: crashpad
 URL: https://crashpad.chromium.org/
 Version: unknown
-Revision: 3e80b95054c868241ee3ec291603f5babda685e1
+Revision: a2d0cefe018b9c33ce9ac4305e4aae610d63ed68
 License: Apache 2.0
 License File: crashpad/LICENSE
 Security Critical: yes
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc
index 71ff734..951803a 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc
@@ -359,8 +359,15 @@
       mach_vm_address_t expected_stack_region_end = iterator->second.stack_base;
       if (thread_index > 0) {
         // Non-main threads use the stack region to store thread data. See
-        // _pthread_allocate.
+        // macOS 12 libpthread-486.100.11 src/pthread.c _pthread_allocate().
+#if defined(ARCH_CPU_ARM64)
+        // arm64 has an additional offset for alignment. See macOS 12 
+        // libpthread-486.100.11 src/pthread.c _pthread_allocate() and
+        // PTHREAD_T_OFFSET (defined in src/types_internal.h).
+        expected_stack_region_end += sizeof(_opaque_pthread_t) + 0x3000;
+#else
         expected_stack_region_end += sizeof(_opaque_pthread_t);
+#endif
       }
       EXPECT_LT(iterator->second.stack_base - iterator->second.stack_size,
                 thread.stack_region_address);
diff --git a/third_party/crashpad/crashpad/util/BUILD.gn b/third_party/crashpad/crashpad/util/BUILD.gn
index 33de2fdf..e59f67d 100644
--- a/third_party/crashpad/crashpad/util/BUILD.gn
+++ b/third_party/crashpad/crashpad/util/BUILD.gn
@@ -679,10 +679,6 @@
     }
   } else if (crashpad_http_transport_impl == "libcurl") {
     sources += [ "net/http_transport_libcurl.cc" ]
-    if (crashpad_is_in_fuchsia) {
-      # Host Linux builds in Fuchsia don't have libcurl in a sysroot.
-      deps += [ "//third_party/curl:libcurl" ]
-    }
   }
 }
 
diff --git a/third_party/ipcz/src/connect_test.cc b/third_party/ipcz/src/connect_test.cc
index 41cb3d54..80dd073 100644
--- a/third_party/ipcz/src/connect_test.cc
+++ b/third_party/ipcz/src/connect_test.cc
@@ -4,8 +4,11 @@
 
 #include <string>
 
+#include "build/build_config.h"
 #include "ipcz/ipcz.h"
 #include "ipcz/node_messages.h"
+#include "reference_drivers/async_reference_driver.h"
+#include "reference_drivers/sync_reference_driver.h"
 #include "test/multinode_test.h"
 #include "test/test_transport_listener.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -15,7 +18,16 @@
 namespace ipcz {
 namespace {
 
-using ConnectTestNode = test::TestNode;
+class ConnectTestNode : public test::TestNode {
+ public:
+  void ActivateAndClose(IpczDriverHandle transport) {
+    // Registering any listener callback activates the transport, and
+    // listener destruction closes it.
+    test::TestTransportListener listener(node(), transport);
+    listener.OnError([] {});
+  }
+};
+
 using ConnectTest = test::MultinodeTest<ConnectTestNode>;
 
 MULTINODE_TEST_NODE(ConnectTestNode, BrokerToNonBrokerClient) {
@@ -62,8 +74,7 @@
   IpczDriverHandle our_transport;
   auto controller =
       SpawnTestNodeNoConnect<ExpectDisconnectFromBroker>(our_transport);
-  EXPECT_EQ(IPCZ_RESULT_OK,
-            GetDriver().Close(our_transport, IPCZ_NO_FLAGS, nullptr));
+  ActivateAndClose(our_transport);
   controller->WaitForShutdown();
 }
 
@@ -90,8 +101,7 @@
       IPCZ_RESULT_OK,
       GetDriver().Transmit(our_transport, kBadMessage, std::size(kBadMessage),
                            nullptr, 0, IPCZ_NO_FLAGS, nullptr));
-  EXPECT_EQ(IPCZ_RESULT_OK,
-            GetDriver().Close(our_transport, IPCZ_NO_FLAGS, nullptr));
+  ActivateAndClose(our_transport);
 
   // The other node will only shut down once it's observed peer closure on its
   // portal to us; which it should, because we just sent it some garbage.
@@ -160,6 +170,16 @@
 }
 
 MULTINODE_TEST(ConnectTest, NonBrokerToNonBroker) {
+#if BUILDFLAG(IS_ANDROID)
+  // Client nodes launching other client nodes doesn't work for Chromium's
+  // custom test driver on Android. Limit this test to the reference test
+  // drivers there.
+  if (&GetDriver() != &reference_drivers::kSyncReferenceDriver &&
+      &GetDriver() != &reference_drivers::kAsyncReferenceDriver) {
+    return;
+  }
+#endif
+
   IpczHandle c1 = SpawnTestNode<NonBrokerToNonBrokerClient>();
   IpczHandle c2 = SpawnTestNode<NonBrokerToNonBrokerClient>();
 
@@ -234,11 +254,10 @@
       SpawnTestNodeNoConnect<FailedNonBrokerReferralReferredClient>(
           our_transport);
 
-  // Disconnect the transport instead of passing to our broker with
-  // ConnectNode(). The referred client should observe disconnection of its
-  // initial portals and terminate itself.
-  EXPECT_EQ(IPCZ_RESULT_OK,
-            GetDriver().Close(our_transport, IPCZ_NO_FLAGS, nullptr));
+  // Activate and immediately disconnect the transport instead of passing to our
+  // broker with ConnectNode(). The referred client should observe disconnection
+  // of its initial portals and terminate itself.
+  ActivateAndClose(our_transport);
   controller->WaitForShutdown();
   Close(b);
 }
diff --git a/third_party/ipcz/src/remote_portal_test.cc b/third_party/ipcz/src/remote_portal_test.cc
index fb554c8..9056900 100644
--- a/third_party/ipcz/src/remote_portal_test.cc
+++ b/third_party/ipcz/src/remote_portal_test.cc
@@ -178,10 +178,8 @@
 
     IpczHandle box = BoxBlob(absl::StrCat(absl::Dec(i)));
     EXPECT_EQ(IPCZ_RESULT_OK, Put(portals[i], "", {&box, 1}));
-  }
 
-  for (size_t i = 0; i < kHugeNumberOfPortalsCount; ++i) {
-    IpczHandle box;
+    box = IPCZ_INVALID_HANDLE;
     EXPECT_EQ(IPCZ_RESULT_OK, WaitToGet(portals[i], nullptr, {&box, 1}));
     EXPECT_EQ(absl::StrCat(absl::Dec(i)), UnboxBlob(box));
   }
diff --git a/third_party/metrics_proto/OWNERS b/third_party/metrics_proto/OWNERS
index 6beb6cf7..dc0cf63 100644
--- a/third_party/metrics_proto/OWNERS
+++ b/third_party/metrics_proto/OWNERS
@@ -1,5 +1,10 @@
 file://base/metrics/OWNERS
 
+# Allow anyone to review README.chromium changes created by the import script.
+# This lets per-file OWNERS approve changes without looping in a base/metrics
+# OWNER just for the README.
+per-file README.chromium=*
+
 per-file sampled_profile.proto=wittman@chromium.org
 per-file call_stack_profile.proto=wittman@chromium.org
 per-file execution_context.proto=wittman@chromium.org
diff --git a/third_party/metrics_proto/PRESUBMIT.py b/third_party/metrics_proto/PRESUBMIT.py
index 6445c0e..26da2b77 100644
--- a/third_party/metrics_proto/PRESUBMIT.py
+++ b/third_party/metrics_proto/PRESUBMIT.py
@@ -12,6 +12,8 @@
 
 README = 'README.chromium'
 PRESUBMIT = 'PRESUBMIT.py'
+PRESUBMIT_TEST = 'PRESUBMIT_test.py'
+OWNERS = 'OWNERS'
 
 
 def IsMetricsProtoPath(input_api, path):
@@ -24,7 +26,8 @@
 
 
 def IsImportedFile(input_api, path):
-  return (input_api.os_path.basename(path) != PRESUBMIT and
+  return (not input_api.os_path.basename(path) in(PRESUBMIT, PRESUBMIT_TEST,
+                                                  OWNERS) and
           IsMetricsProtoPath(input_api, path))
 
 
diff --git a/third_party/metrics_proto/PRESUBMIT_test.py b/third_party/metrics_proto/PRESUBMIT_test.py
index d64106c..bdecd21 100755
--- a/third_party/metrics_proto/PRESUBMIT_test.py
+++ b/third_party/metrics_proto/PRESUBMIT_test.py
@@ -44,16 +44,20 @@
   def testExcludedPaths(self):
     input_api = MockInputApi()
     input_api.files = [
-      # Changes to this file don't require README changes.
+      # Changes to these files don't require README changes.
       MockAffectedFile(FullPath('PRESUBMIT.py'), 'some diff'),
+      MockAffectedFile(FullPath('PRESUBMIT_test.py'), 'some diff'),
+      MockAffectedFile(FullPath('OWNERS'), 'some diff'),
     ]
     self.assertEqual(0, len(PRESUBMIT.CheckChange(input_api, MockOutputApi())))
 
   def testIncludedAndExcludedPaths(self):
     input_api = MockInputApi()
     input_api.files = [
-      # Changes to this file don't require README changes.
+      # Changes to these files don't require README changes.
       MockAffectedFile(FullPath('PRESUBMIT.py'), 'some diff'),
+      MockAffectedFile(FullPath('PRESUBMIT_test.py'), 'some diff'),
+      MockAffectedFile(FullPath('OWNERS'), 'some diff'),
       # But this one does.
       MockAffectedFile(FullPath('somefile.proto'), 'some diff'),
     ]
diff --git a/third_party/updater/chromium_win_x86/3pp/fetch.py b/third_party/updater/chromium_win_x86/3pp/fetch.py
index 4a9cab09..1254a8a 100755
--- a/third_party/updater/chromium_win_x86/3pp/fetch.py
+++ b/third_party/updater/chromium_win_x86/3pp/fetch.py
@@ -14,7 +14,7 @@
 # MIN_VERSION is the earliest working version of the updater for self-update
 # testing. If a backwards-incompatible change to the updater is made, it may be
 # necessary to increase the version.
-MIN_VERSION = 1017712
+MIN_VERSION = 1037709
 
 def get_platform():
     return 'Win'
diff --git a/third_party/updater/chromium_win_x86_64/3pp/fetch.py b/third_party/updater/chromium_win_x86_64/3pp/fetch.py
index ae21895..969e7d22 100755
--- a/third_party/updater/chromium_win_x86_64/3pp/fetch.py
+++ b/third_party/updater/chromium_win_x86_64/3pp/fetch.py
@@ -14,7 +14,7 @@
 # MIN_VERSION is the earliest working version of the updater for self-update
 # testing. If a backwards-incompatible change to the updater is made, it may be
 # necessary to increase the version.
-MIN_VERSION = 1017727
+MIN_VERSION = 1037734
 
 def get_platform():
     return 'Win_x64'
diff --git a/third_party/wpt_tools/README.chromium b/third_party/wpt_tools/README.chromium
index 21e2640..ece8f3e31 100644
--- a/third_party/wpt_tools/README.chromium
+++ b/third_party/wpt_tools/README.chromium
@@ -1,7 +1,7 @@
 Name: web-platform-tests - Test Suites for Web Platform specifications
 Short Name: wpt
 URL: https://github.com/web-platform-tests/wpt/
-Version: 853d9c3a31016504d1a51aa811c9890495a1d442
+Version: e238ab918eac3ef48132d5c1cf9e161428f11b11
 License: LICENSES FOR W3C TEST SUITES (https://www.w3.org/Consortium/Legal/2008/03-bsd-license.html)
 License File: NOT_SHIPPED
 Security Critical: no
diff --git a/third_party/wpt_tools/wpt/tools/certs/README.md b/third_party/wpt_tools/wpt/tools/certs/README.md
index fd75c22..95d9fbd2 100644
--- a/third_party/wpt_tools/wpt/tools/certs/README.md
+++ b/third_party/wpt_tools/wpt/tools/certs/README.md
@@ -25,9 +25,26 @@
 
 ## Regenerating certificates
 
-If you wish to generate new certificates for any reason, it's possible to use
-OpenSSL when starting the server, or starting a test run, by providing the
-`--ssl-type=openssl` argument to the `wpt serve` or `wpt run` commands.
+The easiest way to regenerate the pregenerated certificates is to the
+the command
+
+```
+wpt regen-certs
+```
+
+By default this will not generate new certificates unless the existing
+ones are about to expire. In cases where the certificates need to be
+updated anyway (e.g. because the server configuration changed), this
+can be overridden with `--force`.
+
+Generating the certificates requires OpenSSL to be installed.
+
+### Implementation Details
+
+If you wish to manually generate new certificates for any reason, it's
+possible to use OpenSSL when starting the server, or starting a test
+run, by providing the `--ssl-type=openssl` argument to the `wpt serve`
+or `wpt run` commands.
 
 If you installed OpenSSL in such a way that running `openssl` at a
 command line doesn't work, you also need to adjust the path to the
@@ -38,10 +55,16 @@
 "ssl": {"openssl": {"binary": "/path/to/openssl"}}
 ```
 
-On Windows using OpenSSL typically requires installing an OpenSSL distribution.
+### Windows-specific Instructions
+
+For Windows users, the easiest approach is likely to be using
+[WSL](https://docs.microsoft.com/en-us/windows/wsl/) and generate
+certificates in a Linux environment. However it is possible to install
+OpenSSL and generate the certificates without using WSL.
+
 [Shining Light](https://slproweb.com/products/Win32OpenSSL.html)
 provide a convenient installer that is known to work, but requires a
-little extra setup, i.e.:
+little extra setup:
 
 Run the installer for Win32_OpenSSL_v1.1.0b (30MB). During installation,
 change the default location for where to Copy OpenSSL Dlls from the
@@ -74,8 +97,3 @@
   },
 }
 ```
-
-### Regenerating the pregenerated certificates
-
-From the root, run `./wpt serve --config tools/certs/config.json` and terminate
-it after it has started up.
diff --git a/third_party/wpt_tools/wpt/tools/certs/cacert.key b/third_party/wpt_tools/wpt/tools/certs/cacert.key
index a36b5b57..a02adca 100644
--- a/third_party/wpt_tools/wpt/tools/certs/cacert.key
+++ b/third_party/wpt_tools/wpt/tools/certs/cacert.key
@@ -1,30 +1,30 @@
 -----BEGIN ENCRYPTED PRIVATE KEY-----
-MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQI+U8w4bULmEUCAggA
-MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECBSwsRljMUldBIIEyOxEXl3tiNYt
-kt4de0FQppfqEvUtPtLXIjpBOJznFb6U2QD/1PzDRpHAzchifLwnwUE8nYJ/hpWX
-2yIBXjHAHwnynApkoWGTt2aN0je+qa0GZLZaiGa241zM+n0qzIVfep8Lj6hPEf2s
-u6ZU8UekbJ13sMbQk/7aB270G6ArwCQZTy9WobRMtDliDPqXfke+4/7JV4jhQ1K2
-34WwXXLGw96gk7+XlmPHvpr4TPTxwM9DrEra8jvkT4SC0XkGygR8kTsCWKCyfy6X
-d7uo0YrShRsqkI32ciDSszUSZdPzeLX+OJaiIkIAXt6xyZS8QRoN09s/1u6wmLKF
-CTXSev4NSUohcxGpPXYZ9F/hXVSjlc/MlQ7G8gsOWGC2NG63fuZDkl4D3TqhL8xX
-yki9hgmvwWtGJKRDW4nlBjixkFlWuBeVTfpYDE3PwmopVOe/zLlK88E05d5SVlmX
-qEAifSfpfjcL2WcEe/wgeoxuQ+L/urfBhgaM7H9InXclxzzj1tO9CRbji7OHl10s
-IDPhEuuOc09EYouBJE+u1nieL6fJ41hSwXBrWPX4IeUAbRvI7e+79L1VnI/VXPxT
-DM7XWus99/cEObte8qZ1pOv7bx291VMJkKcLEnMu5WlPiv7R4SsvQCx22E97bzHq
-cH9147T7vtwUIhxHMbF7Ue7jpUvUbdFbNgsm5VjQz+XnOvrFntVUUX+ch34m4GXJ
-WVJG7OhLOw5P9i6R9AViN5WVJWXx7xJKSpw2BLK7Pfvi/gZY+0er0Z6s2V/PKRl9
-AnuGX4XCulcO+3fujp0RvkKRywvWR+eN0R9sAvupJ3z3R8p0KeMqbF73CRfgetei
-KQKhV2CkEmrgdlfFgTkIqh5vtlc2yxnFS4WEi+3CiFAqNyjx20Sa38lSScYI4CJ5
-lKy4wHcaz5cbsgq9kjnPnL0Enmfeh/WMylxtnckTIqaPyA6sLlInAWI1hUTOkcRs
-4WH9C0iXF51T+SBzFvjHWNRoYp3G1KYtHDV7/4OuUJeaVRNlx/bUsarhMf7QD+wt
-FHPrOFsGemd+L0uEChP2TlgzmVpYWokwBwHYHvh5auGtjJm6f4IUoCSsLD/jNwC5
-6Iw6XiWlHvx1cT+So22TgfmVy94MoW/pg8PaPwrkdMg5CuPLncCymITwBHMtMZPw
-wytuNv21t2PKKfB/YLnLDkj3Hzs0spDFU0V/+EYt+fJk3b7l16FtYFBYk586bUmi
-pPDY9ofD0acuKUeJPJzndVaqBAp/5w6DnTLy5mISRqaoKWmrQQjc8egjzPW1r4td
-CXdt/SyGkuWPCU3c7J4DAB582t6Kg2Ltp4VM8AY9NUGy8vFJG6VFr2rDjsvOIx/6
-UZSni83ZPqBcLhdLifCkJzRmbOxESnd1YNKGBj1OlDbpytu3y+oBgRC1SoXAuLAE
-YZgJsEYiY8O99D5Wq+Icp2qYxY5ieCQIk5dabNCfVJwfX5gSyWpI0ra7OFmsO5vH
-WXrCHUgH5JFxWWPhjq+Wn6pF7qut+CvVr3nRek174lqgq+DAwFap6hn/NywD19Bp
-B4ypqGqwW1y9YAshp4tpp2kkeSBKw/ISvqN0YfLb4nZ6vy/Y+u3BRwAMCKnFd7X3
-SZKKtBYZewb6oyChE0OJUg==
+MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQI6zyhjDZlpjsCAggA
+MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECKlIS+BRd8lLBIIEyCwK12KwvZLZ
+v0G+K0yv6s3h45NNywn2Jn8e8GxSMbsGvUswNlNIzYbloibVnu7KpdZ58D4upbTu
+dJCrxCtvfP44h7aYswgVk7+thutpAl9roeDWe9e3C+iQMA4UHiIiSmSNe5KrLmu2
+DMezpSyQjqX+OJPpL/3Yiwd45Ae4Okd/c6DqnFEMWFdBqWt0Ft8+HOWELTQyQgYs
+8cma4rqDqtX5QBZ4QBPm8hOp7+LhHITV1qpyaa/nnQQfZx/e1Cyq/h/hcnkbrwuE
+I26s7hcpCaFXN7mSt7GJcZAt5oBqzmDw735iM+FlShokdBsYJEQqWaOVfuzeQYYx
+xt0fz8CReOskIg06jJMXyiWPauutHpiNmQTdcFAE9oO2pUJQCZ3ytaSYG3oP0Byb
+QgEyxhiw6mKv64ZtiAeHPBv7nBl/UPlOSNrXQ+QIyimohdQ+QFeay0eSPgnBwC/H
+MnRaKG6341j5Tk3Itl/5cB6b9VZxvaDgvQNmRNf82EtqCj3YDx7cJF19C7Ut1M0W
+mGLYkudLXne+pLkCWuhKWKEjDp+uDQHF7Zq2q3+l1Wk4DROCtEIO3ruOBLYgNUQf
+flEA6FCw94YlrGKzjRzusXGvBriSrcwlvIc/d55goTZWIZiztPz9c0O93Qg2vYiC
+eJU7D/73byozX0hYOL6d6gWPq4yvbtV/IAZzr+7JuT4j+MVcRkm7lbFhqge/RSbf
+q2iwOOKLs3bpNlMI8S2jtBxPqZ5U/B/eI5slap8Z3xbMuqVAJr4vW4kDGC2WCDFG
+3PXtJvfk4+slbU6cNSzHVk88cS73fRzB4IYyU/txNicyEL0R2iHm7scYKRFJqcKX
+OnDqy4oc5afdv1jfmjb6hA2Xx6T5rC8FMcHBx0M6gi9Y6A/7OadHcRyZySG3F7Xq
++3eub3bwrLwOBEnpm4nl0ucU19WS8kI64gvZbDoQf9kxvOHHFZmjYC0KPFruEWG2
+jFq6xINzA9oTCsR7KWsn+/q3zu5yic9lHtQFN2WnzDzuDoZaVvLY/xqq61ZfROHT
+Q14CfWQMXHwXOn/k9knkm2pNzjti07b+v/X2Wb3eYp85ysn+/jT6ubq4qCtXwHRU
+++IZFpeL3xiuW6uyv+d1Am7Jt/m1JR743WFEOcLV3DZYikbzqG0Y2rWN0L95uhUm
+eCxGLhPoj+j32dSgLhyK/R2n/ka2Ggp+YD+BAyctNUdpVVoqp4IOdCurPBNzNjAv
+Z1qf2SJPKtIk4072VhyuOVUrz8eEQP5+gTUTMNMxFu001EVPrLtAH15KqBay2WAg
+7tdiBZhvXZuICODwMHl8T+hOfLKYGRvxzsjhLU9Ja2b/0jyblt+9pGIwR4RcOBnO
+iZTjKeUlq0R+5P5juqiOSEsB1gazaqu8t/xPzILAxBKz2PypeiVgDLxoRZaa2jGZ
+4SAbE53d58NteP6N0wNPtMix0n2JfH1iwdghHXPF+BS+OHjl+4SriJJw+ylmIpjW
+Sj5u5vQFyl+vnxCiAvo0396MsNsuvIgw8LIcDCI+xgtziYhXapi7vz+U0v2MnglG
+GIVsfsJpMV92B7ch9OodKzitrBZxMRhnKOGekNkjJaGK/iBiRFbDCfnVqWK0Qete
+hPlZzINynSbHPifLVeyfZg==
 -----END ENCRYPTED PRIVATE KEY-----
diff --git a/third_party/wpt_tools/wpt/tools/certs/cacert.pem b/third_party/wpt_tools/wpt/tools/certs/cacert.pem
index 35bdc180..101ed617 100644
--- a/third_party/wpt_tools/wpt/tools/certs/cacert.pem
+++ b/third_party/wpt_tools/wpt/tools/certs/cacert.pem
@@ -1,347 +1,125 @@
 -----BEGIN CERTIFICATE-----
-MIJAhzCCP2+gAwIBAgIDCu6TMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEndl
-Yi1wbGF0Zm9ybS10ZXN0czAeFw0yMTEwMTIwMDQzMzJaFw0yMjEwMTIwMDQzMzJa
+MIIW5zCCFc+gAwIBAgIDCrFbMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEndl
+Yi1wbGF0Zm9ybS10ZXN0czAeFw0yMjA3MTIxMjQ1MTdaFw0yMzA3MTIxMjQ1MTda
 MB0xGzAZBgNVBAMMEndlYi1wbGF0Zm9ybS10ZXN0czCCASIwDQYJKoZIhvcNAQEB
-BQADggEPADCCAQoCggEBANPZQxXPz7FgUF81Pb+ElCkDalX46VSE2l9wagadk6+j
-O9QqWYkEwd/II7p4qLXANlUOMmfDvdmmYR2+96mB/J74eMaqFtHGVboE2eCyRUS3
-XHuCW+evA3vZ0nzFxmty4oJG3gY7VxFO9gdJJh7UgFYmpNU6IWeVHyAdMBbVO2vo
-WuTfitRAyt9FPwgmUjbxYhhcyHrXpuZaJUGzNRnEyH2OpjLdbGD4+Nvd5xaeaMki
-HKT5+qBrKBCsv/krKqH9+h5nYup5dG1d9fKhf4Gjgx3E+d4D9Bebp88zlZnrBGi8
-PzkSUpKWwDOHktxlh1aznqXVdnzydedAcmnsTuZ8YYcCAwEAAaOCPc4wgj3KMAwG
-A1UdEwQFMAMBAf8wHQYDVR0OBBYEFP8Ej6Ego770wNbDvyAhm5B9asPMMEcGA1Ud
-IwRAMD6AFP8Ej6Ego770wNbDvyAhm5B9asPMoSGkHzAdMRswGQYDVQQDDBJ3ZWIt
-cGxhdGZvcm0tdGVzdHOCAwrukzALBgNVHQ8EBAMCAgQwgh+bBgNVHR4Egh+SMIIf
-jqCCH4owE4IRd2ViLXBsYXRmb3JtLnRlc3QwF4IVb3A3LndlYi1wbGF0Zm9ybS50
-ZXN0MBeCFW9wNi53ZWItcGxhdGZvcm0udGVzdDAXghVvcDEud2ViLXBsYXRmb3Jt
-LnRlc3QwF4IVb3A1LndlYi1wbGF0Zm9ybS50ZXN0MBeCFXd3dy53ZWItcGxhdGZv
-cm0udGVzdDAXghVvcDkud2ViLXBsYXRmb3JtLnRlc3QwF4IVb3A4LndlYi1wbGF0
-Zm9ybS50ZXN0MBeCFW5vdC13ZWItcGxhdGZvcm0udGVzdDAXghVvcDQud2ViLXBs
-YXRmb3JtLnRlc3QwF4IVb3AzLndlYi1wbGF0Zm9ybS50ZXN0MBeCFW9wMi53ZWIt
-cGxhdGZvcm0udGVzdDAYghZvcDYxLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNjMu
-d2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AzMC53ZWItcGxhdGZvcm0udGVzdDAYghZv
-cDc0LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNzMud2ViLXBsYXRmb3JtLnRlc3Qw
-GIIWb3A0Ni53ZWItcGxhdGZvcm0udGVzdDAYghZvcDM0LndlYi1wbGF0Zm9ybS50
-ZXN0MBiCFm9wODkud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AzMS53ZWItcGxhdGZv
-cm0udGVzdDAYghZvcDM2LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wOTkud2ViLXBs
-YXRmb3JtLnRlc3QwGIIWb3AxMy53ZWItcGxhdGZvcm0udGVzdDAYghZ3d3cxLndl
-Yi1wbGF0Zm9ybS50ZXN0MBiCFnd3dzIud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3Ax
-NS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDg3LndlYi1wbGF0Zm9ybS50ZXN0MBiC
-Fm9wMTYud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A5Ni53ZWItcGxhdGZvcm0udGVz
-dDAYghZvcDIxLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMTIud2ViLXBsYXRmb3Jt
-LnRlc3QwGIIWb3A5My53ZWItcGxhdGZvcm0udGVzdDAYghZvcDkxLndlYi1wbGF0
-Zm9ybS50ZXN0MBiCFm9wNTMud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AyNC53ZWIt
-cGxhdGZvcm0udGVzdDAYghZvcDQ1LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMzIu
-d2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A0OC53ZWItcGxhdGZvcm0udGVzdDAYghZv
-cDU2LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNzkud2ViLXBsYXRmb3JtLnRlc3Qw
-GIIWb3A5MC53ZWItcGxhdGZvcm0udGVzdDAYghZvcDE3LndlYi1wbGF0Zm9ybS50
-ZXN0MBiCFm9wNjIud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A1MS53ZWItcGxhdGZv
-cm0udGVzdDAYghZvcDQxLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNzgud2ViLXBs
-YXRmb3JtLnRlc3QwGIIWb3AzNy53ZWItcGxhdGZvcm0udGVzdDAYghZvcDE4Lndl
-Yi1wbGF0Zm9ybS50ZXN0MBiCFm9wNjkud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A2
-NC53ZWItcGxhdGZvcm0udGVzdDAYghZvcDM5LndlYi1wbGF0Zm9ybS50ZXN0MBiC
-Fm9wMzgud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A4NC53ZWItcGxhdGZvcm0udGVz
-dDAYghZvcDIwLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNTgud2ViLXBsYXRmb3Jt
-LnRlc3QwGIIWb3A5OC53ZWItcGxhdGZvcm0udGVzdDAYghZvcDE0LndlYi1wbGF0
-Zm9ybS50ZXN0MBiCFm9wOTQud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AyNy53ZWIt
-cGxhdGZvcm0udGVzdDAYghZvcDI5LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMzUu
-d2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A5Ny53ZWItcGxhdGZvcm0udGVzdDAYghZv
-cDY2LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMjgud2ViLXBsYXRmb3JtLnRlc3Qw
-GIIWb3AxOS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDg4LndlYi1wbGF0Zm9ybS50
-ZXN0MBiCFm9wMTAud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A4Mi53ZWItcGxhdGZv
-cm0udGVzdDAYghZvcDU0LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNjgud2ViLXBs
-YXRmb3JtLnRlc3QwGIIWb3A4Ni53ZWItcGxhdGZvcm0udGVzdDAYghZvcDUwLndl
-Yi1wbGF0Zm9ybS50ZXN0MBiCFm9wNTUud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A0
-MC53ZWItcGxhdGZvcm0udGVzdDAYghZvcDc2LndlYi1wbGF0Zm9ybS50ZXN0MBiC
-Fm9wNzcud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A1Ny53ZWItcGxhdGZvcm0udGVz
-dDAYghZvcDk1LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNzAud2ViLXBsYXRmb3Jt
-LnRlc3QwGIIWb3AxMS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDQ3LndlYi1wbGF0
-Zm9ybS50ZXN0MBiCFm9wMzMud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A2NS53ZWIt
-cGxhdGZvcm0udGVzdDAYghZvcDgwLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMjMu
-d2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A3NS53ZWItcGxhdGZvcm0udGVzdDAYghZv
-cDI2LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNzEud2ViLXBsYXRmb3JtLnRlc3Qw
-GIIWb3A5Mi53ZWItcGxhdGZvcm0udGVzdDAYghZvcDQzLndlYi1wbGF0Zm9ybS50
-ZXN0MBiCFm9wNzIud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AyNS53ZWItcGxhdGZv
-cm0udGVzdDAYghZvcDY3LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNDQud2ViLXBs
-YXRmb3JtLnRlc3QwGIIWb3A4NS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDQ5Lndl
-Yi1wbGF0Zm9ybS50ZXN0MBiCFm9wODEud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A4
-My53ZWItcGxhdGZvcm0udGVzdDAYghZvcDQyLndlYi1wbGF0Zm9ybS50ZXN0MBiC
-Fm9wNTkud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A1Mi53ZWItcGxhdGZvcm0udGVz
-dDAYghZvcDIyLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNjAud2ViLXBsYXRmb3Jt
-LnRlc3QwG4IZb3AyLm5vdC13ZWItcGxhdGZvcm0udGVzdDAbghlvcDEubm90LXdl
-Yi1wbGF0Zm9ybS50ZXN0MBuCGXd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwG4IZ
-b3A4Lm5vdC13ZWItcGxhdGZvcm0udGVzdDAbghlvcDYubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0MBuCGW9wOS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwG4IZb3A1Lm5vdC13
-ZWItcGxhdGZvcm0udGVzdDAbghlvcDMubm90LXdlYi1wbGF0Zm9ybS50ZXN0MBuC
-GW9wNy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwG4IZd3d3Lnd3dy53ZWItcGxhdGZv
-cm0udGVzdDAbghlvcDQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjAubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjAubm90LXdlYi1wbGF0Zm9ybS50ZXN0
-MByCGm9wNTMubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dy53d3cxLndlYi1w
-bGF0Zm9ybS50ZXN0MByCGm9wMzgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
-ODQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wODIubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0MByCGm9wOTkubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjUubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjcubm90LXdlYi1wbGF0Zm9ybS50ZXN0
-MByCGm9wNzgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dy53d3cyLndlYi1w
-bGF0Zm9ybS50ZXN0MByCGm9wMTgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
-NDgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjkubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0MByCGm9wMzQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNzYubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMzAubm90LXdlYi1wbGF0Zm9ybS50ZXN0
-MByCGm9wOTQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTQubm90LXdlYi1w
-bGF0Zm9ybS50ZXN0MByCGm9wNjgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
-NzAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNzcubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0MByCGm9wOTAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wODAubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTYubm90LXdlYi1wbGF0Zm9ybS50ZXN0
-MByCGm9wNDUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNzEubm90LXdlYi1w
-bGF0Zm9ybS50ZXN0MByCGm9wNDIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
-OTEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTYubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0MByCGm9wMjQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dzIud3d3
-LndlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDMubm90LXdlYi1wbGF0Zm9ybS50ZXN0
-MByCGm9wNzQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTEubm90LXdlYi1w
-bGF0Zm9ybS50ZXN0MByCGm9wMzYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
-Nzkubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wODEubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0MByCGm9wOTUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjcubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTIubm90LXdlYi1wbGF0Zm9ybS50ZXN0
-MByCGm9wNDYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDAubm90LXdlYi1w
-bGF0Zm9ybS50ZXN0MByCGm9wMzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
-NTAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wODkubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0MByCGm9wMTkubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTIubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTAubm90LXdlYi1wbGF0Zm9ybS50ZXN0
-MByCGm9wNzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTYubm90LXdlYi1w
-bGF0Zm9ybS50ZXN0MByCGm9wMTEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
-OTMubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTcubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0MByCGm9wNzUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTcubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNzMubm90LXdlYi1wbGF0Zm9ybS50ZXN0
-MByCGm9wOTcubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjQubm90LXdlYi1w
-bGF0Zm9ybS50ZXN0MByCGm9wMzUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
-NjMubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDcubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0MByCGm9wMjUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMzEubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wODgubm90LXdlYi1wbGF0Zm9ybS50ZXN0
-MByCGnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjYubm90LXdlYi1w
-bGF0Zm9ybS50ZXN0MByCGm9wNDQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
-ODUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wODcubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0MByCGm9wODYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMzcubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dzEud3d3LndlYi1wbGF0Zm9ybS50ZXN0
-MByCGm9wMjEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMzkubm90LXdlYi1w
-bGF0Zm9ybS50ZXN0MByCGnd3dzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
-MzMubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTkubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0MByCGm9wNTIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTMubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjYubm90LXdlYi1wbGF0Zm9ybS50ZXN0
-MByCGm9wMTUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjgubm90LXdlYi1w
-bGF0Zm9ybS50ZXN0MByCGm9wNjIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
-NTgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wODMubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0MByCGm9wNTUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjkubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjEubm90LXdlYi1wbGF0Zm9ybS50ZXN0
-MByCGm9wNDEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDkubm90LXdlYi1w
-bGF0Zm9ybS50ZXN0MByCGm9wMTQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
-MjMubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjIubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0MByCGm9wOTgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MB2CG3d3dzEud3d3
-Mi53ZWItcGxhdGZvcm0udGVzdDAdght3d3cyLnd3dzEud2ViLXBsYXRmb3JtLnRl
-c3QwHYIbd3d3MS53d3cxLndlYi1wbGF0Zm9ybS50ZXN0MB2CG3d3dzIud3d3Mi53
-ZWItcGxhdGZvcm0udGVzdDAfgh13d3cud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVz
-dDAggh53d3cxLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwIIIed3d3Lnd3dzIu
-bm90LXdlYi1wbGF0Zm9ybS50ZXN0MCCCHnd3dzIud3d3Lm5vdC13ZWItcGxhdGZv
-cm0udGVzdDAggh54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3QwIIIed3d3
-Lnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MCGCH3d3dzEud3d3MS5ub3Qtd2Vi
-LXBsYXRmb3JtLnRlc3QwIYIfd3d3Mi53d3cyLm5vdC13ZWItcGxhdGZvcm0udGVz
-dDAhgh93d3cxLnd3dzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MCGCH3d3dzIud3d3
-MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwJIIieG4tLWx2ZS02bGFkLm5vdC13ZWIt
-cGxhdGZvcm0udGVzdDAkgiJ3d3cueG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50
-ZXN0MCSCInhuLS1sdmUtNmxhZC53d3cud2ViLXBsYXRmb3JtLnRlc3QwJYIjeG4t
-LWx2ZS02bGFkLnd3dzEud2ViLXBsYXRmb3JtLnRlc3QwJYIjd3d3MS54bi0tbHZl
-LTZsYWQud2ViLXBsYXRmb3JtLnRlc3QwJYIjd3d3Mi54bi0tbHZlLTZsYWQud2Vi
-LXBsYXRmb3JtLnRlc3QwJYIjeG4tLWx2ZS02bGFkLnd3dzIud2ViLXBsYXRmb3Jt
-LnRlc3QwKIImeG4tLWx2ZS02bGFkLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3Qw
-KIImd3d3LnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwKYInd3d3
-Mi54bi0tbHZlLTZsYWQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MCmCJ3huLS1sdmUt
-NmxhZC53d3cyLm5vdC13ZWItcGxhdGZvcm0udGVzdDApgid3d3cxLnhuLS1sdmUt
-NmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwKYIneG4tLWx2ZS02bGFkLnd3dzEu
-bm90LXdlYi1wbGF0Zm9ybS50ZXN0MCuCKXhuLS1uOGo2ZHM1M2x3d2tycWh2Mjhh
-LndlYi1wbGF0Zm9ybS50ZXN0MC2CK3huLS1sdmUtNmxhZC54bi0tbHZlLTZsYWQu
-d2ViLXBsYXRmb3JtLnRlc3QwL4Itd3d3LnhuLS1uOGo2ZHM1M2x3d2tycWh2Mjhh
-LndlYi1wbGF0Zm9ybS50ZXN0MC+CLXhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLm5v
-dC13ZWItcGxhdGZvcm0udGVzdDAvgi14bi0tbjhqNmRzNTNsd3drcnFodjI4YS53
-d3cud2ViLXBsYXRmb3JtLnRlc3QwMIIud3d3Mi54bi0tbjhqNmRzNTNsd3drcnFo
-djI4YS53ZWItcGxhdGZvcm0udGVzdDAwgi54bi0tbjhqNmRzNTNsd3drcnFodjI4
-YS53d3cyLndlYi1wbGF0Zm9ybS50ZXN0MDCCLnd3dzEueG4tLW44ajZkczUzbHd3
-a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3QwMIIueG4tLW44ajZkczUzbHd3a3Jx
-aHYyOGEud3d3MS53ZWItcGxhdGZvcm0udGVzdDAxgi94bi0tbHZlLTZsYWQueG4t
-LWx2ZS02bGFkLm5vdC13ZWItcGxhdGZvcm0udGVzdDAzgjF3d3cueG4tLW44ajZk
-czUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MDOCMXhuLS1uOGo2
-ZHM1M2x3d2tycWh2MjhhLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwNIIyeG4t
+BQADggEPADCCAQoCggEBAOIOEkl98dlmCeI7SCy2wyAALDEblG813gVVErnMjOPl
+o6BpynugeJx7OX85cGJXpn/xiPZi7922W+swGnBCtoe073kMif6WQRylplkJQhqf
+I92IaDecX+f5ROTr7mCcloolt2yRohsAODe1TLZ7VqXouVEMws4+Y5Sp+TMG011Y
+mB+qFEYIjhmvH0w4UoQxz5TBtvj6nkFoRdZRgnLbIkJZ0HVtefy1AhEsOgnz7yba
+pstR97iZTuro0E6hcnMAdEKpXXXSYqV3HYPZzn9YAA8BloAM0GHSS9yWMRoV7UnS
+07YjsorpbE6iQAV/CAWZtBaLmMlNY+cxefEK2NRPqhECAwEAAaOCFC4wghQqMAwG
+A1UdEwQFMAMBAf8wHQYDVR0OBBYEFMo8kufcUDkL5UQ/32+RXOKIKjrWMEcGA1Ud
+IwRAMD6AFMo8kufcUDkL5UQ/32+RXOKIKjrWoSGkHzAdMRswGQYDVQQDDBJ3ZWIt
+cGxhdGZvcm0tdGVzdHOCAwqxWzALBgNVHQ8EBAMCAgQwggoFBgNVHR4Eggn8MIIJ
++KCCCfQwE4IRd2ViLXBsYXRmb3JtLnRlc3QwF4IVd3d3LndlYi1wbGF0Zm9ybS50
+ZXN0MBeCFW5vdC13ZWItcGxhdGZvcm0udGVzdDAYghZ3d3cxLndlYi1wbGF0Zm9y
+bS50ZXN0MBiCFnd3dzIud2ViLXBsYXRmb3JtLnRlc3QwG4IZd3d3Lnd3dy53ZWIt
+cGxhdGZvcm0udGVzdDAbghl3d3cubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3
+dy53d3cyLndlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dy53d3cxLndlYi1wbGF0Zm9y
+bS50ZXN0MByCGnd3dzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dzEud3d3
+LndlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0
+MByCGnd3dzIud3d3LndlYi1wbGF0Zm9ybS50ZXN0MB2CG3d3dzEud3d3MS53ZWIt
+cGxhdGZvcm0udGVzdDAdght3d3cyLnd3dzEud2ViLXBsYXRmb3JtLnRlc3QwHYIb
+d3d3MS53d3cyLndlYi1wbGF0Zm9ybS50ZXN0MB2CG3d3dzIud3d3Mi53ZWItcGxh
+dGZvcm0udGVzdDAfgh13d3cud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVzdDAggh53
+d3cyLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwIIIed3d3Lnd3dzEubm90LXdl
+Yi1wbGF0Zm9ybS50ZXN0MCCCHnd3dzEud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVz
+dDAggh54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3QwIIIed3d3Lnd3dzIu
+bm90LXdlYi1wbGF0Zm9ybS50ZXN0MCGCH3d3dzEud3d3MS5ub3Qtd2ViLXBsYXRm
+b3JtLnRlc3QwIYIfd3d3Mi53d3cyLm5vdC13ZWItcGxhdGZvcm0udGVzdDAhgh93
+d3cyLnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MCGCH3d3dzEud3d3Mi5ub3Qt
+d2ViLXBsYXRmb3JtLnRlc3QwJIIieG4tLWx2ZS02bGFkLm5vdC13ZWItcGxhdGZv
+cm0udGVzdDAkgiJ3d3cueG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0MCSC
+InhuLS1sdmUtNmxhZC53d3cud2ViLXBsYXRmb3JtLnRlc3QwJYIjeG4tLWx2ZS02
+bGFkLnd3dzIud2ViLXBsYXRmb3JtLnRlc3QwJYIjeG4tLWx2ZS02bGFkLnd3dzEu
+d2ViLXBsYXRmb3JtLnRlc3QwJYIjd3d3Mi54bi0tbHZlLTZsYWQud2ViLXBsYXRm
+b3JtLnRlc3QwJYIjd3d3MS54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3Qw
+KIImeG4tLWx2ZS02bGFkLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwKIImd3d3
+LnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwKYIneG4tLWx2ZS02
+bGFkLnd3dzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MCmCJ3huLS1sdmUtNmxhZC53
+d3cxLm5vdC13ZWItcGxhdGZvcm0udGVzdDApgid3d3cxLnhuLS1sdmUtNmxhZC5u
+b3Qtd2ViLXBsYXRmb3JtLnRlc3QwKYInd3d3Mi54bi0tbHZlLTZsYWQubm90LXdl
+Yi1wbGF0Zm9ybS50ZXN0MCuCKXhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLndlYi1w
+bGF0Zm9ybS50ZXN0MC2CK3huLS1sdmUtNmxhZC54bi0tbHZlLTZsYWQud2ViLXBs
+YXRmb3JtLnRlc3QwL4IteG4tLW44ajZkczUzbHd3a3JxaHYyOGEud3d3LndlYi1w
+bGF0Zm9ybS50ZXN0MC+CLXd3dy54bi0tbjhqNmRzNTNsd3drcnFodjI4YS53ZWIt
+cGxhdGZvcm0udGVzdDAvgi14bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2Vi
+LXBsYXRmb3JtLnRlc3QwMIIud3d3Mi54bi0tbjhqNmRzNTNsd3drcnFodjI4YS53
+ZWItcGxhdGZvcm0udGVzdDAwgi54bi0tbjhqNmRzNTNsd3drcnFodjI4YS53d3cx
+LndlYi1wbGF0Zm9ybS50ZXN0MDCCLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3
+dzIud2ViLXBsYXRmb3JtLnRlc3QwMIIud3d3MS54bi0tbjhqNmRzNTNsd3drcnFo
+djI4YS53ZWItcGxhdGZvcm0udGVzdDAxgi94bi0tbHZlLTZsYWQueG4tLWx2ZS02
+bGFkLm5vdC13ZWItcGxhdGZvcm0udGVzdDAzgjF4bi0tbjhqNmRzNTNsd3drcnFo
+djI4YS53d3cubm90LXdlYi1wbGF0Zm9ybS50ZXN0MDOCMXd3dy54bi0tbjhqNmRz
+NTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwNIIyeG4tLW44ajZk
+czUzbHd3a3JxaHYyOGEud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwNIIyeG4t
 LW44ajZkczUzbHd3a3JxaHYyOGEud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3Qw
 NIIyd3d3Mi54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3Jt
-LnRlc3QwNIIyeG4tLW44ajZkczUzbHd3a3JxaHYyOGEud3d3Mi5ub3Qtd2ViLXBs
-YXRmb3JtLnRlc3QwNIIyd3d3MS54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qt
-d2ViLXBsYXRmb3JtLnRlc3QwOII2eG4tLW44ajZkczUzbHd3a3JxaHYyOGEueG4t
-LWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0MDiCNnhuLS1sdmUtNmxhZC54bi0t
-bjhqNmRzNTNsd3drcnFodjI4YS53ZWItcGxhdGZvcm0udGVzdDA8gjp4bi0tbjhq
-NmRzNTNsd3drcnFodjI4YS54bi0tbHZlLTZsYWQubm90LXdlYi1wbGF0Zm9ybS50
-ZXN0MDyCOnhuLS1sdmUtNmxhZC54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qt
-d2ViLXBsYXRmb3JtLnRlc3QwQ4JBeG4tLW44ajZkczUzbHd3a3JxaHYyOGEueG4t
-LW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3QwR4JFeG4tLW44
-ajZkczUzbHd3a3JxaHYyOGEueG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90LXdl
-Yi1wbGF0Zm9ybS50ZXN0MBMGA1UdJQQMMAoGCCsGAQUFBwMBMIIdjwYDVR0RBIId
-hjCCHYKCEXdlYi1wbGF0Zm9ybS50ZXN0ghVvcDcud2ViLXBsYXRmb3JtLnRlc3SC
-FW9wNi53ZWItcGxhdGZvcm0udGVzdIIVb3AxLndlYi1wbGF0Zm9ybS50ZXN0ghVv
-cDUud2ViLXBsYXRmb3JtLnRlc3SCFXd3dy53ZWItcGxhdGZvcm0udGVzdIIVb3A5
-LndlYi1wbGF0Zm9ybS50ZXN0ghVvcDgud2ViLXBsYXRmb3JtLnRlc3SCFW5vdC13
-ZWItcGxhdGZvcm0udGVzdIIVb3A0LndlYi1wbGF0Zm9ybS50ZXN0ghVvcDMud2Vi
-LXBsYXRmb3JtLnRlc3SCFW9wMi53ZWItcGxhdGZvcm0udGVzdIIWb3A2MS53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A2My53ZWItcGxhdGZvcm0udGVzdIIWb3AzMC53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A3NC53ZWItcGxhdGZvcm0udGVzdIIWb3A3My53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A0Ni53ZWItcGxhdGZvcm0udGVzdIIWb3AzNC53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A4OS53ZWItcGxhdGZvcm0udGVzdIIWb3AzMS53ZWIt
-cGxhdGZvcm0udGVzdIIWb3AzNi53ZWItcGxhdGZvcm0udGVzdIIWb3A5OS53ZWIt
-cGxhdGZvcm0udGVzdIIWb3AxMy53ZWItcGxhdGZvcm0udGVzdIIWd3d3MS53ZWIt
-cGxhdGZvcm0udGVzdIIWd3d3Mi53ZWItcGxhdGZvcm0udGVzdIIWb3AxNS53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A4Ny53ZWItcGxhdGZvcm0udGVzdIIWb3AxNi53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A5Ni53ZWItcGxhdGZvcm0udGVzdIIWb3AyMS53ZWIt
-cGxhdGZvcm0udGVzdIIWb3AxMi53ZWItcGxhdGZvcm0udGVzdIIWb3A5My53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A5MS53ZWItcGxhdGZvcm0udGVzdIIWb3A1My53ZWIt
-cGxhdGZvcm0udGVzdIIWb3AyNC53ZWItcGxhdGZvcm0udGVzdIIWb3A0NS53ZWIt
-cGxhdGZvcm0udGVzdIIWb3AzMi53ZWItcGxhdGZvcm0udGVzdIIWb3A0OC53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A1Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A3OS53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A5MC53ZWItcGxhdGZvcm0udGVzdIIWb3AxNy53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A2Mi53ZWItcGxhdGZvcm0udGVzdIIWb3A1MS53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A0MS53ZWItcGxhdGZvcm0udGVzdIIWb3A3OC53ZWIt
-cGxhdGZvcm0udGVzdIIWb3AzNy53ZWItcGxhdGZvcm0udGVzdIIWb3AxOC53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A2OS53ZWItcGxhdGZvcm0udGVzdIIWb3A2NC53ZWIt
-cGxhdGZvcm0udGVzdIIWb3AzOS53ZWItcGxhdGZvcm0udGVzdIIWb3AzOC53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A4NC53ZWItcGxhdGZvcm0udGVzdIIWb3AyMC53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A1OC53ZWItcGxhdGZvcm0udGVzdIIWb3A5OC53ZWIt
-cGxhdGZvcm0udGVzdIIWb3AxNC53ZWItcGxhdGZvcm0udGVzdIIWb3A5NC53ZWIt
-cGxhdGZvcm0udGVzdIIWb3AyNy53ZWItcGxhdGZvcm0udGVzdIIWb3AyOS53ZWIt
-cGxhdGZvcm0udGVzdIIWb3AzNS53ZWItcGxhdGZvcm0udGVzdIIWb3A5Ny53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A2Ni53ZWItcGxhdGZvcm0udGVzdIIWb3AyOC53ZWIt
-cGxhdGZvcm0udGVzdIIWb3AxOS53ZWItcGxhdGZvcm0udGVzdIIWb3A4OC53ZWIt
-cGxhdGZvcm0udGVzdIIWb3AxMC53ZWItcGxhdGZvcm0udGVzdIIWb3A4Mi53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A1NC53ZWItcGxhdGZvcm0udGVzdIIWb3A2OC53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A4Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A1MC53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A1NS53ZWItcGxhdGZvcm0udGVzdIIWb3A0MC53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A3Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A3Ny53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A1Ny53ZWItcGxhdGZvcm0udGVzdIIWb3A5NS53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A3MC53ZWItcGxhdGZvcm0udGVzdIIWb3AxMS53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A0Ny53ZWItcGxhdGZvcm0udGVzdIIWb3AzMy53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A2NS53ZWItcGxhdGZvcm0udGVzdIIWb3A4MC53ZWIt
-cGxhdGZvcm0udGVzdIIWb3AyMy53ZWItcGxhdGZvcm0udGVzdIIWb3A3NS53ZWIt
-cGxhdGZvcm0udGVzdIIWb3AyNi53ZWItcGxhdGZvcm0udGVzdIIWb3A3MS53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A5Mi53ZWItcGxhdGZvcm0udGVzdIIWb3A0My53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A3Mi53ZWItcGxhdGZvcm0udGVzdIIWb3AyNS53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A2Ny53ZWItcGxhdGZvcm0udGVzdIIWb3A0NC53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A4NS53ZWItcGxhdGZvcm0udGVzdIIWb3A0OS53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A4MS53ZWItcGxhdGZvcm0udGVzdIIWb3A4My53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A0Mi53ZWItcGxhdGZvcm0udGVzdIIWb3A1OS53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A1Mi53ZWItcGxhdGZvcm0udGVzdIIWb3AyMi53ZWIt
-cGxhdGZvcm0udGVzdIIWb3A2MC53ZWItcGxhdGZvcm0udGVzdIIZb3AyLm5vdC13
-ZWItcGxhdGZvcm0udGVzdIIZb3AxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIZd3d3
-Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A4Lm5vdC13ZWItcGxhdGZvcm0udGVz
-dIIZb3A2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A5Lm5vdC13ZWItcGxhdGZv
-cm0udGVzdIIZb3A1Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3AzLm5vdC13ZWIt
-cGxhdGZvcm0udGVzdIIZb3A3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZd3d3Lnd3
-dy53ZWItcGxhdGZvcm0udGVzdIIZb3A0Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIa
-b3A2MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMjAubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0ghpvcDUzLm5vdC13ZWItcGxhdGZvcm0udGVzdIIad3d3Lnd3dzEud2Vi
-LXBsYXRmb3JtLnRlc3SCGm9wMzgubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDg0
-Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A4Mi5ub3Qtd2ViLXBsYXRmb3JtLnRl
-c3SCGm9wOTkubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDY1Lm5vdC13ZWItcGxh
-dGZvcm0udGVzdIIab3A2Ny5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNzgubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0ghp3d3cud3d3Mi53ZWItcGxhdGZvcm0udGVzdIIa
-b3AxOC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNDgubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0ghpvcDY5Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AzNC5ub3Qtd2Vi
-LXBsYXRmb3JtLnRlc3SCGm9wNzYubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDMw
-Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5NC5ub3Qtd2ViLXBsYXRmb3JtLnRl
-c3SCGm9wNTQubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDY4Lm5vdC13ZWItcGxh
-dGZvcm0udGVzdIIab3A3MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNzcubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDkwLm5vdC13ZWItcGxhdGZvcm0udGVzdIIa
-b3A4MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMTYubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0ghpvcDQ1Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A3MS5ub3Qtd2Vi
-LXBsYXRmb3JtLnRlc3SCGm9wNDIubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDkx
-Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A1Ni5ub3Qtd2ViLXBsYXRmb3JtLnRl
-c3SCGm9wMjQubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghp3d3cyLnd3dy53ZWItcGxh
-dGZvcm0udGVzdIIab3A0My5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNzQubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDUxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIa
-b3AzNi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNzkubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0ghpvcDgxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5NS5ub3Qtd2Vi
-LXBsYXRmb3JtLnRlc3SCGm9wMjcubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDEy
-Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A0Ni5ub3Qtd2ViLXBsYXRmb3JtLnRl
-c3SCGm9wNDAubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDMyLm5vdC13ZWItcGxh
-dGZvcm0udGVzdIIab3A1MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wODkubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDE5Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIa
-b3A5Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMTAubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0ghpvcDcyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5Ni5ub3Qtd2Vi
-LXBsYXRmb3JtLnRlc3SCGm9wMTEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDkz
-Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AxNy5ub3Qtd2ViLXBsYXRmb3JtLnRl
-c3SCGm9wNzUubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDU3Lm5vdC13ZWItcGxh
-dGZvcm0udGVzdIIab3A3My5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wOTcubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDY0Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIa
-b3AzNS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNjMubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0ghpvcDQ3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AyNS5ub3Qtd2Vi
-LXBsYXRmb3JtLnRlc3SCGm9wMzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDg4
-Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIad3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRl
-c3SCGm9wMjYubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQ0Lm5vdC13ZWItcGxh
-dGZvcm0udGVzdIIab3A4NS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wODcubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDg2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIa
-b3AzNy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGnd3dzEud3d3LndlYi1wbGF0Zm9y
-bS50ZXN0ghpvcDIxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AzOS5ub3Qtd2Vi
-LXBsYXRmb3JtLnRlc3SCGnd3dzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDMz
-Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A1OS5ub3Qtd2ViLXBsYXRmb3JtLnRl
-c3SCGm9wNTIubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDEzLm5vdC13ZWItcGxh
-dGZvcm0udGVzdIIab3A2Ni5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMTUubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDI4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIa
-b3A2Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNTgubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0ghpvcDgzLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A1NS5ub3Qtd2Vi
-LXBsYXRmb3JtLnRlc3SCGm9wMjkubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDYx
-Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A0MS5ub3Qtd2ViLXBsYXRmb3JtLnRl
-c3SCGm9wNDkubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDE0Lm5vdC13ZWItcGxh
-dGZvcm0udGVzdIIab3AyMy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMjIubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDk4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIb
-d3d3MS53d3cyLndlYi1wbGF0Zm9ybS50ZXN0ght3d3cyLnd3dzEud2ViLXBsYXRm
-b3JtLnRlc3SCG3d3dzEud3d3MS53ZWItcGxhdGZvcm0udGVzdIIbd3d3Mi53d3cy
+LnRlc3QwNIIyd3d3MS54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBs
+YXRmb3JtLnRlc3QwOII2eG4tLWx2ZS02bGFkLnhuLS1uOGo2ZHM1M2x3d2tycWh2
+MjhhLndlYi1wbGF0Zm9ybS50ZXN0MDiCNnhuLS1uOGo2ZHM1M2x3d2tycWh2Mjhh
+LnhuLS1sdmUtNmxhZC53ZWItcGxhdGZvcm0udGVzdDA8gjp4bi0tbjhqNmRzNTNs
+d3drcnFodjI4YS54bi0tbHZlLTZsYWQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MDyC
+OnhuLS1sdmUtNmxhZC54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBs
+YXRmb3JtLnRlc3QwQ4JBeG4tLW44ajZkczUzbHd3a3JxaHYyOGEueG4tLW44ajZk
+czUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3QwR4JFeG4tLW44ajZkczUz
+bHd3a3JxaHYyOGEueG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0
+Zm9ybS50ZXN0MBMGA1UdJQQMMAoGCCsGAQUFBwMBMIIJhQYDVR0RBIIJfDCCCXiC
+EXdlYi1wbGF0Zm9ybS50ZXN0ghV3d3cud2ViLXBsYXRmb3JtLnRlc3SCFW5vdC13
+ZWItcGxhdGZvcm0udGVzdIIWd3d3MS53ZWItcGxhdGZvcm0udGVzdIIWd3d3Mi53
+ZWItcGxhdGZvcm0udGVzdIIZd3d3Lnd3dy53ZWItcGxhdGZvcm0udGVzdIIZd3d3
+Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIad3d3Lnd3dzIud2ViLXBsYXRmb3JtLnRl
+c3SCGnd3dy53d3cxLndlYi1wbGF0Zm9ybS50ZXN0ghp3d3cyLm5vdC13ZWItcGxh
+dGZvcm0udGVzdIIad3d3MS53d3cud2ViLXBsYXRmb3JtLnRlc3SCGnd3dzEubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0ghp3d3cyLnd3dy53ZWItcGxhdGZvcm0udGVzdIIb
+d3d3MS53d3cxLndlYi1wbGF0Zm9ybS50ZXN0ght3d3cyLnd3dzEud2ViLXBsYXRm
+b3JtLnRlc3SCG3d3dzEud3d3Mi53ZWItcGxhdGZvcm0udGVzdIIbd3d3Mi53d3cy
 LndlYi1wbGF0Zm9ybS50ZXN0gh13d3cud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVz
-dIIed3d3MS53d3cubm90LXdlYi1wbGF0Zm9ybS50ZXN0gh53d3cud3d3Mi5ub3Qt
-d2ViLXBsYXRmb3JtLnRlc3SCHnd3dzIud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVz
-dIIeeG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0gh53d3cud3d3MS5ub3Qt
+dIIed3d3Mi53d3cubm90LXdlYi1wbGF0Zm9ybS50ZXN0gh53d3cud3d3MS5ub3Qt
+d2ViLXBsYXRmb3JtLnRlc3SCHnd3dzEud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVz
+dIIeeG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0gh53d3cud3d3Mi5ub3Qt
 d2ViLXBsYXRmb3JtLnRlc3SCH3d3dzEud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRl
-c3SCH3d3dzIud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzEud3d3Mi5u
-b3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzIud3d3MS5ub3Qtd2ViLXBsYXRmb3Jt
+c3SCH3d3dzIud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzIud3d3MS5u
+b3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzEud3d3Mi5ub3Qtd2ViLXBsYXRmb3Jt
 LnRlc3SCInhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCInd3dy54
 bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3SCInhuLS1sdmUtNmxhZC53d3cu
-d2ViLXBsYXRmb3JtLnRlc3SCI3huLS1sdmUtNmxhZC53d3cxLndlYi1wbGF0Zm9y
-bS50ZXN0giN3d3cxLnhuLS1sdmUtNmxhZC53ZWItcGxhdGZvcm0udGVzdIIjd3d3
-Mi54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3SCI3huLS1sdmUtNmxhZC53
-d3cyLndlYi1wbGF0Zm9ybS50ZXN0giZ4bi0tbHZlLTZsYWQud3d3Lm5vdC13ZWIt
+d2ViLXBsYXRmb3JtLnRlc3SCI3huLS1sdmUtNmxhZC53d3cyLndlYi1wbGF0Zm9y
+bS50ZXN0giN4bi0tbHZlLTZsYWQud3d3MS53ZWItcGxhdGZvcm0udGVzdIIjd3d3
+Mi54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3SCI3d3dzEueG4tLWx2ZS02
+bGFkLndlYi1wbGF0Zm9ybS50ZXN0giZ4bi0tbHZlLTZsYWQud3d3Lm5vdC13ZWIt
 cGxhdGZvcm0udGVzdIImd3d3LnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3Jt
-LnRlc3SCJ3d3dzIueG4tLWx2ZS02bGFkLm5vdC13ZWItcGxhdGZvcm0udGVzdIIn
-eG4tLWx2ZS02bGFkLnd3dzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0gid3d3cxLnhu
-LS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCJ3huLS1sdmUtNmxhZC53
-d3cxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIpeG4tLW44ajZkczUzbHd3a3JxaHYy
+LnRlc3SCJ3huLS1sdmUtNmxhZC53d3cyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIn
+eG4tLWx2ZS02bGFkLnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0gid3d3cxLnhu
+LS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCJ3d3dzIueG4tLWx2ZS02
+bGFkLm5vdC13ZWItcGxhdGZvcm0udGVzdIIpeG4tLW44ajZkczUzbHd3a3JxaHYy
 OGEud2ViLXBsYXRmb3JtLnRlc3SCK3huLS1sdmUtNmxhZC54bi0tbHZlLTZsYWQu
-d2ViLXBsYXRmb3JtLnRlc3SCLXd3dy54bi0tbjhqNmRzNTNsd3drcnFodjI4YS53
-ZWItcGxhdGZvcm0udGVzdIIteG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90LXdl
-Yi1wbGF0Zm9ybS50ZXN0gi14bi0tbjhqNmRzNTNsd3drcnFodjI4YS53d3cud2Vi
+d2ViLXBsYXRmb3JtLnRlc3SCLXhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3dy53
+ZWItcGxhdGZvcm0udGVzdIItd3d3LnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLndl
+Yi1wbGF0Zm9ybS50ZXN0gi14bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2Vi
 LXBsYXRmb3JtLnRlc3SCLnd3dzIueG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2Vi
+LXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3dzEud2Vi
 LXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3dzIud2Vi
 LXBsYXRmb3JtLnRlc3SCLnd3dzEueG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2Vi
-LXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3dzEud2Vi
 LXBsYXRmb3JtLnRlc3SCL3huLS1sdmUtNmxhZC54bi0tbHZlLTZsYWQubm90LXdl
-Yi1wbGF0Zm9ybS50ZXN0gjF3d3cueG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90
-LXdlYi1wbGF0Zm9ybS50ZXN0gjF4bi0tbjhqNmRzNTNsd3drcnFodjI4YS53d3cu
+Yi1wbGF0Zm9ybS50ZXN0gjF4bi0tbjhqNmRzNTNsd3drcnFodjI4YS53d3cubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0gjF3d3cueG4tLW44ajZkczUzbHd3a3JxaHYyOGEu
 bm90LXdlYi1wbGF0Zm9ybS50ZXN0gjJ4bi0tbjhqNmRzNTNsd3drcnFodjI4YS53
-d3cxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIyd3d3Mi54bi0tbjhqNmRzNTNsd3dr
-cnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCMnhuLS1uOGo2ZHM1M2x3d2ty
-cWh2MjhhLnd3dzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjJ3d3cxLnhuLS1uOGo2
-ZHM1M2x3d2tycWh2MjhhLm5vdC13ZWItcGxhdGZvcm0udGVzdII2eG4tLW44ajZk
-czUzbHd3a3JxaHYyOGEueG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0gjZ4
-bi0tbHZlLTZsYWQueG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3Jt
+d3cyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIyeG4tLW44ajZkczUzbHd3a3JxaHYy
+OGEud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCMnd3dzIueG4tLW44ajZkczUz
+bHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjJ3d3cxLnhuLS1uOGo2
+ZHM1M2x3d2tycWh2MjhhLm5vdC13ZWItcGxhdGZvcm0udGVzdII2eG4tLWx2ZS02
+bGFkLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLndlYi1wbGF0Zm9ybS50ZXN0gjZ4
+bi0tbjhqNmRzNTNsd3drcnFodjI4YS54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3Jt
 LnRlc3SCOnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnhuLS1sdmUtNmxhZC5ub3Qt
 d2ViLXBsYXRmb3JtLnRlc3SCOnhuLS1sdmUtNmxhZC54bi0tbjhqNmRzNTNsd3dr
 cnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCQXhuLS1uOGo2ZHM1M2x3d2ty
 cWh2MjhhLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLndlYi1wbGF0Zm9ybS50ZXN0
 gkV4bi0tbjhqNmRzNTNsd3drcnFodjI4YS54bi0tbjhqNmRzNTNsd3drcnFodjI4
-YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwDQYJKoZIhvcNAQELBQADggEBAJZUUYLx
-2KRkFYPUktXmqLB4+JqhA73enrQgAfVXgzm8dDBxEHqRGI5+uP81pzp3muwMHU7J
-LheYwAoFXd+D5p9QwJ4Aa82Af8HlmaE0vrNUR5vHtCvKwJLG5f9lLN/pCFyRFBB8
-U4mJoyWCB2f48FzI4nzi3api5rlOC/5uLU/3ySY1wakPJPH0aPiEJDR7DlRXmQ53
-j++zvsV4evzte2WaNJHD72cHV42FMzr0AzXR0qeIZLdqaZxTQXJLRmGJWlOcnFwB
-tZh4OVJh4q6jRHpg5FAoHfBdV20YTE1PHRIkYHBzPgjd47wxqzDoCjhtgpsCy9U6
-8t5/sXRe2nL5ktQ=
+YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwDQYJKoZIhvcNAQELBQADggEBAFgUyc+X
+AMTXjKv+IuKOSKSNp5WsA7tNEK8HHvKyKraX611JTPUejxohoSZv7scL2+8GOMsq
+9I9mmju4l0F45FiphfrR3swVquSM1jK6k9BDTchQU5FQOoBhunvrtwb7Y64/AiCy
+ZRE7nkOtV/6mIjrGjFu97JT0OwbZ+SFw+bNVWmf6RMea550ODCS/jsEo3Scbihya
+oHPCVFk29oEBqOOlWITasEc5Z4IpZRn31mT3YV/+GHfMDJ16lEENwg2iXIrjcU0a
+a0/KCLgRZKBNorlVt3E/3awQVJV2qn4Ei7sMaIjPn4oMen166poZe7oA8mKHaavp
+VKvWQ5Gh5LHGhZs=
 -----END CERTIFICATE-----
diff --git a/third_party/wpt_tools/wpt/tools/certs/web-platform.test.key b/third_party/wpt_tools/wpt/tools/certs/web-platform.test.key
index c63eb24e01..26b926f7 100644
--- a/third_party/wpt_tools/wpt/tools/certs/web-platform.test.key
+++ b/third_party/wpt_tools/wpt/tools/certs/web-platform.test.key
@@ -1,28 +1,28 @@
 -----BEGIN PRIVATE KEY-----
-MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCk+/0ce04ZJIm2
-ay2Edu6Nkx3NtFSMA0zRKEdgMJYoyOdBR15ZElBBAVoc6yw4RpYwFWxB4bRc1weq
-3LGi1/iiqMV95pZowFpOXxuVilYb3O8Jy78hXjo2fIFXiANhgqE4COIsoy1H1xAT
-UYYe1DtQ8j8ugxeRonpzuRHlaW2KJLUVZa7HdR/YjCGLyyVbroh0YprVfrN1SRlP
-SSU9s+3UQbhboT+y2zusq9JuaqMeUwVgxN91VKpQgHrmX4pKyb3h51s/5M7xnpHk
-1M9eYhx+1vqHiPPCdM3lin3w2NKoAWLMCd3hw7C1tIpcPS0yV1rlTbMiLyHx0gK1
-T+QCuZDLAgMBAAECggEAe1vW0zb3HCGPvo/AxuzOTZkUjbwqA05sX29IfwmVHQWq
-s8qTJvJkg1ZpdHn65FES9vztpw0F+Ozm1MCTKXlmdOjQUeTZzZUVcMf4LgXzgH3f
-VWm8jUyRJjBN3Y7bSEuOFAHAazPPJYoOgQNRzzdM6qdWyoZGVyQvftuAIBKGTuUT
-sQ8CEmQa9NySqPCsAu+mGhWvUGACy4hF7ucvA5r/IxbfAaEolAc/cl52QNUgC/Yf
-x0qvO2cSKdY/51oRCgarNcIbEqXRyfAELULR8ti62g86ZfoUAGtjMqSt+yl4cd4B
-GN71U74Lj74JmlmVNKQbbo8N/WGZ2/V5s77f2NuH8QKBgQDYGeVmDo2EakCHzinT
-/NushSHlS/1CN0mWf67bMI+3Hh6Y12F37DVKGLsGn8Nb2HY05FggxAeVMivKb6yB
-Vi3L1J0wEIUjNVyfxPVL8FjWxtfm1WONFtddiuclbGC62U2fPJ8azQmEtgbUulxa
-eMiKwJk/eRhDS3fuzoBTYkrvvwKBgQDDcglKQDvDYYzwFxLAuQHEh/2nSPU/fRIH
-UuS0TG2ka7umjRPKdyq/XTjV7NUEgD+In7pf+dqxqhaoWOPJMAARSnWJSo5iUI4Q
-Guz8V5wuOex54wr3YVbkapqmOWOAPoKDzG+xVe3ytd8/4AfMbwLSrcw9g4oUVjcG
-TTl5PoWh9QKBgQCwwAWMAs0nB8y+BxbZJ5D5O27s38lGNng+2zJGXyK88Kqv8kHr
-V0yCzVVzZorf/V05h6a5LfzRv9ZnXg2nP7h3ZfAnFuv+Ty/yEaNcODpBeSOvzsr8
-5DjEbs7+IfW//epqGqg7wIZPgJ53sfHFodLNAhiV/NKmf/yZW1dEXDnUewKBgAIs
-jY/m4QNOXXv6NboxFKT0Ak1PEXNQV9f/Aw5CX2HZ1O+IWDUDWFVimxQ+Gyx+pLZH
-WJJivB0H0FK1EmuVfhqzIlWRn73WOY5STlqMOu+Es22zqdaQnZ/S07+Pmdy+VUNU
-DdYCJ7Bwd3hFbLDId1aSmlgA05NgViJaz43atS/VAoGALCO1IeTWP0xrgMG06dhg
-93G0nbBWwod9ZTcqVnGtF7K7fyXu8n0on0rGnzzlWMIad8ubCIir7GoE8f3X/fkh
-Ss9pt0kYNIad+rJ2SrSOo/5G+lu41HfDcqKpdl5D1KX0RmRBGqHDB15zoz+sOvrB
-2YfUvYjSk1wwpncAYRi68xY=
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDf1DWXJxBWd17d
+IofHTgQIBfsq32PiaxjN/89gNhC+rB4RHwhnCX3cuvLPDOvvMpA4GCXAX3pYeDSV
+OBks6xuZNx25BQTvV0ydCDhf7YVkkRZfj1x0bRPknwSNDjCE0NPH40AghmS/h+Tf
+GU80rQDFji0/FapcswmLMmKcB9kl+dvudmaSWqCnWZTpT/kyLBWSd5+mkA6S1br2
+lQSIE6N5O9oaU1jAK1E6jQ2ld3DFM8JINRW9fsx7u5OMu2gds84AbGPc1bPOW9ad
+gFrcxngiYdHGZ0hvYLi7RofbD3OR0CTir4txNd0YXewTcENKBcBb7i2DRP9J8nuy
+5YUhycgXAgMBAAECggEAGMEPbDgVxnpNM4euHIy0RW7j6Enscg4GIEI6XRmdoHjI
+mnwkIcEa+l5ynBOBxGKDMLD6+9uTXFVu+1HI9v7Jfphp4Rx8/ztYbcWK9pD+P7EM
+GGVyhC3MFWzAxBjdpNKzmVe4r+AtJEGTPlk+OUUo4LBosKFkxfvHAm4AGeGEUn6q
+ppoaJbGjjbeKzZFkS6RdHqpJJ4b/o8oOlraHAEZb/vJk31pgokUBV1Hh0BYeLuHA
+ugQT2+a8sX3MwbHC8+6poPR5kpmQUzoVEuN+Iz/ccr9ruUeD10TFcQYl/4gx/gl4
+isjLK3mDCAt7FWGWeVuIjxyBOTrCeyHP0cZza8oKgQKBgQD5MYy3FNXdH9TowU54
+0J+0nAkoSz3w6Tsg9J2jdUtJ+l4yITiFd4p4512q8aVcaTIwQCCGEWxE3Y7Cbt09
+YAK+BLNnXaGQPYomIvt9W8zOrjp/5sB1ac40q5e90Ng9czVHWIGDxE5pEpg8eHza
+PxxdhCGAkEtkahKpYn6nqT7S+wKBgQDl8U0e05DerY36hxSmWVSv+P7ccwzq/FWS
+oke1CUTO2njt/IWiPI/Di5VZl0jQ7vChcHVFpFn/Igr4sWq30fqdRvNjGV78Htyy
+2Jd6XpLSDOHdJr4Ykx0WORenXerdvZB1+OV78I2m1BgVS/OOhOgwK9LhTYlMHVIn
+hU1ASbo0lQKBgQCzoT44M3K+xVVquv3gJTMatGf9fc+Wu+l9pheEXub42tvP8xaV
+T0ioQs/IjAyRgttE4NURD7omIjfofJZKyczwQN86Icp2+YV+XDVBdk06p2lQDXyq
+pqyYVyE5GTTnhwbe+TPTUkzbfSX0YT5O7LN7zeWAkYNnTPdK1s9J+LxqxQKBgQCR
+vzUmyOsWeeN4XI6WMiEfuS+yA6q4d2C2JO5WrZ1Tj97+2gTKJKDrTVpJAz9AT3Nu
+oJ10mwwAT0+s+qeuBAZaElLLCZXPMLCrG+ZHxhJB2bCAQMJVSUoyf9WiXEE2c6VR
+YYXz3TGsANuTBCVIvK1/ewebj03rVNpx+mhQy2qfUQKBgQDYzRKBO21bpw0IcD1v
+r35D688y55bG2vTjV2vFoUpanLV6gftY473C/gwNJXAs69uJIeT9AM+KE6n/3bEK
+8rS8M6TcN8I3cRYwNnx+OPFF+YD8KVsbv8I2y2Gu1xGrMd+PyAHYnQmXcaYqN7eU
+hqH7BXYpwNm96Lm4De1W+tXPJA==
 -----END PRIVATE KEY-----
diff --git a/third_party/wpt_tools/wpt/tools/certs/web-platform.test.pem b/third_party/wpt_tools/wpt/tools/certs/web-platform.test.pem
index 871a093..be1bfd5a 100644
--- a/third_party/wpt_tools/wpt/tools/certs/web-platform.test.pem
+++ b/third_party/wpt_tools/wpt/tools/certs/web-platform.test.pem
@@ -1,240 +1,133 @@
 Certificate:
     Data:
         Version: 3 (0x2)
-        Serial Number: 716436 (0xaee94)
+        Serial Number: 700764 (0xab15c)
         Signature Algorithm: sha256WithRSAEncryption
         Issuer: CN=web-platform-tests
         Validity
-            Not Before: Oct 12 00:43:33 2021 GMT
-            Not After : Oct 12 00:43:33 2022 GMT
+            Not Before: Jul 12 12:45:17 2022 GMT
+            Not After : Jul 12 12:45:17 2023 GMT
         Subject: CN=web-platform.test
         Subject Public Key Info:
             Public Key Algorithm: rsaEncryption
                 RSA Public-Key: (2048 bit)
                 Modulus:
-                    00:a4:fb:fd:1c:7b:4e:19:24:89:b6:6b:2d:84:76:
-                    ee:8d:93:1d:cd:b4:54:8c:03:4c:d1:28:47:60:30:
-                    96:28:c8:e7:41:47:5e:59:12:50:41:01:5a:1c:eb:
-                    2c:38:46:96:30:15:6c:41:e1:b4:5c:d7:07:aa:dc:
-                    b1:a2:d7:f8:a2:a8:c5:7d:e6:96:68:c0:5a:4e:5f:
-                    1b:95:8a:56:1b:dc:ef:09:cb:bf:21:5e:3a:36:7c:
-                    81:57:88:03:61:82:a1:38:08:e2:2c:a3:2d:47:d7:
-                    10:13:51:86:1e:d4:3b:50:f2:3f:2e:83:17:91:a2:
-                    7a:73:b9:11:e5:69:6d:8a:24:b5:15:65:ae:c7:75:
-                    1f:d8:8c:21:8b:cb:25:5b:ae:88:74:62:9a:d5:7e:
-                    b3:75:49:19:4f:49:25:3d:b3:ed:d4:41:b8:5b:a1:
-                    3f:b2:db:3b:ac:ab:d2:6e:6a:a3:1e:53:05:60:c4:
-                    df:75:54:aa:50:80:7a:e6:5f:8a:4a:c9:bd:e1:e7:
-                    5b:3f:e4:ce:f1:9e:91:e4:d4:cf:5e:62:1c:7e:d6:
-                    fa:87:88:f3:c2:74:cd:e5:8a:7d:f0:d8:d2:a8:01:
-                    62:cc:09:dd:e1:c3:b0:b5:b4:8a:5c:3d:2d:32:57:
-                    5a:e5:4d:b3:22:2f:21:f1:d2:02:b5:4f:e4:02:b9:
-                    90:cb
+                    00:df:d4:35:97:27:10:56:77:5e:dd:22:87:c7:4e:
+                    04:08:05:fb:2a:df:63:e2:6b:18:cd:ff:cf:60:36:
+                    10:be:ac:1e:11:1f:08:67:09:7d:dc:ba:f2:cf:0c:
+                    eb:ef:32:90:38:18:25:c0:5f:7a:58:78:34:95:38:
+                    19:2c:eb:1b:99:37:1d:b9:05:04:ef:57:4c:9d:08:
+                    38:5f:ed:85:64:91:16:5f:8f:5c:74:6d:13:e4:9f:
+                    04:8d:0e:30:84:d0:d3:c7:e3:40:20:86:64:bf:87:
+                    e4:df:19:4f:34:ad:00:c5:8e:2d:3f:15:aa:5c:b3:
+                    09:8b:32:62:9c:07:d9:25:f9:db:ee:76:66:92:5a:
+                    a0:a7:59:94:e9:4f:f9:32:2c:15:92:77:9f:a6:90:
+                    0e:92:d5:ba:f6:95:04:88:13:a3:79:3b:da:1a:53:
+                    58:c0:2b:51:3a:8d:0d:a5:77:70:c5:33:c2:48:35:
+                    15:bd:7e:cc:7b:bb:93:8c:bb:68:1d:b3:ce:00:6c:
+                    63:dc:d5:b3:ce:5b:d6:9d:80:5a:dc:c6:78:22:61:
+                    d1:c6:67:48:6f:60:b8:bb:46:87:db:0f:73:91:d0:
+                    24:e2:af:8b:71:35:dd:18:5d:ec:13:70:43:4a:05:
+                    c0:5b:ee:2d:83:44:ff:49:f2:7b:b2:e5:85:21:c9:
+                    c8:17
                 Exponent: 65537 (0x10001)
         X509v3 extensions:
             X509v3 Basic Constraints: 
                 CA:FALSE
             X509v3 Subject Key Identifier: 
-                8C:6E:90:2B:45:B9:4A:58:DF:27:DD:C3:72:E0:5F:80:29:13:D3:16
+                53:34:14:49:85:A6:DE:7F:A4:F6:2C:42:A9:1A:9C:F7:D9:20:50:C1
             X509v3 Authority Key Identifier: 
-                keyid:FF:04:8F:A1:20:A3:BE:F4:C0:D6:C3:BF:20:21:9B:90:7D:6A:C3:CC
+                keyid:CA:3C:92:E7:DC:50:39:0B:E5:44:3F:DF:6F:91:5C:E2:88:2A:3A:D6
 
             X509v3 Key Usage: 
                 Digital Signature, Non Repudiation, Key Encipherment
             X509v3 Extended Key Usage: 
                 TLS Web Server Authentication
             X509v3 Subject Alternative Name: 
-                DNS:web-platform.test, DNS:op7.web-platform.test, DNS:op6.web-platform.test, DNS:op1.web-platform.test, DNS:op5.web-platform.test, DNS:www.web-platform.test, DNS:op9.web-platform.test, DNS:op8.web-platform.test, DNS:not-web-platform.test, DNS:op4.web-platform.test, DNS:op3.web-platform.test, DNS:op2.web-platform.test, DNS:op61.web-platform.test, DNS:op63.web-platform.test, DNS:op30.web-platform.test, DNS:op74.web-platform.test, DNS:op73.web-platform.test, DNS:op46.web-platform.test, DNS:op34.web-platform.test, DNS:op89.web-platform.test, DNS:op31.web-platform.test, DNS:op36.web-platform.test, DNS:op99.web-platform.test, DNS:op13.web-platform.test, DNS:www1.web-platform.test, DNS:www2.web-platform.test, DNS:op15.web-platform.test, DNS:op87.web-platform.test, DNS:op16.web-platform.test, DNS:op96.web-platform.test, DNS:op21.web-platform.test, DNS:op12.web-platform.test, DNS:op93.web-platform.test, DNS:op91.web-platform.test, DNS:op53.web-platform.test, DNS:op24.web-platform.test, DNS:op45.web-platform.test, DNS:op32.web-platform.test, DNS:op48.web-platform.test, DNS:op56.web-platform.test, DNS:op79.web-platform.test, DNS:op90.web-platform.test, DNS:op17.web-platform.test, DNS:op62.web-platform.test, DNS:op51.web-platform.test, DNS:op41.web-platform.test, DNS:op78.web-platform.test, DNS:op37.web-platform.test, DNS:op18.web-platform.test, DNS:op69.web-platform.test, DNS:op64.web-platform.test, DNS:op39.web-platform.test, DNS:op38.web-platform.test, DNS:op84.web-platform.test, DNS:op20.web-platform.test, DNS:op58.web-platform.test, DNS:op98.web-platform.test, DNS:op14.web-platform.test, DNS:op94.web-platform.test, DNS:op27.web-platform.test, DNS:op29.web-platform.test, DNS:op35.web-platform.test, DNS:op97.web-platform.test, DNS:op66.web-platform.test, DNS:op28.web-platform.test, DNS:op19.web-platform.test, DNS:op88.web-platform.test, DNS:op10.web-platform.test, DNS:op82.web-platform.test, DNS:op54.web-platform.test, DNS:op68.web-platform.test, DNS:op86.web-platform.test, DNS:op50.web-platform.test, DNS:op55.web-platform.test, DNS:op40.web-platform.test, DNS:op76.web-platform.test, DNS:op77.web-platform.test, DNS:op57.web-platform.test, DNS:op95.web-platform.test, DNS:op70.web-platform.test, DNS:op11.web-platform.test, DNS:op47.web-platform.test, DNS:op33.web-platform.test, DNS:op65.web-platform.test, DNS:op80.web-platform.test, DNS:op23.web-platform.test, DNS:op75.web-platform.test, DNS:op26.web-platform.test, DNS:op71.web-platform.test, DNS:op92.web-platform.test, DNS:op43.web-platform.test, DNS:op72.web-platform.test, DNS:op25.web-platform.test, DNS:op67.web-platform.test, DNS:op44.web-platform.test, DNS:op85.web-platform.test, DNS:op49.web-platform.test, DNS:op81.web-platform.test, DNS:op83.web-platform.test, DNS:op42.web-platform.test, DNS:op59.web-platform.test, DNS:op52.web-platform.test, DNS:op22.web-platform.test, DNS:op60.web-platform.test, DNS:op2.not-web-platform.test, DNS:op1.not-web-platform.test, DNS:www.not-web-platform.test, DNS:op8.not-web-platform.test, DNS:op6.not-web-platform.test, DNS:op9.not-web-platform.test, DNS:op5.not-web-platform.test, DNS:op3.not-web-platform.test, DNS:op7.not-web-platform.test, DNS:www.www.web-platform.test, DNS:op4.not-web-platform.test, DNS:op60.not-web-platform.test, DNS:op20.not-web-platform.test, DNS:op53.not-web-platform.test, DNS:www.www1.web-platform.test, DNS:op38.not-web-platform.test, DNS:op84.not-web-platform.test, DNS:op82.not-web-platform.test, DNS:op99.not-web-platform.test, DNS:op65.not-web-platform.test, DNS:op67.not-web-platform.test, DNS:op78.not-web-platform.test, DNS:www.www2.web-platform.test, DNS:op18.not-web-platform.test, DNS:op48.not-web-platform.test, DNS:op69.not-web-platform.test, DNS:op34.not-web-platform.test, DNS:op76.not-web-platform.test, DNS:op30.not-web-platform.test, DNS:op94.not-web-platform.test, DNS:op54.not-web-platform.test, DNS:op68.not-web-platform.test, DNS:op70.not-web-platform.test, DNS:op77.not-web-platform.test, DNS:op90.not-web-platform.test, DNS:op80.not-web-platform.test, DNS:op16.not-web-platform.test, DNS:op45.not-web-platform.test, DNS:op71.not-web-platform.test, DNS:op42.not-web-platform.test, DNS:op91.not-web-platform.test, DNS:op56.not-web-platform.test, DNS:op24.not-web-platform.test, DNS:www2.www.web-platform.test, DNS:op43.not-web-platform.test, DNS:op74.not-web-platform.test, DNS:op51.not-web-platform.test, DNS:op36.not-web-platform.test, DNS:op79.not-web-platform.test, DNS:op81.not-web-platform.test, DNS:op95.not-web-platform.test, DNS:op27.not-web-platform.test, DNS:op12.not-web-platform.test, DNS:op46.not-web-platform.test, DNS:op40.not-web-platform.test, DNS:op32.not-web-platform.test, DNS:op50.not-web-platform.test, DNS:op89.not-web-platform.test, DNS:op19.not-web-platform.test, DNS:op92.not-web-platform.test, DNS:op10.not-web-platform.test, DNS:op72.not-web-platform.test, DNS:op96.not-web-platform.test, DNS:op11.not-web-platform.test, DNS:op93.not-web-platform.test, DNS:op17.not-web-platform.test, DNS:op75.not-web-platform.test, DNS:op57.not-web-platform.test, DNS:op73.not-web-platform.test, DNS:op97.not-web-platform.test, DNS:op64.not-web-platform.test, DNS:op35.not-web-platform.test, DNS:op63.not-web-platform.test, DNS:op47.not-web-platform.test, DNS:op25.not-web-platform.test, DNS:op31.not-web-platform.test, DNS:op88.not-web-platform.test, DNS:www1.not-web-platform.test, DNS:op26.not-web-platform.test, DNS:op44.not-web-platform.test, DNS:op85.not-web-platform.test, DNS:op87.not-web-platform.test, DNS:op86.not-web-platform.test, DNS:op37.not-web-platform.test, DNS:www1.www.web-platform.test, DNS:op21.not-web-platform.test, DNS:op39.not-web-platform.test, DNS:www2.not-web-platform.test, DNS:op33.not-web-platform.test, DNS:op59.not-web-platform.test, DNS:op52.not-web-platform.test, DNS:op13.not-web-platform.test, DNS:op66.not-web-platform.test, DNS:op15.not-web-platform.test, DNS:op28.not-web-platform.test, DNS:op62.not-web-platform.test, DNS:op58.not-web-platform.test, DNS:op83.not-web-platform.test, DNS:op55.not-web-platform.test, DNS:op29.not-web-platform.test, DNS:op61.not-web-platform.test, DNS:op41.not-web-platform.test, DNS:op49.not-web-platform.test, DNS:op14.not-web-platform.test, DNS:op23.not-web-platform.test, DNS:op22.not-web-platform.test, DNS:op98.not-web-platform.test, DNS:www1.www2.web-platform.test, DNS:www2.www1.web-platform.test, DNS:www1.www1.web-platform.test, DNS:www2.www2.web-platform.test, DNS:www.www.not-web-platform.test, DNS:www1.www.not-web-platform.test, DNS:www.www2.not-web-platform.test, DNS:www2.www.not-web-platform.test, DNS:xn--lve-6lad.web-platform.test, DNS:www.www1.not-web-platform.test, DNS:www1.www1.not-web-platform.test, DNS:www2.www2.not-web-platform.test, DNS:www1.www2.not-web-platform.test, DNS:www2.www1.not-web-platform.test, DNS:xn--lve-6lad.not-web-platform.test, DNS:www.xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.www.web-platform.test, DNS:xn--lve-6lad.www1.web-platform.test, DNS:www1.xn--lve-6lad.web-platform.test, DNS:www2.xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.www2.web-platform.test, DNS:xn--lve-6lad.www.not-web-platform.test, DNS:www.xn--lve-6lad.not-web-platform.test, DNS:www2.xn--lve-6lad.not-web-platform.test, DNS:xn--lve-6lad.www2.not-web-platform.test, DNS:www1.xn--lve-6lad.not-web-platform.test, DNS:xn--lve-6lad.www1.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--lve-6lad.xn--lve-6lad.web-platform.test, DNS:www.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www.web-platform.test, DNS:www2.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www2.web-platform.test, DNS:www1.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www1.web-platform.test, DNS:xn--lve-6lad.xn--lve-6lad.not-web-platform.test, DNS:www.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www1.not-web-platform.test, DNS:www2.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www2.not-web-platform.test, DNS:www1.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--lve-6lad.not-web-platform.test, DNS:xn--lve-6lad.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test
+                DNS:web-platform.test, DNS:www.web-platform.test, DNS:not-web-platform.test, DNS:www1.web-platform.test, DNS:www2.web-platform.test, DNS:www.www.web-platform.test, DNS:www.not-web-platform.test, DNS:www.www2.web-platform.test, DNS:www.www1.web-platform.test, DNS:www2.not-web-platform.test, DNS:www1.www.web-platform.test, DNS:www1.not-web-platform.test, DNS:www2.www.web-platform.test, DNS:www1.www1.web-platform.test, DNS:www2.www1.web-platform.test, DNS:www1.www2.web-platform.test, DNS:www2.www2.web-platform.test, DNS:www.www.not-web-platform.test, DNS:www2.www.not-web-platform.test, DNS:www.www1.not-web-platform.test, DNS:www1.www.not-web-platform.test, DNS:xn--lve-6lad.web-platform.test, DNS:www.www2.not-web-platform.test, DNS:www1.www1.not-web-platform.test, DNS:www2.www2.not-web-platform.test, DNS:www2.www1.not-web-platform.test, DNS:www1.www2.not-web-platform.test, DNS:xn--lve-6lad.not-web-platform.test, DNS:www.xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.www.web-platform.test, DNS:xn--lve-6lad.www2.web-platform.test, DNS:xn--lve-6lad.www1.web-platform.test, DNS:www2.xn--lve-6lad.web-platform.test, DNS:www1.xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.www.not-web-platform.test, DNS:www.xn--lve-6lad.not-web-platform.test, DNS:xn--lve-6lad.www2.not-web-platform.test, DNS:xn--lve-6lad.www1.not-web-platform.test, DNS:www1.xn--lve-6lad.not-web-platform.test, DNS:www2.xn--lve-6lad.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--lve-6lad.xn--lve-6lad.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www.web-platform.test, DNS:www.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:www2.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www1.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www2.web-platform.test, DNS:www1.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--lve-6lad.xn--lve-6lad.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www.not-web-platform.test, DNS:www.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www2.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www1.not-web-platform.test, DNS:www2.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:www1.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--lve-6lad.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--lve-6lad.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--lve-6lad.not-web-platform.test, DNS:xn--lve-6lad.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test
     Signature Algorithm: sha256WithRSAEncryption
-         cd:4e:a8:23:07:57:ae:7a:31:e6:27:58:87:c2:be:42:21:23:
-         42:c3:e2:d3:0a:82:54:f9:95:42:23:67:55:cf:c4:92:b8:90:
-         e7:f2:d1:28:e4:aa:52:ba:46:c0:db:ba:0d:70:f5:90:17:48:
-         be:80:b2:b5:23:80:3e:57:f0:8e:f7:a9:1b:da:5c:0f:a8:3e:
-         46:38:c4:a8:f6:61:c0:d4:b7:f9:97:5e:d1:e3:d1:87:44:76:
-         1f:5c:89:05:fc:1f:ce:10:1f:e0:99:d7:20:e8:60:4c:e1:b7:
-         9b:7a:b7:87:a7:3f:c6:a2:0d:a8:0d:89:bb:2e:ed:42:14:a4:
-         42:64:b0:b6:e2:ac:bc:f5:7d:5e:ed:98:5a:f6:93:8e:72:d0:
-         43:6e:48:c9:2b:7b:9d:0e:ef:f1:97:10:c3:77:f0:bc:f3:fb:
-         b0:89:64:94:55:6c:ac:19:30:6b:11:1d:8b:84:c0:de:65:e1:
-         6c:3d:96:bd:49:9b:48:67:2f:9d:8b:7f:ae:ed:72:4c:a6:e0:
-         84:34:86:af:ee:69:c1:8e:c7:5b:3e:c7:1c:77:70:9c:77:0c:
-         7d:61:32:01:47:2f:06:ae:38:f4:ae:dc:e8:e9:bd:c9:7d:97:
-         a3:0c:e8:21:e5:23:85:9b:d5:4e:a1:ee:fe:ae:95:4d:d2:44:
-         d6:18:22:88
+         74:00:12:c7:43:34:fd:87:4e:f8:67:58:34:e2:c7:42:be:a8:
+         fc:61:df:11:9c:77:18:d5:0b:e6:92:a1:c2:d9:9b:20:a5:ee:
+         e8:81:ab:62:fb:55:67:35:95:fa:8b:b6:a5:3b:52:f7:d4:21:
+         e8:7c:b5:37:12:58:02:24:b5:7e:93:4f:6c:ce:5b:4b:af:8f:
+         fc:22:e2:03:2d:47:d2:87:43:c0:de:82:a7:5b:6a:97:2f:e9:
+         f7:46:f4:41:d2:35:07:62:c5:a4:e8:08:a2:90:1d:44:4a:3d:
+         71:d6:c5:f5:40:2d:99:0d:33:4f:0f:31:69:f7:02:bd:c5:44:
+         b9:42:9e:f2:94:36:44:66:b8:b8:81:99:06:d2:b7:df:cb:b0:
+         01:c8:5b:64:15:a4:75:78:da:71:b1:92:01:5b:55:7c:76:94:
+         a2:f3:1a:23:78:37:e5:65:51:0f:ca:66:91:d4:62:1b:b7:22:
+         d2:75:37:7e:67:ac:b5:9d:b3:50:c8:db:76:29:a1:73:21:74:
+         71:9e:25:de:25:2a:2c:20:fb:e8:68:eb:9f:fc:f1:a7:85:69:
+         a4:a8:0d:93:4b:ff:f5:9d:32:31:d3:ca:7e:0e:79:f3:45:32:
+         d8:fc:35:12:d4:08:71:fd:e2:0e:64:55:a2:5a:f4:2f:be:19:
+         f1:2d:be:3f
 -----BEGIN CERTIFICATE-----
-MIIgvDCCH6SgAwIBAgIDCu6UMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEndl
-Yi1wbGF0Zm9ybS10ZXN0czAeFw0yMTEwMTIwMDQzMzNaFw0yMjEwMTIwMDQzMzNa
+MIIMsjCCC5qgAwIBAgIDCrFcMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEndl
+Yi1wbGF0Zm9ybS10ZXN0czAeFw0yMjA3MTIxMjQ1MTdaFw0yMzA3MTIxMjQ1MTda
 MBwxGjAYBgNVBAMMEXdlYi1wbGF0Zm9ybS50ZXN0MIIBIjANBgkqhkiG9w0BAQEF
-AAOCAQ8AMIIBCgKCAQEApPv9HHtOGSSJtmsthHbujZMdzbRUjANM0ShHYDCWKMjn
-QUdeWRJQQQFaHOssOEaWMBVsQeG0XNcHqtyxotf4oqjFfeaWaMBaTl8blYpWG9zv
-Ccu/IV46NnyBV4gDYYKhOAjiLKMtR9cQE1GGHtQ7UPI/LoMXkaJ6c7kR5WltiiS1
-FWWux3Uf2Iwhi8slW66IdGKa1X6zdUkZT0klPbPt1EG4W6E/sts7rKvSbmqjHlMF
-YMTfdVSqUIB65l+KSsm94edbP+TO8Z6R5NTPXmIcftb6h4jzwnTN5Yp98NjSqAFi
-zAnd4cOwtbSKXD0tMlda5U2zIi8h8dICtU/kArmQywIDAQABo4IeBDCCHgAwCQYD
-VR0TBAIwADAdBgNVHQ4EFgQUjG6QK0W5SljfJ93DcuBfgCkT0xYwHwYDVR0jBBgw
-FoAU/wSPoSCjvvTA1sO/ICGbkH1qw8wwCwYDVR0PBAQDAgXgMBMGA1UdJQQMMAoG
-CCsGAQUFBwMBMIIdjwYDVR0RBIIdhjCCHYKCEXdlYi1wbGF0Zm9ybS50ZXN0ghVv
-cDcud2ViLXBsYXRmb3JtLnRlc3SCFW9wNi53ZWItcGxhdGZvcm0udGVzdIIVb3Ax
-LndlYi1wbGF0Zm9ybS50ZXN0ghVvcDUud2ViLXBsYXRmb3JtLnRlc3SCFXd3dy53
-ZWItcGxhdGZvcm0udGVzdIIVb3A5LndlYi1wbGF0Zm9ybS50ZXN0ghVvcDgud2Vi
-LXBsYXRmb3JtLnRlc3SCFW5vdC13ZWItcGxhdGZvcm0udGVzdIIVb3A0LndlYi1w
-bGF0Zm9ybS50ZXN0ghVvcDMud2ViLXBsYXRmb3JtLnRlc3SCFW9wMi53ZWItcGxh
-dGZvcm0udGVzdIIWb3A2MS53ZWItcGxhdGZvcm0udGVzdIIWb3A2My53ZWItcGxh
-dGZvcm0udGVzdIIWb3AzMC53ZWItcGxhdGZvcm0udGVzdIIWb3A3NC53ZWItcGxh
-dGZvcm0udGVzdIIWb3A3My53ZWItcGxhdGZvcm0udGVzdIIWb3A0Ni53ZWItcGxh
-dGZvcm0udGVzdIIWb3AzNC53ZWItcGxhdGZvcm0udGVzdIIWb3A4OS53ZWItcGxh
-dGZvcm0udGVzdIIWb3AzMS53ZWItcGxhdGZvcm0udGVzdIIWb3AzNi53ZWItcGxh
-dGZvcm0udGVzdIIWb3A5OS53ZWItcGxhdGZvcm0udGVzdIIWb3AxMy53ZWItcGxh
-dGZvcm0udGVzdIIWd3d3MS53ZWItcGxhdGZvcm0udGVzdIIWd3d3Mi53ZWItcGxh
-dGZvcm0udGVzdIIWb3AxNS53ZWItcGxhdGZvcm0udGVzdIIWb3A4Ny53ZWItcGxh
-dGZvcm0udGVzdIIWb3AxNi53ZWItcGxhdGZvcm0udGVzdIIWb3A5Ni53ZWItcGxh
-dGZvcm0udGVzdIIWb3AyMS53ZWItcGxhdGZvcm0udGVzdIIWb3AxMi53ZWItcGxh
-dGZvcm0udGVzdIIWb3A5My53ZWItcGxhdGZvcm0udGVzdIIWb3A5MS53ZWItcGxh
-dGZvcm0udGVzdIIWb3A1My53ZWItcGxhdGZvcm0udGVzdIIWb3AyNC53ZWItcGxh
-dGZvcm0udGVzdIIWb3A0NS53ZWItcGxhdGZvcm0udGVzdIIWb3AzMi53ZWItcGxh
-dGZvcm0udGVzdIIWb3A0OC53ZWItcGxhdGZvcm0udGVzdIIWb3A1Ni53ZWItcGxh
-dGZvcm0udGVzdIIWb3A3OS53ZWItcGxhdGZvcm0udGVzdIIWb3A5MC53ZWItcGxh
-dGZvcm0udGVzdIIWb3AxNy53ZWItcGxhdGZvcm0udGVzdIIWb3A2Mi53ZWItcGxh
-dGZvcm0udGVzdIIWb3A1MS53ZWItcGxhdGZvcm0udGVzdIIWb3A0MS53ZWItcGxh
-dGZvcm0udGVzdIIWb3A3OC53ZWItcGxhdGZvcm0udGVzdIIWb3AzNy53ZWItcGxh
-dGZvcm0udGVzdIIWb3AxOC53ZWItcGxhdGZvcm0udGVzdIIWb3A2OS53ZWItcGxh
-dGZvcm0udGVzdIIWb3A2NC53ZWItcGxhdGZvcm0udGVzdIIWb3AzOS53ZWItcGxh
-dGZvcm0udGVzdIIWb3AzOC53ZWItcGxhdGZvcm0udGVzdIIWb3A4NC53ZWItcGxh
-dGZvcm0udGVzdIIWb3AyMC53ZWItcGxhdGZvcm0udGVzdIIWb3A1OC53ZWItcGxh
-dGZvcm0udGVzdIIWb3A5OC53ZWItcGxhdGZvcm0udGVzdIIWb3AxNC53ZWItcGxh
-dGZvcm0udGVzdIIWb3A5NC53ZWItcGxhdGZvcm0udGVzdIIWb3AyNy53ZWItcGxh
-dGZvcm0udGVzdIIWb3AyOS53ZWItcGxhdGZvcm0udGVzdIIWb3AzNS53ZWItcGxh
-dGZvcm0udGVzdIIWb3A5Ny53ZWItcGxhdGZvcm0udGVzdIIWb3A2Ni53ZWItcGxh
-dGZvcm0udGVzdIIWb3AyOC53ZWItcGxhdGZvcm0udGVzdIIWb3AxOS53ZWItcGxh
-dGZvcm0udGVzdIIWb3A4OC53ZWItcGxhdGZvcm0udGVzdIIWb3AxMC53ZWItcGxh
-dGZvcm0udGVzdIIWb3A4Mi53ZWItcGxhdGZvcm0udGVzdIIWb3A1NC53ZWItcGxh
-dGZvcm0udGVzdIIWb3A2OC53ZWItcGxhdGZvcm0udGVzdIIWb3A4Ni53ZWItcGxh
-dGZvcm0udGVzdIIWb3A1MC53ZWItcGxhdGZvcm0udGVzdIIWb3A1NS53ZWItcGxh
-dGZvcm0udGVzdIIWb3A0MC53ZWItcGxhdGZvcm0udGVzdIIWb3A3Ni53ZWItcGxh
-dGZvcm0udGVzdIIWb3A3Ny53ZWItcGxhdGZvcm0udGVzdIIWb3A1Ny53ZWItcGxh
-dGZvcm0udGVzdIIWb3A5NS53ZWItcGxhdGZvcm0udGVzdIIWb3A3MC53ZWItcGxh
-dGZvcm0udGVzdIIWb3AxMS53ZWItcGxhdGZvcm0udGVzdIIWb3A0Ny53ZWItcGxh
-dGZvcm0udGVzdIIWb3AzMy53ZWItcGxhdGZvcm0udGVzdIIWb3A2NS53ZWItcGxh
-dGZvcm0udGVzdIIWb3A4MC53ZWItcGxhdGZvcm0udGVzdIIWb3AyMy53ZWItcGxh
-dGZvcm0udGVzdIIWb3A3NS53ZWItcGxhdGZvcm0udGVzdIIWb3AyNi53ZWItcGxh
-dGZvcm0udGVzdIIWb3A3MS53ZWItcGxhdGZvcm0udGVzdIIWb3A5Mi53ZWItcGxh
-dGZvcm0udGVzdIIWb3A0My53ZWItcGxhdGZvcm0udGVzdIIWb3A3Mi53ZWItcGxh
-dGZvcm0udGVzdIIWb3AyNS53ZWItcGxhdGZvcm0udGVzdIIWb3A2Ny53ZWItcGxh
-dGZvcm0udGVzdIIWb3A0NC53ZWItcGxhdGZvcm0udGVzdIIWb3A4NS53ZWItcGxh
-dGZvcm0udGVzdIIWb3A0OS53ZWItcGxhdGZvcm0udGVzdIIWb3A4MS53ZWItcGxh
-dGZvcm0udGVzdIIWb3A4My53ZWItcGxhdGZvcm0udGVzdIIWb3A0Mi53ZWItcGxh
-dGZvcm0udGVzdIIWb3A1OS53ZWItcGxhdGZvcm0udGVzdIIWb3A1Mi53ZWItcGxh
-dGZvcm0udGVzdIIWb3AyMi53ZWItcGxhdGZvcm0udGVzdIIWb3A2MC53ZWItcGxh
-dGZvcm0udGVzdIIZb3AyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3AxLm5vdC13
-ZWItcGxhdGZvcm0udGVzdIIZd3d3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A4
-Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A2Lm5vdC13ZWItcGxhdGZvcm0udGVz
-dIIZb3A5Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A1Lm5vdC13ZWItcGxhdGZv
-cm0udGVzdIIZb3AzLm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A3Lm5vdC13ZWIt
-cGxhdGZvcm0udGVzdIIZd3d3Lnd3dy53ZWItcGxhdGZvcm0udGVzdIIZb3A0Lm5v
-dC13ZWItcGxhdGZvcm0udGVzdIIab3A2MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
-Gm9wMjAubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDUzLm5vdC13ZWItcGxhdGZv
-cm0udGVzdIIad3d3Lnd3dzEud2ViLXBsYXRmb3JtLnRlc3SCGm9wMzgubm90LXdl
-Yi1wbGF0Zm9ybS50ZXN0ghpvcDg0Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A4
-Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wOTkubm90LXdlYi1wbGF0Zm9ybS50
-ZXN0ghpvcDY1Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A2Ny5ub3Qtd2ViLXBs
-YXRmb3JtLnRlc3SCGm9wNzgubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghp3d3cud3d3
-Mi53ZWItcGxhdGZvcm0udGVzdIIab3AxOC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
-Gm9wNDgubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDY5Lm5vdC13ZWItcGxhdGZv
-cm0udGVzdIIab3AzNC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNzYubm90LXdl
-Yi1wbGF0Zm9ybS50ZXN0ghpvcDMwLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5
-NC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNTQubm90LXdlYi1wbGF0Zm9ybS50
-ZXN0ghpvcDY4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A3MC5ub3Qtd2ViLXBs
-YXRmb3JtLnRlc3SCGm9wNzcubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDkwLm5v
-dC13ZWItcGxhdGZvcm0udGVzdIIab3A4MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
-Gm9wMTYubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQ1Lm5vdC13ZWItcGxhdGZv
-cm0udGVzdIIab3A3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNDIubm90LXdl
-Yi1wbGF0Zm9ybS50ZXN0ghpvcDkxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A1
-Ni5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMjQubm90LXdlYi1wbGF0Zm9ybS50
-ZXN0ghp3d3cyLnd3dy53ZWItcGxhdGZvcm0udGVzdIIab3A0My5ub3Qtd2ViLXBs
-YXRmb3JtLnRlc3SCGm9wNzQubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDUxLm5v
-dC13ZWItcGxhdGZvcm0udGVzdIIab3AzNi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
-Gm9wNzkubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDgxLm5vdC13ZWItcGxhdGZv
-cm0udGVzdIIab3A5NS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMjcubm90LXdl
-Yi1wbGF0Zm9ybS50ZXN0ghpvcDEyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A0
-Ni5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNDAubm90LXdlYi1wbGF0Zm9ybS50
-ZXN0ghpvcDMyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A1MC5ub3Qtd2ViLXBs
-YXRmb3JtLnRlc3SCGm9wODkubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDE5Lm5v
-dC13ZWItcGxhdGZvcm0udGVzdIIab3A5Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
-Gm9wMTAubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDcyLm5vdC13ZWItcGxhdGZv
-cm0udGVzdIIab3A5Ni5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMTEubm90LXdl
-Yi1wbGF0Zm9ybS50ZXN0ghpvcDkzLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3Ax
-Ny5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNzUubm90LXdlYi1wbGF0Zm9ybS50
-ZXN0ghpvcDU3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A3My5ub3Qtd2ViLXBs
-YXRmb3JtLnRlc3SCGm9wOTcubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDY0Lm5v
-dC13ZWItcGxhdGZvcm0udGVzdIIab3AzNS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
-Gm9wNjMubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQ3Lm5vdC13ZWItcGxhdGZv
-cm0udGVzdIIab3AyNS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMzEubm90LXdl
-Yi1wbGF0Zm9ybS50ZXN0ghpvcDg4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIad3d3
-MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMjYubm90LXdlYi1wbGF0Zm9ybS50
-ZXN0ghpvcDQ0Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A4NS5ub3Qtd2ViLXBs
-YXRmb3JtLnRlc3SCGm9wODcubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDg2Lm5v
-dC13ZWItcGxhdGZvcm0udGVzdIIab3AzNy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
-Gnd3dzEud3d3LndlYi1wbGF0Zm9ybS50ZXN0ghpvcDIxLm5vdC13ZWItcGxhdGZv
-cm0udGVzdIIab3AzOS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGnd3dzIubm90LXdl
-Yi1wbGF0Zm9ybS50ZXN0ghpvcDMzLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A1
-OS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNTIubm90LXdlYi1wbGF0Zm9ybS50
-ZXN0ghpvcDEzLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A2Ni5ub3Qtd2ViLXBs
-YXRmb3JtLnRlc3SCGm9wMTUubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDI4Lm5v
-dC13ZWItcGxhdGZvcm0udGVzdIIab3A2Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
-Gm9wNTgubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDgzLm5vdC13ZWItcGxhdGZv
-cm0udGVzdIIab3A1NS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMjkubm90LXdl
-Yi1wbGF0Zm9ybS50ZXN0ghpvcDYxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A0
-MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNDkubm90LXdlYi1wbGF0Zm9ybS50
-ZXN0ghpvcDE0Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AyMy5ub3Qtd2ViLXBs
-YXRmb3JtLnRlc3SCGm9wMjIubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDk4Lm5v
-dC13ZWItcGxhdGZvcm0udGVzdIIbd3d3MS53d3cyLndlYi1wbGF0Zm9ybS50ZXN0
-ght3d3cyLnd3dzEud2ViLXBsYXRmb3JtLnRlc3SCG3d3dzEud3d3MS53ZWItcGxh
-dGZvcm0udGVzdIIbd3d3Mi53d3cyLndlYi1wbGF0Zm9ybS50ZXN0gh13d3cud3d3
-Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIed3d3MS53d3cubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0gh53d3cud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCHnd3dzIud3d3
-Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIeeG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9y
-bS50ZXN0gh53d3cud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzEud3d3
-MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzIud3d3Mi5ub3Qtd2ViLXBsYXRm
-b3JtLnRlc3SCH3d3dzEud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzIu
-d3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCInhuLS1sdmUtNmxhZC5ub3Qtd2Vi
-LXBsYXRmb3JtLnRlc3SCInd3dy54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRl
-c3SCInhuLS1sdmUtNmxhZC53d3cud2ViLXBsYXRmb3JtLnRlc3SCI3huLS1sdmUt
-NmxhZC53d3cxLndlYi1wbGF0Zm9ybS50ZXN0giN3d3cxLnhuLS1sdmUtNmxhZC53
-ZWItcGxhdGZvcm0udGVzdIIjd3d3Mi54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3Jt
-LnRlc3SCI3huLS1sdmUtNmxhZC53d3cyLndlYi1wbGF0Zm9ybS50ZXN0giZ4bi0t
-bHZlLTZsYWQud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIImd3d3LnhuLS1sdmUt
-NmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCJ3d3dzIueG4tLWx2ZS02bGFkLm5v
-dC13ZWItcGxhdGZvcm0udGVzdIIneG4tLWx2ZS02bGFkLnd3dzIubm90LXdlYi1w
-bGF0Zm9ybS50ZXN0gid3d3cxLnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3Jt
-LnRlc3SCJ3huLS1sdmUtNmxhZC53d3cxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIp
-eG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCK3huLS1s
-dmUtNmxhZC54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3SCLXd3dy54bi0t
-bjhqNmRzNTNsd3drcnFodjI4YS53ZWItcGxhdGZvcm0udGVzdIIteG4tLW44ajZk
-czUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9ybS50ZXN0gi14bi0tbjhqNmRz
-NTNsd3drcnFodjI4YS53d3cud2ViLXBsYXRmb3JtLnRlc3SCLnd3dzIueG4tLW44
-ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1
-M2x3d2tycWh2MjhhLnd3dzIud2ViLXBsYXRmb3JtLnRlc3SCLnd3dzEueG4tLW44
-ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1
-M2x3d2tycWh2MjhhLnd3dzEud2ViLXBsYXRmb3JtLnRlc3SCL3huLS1sdmUtNmxh
-ZC54bi0tbHZlLTZsYWQubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjF3d3cueG4tLW44
-ajZkczUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjF4bi0tbjhq
-NmRzNTNsd3drcnFodjI4YS53d3cubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjJ4bi0t
-bjhqNmRzNTNsd3drcnFodjI4YS53d3cxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIy
-d3d3Mi54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRl
-c3SCMnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3dzIubm90LXdlYi1wbGF0Zm9y
-bS50ZXN0gjJ3d3cxLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLm5vdC13ZWItcGxh
-dGZvcm0udGVzdII2eG4tLW44ajZkczUzbHd3a3JxaHYyOGEueG4tLWx2ZS02bGFk
-LndlYi1wbGF0Zm9ybS50ZXN0gjZ4bi0tbHZlLTZsYWQueG4tLW44ajZkczUzbHd3
-a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCOnhuLS1uOGo2ZHM1M2x3d2tycWh2
-MjhhLnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCOnhuLS1sdmUt
-NmxhZC54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRl
-c3SCQXhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnhuLS1uOGo2ZHM1M2x3d2tycWh2
-MjhhLndlYi1wbGF0Zm9ybS50ZXN0gkV4bi0tbjhqNmRzNTNsd3drcnFodjI4YS54
-bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwDQYJ
-KoZIhvcNAQELBQADggEBAM1OqCMHV656MeYnWIfCvkIhI0LD4tMKglT5lUIjZ1XP
-xJK4kOfy0SjkqlK6RsDbug1w9ZAXSL6AsrUjgD5X8I73qRvaXA+oPkY4xKj2YcDU
-t/mXXtHj0YdEdh9ciQX8H84QH+CZ1yDoYEzht5t6t4enP8aiDagNibsu7UIUpEJk
-sLbirLz1fV7tmFr2k45y0ENuSMkre50O7/GXEMN38Lzz+7CJZJRVbKwZMGsRHYuE
-wN5l4Ww9lr1Jm0hnL52Lf67tckym4IQ0hq/uacGOx1s+xxx3cJx3DH1hMgFHLwau
-OPSu3Ojpvcl9l6MM6CHlI4Wb1U6h7v6ulU3SRNYYIog=
+AAOCAQ8AMIIBCgKCAQEA39Q1lycQVnde3SKHx04ECAX7Kt9j4msYzf/PYDYQvqwe
+ER8IZwl93Lryzwzr7zKQOBglwF96WHg0lTgZLOsbmTcduQUE71dMnQg4X+2FZJEW
+X49cdG0T5J8EjQ4whNDTx+NAIIZkv4fk3xlPNK0AxY4tPxWqXLMJizJinAfZJfnb
+7nZmklqgp1mU6U/5MiwVknefppAOktW69pUEiBOjeTvaGlNYwCtROo0NpXdwxTPC
+SDUVvX7Me7uTjLtoHbPOAGxj3NWzzlvWnYBa3MZ4ImHRxmdIb2C4u0aH2w9zkdAk
+4q+LcTXdGF3sE3BDSgXAW+4tg0T/SfJ7suWFIcnIFwIDAQABo4IJ+jCCCfYwCQYD
+VR0TBAIwADAdBgNVHQ4EFgQUUzQUSYWm3n+k9ixCqRqc99kgUMEwHwYDVR0jBBgw
+FoAUyjyS59xQOQvlRD/fb5Fc4ogqOtYwCwYDVR0PBAQDAgXgMBMGA1UdJQQMMAoG
+CCsGAQUFBwMBMIIJhQYDVR0RBIIJfDCCCXiCEXdlYi1wbGF0Zm9ybS50ZXN0ghV3
+d3cud2ViLXBsYXRmb3JtLnRlc3SCFW5vdC13ZWItcGxhdGZvcm0udGVzdIIWd3d3
+MS53ZWItcGxhdGZvcm0udGVzdIIWd3d3Mi53ZWItcGxhdGZvcm0udGVzdIIZd3d3
+Lnd3dy53ZWItcGxhdGZvcm0udGVzdIIZd3d3Lm5vdC13ZWItcGxhdGZvcm0udGVz
+dIIad3d3Lnd3dzIud2ViLXBsYXRmb3JtLnRlc3SCGnd3dy53d3cxLndlYi1wbGF0
+Zm9ybS50ZXN0ghp3d3cyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIad3d3MS53d3cu
+d2ViLXBsYXRmb3JtLnRlc3SCGnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghp3
+d3cyLnd3dy53ZWItcGxhdGZvcm0udGVzdIIbd3d3MS53d3cxLndlYi1wbGF0Zm9y
+bS50ZXN0ght3d3cyLnd3dzEud2ViLXBsYXRmb3JtLnRlc3SCG3d3dzEud3d3Mi53
+ZWItcGxhdGZvcm0udGVzdIIbd3d3Mi53d3cyLndlYi1wbGF0Zm9ybS50ZXN0gh13
+d3cud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIed3d3Mi53d3cubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0gh53d3cud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCHnd3
+dzEud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIeeG4tLWx2ZS02bGFkLndlYi1w
+bGF0Zm9ybS50ZXN0gh53d3cud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3
+dzEud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzIud3d3Mi5ub3Qtd2Vi
+LXBsYXRmb3JtLnRlc3SCH3d3dzIud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
+H3d3dzEud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCInhuLS1sdmUtNmxhZC5u
+b3Qtd2ViLXBsYXRmb3JtLnRlc3SCInd3dy54bi0tbHZlLTZsYWQud2ViLXBsYXRm
+b3JtLnRlc3SCInhuLS1sdmUtNmxhZC53d3cud2ViLXBsYXRmb3JtLnRlc3SCI3hu
+LS1sdmUtNmxhZC53d3cyLndlYi1wbGF0Zm9ybS50ZXN0giN4bi0tbHZlLTZsYWQu
+d3d3MS53ZWItcGxhdGZvcm0udGVzdIIjd3d3Mi54bi0tbHZlLTZsYWQud2ViLXBs
+YXRmb3JtLnRlc3SCI3d3dzEueG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0
+giZ4bi0tbHZlLTZsYWQud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIImd3d3Lnhu
+LS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCJ3huLS1sdmUtNmxhZC53
+d3cyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIneG4tLWx2ZS02bGFkLnd3dzEubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0gid3d3cxLnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBs
+YXRmb3JtLnRlc3SCJ3d3dzIueG4tLWx2ZS02bGFkLm5vdC13ZWItcGxhdGZvcm0u
+dGVzdIIpeG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SC
+K3huLS1sdmUtNmxhZC54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3SCLXhu
+LS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3dy53ZWItcGxhdGZvcm0udGVzdIItd3d3
+LnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLndlYi1wbGF0Zm9ybS50ZXN0gi14bi0t
+bjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCLnd3dzIu
+eG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCLnhuLS1u
+OGo2ZHM1M2x3d2tycWh2MjhhLnd3dzEud2ViLXBsYXRmb3JtLnRlc3SCLnhuLS1u
+OGo2ZHM1M2x3d2tycWh2MjhhLnd3dzIud2ViLXBsYXRmb3JtLnRlc3SCLnd3dzEu
+eG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCL3huLS1s
+dmUtNmxhZC54bi0tbHZlLTZsYWQubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjF4bi0t
+bjhqNmRzNTNsd3drcnFodjI4YS53d3cubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjF3
+d3cueG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9ybS50ZXN0
+gjJ4bi0tbjhqNmRzNTNsd3drcnFodjI4YS53d3cyLm5vdC13ZWItcGxhdGZvcm0u
+dGVzdIIyeG4tLW44ajZkczUzbHd3a3JxaHYyOGEud3d3MS5ub3Qtd2ViLXBsYXRm
+b3JtLnRlc3SCMnd3dzIueG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0gjJ3d3cxLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLm5vdC13
+ZWItcGxhdGZvcm0udGVzdII2eG4tLWx2ZS02bGFkLnhuLS1uOGo2ZHM1M2x3d2ty
+cWh2MjhhLndlYi1wbGF0Zm9ybS50ZXN0gjZ4bi0tbjhqNmRzNTNsd3drcnFodjI4
+YS54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3SCOnhuLS1uOGo2ZHM1M2x3
+d2tycWh2MjhhLnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCOnhu
+LS1sdmUtNmxhZC54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRm
+b3JtLnRlc3SCQXhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnhuLS1uOGo2ZHM1M2x3
+d2tycWh2MjhhLndlYi1wbGF0Zm9ybS50ZXN0gkV4bi0tbjhqNmRzNTNsd3drcnFo
+djI4YS54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRl
+c3QwDQYJKoZIhvcNAQELBQADggEBAHQAEsdDNP2HTvhnWDTix0K+qPxh3xGcdxjV
+C+aSocLZmyCl7uiBq2L7VWc1lfqLtqU7UvfUIeh8tTcSWAIktX6TT2zOW0uvj/wi
+4gMtR9KHQ8Degqdbapcv6fdG9EHSNQdixaToCKKQHURKPXHWxfVALZkNM08PMWn3
+Ar3FRLlCnvKUNkRmuLiBmQbSt9/LsAHIW2QVpHV42nGxkgFbVXx2lKLzGiN4N+Vl
+UQ/KZpHUYhu3ItJ1N35nrLWds1DI23YpoXMhdHGeJd4lKiwg++ho65/88aeFaaSo
+DZNL//WdMjHTyn4OefNFMtj8NRLUCHH94g5kVaJa9C++GfEtvj8=
 -----END CERTIFICATE-----
diff --git a/third_party/wpt_tools/wpt/tools/serve/serve.py b/third_party/wpt_tools/wpt/tools/serve/serve.py
index fdfa603..80ccbc64 100644
--- a/third_party/wpt_tools/wpt/tools/serve/serve.py
+++ b/third_party/wpt_tools/wpt/tools/serve/serve.py
@@ -569,7 +569,6 @@
             ("GET", "*.any.worker.js", ClassicWorkerHandler),
             ("GET", "*.any.worker-module.js", ModuleWorkerHandler),
             ("GET", "*.asis", handlers.AsIsHandler),
-            ("GET", "/.well-known/origin-policy", handlers.PythonScriptHandler),
             ("*", "/.well-known/attribution-reporting/report-event-attribution", handlers.PythonScriptHandler),
             ("*", "/.well-known/attribution-reporting/debug/report-event-attribution", handlers.PythonScriptHandler),
             ("*", "/.well-known/attribution-reporting/report-aggregate-attribution", handlers.PythonScriptHandler),
@@ -960,10 +959,6 @@
     return {".".join(x) for x in chain(*(product(s, repeat=i) for i in range(1, depth+1)))}
 
 
-def _make_origin_policy_subdomains(limit: int) -> Set[str]:
-    return {"op%d" % x for x in range(1,limit+1)}
-
-
 _subdomains = {"www",
                "www1",
                "www2",
@@ -974,12 +969,6 @@
 
 _subdomains = _make_subdomains_product(_subdomains)
 
-# Origin policy subdomains need to not be reused by any other tests, since origin policies have
-# origin-wide impacts like installing a CSP or Feature Policy that could interfere with features
-# under test.
-# See https://github.com/web-platform-tests/rfcs/pull/44.
-_subdomains |= _make_origin_policy_subdomains(99)
-
 _not_subdomains = _make_subdomains_product(_not_subdomains)
 
 
diff --git a/third_party/wpt_tools/wpt/tools/wpt/browser.py b/third_party/wpt_tools/wpt/tools/wpt/browser.py
index cc3e793..9dd63eb 100644
--- a/third_party/wpt_tools/wpt/tools/wpt/browser.py
+++ b/third_party/wpt_tools/wpt/tools/wpt/browser.py
@@ -551,15 +551,19 @@
                 f"{self._chromium_platform_string}/{revision}/{filename}")
 
     def _get_latest_chromium_revision(self):
-        """Queries Chromium Snapshots and returns the latest Chromium revision number
-        for the current platform.
-        """
+        """Returns latest Chromium revision available for download."""
+        # This is only used if the user explicitly passes "latest" for the revision flag.
+        # The pinned revision is used by default to avoid unexpected failures as versions update.
         revision_url = ("https://storage.googleapis.com/chromium-browser-snapshots/"
                         f"{self._chromium_platform_string}/LAST_CHANGE")
         return get(revision_url).text.strip()
 
-    def _get_chromium_revision(self, filename, version=None):
-        """Format a Chromium Snapshots URL to download a browser component."""
+    def _get_pinned_chromium_revision(self):
+        """Returns the pinned Chromium revision number."""
+        return get("https://storage.googleapis.com/wpt-versions/pinned_chromium_revision").text.strip()
+
+    def _get_chromium_revision(self, filename=None, version=None):
+        """Retrieve a valid Chromium revision to download a browser component."""
 
         # If a specific version is passed as an argument, we will use it.
         if version is not None:
@@ -576,8 +580,8 @@
                     self.logger.warning("404: Unsuccessful attempt to download file "
                                         f"based on version. {url}")
         # If no URL was used in a previous install
-        # and no version was passed, use the latest Chromium revision.
-        revision = self._get_latest_chromium_revision()
+        # and no version was passed, use the pinned Chromium revision.
+        revision = self._get_pinned_chromium_revision()
 
         # If the url is successfully used to download/install, it will be used again
         # if another component is also installed during this run (browser/webdriver).
@@ -692,36 +696,12 @@
             self.logger.error(f"Cannot enable MojoJS: {e}")
             return None
 
-    def install_webdriver(self, dest=None, channel=None, browser_binary=None):
-        if dest is None:
-            dest = os.pwd
-
-        # A browser binary is needed so that the version can be detected.
-        # The ChromeDriver that is installed will match this version.
-        if browser_binary is None:
-            # If a browser binary path was not given, detect a valid path.
-            browser_binary = self.find_binary(channel=channel)
-            # We need a browser to version match, so if a browser binary path
-            # was not given and cannot be detected, raise an error.
-            if browser_binary is None:
-                raise FileNotFoundError("No browser binary detected. "
-                                        "Cannot install ChromeDriver without a browser version.")
-
-        version = self.version(browser_binary)
-        if version is None:
-            raise ValueError(f"Unable to detect browser version from binary at {browser_binary}. "
-                             "Cannot install ChromeDriver without a valid version to match.")
-
-        chromedriver_path = self.install_webdriver_by_version(version, dest)
-        return chromedriver_path
-
-    def install_webdriver_by_version(self, version, dest, channel=None):
+    def install_webdriver_by_version(self, version, dest, revision=None):
         dest = os.path.join(dest, self.product)
         self._remove_existing_chromedriver_binary(dest)
-
         # _get_webdriver_url is implemented differently for Chrome and Chromium because
         # they download their respective versions of ChromeDriver from different sources.
-        url = self._get_webdriver_url(version)
+        url = self._get_webdriver_url(version, revision)
         self.logger.info(f"Downloading ChromeDriver from {url}")
         unzip(get(url).raw, dest)
 
@@ -791,6 +771,20 @@
     def _chromium_package_name(self):
         return f"chrome-{self.platform.lower()}"
 
+    def _get_existing_browser_revision(self, venv_path, channel):
+        revision = None
+        try:
+            # A file referencing the revision number is saved with the binary.
+            # Check if this revision number exists and use it if it does.
+            path = os.path.join(self._get_browser_binary_dir(None, channel), "revision")
+            with open(path) as f:
+                revision = f.read().strip()
+        except FileNotFoundError:
+            # If there is no information about the revision downloaded,
+            # use the pinned revision.
+            revision = self._get_pinned_chromium_revision()
+        return revision
+
     def _find_binary_in_directory(self, directory):
         """Search for Chromium browser binary in a given directory."""
         if uname[0] == "Darwin":
@@ -802,7 +796,7 @@
         # find_executable will add .exe on Windows automatically.
         return find_executable("chrome", os.path.join(directory, self._chromium_package_name))
 
-    def _get_webdriver_url(self, version):
+    def _get_webdriver_url(self, version, revision=None):
         """Get Chromium Snapshots url to download Chromium ChromeDriver."""
         filename = f"chromedriver_{self._chromedriver_platform_string}.zip"
 
@@ -811,15 +805,28 @@
         # that url takes priority over trying to form another.
         if hasattr(self, "last_revision_used") and self.last_revision_used is not None:
             return self._build_snapshots_url(self.last_revision_used, filename)
-        revision = self._get_chromium_revision(filename, version)
+        if revision is None:
+            revision = self._get_chromium_revision(filename, version)
+        elif revision == "latest":
+            revision = self._get_latest_chromium_revision()
+        elif revision == "pinned":
+            revision = self._get_pinned_chromium_revision()
+
         return self._build_snapshots_url(revision, filename)
 
-    def download(self, dest=None, channel=None, rename=None, version=None):
+    def download(self, dest=None, channel=None, rename=None, version=None, revision=None):
         if dest is None:
             dest = self._get_browser_binary_dir(None, channel)
 
         filename = f"{self._chromium_package_name}.zip"
-        revision = self._get_chromium_revision(filename, version)
+
+        if revision is None:
+            revision = self._get_chromium_revision(filename, version)
+        elif revision == "latest":
+            revision = self._get_latest_chromium_revision()
+        elif revision == "pinned":
+            revision = self._get_pinned_chromium_revision()
+
         url = self._build_snapshots_url(revision, filename)
         self.logger.info(f"Downloading Chromium from {url}")
         resp = get(url)
@@ -829,19 +836,34 @@
 
         # Revision successfully used. Keep this revision if another component install is needed.
         self.last_revision_used = revision
+        with open(os.path.join(dest, "revision"), "w") as f:
+            f.write(revision)
         return installer_path
 
     def find_binary(self, venv_path=None, channel=None):
         return self._find_binary_in_directory(self._get_browser_binary_dir(venv_path, channel))
 
-    def install(self, dest=None, channel=None, version=None):
+    def install(self, dest=None, channel=None, version=None, revision=None):
         dest = self._get_browser_binary_dir(dest, channel)
-        installer_path = self.download(dest, channel, version=version)
+        installer_path = self.download(dest, channel, version=version, revision=revision)
         with open(installer_path, "rb") as f:
             unzip(f, dest)
         os.remove(installer_path)
         return self._find_binary_in_directory(dest)
 
+    def install_webdriver(self, dest=None, channel=None, browser_binary=None, revision=None):
+        if dest is None:
+            dest = os.pwd
+
+        if revision is None:
+            # If a revision was not given, we will need to detect the browser version.
+            # The ChromeDriver that is installed will match this version.
+            revision = self._get_existing_browser_revision(dest, channel)
+
+        chromedriver_path = self.install_webdriver_by_version(None, dest, revision)
+
+        return chromedriver_path
+
     def webdriver_supports_browser(self, webdriver_binary, browser_binary, browser_channel=None):
         """Check that the browser binary and ChromeDriver versions are a valid match."""
         browser_version = self.version(browser_binary)
@@ -887,7 +909,7 @@
             return "mac64_m1"
         return self._chromedriver_platform_string
 
-    def _get_webdriver_url(self, version):
+    def _get_webdriver_url(self, version, revision=None):
         """Get a ChromeDriver API URL to download a version of ChromeDriver that matches
         the browser binary version. Version selection is described here:
         https://chromedriver.chromium.org/downloads/version-selection"""
@@ -949,6 +971,30 @@
     def install(self, dest=None, channel=None):
         raise NotImplementedError("Installing of Chrome browser binary not implemented.")
 
+    def install_webdriver(self, dest=None, channel=None, browser_binary=None, revision=None):
+        if dest is None:
+            dest = os.pwd
+
+        # Detect the browser version.
+        # The ChromeDriver that is installed will match this version.
+        if browser_binary is None:
+            # If a browser binary path was not given, detect a valid path.
+            browser_binary = self.find_binary(channel=channel)
+            # We need a browser to version match, so if a browser binary path
+            # was not given and cannot be detected, raise an error.
+            if browser_binary is None:
+                raise FileNotFoundError("No browser binary detected. "
+                                        "Cannot install ChromeDriver without a browser version.")
+
+        version = self.version(browser_binary)
+        if version is None:
+            raise ValueError(f"Unable to detect browser version from binary at {browser_binary}. "
+                             " Cannot install ChromeDriver without a valid version to match.")
+
+        chromedriver_path = self.install_webdriver_by_version(version, dest, revision)
+
+        return chromedriver_path
+
     def webdriver_supports_browser(self, webdriver_binary, browser_binary, browser_channel):
         """Check that the browser binary and ChromeDriver versions are a valid match."""
         # TODO(DanielRyanSmith): The procedure for matching the browser and ChromeDriver
diff --git a/third_party/wpt_tools/wpt/tools/wpt/install.py b/third_party/wpt_tools/wpt/tools/wpt/install.py
index bebcec8..821ce86 100644
--- a/third_party/wpt_tools/wpt/tools/wpt/install.py
+++ b/third_party/wpt_tools/wpt/tools/wpt/install.py
@@ -55,6 +55,8 @@
                         "(only with --download-only)")
     parser.add_argument('-d', '--destination',
                         help='filesystem directory to place the component')
+    parser.add_argument('--revision', default=None,
+                        help='Chromium revision to install from snapshots')
     return parser
 
 
@@ -86,12 +88,16 @@
             raise argparse.ArgumentError(None,
                                          "No --destination argument, and no default for the environment")
 
+    if kwargs["revision"] is not None and browser != "chromium":
+        raise argparse.ArgumentError(None, "--revision flag cannot be used for non-Chromium browsers.")
+
     install(browser, kwargs["component"], destination, channel, logger=logger,
-            download_only=kwargs["download_only"], rename=kwargs["rename"])
+            download_only=kwargs["download_only"], rename=kwargs["rename"],
+            revision=kwargs["revision"])
 
 
 def install(name, component, destination, channel="nightly", logger=None, download_only=False,
-            rename=None):
+            rename=None, revision=None):
     if logger is None:
         import logging
         logger = logging.getLogger("install")
@@ -106,6 +112,9 @@
     kwargs = {}
     if download_only and rename:
         kwargs["rename"] = rename
+    if revision:
+        kwargs["revision"] = revision
+
     path = getattr(browser_cls(logger), method)(dest=destination, channel=channel, **kwargs)
     if path:
         logger.info('Binary %s as %s', "downloaded" if download_only else "installed", path)
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_ios.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_ios.py
index d870d668..85c98f29 100644
--- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_ios.py
+++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_ios.py
@@ -42,7 +42,8 @@
 
 
 def env_options():
-    return {}
+    # allow the use of host-resolver-rules in lieu of modifying /etc/hosts file
+    return {"server_host": "127.0.0.1"}
 
 
 class ChromeiOSBrowser(WebDriverBrowser):
@@ -53,4 +54,5 @@
     init_timeout = 120
 
     def make_command(self):
-        return [self.binary, f"--port={self.port}"] + self.webdriver_args
+        return ([self.webdriver_binary, f"--port={self.port}"] +
+                self.webdriver_args)
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_spki_certs.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_spki_certs.py
index 269b295..e1f133f 100644
--- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_spki_certs.py
+++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_spki_certs.py
@@ -2,7 +2,7 @@
 # DO NOT EDIT MANUALLY.
 
 # tools/certs/web-platform.test.pem
-WPT_FINGERPRINT = 'KGfpbZyVqJ6ztPLyXNAGcQwsl5OT7ecOpTKsgd01bNM='
+WPT_FINGERPRINT = 'XreVR++++c9QamuUZu0YWHyqsL3PJarhG/0h87zEimI='
 
 # signed-exchange/resources/127.0.0.1.sxg.pem
 SXG_WPT_FINGERPRINT = '0Rt4mT6SJXojEMHTnKnlJ/hBKMBcI4kteBlhR1eTTdk='
diff --git a/tools/binary_size/libsupersize/testdata/OWNERS b/tools/binary_size/libsupersize/testdata/OWNERS
deleted file mode 100644
index facfe6ea..0000000
--- a/tools/binary_size/libsupersize/testdata/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-foreman@coalhill.org
-
-# COMPONENT: Fake>ShouldNeverBeInSymbol
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 91c026e6..4eea89f 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -34108,6 +34108,8 @@
       label="For ReadingListEntryPoint feature."/>
   <suffix name="ReadingListMessages" label="For ReadingListMessages feature."/>
   <suffix name="ReopenTab" label="For ReopenTab feature."/>
+  <suffix name="RequestDesktopSiteAppMenu"
+      label="For the RequestDesktopSiteAppMenu feature."/>
   <suffix name="SharedHighlightingBuilder"
       label="For SharedHighlightingBuilder feature."/>
   <suffix name="SharedHighlightingReceiver"
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index a4b0548..d17df92 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -76044,6 +76044,33 @@
   <int value="5" label="No Matching HTTPS, HSTS enabled"/>
 </enum>
 
+<enum name="PasswordManagerImportEntryStatus">
+  <int value="0" label="None"/>
+  <int value="1" label="Unknown error"/>
+  <int value="2" label="Missing password"/>
+  <int value="3" label="Missing URL"/>
+  <int value="4" label="Invalid URL"/>
+  <int value="5" label="Non-ASCII URL"/>
+  <int value="6" label="Long URL"/>
+  <int value="7" label="Long password"/>
+  <int value="8" label="Long username"/>
+  <int value="9" label="Conflict profile"/>
+  <int value="10" label="Conflict account"/>
+</enum>
+
+<enum name="PasswordManagerImportResultsStatus">
+  <int value="0" label="None"/>
+  <int value="1" label="Unknown error"/>
+  <int value="2" label="Success"/>
+  <int value="3" label="I/O error"/>
+  <int value="4" label="Bad format"/>
+  <int value="5" label="Dismissed"/>
+  <int value="6" label="Chosen file exceeds max file size"/>
+  <int value="7" label="Import already active"/>
+  <int value="8" label="Import already active"/>
+  <int value="9" label="Number of allowed passwords exceeded"/>
+</enum>
+
 <enum name="PasswordManagerMatchedFormType">
   <int value="0" label="Exact match"/>
   <int value="1" label="Public suffix match">
@@ -89140,6 +89167,15 @@
   <int value="1" label="Managed account"/>
 </enum>
 
+<enum name="SigninAndroidAddAccountState">
+  <int value="0" label="Requested"/>
+  <int value="1" label="Started"/>
+  <int value="2" label="Succeeded"/>
+  <int value="3" label="Failed"/>
+  <int value="4" label="Cancelled"/>
+  <int value="5" label="Returned null account name"/>
+</enum>
+
 <enum name="SigninChoice">
   <obsolete>
     Removed in M91 since the data is not monitored.
diff --git a/tools/metrics/histograms/metadata/arc/histograms.xml b/tools/metrics/histograms/metadata/arc/histograms.xml
index 1b0eafd..baf228e 100644
--- a/tools/metrics/histograms/metadata/arc/histograms.xml
+++ b/tools/metrics/histograms/metadata/arc/histograms.xml
@@ -1958,7 +1958,7 @@
 </histogram>
 
 <histogram name="Arc.Supervision.Transition.Result"
-    enum="ArcSupervisionTransitionResult" expires_after="2022-12-25">
+    enum="ArcSupervisionTransitionResult" expires_after="2023-10-04">
   <owner>mhasank@chromium.org</owner>
   <owner>arc-commercial@google.com</owner>
   <summary>
@@ -1968,7 +1968,7 @@
 </histogram>
 
 <histogram name="Arc.Supervision.Transition.Screen.Success.TimeDelta"
-    units="ms" expires_after="2022-10-04">
+    units="ms" expires_after="2023-10-04">
   <owner>mhasank@chromium.org</owner>
   <owner>arc-commercial@google.com</owner>
   <summary>
@@ -1978,7 +1978,7 @@
 </histogram>
 
 <histogram name="Arc.Supervision.Transition.Screen.Successful"
-    enum="BooleanSuccess" expires_after="2022-12-25">
+    enum="BooleanSuccess" expires_after="2023-10-24">
   <owner>mhasank@chromium.org</owner>
   <owner>arc-commercial@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/feature_engagement/histograms.xml b/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
index 2edce0d..eef7c0d 100644
--- a/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
+++ b/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
@@ -196,6 +196,9 @@
   <variant name="IPH_ReadLaterContextMenu"
       summary="read later context menu entry point"/>
   <variant name="IPH_ReopenTab" summary="reopening closed tabs"/>
+  <variant name="IPH_RequestDesktopSiteAppMenu"
+      summary="educating users about using the desktop site app menu item to
+               add a site-level exception."/>
   <variant name="IPH_SharedHighlightingBuilder"
       summary="the in product help message to notify the user that the share
                action can preemptively share a link-to-text"/>
diff --git a/tools/metrics/histograms/metadata/notifications/histograms.xml b/tools/metrics/histograms/metadata/notifications/histograms.xml
index 0b74ac4..bcc6e0c 100644
--- a/tools/metrics/histograms/metadata/notifications/histograms.xml
+++ b/tools/metrics/histograms/metadata/notifications/histograms.xml
@@ -545,47 +545,51 @@
 </histogram>
 
 <histogram name="Notifications.NotificationHelper.ComServerModuleStatus"
-    enum="NotificationHelperComServerModuleStatus" expires_after="M87">
+    enum="NotificationHelperComServerModuleStatus" expires_after="2023-09-01">
   <owner>finnur@chromium.org</owner>
   <summary>
     The execute status of a ComServerModule class instance. Logged whenever a
-    notification_helper process is launched by Windows.
+    notification_helper process is launched by Windows. Note: Not logged after
+    M87 until end of August 2022.
   </summary>
 </histogram>
 
 <histogram
     name="Notifications.NotificationHelper.NotificationActivatorPrimaryStatus"
     enum="NotificationHelperNotificationActivatorPrimaryStatus"
-    expires_after="M85">
+    expires_after="2023-09-01">
   <owner>chengx@chromium.org</owner>
   <owner>finnur@chromium.org</owner>
   <summary>
     The primary execute status of NotificationActivator::Activate. Logged
-    whenever a notification_helper process is launched by Windows.
+    whenever a notification_helper process is launched by Windows. Note: Not
+    logged after M85 until end of August 2022.
   </summary>
 </histogram>
 
 <histogram
     name="Notifications.NotificationHelper.NotificationActivatorSecondaryStatus"
     enum="NotificationHelperNotificationActivatorSecondaryStatus"
-    expires_after="M85">
+    expires_after="2023-09-01">
   <owner>chengx@chromium.org</owner>
   <owner>finnur@chromium.org</owner>
   <summary>
     The secondary execute status of NotificationActivator::Activate. Logged
-    whenever a notification_helper process is launched by Windows.
+    whenever a notification_helper process is launched by Windows. Note: Not
+    logged after M85 until end of August 2022.
   </summary>
 </histogram>
 
 <histogram name="Notifications.NotificationHelper.ServerRuntime" units="ms"
-    expires_after="M87">
+    expires_after="2023-09-01">
   <owner>finnur@chromium.org</owner>
   <summary>
     The runtime of the notification_helper server process. This process is
     created when a notification is activated from the Windows Action Center.
     Once created, this process does some COM class registration work, so that
     Windows can call certain APIs to handle the notification activation. Upon
-    finishing the API calls, Windows signals this process to exit.
+    finishing the API calls, Windows signals this process to exit. Note: Not
+    logged after M87 until end of August 2022.
   </summary>
 </histogram>
 
@@ -1000,40 +1004,43 @@
 </histogram>
 
 <histogram name="Notifications.Windows.ActivationStatus"
-    enum="WindowsNotificationActivationStatus" expires_after="2022-01-02">
+    enum="WindowsNotificationActivationStatus" expires_after="2023-09-01">
   <owner>finnur@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <owner>chengx@chromium.org</owner>
   <summary>
     The status of Activation requests in NotificationPlatformBridgeWin (Windows
-    only). Logged whenever an activation from a notification occurs.
+    only). Logged whenever an activation from a notification occurs. Note: Not
+    logged from January 2021 to end of August 2022.
   </summary>
 </histogram>
 
 <histogram name="Notifications.Windows.CloseStatus"
-    enum="WindowsNotificationCloseStatus" expires_after="M98">
+    enum="WindowsNotificationCloseStatus" expires_after="2023-09-01">
   <owner>finnur@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
     The status of Close requests in NotificationPlatformBridgeWin (Windows
-    only). Logged whenever a notification is closed.
+    only). Logged whenever a notification is closed. Note: Not logged after M98
+    until end of August 2022.
   </summary>
 </histogram>
 
 <histogram name="Notifications.Windows.CreateToastManagerErrorCode"
-    enum="Hresult" expires_after="M98">
+    enum="Hresult" expires_after="2023-09-01">
   <owner>finnur@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
     The HRESULT returned by the Windows Action Center, when trying to create a
     toast manager fails. This provides a more detailed error in the cases the
     histogram Notifications.Windows.DisplayStatus reported
-    CREATE_TOAST_NOTIFIER_WITH_ID_FAILED.
+    CREATE_TOAST_NOTIFIER_WITH_ID_FAILED. Note: Not logged after M89 until end
+    of August 2022.
   </summary>
 </histogram>
 
 <histogram name="Notifications.Windows.DisplayFailure" enum="Hresult"
-    expires_after="2023-01-15">
+    expires_after="2023-09-01">
   <owner>finnur@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
@@ -1043,7 +1050,7 @@
 </histogram>
 
 <histogram name="Notifications.Windows.DisplayStatus"
-    enum="WindowsNotificationDisplayStatus" expires_after="2022-01-02">
+    enum="WindowsNotificationDisplayStatus" expires_after="2023-09-01">
   <owner>finnur@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
@@ -1051,56 +1058,61 @@
     only). Logged whenever a notification is displayed. For a more detailed
     error about CREATE_TOAST_NOTIFIER_WITH_ID_FAILED and SHOWING_TOAST_FAILED,
     see Notification.Windows histograms CreateToastManagerErrorCode and
-    ShowFailedErrorCode (respectively).
+    ShowFailedErrorCode (respectively). Note: Not logged between January 2022
+    until end of August 2022.
   </summary>
 </histogram>
 
 <histogram name="Notifications.Windows.GetDisplayedLaunchIdStatus"
-    enum="WindowsNotificationGetDisplayedLaunchIdStatus" expires_after="M98">
+    enum="WindowsNotificationGetDisplayedLaunchIdStatus"
+    expires_after="2023-09-01">
   <owner>finnur@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
     The status of decoding launch ids while processing a GetDisplayed requests
     in NotificationPlatformBridgeWin (Windows only). Logged whenever a request
-    to retrieve all displayed notifications comes in.
+    to retrieve all displayed notifications comes in. Note: Not logged after M98
+    until end of August 2022.
   </summary>
 </histogram>
 
 <histogram name="Notifications.Windows.GetDisplayedStatus"
-    enum="WindowsNotificationGetDisplayedStatus" expires_after="M98">
+    enum="WindowsNotificationGetDisplayedStatus" expires_after="2023-09-01">
   <owner>finnur@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
     The status of GetDisplayedStatus requests in NotificationPlatformBridgeWin
     (Windows only). Logged whenever a request to retrieve all displayed
-    notifications comes in.
+    notifications comes in. Note: Not logged after M98 until end of August 2022.
   </summary>
 </histogram>
 
 <histogram name="Notifications.Windows.GetNotificationLaunchIdStatus"
     enum="WindowsNotificationGetNotificationLaunchIdStatus"
-    expires_after="2022-01-02">
+    expires_after="2023-09-01">
   <owner>finnur@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
     The status of GetNotificationLaunchId requests in
     NotificationPlatformBridgeWin (Windows only). Logged whenever a request to
-    decode the GetNotificationLaunchId comes in.
+    decode the GetNotificationLaunchId comes in. Note: Not logged between
+    January 2022 until end of August 2022.
   </summary>
 </histogram>
 
 <histogram name="Notifications.Windows.GetSettingPolicy"
-    enum="WindowsNotificationGetSettingPolicy" expires_after="M98">
+    enum="WindowsNotificationGetSettingPolicy" expires_after="2023-09-01">
   <owner>finnur@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
     The policy value provided by get_Setting in NotificationPlatformBridgeWin
     (Windows only). Logged whenever a request to show a notification comes in.
+    Note: Not logged after M98 until end of August 2022.
   </summary>
 </histogram>
 
 <histogram name="Notifications.Windows.GetSettingPolicyStartup"
-    enum="WindowsNotificationGetSettingPolicy" expires_after="2022-08-21">
+    enum="WindowsNotificationGetSettingPolicy" expires_after="2023-09-01">
   <owner>finnur@chromium.org</owner>
   <owner>knollr@chromium.org</owner>
   <owner>peter@chromium.org</owner>
@@ -1111,7 +1123,7 @@
 </histogram>
 
 <histogram name="Notifications.Windows.GetSettingStatus"
-    enum="WindowsNotificationGetSettingStatus" expires_after="2022-08-28">
+    enum="WindowsNotificationGetSettingStatus" expires_after="2023-09-01">
   <owner>finnur@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
@@ -1121,7 +1133,7 @@
 </histogram>
 
 <histogram name="Notifications.Windows.GetSettingStatusStartup"
-    enum="WindowsNotificationGetSettingStatus" expires_after="2022-09-11">
+    enum="WindowsNotificationGetSettingStatus" expires_after="2023-09-01">
   <owner>finnur@chromium.org</owner>
   <owner>knollr@chromium.org</owner>
   <owner>peter@chromium.org</owner>
@@ -1132,75 +1144,84 @@
 </histogram>
 
 <histogram name="Notifications.Windows.HandleEventStatus"
-    enum="WindowsNotificationHandleEventStatus" expires_after="2022-01-02">
+    enum="WindowsNotificationHandleEventStatus" expires_after="2023-09-01">
   <owner>finnur@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
     The status of HandleEvent requests in NotificationPlatformBridgeWin (Windows
-    only). Logged whenever a notification event is being handled.
+    only). Logged whenever a notification event is being handled. Note: Not
+    logged between January 2022 and end of August 2022.
   </summary>
 </histogram>
 
 <histogram name="Notifications.Windows.HistoryStatus"
-    enum="WindowsNotificationHistoryStatus" expires_after="M98">
+    enum="WindowsNotificationHistoryStatus" expires_after="2023-09-01">
   <owner>finnur@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
     The status of History requests in NotificationPlatformBridgeWin (Windows
-    only). Logged whenever history is requested for notifications.
+    only). Logged whenever history is requested for notifications. Note: Not
+    logged after M98 until end of August 2022.
   </summary>
 </histogram>
 
 <histogram name="Notifications.Windows.LaunchIdDecodeStatus"
-    enum="WindowsNotificationLaunchIdDecodeStatus" expires_after="M87">
+    enum="WindowsNotificationLaunchIdDecodeStatus" expires_after="2023-09-01">
   <owner>chengx@chromium.org</owner>
   <owner>finnur@chromium.org</owner>
   <summary>
     Used to indicate the status of decoding an input launch id string (Windows
-    only). Logged whenever a notification event is being handled.
+    only). Logged whenever a notification event is being handled. Note: Not
+    logged after M87 until end of August 2022.
   </summary>
 </histogram>
 
 <histogram name="Notifications.Windows.OnFailedStatus"
-    enum="WindowsNotificationOnFailedStatus" expires_after="M98">
+    enum="WindowsNotificationOnFailedStatus" expires_after="2023-09-01">
   <owner>chengx@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
     The status of OnFailed requests in NotificationPlatformBridgeWin (Windows
-    only). Logged whenever a failed event is handled.
+    only). Logged whenever a failed event is handled. Note: Not logged after M98
+    until end of August 2022.
   </summary>
 </histogram>
 
 <histogram name="Notifications.Windows.SetReadyCallbackStatus2"
-    enum="WindowsNotificationSetReadyCallbackStatus2" expires_after="M98">
+    enum="WindowsNotificationSetReadyCallbackStatus2"
+    expires_after="2023-09-01">
   <owner>chengx@chromium.org</owner>
   <owner>finnur@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
     The status of SetReadyCallback requests in NotificationPlatformBridgeWin
-    (Windows only). Logged once at startup.
+    (Windows only). Logged once at startup. Note: Not logged after M98 until end
+    of August 2022.
   </summary>
 </histogram>
 
 <histogram name="Notifications.Windows.ShowFailedErrorCode" enum="Hresult"
-    expires_after="M98">
+    expires_after="2023-09-01">
   <owner>finnur@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
     The HRESULT returned by the Windows Action Center, when trying to create a
     toast manager fails. This provides a more detailed error in the cases the
     histogram Notifications.Windows.DisplayStatus reported SHOWING_TOAST_FAILED.
+    Note: Not logged after M98 until end of August 2022.
   </summary>
 </histogram>
 
 <histogram name="Notifications.Windows.StartMenuShortcutStatus"
-    enum="WindowsNotificationStartMenuShortcutStatus" expires_after="M98">
+    enum="WindowsNotificationStartMenuShortcutStatus"
+    expires_after="2023-09-01">
   <owner>chengx@chromium.org</owner>
   <owner>finnur@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
     Used to indicate the status of start menu shortcut (Windows only). Logged
-    whenever a notification display attempt is made.
+    whenever a notification display attempt is made. Note: Not logged after M98
+    until end of August 2022.
   </summary>
 </histogram>
 
diff --git a/tools/metrics/histograms/metadata/optimization/histograms.xml b/tools/metrics/histograms/metadata/optimization/histograms.xml
index e51f36a91..0fad1ce 100644
--- a/tools/metrics/histograms/metadata/optimization/histograms.xml
+++ b/tools/metrics/histograms/metadata/optimization/histograms.xml
@@ -51,6 +51,8 @@
   <variant name="SegmentationNewTab" summary="Segmentation: New tab page user"/>
   <variant name="SegmentationQueryTiles" summary="Query tiles"/>
   <variant name="SegmentationShare" summary="Segmentation: Share user"/>
+  <variant name="SegmentationShoppingUser"
+      summary="Segmentation: Shopping user"/>
   <variant name="SegmentationVoice" summary="Segmentation: Voice user"/>
   <variant name="TextClassifier" summary="Smart text selection"/>
 </variants>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml
index 9b9d704a..6f42070 100644
--- a/tools/metrics/histograms/metadata/password/histograms.xml
+++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -1638,6 +1638,18 @@
   </summary>
 </histogram>
 
+<histogram name="PasswordManager.ImportEntryStatus"
+    enum="PasswordManagerImportEntryStatus" expires_after="2023-02-01">
+  <owner>eliaskh@chromium.org</owner>
+  <owner>natiahlyi@google.com</owner>
+  <summary>
+    Tracks the individual status of a single password entry from the provided
+    CSV File after it has been processed in the Passwords Import flow in
+    settings UI. Recorded when a single entry has been processed and checked for
+    errors or missing fields. Recording occurs within password settings.
+  </summary>
+</histogram>
+
 <histogram name="PasswordManager.ImportFileSize" units="bytes"
     expires_after="2023-02-01">
   <owner>eliaskh@chromium.org</owner>
@@ -1649,6 +1661,17 @@
   </summary>
 </histogram>
 
+<histogram name="PasswordManager.ImportResultsStatus"
+    enum="PasswordManagerImportResultsStatus" expires_after="2023-02-01">
+  <owner>eliaskh@chromium.org</owner>
+  <owner>natiahlyi@google.com</owner>
+  <summary>
+    Tracks the final outcome status of importing a CSV File to Chrome Password
+    Manager in settings UI. Recorded when the import flow finishes within
+    password settings. This can be either successfuly or due to an error.
+  </summary>
+</histogram>
+
 <histogram name="PasswordManager.iOS.InfoBar.PasswordSave" enum="Boolean"
     expires_after="2022-10-16">
   <owner>djean@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/signin/histograms.xml b/tools/metrics/histograms/metadata/signin/histograms.xml
index fc68ba5..6880e10 100644
--- a/tools/metrics/histograms/metadata/signin/histograms.xml
+++ b/tools/metrics/histograms/metadata/signin/histograms.xml
@@ -197,6 +197,16 @@
   </summary>
 </histogram>
 
+<histogram name="Signin.AddAccountState" enum="SigninAndroidAddAccountState"
+    expires_after="2023-08-18">
+  <owner>triploblastic@chromium.org</owner>
+  <owner>chrome-signin-team@google.com</owner>
+  <summary>
+    This histogram records states in the add account process launched from
+    Chrome on Android.
+  </summary>
+</histogram>
+
 <histogram name="Signin.AndroidAccountInfoFetchTime" units="ms"
     expires_after="2023-01-01">
   <owner>aliceywang@chromium.org</owner>
diff --git a/tools/perf/contrib/blink_layoutng_perf/OWNERS b/tools/perf/contrib/blink_layoutng_perf/OWNERS
index d80a064..51c6a57d 100644
--- a/tools/perf/contrib/blink_layoutng_perf/OWNERS
+++ b/tools/perf/contrib/blink_layoutng_perf/OWNERS
@@ -1,2 +1 @@
-eae@chromium.org
 cbiesinger@chromium.org
diff --git a/tools/perf/contrib/blink_perf_cmdline/OWNERS b/tools/perf/contrib/blink_perf_cmdline/OWNERS
index 33952d7..877f13a 100644
--- a/tools/perf/contrib/blink_perf_cmdline/OWNERS
+++ b/tools/perf/contrib/blink_perf_cmdline/OWNERS
@@ -1,2 +1 @@
-charliea@chromium.org
 wangxianzhu@chromium.org
diff --git a/tools/perf/contrib/tracing/OWNERS b/tools/perf/contrib/tracing/OWNERS
index 6f75aa01..3dab710e 100644
--- a/tools/perf/contrib/tracing/OWNERS
+++ b/tools/perf/contrib/tracing/OWNERS
@@ -1,2 +1 @@
 oysteine@chromium.org
-zhenw@chromium.org
diff --git a/tools/perf/generate_perf_sharding.py b/tools/perf/generate_perf_sharding.py
index a6049eaf..9340580 100755
--- a/tools/perf/generate_perf_sharding.py
+++ b/tools/perf/generate_perf_sharding.py
@@ -352,7 +352,7 @@
         'UNSCHEDULED_{benchmark}'.format(benchmark=benchmark))
 
   for error in errors:
-    print('*', textwrap.fill(error, 70), '\n', file=sys.stderr)
+    print('*', error, '\n', file=sys.stderr)
   if errors:
     return 1
   return 0
diff --git a/tools/resultdb/OWNERS b/tools/resultdb/OWNERS
index e5677cc14..4e64a19 100644
--- a/tools/resultdb/OWNERS
+++ b/tools/resultdb/OWNERS
@@ -1,3 +1,2 @@
 chanli@chromium.org
-ddoman@chromium.org
 robertocn@chromium.org
diff --git a/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.cc b/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.cc
index bcde64fd..4f10a38c 100644
--- a/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.cc
+++ b/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.cc
@@ -6,6 +6,7 @@
 
 #include <string>
 
+#include "ui/events/event_constants.h"
 #include "ui/events/keycodes/dom/dom_code.h"
 #include "ui/events/keycodes/dom/dom_key.h"
 #include "ui/events/keycodes/keyboard_code_conversion.h"
@@ -45,6 +46,32 @@
                                       int flags,
                                       DomKey* out_dom_key,
                                       KeyboardCode* out_key_code) const {
+  if (!custom_lookup_.empty()) {
+    for (const auto& entry : custom_lookup_) {
+      if (entry.dom_code == dom_code) {
+        int shift_down = ((flags & EF_SHIFT_DOWN) == EF_SHIFT_DOWN);
+        char16_t ch;
+        if (shift_down) {
+          ch = entry.character_shifted;
+        } else {
+          ch = entry.character;
+        }
+        if ((flags & EF_CAPS_LOCK_ON) == EF_CAPS_LOCK_ON) {
+          if ((ch >= 'a') && (ch <= 'z')) {
+            if (shift_down) {
+              ch = entry.character;
+            } else {
+              ch = entry.character_shifted;
+            }
+          }
+        }
+        *out_dom_key = DomKey::FromCharacter(ch);
+        *out_key_code = entry.key_code;
+        return true;
+      }
+    }
+  }
+
   return DomCodeToUsLayoutDomKey(dom_code, flags, out_dom_key, out_key_code);
 }
 
@@ -53,4 +80,9 @@
   std::move(closure).Run();
 }
 
+void StubKeyboardLayoutEngine::SetCustomLookupTableForTesting(
+    const std::vector<CustomLookupEntry>& table) {
+  custom_lookup_ = table;
+}
+
 }  // namespace ui
diff --git a/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h b/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h
index 3cfe7dd..8f6c959 100644
--- a/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h
+++ b/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h
@@ -5,7 +5,10 @@
 #ifndef UI_EVENTS_OZONE_LAYOUT_STUB_STUB_KEYBOARD_LAYOUT_ENGINE_H_
 #define UI_EVENTS_OZONE_LAYOUT_STUB_STUB_KEYBOARD_LAYOUT_ENGINE_H_
 
+#include <vector>
+
 #include "base/component_export.h"
+#include "ui/events/keycodes/keyboard_codes_posix.h"
 #include "ui/events/ozone/layout/keyboard_layout_engine.h"
 
 namespace ui {
@@ -13,6 +16,13 @@
 class COMPONENT_EXPORT(EVENTS_OZONE_LAYOUT) StubKeyboardLayoutEngine
     : public KeyboardLayoutEngine {
  public:
+  struct CustomLookupEntry {
+    ui::DomCode dom_code;
+    char16_t character;
+    char16_t character_shifted;
+    ui::KeyboardCode key_code;
+  };
+
   StubKeyboardLayoutEngine();
   ~StubKeyboardLayoutEngine() override;
 
@@ -28,6 +38,12 @@
               DomKey* dom_key,
               KeyboardCode* key_code) const override;
   void SetInitCallbackForTest(base::OnceClosure closure) override;
+
+  void SetCustomLookupTableForTesting(
+      const std::vector<CustomLookupEntry>& table);
+
+ private:
+  std::vector<CustomLookupEntry> custom_lookup_;
 };
 
 }  // namespace ui
diff --git a/ui/gl/gl_image_native_pixmap.cc b/ui/gl/gl_image_native_pixmap.cc
index b68eb27..7990afb 100644
--- a/ui/gl/gl_image_native_pixmap.cc
+++ b/ui/gl/gl_image_native_pixmap.cc
@@ -234,12 +234,12 @@
       attrs.push_back(EGL_NONE);
     }
 
-    did_initialize_ = true;
     if (!GLImageEGL::Initialize(EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
                                 static_cast<EGLClientBuffer>(nullptr),
                                 &attrs[0])) {
       return false;
     }
+    did_initialize_ = true;
   }
 
   pixmap_ = pixmap;
@@ -268,9 +268,13 @@
       reinterpret_cast<EGLContext>(current_context->GetHandle());
   DCHECK_NE(context_handle, EGL_NO_CONTEXT);
 
-  return GLImageEGL::Initialize(context_handle, EGL_GL_TEXTURE_2D_KHR,
-                                reinterpret_cast<EGLClientBuffer>(texture_id),
-                                nullptr);
+  if (!GLImageEGL::Initialize(context_handle, EGL_GL_TEXTURE_2D_KHR,
+                              reinterpret_cast<EGLClientBuffer>(texture_id),
+                              nullptr)) {
+    return false;
+  }
+  did_initialize_ = true;
+  return true;
 }
 
 gfx::NativePixmapHandle GLImageNativePixmap::ExportHandle() {
diff --git a/ui/gtk/gtk_ui_platform_stub.cc b/ui/gtk/gtk_ui_platform_stub.cc
index 5f01c8b..bfd10bc7 100644
--- a/ui/gtk/gtk_ui_platform_stub.cc
+++ b/ui/gtk/gtk_ui_platform_stub.cc
@@ -5,6 +5,7 @@
 #include "ui/gtk/gtk_ui_platform_stub.h"
 
 #include "base/callback.h"
+#include "ui/base/ime/linux/linux_input_method_context.h"
 
 namespace gtk {
 
diff --git a/ui/views/controls/menu/menu_cocoa_watcher_mac.h b/ui/views/controls/menu/menu_cocoa_watcher_mac.h
index 548a270..652ccec 100644
--- a/ui/views/controls/menu/menu_cocoa_watcher_mac.h
+++ b/ui/views/controls/menu/menu_cocoa_watcher_mac.h
@@ -12,6 +12,12 @@
 
 namespace views {
 
+enum class MacNotificationFilter {
+  DontIgnoreNotifications,
+  IgnoreWorkspaceNotifications,
+  IgnoreAllNotifications
+};
+
 // This class executes a callback when a native menu begins tracking, or when a
 // new window takes focus. With native menus, each one automatically closes when
 // a new one begins tracking, and MenuPreTargetHandlerAura::OnWindowActivated()
@@ -19,6 +25,9 @@
 // correct behavior.
 class VIEWS_EXPORT MenuCocoaWatcherMac {
  public:
+  // Forces all MenuCocoaWatcherMac instances to ignore certain NSNotifications.
+  static void SetNotificationFilterForTesting(MacNotificationFilter filter);
+
   explicit MenuCocoaWatcherMac(base::OnceClosure callback);
 
   MenuCocoaWatcherMac(const MenuCocoaWatcherMac&) = delete;
diff --git a/ui/views/controls/menu/menu_cocoa_watcher_mac.mm b/ui/views/controls/menu/menu_cocoa_watcher_mac.mm
index 541ae03..ff67677f7 100644
--- a/ui/views/controls/menu/menu_cocoa_watcher_mac.mm
+++ b/ui/views/controls/menu/menu_cocoa_watcher_mac.mm
@@ -10,6 +10,31 @@
 #import <utility>
 
 namespace views {
+namespace {
+
+// Returns the global notification filter.
+MacNotificationFilter& NotificationFilterInternal() {
+  static MacNotificationFilter filter =
+      MacNotificationFilter::DontIgnoreNotifications;
+  return filter;
+}
+
+// Returns YES if `notification` should be ignored based on the current value of
+// the notification filter.
+BOOL ShouldIgnoreNotification(NSNotification* notification) {
+  switch (NotificationFilterInternal()) {
+    case MacNotificationFilter::DontIgnoreNotifications:
+      return NO;
+    case MacNotificationFilter::IgnoreWorkspaceNotifications:
+      return [[notification name]
+          isEqualToString:NSWorkspaceDidActivateApplicationNotification];
+    case MacNotificationFilter::IgnoreAllNotifications:
+      return YES;
+  }
+
+  return NO;
+}
+}  // namespace
 
 MenuCocoaWatcherMac::MenuCocoaWatcherMac(base::OnceClosure callback)
     : callback_(std::move(callback)) {
@@ -18,6 +43,9 @@
                   object:nil
                    queue:nil
               usingBlock:^(NSNotification* notification) {
+                if (ShouldIgnoreNotification(notification))
+                  return;
+
                 ExecuteCallback();
               }];
   observer_token_new_window_focus_ = [[NSNotificationCenter defaultCenter]
@@ -25,6 +53,9 @@
                   object:nil
                    queue:nil
               usingBlock:^(NSNotification* notification) {
+                if (ShouldIgnoreNotification(notification))
+                  return;
+
                 ExecuteCallback();
               }];
   observer_token_app_change_ =
@@ -33,6 +64,9 @@
                       object:nil
                        queue:nil
                   usingBlock:^(NSNotification* notification) {
+                    if (ShouldIgnoreNotification(notification))
+                      return;
+
                     // Only destroy menus if the browser is losing focus, not if
                     // it's gaining focus. This is to ensure that we can invoke
                     // a context menu while focused on another app, and still be
@@ -52,6 +86,11 @@
       removeObserver:observer_token_app_change_];
 }
 
+void MenuCocoaWatcherMac::SetNotificationFilterForTesting(
+    MacNotificationFilter filter) {
+  NotificationFilterInternal() = filter;
+}
+
 void MenuCocoaWatcherMac::ExecuteCallback() {
   __block base::OnceClosure callback = std::move(callback_);
   dispatch_async(dispatch_get_main_queue(), ^{
diff --git a/ui/views/controls/menu/menu_runner_cocoa_unittest.mm b/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
index 95b0d17..14f6928 100644
--- a/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
+++ b/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
@@ -19,11 +19,11 @@
 #include "ui/base/models/simple_menu_model.h"
 #include "ui/events/event_utils.h"
 #import "ui/events/test/cocoa_test_event_utils.h"
+#include "ui/views/controls/menu/menu_cocoa_watcher_mac.h"
 #include "ui/views/controls/menu/menu_runner_impl_adapter.h"
 #include "ui/views/test/views_test_base.h"
 
-namespace views {
-namespace test {
+namespace views::test {
 namespace {
 
 constexpr int kTestCommandId = 0;
@@ -135,6 +135,10 @@
       runner_ = nullptr;
     }
 
+    // Clean up for tests that set the notification filter.
+    MenuCocoaWatcherMac::SetNotificationFilterForTesting(
+        MacNotificationFilter::DontIgnoreNotifications);
+
     parent_->CloseNow();
     ViewsTestBase::TearDown();
   }
@@ -143,16 +147,28 @@
 
   // Runs the menu after registering |callback| as the menu open callback.
   void RunMenu(base::OnceClosure callback) {
+    MenuCocoaWatcherMac::SetNotificationFilterForTesting(
+        MacNotificationFilter::IgnoreAllNotifications);
+
+    base::OnceClosure wrapped_callback = base::BindOnce(
+        [](base::OnceClosure cb) {
+          // Ignore app activation notifications while the test is running (all
+          // others are OK).
+          MenuCocoaWatcherMac::SetNotificationFilterForTesting(
+              MacNotificationFilter::IgnoreWorkspaceNotifications);
+          std::move(cb).Run();
+        },
+        std::move(callback));
     if (IsAsync()) {
       // Cancelling an async menu under MenuControllerCocoa::OpenMenuImpl()
       // (which invokes WillShowMenu()) will cause a UAF when that same function
       // tries to show the menu. So post a task instead.
-      base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                    std::move(callback));
+      base::ThreadTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE, std::move(wrapped_callback));
     } else {
       menu_->set_menu_open_callback(
           base::BindOnce(&MenuRunnerCocoaTest::RunMenuWrapperCallback,
-                         base::Unretained(this), std::move(callback)));
+                         base::Unretained(this), std::move(wrapped_callback)));
     }
 
     runner_->RunMenuAt(parent_, nullptr, gfx::Rect(),
@@ -164,11 +180,21 @@
   // Runs then cancels a combobox menu and captures the frame of the anchoring
   // view.
   void RunMenuAt(const gfx::Rect& anchor) {
+    MenuCocoaWatcherMac::SetNotificationFilterForTesting(
+        MacNotificationFilter::IgnoreAllNotifications);
+
     last_anchor_frame_ = NSZeroRect;
 
-    base::OnceClosure callback =
-        base::BindOnce(&MenuRunnerCocoaTest::ComboboxRunMenuAtCallback,
-                       base::Unretained(this));
+    base::OnceClosure callback = base::BindOnce(
+        [](MenuRunnerCocoaTest* test) {
+          // Ignore app activation notifications while the test is running (all
+          // others are OK).
+          MenuCocoaWatcherMac::SetNotificationFilterForTesting(
+              MacNotificationFilter::IgnoreWorkspaceNotifications);
+          test->ComboboxRunMenuAtCallback();
+        },
+        base::Unretained(this));
+
     if (IsAsync()) {
       base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                     std::move(callback));
@@ -307,8 +333,7 @@
   base::RepeatingClosure quit_closure_;
 };
 
-// Crashes frequently, https://crbug.com/1073069
-TEST_P(MenuRunnerCocoaTest, DISABLED_RunMenuAndCancel) {
+TEST_P(MenuRunnerCocoaTest, RunMenuAndCancel) {
   base::TimeTicks min_time = ui::EventTimeForNow();
 
   RunMenu(base::BindOnce(&MenuRunnerCocoaTest::MenuCancelCallback,
@@ -333,8 +358,7 @@
   EXPECT_EQ(1, menu_close_count_);
 }
 
-// Marking as disabled for crbug/1058157.
-TEST_P(MenuRunnerCocoaTest, DISABLED_RunMenuAndDelete) {
+TEST_P(MenuRunnerCocoaTest, RunMenuAndDelete) {
   RunMenu(base::BindOnce(&MenuRunnerCocoaTest::MenuDeleteCallback,
                          base::Unretained(this)));
   // Note the close callback is NOT invoked for deleted menus.
@@ -343,8 +367,7 @@
 
 // Tests a potential lifetime issue using the Cocoa MenuController, which has a
 // weak reference to the model.
-// Disabled: crbug.com/1060063
-TEST_P(MenuRunnerCocoaTest, DISABLED_RunMenuAndDeleteThenSelectItem) {
+TEST_P(MenuRunnerCocoaTest, RunMenuAndDeleteThenSelectItem) {
   RunMenu(
       base::BindOnce(&MenuRunnerCocoaTest::ModelDeleteThenSelectItemCallback,
                      base::Unretained(this)));
@@ -353,8 +376,7 @@
 
 // Ensure a menu can be safely released immediately after a call to Cancel() in
 // the same run loop iteration.
-// Disabled: crbug.com/1060063
-TEST_P(MenuRunnerCocoaTest, DISABLED_DestroyAfterCanceling) {
+TEST_P(MenuRunnerCocoaTest, DestroyAfterCanceling) {
   RunMenu(base::BindOnce(&MenuRunnerCocoaTest::MenuCancelAndDeleteCallback,
                          base::Unretained(this)));
 
@@ -367,8 +389,7 @@
   }
 }
 
-// Marking as disabled as test is flaky. crbug.com/1060063
-TEST_P(MenuRunnerCocoaTest, DISABLED_RunMenuTwice) {
+TEST_P(MenuRunnerCocoaTest, RunMenuTwice) {
   for (int i = 0; i < 2; ++i) {
     RunMenu(base::BindOnce(&MenuRunnerCocoaTest::MenuCancelCallback,
                            base::Unretained(this)));
@@ -391,8 +412,7 @@
 }
 
 // Tests anchoring of the menus used for toolkit-views Comboboxes.
-// Disabled: crbug.com/1060063
-TEST_P(MenuRunnerCocoaTest, DISABLED_ComboboxAnchoring) {
+TEST_P(MenuRunnerCocoaTest, ComboboxAnchoring) {
   // Combobox at 20,10 in the Widget.
   const gfx::Rect combobox_rect(20, 10, 80, 50);
 
@@ -434,9 +454,10 @@
   // In RTL, Cocoa messes up the positioning unless the anchor rectangle is
   // offset to the right of the view. The offset for the checkmark is also
   // skipped, to give a better match to native behavior.
-  base::i18n::SetICUDefaultLocale("he");
+  base::i18n::SetRTLForTesting(true);
   RunMenuAt(anchor_rect);
   EXPECT_EQ(combobox_rect.right(), last_anchor_frame_.origin.x);
+  base::i18n::SetRTLForTesting(false);
 }
 
 INSTANTIATE_TEST_SUITE_P(,
@@ -444,5 +465,4 @@
                          ::testing::Values(MenuType::NATIVE, MenuType::VIEWS),
                          &MenuTypeToString);
 
-}  // namespace test
-}  // namespace views
+}  // namespace views::test
diff --git a/ui/views/controls/menu/menu_runner_unittest.cc b/ui/views/controls/menu/menu_runner_unittest.cc
index 0b817da..cb347e8 100644
--- a/ui/views/controls/menu/menu_runner_unittest.cc
+++ b/ui/views/controls/menu/menu_runner_unittest.cc
@@ -35,8 +35,11 @@
 #include "ui/views/widget/widget_delegate.h"
 #include "ui/views/widget/widget_utils.h"
 
-namespace views {
-namespace test {
+#if BUILDFLAG(IS_MAC)
+#include "ui/views/controls/menu/menu_cocoa_watcher_mac.h"
+#endif
+
+namespace views::test {
 
 class MenuRunnerTest : public ViewsTestBase {
  public:
@@ -74,10 +77,27 @@
   MenuRunner* menu_runner() { return menu_runner_.get(); }
   Widget* owner() { return owner_.get(); }
 
+#if BUILDFLAG(IS_MAC)
+  void SetUp() override {
+    ViewsTestBase::SetUp();
+
+    // Ignore app activation notifications during tests (they make the tests
+    // flaky).
+    MenuCocoaWatcherMac::SetNotificationFilterForTesting(
+        MacNotificationFilter::IgnoreWorkspaceNotifications);
+  }
+#endif
+
   // ViewsTestBase:
   void TearDown() override {
     if (owner_)
       owner_->CloseNow();
+
+#if BUILDFLAG(IS_MAC)
+    MenuCocoaWatcherMac::SetNotificationFilterForTesting(
+        MacNotificationFilter::DontIgnoreNotifications);
+#endif
+
     ViewsTestBase::TearDown();
   }
 
@@ -735,5 +755,4 @@
   EXPECT_EQ(nullptr, menu_controller.controller());
 }
 
-}  // namespace test
-}  // namespace views
+}  // namespace views::test
diff --git a/ui/webui/resources/cr_components/help_bubble/help_bubble.html b/ui/webui/resources/cr_components/help_bubble/help_bubble.html
index e19004e..8147524 100644
--- a/ui/webui/resources/cr_components/help_bubble/help_bubble.html
+++ b/ui/webui/resources/cr_components/help_bubble/help_bubble.html
@@ -17,7 +17,7 @@
     position: absolute;
   }
 
-  /* #arrow is rotated and positioned in a container to simplify positioning */
+  /* #inner-arrow is rotated and positioned in a container to simplify positioning */
   #inner-arrow {
     background-color: var(--help-bubble-background);
     height: var(--help-bubble-arrow-size);
@@ -122,7 +122,6 @@
 
   .title {
     flex: 1;
-    font-family: 'Roboto';
     font-size: 18px;
     font-style: normal;
     font-weight: 500;
@@ -132,7 +131,6 @@
   /* Note: help bubbles have the same color treatment in both light and dark
    * themes, which is why the values below do not change based on theme
    * preference. */
-
   .help-bubble {
     --help-bubble-background: var(--google-blue-700);
     --help-bubble-element-spacing: 8px;
@@ -145,6 +143,10 @@
     justify-content: space-between;
     padding: 16px 20px;
     position: relative;
+    /*
+     * actual width is 340px when adding padding
+     * cannot use 'box-sizing: border-box' here because size calculation in js
+     */
     width: 300px;
   }
 
diff --git a/ui/wm/core/window_animations.cc b/ui/wm/core/window_animations.cc
index 203cfea..e7a78c3 100644
--- a/ui/wm/core/window_animations.cc
+++ b/ui/wm/core/window_animations.cc
@@ -58,6 +58,9 @@
  public:
   explicit HidingWindowAnimationObserverBase(aura::Window* window)
       : window_(window) {
+    window_->SetProperty(
+        kWindowHidingAnimationCountKey,
+        window_->GetProperty(kWindowHidingAnimationCountKey) + 1);
     window_->AddObserver(this);
   }
 
@@ -67,8 +70,13 @@
       const HidingWindowAnimationObserverBase&) = delete;
 
   ~HidingWindowAnimationObserverBase() override {
-    if (window_)
-      window_->RemoveObserver(this);
+    if (!window_)
+      return;
+    window_->RemoveObserver(this);
+    window_->SetProperty(
+        kWindowHidingAnimationCountKey,
+        window_->GetProperty(kWindowHidingAnimationCountKey) - 1);
+    DCHECK_GE(window_->GetProperty(kWindowHidingAnimationCountKey), 0);
   }
 
   // aura::WindowObserver:
diff --git a/ui/wm/core/window_properties.cc b/ui/wm/core/window_properties.cc
index 7389694..536ecd1 100644
--- a/ui/wm/core/window_properties.cc
+++ b/ui/wm/core/window_properties.cc
@@ -26,5 +26,6 @@
 DEFINE_UI_CLASS_PROPERTY_KEY(float,
                              kWindowVisibilityAnimationVerticalPositionKey,
                              15.f)
+DEFINE_UI_CLASS_PROPERTY_KEY(int32_t, kWindowHidingAnimationCountKey, 0)
 
 }  // namespace wm
diff --git a/ui/wm/core/window_properties.h b/ui/wm/core/window_properties.h
index 62caea0f..b70581d7 100644
--- a/ui/wm/core/window_properties.h
+++ b/ui/wm/core/window_properties.h
@@ -43,6 +43,10 @@
 extern const ui::ClassProperty<float>* const
     kWindowVisibilityAnimationVerticalPositionKey;
 
+// The number of hiding animations in progress on the window.
+COMPONENT_EXPORT(UI_WM)
+extern const ui::ClassProperty<int32_t>* const kWindowHidingAnimationCountKey;
+
 }  // namespace wm
 
 // These need to be declared here for jumbo builds.