diff --git a/DEPS b/DEPS
index 2ab2dcf90..a0c8bdd 100644
--- a/DEPS
+++ b/DEPS
@@ -253,23 +253,23 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '6b49c5427038495e1a35ac6ca6be041a021d0079',
+  'skia_revision': '55ec34727676ec9a3bcd9aea00d58ae5a4e1d11c',
   # 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': '63f4b58d24824b799c3aee51ae30bae7eef06d4b',
+  'v8_revision': 'ad2e42379a0b772da47db66e251d173ec1fb63a3',
   # 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': '1d71f55f3b33d0860eaa96601166140e218f7047',
+  'angle_revision': 'f2e7a2359c5daf22719ffcac3fafb43d735baed3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': 'e1c0739cdd2d0b5f3a00097574e576af4d87c35f',
+  'swiftshader_revision': '205ddee16e5f6fe673e2fdb64510034ce4c9ad03',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '969fbf8b5255cc9f0b183563d547f2289663792d',
+  'pdfium_revision': '71a6d08cb833437b1befd1bed84dd79c9700b3ac',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -320,7 +320,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'b2ed43640f35da1fb8e352d8a08f074c70b9bee8',
+  'catapult_revision': '7b41c53e65d18c76f3671dc918ee51a9bd86da99',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -372,7 +372,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'quiche_revision': 'e1e95c317128c4859cab9dc1bc69a0a4d86aa2bc',
+  'quiche_revision': 'a7d8822ed437f522c553e2fcf7e9c155f1e163b1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -724,7 +724,7 @@
     Var('chromium_git') + '/external/github.com/toji/webvr.info.git' + '@' + 'c58ae99b9ff9e2aa4c524633519570bf33536248',
 
   'src/docs/website': {
-    'url': Var('chromium_git') + '/website.git' + '@' + '9e03811dcd09e0b382264f94108f4b3840cd7fbd',
+    'url': Var('chromium_git') + '/website.git' + '@' + 'ca9169626e4a110ebaa4ee2f0bc40fdd79f9baef',
   },
 
   'src/ios/third_party/earl_grey2/src': {
@@ -748,7 +748,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '5dce9626ae787c33d7bdbda5f156c1415b986c08',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'a20491bb2d8238a66bab188b02b24c9b546181ed',
       'condition': 'checkout_ios',
   },
 
@@ -1120,7 +1120,7 @@
   # Tools used when building Chrome for Chrome OS. This affects both the Simple
   # Chrome workflow, as well as the chromeos-chrome ebuild.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'f37f7da7156cc4c6cba405465e2ae30c8fe6fb50',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '398269f1a37f0373ed4090b006d21bed763220cf',
       'condition': 'checkout_chromeos',
   },
 
@@ -1705,7 +1705,7 @@
   'src/third_party/usrsctp/usrsctplib':
     Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '62d7d0c928c9a040dce96aa2f16c00e7e67d59cb',
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@3ef0c7c00c0886a3fae8e073cc0d73cfa6699843',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@d088cb1f4f5dfd77fc072917c93763e5ae7c273a',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907',
@@ -1741,10 +1741,10 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'cf04aebdf9b53bb2853f22a81465688daf879ec6',
 
   'src/third_party/webgpu-cts/src':
-    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '981b513154230fb38aaa1d999d4c30bd7a3c3966',
+    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '68fbc0f8f30c00408fb94807c197f055e5535795',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'a8bc1378356454572596717faba6facb00a42d21',
+    Var('webrtc_git') + '/src.git' + '@' + '3cdd653d6691c145ac1e102224c7cd48a56c2ca5',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1814,7 +1814,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@680f49176104d127cf190bf924dfc67e5dbf6f15',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@2ed604efd56355b3d6c8ce7e78fe07d59fbdc1be',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/WATCHLISTS b/WATCHLISTS
index 67c95b0..5ae4660 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1661,6 +1661,9 @@
       'filepath': '^remoting/' \
                   '|^testing/chromoting'
     },
+    'rgb_kbd': {
+      'filepath': 'ash/rgb_keyboard/'
+    },
     'rlz_id': {
       'filepath' :'rlz/lib/machine_id.cc|'\
                   'rlz/lib/machine_id.h|'\
@@ -2738,6 +2741,9 @@
     'relaunch_notification': ['grt+watch@chromium.org'],
     'remoteplayback': ['mfoltz+watch@chromium.org'],
     'remoting': ['chromoting-reviews@chromium.org'],
+    'rgb_kbd': ['michaelcheco+watch-rgb-kbd@google.com',
+                'jimmyxgong+watch-rgb-kbd@chromium.org',
+                'zentaro+watch-rgb-kbd@chromium.org'],
     'rlz_id': ['gab+watch@chromium.org',
                'robertshield+watch@chromium.org'],
     'runtime_enabled_features': ['jmedley+watch@chromium.org'],
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index 566e26e8..cdd0ef2 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -260,6 +260,8 @@
     network::mojom::NetworkService* network_service) {
   content::GetNetworkService()->SetUpHttpAuth(
       network::mojom::HttpAuthStaticParams::New());
+  content::GetNetworkService()->ConfigureHttpAuthPrefs(
+      AwBrowserProcess::GetInstance()->CreateHttpAuthDynamicParams());
 }
 
 void AwContentBrowserClient::ConfigureNetworkContextParams(
diff --git a/android_webview/browser/network_service/aw_network_change_notifier.cc b/android_webview/browser/network_service/aw_network_change_notifier.cc
index d07b385d..1c1f564 100644
--- a/android_webview/browser/network_service/aw_network_change_notifier.cc
+++ b/android_webview/browser/network_service/aw_network_change_notifier.cc
@@ -44,6 +44,8 @@
 
 void AwNetworkChangeNotifier::OnConnectionTypeChanged() {}
 
+void AwNetworkChangeNotifier::OnConnectionCostChanged() {}
+
 void AwNetworkChangeNotifier::OnMaxBandwidthChanged(
     double max_bandwidth_mbps,
     ConnectionType type) {
diff --git a/android_webview/browser/network_service/aw_network_change_notifier.h b/android_webview/browser/network_service/aw_network_change_notifier.h
index 660f8a1..96f0776a 100644
--- a/android_webview/browser/network_service/aw_network_change_notifier.h
+++ b/android_webview/browser/network_service/aw_network_change_notifier.h
@@ -44,6 +44,7 @@
 
   // NetworkChangeNotifierDelegateAndroid::Observer:
   void OnConnectionTypeChanged() override;
+  void OnConnectionCostChanged() override;
   void OnMaxBandwidthChanged(double max_bandwidth_mbps,
                              ConnectionType type) override;
   void OnNetworkConnected(NetworkHandle network) override;
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
index 7176869..120632a 100644
--- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
+++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -282,6 +282,9 @@
             Flag.baseFeature(BlinkFeatures.AUTOFILL_SHADOW_DOM,
                     "Enables Autofill associate form elements with form "
                             + "control elements across shadow boundaries."),
+            Flag.baseFeature(BlinkFeatures.UACH_OVERRIDE_BLANK,
+                    "Changes behavior of User-Agent Client Hints to send blank headers "
+                            + "when the User-Agent string is overriden"),
             // Add new commandline switches and features above. The final entry should have a
             // trailing comma for cleaner diffs.
     };
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
index 5e04b80..7a177d2 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
@@ -1955,7 +1955,7 @@
     @Test
     @SmallTest
     @Feature({"AndroidWebView", "Preferences"})
-    @CommandLineFlags.Add({"enable-features=UserAgentClientHint"})
+    @CommandLineFlags.Add({"enable-features=UserAgentClientHint,UACHOverrideBlank"})
     public void testUserAgentOverrideClientHints() throws Throwable {
         final TestAwContentsClient contentClient = new TestAwContentsClient();
         final AwTestContainerView testContainerView =
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 79c1a64..f6ab8d6 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -583,6 +583,9 @@
 const base::Feature kEnableSamlReauthenticationOnLockscreen{
     "EnableSamlReauthenticationOnLockScreen", base::FEATURE_ENABLED_BY_DEFAULT};
 
+const base::Feature kEnableSavedDesks{"EnableSavedDesks",
+                                      base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enables WireGuard VPN, if running a compatible kernel.
 const base::Feature kEnableWireGuard{"EnableWireGuard",
                                      base::FEATURE_ENABLED_BY_DEFAULT};
@@ -2037,6 +2040,10 @@
   return base::FeatureList::IsEnabled(kEnableSamlReauthenticationOnLockscreen);
 }
 
+bool IsSavedDesksEnabled() {
+  return base::FeatureList::IsEnabled(kEnableSavedDesks);
+}
+
 bool IsScalableStatusAreaEnabled() {
   return base::FeatureList::IsEnabled(kScalableStatusArea);
 }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index a8478d3..65e1b0e8 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -236,6 +236,7 @@
 extern const base::Feature kEnableSamlNotificationOnPasswordChangeSuccess;
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kEnableSamlReauthenticationOnLockscreen;
+COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kEnableSavedDesks;
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kEnableWireGuard;
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kEnforceAshExtensionKeeplist;
@@ -712,6 +713,7 @@
 bool IsSamlNotificationOnPasswordChangeSuccessEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS)
 bool IsSamlReauthenticationOnLockscreenEnabled();
+COMPONENT_EXPORT(ASH_CONSTANTS) bool IsSavedDesksEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsScalableStatusAreaEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsSeparateNetworkIconsEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS)
diff --git a/ash/system/network/network_state_list_detailed_view.cc b/ash/system/network/network_state_list_detailed_view.cc
index bccf554..943430f 100644
--- a/ash/system/network/network_state_list_detailed_view.cc
+++ b/ash/system/network/network_state_list_detailed_view.cc
@@ -189,53 +189,6 @@
 };
 
 //------------------------------------------------------------------------------
-
-// Special layout to overlap the scanning throbber and the info button.
-class InfoThrobberLayout : public views::LayoutManager {
- public:
-  InfoThrobberLayout() = default;
-
-  InfoThrobberLayout(const InfoThrobberLayout&) = delete;
-  InfoThrobberLayout& operator=(const InfoThrobberLayout&) = delete;
-
-  ~InfoThrobberLayout() override = default;
-
-  // views::LayoutManager
-  void Layout(views::View* host) override {
-    gfx::Size max_size(GetMaxChildSize(host));
-    // Center each child view within |max_size|.
-    for (auto* child : host->children()) {
-      if (!child->GetVisible())
-        continue;
-      gfx::Size child_size = child->GetPreferredSize();
-      gfx::Point origin;
-      origin.set_x((max_size.width() - child_size.width()) / 2);
-      origin.set_y((max_size.height() - child_size.height()) / 2);
-      gfx::Rect bounds(origin, child_size);
-      bounds.Inset(-host->GetInsets());
-      child->SetBoundsRect(bounds);
-    }
-  }
-
-  gfx::Size GetPreferredSize(const views::View* host) const override {
-    gfx::Point origin;
-    gfx::Rect rect(origin, GetMaxChildSize(host));
-    rect.Inset(-host->GetInsets());
-    return rect.size();
-  }
-
- private:
-  gfx::Size GetMaxChildSize(const views::View* host) const {
-    gfx::Size max_size;
-    for (const auto* child : host->children()) {
-      if (child->GetVisible())
-        max_size.SetToMax(child->GetPreferredSize());
-    }
-    return max_size;
-  }
-};
-
-//------------------------------------------------------------------------------
 // NetworkStateListDetailedView
 
 NetworkStateListDetailedView::NetworkStateListDetailedView(
diff --git a/ash/webui/scanning/scanning_handler.cc b/ash/webui/scanning/scanning_handler.cc
index cc7b02c0..8814c11 100644
--- a/ash/webui/scanning/scanning_handler.cc
+++ b/ash/webui/scanning/scanning_handler.cc
@@ -39,7 +39,10 @@
           {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
            base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {}
 
-ScanningHandler::~ScanningHandler() = default;
+ScanningHandler::~ScanningHandler() {
+  if (select_file_dialog_)
+    select_file_dialog_->ListenerDestroyed();
+}
 
 void ScanningHandler::RegisterMessages() {
   web_ui()->RegisterDeprecatedMessageCallback(
@@ -90,17 +93,17 @@
 void ScanningHandler::FileSelected(const base::FilePath& path,
                                    int index,
                                    void* params) {
-  if (!IsJavascriptAllowed())
-    return;
+  DCHECK(IsJavascriptAllowed());
 
+  select_file_dialog_ = nullptr;
   ResolveJavascriptCallback(base::Value(scan_location_callback_id_),
                             CreateSelectedPathValue(path));
 }
 
 void ScanningHandler::FileSelectionCanceled(void* params) {
-  if (!IsJavascriptAllowed())
-    return;
+  DCHECK(IsJavascriptAllowed());
 
+  select_file_dialog_ = nullptr;
   ResolveJavascriptCallback(base::Value(scan_location_callback_id_),
                             CreateSelectedPathValue(base::FilePath()));
 }
@@ -147,6 +150,13 @@
 }
 
 void ScanningHandler::HandleRequestScanToLocation(const base::ListValue* args) {
+  if (!IsJavascriptAllowed())
+    return;
+
+  // Early return if the select file dialog is already active.
+  if (select_file_dialog_)
+    return;
+
   CHECK_EQ(1U, args->GetListDeprecated().size());
   scan_location_callback_id_ = args->GetListDeprecated()[0].GetString();
 
diff --git a/ash/webui/scanning/scanning_handler_unittest.cc b/ash/webui/scanning/scanning_handler_unittest.cc
index ff3c702b..5e73a00 100644
--- a/ash/webui/scanning/scanning_handler_unittest.cc
+++ b/ash/webui/scanning/scanning_handler_unittest.cc
@@ -69,8 +69,12 @@
       return;
     }
 
-    listener_->FileSelected(selected_path_, 0 /* index */,
-                            nullptr /* params */);
+    // Put the selected path on the stack so that it stays valid for the
+    // duration of Listener::FileSelected() despite deleting the
+    // SelectFileDialog immediately. This is in line with the default behavior
+    // of SelectFileDialog.
+    base::FilePath selected_path = std::move(selected_path_);
+    listener_->FileSelected(selected_path, 0 /* index */, nullptr /* params */);
   }
 
   bool IsRunning(gfx::NativeWindow owning_window) const override {
diff --git a/ash/webui/shimless_rma/resources/onboarding_landing_page.html b/ash/webui/shimless_rma/resources/onboarding_landing_page.html
index d3b2cb28..59e7e29b 100644
--- a/ash/webui/shimless_rma/resources/onboarding_landing_page.html
+++ b/ash/webui/shimless_rma/resources/onboarding_landing_page.html
@@ -3,6 +3,10 @@
     height: 30px;
     width: 30px;
   }
+
+  #nextButtonCaret {
+    margin-inline-start: 5px;
+  }
 </style>
 
 <base-page>
@@ -29,6 +33,13 @@
         </span>
       </span>
     </div>
+    <cr-button id="nextButton" class="action-button"
+        on-click="onGetStartedButtonClicked_"
+        disabled="[[isGetStartedButtonDisabled_(verificationInProgress_,
+        allButtonsDisabled)]]">
+      [[i18n('getStartedButtonLabel')]]
+      <span id="nextButtonCaret">&#62;</span>
+    </cr-button>
   </div>
   <div slot="right-pane">
     <div class="illustration-wrapper">
diff --git a/ash/webui/shimless_rma/resources/onboarding_landing_page.js b/ash/webui/shimless_rma/resources/onboarding_landing_page.js
index 0e1248f3..fa24e98 100644
--- a/ash/webui/shimless_rma/resources/onboarding_landing_page.js
+++ b/ash/webui/shimless_rma/resources/onboarding_landing_page.js
@@ -42,6 +42,12 @@
   static get properties() {
     return {
       /**
+       * Set by shimless_rma.js.
+       * @type {boolean}
+       */
+      allButtonsDisabled: Boolean,
+
+      /**
        * List of unqualified components from rmad service, not i18n.
        * @protected
        */
@@ -103,6 +109,27 @@
     return Promise.reject(new Error('Hardware verification is not complete.'));
   }
 
+  /** @protected */
+  onGetStartedButtonClicked_(e) {
+    e.preventDefault();
+
+    this.dispatchEvent(new CustomEvent(
+        'transition-state',
+        {
+          bubbles: true,
+          composed: true,
+          detail: (() => {
+            if (!this.verificationInProgress_) {
+              return this.shimlessRmaService_.beginFinalization();
+            }
+
+            return Promise.reject(
+                new Error('Hardware verification is not complete.'));
+          })
+        },
+        ));
+  }
+
   /**
    * @protected
    * @return {string}
@@ -146,6 +173,11 @@
   closeDialog_() {
     this.shadowRoot.querySelector('#unqualifiedComponentsDialog').close();
   }
+
+  /** @protected */
+  isGetStartedButtonDisabled_() {
+    return this.verificationInProgress_ || this.allButtonsDisabled;
+  }
 }
 
 customElements.define(OnboardingLandingPage.is, OnboardingLandingPage);
diff --git a/ash/webui/shimless_rma/resources/reimaging_provisioning_page.js b/ash/webui/shimless_rma/resources/reimaging_provisioning_page.js
index 3fc378c9..7edc582c2 100644
--- a/ash/webui/shimless_rma/resources/reimaging_provisioning_page.js
+++ b/ash/webui/shimless_rma/resources/reimaging_provisioning_page.js
@@ -18,7 +18,7 @@
 
 /** @type {!Object<!ProvisioningStatus, string>} */
 const provisioningStatusTextKeys = {
-  [ProvisioningStatus.kInProgress]: 'provisioningPageProgressText',
+  [ProvisioningStatus.kInProgress]: 'provisioningPageInProgressText',
   [ProvisioningStatus.kComplete]: 'provisioningPageCompleteText',
   [ProvisioningStatus.kFailedBlocking]: 'provisioningPageFailedBlockingText',
   [ProvisioningStatus.kFailedNonBlocking]:
@@ -65,15 +65,9 @@
       },
 
       /** @protected */
-      progress_: {
-        type: Number,
-        value: 0.0,
-      },
-
-      /** @protected */
       statusString_: {
         type: String,
-        computed: 'getStatusString_(status_, progress_)',
+        computed: 'getStatusString_(status_)',
       },
 
       /** @protected {boolean} */
@@ -114,13 +108,7 @@
       return '';
     }
 
-    if (this.status_ === ProvisioningStatus.kInProgress) {
-      return this.i18n(
-          provisioningStatusTextKeys[this.status_],
-          Math.round(this.progress_ * 100));
-    } else {
-      return this.i18n(provisioningStatusTextKeys[this.status_]);
-    }
+    return this.i18n(provisioningStatusTextKeys[this.status_]);
   }
 
   /**
@@ -132,7 +120,6 @@
    */
   onProvisioningUpdated(status, progress) {
     this.status_ = status;
-    this.progress_ = progress;
     const disabled = this.status_ != ProvisioningStatus.kComplete &&
         this.status_ != ProvisioningStatus.kFailedNonBlocking;
     if (disabled) {
diff --git a/ash/webui/shimless_rma/shimless_rma.cc b/ash/webui/shimless_rma/shimless_rma.cc
index 8559b1ca..9adc2d7 100644
--- a/ash/webui/shimless_rma/shimless_rma.cc
+++ b/ash/webui/shimless_rma/shimless_rma.cc
@@ -194,7 +194,8 @@
        IDS_SHIMLESS_RMA_RUN_CALIBRATING_COMPONENT},
       // Device provisioning page
       {"provisioningPageTitleText", IDS_SHIMLESS_RMA_PROVISIONING_TITLE},
-      {"provisioningPageProgressText", IDS_SHIMLESS_RMA_PROVISIONING_PROGRESS},
+      {"provisioningPageInProgressText",
+       IDS_SHIMLESS_RMA_PROVISIONING_IN_PROGRESS},
       {"provisioningPageCompleteText", IDS_SHIMLESS_RMA_PROVISIONING_COMPLETE},
       {"provisioningPageFailedBlockingText",
        IDS_SHIMLESS_RMA_PROVISIONING_FAILED_BLOCKING},
diff --git a/base/native_library_fuchsia.cc b/base/native_library_fuchsia.cc
index 5dfc33f..8b9413c 100644
--- a/base/native_library_fuchsia.cc
+++ b/base/native_library_fuchsia.cc
@@ -53,10 +53,11 @@
   // TODO(1018538): Teach base::File about FLAG_WIN_EXECUTE on Fuchsia, and then
   // use it here instead of using fdio_open_fd() directly.
   base::ScopedFD fd;
-  zx_status_t status = fdio_open_fd(
-      computed_path.value().c_str(),
-      fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_RIGHT_EXECUTABLE,
-      base::ScopedFD::Receiver(fd).get());
+  zx_status_t status =
+      fdio_open_fd(computed_path.value().c_str(),
+                   static_cast<uint32_t>(fuchsia::io::OPEN_RIGHT_READABLE |
+                                         fuchsia::io::OPEN_RIGHT_EXECUTABLE),
+                   base::ScopedFD::Receiver(fd).get());
   if (status != ZX_OK) {
     if (error) {
       error->message =
diff --git a/base/win/scoped_select_object.h b/base/win/scoped_select_object.h
index ee84a9c..dcbc673d 100644
--- a/base/win/scoped_select_object.h
+++ b/base/win/scoped_select_object.h
@@ -19,7 +19,8 @@
       : hdc_(hdc), oldobj_(SelectObject(hdc, object)) {
     DCHECK(hdc_);
     DCHECK(object);
-    DCHECK(oldobj_ != NULL && oldobj_ != HGDI_ERROR);
+    DCHECK(oldobj_);
+    DCHECK(oldobj_ != HGDI_ERROR);
   }
 
   ScopedSelectObject(const ScopedSelectObject&) = delete;
@@ -27,13 +28,13 @@
 
   ~ScopedSelectObject() {
     HGDIOBJ object = SelectObject(hdc_, oldobj_);
-    DCHECK((GetObjectType(oldobj_) != OBJ_REGION && object != NULL) ||
+    DCHECK((GetObjectType(oldobj_) != OBJ_REGION && object) ||
            (GetObjectType(oldobj_) == OBJ_REGION && object != HGDI_ERROR));
   }
 
  private:
-  HDC hdc_;
-  HGDIOBJ oldobj_;
+  const HDC hdc_;
+  const HGDIOBJ oldobj_;
 };
 
 }  // namespace win
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py
index c00670a0..4b5b84c 100755
--- a/build/android/gyp/write_build_config.py
+++ b/build/android/gyp/write_build_config.py
@@ -671,13 +671,18 @@
 
 
 def GetAllDepsConfigsInOrder(deps_config_paths, filter_func=None):
-  def GetDeps(path):
-    config = GetDepConfig(path)
-    if filter_func and not filter_func(config):
-      return []
-    return config['deps_configs']
+  def apply_filter(paths):
+    if filter_func:
+      return [p for p in paths if filter_func(GetDepConfig(p))]
+    return paths
 
-  return build_utils.GetSortedTransitiveDependencies(deps_config_paths, GetDeps)
+  def discover(path):
+    return apply_filter(GetDepConfig(path)['deps_configs'])
+
+  deps_config_paths = apply_filter(deps_config_paths)
+  deps_config_paths = build_utils.GetSortedTransitiveDependencies(
+      deps_config_paths, discover)
+  return deps_config_paths
 
 
 def GetObjectByPath(obj, key_path):
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index f9c9e8e1..d36ddce 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-7.20220325.0.1
+7.20220325.2.1
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index 676a9675..d36ddce 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-7.20220325.1.1
+7.20220325.2.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index f9c9e8e1..d36ddce 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-7.20220325.0.1
+7.20220325.2.1
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index c85c71b..ba98555 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -6452,7 +6452,7 @@
         Pick cards that keep you updated on things that matter to you
       </message>
       <message name="IDS_NTP_MODULES_FIRST_RUN_EXPERIENCE_BODY_LINE_2" desc="Line 2 of Modular NTP Desktop v1 First Run Experience's body.">
-        See all card options in <ph name="BEGIN_LINK">&lt;a is="action-link" id="customizeChromeLink" on-click="onCustomizeModuleFre_"&gt;</ph>Customize Chrome<ph name="END_LINK">&lt;/a&gt;</ph>
+        See all card options in <ph name="BEGIN_LINK">&lt;a is="action-link" id="customizeChromeLink" tabIndex=0 on-click="onCustomizeModuleFre_"&gt;</ph>Customize Chrome<ph name="END_LINK">&lt;/a&gt;</ph>
       </message>
       <message name="IDS_NTP_MODULES_FIRST_RUN_EXPERIENCE_OPT_IN" desc="Opt in button for Modular NTP Desktop v1 First Run Experience.">
         Got it
diff --git a/chrome/app/nearby_share_strings.grdp b/chrome/app/nearby_share_strings.grdp
index b5083d0..35f677e4 100644
--- a/chrome/app/nearby_share_strings.grdp
+++ b/chrome/app/nearby_share_strings.grdp
@@ -318,7 +318,7 @@
       other {<ph name="DEVICE_NAME">$1<ex>Ted's Pixel 2</ex></ph> is sharing <ph name="ATTACHMENTS">$2<ex>3 items</ex></ph> with you.}}
   </message>
   <message name="IDS_NEARBY_NOTIFICATION_CONNECTION_REQUEST_MESSAGE_WIFI_CREDENTIALS" desc="Text shown as the message of a notfication when a nearby device requests a connection via Nearby Share to send Wi-Fi network credentials.">
-    <ph name="DEVICE_NAME">$1<ex>Ted's Pixel 2</ex></ph> is sharing a Wi-Fi network with you.
+    <ph name="DEVICE_NAME">$1<ex>Ted's Pixel 2</ex></ph> is sharing a Wi-Fi network with you
   </message>
   <message name="IDS_NEARBY_NOTIFICATION_CONNECTION_REQUEST_TITLE" desc="Text shown as the title of a notfication when a nearby device requests a connection via Nearby Share.">
     Receive with Nearby Share?
@@ -359,7 +359,7 @@
       other {Failed to receive <ph name="ATTACHMENTS">$1<ex>3 items</ex></ph> from <ph name="DEVICE_NAME">$2<ex>Ted's Pixel 2</ex></ph>}}
   </message>
   <message name="IDS_NEARBY_NOTIFICATION_RECEIVE_FAILURE_TITLE_WIFI_CREDENTIALS" desc="Text shown as the title of a notfication when receiving Wi-Fi credentials via Nearby Share failed.">
-    Failed to receive network configuration for '<ph name="NETWORK_NAME">$1<ex>My Home Wi-Fi</ex></ph>' from <ph name="DEVICE_NAME">$2<ex>Ted's Pixel 2</ex></ph>
+    Couldn't save '<ph name="NETWORK_NAME">$1<ex>My Home Wi-Fi</ex></ph>' from <ph name="DEVICE_NAME">$2<ex>Ted's Pixel 2</ex></ph>
   </message>
   <message name="IDS_NEARBY_NOTIFICATION_RECEIVE_PROGRESS_TITLE" desc="Text shown as the title of a notfication when receiving data via Nearby Share.">
     {COUNT, plural,
@@ -367,7 +367,7 @@
       other {Receiving <ph name="ATTACHMENTS">$1<ex>3 items</ex></ph> from <ph name="DEVICE_NAME">$2<ex>Ted's Pixel 2</ex></ph>}}
   </message>
   <message name="IDS_NEARBY_NOTIFICATION_RECEIVE_PROGRESS_TITLE_WIFI_CREDENTIALS" desc="Text shown as the title of a notfication when receiving Wi-Fi credentials via Nearby Share.">
-    Receiving network configuration for '<ph name="NETWORK_NAME">$1<ex>My Home Wi-Fi</ex></ph>' from <ph name="DEVICE_NAME">$2<ex>Ted's Pixel 2</ex></ph>
+    Receiving Wi-Fi network
   </message>
   <message name="IDS_NEARBY_NOTIFICATION_RECEIVE_SUCCESS_TITLE" desc="Text shown as the title of a notfication when data was sucessfully received via Nearby Share.">
     {COUNT, plural,
@@ -375,7 +375,7 @@
       other {<ph name="ATTACHMENTS">$1<ex>3 items</ex></ph> received from <ph name="DEVICE_NAME">$2<ex>Ted's Pixel 2</ex></ph>}}
   </message>
   <message name="IDS_NEARBY_NOTIFICATION_RECEIVE_SUCCESS_TITLE_WIFI_CREDENTIALS" desc="Text shown as the title of a notfication when Wi-Fi credentials were sucessfully received via Nearby Share.">
-    Received network configuration for '<ph name="NETWORK_NAME">$1<ex>My Home Wi-Fi</ex></ph>' from <ph name="DEVICE_NAME">$2<ex>Ted's Pixel 2</ex></ph>
+    '<ph name="NETWORK_NAME">$1<ex>My Home Wi-Fi</ex></ph>' saved from <ph name="DEVICE_NAME">$2<ex>Ted's Pixel 2</ex></ph>
   </message>
   <message name="IDS_NEARBY_NOTIFICATION_SEND_FAILURE_TITLE" desc="Text shown as the title of a notfication when sending data via Nearby Share failed.">
     {COUNT, plural,
diff --git a/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_CONNECTION_REQUEST_MESSAGE_WIFI_CREDENTIALS.png.sha1 b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_CONNECTION_REQUEST_MESSAGE_WIFI_CREDENTIALS.png.sha1
index f029be6..f38915d 100644
--- a/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_CONNECTION_REQUEST_MESSAGE_WIFI_CREDENTIALS.png.sha1
+++ b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_CONNECTION_REQUEST_MESSAGE_WIFI_CREDENTIALS.png.sha1
@@ -1 +1 @@
-252446754b1dfd18f34ec63763abc3c068fa08e7
\ No newline at end of file
+0830c34d6356f3d2d22331e55c9674b962e45a55
\ No newline at end of file
diff --git a/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_FAILURE_TITLE_WIFI_CREDENTIALS.png.sha1 b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_FAILURE_TITLE_WIFI_CREDENTIALS.png.sha1
index f7d875e..79677e1 100644
--- a/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_FAILURE_TITLE_WIFI_CREDENTIALS.png.sha1
+++ b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_FAILURE_TITLE_WIFI_CREDENTIALS.png.sha1
@@ -1 +1 @@
-95ed62106905cb873330d1a25501f17a798a58f3
\ No newline at end of file
+e7eeb39a25f37afede4643b45327c03119078322
\ No newline at end of file
diff --git a/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_PROGRESS_TITLE_WIFI_CREDENTIALS.png.sha1 b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_PROGRESS_TITLE_WIFI_CREDENTIALS.png.sha1
index 8ad54fb5..dd7efe5e 100644
--- a/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_PROGRESS_TITLE_WIFI_CREDENTIALS.png.sha1
+++ b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_PROGRESS_TITLE_WIFI_CREDENTIALS.png.sha1
@@ -1 +1 @@
-3b30821d6d181923dd8da6da0a6a2983acfe7520
\ No newline at end of file
+7b1cb89db687772cb1566e9b1963d6e71fe7a52c
\ No newline at end of file
diff --git a/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_SUCCESS_TITLE_WIFI_CREDENTIALS.png.sha1 b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_SUCCESS_TITLE_WIFI_CREDENTIALS.png.sha1
index 0b615e5..ac89c04 100644
--- a/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_SUCCESS_TITLE_WIFI_CREDENTIALS.png.sha1
+++ b/chrome/app/nearby_share_strings_grdp/IDS_NEARBY_NOTIFICATION_RECEIVE_SUCCESS_TITLE_WIFI_CREDENTIALS.png.sha1
@@ -1 +1 @@
-23f0c76d7d3113d1f5f1e6ca3f1a4c0c55b7a94b
\ No newline at end of file
+7f8c2bb6ff5b8d1cdaa8be78af2811bea62df593
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 53191e2d..db6fc6a 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -123,7 +123,7 @@
 }
 
 # Use a static library here because many test binaries depend on this but don't
-# require many files from it.This makes linking more efficient.
+# require many files from it. This makes linking more efficient.
 static_library("browser") {
   sources = [
     "about_flags.cc",
@@ -4390,6 +4390,8 @@
       "usb/web_usb_chooser_desktop.h",
       "usb/web_usb_detector.cc",
       "usb/web_usb_detector.h",
+      "user_notes/user_note_service_factory.cc",
+      "user_notes/user_note_service_factory.h",
       "webauthn/authenticator_list_observer.h",
       "webauthn/authenticator_reference.cc",
       "webauthn/authenticator_reference.h",
@@ -4471,6 +4473,8 @@
       "//components/soda",
       "//components/soda:constants",
       "//components/ukm/content",
+      "//components/user_notes:features",
+      "//components/user_notes/browser",
       "//components/web_modal",
       "//courgette:courgette_lib",
       "//services/device/public/cpp/hid",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index 2176f5d0..fa66b65 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -356,6 +356,7 @@
   "+components/url_matcher",
   "+components/url_pattern_index/proto",
   "+components/user_manager",
+  "+components/user_notes",
   "+components/user_prefs",
   "+components/value_store",
   "+components/vector_icons",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 78a4e7b..26f5a34 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -5177,6 +5177,11 @@
      flag_descriptions::kSidePanelDragAndDropDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(features::kSidePanelDragAndDrop)},
 
+    {"side-panel-improved-clobbering",
+     flag_descriptions::kSidePanelImprovedClobberingName,
+     flag_descriptions::kSidePanelImprovedClobberingDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(features::kSidePanelImprovedClobbering)},
+
     {flag_descriptions::kUnifiedSidePanelFlagId,
      flag_descriptions::kUnifiedSidePanelName,
      flag_descriptions::kUnifiedSidePanelDescription, kOsDesktop,
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
index 57d7129..8dab415 100644
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -3312,12 +3312,13 @@
 
 }  // namespace
 
-// TODO(crbug.com/994789): Flaky on MSan, Linux, and Chrome OS.
-#if defined(MEMORY_SANITIZER) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
+// TODO(crbug.com/994789): Flaky on MSan, Linux, Chrome OS, and Mac.
+#if defined(MEMORY_SANITIZER) || BUILDFLAG(IS_LINUX) || \
+    BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC)
 #define MAYBE_DownloadCookieIsolation DISABLED_DownloadCookieIsolation
 #else
 #define MAYBE_DownloadCookieIsolation DownloadCookieIsolation
-#endif  // !defined(MEMORY_SANITIZER)
+#endif
 // Downloads initiated from isolated guest parititons should use their
 // respective cookie stores. In addition, if those downloads are resumed, they
 // should continue to use their respective cookie stores.
diff --git a/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
index c01777c..5b8cee25 100644
--- a/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
+++ b/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
@@ -1250,7 +1250,8 @@
   sm_.Replay();
 }
 
-IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, SmartStickyMode) {
+// TODO(crbug.com/1310316): Test is flaky.
+IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, DISABLED_SmartStickyMode) {
   EnableChromeVox();
   sm_.Call([this]() {
     ASSERT_TRUE(ui_test_utils::NavigateToURL(
diff --git a/chrome/browser/browsing_topics/browsing_topics_service_browsertest.cc b/chrome/browser/browsing_topics/browsing_topics_service_browsertest.cc
index d8b2cc0..8e33083 100644
--- a/chrome/browser/browsing_topics/browsing_topics_service_browsertest.cc
+++ b/chrome/browser/browsing_topics/browsing_topics_service_browsertest.cc
@@ -2,21 +2,131 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/json/json_file_value_serializer.h"
+#include "base/json/values_util.h"
+#include "base/path_service.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/browsing_topics/browsing_topics_service_factory.h"
+#include "chrome/browser/history/history_service_factory.h"
+#include "chrome/browser/optimization_guide/browser_test_util.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/optimization_guide/page_content_annotations_service_factory.h"
+#include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/browsing_topics/browsing_topics_service.h"
+#include "components/browsing_topics/browsing_topics_service_impl.h"
+#include "components/browsing_topics/epoch_topics.h"
+#include "components/browsing_topics/test_util.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/optimization_guide/content/browser/page_content_annotations_service.h"
+#include "components/optimization_guide/content/browser/test_page_content_annotator.h"
+#include "components/optimization_guide/core/optimization_guide_features.h"
+#include "components/optimization_guide/core/test_model_info_builder.h"
+#include "components/optimization_guide/core/test_optimization_guide_model_provider.h"
+#include "components/privacy_sandbox/privacy_sandbox_settings.h"
+#include "content/public/browser/browsing_topics_site_data_manager.h"
+#include "content/public/browser/storage_partition.h"
 #include "content/public/common/content_features.h"
 #include "content/public/test/browser_test.h"
+#include "content/public/test/browsing_topics_test_util.h"
+#include "content/public/test/fenced_frame_test_util.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/request_handler_util.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/common/features.h"
 
 namespace browsing_topics {
 
+namespace {
+
+constexpr browsing_topics::HmacKey kTestKey = {1};
+
+constexpr base::Time kTime1 =
+    base::Time::FromDeltaSinceWindowsEpoch(base::Days(1));
+constexpr base::Time kTime2 =
+    base::Time::FromDeltaSinceWindowsEpoch(base::Days(2));
+
+constexpr size_t kTaxonomySize = 349;
+constexpr int kTaxonomyVersion = 1;
+constexpr int64_t kModelVersion = 2;
+constexpr size_t kPaddedTopTopicsStartIndex = 3;
+
+constexpr char kExpectedResultOrder1[] =
+    "[{\"configVersion\":\"chrome.1\",\"modelVersion\":\"2\","
+    "\"taxonomyVersion\":\"1\",\"topic\":1,\"version\":\"chrome.1:1:2\"};{"
+    "\"configVersion\":\"chrome.1\",\"modelVersion\":\"2\","
+    "\"taxonomyVersion\":\"1\",\"topic\":10,\"version\":\"chrome.1:1:2\"};]";
+
+constexpr char kExpectedResultOrder2[] =
+    "[{\"configVersion\":\"chrome.1\",\"modelVersion\":\"2\","
+    "\"taxonomyVersion\":\"1\",\"topic\":10,\"version\":\"chrome.1:1:2\"};{"
+    "\"configVersion\":\"chrome.1\",\"modelVersion\":\"2\","
+    "\"taxonomyVersion\":\"1\",\"topic\":1,\"version\":\"chrome.1:1:2\"};]";
+
+EpochTopics CreateTestEpochTopics(
+    const std::vector<std::pair<Topic, std::set<HashedDomain>>>& topics,
+    base::Time calculation_time) {
+  DCHECK_EQ(topics.size(), 5u);
+
+  std::vector<TopicAndDomains> top_topics_and_observing_domains;
+  for (size_t i = 0; i < 5; ++i) {
+    top_topics_and_observing_domains.emplace_back(topics[i].first,
+                                                  topics[i].second);
+  }
+
+  return EpochTopics(std::move(top_topics_and_observing_domains),
+                     kPaddedTopTopicsStartIndex, kTaxonomySize,
+                     kTaxonomyVersion, kModelVersion, calculation_time);
+}
+
+}  // namespace
+
+// A tester class that allows waiting for the first calculation to finish.
+class TesterBrowsingTopicsService : public BrowsingTopicsServiceImpl {
+ public:
+  TesterBrowsingTopicsService(
+      const base::FilePath& profile_path,
+      privacy_sandbox::PrivacySandboxSettings* privacy_sandbox_settings,
+      history::HistoryService* history_service,
+      content::BrowsingTopicsSiteDataManager* site_data_manager,
+      optimization_guide::PageContentAnnotationsService* annotations_service,
+      base::OnceClosure calculation_finish_callback)
+      : BrowsingTopicsServiceImpl(profile_path,
+                                  privacy_sandbox_settings,
+                                  history_service,
+                                  site_data_manager,
+                                  annotations_service),
+        calculation_finish_callback_(std::move(calculation_finish_callback)) {}
+
+  ~TesterBrowsingTopicsService() override = default;
+
+  TesterBrowsingTopicsService(const TesterBrowsingTopicsService&) = delete;
+  TesterBrowsingTopicsService& operator=(const TesterBrowsingTopicsService&) =
+      delete;
+  TesterBrowsingTopicsService(TesterBrowsingTopicsService&&) = delete;
+  TesterBrowsingTopicsService& operator=(TesterBrowsingTopicsService&&) =
+      delete;
+
+  const BrowsingTopicsState& browsing_topics_state() override {
+    return BrowsingTopicsServiceImpl::browsing_topics_state();
+  }
+
+  void OnCalculateBrowsingTopicsCompleted(EpochTopics epoch_topics) override {
+    BrowsingTopicsServiceImpl::OnCalculateBrowsingTopicsCompleted(
+        std::move(epoch_topics));
+
+    if (calculation_finish_callback_)
+      std::move(calculation_finish_callback_).Run();
+  }
+
+ private:
+  base::OnceClosure calculation_finish_callback_;
+};
+
 class BrowsingTopicsBrowserTestBase : public InProcessBrowserTest {
  public:
   void SetUpOnMainThread() override {
@@ -31,6 +141,8 @@
     ASSERT_TRUE(embedded_test_server()->Start());
   }
 
+  ~BrowsingTopicsBrowserTestBase() override = default;
+
   std::string InvokeTopicsAPI(const content::ToRenderFrameHost& adapter) {
     return EvalJs(adapter, R"(
       if (!(document.browsingTopics instanceof Function)) {
@@ -64,7 +176,8 @@
  public:
   BrowsingTopicsDisabledBrowserTest() {
     scoped_feature_list_.InitWithFeatures(
-        /*enabled_features=*/{},
+        /*enabled_features=*/{optimization_guide::features::
+                                  kPageContentAnnotations},
         /*disabled_features=*/{blink::features::kBrowsingTopics});
   }
 
@@ -91,17 +204,241 @@
  public:
   BrowsingTopicsBrowserTest() {
     scoped_feature_list_.InitWithFeatures(
-        /*enabled_features=*/{blink::features::kBrowsingTopics,
-                              features::kPrivacySandboxAdsAPIsOverride},
+        /*enabled_features=*/
+        {optimization_guide::features::kPageContentAnnotations,
+         blink::features::kBrowsingTopics,
+         blink::features::kBrowsingTopicsBypassIPIsPubliclyRoutableCheck,
+         features::kPrivacySandboxAdsAPIsOverride},
         /*disabled_features=*/{});
   }
 
-  browsing_topics::BrowsingTopicsService* browsing_topics_service() {
-    return BrowsingTopicsServiceFactory::GetForProfile(browser()->profile());
+  ~BrowsingTopicsBrowserTest() override = default;
+
+  void SetUpOnMainThread() override {
+    BrowsingTopicsBrowserTestBase::SetUpOnMainThread();
+
+    for (auto& profile_and_calculation_finish_waiter :
+         calculation_finish_waiters_) {
+      profile_and_calculation_finish_waiter.second->Run();
+    }
+  }
+
+  // BrowserTestBase::SetUpInProcessBrowserTestFixture
+  void SetUpInProcessBrowserTestFixture() override {
+    subscription_ =
+        BrowserContextDependencyManager::GetInstance()
+            ->RegisterCreateServicesCallbackForTesting(base::BindRepeating(
+                &BrowsingTopicsBrowserTest::OnWillCreateBrowserContextServices,
+                base::Unretained(this)));
   }
 
  protected:
+  void ExpectResultTopicsEqual(
+      const std::vector<TopicAndDomains>& result,
+      std::vector<std::pair<Topic, std::set<HashedDomain>>> expected) {
+    DCHECK_EQ(expected.size(), 5u);
+    EXPECT_EQ(result.size(), 5u);
+
+    for (int i = 0; i < 5; ++i) {
+      EXPECT_EQ(result[i].topic(), expected[i].first);
+      EXPECT_EQ(result[i].hashed_domains(), expected[i].second);
+    }
+  }
+
+  HashedDomain GetHashedDomain(const std::string& domain) {
+    return HashContextDomainForStorage(kTestKey, domain);
+  }
+
+  void CreateBrowsingTopicsStateFile(
+      const base::FilePath& profile_path,
+      const std::vector<EpochTopics>& epochs,
+      base::Time next_scheduled_calculation_time) {
+    base::Value::List epochs_list;
+    for (const EpochTopics& epoch : epochs) {
+      epochs_list.Append(epoch.ToDictValue());
+    }
+
+    base::Value::Dict dict;
+    dict.Set("epochs", std::move(epochs_list));
+    dict.Set("next_scheduled_calculation_time",
+             base::TimeToValue(next_scheduled_calculation_time));
+    dict.Set("hex_encoded_hmac_key", base::HexEncode(kTestKey));
+    dict.Set("config_version", 1);
+
+    JSONFileValueSerializer(
+        profile_path.Append(FILE_PATH_LITERAL("BrowsingTopicsState")))
+        .Serialize(dict);
+  }
+
+  content::BrowsingTopicsSiteDataManager* browsing_topics_site_data_manager() {
+    return browser()
+        ->profile()
+        ->GetDefaultStoragePartition()
+        ->GetBrowsingTopicsSiteDataManager();
+  }
+
+  TesterBrowsingTopicsService* browsing_topics_service() {
+    return static_cast<TesterBrowsingTopicsService*>(
+        BrowsingTopicsServiceFactory::GetForProfile(browser()->profile()));
+  }
+
+  const BrowsingTopicsState& browsing_topics_state() {
+    return browsing_topics_service()->browsing_topics_state();
+  }
+
+  std::vector<optimization_guide::WeightedIdentifier> TopicsAndWeight(
+      const std::vector<int32_t>& topics,
+      double weight) {
+    std::vector<optimization_guide::WeightedIdentifier> result;
+    for (int32_t topic : topics) {
+      result.emplace_back(topic, weight);
+    }
+
+    return result;
+  }
+
+  void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
+    PageContentAnnotationsServiceFactory::GetInstance()->SetTestingFactory(
+        context,
+        base::BindRepeating(
+            &BrowsingTopicsBrowserTest::CreatePageContentAnnotationsService,
+            base::Unretained(this)));
+
+    browsing_topics::BrowsingTopicsServiceFactory::GetInstance()
+        ->SetTestingFactory(
+            context,
+            base::BindRepeating(
+                &BrowsingTopicsBrowserTest::CreateBrowsingTopicsService,
+                base::Unretained(this)));
+  }
+
+  std::unique_ptr<KeyedService> CreatePageContentAnnotationsService(
+      content::BrowserContext* context) {
+    Profile* profile = Profile::FromBrowserContext(context);
+
+    history::HistoryService* history_service =
+        HistoryServiceFactory::GetForProfile(
+            profile, ServiceAccessType::IMPLICIT_ACCESS);
+
+    DCHECK(!base::Contains(optimization_guide_model_providers_, profile));
+    optimization_guide_model_providers_.emplace(
+        profile, std::make_unique<
+                     optimization_guide::TestOptimizationGuideModelProvider>());
+
+    auto page_content_annotations_service =
+        std::make_unique<optimization_guide::PageContentAnnotationsService>(
+            "en-US", optimization_guide_model_providers_.at(profile).get(),
+            history_service, nullptr, base::FilePath(), nullptr);
+
+    page_content_annotations_service->OverridePageContentAnnotatorForTesting(
+        &test_page_content_annotator_);
+
+    return page_content_annotations_service;
+  }
+
+  void InitializePreexistingState(
+      history::HistoryService* history_service,
+      content::BrowsingTopicsSiteDataManager* site_data_manager,
+      const base::FilePath& profile_path) {
+    // Configure the (mock) model.
+    test_page_content_annotator_.UsePageTopics(
+        *optimization_guide::TestModelInfoBuilder().SetVersion(1).Build(),
+        {{"foo6 com", TopicsAndWeight({1, 2, 3, 4, 5, 6}, 0.1)},
+         {"foo5 com", TopicsAndWeight({2, 3, 4, 5, 6}, 0.1)},
+         {"foo4 com", TopicsAndWeight({3, 4, 5, 6}, 0.1)},
+         {"foo3 com", TopicsAndWeight({4, 5, 6}, 0.1)},
+         {"foo2 com", TopicsAndWeight({5, 6}, 0.1)},
+         {"foo1 com", TopicsAndWeight({6}, 0.1)}});
+
+    // Add some initial history.
+    history::HistoryAddPageArgs add_page_args;
+    add_page_args.time = base::Time::Now();
+    add_page_args.context_id = reinterpret_cast<history::ContextID>(1);
+    add_page_args.nav_entry_id = 1;
+
+    // Note: foo6.com isn't in the initial history.
+    for (int i = 1; i <= 5; ++i) {
+      add_page_args.url =
+          GURL(base::StrCat({"https://foo", base::NumberToString(i), ".com"}));
+      history_service->AddPage(add_page_args);
+      history_service->SetBrowsingTopicsAllowed(add_page_args.context_id,
+                                                add_page_args.nav_entry_id,
+                                                add_page_args.url);
+    }
+
+    // Add some API usage contexts data.
+    site_data_manager->OnBrowsingTopicsApiUsed(
+        HashMainFrameHostForStorage("foo1.com"), {HashedDomain(1)},
+        base::Time::Now());
+
+    // Initialize the `BrowsingTopicsState`.
+    std::vector<EpochTopics> preexisting_epochs;
+    preexisting_epochs.push_back(
+        CreateTestEpochTopics({{Topic(1), {GetHashedDomain("a.test")}},
+                               {Topic(2), {GetHashedDomain("a.test")}},
+                               {Topic(3), {GetHashedDomain("a.test")}},
+                               {Topic(4), {GetHashedDomain("a.test")}},
+                               {Topic(5), {GetHashedDomain("a.test")}}},
+                              kTime1));
+    preexisting_epochs.push_back(
+        CreateTestEpochTopics({{Topic(6), {GetHashedDomain("a.test")}},
+                               {Topic(7), {GetHashedDomain("a.test")}},
+                               {Topic(8), {GetHashedDomain("a.test")}},
+                               {Topic(9), {GetHashedDomain("a.test")}},
+                               {Topic(10), {GetHashedDomain("a.test")}}},
+                              kTime2));
+
+    CreateBrowsingTopicsStateFile(
+        profile_path, std::move(preexisting_epochs),
+        /*next_scheduled_calculation_time=*/base::Time::Now() - base::Days(1));
+  }
+
+  std::unique_ptr<KeyedService> CreateBrowsingTopicsService(
+      content::BrowserContext* context) {
+    Profile* profile = Profile::FromBrowserContext(context);
+
+    privacy_sandbox::PrivacySandboxSettings* privacy_sandbox_settings =
+        PrivacySandboxSettingsFactory::GetForProfile(profile);
+
+    history::HistoryService* history_service =
+        HistoryServiceFactory::GetForProfile(
+            profile, ServiceAccessType::IMPLICIT_ACCESS);
+
+    content::BrowsingTopicsSiteDataManager* site_data_manager =
+        context->GetDefaultStoragePartition()
+            ->GetBrowsingTopicsSiteDataManager();
+
+    optimization_guide::PageContentAnnotationsService* annotations_service =
+        PageContentAnnotationsServiceFactory::GetForProfile(profile);
+
+    InitializePreexistingState(history_service, site_data_manager,
+                               profile->GetPath());
+
+    DCHECK(!base::Contains(calculation_finish_waiters_, profile));
+    calculation_finish_waiters_.emplace(profile,
+                                        std::make_unique<base::RunLoop>());
+
+    return std::make_unique<TesterBrowsingTopicsService>(
+        profile->GetPath(), privacy_sandbox_settings, history_service,
+        site_data_manager, annotations_service,
+        calculation_finish_waiters_.at(profile)->QuitClosure());
+  }
+
+  content::test::FencedFrameTestHelper fenced_frame_test_helper_;
+
   base::test::ScopedFeatureList scoped_feature_list_;
+
+  std::map<
+      Profile*,
+      std::unique_ptr<optimization_guide::TestOptimizationGuideModelProvider>>
+      optimization_guide_model_providers_;
+
+  std::map<Profile*, std::unique_ptr<base::RunLoop>>
+      calculation_finish_waiters_;
+
+  optimization_guide::TestPageContentAnnotator test_page_content_annotator_;
+
+  base::CallbackListSubscription subscription_;
 };
 
 IN_PROC_BROWSER_TEST_F(BrowsingTopicsBrowserTest, HasBrowsingTopicsService) {
@@ -123,19 +460,186 @@
 }
 
 IN_PROC_BROWSER_TEST_F(BrowsingTopicsBrowserTest, BrowsingTopicsStateOnStart) {
-  EXPECT_TRUE(browsing_topics_service()
-                  ->GetTopicsForSiteForDisplay(/*top_origin=*/url::Origin())
-                  .empty());
-  EXPECT_TRUE(browsing_topics_service()->GetTopTopicsForDisplay().empty());
-}
-
-IN_PROC_BROWSER_TEST_F(BrowsingTopicsBrowserTest, EmptyPage_TopicsAPI) {
   GURL main_frame_url =
       https_server_.GetURL("a.test", "/browsing_topics/empty_page.html");
 
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_frame_url));
 
-  EXPECT_EQ("[]", InvokeTopicsAPI(web_contents()));
+  base::Time now = base::Time::Now();
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 3u);
+  EXPECT_EQ(browsing_topics_state().epochs()[0].calculation_time(), kTime1);
+  EXPECT_EQ(browsing_topics_state().epochs()[1].calculation_time(), kTime2);
+  EXPECT_GT(browsing_topics_state().epochs()[2].calculation_time(),
+            now - base::Minutes(1));
+  EXPECT_LT(browsing_topics_state().epochs()[2].calculation_time(), now);
+
+  ExpectResultTopicsEqual(
+      browsing_topics_state().epochs()[0].top_topics_and_observing_domains(),
+      {{Topic(1), {GetHashedDomain("a.test")}},
+       {Topic(2), {GetHashedDomain("a.test")}},
+       {Topic(3), {GetHashedDomain("a.test")}},
+       {Topic(4), {GetHashedDomain("a.test")}},
+       {Topic(5), {GetHashedDomain("a.test")}}});
+
+  ExpectResultTopicsEqual(
+      browsing_topics_state().epochs()[1].top_topics_and_observing_domains(),
+      {{Topic(6), {GetHashedDomain("a.test")}},
+       {Topic(7), {GetHashedDomain("a.test")}},
+       {Topic(8), {GetHashedDomain("a.test")}},
+       {Topic(9), {GetHashedDomain("a.test")}},
+       {Topic(10), {GetHashedDomain("a.test")}}});
+
+  ExpectResultTopicsEqual(
+      browsing_topics_state().epochs()[2].top_topics_and_observing_domains(),
+      {{Topic(6), {HashedDomain(1)}},
+       {Topic(5), {}},
+       {Topic(4), {}},
+       {Topic(3), {}},
+       {Topic(2), {}}});
+
+  EXPECT_GT(browsing_topics_state().next_scheduled_calculation_time(),
+            now + base::Days(7) - base::Minutes(1));
+  EXPECT_LT(browsing_topics_state().next_scheduled_calculation_time(),
+            now + base::Days(7));
+}
+
+IN_PROC_BROWSER_TEST_F(BrowsingTopicsBrowserTest, GetTopicsForSiteForDisplay) {
+  GURL main_frame_url =
+      https_server_.GetURL("a.test", "/browsing_topics/empty_page.html");
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_frame_url));
+
+  std::vector<privacy_sandbox::CanonicalTopic> result =
+      browsing_topics_service()->GetTopicsForSiteForDisplay(
+          web_contents()->GetMainFrame()->GetLastCommittedOrigin());
+
+  // Epoch switch time has not arrived. So expect one topic from each of the
+  // first two epochs.
+  EXPECT_EQ(result.size(), 2u);
+  EXPECT_EQ(result[0].topic_id(), Topic(1));
+  EXPECT_EQ(result[0].taxonomy_version(), 1);
+  EXPECT_EQ(result[1].topic_id(), Topic(10));
+  EXPECT_EQ(result[1].taxonomy_version(), 1);
+}
+
+IN_PROC_BROWSER_TEST_F(BrowsingTopicsBrowserTest, GetTopTopicsForDisplay) {
+  GURL main_frame_url =
+      https_server_.GetURL("a.test", "/browsing_topics/empty_page.html");
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_frame_url));
+
+  std::vector<privacy_sandbox::CanonicalTopic> result =
+      browsing_topics_service()->GetTopTopicsForDisplay();
+
+  EXPECT_EQ(result.size(), 15u);
+  EXPECT_EQ(result[0].topic_id(), Topic(1));
+  EXPECT_EQ(result[1].topic_id(), Topic(2));
+  EXPECT_EQ(result[2].topic_id(), Topic(3));
+  EXPECT_EQ(result[3].topic_id(), Topic(4));
+  EXPECT_EQ(result[4].topic_id(), Topic(5));
+  EXPECT_EQ(result[5].topic_id(), Topic(6));
+  EXPECT_EQ(result[6].topic_id(), Topic(7));
+  EXPECT_EQ(result[7].topic_id(), Topic(8));
+  EXPECT_EQ(result[8].topic_id(), Topic(9));
+  EXPECT_EQ(result[9].topic_id(), Topic(10));
+  EXPECT_EQ(result[10].topic_id(), Topic(6));
+  EXPECT_EQ(result[11].topic_id(), Topic(5));
+  EXPECT_EQ(result[12].topic_id(), Topic(4));
+  EXPECT_EQ(result[13].topic_id(), Topic(3));
+  EXPECT_EQ(result[14].topic_id(), Topic(2));
+}
+
+IN_PROC_BROWSER_TEST_F(BrowsingTopicsBrowserTest,
+                       TopicsAPI_ContextDomainNotFiltered_FromMainFrame) {
+  GURL main_frame_url =
+      https_server_.GetURL("a.test", "/browsing_topics/one_iframe_page.html");
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_frame_url));
+
+  std::string result = InvokeTopicsAPI(web_contents());
+
+  EXPECT_TRUE(result == kExpectedResultOrder1 ||
+              result == kExpectedResultOrder2);
+}
+
+IN_PROC_BROWSER_TEST_F(BrowsingTopicsBrowserTest,
+                       TopicsAPI_ContextDomainNotFiltered_FromSubframe) {
+  GURL main_frame_url =
+      https_server_.GetURL("a.test", "/browsing_topics/one_iframe_page.html");
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_frame_url));
+
+  GURL subframe_url =
+      https_server_.GetURL("a.test", "/browsing_topics/empty_page.html");
+
+  ASSERT_TRUE(content::NavigateIframeToURL(web_contents(),
+                                           /*iframe_id=*/"frame",
+                                           subframe_url));
+
+  std::string result =
+      InvokeTopicsAPI(content::ChildFrameAt(web_contents()->GetMainFrame(), 0));
+
+  EXPECT_TRUE(result == kExpectedResultOrder1 ||
+              result == kExpectedResultOrder2);
+}
+
+IN_PROC_BROWSER_TEST_F(BrowsingTopicsBrowserTest,
+                       TopicsAPI_ContextDomainFiltered) {
+  GURL main_frame_url =
+      https_server_.GetURL("a.test", "/browsing_topics/one_iframe_page.html");
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_frame_url));
+
+  GURL subframe_url =
+      https_server_.GetURL("b.test", "/browsing_topics/empty_page.html");
+
+  ASSERT_TRUE(content::NavigateIframeToURL(web_contents(),
+                                           /*iframe_id=*/"frame",
+                                           subframe_url));
+
+  // b.test has yet to call the API so it shouldn't receive a topic.
+  EXPECT_EQ("[]", InvokeTopicsAPI(content::ChildFrameAt(
+                      web_contents()->GetMainFrame(), 0)));
+}
+
+IN_PROC_BROWSER_TEST_F(BrowsingTopicsBrowserTest,
+                       TopicsAPI_ContextDomainTracked) {
+  GURL main_frame_url =
+      https_server_.GetURL("a.test", "/browsing_topics/one_iframe_page.html");
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_frame_url));
+
+  GURL subframe_url =
+      https_server_.GetURL("b.test", "/browsing_topics/empty_page.html");
+
+  ASSERT_TRUE(content::NavigateIframeToURL(web_contents(),
+                                           /*iframe_id=*/"frame",
+                                           subframe_url));
+
+  // The usage is not tracked before the API call. The returned entry was from
+  // the pre-existing storage.
+  std::vector<ApiUsageContext> api_usage_contexts =
+      content::GetBrowsingTopicsApiUsage(browsing_topics_site_data_manager());
+  EXPECT_EQ(api_usage_contexts.size(), 1u);
+
+  EXPECT_EQ("[]", InvokeTopicsAPI(content::ChildFrameAt(
+                      web_contents()->GetMainFrame(), 0)));
+
+  api_usage_contexts =
+      content::GetBrowsingTopicsApiUsage(browsing_topics_site_data_manager());
+
+  // The usage is tracked after the API call.
+  EXPECT_EQ(api_usage_contexts.size(), 2u);
+  EXPECT_EQ(api_usage_contexts[0].hashed_main_frame_host,
+            HashMainFrameHostForStorage("foo1.com"));
+  EXPECT_EQ(api_usage_contexts[0].hashed_context_domain, HashedDomain(1));
+
+  EXPECT_EQ(
+      api_usage_contexts[1].hashed_main_frame_host,
+      HashMainFrameHostForStorage(https_server_.GetURL("a.test", "/").host()));
+  EXPECT_EQ(api_usage_contexts[1].hashed_context_domain,
+            GetHashedDomain("b.test"));
 }
 
 IN_PROC_BROWSER_TEST_F(
@@ -181,7 +685,9 @@
                                            /*iframe_id=*/"frame",
                                            subframe_url));
 
-  EXPECT_EQ("[]", InvokeTopicsAPI(web_contents()));
+  std::string result = InvokeTopicsAPI(web_contents());
+  EXPECT_TRUE(result == kExpectedResultOrder1 ||
+              result == kExpectedResultOrder2);
 
   EXPECT_EQ(
       "The \"browsing-topics\" Permissions Policy denied the use of "
@@ -204,7 +710,9 @@
 
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_frame_url));
 
-  EXPECT_EQ("[]", InvokeTopicsAPI(web_contents()));
+  std::string result = InvokeTopicsAPI(web_contents());
+  EXPECT_TRUE(result == kExpectedResultOrder1 ||
+              result == kExpectedResultOrder2);
 
   GURL subframe_url =
       https_server_.GetURL("c.test", "/browsing_topics/empty_page.html");
@@ -270,4 +778,37 @@
     )"));
 }
 
+IN_PROC_BROWSER_TEST_F(BrowsingTopicsBrowserTest,
+                       TopicsAPINotAllowedInOpaqueOriginDocument) {
+  GURL main_frame_url = https_server_.GetURL(
+      "a.test", "/browsing_topics/one_sandboxed_iframe_page.html");
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_frame_url));
+
+  EXPECT_EQ(
+      "document.browsingTopics() is not allowed in an opaque origin context.",
+      InvokeTopicsAPI(
+          content::ChildFrameAt(web_contents()->GetMainFrame(), 0)));
+}
+
+IN_PROC_BROWSER_TEST_F(BrowsingTopicsBrowserTest,
+                       TopicsAPINotAllowedInFencedFrame) {
+  GURL main_frame_url =
+      https_server_.GetURL("a.test", "/browsing_topics/one_iframe_page.html");
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_frame_url));
+
+  GURL fenced_frame_url =
+      https_server_.GetURL("b.test", "/fenced_frames/title1.html");
+
+  content::RenderFrameHostWrapper fenced_frame_rfh_wrapper(
+      fenced_frame_test_helper_.CreateFencedFrame(
+          web_contents()->GetMainFrame(), fenced_frame_url));
+
+  EXPECT_EQ(
+      "document.browsingTopics() is only allowed in the primary main frame or "
+      "in its child iframes.",
+      InvokeTopicsAPI(fenced_frame_rfh_wrapper.get()));
+}
+
 }  // namespace browsing_topics
diff --git a/chrome/browser/browsing_topics/browsing_topics_service_factory.cc b/chrome/browser/browsing_topics/browsing_topics_service_factory.cc
index aa5a533..1947a7f 100644
--- a/chrome/browser/browsing_topics/browsing_topics_service_factory.cc
+++ b/chrome/browser/browsing_topics/browsing_topics_service_factory.cc
@@ -4,10 +4,19 @@
 
 #include "chrome/browser/browsing_topics/browsing_topics_service_factory.h"
 
+#include "chrome/browser/history/history_service_factory.h"
+#include "chrome/browser/optimization_guide/page_content_annotations_service_factory.h"
+#include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "components/browsing_topics/browsing_topics_service.h"
 #include "components/browsing_topics/browsing_topics_service_impl.h"
+#include "components/history/core/browser/history_service.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/keyed_service/core/service_access_type.h"
+#include "components/optimization_guide/content/browser/page_content_annotations_service.h"
+#include "components/privacy_sandbox/privacy_sandbox_settings.h"
+#include "content/public/browser/browsing_topics_site_data_manager.h"
+#include "content/public/browser/storage_partition.h"
 #include "third_party/blink/public/common/features.h"
 
 namespace browsing_topics {
@@ -28,7 +37,11 @@
 BrowsingTopicsServiceFactory::BrowsingTopicsServiceFactory()
     : BrowserContextKeyedServiceFactory(
           "BrowsingTopicsService",
-          BrowserContextDependencyManager::GetInstance()) {}
+          BrowserContextDependencyManager::GetInstance()) {
+  DependsOn(PrivacySandboxSettingsFactory::GetInstance());
+  DependsOn(HistoryServiceFactory::GetInstance());
+  DependsOn(PageContentAnnotationsServiceFactory::GetInstance());
+}
 
 BrowsingTopicsServiceFactory::~BrowsingTopicsServiceFactory() = default;
 
@@ -37,7 +50,32 @@
   if (!base::FeatureList::IsEnabled(blink::features::kBrowsingTopics))
     return nullptr;
 
-  return new BrowsingTopicsServiceImpl();
+  Profile* profile = Profile::FromBrowserContext(context);
+
+  privacy_sandbox::PrivacySandboxSettings* privacy_sandbox_settings =
+      PrivacySandboxSettingsFactory::GetForProfile(profile);
+  if (!privacy_sandbox_settings)
+    return nullptr;
+
+  history::HistoryService* history_service =
+      HistoryServiceFactory::GetForProfile(profile,
+                                           ServiceAccessType::IMPLICIT_ACCESS);
+  if (!history_service)
+    return nullptr;
+
+  content::BrowsingTopicsSiteDataManager* site_data_manager =
+      context->GetDefaultStoragePartition()->GetBrowsingTopicsSiteDataManager();
+  if (!site_data_manager)
+    return nullptr;
+
+  optimization_guide::PageContentAnnotationsService* annotations_service =
+      PageContentAnnotationsServiceFactory::GetForProfile(profile);
+  if (!annotations_service)
+    return nullptr;
+
+  return new BrowsingTopicsServiceImpl(
+      profile->GetPath(), privacy_sandbox_settings, history_service,
+      site_data_manager, annotations_service);
 }
 
 bool BrowsingTopicsServiceFactory::ServiceIsCreatedWithBrowserContext() const {
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 993c961..40b7f4772 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -35,6 +35,7 @@
 #include "chrome/browser/browser_about_handler.h"
 #include "chrome/browser/browser_features.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/browsing_topics/browsing_topics_service_factory.h"
 #include "chrome/browser/captive_portal/captive_portal_service_factory.h"
 #include "chrome/browser/chrome_content_browser_client_binder_policies.h"
 #include "chrome/browser/chrome_content_browser_client_parts.h"
@@ -174,6 +175,7 @@
 #include "chrome/installer/util/google_update_settings.h"
 #include "components/autofill/core/common/autofill_switches.h"
 #include "components/blocked_content/popup_blocker.h"
+#include "components/browsing_topics/browsing_topics_service.h"
 #include "components/captive_portal/core/buildflags.h"
 #include "components/cloud_devices/common/cloud_devices_switches.h"
 #include "components/content_settings/browser/page_specific_content_settings.h"
@@ -309,6 +311,7 @@
 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
 #include "third_party/blink/public/common/navigation/navigation_policy.h"
 #include "third_party/blink/public/common/switches.h"
+#include "third_party/blink/public/mojom/browsing_topics/browsing_topics.mojom.h"
 #include "third_party/blink/public/public_buildflags.h"
 #include "third_party/widevine/cdm/buildflags.h"
 #include "ui/base/clipboard/clipboard_format_type.h"
@@ -5981,6 +5984,23 @@
   }
 }
 
+std::vector<blink::mojom::EpochTopicPtr>
+ChromeContentBrowserClient::GetBrowsingTopicsForJsApi(
+    const url::Origin& context_origin,
+    content::RenderFrameHost* main_frame) {
+  browsing_topics::BrowsingTopicsService* browsing_topics_service =
+      browsing_topics::BrowsingTopicsServiceFactory::GetForProfile(
+          Profile::FromBrowserContext(
+              content::WebContents::FromRenderFrameHost(main_frame)
+                  ->GetBrowserContext()));
+
+  if (!browsing_topics_service)
+    return {};
+
+  return browsing_topics_service->GetBrowsingTopicsForJsApi(context_origin,
+                                                            main_frame);
+}
+
 bool ChromeContentBrowserClient::IsBluetoothScanningBlocked(
     content::BrowserContext* browser_context,
     const url::Origin& requesting_origin,
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 5e6de55c..e5a7bd9 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -680,6 +680,10 @@
       bool user_gesture,
       blink::NavigationDownloadPolicy* download_policy) override;
 
+  std::vector<blink::mojom::EpochTopicPtr> GetBrowsingTopicsForJsApi(
+      const url::Origin& context_origin,
+      content::RenderFrameHost* main_frame) override;
+
   bool IsBluetoothScanningBlocked(content::BrowserContext* browser_context,
                                   const url::Origin& requesting_origin,
                                   const url::Origin& embedding_origin) override;
diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc
index d60c68f..9cfc344 100644
--- a/chrome/browser/client_hints/client_hints_browsertest.cc
+++ b/chrome/browser/client_hints/client_hints_browsertest.cc
@@ -21,6 +21,7 @@
 #include "base/synchronization/lock.h"
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
@@ -1616,14 +1617,12 @@
       .GetLastCommittedEntry()
       ->SetIsOverridingUserAgent(true);
 
-  // Since no value was provided for client hints, they are sent with blank or
-  // false values.
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), kUrl));
   EXPECT_TRUE(ExecuteScriptAndExtractString(
       web_contents,
       "window.domAutomationController.send(document.body.textContent);",
       &header_value));
-  EXPECT_EQ("foo\n\n?0", header_value);
+  EXPECT_EQ("foo\nNone\nNone", header_value);
   EXPECT_TRUE(
       ExecuteScriptAndExtractString(web_contents,
                                     "window.domAutomationController.send(JSON."
@@ -1655,6 +1654,53 @@
       header_value);
 }
 
+class ClientHintsUAOverrideBrowserTest : public ClientHintsBrowserTest {
+ public:
+  void SetUp() override {
+    scoped_feature_list_.InitAndEnableFeature(
+        blink::features::kUACHOverrideBlank);
+    InProcessBrowserTest::SetUp();
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(ClientHintsUAOverrideBrowserTest,
+                       UserAgentOverrideClientHints) {
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  ASSERT_TRUE(embedded_test_server()->Start());
+  const std::string kHeaderPath = std::string("/echoheader?") +
+                                  net::HttpRequestHeaders::kUserAgent +
+                                  "&sec-ch-ua&sec-ch-ua-mobile";
+  const GURL kUrl(embedded_test_server()->GetURL(kHeaderPath));
+
+  web_contents->SetUserAgentOverride(
+      blink::UserAgentOverride::UserAgentOnly("foo"), false);
+  web_contents->GetController()
+      .GetLastCommittedEntry()
+      ->SetIsOverridingUserAgent(true);
+
+  // Since no value was provided for client hints, they are sent with blank or
+  // false values.
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), kUrl));
+
+  std::string header_value;
+  EXPECT_TRUE(ExecuteScriptAndExtractString(
+      web_contents,
+      "window.domAutomationController.send(document.body.textContent);",
+      &header_value));
+  EXPECT_EQ("foo\n\n?0", header_value);
+  EXPECT_TRUE(
+      ExecuteScriptAndExtractString(web_contents,
+                                    "window.domAutomationController.send(JSON."
+                                    "stringify(navigator.userAgentData));",
+                                    &header_value));
+  EXPECT_EQ(R"({"brands":[],"mobile":false})", header_value);
+}
+
 IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, EmptyAcceptCH) {
   // First navigate to a page that enables hints. No CH for it yet, since
   // nothing opted in.
@@ -3526,7 +3572,8 @@
   void SetUp() override {
     std::unique_ptr<base::FeatureList> feature_list =
         std::make_unique<base::FeatureList>();
-    feature_list->InitializeFromCommandLine("CriticalClientHint", "");
+    feature_list->InitializeFromCommandLine(
+        "CriticalClientHint,UACHOverrideBlank", "");
     scoped_feature_list_.InitWithFeatureList(std::move(feature_list));
 
     InProcessBrowserTest::SetUp();
diff --git a/chrome/browser/extensions/api/storage/settings_sync_processor.cc b/chrome/browser/extensions/api/storage/settings_sync_processor.cc
index 837a5f7..fed0471 100644
--- a/chrome/browser/extensions/api/storage/settings_sync_processor.cc
+++ b/chrome/browser/extensions/api/storage/settings_sync_processor.cc
@@ -52,28 +52,26 @@
   std::set<std::string> added_keys;
   std::set<std::string> deleted_keys;
 
-  for (auto i = changes.cbegin(); i != changes.cend(); ++i) {
-    const std::string& key = i->key();
-    const base::Value* value = i->new_value();
-    if (value) {
-      if (synced_keys_.count(key)) {
+  for (const auto& i : changes) {
+    if (i.new_value) {
+      if (synced_keys_.count(i.key)) {
         // New value, key is synced; send ACTION_UPDATE.
         sync_changes.push_back(settings_sync_util::CreateUpdate(
-            extension_id_, key, *value, type_));
+            extension_id_, i.key, *i.new_value, type_));
       } else {
         // New value, key is not synced; send ACTION_ADD.
         sync_changes.push_back(settings_sync_util::CreateAdd(
-            extension_id_, key, *value, type_));
-        added_keys.insert(key);
+            extension_id_, i.key, *i.new_value, type_));
+        added_keys.insert(i.key);
       }
     } else {
-      if (synced_keys_.count(key)) {
+      if (synced_keys_.count(i.key)) {
         // Clearing value, key is synced; send ACTION_DELETE.
-        sync_changes.push_back(settings_sync_util::CreateDelete(
-            extension_id_, key, type_));
-        deleted_keys.insert(key);
+        sync_changes.push_back(
+            settings_sync_util::CreateDelete(extension_id_, i.key, type_));
+        deleted_keys.insert(i.key);
       } else {
-        LOG(WARNING) << "Deleted " << key << " but not in synced_keys_";
+        LOG(WARNING) << "Deleted " << i.key << " but not in synced_keys_";
       }
     }
   }
@@ -99,11 +97,11 @@
   DCHECK(IsOnBackendSequence());
   CHECK(initialized_) << "Init not called";
 
-  for (auto i = changes.cbegin(); i != changes.cend(); ++i) {
-    if (i->new_value())
-      synced_keys_.insert(i->key());
+  for (const auto& i : changes) {
+    if (i.new_value)
+      synced_keys_.insert(i.key);
     else
-      synced_keys_.erase(i->key());
+      synced_keys_.erase(i.key);
   }
 }
 
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index ef195e84..4c32bcb 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -5446,6 +5446,11 @@
     "expiry_milestone" : 101
   },
   {
+    "name" : "side-panel-improved-clobbering",
+    "owners": [ "chrome-cros@google.com", "tluk" ],
+    "expiry_milestone" : 104
+  },
+  {
     "name" : "side-search",
     "owners": [ "chrome-cros@google.com", "tluk" ],
     "expiry_milestone" : 104
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 53be7637..d2bd35e 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2281,6 +2281,11 @@
 const char kSidePanelDragAndDropDescription[] =
     "Enables drag and drop of bookmarks within the side panel.";
 
+const char kSidePanelImprovedClobberingName[] =
+    "Side panel improved clobbering";
+const char kSidePanelImprovedClobberingDescription[] =
+    "Improves the side panel clobbering experience for RHS side panels.";
+
 const char kSharedClipboardUIName[] =
     "Enable shared clipboard feature signals to be handled";
 const char kSharedClipboardUIDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 1909e9bd..cd2f531 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1292,6 +1292,9 @@
 extern const char kSidePanelDragAndDropName[];
 extern const char kSidePanelDragAndDropDescription[];
 
+extern const char kSidePanelImprovedClobberingName[];
+extern const char kSidePanelImprovedClobberingDescription[];
+
 extern const char kSharedClipboardUIName[];
 extern const char kSharedClipboardUIDescription[];
 
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc
index 743fdbb..0df08811 100644
--- a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc
+++ b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc
@@ -9,12 +9,9 @@
 
 #include "base/bind.h"
 #include "base/metrics/user_metrics.h"
-#include "chrome/browser/permissions/permission_manager_factory.h"
-#include "chrome/browser/profiles/profile.h"
 #include "chrome/common/buildflags.h"
-#include "components/content_settings/core/common/content_settings_types.h"
-#include "components/permissions/permission_manager.h"
-#include "components/permissions/permission_request_id.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/permission_controller.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
@@ -31,8 +28,8 @@
 namespace {
 
 void CallbackWrapper(base::OnceCallback<void(bool)> callback,
-                     ContentSetting status) {
-  std::move(callback).Run(status == CONTENT_SETTING_ALLOW);
+                     blink::mojom::PermissionStatus status) {
+  std::move(callback).Run(status == blink::mojom::PermissionStatus::GRANTED);
 }
 
 }  // anonymous namespace
@@ -180,21 +177,21 @@
 
 void ChromeWebViewPermissionHelperDelegate::OnGeolocationPermissionResponse(
     bool user_gesture,
-    base::OnceCallback<void(ContentSetting)> callback,
+    base::OnceCallback<void(blink::mojom::PermissionStatus)> callback,
     bool allow,
     const std::string& user_input) {
   // The <webview> embedder has allowed the permission. We now need to make sure
   // that the embedder has geolocation permission.
   if (!allow || !web_view_guest()->attached()) {
-    std::move(callback).Run(CONTENT_SETTING_BLOCK);
+    std::move(callback).Run(blink::mojom::PermissionStatus::DENIED);
     return;
   }
 
-  Profile* profile = Profile::FromBrowserContext(
-      web_view_guest()->browser_context());
-  PermissionManagerFactory::GetForProfile(profile)
+  web_view_guest()
+      ->browser_context()
+      ->GetPermissionController()
       ->RequestPermissionFromCurrentDocument(
-          ContentSettingsType::GEOLOCATION,
+          content::PermissionType::GEOLOCATION,
           web_view_guest()->embedder_web_contents()->GetMainFrame(),
           user_gesture, std::move(callback));
 }
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h
index b6cf199..8be3b28 100644
--- a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h
+++ b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h
@@ -6,7 +6,6 @@
 #define CHROME_BROWSER_GUEST_VIEW_WEB_VIEW_CHROME_WEB_VIEW_PERMISSION_HELPER_DELEGATE_H_
 
 #include "chrome/common/buildflags.h"
-#include "components/content_settings/core/common/content_settings.h"
 #include "content/public/browser/render_frame_host_receiver_set.h"
 #include "extensions/browser/guest_view/web_view/web_view_permission_helper.h"
 #include "extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.h"
@@ -77,7 +76,7 @@
 
   void OnGeolocationPermissionResponse(
       bool user_gesture,
-      base::OnceCallback<void(ContentSetting)> callback,
+      base::OnceCallback<void(blink::mojom::PermissionStatus)> callback,
       bool allow,
       const std::string& user_input);
 
diff --git a/chrome/browser/image_decoder/image_decoder.cc b/chrome/browser/image_decoder/image_decoder.cc
index 9305a91..d4fecdf 100644
--- a/chrome/browser/image_decoder/image_decoder.cc
+++ b/chrome/browser/image_decoder/image_decoder.cc
@@ -98,8 +98,8 @@
 
 // static
 ImageDecoder* ImageDecoder::GetInstance() {
-  static auto* image_decoder = new ImageDecoder();
-  return image_decoder;
+  static base::NoDestructor<ImageDecoder> image_decoder;
+  return image_decoder.get();
 }
 
 // static
diff --git a/chrome/browser/image_decoder/image_decoder.h b/chrome/browser/image_decoder/image_decoder.h
index 84e2936..5ee9612 100644
--- a/chrome/browser/image_decoder/image_decoder.h
+++ b/chrome/browser/image_decoder/image_decoder.h
@@ -11,6 +11,7 @@
 
 #include "base/memory/raw_ptr.h"
 #include "base/memory/ref_counted.h"
+#include "base/no_destructor.h"
 #include "base/sequence_checker.h"
 #include "base/synchronization/lock.h"
 #include "base/task/sequenced_task_runner.h"
@@ -117,6 +118,7 @@
   static void Cancel(ImageRequest* image_request);
 
  private:
+  friend base::NoDestructor<ImageDecoder>;
   using RequestMap = std::map<int, ImageRequest*>;
 
   ImageDecoder();
diff --git a/chrome/browser/lifetime/browser_close_manager.cc b/chrome/browser/lifetime/browser_close_manager.cc
index 7bc9254..8601ee1 100644
--- a/chrome/browser/lifetime/browser_close_manager.cc
+++ b/chrome/browser/lifetime/browser_close_manager.cc
@@ -120,7 +120,12 @@
     int download_count,
     base::OnceCallback<void(bool)> callback) {
   Browser* browser = BrowserList::GetInstance()->GetLastActive();
-  DCHECK(browser);
+  if (browser == nullptr) {
+    // Background may call CloseAllBrowsers() with no Browsers. In this
+    // case immediately continue with shutting down.
+    std::move(callback).Run(/* proceed= */ true);
+    return;
+  }
   browser->window()->ConfirmBrowserCloseWithPendingDownloads(
       download_count, Browser::DownloadCloseType::kBrowserShutdown,
       std::move(callback));
diff --git a/chrome/browser/media/cdm_document_service_impl.cc b/chrome/browser/media/cdm_document_service_impl.cc
index bd662dc..16a5800a 100644
--- a/chrome/browser/media/cdm_document_service_impl.cc
+++ b/chrome/browser/media/cdm_document_service_impl.cc
@@ -361,6 +361,11 @@
   CdmPrefServiceHelper::SetCdmClientToken(user_prefs, cdm_origin, client_token);
 }
 
+void CdmDocumentServiceImpl::OnCdmEvent(media::CdmEvent event) {
+  DVLOG(1) << __func__ << ": event=" << static_cast<int>(event);
+  NOTIMPLEMENTED();
+}
+
 // This function goes over each folder located under the MediaFoundationCdm
 // store root path and delete them as needed. A folder needs to be deleted for
 // the following reason:
diff --git a/chrome/browser/media/cdm_document_service_impl.h b/chrome/browser/media/cdm_document_service_impl.h
index 1e36ac3..951f9853 100644
--- a/chrome/browser/media/cdm_document_service_impl.h
+++ b/chrome/browser/media/cdm_document_service_impl.h
@@ -51,6 +51,7 @@
   void GetMediaFoundationCdmData(
       GetMediaFoundationCdmDataCallback callback) final;
   void SetCdmClientToken(const std::vector<uint8_t>& client_token) final;
+  void OnCdmEvent(media::CdmEvent event) final;
 
   static void ClearCdmData(
       Profile* profile,
diff --git a/chrome/browser/media/platform_verification_chromeos.cc b/chrome/browser/media/platform_verification_chromeos.cc
index 396c4da..a88be9b 100644
--- a/chrome/browser/media/platform_verification_chromeos.cc
+++ b/chrome/browser/media/platform_verification_chromeos.cc
@@ -5,11 +5,8 @@
 #include "chrome/browser/media/platform_verification_chromeos.h"
 
 #include "base/metrics/histogram_macros.h"
-#include "chrome/browser/permissions/permission_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "components/content_settings/core/common/content_settings.h"
-#include "components/permissions/permission_manager.h"
-#include "components/permissions/permission_util.h"
+#include "content/public/browser/permission_controller.h"
 #include "content/public/browser/web_contents.h"
 #include "url/gurl.h"
 
@@ -35,15 +32,11 @@
 // Whether platform verification is permitted by the user-configurable content
 // setting.
 bool IsPermittedByContentSettings(content::RenderFrameHost* render_frame_host) {
-  ContentSetting content_setting =
-      PermissionManagerFactory::GetForProfile(
-          Profile::FromBrowserContext(render_frame_host->GetBrowserContext()))
-          ->GetPermissionStatusForCurrentDocument(
-              ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER,
-              render_frame_host)
-          .content_setting;
-
-  return content_setting == CONTENT_SETTING_ALLOW;
+  return render_frame_host->GetBrowserContext()
+             ->GetPermissionController()
+             ->GetPermissionStatusForCurrentDocument(
+                 content::PermissionType::PROTECTED_MEDIA_IDENTIFIER,
+                 render_frame_host) == blink::mojom::PermissionStatus::GRANTED;
 }
 
 // Whether platform verification is permitted by the profile type. Currently
diff --git a/chrome/browser/media/platform_verification_chromeos_unittest.cc b/chrome/browser/media/platform_verification_chromeos_unittest.cc
index 361858a..768d299 100644
--- a/chrome/browser/media/platform_verification_chromeos_unittest.cc
+++ b/chrome/browser/media/platform_verification_chromeos_unittest.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/permissions/test/permission_test_util.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/web_contents_tester.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -23,6 +24,8 @@
     : public ChromeRenderViewHostTestHarness {
   void SetUp() override {
     ChromeRenderViewHostTestHarness::SetUp();
+    profile()->SetPermissionControllerDelegate(
+        permissions::GetPermissionControllerDelegate(profile()));
     NavigateAndCommit(GetTestURL());
   }
 };
diff --git a/chrome/browser/notifications/notifier_state_tracker.cc b/chrome/browser/notifications/notifier_state_tracker.cc
index b6eb67ad..c65110b9 100644
--- a/chrome/browser/notifications/notifier_state_tracker.cc
+++ b/chrome/browser/notifications/notifier_state_tracker.cc
@@ -14,16 +14,14 @@
 #include "base/values.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
-#include "chrome/browser/permissions/permission_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
-#include "components/content_settings/core/common/content_settings_types.h"
-#include "components/permissions/permission_manager.h"
-#include "components/permissions/permission_result.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/scoped_user_pref_update.h"
+#include "content/public/browser/permission_controller.h"
 #include "extensions/buildflags/buildflags.h"
 #include "ui/message_center/public/cpp/notifier_id.h"
+#include "url/origin.h"
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
 #include "chrome/common/extensions/api/notifications.h"
@@ -69,10 +67,11 @@
       return disabled_extension_ids_.find(notifier_id.id) ==
           disabled_extension_ids_.end();
     case message_center::NotifierType::WEB_PAGE:
-      return PermissionManagerFactory::GetForProfile(profile_)
-                 ->GetPermissionStatus(ContentSettingsType::NOTIFICATIONS,
-                                       notifier_id.url, notifier_id.url)
-                 .content_setting == CONTENT_SETTING_ALLOW;
+      return profile_->GetPermissionController()
+                 ->GetPermissionStatusForOriginWithoutContext(
+                     content::PermissionType::NOTIFICATIONS,
+                     url::Origin::Create(notifier_id.url)) ==
+             blink::mojom::PermissionStatus::GRANTED;
     case message_center::NotifierType::SYSTEM_COMPONENT:
       // We do not disable system component notifications.
       return true;
diff --git a/chrome/browser/notifications/web_page_notifier_controller_unittest.cc b/chrome/browser/notifications/web_page_notifier_controller_unittest.cc
index 85d25a0..1332470 100644
--- a/chrome/browser/notifications/web_page_notifier_controller_unittest.cc
+++ b/chrome/browser/notifications/web_page_notifier_controller_unittest.cc
@@ -16,6 +16,7 @@
 #include "components/content_settings/core/test/content_settings_mock_provider.h"
 #include "components/content_settings/core/test/content_settings_test_utils.h"
 #include "components/favicon/core/test/mock_favicon_service.h"
+#include "components/permissions/test/permission_test_util.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -80,6 +81,9 @@
                             base::BindRepeating(&BuildMockFaviconService));
   profile = builder.Build();
 
+  profile->SetPermissionControllerDelegate(
+      permissions::GetPermissionControllerDelegate(profile.get()));
+
   auto* host_content_settings_map =
       HostContentSettingsMapFactory::GetForProfile(profile.get());
 
diff --git a/chrome/browser/page_load_metrics/observers/multi_tab_loading_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/multi_tab_loading_page_load_metrics_observer_browsertest.cc
index c8bb5d6..6cd75239 100644
--- a/chrome/browser/page_load_metrics/observers/multi_tab_loading_page_load_metrics_observer_browsertest.cc
+++ b/chrome/browser/page_load_metrics/observers/multi_tab_loading_page_load_metrics_observer_browsertest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/page_load_metrics/observers/multi_tab_loading_page_load_metrics_observer.h"
 
 #include "base/test/metrics/histogram_tester.h"
+#include "build/build_config.h"
 #include "chrome/browser/page_load_metrics/observers/histogram_suffixes.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -56,8 +57,14 @@
       0);
 }
 
+// TODO(crbug.com/1310328): Test is flaky on Linux.
+#if BUILDFLAG(IS_LINUX)
+#define MAYBE_MultiTabForeground DISABLED_MultiTabForeground
+#else
+#define MAYBE_MultiTabForeground MultiTabForeground
+#endif
 IN_PROC_BROWSER_TEST_F(MultiTabLoadingPageLoadMetricsBrowserTest,
-                       MultiTabForeground) {
+                       MAYBE_MultiTabForeground) {
   base::HistogramTester histogram_tester;
 
   NavigateToURLWithoutWaiting(embedded_test_server()->GetURL("/hung"));
diff --git a/chrome/browser/performance_manager/mechanisms/page_freezer.cc b/chrome/browser/performance_manager/mechanisms/page_freezer.cc
index 3b915929..f7e0715 100644
--- a/chrome/browser/performance_manager/mechanisms/page_freezer.cc
+++ b/chrome/browser/performance_manager/mechanisms/page_freezer.cc
@@ -6,15 +6,13 @@
 
 #include "base/bind.h"
 #include "base/task/task_traits.h"
-#include "chrome/browser/permissions/permission_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/content_settings/core/common/content_settings_types.h"
 #include "components/performance_manager/public/graph/page_node.h"
 #include "components/performance_manager/public/web_contents_proxy.h"
-#include "components/permissions/permission_manager.h"
-#include "components/permissions/permission_result.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/permission_controller.h"
 #include "content/public/browser/visibility.h"
 #include "content/public/browser/web_contents.h"
 
@@ -29,20 +27,18 @@
   if (!contents)
     return;
 
-  const GURL last_committed_origin =
-      permissions::PermissionUtil::GetLastCommittedOriginAsURL(contents);
+  content::PermissionController* permission_controller =
+      contents->GetBrowserContext()->GetPermissionController();
 
   // Page with the notification permission shouldn't be frozen as this is a
   // strong signal that the user wants to receive updates from this page while
   // it's in background. This information isn't available in the PM graph, this
   // has to be checked on the UI thread.
-  auto notif_permission =
-      PermissionManagerFactory::GetForProfile(
-          Profile::FromBrowserContext(contents->GetBrowserContext()))
-          ->GetPermissionStatus(ContentSettingsType::NOTIFICATIONS,
-                                last_committed_origin, last_committed_origin);
-  if (notif_permission.content_setting == CONTENT_SETTING_ALLOW)
+  if (permission_controller->GetPermissionStatusForCurrentDocument(
+          content::PermissionType::NOTIFICATIONS, contents->GetMainFrame()) ==
+      blink::mojom::PermissionStatus::GRANTED) {
     return;
+  }
 
   contents->SetPageFrozen(true);
 }
diff --git a/chrome/browser/performance_manager/mechanisms/page_freezer_unittest.cc b/chrome/browser/performance_manager/mechanisms/page_freezer_unittest.cc
index d50481c..e87181d8 100644
--- a/chrome/browser/performance_manager/mechanisms/page_freezer_unittest.cc
+++ b/chrome/browser/performance_manager/mechanisms/page_freezer_unittest.cc
@@ -4,20 +4,14 @@
 
 #include "chrome/browser/performance_manager/mechanisms/page_freezer.h"
 
-#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h"
-#include "chrome/browser/permissions/permission_manager_factory.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
-#include "components/content_settings/browser/page_specific_content_settings.h"
 #include "components/performance_manager/public/performance_manager.h"
 #include "components/performance_manager/test_support/performance_manager_test_harness.h"
 #include "components/performance_manager/test_support/test_harness_helper.h"
-#include "components/permissions/permission_manager.h"
-#include "components/permissions/permission_request_manager.h"
-#include "components/permissions/permission_result.h"
-#include "components/permissions/test/mock_permission_prompt_factory.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/test/mock_permission_controller.h"
 #include "content/public/test/web_contents_tester.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
@@ -127,28 +121,11 @@
 TEST_F(PageFreezerTest, CantFreezePageWithNotificationPermission) {
   SetContents(CreateTestWebContents());
 
-  // Give the notification permission to |web_contents()|.
-  permissions::PermissionRequestManager::CreateForWebContents(web_contents());
-  content_settings::PageSpecificContentSettings::CreateForWebContents(
-      web_contents(),
-      std::make_unique<chrome::PageSpecificContentSettingsDelegate>(
-          web_contents()));
-  auto* manager =
-      permissions::PermissionRequestManager::FromWebContents(web_contents());
-  permissions::MockPermissionPromptFactory mock_prompt_factory(manager);
-  NavigateAndCommit(GURL(kUrl));
-  manager->DocumentOnLoadCompletedInPrimaryMainFrame();
+  // Allow permissions.
+  GetBrowserContext()->SetPermissionControllerForTesting(
+      std::make_unique<content::MockPermissionController>());
 
-  base::RunLoop run_loop;
-  PermissionManagerFactory::GetForProfile(profile())->RequestPermission(
-      ContentSettingsType::NOTIFICATIONS, main_rfh(), GURL(kUrl), true,
-      base::BindOnce([](ContentSetting content_setting) {
-        EXPECT_EQ(content_setting, CONTENT_SETTING_ALLOW);
-      }).Then(run_loop.QuitClosure()));
-  task_environment()->RunUntilIdle();
-  ASSERT_TRUE(manager->IsRequestInProgress());
-  manager->Accept();
-  run_loop.Run();
+  NavigateAndCommit(GURL(kUrl));
 
   // Try to freeze the page node, this should fail.
   MaybeFreezePageNode(web_contents());
diff --git a/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_consent.xml b/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_consent.xml
index dfc7aff3..4c0aa6d 100644
--- a/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_consent.xml
+++ b/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_consent.xml
@@ -54,14 +54,14 @@
                     android:layout_height="wrap_content"
                     android:textAlignment="center"
                     android:text="@string/privacy_sandbox_consent_subtitle"
-                    style="@style/TextAppearance.TextMedium.Primary" />
+                    style="@style/TextAppearance.TextLarge.Primary" />
 
                 <TextView
                     android:layout_marginBottom="@dimen/promo_between_text_margin"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/privacy_sandbox_consent_heading_one"
-                    style="@style/TextAppearance.TextMedium.Primary" />
+                    style="@style/TextAppearance.TextLarge.Primary" />
 
                 <TextView
                     android:layout_marginBottom="@dimen/list_item_default_margin"
@@ -75,7 +75,7 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/privacy_sandbox_consent_heading_two"
-                    style="@style/TextAppearance.TextMedium.Primary" />
+                    style="@style/TextAppearance.TextLarge.Primary" />
 
                 <TextView
                     android:layout_marginBottom="@dimen/list_item_default_margin"
diff --git a/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_notice.xml b/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_notice.xml
index b024bede..0d62e268 100644
--- a/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_notice.xml
+++ b/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_notice.xml
@@ -54,7 +54,7 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/privacy_sandbox_consent_heading_one"
-                    style="@style/TextAppearance.TextMedium.Primary" />
+                    style="@style/TextAppearance.TextLarge.Primary" />
 
                 <TextView
                     android:layout_marginBottom="@dimen/list_item_default_margin"
@@ -68,7 +68,7 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/privacy_sandbox_consent_heading_two"
-                    style="@style/TextAppearance.TextMedium.Primary" />
+                    style="@style/TextAppearance.TextLarge.Primary" />
 
                 <TextView
                     android:layout_marginBottom="@dimen/promo_between_text_margin"
diff --git a/chrome/browser/resource_coordinator/session_restore_policy.cc b/chrome/browser/resource_coordinator/session_restore_policy.cc
index 4e6e78f..4380d69 100644
--- a/chrome/browser/resource_coordinator/session_restore_policy.cc
+++ b/chrome/browser/resource_coordinator/session_restore_policy.cc
@@ -30,15 +30,13 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/permission_controller.h"
 #include "content/public/browser/web_contents.h"
 
 #if !BUILDFLAG(IS_ANDROID)
-#include "chrome/browser/permissions/permission_manager_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "components/permissions/permission_manager.h"
-#include "components/permissions/permission_result.h"
 #endif
 
 namespace resource_coordinator {
@@ -206,15 +204,14 @@
   if (!tab_data->is_pinned && reader_data.updates_title_in_bg)
     used_in_bg = true;
 
-  const GURL last_committed_origin =
-      permissions::PermissionUtil::GetLastCommittedOriginAsURL(contents);
-  auto notif_permission =
-      PermissionManagerFactory::GetForProfile(
-          Profile::FromBrowserContext(contents->GetBrowserContext()))
-          ->GetPermissionStatus(ContentSettingsType::NOTIFICATIONS,
-                                last_committed_origin, last_committed_origin);
-  if (notif_permission.content_setting == CONTENT_SETTING_ALLOW)
+  content::PermissionController* permission_controller =
+      contents->GetBrowserContext()->GetPermissionController();
+
+  if (permission_controller->GetPermissionStatusForCurrentDocument(
+          content::PermissionType::NOTIFICATIONS, contents->GetMainFrame()) ==
+      blink::mojom::PermissionStatus::GRANTED) {
     used_in_bg = true;
+  }
 
   tab_data->used_in_bg = used_in_bg;
 }
diff --git a/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc b/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc
index bd832c9..8732d87 100644
--- a/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc
+++ b/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc
@@ -15,7 +15,6 @@
 #include "base/test/bind.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "build/build_config.h"
-#include "chrome/browser/notifications/notification_permission_context.h"
 #if !BUILDFLAG(IS_ANDROID)
 #include "chrome/browser/performance_manager/test_support/site_data_utils.h"
 #endif
@@ -27,6 +26,7 @@
 #include "components/performance_manager/public/decorators/site_data_recorder.h"
 #include "components/performance_manager/public/performance_manager.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/test/mock_permission_controller.h"
 #include "content/public/test/web_contents_tester.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -457,10 +457,8 @@
 
   // Allow |contents1_| to display notifications, this should cause the
   // |used_in_bg| bit to change to true.
-  NotificationPermissionContext::UpdatePermission(
-      profile(),
-      contents1_.get()->GetMainFrame()->GetLastCommittedOrigin().GetURL(),
-      CONTENT_SETTING_ALLOW);
+  GetBrowserContext()->SetPermissionControllerForTesting(
+      std::make_unique<content::MockPermissionController>());
 
   // Adding/Removing the tab for scoring will cause the callback to be called a
   // few times, ignore this.
diff --git a/chrome/browser/resources/history/history_clusters/clusters.html b/chrome/browser/resources/history/history_clusters/clusters.html
index b5efb5c..8a0de28 100644
--- a/chrome/browser/resources/history/history_clusters/clusters.html
+++ b/chrome/browser/resources/history/history_clusters/clusters.html
@@ -6,18 +6,13 @@
     overflow-y: auto;
   }
 
-  #clusters,
-  #header {
+  #clusters {
     margin: 0 auto;
     max-width: var(--cluster-max-width);
     min-width: var(--cluster-min-width);
     padding: var(--first-cluster-padding-top) var(--cluster-padding-horizontal) 0;
   }
 
-  #header {
-    font-size: 1.25rem;  /* 20px */
-  }
-
   #placeholder {
     font-size: inherit;
   }
@@ -29,7 +24,6 @@
         0 var(--cluster-padding-horizontal) var(--cluster-padding-vertical);
   }
 </style>
-<div id="header" hidden="[[!headerText_]]">[[headerText_]]</div>
 <div id="placeholder" class="centered-message" hidden="[[!placeholderText_]]">
   [[placeholderText_]]
 </div>
diff --git a/chrome/browser/resources/history/history_clusters/clusters.ts b/chrome/browser/resources/history/history_clusters/clusters.ts
index a599e8a..f499ebd 100644
--- a/chrome/browser/resources/history/history_clusters/clusters.ts
+++ b/chrome/browser/resources/history/history_clusters/clusters.ts
@@ -72,14 +72,6 @@
       },
 
       /**
-       * The header text to show when the query and the results are non-empty.
-       */
-      headerText_: {
-        type: String,
-        computed: `computeHeaderText_(result_.*)`,
-      },
-
-      /**
        * The placeholder text to show when the results are empty.
        */
       placeholderText_: {
@@ -257,12 +249,6 @@
   // Helper methods
   //============================================================================
 
-  private computeHeaderText_(): string {
-    return this.result_ && this.result_.query && this.result_.clusters.length ?
-        loadTimeData.getStringF('headerText', this.result_.query) :
-        '';
-  }
-
   private computePlaceholderText_(): string {
     if (!this.result_) {
       return '';
diff --git a/chrome/browser/resources/new_tab_page/modules/modules.html b/chrome/browser/resources/new_tab_page/modules/modules.html
index cb20987f4..60e187c 100644
--- a/chrome/browser/resources/new_tab_page/modules/modules.html
+++ b/chrome/browser/resources/new_tab_page/modules/modules.html
@@ -5,6 +5,14 @@
     --ntp-module-container-padding-top: 16px;
   }
 
+  @media (min-width: 672px) {
+    #firstRunExperience {
+      background-image: url(./modules/chromefetti.svg);
+      background-position: top center;
+      background-repeat: no-repeat;
+    }
+  }
+
   :host([show-modules-fre_]) #freAndModulesContainer {
     background-color: var(--ntp-background-override-color);
     border: 1px solid var(--ntp-border-color);
@@ -13,9 +21,6 @@
   }
 
   #firstRunExperience {
-    background-image: url(./modules/chromefetti.svg);
-    background-position: top center;
-    background-repeat: no-repeat;
     box-sizing: border-box;
     padding-bottom: 24px;
     padding-top: 32px;
@@ -51,6 +56,7 @@
   #customizeChromeLink {
     color: var(--cr-link-color);
     cursor: pointer;
+    font-weight: 700;
   }
 
   .action-button {
@@ -103,9 +109,9 @@
 <div id="freAndModulesContainer">
   <template is="dom-if" if="[[showModulesFre_]]">
     <div id="firstRunExperience">
-      <div id="firstRunExperienceTitle">
+      <header id="firstRunExperienceTitle">
         $i18n{modulesFirstRunExperienceTitle}
-      </div>
+      </header>
       <div id="newTag">$i18n{modulesNewTagLabel}</div>
       <div class="first-run-experience-body">
         $i18n{modulesFirstRunExperienceBodyLine1}
diff --git a/chrome/browser/resources/new_tab_page/modules/modules.ts b/chrome/browser/resources/new_tab_page/modules/modules.ts
index 7bc04e98..771eaba 100644
--- a/chrome/browser/resources/new_tab_page/modules/modules.ts
+++ b/chrome/browser/resources/new_tab_page/modules/modules.ts
@@ -92,6 +92,11 @@
         value: false,
       },
 
+      modulesFreRemoved_: {
+        type: Boolean,
+        value: false,
+      },
+
       /**
        * When the first run experience (FRE) is disabled and modules are
        * enabled, we show the modules without a FRE.
@@ -131,6 +136,7 @@
   private modulesLoadedAndVisibilityDetermined_: boolean;
   private modulesShownToUser_: boolean;
   private modulesFreVisible_: boolean;
+  private modulesFreRemoved_: boolean;
   private showModulesFre_: boolean;
   private dragEnabled_: boolean;
 
@@ -393,6 +399,10 @@
     this.$.removeModuleToast.hide();
 
     this.removedModuleData_ = null;
+
+    // Prevent user from resurfacing FRE when they are undoing removal of
+    // module.
+    this.modulesFreRemoved_ = false;
   }
 
   /**
@@ -436,14 +446,21 @@
     // restored if FRE opt out is undone.
     this.removedModuleData_ = null;
 
+    this.modulesFreRemoved_ = true;
+
     // Notify the user
     this.$.removeModuleFreToast.show();
   }
 
   private onUndoRemoveModuleFreButtonClick_() {
+    if (!this.modulesFreRemoved_) {
+      return;
+    }
+
     NewTabPageProxy.getInstance().handler.setModulesFreVisible(true);
     NewTabPageProxy.getInstance().handler.setModulesVisible(true);
     this.$.removeModuleFreToast.hide();
+    this.modulesFreRemoved_ = false;
   }
 
   /**
diff --git a/chrome/browser/resources/ntp4/apps_page.js b/chrome/browser/resources/ntp4/apps_page.js
index bf98437..12ddaf6 100644
--- a/chrome/browser/resources/ntp4/apps_page.js
+++ b/chrome/browser/resources/ntp4/apps_page.js
@@ -195,6 +195,7 @@
         !app.appData.mayChangeLaunchType || !hasLaunchType;
 
     this.options_.disabled = !app.appData.optionsUrl || !app.appData.enabled;
+    this.options_.hidden = app.appData.optionsUrl === undefined;
 
     this.uninstall_.disabled = !app.appData.mayDisable;
 
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc
index a579074..9b3be057 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc
@@ -21,6 +21,7 @@
 #include "build/branding_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/enterprise/connectors/connectors_manager.h"
+#include "chrome/browser/enterprise/util/affiliation.h"
 #include "chrome/browser/policy/chrome_browser_policy_connector.h"
 #include "chrome/browser/policy/dm_token_utils.h"
 #include "chrome/browser/profiles/profile.h"
@@ -29,6 +30,7 @@
 #include "chrome/browser/safe_browsing/cloud_content_scanning/binary_fcm_service.h"
 #include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.h"
 #include "chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
 #include "components/enterprise/common/proto/connectors.pb.h"
 #include "components/enterprise/common/strings.h"
 #include "components/prefs/pref_service.h"
@@ -353,6 +355,27 @@
       base::Minutes(6), 50);
 
   request->set_fcm_token(instance_id);
+
+  if (base::FeatureList::IsEnabled(kConnectorsScanningAccessToken) &&
+      chrome::enterprise_util::IsProfileAffiliated(profile_)) {
+    if (!token_fetcher_) {
+      token_fetcher_ = std::make_unique<SafeBrowsingPrimaryAccountTokenFetcher>(
+          IdentityManagerFactory::GetForProfile(profile_));
+    }
+    token_fetcher_->Start(base::BindOnce(&BinaryUploadService::OnGetAccessToken,
+                                         weakptr_factory_.GetWeakPtr(),
+                                         request));
+    return;
+  }
+
+  request->GetRequestData(base::BindOnce(&BinaryUploadService::OnGetRequestData,
+                                         weakptr_factory_.GetWeakPtr(),
+                                         request));
+}
+
+void BinaryUploadService::OnGetAccessToken(Request* request,
+                                           const std::string& access_token) {
+  request->set_access_token(access_token);
   request->GetRequestData(base::BindOnce(&BinaryUploadService::OnGetRequestData,
                                          weakptr_factory_.GetWeakPtr(),
                                          request));
@@ -409,6 +432,7 @@
                   enterprise_connectors::ContentAnalysisResponse());
     return;
   }
+  upload_request->set_access_token(request->access_token());
 
   WebUIInfoSingleton::GetInstance()->AddToDeepScanRequests(
       request->tab_url(), request->per_profile_request(),
@@ -769,6 +793,15 @@
   return false;
 }
 
+const std::string& BinaryUploadService::Request::access_token() const {
+  return access_token_;
+}
+
+void BinaryUploadService::Request::set_access_token(
+    const std::string& access_token) {
+  access_token_ = access_token;
+}
+
 bool BinaryUploadService::IsActive(Request* request) {
   return (active_requests_.find(request) != active_requests_.end());
 }
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h
index 5b8ff79..de345eb 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h
@@ -25,6 +25,7 @@
 #include "chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.h"
 #include "components/enterprise/common/proto/connectors.pb.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.h"
 #include "components/safe_browsing/core/common/proto/csd.pb.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
@@ -197,6 +198,9 @@
     // optimizations such as omitting FCM code paths for auth requests.
     virtual bool IsAuthRequest() const;
 
+    const std::string& access_token() const;
+    void set_access_token(const std::string& access_token);
+
    private:
     enterprise_connectors::ContentAnalysisRequest content_analysis_request_;
     ContentAnalysisCallback content_analysis_callback_;
@@ -209,6 +213,9 @@
 
     // Indicates if the request was triggered by a profile-level policy or not.
     bool per_profile_request_ = false;
+
+    // Access token to be attached in the request headers.
+    std::string access_token_;
   };
 
   // Upload the given file contents for deep scanning if the browser is
@@ -263,6 +270,8 @@
 
   void OnGetInstanceID(Request* request, const std::string& token);
 
+  void OnGetAccessToken(Request* request, const std::string& access_token);
+
   void OnGetRequestData(Request* request, Result result, Request::Data data);
 
   void OnUploadComplete(Request* request,
@@ -351,6 +360,9 @@
   // hours.
   base::RepeatingTimer timer_;
 
+  // Used to obtain an access token to attach to requests.
+  std::unique_ptr<SafeBrowsingTokenFetcher> token_fetcher_;
+
   base::WeakPtrFactory<BinaryUploadService> weakptr_factory_;
 };
 
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.cc b/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.cc
index 2bacd1e8..aa6e7e6 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.cc
@@ -18,6 +18,7 @@
 #include "base/time/time.h"
 #include "chrome/browser/safe_browsing/cloud_content_scanning/multipart_data_pipe_getter.h"
 #include "components/safe_browsing/core/common/features.h"
+#include "components/safe_browsing/core/common/utils.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "mojo/public/c/system/data_pipe.h"
@@ -162,7 +163,13 @@
   resource_request->url = base_url_;
   resource_request->method = "POST";
   resource_request->headers.SetHeader("X-Goog-Upload-Protocol", "multipart");
-  resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
+
+  if (access_token_.empty()) {
+    resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
+  } else {
+    SetAccessTokenAndClearCookieInResourceRequest(resource_request.get(),
+                                                  access_token_);
+  }
 
   switch (data_source_) {
     case STRING:
@@ -176,7 +183,7 @@
       break;
     default:
       NOTREACHED();
-  };
+  }
 }
 
 void MultipartUploadRequest::SendStringRequest(
@@ -374,4 +381,8 @@
                                      std::move(callback));
 }
 
+void MultipartUploadRequest::set_access_token(const std::string& access_token) {
+  access_token_ = access_token;
+}
+
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.h b/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.h
index 6110363..79bcd566 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.h
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.h
@@ -112,6 +112,8 @@
     return data_pipe_getter_.get();
   }
 
+  void set_access_token(const std::string& access_token);
+
  private:
   FRIEND_TEST_ALL_PREFIXES(MultipartUploadRequestTest, GeneratesCorrectBody);
   FRIEND_TEST_ALL_PREFIXES(MultipartUploadRequestTest, RetriesCorrectly);
@@ -189,6 +191,8 @@
 
   base::Time start_time_;
 
+  std::string access_token_;
+
   base::WeakPtrFactory<MultipartUploadRequest> weak_factory_{this};
 };
 
diff --git a/chrome/browser/signin/dice_web_signin_interceptor.cc b/chrome/browser/signin/dice_web_signin_interceptor.cc
index aaf843e..a9064f3c0 100644
--- a/chrome/browser/signin/dice_web_signin_interceptor.cc
+++ b/chrome/browser/signin/dice_web_signin_interceptor.cc
@@ -105,7 +105,12 @@
     SigninInterceptionHeuristicOutcome outcome) {
   return outcome == SigninInterceptionHeuristicOutcome::kInterceptEnterprise ||
          outcome == SigninInterceptionHeuristicOutcome::kInterceptMultiUser ||
-         outcome == SigninInterceptionHeuristicOutcome::kInterceptProfileSwitch;
+         outcome ==
+             SigninInterceptionHeuristicOutcome::kInterceptProfileSwitch ||
+         outcome ==
+             SigninInterceptionHeuristicOutcome::kInterceptEnterpriseForced ||
+         outcome == SigninInterceptionHeuristicOutcome::
+                        kInterceptEnterpriseForcedProfileSwitch;
 }
 
 DiceWebSigninInterceptor::DiceWebSigninInterceptor(
@@ -138,8 +143,8 @@
     bool is_sync_signin,
     const std::string& email,
     const ProfileAttributesEntry** entry) const {
-  if (!profile_->GetPrefs()->GetBoolean(prefs::kSigninInterceptionEnabled))
-    return SigninInterceptionHeuristicOutcome::kAbortInterceptionDisabled;
+  bool signin_interception_enabled =
+      profile_->GetPrefs()->GetBoolean(prefs::kSigninInterceptionEnabled);
 
   if (is_sync_signin) {
     // Do not intercept signins from the Sync startup flow.
@@ -148,18 +153,25 @@
     // interception is missed.
     return SigninInterceptionHeuristicOutcome::kAbortSyncSignin;
   }
-  // Wait for more account info is enterprise separation is required or if more
-  // info is needed.
-  if (EnterpriseSeparationMaybeRequired(
-          email, is_new_account,
-          /*managed_account_profile_level_signin_restriction=*/absl::nullopt)
-          .value_or(true)) {
-    return absl::nullopt;
-  }
 
-  if (!is_new_account) {
+  auto enforce_enterprise_separation = EnterpriseSeparationMaybeRequired(
+      email, is_new_account,
+      /*managed_account_profile_level_signin_restriction=*/absl::nullopt);
+
+  // If we do not have all the information to enforce or not enterprise profile
+  // separation, return `absl::nullopt` so that we can try and get more info on
+  // the intercepted account.
+  if (!enforce_enterprise_separation)
+    return absl::nullopt;
+
+  if (!enforce_enterprise_separation.value()) {
+    // If interception is disabled abort, unless we need to enforce enterprise
+    // profile separation.
+    if (!signin_interception_enabled)
+      return SigninInterceptionHeuristicOutcome::kAbortInterceptionDisabled;
     // Do not intercept reauth.
-    return SigninInterceptionHeuristicOutcome::kAbortAccountNotNew;
+    if (!is_new_account)
+      return SigninInterceptionHeuristicOutcome::kAbortAccountNotNew;
   }
 
   const ProfileAttributesEntry* switch_to_entry = ShouldShowProfileSwitchBubble(
@@ -168,9 +180,19 @@
   if (switch_to_entry) {
     if (entry)
       *entry = switch_to_entry;
+    if (enforce_enterprise_separation.value()) {
+      return SigninInterceptionHeuristicOutcome::
+          kInterceptEnterpriseForcedProfileSwitch;
+    }
+    DCHECK(is_new_account) << "Reauths were already handled above";
     return SigninInterceptionHeuristicOutcome::kInterceptProfileSwitch;
   }
 
+  if (enforce_enterprise_separation.value())
+    return SigninInterceptionHeuristicOutcome::kInterceptEnterpriseForced;
+
+  DCHECK(signin_interception_enabled && !enforce_enterprise_separation.value());
+
   // From this point the remaining possible interceptions involve creating a new
   // profile.
   if (!profiles::IsProfileCreationAllowed()) {
@@ -256,26 +278,10 @@
   new_account_interception_ = is_new_account;
   web_contents_ = web_contents->GetWeakPtr();
 
-  if (heuristic_outcome) {
+  if (heuristic_outcome &&
+      !SigninInterceptionHeuristicOutcomeIsSuccess(*heuristic_outcome)) {
     RecordSigninInterceptionHeuristicOutcome(*heuristic_outcome);
-    if (*heuristic_outcome ==
-        SigninInterceptionHeuristicOutcome::kInterceptProfileSwitch) {
-      DCHECK(entry);
-      Delegate::BubbleParameters bubble_parameters{
-          SigninInterceptionType::kProfileSwitch, account_info,
-          GetPrimaryAccountInfo(identity_manager_),
-          entry->GetProfileThemeColors().profile_highlight_color,
-          /*show_guest_option=*/false};
-      ShowSigninInterceptionBubble(
-          bubble_parameters,
-          base::BindOnce(&DiceWebSigninInterceptor::OnProfileSwitchChoice,
-                         base::Unretained(this), account_info.email,
-                         entry->GetPath()));
-    } else {
-      // Interception is aborted.
-      DCHECK(!SigninInterceptionHeuristicOutcomeIsSuccess(*heuristic_outcome));
-      Reset();
-    }
+    Reset();
     return;
   }
 
@@ -461,34 +467,41 @@
     return;
   }
 
-  if (switch_to_entry) {
-    // Propose account switching if we skipped in GetHeuristicOutcome because we
-    // returned a nullptr to get more information about forced enterprise
-    // profile separation.
-    interception_type = force_profile_separation
-                            ? SigninInterceptionType::kProfileSwitchForced
-                            : SigninInterceptionType::kProfileSwitch;
-    RecordSigninInterceptionHeuristicOutcome(
-        force_profile_separation
-            ? SigninInterceptionHeuristicOutcome::
-                  kInterceptEnterpriseForcedProfileSwitch
-            : SigninInterceptionHeuristicOutcome::kInterceptProfileSwitch);
-  } else if (force_profile_separation) {
-    // In case of a reauth of an account that already had sync enabled,
-    // the user already accepted to use a managed profile. Simply update that
-    // fact.
-    if (!new_account_interception_ &&
-        identity_manager_->GetPrimaryAccountId(signin::ConsentLevel::kSync) ==
-            info.account_id) {
+  if (force_profile_separation) {
+    if (switch_to_entry) {
+      interception_type = SigninInterceptionType::kProfileSwitchForced;
+      RecordSigninInterceptionHeuristicOutcome(
+          SigninInterceptionHeuristicOutcome::
+              kInterceptEnterpriseForcedProfileSwitch);
+    } else if (!new_account_interception_ &&
+               identity_manager_->GetPrimaryAccountId(
+                   signin::ConsentLevel::kSync) == info.account_id) {
+      // In case of a reauth of an account that already had sync enabled,
+      // the user already accepted to use a managed profile. Simply update that
+      // fact.
       chrome::enterprise_util::SetUserAcceptedAccountManagement(profile_, true);
       RecordSigninInterceptionHeuristicOutcome(
           SigninInterceptionHeuristicOutcome::kAbortAccountNotNew);
       Reset();
       return;
+    } else {
+      interception_type = SigninInterceptionType::kEnterpriseForced;
+      RecordSigninInterceptionHeuristicOutcome(
+          SigninInterceptionHeuristicOutcome::kInterceptEnterpriseForced);
     }
-    interception_type = SigninInterceptionType::kEnterpriseForced;
+  } else if (!profile_->GetPrefs()->GetBoolean(
+                 prefs::kSigninInterceptionEnabled)) {
     RecordSigninInterceptionHeuristicOutcome(
-        SigninInterceptionHeuristicOutcome::kInterceptEnterpriseForced);
+        SigninInterceptionHeuristicOutcome::kAbortInterceptionDisabled);
+    Reset();
+    return;
+  } else if (switch_to_entry) {
+    // Propose account switching if we skipped in GetHeuristicOutcome because we
+    // returned a nullptr to get more information about forced enterprise
+    // profile separation.
+    interception_type = SigninInterceptionType::kProfileSwitch;
+    RecordSigninInterceptionHeuristicOutcome(
+        SigninInterceptionHeuristicOutcome::kInterceptProfileSwitch);
   } else if (ShouldShowEnterpriseBubble(info)) {
     interception_type = SigninInterceptionType::kEnterprise;
     RecordSigninInterceptionHeuristicOutcome(
diff --git a/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc b/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc
index 5d2de47..ecde6ed0 100644
--- a/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc
+++ b/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc
@@ -175,7 +175,7 @@
     EXPECT_TRUE(interceptor()->is_interception_in_progress());
   }
 
- private:
+ protected:
   // testing::Test:
   void SetUp() override {
     BrowserWithTestWindowTest::SetUp();
@@ -195,6 +195,7 @@
     AddTab(browser(), GURL("http://foo/1"));
   }
 
+ private:
   void TearDown() override {
     dice_web_signin_interceptor_->Shutdown();
     identity_test_env_profile_adaptor_.reset();
@@ -398,7 +399,19 @@
       primary_account_info));
 }
 
-TEST_F(DiceWebSigninInterceptorTest, EnforceManagedAccountAsPrimaryReauth) {
+class DiceWebSigninInterceptorManagedAccountTest
+    : public DiceWebSigninInterceptorTest,
+      public testing::WithParamInterface<bool> {
+ protected:
+  void SetUp() override {
+    DiceWebSigninInterceptorTest::SetUp();
+    profile()->GetPrefs()->SetBoolean(prefs::kSigninInterceptionEnabled,
+                                      GetParam());
+  }
+};
+
+TEST_P(DiceWebSigninInterceptorManagedAccountTest,
+       EnforceManagedAccountAsPrimaryReauth) {
   profile()->GetPrefs()->SetBoolean(
       prefs::kManagedAccountsSigninRestrictionScopeMachine, true);
   profile()->GetPrefs()->SetString(prefs::kManagedAccountsSigninRestriction,
@@ -422,12 +435,13 @@
                   web_contents(), MatchBubbleParameters(expected_parameters),
                   testing::_));
 
-  TestAsynchronousInterception(
+  TestSynchronousInterception(
       account_info, /*is_new_account=*/false, /*is_sync_signin=*/false,
       SigninInterceptionHeuristicOutcome::kInterceptEnterpriseForced);
 }
 
-TEST_F(DiceWebSigninInterceptorTest, EnforceManagedAccountAsPrimaryManaged) {
+TEST_P(DiceWebSigninInterceptorManagedAccountTest,
+       EnforceManagedAccountAsPrimaryManaged) {
   AccountInfo account_info =
       identity_test_env()->MakeAccountAvailable("alice@example.com");
   MakeValidAccountInfo(&account_info, "example.com");
@@ -444,12 +458,12 @@
               ShowSigninInterceptionBubble(
                   web_contents(), MatchBubbleParameters(expected_parameters),
                   testing::_));
-  TestAsynchronousInterception(
+  TestSynchronousInterception(
       account_info, /*is_new_account=*/true, /*is_sync_signin=*/false,
       SigninInterceptionHeuristicOutcome::kInterceptEnterpriseForced);
 }
 
-TEST_F(DiceWebSigninInterceptorTest,
+TEST_P(DiceWebSigninInterceptorManagedAccountTest,
        EnforceManagedAccountAsPrimaryProfileSwitch) {
   AccountInfo account_info =
       identity_test_env()->MakeAccountAvailable("alice@example.com");
@@ -477,12 +491,16 @@
               ShowSigninInterceptionBubble(
                   web_contents(), MatchBubbleParameters(expected_parameters),
                   testing::_));
-  TestAsynchronousInterception(account_info, /*is_new_account=*/true,
-                               /*is_sync_signin=*/false,
-                               SigninInterceptionHeuristicOutcome::
-                                   kInterceptEnterpriseForcedProfileSwitch);
+  TestSynchronousInterception(account_info, /*is_new_account=*/true,
+                              /*is_sync_signin=*/false,
+                              SigninInterceptionHeuristicOutcome::
+                                  kInterceptEnterpriseForcedProfileSwitch);
 }
 
+INSTANTIATE_TEST_SUITE_P(All,
+                         DiceWebSigninInterceptorManagedAccountTest,
+                         ::testing::Bool());
+
 TEST_F(DiceWebSigninInterceptorTest, ShouldShowEnterpriseBubbleWithoutUPA) {
   AccountInfo account_info_1 =
       identity_test_env()->MakeAccountAvailable("bob@example.com");
@@ -630,6 +648,16 @@
       interceptor()->GetHeuristicOutcome(
           /*is_new_account=*/true, /*is_sync_signin=*/false, "bob@example.com",
           /*entry=*/nullptr),
+      absl::nullopt);
+
+  AccountInfo account_info =
+      identity_test_env()->MakeAccountAvailable("bob@example.com");
+  MakeValidAccountInfo(&account_info, "example.com");
+  identity_test_env()->UpdateAccountInfoForAccount(account_info);
+  EXPECT_EQ(
+      interceptor()->GetHeuristicOutcome(
+          /*is_new_account=*/true, /*is_sync_signin=*/false, "bob@example.com",
+          /*entry=*/nullptr),
       SigninInterceptionHeuristicOutcome::kAbortInterceptionDisabled);
 }
 
diff --git a/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_cros.cc b/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_cros.cc
index 8cf75076..56188a9 100644
--- a/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_cros.cc
+++ b/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_cros.cc
@@ -18,13 +18,186 @@
 
 IN_PROC_BROWSER_TEST_F(
     TwoClientWebAppsIntegrationTestCros,
-    WebAppIntegration_29SiteA_11SiteA_40Client2_11SiteA_34SiteA_22) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_7SiteA_12SiteA_37SiteA_17_20) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconNotShown();
+  helper_.CheckLaunchIconShown();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestCros,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_7SiteA_12SiteA_41_10SiteA_42_12SiteA_7SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.SyncTurnOff();
+  helper_.UninstallFromList("SiteA");
+  helper_.SyncTurnOn();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+}
+
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestCros,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_7SiteA_12SiteA_10SiteA_15SiteA_40Client1_15SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.UninstallFromList("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.SwitchProfileClients("Client1");
+  helper_.CheckAppNotInList("SiteA");
+}
+
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestCros,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_7SiteA_12SiteA_37SiteA_17_20) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconNotShown();
+  helper_.CheckLaunchIconShown();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestCros,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_7SiteA_12SiteA_41_10SiteA_42_12SiteA_7SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.SyncTurnOff();
+  helper_.UninstallFromList("SiteA");
+  helper_.SyncTurnOn();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+}
+
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestCros,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_7SiteA_12SiteA_10SiteA_15SiteA_40Client1_15SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.UninstallFromList("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.SwitchProfileClients("Client1");
+  helper_.CheckAppNotInList("SiteA");
+}
+
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestCros,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_7SiteA_12SiteA_37SiteA_17_20) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconNotShown();
+  helper_.CheckLaunchIconShown();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestCros,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_7SiteA_12SiteA_41_10SiteA_42_12SiteA_7SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.SyncTurnOff();
+  helper_.UninstallFromList("SiteA");
+  helper_.SyncTurnOn();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+}
+
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestCros,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_7SiteA_12SiteA_10SiteA_15SiteA_40Client1_15SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.UninstallFromList("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.SwitchProfileClients("Client1");
+  helper_.CheckAppNotInList("SiteA");
+}
+
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestCros,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_7SiteA_11SiteA_34SiteA_22) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutTabbed("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SwitchProfileClients("Client2");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
   helper_.CheckTabCreated();
@@ -32,184 +205,39 @@
 
 IN_PROC_BROWSER_TEST_F(
     TwoClientWebAppsIntegrationTestCros,
-    WebAppIntegration_30SiteA_24_12SiteA_40Client2_12SiteA_37SiteA_17_20) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconNotShown();
-  helper_.CheckLaunchIconShown();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestCros,
-    WebAppIntegration_31SiteA_24_12SiteA_40Client2_12SiteA_37SiteA_17_20) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconNotShown();
-  helper_.CheckLaunchIconShown();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestCros,
-    WebAppIntegration_47SiteA_24_12SiteA_40Client2_12SiteA_37SiteA_17_20) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconNotShown();
-  helper_.CheckLaunchIconShown();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestCros,
-    WebAppIntegration_30SiteA_24_12SiteA_40Client2_12SiteA_10SiteA_15SiteA_40Client1_15SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.UninstallFromList("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.SwitchProfileClients("Client1");
-  helper_.CheckAppNotInList("SiteA");
-}
-
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestCros,
-    WebAppIntegration_31SiteA_24_12SiteA_40Client2_12SiteA_10SiteA_15SiteA_40Client1_15SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.UninstallFromList("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.SwitchProfileClients("Client1");
-  helper_.CheckAppNotInList("SiteA");
-}
-
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestCros,
-    WebAppIntegration_47SiteA_24_12SiteA_40Client2_12SiteA_10SiteA_15SiteA_40Client1_15SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.UninstallFromList("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.SwitchProfileClients("Client1");
-  helper_.CheckAppNotInList("SiteA");
-}
-
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestCros,
-    WebAppIntegration_29SiteA_11SiteA_40Client2_11SiteA_10SiteA_15SiteA_40Client1_15SiteA) {
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_7SiteA_11SiteA_41_10SiteA_42_11SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutTabbed("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SwitchProfileClients("Client2");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
-  helper_.UninstallFromList("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.SwitchProfileClients("Client1");
-  helper_.CheckAppNotInList("SiteA");
-}
-
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestCros,
-    WebAppIntegration_30SiteA_24_12SiteA_40Client2_12SiteA_41_10SiteA_42_12SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListWindowed("SiteA");
   helper_.SyncTurnOff();
   helper_.UninstallFromList("SiteA");
   helper_.SyncTurnOn();
-  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
 IN_PROC_BROWSER_TEST_F(
     TwoClientWebAppsIntegrationTestCros,
-    WebAppIntegration_31SiteA_24_12SiteA_40Client2_12SiteA_41_10SiteA_42_12SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SyncTurnOff();
-  helper_.UninstallFromList("SiteA");
-  helper_.SyncTurnOn();
-  helper_.CheckAppInListWindowed("SiteA");
-}
-
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestCros,
-    WebAppIntegration_47SiteA_24_12SiteA_40Client2_12SiteA_41_10SiteA_42_12SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SyncTurnOff();
-  helper_.UninstallFromList("SiteA");
-  helper_.SyncTurnOn();
-  helper_.CheckAppInListWindowed("SiteA");
-}
-
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestCros,
-    WebAppIntegration_29SiteA_11SiteA_40Client2_11SiteA_41_10SiteA_42_11SiteA) {
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_7SiteA_11SiteA_10SiteA_15SiteA_40Client1_15SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutTabbed("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SwitchProfileClients("Client2");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
-  helper_.SyncTurnOff();
   helper_.UninstallFromList("SiteA");
-  helper_.SyncTurnOn();
-  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.SwitchProfileClients("Client1");
+  helper_.CheckAppNotInList("SiteA");
 }
 
 }  // namespace
diff --git a/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_mac_win_linux.cc b/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_mac_win_linux.cc
index 5887d9203..a536851 100644
--- a/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_mac_win_linux.cc
+++ b/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_mac_win_linux.cc
@@ -20,388 +20,6 @@
 
 // TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
 #if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_37SiteA_17_20 \
-  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_37SiteA_17_20
-#else
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_37SiteA_17_20 \
-  WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_37SiteA_17_20
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_37SiteA_17_20) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.InstallLocally("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconNotShown();
-  helper_.CheckLaunchIconShown();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_34SiteA_24 \
-  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_34SiteA_24
-#else
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_34SiteA_24 \
-  WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_34SiteA_24
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_34SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.InstallLocally("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromChromeApps("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_34SiteA_22 \
-  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_34SiteA_22
-#else
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_34SiteA_22 \
-  WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_34SiteA_22
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_34SiteA_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.LaunchFromChromeApps("SiteA");
-  helper_.CheckTabCreated();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_37SiteA_18_19 \
-  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_37SiteA_18_19
-#else
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_37SiteA_18_19 \
-  WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_37SiteA_18_19
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_37SiteA_18_19) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconShown();
-  helper_.CheckLaunchIconNotShown();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_37SiteA_17_20 \
-  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_37SiteA_17_20
-#else
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_37SiteA_17_20 \
-  WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_37SiteA_17_20
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_37SiteA_17_20) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.InstallLocally("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconNotShown();
-  helper_.CheckLaunchIconShown();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_34SiteA_24 \
-  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_34SiteA_24
-#else
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_34SiteA_24 \
-  WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_34SiteA_24
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_34SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.InstallLocally("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromChromeApps("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_34SiteA_22 \
-  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_34SiteA_22
-#else
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_34SiteA_22 \
-  WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_34SiteA_22
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_34SiteA_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.LaunchFromChromeApps("SiteA");
-  helper_.CheckTabCreated();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_37SiteA_18_19 \
-  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_37SiteA_18_19
-#else
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_37SiteA_18_19 \
-  WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_37SiteA_18_19
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_37SiteA_18_19) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconShown();
-  helper_.CheckLaunchIconNotShown();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_37SiteA_17_20 \
-  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_37SiteA_17_20
-#else
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_37SiteA_17_20 \
-  WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_37SiteA_17_20
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_37SiteA_17_20) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.InstallLocally("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconNotShown();
-  helper_.CheckLaunchIconShown();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_34SiteA_24 \
-  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_34SiteA_24
-#else
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_34SiteA_24 \
-  WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_34SiteA_24
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_34SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.InstallLocally("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromChromeApps("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_34SiteA_22 \
-  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_34SiteA_22
-#else
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_34SiteA_22 \
-  WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_34SiteA_22
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_34SiteA_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.LaunchFromChromeApps("SiteA");
-  helper_.CheckTabCreated();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_37SiteA_18_19 \
-  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_37SiteA_18_19
-#else
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_37SiteA_18_19 \
-  WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_37SiteA_18_19
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_37SiteA_18_19) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconShown();
-  helper_.CheckLaunchIconNotShown();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_46SiteA_11SiteA_37SiteA_18_19) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.InstallLocally("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconShown();
-  helper_.CheckLaunchIconNotShown();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_46SiteA_11SiteA_34SiteA_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.InstallLocally("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.LaunchFromChromeApps("SiteA");
-  helper_.CheckTabCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_34SiteA_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.LaunchFromChromeApps("SiteA");
-  helper_.CheckTabCreated();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_30SiteC_12SiteC_40Client2_45SiteC_46SiteC_12SiteC_37SiteC_17_20 \
-  DISABLED_WebAppIntegration_30SiteC_12SiteC_40Client2_45SiteC_46SiteC_12SiteC_37SiteC_17_20
-#else
-#define MAYBE_WebAppIntegration_30SiteC_12SiteC_40Client2_45SiteC_46SiteC_12SiteC_37SiteC_17_20 \
-  WebAppIntegration_30SiteC_12SiteC_40Client2_45SiteC_46SiteC_12SiteC_37SiteC_17_20
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_30SiteC_12SiteC_40Client2_45SiteC_46SiteC_12SiteC_37SiteC_17_20) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteC");
-  helper_.CheckAppInListWindowed("SiteC");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteC");
-  helper_.InstallLocally("SiteC");
-  helper_.CheckAppInListWindowed("SiteC");
-  helper_.NavigateBrowser("SiteC");
-  helper_.CheckInstallIconNotShown();
-  helper_.CheckLaunchIconShown();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    WebAppIntegration_29SiteC_11SiteC_40Client2_45SiteC_46SiteC_11SiteC_37SiteC_19) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteC");
-  helper_.CheckAppInListTabbed("SiteC");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteC");
-  helper_.InstallLocally("SiteC");
-  helper_.CheckAppInListTabbed("SiteC");
-  helper_.NavigateBrowser("SiteC");
-  helper_.CheckLaunchIconNotShown();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC)
 #define MAYBE_WebAppIntegration_41_30SiteA_42_40Client2_45SiteA \
   DISABLED_WebAppIntegration_41_30SiteA_42_40Client2_45SiteA
 #else
@@ -510,24 +128,81 @@
 
 // TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
 #if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_35SiteA_24 \
-  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_35SiteA_24
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_37SiteA_17_20 \
+  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_37SiteA_17_20
 #else
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_35SiteA_24 \
-  WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_35SiteA_24
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_37SiteA_17_20 \
+  WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_37SiteA_17_20
 #endif
 IN_PROC_BROWSER_TEST_F(
     TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_35SiteA_24) {
+    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_37SiteA_17_20) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SwitchProfileClients("Client2");
   helper_.CheckAppInListNotLocallyInstalled("SiteA");
   helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconNotShown();
+  helper_.CheckLaunchIconShown();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_69SiteA_24 \
+  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_69SiteA_24
+#else
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_69SiteA_24 \
+  WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_69SiteA_24
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_69SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_35SiteA_24 \
+  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_35SiteA_24
+#else
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_35SiteA_24 \
+  WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_35SiteA_24
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_35SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.LaunchFromLaunchIcon("SiteA");
   helper_.CheckWindowCreated();
@@ -535,24 +210,286 @@
 
 // TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
 #if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_35SiteA_24 \
-  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_35SiteA_24
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_34SiteA_24 \
+  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_34SiteA_24
 #else
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_35SiteA_24 \
-  WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_35SiteA_24
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_34SiteA_24 \
+  WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_34SiteA_24
 #endif
 IN_PROC_BROWSER_TEST_F(
     TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_35SiteA_24) {
+    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_34SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromChromeApps("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_1SiteA_24 \
+  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_1SiteA_24
+#else
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_1SiteA_24 \
+  WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_1SiteA_24
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_1SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromPlatformShortcut("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_34SiteA_22 \
+  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_34SiteA_22
+#else
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_34SiteA_22 \
+  WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_34SiteA_22
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_34SiteA_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.LaunchFromChromeApps("SiteA");
+  helper_.CheckTabCreated();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_1SiteA_22 \
+  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_1SiteA_22
+#else
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_1SiteA_22 \
+  WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_1SiteA_22
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_1SiteA_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.LaunchFromPlatformShortcut("SiteA");
+  helper_.CheckTabCreated();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_37SiteA_18_19 \
+  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_37SiteA_18_19
+#else
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_37SiteA_18_19 \
+  WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_37SiteA_18_19
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_37SiteA_18_19) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconShown();
+  helper_.CheckLaunchIconNotShown();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA \
+  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA
+#else
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA \
+  WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.SyncTurnOff();
+  helper_.UninstallFromList("SiteA");
+  helper_.SyncTurnOn();
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA \
+  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA
+#else
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA \
+  WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.SyncTurnOff();
+  helper_.UninstallFromMenu("SiteA");
+  helper_.SyncTurnOn();
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA \
+  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA
+#else
+#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA \
+  WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.UninstallFromList("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.SwitchProfileClients("Client1");
+  helper_.CheckAppNotInList("SiteA");
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_37SiteA_17_20 \
+  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_37SiteA_17_20
+#else
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_37SiteA_17_20 \
+  WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_37SiteA_17_20
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_37SiteA_17_20) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SwitchProfileClients("Client2");
   helper_.CheckAppInListNotLocallyInstalled("SiteA");
   helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconNotShown();
+  helper_.CheckLaunchIconShown();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_69SiteA_24 \
+  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_69SiteA_24
+#else
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_69SiteA_24 \
+  WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_69SiteA_24
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_69SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_35SiteA_24 \
+  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_35SiteA_24
+#else
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_35SiteA_24 \
+  WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_35SiteA_24
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_35SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.LaunchFromLaunchIcon("SiteA");
   helper_.CheckWindowCreated();
@@ -560,24 +497,286 @@
 
 // TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
 #if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_35SiteA_24 \
-  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_35SiteA_24
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_34SiteA_24 \
+  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_34SiteA_24
 #else
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_35SiteA_24 \
-  WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_35SiteA_24
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_34SiteA_24 \
+  WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_34SiteA_24
 #endif
 IN_PROC_BROWSER_TEST_F(
     TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_35SiteA_24) {
+    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_34SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromChromeApps("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_1SiteA_24 \
+  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_1SiteA_24
+#else
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_1SiteA_24 \
+  WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_1SiteA_24
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_1SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromPlatformShortcut("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_34SiteA_22 \
+  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_34SiteA_22
+#else
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_34SiteA_22 \
+  WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_34SiteA_22
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_34SiteA_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.LaunchFromChromeApps("SiteA");
+  helper_.CheckTabCreated();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_1SiteA_22 \
+  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_1SiteA_22
+#else
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_1SiteA_22 \
+  WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_1SiteA_22
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_1SiteA_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.LaunchFromPlatformShortcut("SiteA");
+  helper_.CheckTabCreated();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_37SiteA_18_19 \
+  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_37SiteA_18_19
+#else
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_37SiteA_18_19 \
+  WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_37SiteA_18_19
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_37SiteA_18_19) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconShown();
+  helper_.CheckLaunchIconNotShown();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA \
+  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA
+#else
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA \
+  WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.SyncTurnOff();
+  helper_.UninstallFromList("SiteA");
+  helper_.SyncTurnOn();
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA \
+  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA
+#else
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA \
+  WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.SyncTurnOff();
+  helper_.UninstallFromMenu("SiteA");
+  helper_.SyncTurnOn();
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA \
+  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA
+#else
+#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA \
+  WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.UninstallFromList("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.SwitchProfileClients("Client1");
+  helper_.CheckAppNotInList("SiteA");
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_37SiteA_17_20 \
+  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_37SiteA_17_20
+#else
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_37SiteA_17_20 \
+  WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_37SiteA_17_20
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_37SiteA_17_20) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SwitchProfileClients("Client2");
   helper_.CheckAppInListNotLocallyInstalled("SiteA");
   helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconNotShown();
+  helper_.CheckLaunchIconShown();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_69SiteA_24 \
+  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_69SiteA_24
+#else
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_69SiteA_24 \
+  WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_69SiteA_24
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_69SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_35SiteA_24 \
+  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_35SiteA_24
+#else
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_35SiteA_24 \
+  WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_35SiteA_24
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_35SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.LaunchFromLaunchIcon("SiteA");
   helper_.CheckWindowCreated();
@@ -585,178 +784,149 @@
 
 // TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
 #if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA \
-  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_34SiteA_24 \
+  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_34SiteA_24
 #else
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA \
-  WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_34SiteA_24 \
+  WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_34SiteA_24
 #endif
 IN_PROC_BROWSER_TEST_F(
     TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.UninstallFromList("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.SwitchProfileClients("Client1");
-  helper_.CheckAppNotInList("SiteA");
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA \
-  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA
-#else
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA \
-  WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.UninstallFromList("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.SwitchProfileClients("Client1");
-  helper_.CheckAppNotInList("SiteA");
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA \
-  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA
-#else
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA \
-  WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA) {
+    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_34SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SwitchProfileClients("Client2");
   helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.UninstallFromList("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.SwitchProfileClients("Client1");
-  helper_.CheckAppNotInList("SiteA");
-}
-
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.UninstallFromList("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.SwitchProfileClients("Client1");
-  helper_.CheckAppNotInList("SiteA");
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA \
-  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA
-#else
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA \
-  WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
+  helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.SyncTurnOff();
-  helper_.UninstallFromList("SiteA");
-  helper_.SyncTurnOn();
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA \
-  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA
-#else
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA \
-  WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
+  helper_.LaunchFromChromeApps("SiteA");
   helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.SyncTurnOff();
-  helper_.UninstallFromList("SiteA");
-  helper_.SyncTurnOn();
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
 }
 
 // TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
 #if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA \
-  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_1SiteA_24 \
+  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_1SiteA_24
 #else
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA \
-  WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_1SiteA_24 \
+  WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_1SiteA_24
 #endif
 IN_PROC_BROWSER_TEST_F(
     TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA) {
+    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_12SiteA_1SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SwitchProfileClients("Client2");
   helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.SyncTurnOff();
-  helper_.UninstallFromList("SiteA");
-  helper_.SyncTurnOn();
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromPlatformShortcut("SiteA");
+  helper_.CheckWindowCreated();
 }
 
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_34SiteA_22 \
+  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_34SiteA_22
+#else
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_34SiteA_22 \
+  WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_34SiteA_22
+#endif
 IN_PROC_BROWSER_TEST_F(
     TwoClientWebAppsIntegrationTestMacWinLinux,
-    WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA) {
+    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_34SiteA_22) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.LaunchFromChromeApps("SiteA");
+  helper_.CheckTabCreated();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_1SiteA_22 \
+  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_1SiteA_22
+#else
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_1SiteA_22 \
+  WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_1SiteA_22
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_1SiteA_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.LaunchFromPlatformShortcut("SiteA");
+  helper_.CheckTabCreated();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_37SiteA_18_19 \
+  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_37SiteA_18_19
+#else
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_37SiteA_18_19 \
+  WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_37SiteA_18_19
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_37SiteA_18_19) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconShown();
+  helper_.CheckLaunchIconNotShown();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA \
+  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA
+#else
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA \
+  WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SwitchProfileClients("Client2");
   helper_.CheckAppInListNotLocallyInstalled("SiteA");
   helper_.SyncTurnOff();
@@ -767,21 +937,22 @@
 
 // TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
 #if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA \
-  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA \
+  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA
 #else
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA \
-  WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA \
+  WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA
 #endif
 IN_PROC_BROWSER_TEST_F(
     TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA) {
+    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SwitchProfileClients("Client2");
   helper_.CheckAppInListNotLocallyInstalled("SiteA");
   helper_.SyncTurnOff();
@@ -792,46 +963,165 @@
 
 // TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
 #if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA \
-  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA \
+  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA
 #else
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA \
-  WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA
+#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA \
+  WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA
 #endif
 IN_PROC_BROWSER_TEST_F(
     TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA) {
+    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
+  helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.UninstallFromList("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.SwitchProfileClients("Client1");
+  helper_.CheckAppNotInList("SiteA");
+}
+
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_11SiteA_37SiteA_18_19) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconShown();
+  helper_.CheckLaunchIconNotShown();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_11SiteA_34SiteA_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.LaunchFromChromeApps("SiteA");
+  helper_.CheckTabCreated();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_11SiteA_1SiteA_22 \
+  DISABLED_WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_11SiteA_1SiteA_22
+#else
+#define MAYBE_WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_11SiteA_1SiteA_22 \
+  WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_11SiteA_1SiteA_22
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_46SiteA_7SiteA_11SiteA_1SiteA_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.InstallLocally("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.LaunchFromPlatformShortcut("SiteA");
+  helper_.CheckTabCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_34SiteA_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.LaunchFromChromeApps("SiteA");
+  helper_.CheckTabCreated();
+}
+
+// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_1SiteA_22 \
+  DISABLED_WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_1SiteA_22
+#else
+#define MAYBE_WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_1SiteA_22 \
+  WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_1SiteA_22
+#endif
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    MAYBE_WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_1SiteA_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.LaunchFromPlatformShortcut("SiteA");
+  helper_.CheckTabCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_41_10SiteA_42_45SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SwitchProfileClients("Client2");
   helper_.CheckAppInListNotLocallyInstalled("SiteA");
   helper_.SyncTurnOff();
-  helper_.UninstallFromMenu("SiteA");
+  helper_.UninstallFromList("SiteA");
   helper_.SyncTurnOn();
   helper_.CheckAppInListNotLocallyInstalled("SiteA");
 }
 
 // TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
 #if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA \
-  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA
+#define MAYBE_WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA \
+  DISABLED_WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA
 #else
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA \
-  WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA
+#define MAYBE_WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA \
+  WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA
 #endif
 IN_PROC_BROWSER_TEST_F(
     TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA) {
+    MAYBE_WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SwitchProfileClients("Client2");
   helper_.CheckAppInListNotLocallyInstalled("SiteA");
   helper_.SyncTurnOff();
@@ -840,293 +1130,66 @@
   helper_.CheckAppInListNotLocallyInstalled("SiteA");
 }
 
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_10SiteA_15SiteA_40Client1_15SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteA");
+  helper_.UninstallFromList("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.SwitchProfileClients("Client1");
+  helper_.CheckAppNotInList("SiteA");
+}
+
+IN_PROC_BROWSER_TEST_F(
+    TwoClientWebAppsIntegrationTestMacWinLinux,
+    WebAppIntegration_29SiteC_11SiteC_7SiteC_40Client2_45SiteC_46SiteC_11SiteC_7SiteC_37SiteC_19) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteC");
+  helper_.CheckAppInListTabbed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
+  helper_.SwitchProfileClients("Client2");
+  helper_.CheckAppInListNotLocallyInstalled("SiteC");
+  helper_.InstallLocally("SiteC");
+  helper_.CheckAppInListTabbed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
+  helper_.NavigateBrowser("SiteC");
+  helper_.CheckLaunchIconNotShown();
+}
+
 // TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
 #if BUILDFLAG(IS_MAC)
-#define MAYBE_WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA \
-  DISABLED_WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA
+#define MAYBE_WebAppIntegration_30SiteC_12SiteC_7SiteC_40Client2_45SiteC_46SiteC_12SiteC_7SiteC_37SiteC_17_20 \
+  DISABLED_WebAppIntegration_30SiteC_12SiteC_7SiteC_40Client2_45SiteC_46SiteC_12SiteC_7SiteC_37SiteC_17_20
 #else
-#define MAYBE_WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA \
-  WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA
+#define MAYBE_WebAppIntegration_30SiteC_12SiteC_7SiteC_40Client2_45SiteC_46SiteC_12SiteC_7SiteC_37SiteC_17_20 \
+  WebAppIntegration_30SiteC_12SiteC_7SiteC_40Client2_45SiteC_46SiteC_12SiteC_7SiteC_37SiteC_17_20
 #endif
 IN_PROC_BROWSER_TEST_F(
     TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_41_43SiteA_42_45SiteA) {
+    MAYBE_WebAppIntegration_30SiteC_12SiteC_7SiteC_40Client2_45SiteC_46SiteC_12SiteC_7SiteC_37SiteC_17_20) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
+  helper_.InstallCreateShortcutWindowed("SiteC");
+  helper_.CheckAppInListWindowed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
   helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.SyncTurnOff();
-  helper_.UninstallFromMenu("SiteA");
-  helper_.SyncTurnOn();
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC) && (!defined(NDEBUG) || defined(ADDRESS_SANITIZER))
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_69SiteA_24 \
-  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_69SiteA_24
-#else
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_69SiteA_24 \
-  WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_69SiteA_24
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_69SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.InstallLocally("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC) && (!defined(NDEBUG) || defined(ADDRESS_SANITIZER))
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_69SiteA_24 \
-  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_69SiteA_24
-#else
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_69SiteA_24 \
-  WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_69SiteA_24
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_69SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.InstallLocally("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC) && (!defined(NDEBUG) || defined(ADDRESS_SANITIZER))
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_69SiteA_24 \
-  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_69SiteA_24
-#else
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_69SiteA_24 \
-  WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_69SiteA_24
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_69SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.InstallLocally("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC) && (!defined(NDEBUG) || defined(ADDRESS_SANITIZER))
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_1SiteA_24 \
-  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_1SiteA_24
-#else
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_1SiteA_24 \
-  WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_1SiteA_24
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_1SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.InstallLocally("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromPlatformShortcut("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC) && (!defined(NDEBUG) || defined(ADDRESS_SANITIZER))
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_1SiteA_22 \
-  DISABLED_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_1SiteA_22
-#else
-#define MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_1SiteA_22 \
-  WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_1SiteA_22
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_1SiteA_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.LaunchFromPlatformShortcut("SiteA");
-  helper_.CheckTabCreated();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC) && (!defined(NDEBUG) || defined(ADDRESS_SANITIZER))
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_1SiteA_24 \
-  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_1SiteA_24
-#else
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_1SiteA_24 \
-  WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_1SiteA_24
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_1SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.InstallLocally("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromPlatformShortcut("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC) && (!defined(NDEBUG) || defined(ADDRESS_SANITIZER))
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_1SiteA_22 \
-  DISABLED_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_1SiteA_22
-#else
-#define MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_1SiteA_22 \
-  WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_1SiteA_22
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_1SiteA_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.LaunchFromPlatformShortcut("SiteA");
-  helper_.CheckTabCreated();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC) && (!defined(NDEBUG) || defined(ADDRESS_SANITIZER))
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_1SiteA_24 \
-  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_1SiteA_24
-#else
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_1SiteA_24 \
-  WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_1SiteA_24
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_46SiteA_12SiteA_1SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.InstallLocally("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromPlatformShortcut("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC) && (!defined(NDEBUG) || defined(ADDRESS_SANITIZER))
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_1SiteA_22 \
-  DISABLED_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_1SiteA_22
-#else
-#define MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_1SiteA_22 \
-  WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_1SiteA_22
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_1SiteA_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.LaunchFromPlatformShortcut("SiteA");
-  helper_.CheckTabCreated();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC) && (!defined(NDEBUG) || defined(ADDRESS_SANITIZER))
-#define MAYBE_WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_46SiteA_11SiteA_1SiteA_22 \
-  DISABLED_WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_46SiteA_11SiteA_1SiteA_22
-#else
-#define MAYBE_WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_46SiteA_11SiteA_1SiteA_22 \
-  WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_46SiteA_11SiteA_1SiteA_22
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_46SiteA_11SiteA_1SiteA_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.InstallLocally("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.LaunchFromPlatformShortcut("SiteA");
-  helper_.CheckTabCreated();
-}
-
-// TODO(crbug.com/1301414): Mac shims failing to launch on Mac debug and ASAN.
-#if BUILDFLAG(IS_MAC) && (!defined(NDEBUG) || defined(ADDRESS_SANITIZER))
-#define MAYBE_WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_1SiteA_22 \
-  DISABLED_WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_1SiteA_22
-#else
-#define MAYBE_WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_1SiteA_22 \
-  WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_1SiteA_22
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    MAYBE_WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_1SiteA_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.SwitchProfileClients("Client2");
-  helper_.CheckAppInListNotLocallyInstalled("SiteA");
-  helper_.LaunchFromPlatformShortcut("SiteA");
-  helper_.CheckTabCreated();
+  helper_.CheckAppInListNotLocallyInstalled("SiteC");
+  helper_.InstallLocally("SiteC");
+  helper_.CheckAppInListWindowed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
+  helper_.NavigateBrowser("SiteC");
+  helper_.CheckInstallIconNotShown();
+  helper_.CheckLaunchIconShown();
 }
 
 }  // namespace
diff --git a/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_win.cc b/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_win.cc
index 59ce1280..172e8db 100644
--- a/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_win.cc
+++ b/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_win.cc
@@ -17,13 +17,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     TwoClientWebAppsIntegrationTestWin,
-    WebAppIntegration_30SiteA_24_12SiteA_40Client2_45SiteA_41_87SiteA_42_45SiteA) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_87SiteA_42_45SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SwitchProfileClients("Client2");
   helper_.CheckAppInListNotLocallyInstalled("SiteA");
   helper_.SyncTurnOff();
@@ -34,13 +35,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     TwoClientWebAppsIntegrationTestWin,
-    WebAppIntegration_31SiteA_24_12SiteA_40Client2_45SiteA_41_87SiteA_42_45SiteA) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_87SiteA_42_45SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SwitchProfileClients("Client2");
   helper_.CheckAppInListNotLocallyInstalled("SiteA");
   helper_.SyncTurnOff();
@@ -51,13 +53,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     TwoClientWebAppsIntegrationTestWin,
-    WebAppIntegration_47SiteA_24_12SiteA_40Client2_45SiteA_41_87SiteA_42_45SiteA) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_40Client2_45SiteA_41_87SiteA_42_45SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SwitchProfileClients("Client2");
   helper_.CheckAppInListNotLocallyInstalled("SiteA");
   helper_.SyncTurnOff();
@@ -68,12 +71,13 @@
 
 IN_PROC_BROWSER_TEST_F(
     TwoClientWebAppsIntegrationTestWin,
-    WebAppIntegration_29SiteA_11SiteA_40Client2_45SiteA_41_87SiteA_42_45SiteA) {
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_40Client2_45SiteA_41_87SiteA_42_45SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutTabbed("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SwitchProfileClients("Client2");
   helper_.CheckAppInListNotLocallyInstalled("SiteA");
   helper_.SyncTurnOff();
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index e77f1d1..41a3e4e 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -4455,6 +4455,7 @@
       "views/overlay/back_to_tab_label_button.h",
       "views/overlay/close_image_button.cc",
       "views/overlay/close_image_button.h",
+      "views/overlay/constants.h",
       "views/overlay/document_overlay_window_views.cc",
       "views/overlay/document_overlay_window_views.h",
       "views/overlay/hang_up_button.cc",
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java
index 1923a093..01e0869 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java
@@ -243,7 +243,7 @@
         // If AutocompleteEditText receives a series of keystrokes(more than 1) from the beginning,
         // the input will be considered as paste. We do this because some IME may paste the text as
         // a series of keystrokes, not from the system copy/paste method.
-        mLastEditWasPaste = (start == 0 && lengthAfter > 1 && !mOnSanitizing);
+        mLastEditWasPaste = (start == 0 && (lengthAfter - lengthBefore) > 1 && !mOnSanitizing);
 
         if (mModel != null) mModel.onTextChanged(text, start, lengthBefore, lengthAfter);
     }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java
index 5983dee..ca17323 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java
@@ -1440,4 +1440,12 @@
         assertTrue(mInputConnection.commitText("avascript:alert(\"Test\")", 1));
         assertEquals("javascript:alert(\"Test\")", mAutocomplete.getText().toString());
     }
+
+    @Test
+    @EnableFeatures(ChromeFeatureList.SPANNABLE_INLINE_AUTOCOMPLETE)
+    public void testJavascriptSchemeShouldNotBeRemovedWhenPatialPaste_LastInputIsOneLetter() {
+        assertTrue(mInputConnection.commitText("javascript", 1));
+        assertTrue(mInputConnection.commitText(":", 1));
+        assertEquals("javascript:", mAutocomplete.getText().toString());
+    }
 }
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc
index 2874b320..d06bd13 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc
+++ b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc
@@ -119,7 +119,9 @@
   SetCategory(Category::kPlayStore);
   SetDisplayType(ash::SearchResultDisplayType::kTile);
   // TODO: The badge icon should be updated to pass through a vector icon and
-  // color id rather than hardcoding the colors here.
+  // color id rather than hardcoding the colors here.  This will require
+  // tweaking sizes/paddings so we can set use_badge_icon_background to true and
+  // remove the superimposition onto a circle here.
   SetBadgeIcon(ui::ImageModel::FromImageSkia(CreateBadgeIcon(
       is_instant_app() ? ash::kBadgeInstantIcon : ash::kBadgePlayIcon,
       ash::SharedAppListConfig::instance().search_tile_badge_icon_dimension(),
diff --git a/chrome/browser/ui/ash/media_client_impl_unittest.cc b/chrome/browser/ui/ash/media_client_impl_unittest.cc
index 48c0efdb..c0ecbb1 100644
--- a/chrome/browser/ui/ash/media_client_impl_unittest.cc
+++ b/chrome/browser/ui/ash/media_client_impl_unittest.cc
@@ -17,6 +17,8 @@
 #include "components/services/app_service/public/cpp/app_capability_access_cache_wrapper.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "components/services/app_service/public/cpp/app_registry_cache_wrapper.h"
+#include "components/services/app_service/public/cpp/app_types.h"
+#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/mojom/types.mojom-forward.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -169,9 +171,9 @@
   }
 
  protected:
-  static apps::mojom::AppPtr MakeApp(const char* app_id, const char* name) {
-    apps::mojom::AppPtr app = apps::mojom::App::New();
-    app->app_id = app_id;
+  static apps::AppPtr MakeApp(const char* app_id, const char* name) {
+    apps::AppPtr app =
+        std::make_unique<apps::App>(apps::AppType::kChromeApp, app_id);
     app->name = name;
     app->short_name = name;
     return app;
@@ -191,11 +193,20 @@
   void LaunchApp(const char* id,
                  const char* name,
                  apps::mojom::OptionalBool use_camera) {
-    std::vector<apps::mojom::AppPtr> registry_deltas;
+    std::vector<apps::AppPtr> registry_deltas;
     registry_deltas.push_back(MakeApp(id, name));
-    registry_cache_.OnApps(std::move(registry_deltas),
-                           apps::mojom::AppType::kUnknown,
-                           /* should_notify_initialized = */ false);
+    if (base::FeatureList::IsEnabled(
+            apps::kAppServiceOnAppUpdateWithoutMojom)) {
+      registry_cache_.OnApps(std::move(registry_deltas),
+                             apps::AppType::kUnknown,
+                             /* should_notify_initialized = */ false);
+    } else {
+      std::vector<apps::mojom::AppPtr> mojom_deltas;
+      mojom_deltas.push_back(apps::ConvertAppToMojomApp(registry_deltas[0]));
+      registry_cache_.OnApps(std::move(mojom_deltas),
+                             apps::mojom::AppType::kUnknown,
+                             /* should_notify_initialized = */ false);
+    }
 
     std::vector<apps::mojom::CapabilityAccessPtr> capability_access_deltas;
     capability_access_deltas.push_back(MakeCapabilityAccess(id, use_camera));
diff --git a/chrome/browser/ui/ash/microphone_mute_notification_delegate_impl_unittest.cc b/chrome/browser/ui/ash/microphone_mute_notification_delegate_impl_unittest.cc
index 95d5aee9..58e4c8ff 100644
--- a/chrome/browser/ui/ash/microphone_mute_notification_delegate_impl_unittest.cc
+++ b/chrome/browser/ui/ash/microphone_mute_notification_delegate_impl_unittest.cc
@@ -12,7 +12,9 @@
 #include "components/services/app_service/public/cpp/app_capability_access_cache_wrapper.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "components/services/app_service/public/cpp/app_registry_cache_wrapper.h"
+#include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/cpp/capability_access_update.h"
+#include "components/services/app_service/public/cpp/features.h"
 #include "components/user_manager/fake_user_manager.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -105,9 +107,9 @@
         cap_cache, reg_cache);
   }
 
-  static apps::mojom::AppPtr MakeApp(const char* app_id, const char* name) {
-    apps::mojom::AppPtr app = apps::mojom::App::New();
-    app->app_id = app_id;
+  static apps::AppPtr MakeApp(const char* app_id, const char* name) {
+    apps::AppPtr app =
+        std::make_unique<apps::App>(apps::AppType::kChromeApp, app_id);
     app->name = name;
     app->short_name = name;
     return app;
@@ -137,11 +139,18 @@
         is_primary_user ? &capability_access_cache_primary_user_
                         : &capability_access_cache_secondary_user_;
 
-    std::vector<apps::mojom::AppPtr> registry_deltas;
+    std::vector<apps::AppPtr> registry_deltas;
     registry_deltas.push_back(MakeApp(id, name));
-    reg_cache->OnApps(std::move(registry_deltas),
-                      apps::mojom::AppType::kUnknown,
-                      /*should_notify_initialized=*/false);
+    if (base::FeatureList::IsEnabled(
+            apps::kAppServiceOnAppUpdateWithoutMojom)) {
+      reg_cache->OnApps(std::move(registry_deltas), apps::AppType::kUnknown,
+                        /*should_notify_initialized=*/false);
+    } else {
+      std::vector<apps::mojom::AppPtr> mojom_deltas;
+      mojom_deltas.push_back(apps::ConvertAppToMojomApp(registry_deltas[0]));
+      reg_cache->OnApps(std::move(mojom_deltas), apps::mojom::AppType::kUnknown,
+                        /*should_notify_initialized=*/false);
+    }
 
     std::vector<apps::mojom::CapabilityAccessPtr> capability_access_deltas;
     capability_access_deltas.push_back(MakeCapabilityAccess(
diff --git a/chrome/browser/ui/blocked_content/popunder_preventer.cc b/chrome/browser/ui/blocked_content/popunder_preventer.cc
index b0bb31e..e28c5eef 100644
--- a/chrome/browser/ui/blocked_content/popunder_preventer.cc
+++ b/chrome/browser/ui/blocked_content/popunder_preventer.cc
@@ -36,8 +36,21 @@
 
 }  // namespace
 
-PopunderPreventer::PopunderPreventer(
+PopunderPreventer::PopunderPreventer(content::WebContents* activating_contents)
+    : activating_contents_(activating_contents->GetWeakPtr()) {
+  WillActivateWebContents(activating_contents);
+}
+
+PopunderPreventer::~PopunderPreventer() {
+  for (base::WeakPtr<content::WebContents>& popup : popups_) {
+    if (popup && popup->GetDelegate())
+      popup->GetDelegate()->ActivateContents(popup.get());
+  }
+}
+
+void PopunderPreventer::WillActivateWebContents(
     content::WebContents* activating_contents) {
+  DCHECK_EQ(activating_contents_.get(), activating_contents);
   // If a popup is the active window, and the WebContents that is going to be
   // activated shares in the opener chain of that popup, then we suspect that
   // WebContents to be trying to create a popunder. Store the popup window so
@@ -49,20 +62,22 @@
 
   content::WebContents* active_popup =
       active_browser->tab_strip_model()->GetActiveWebContents();
-  if (!active_popup)
-    return;
+  if (active_popup)
+    AddPotentialPopunder(active_popup);
+}
 
-  content::WebContents* actual_activating_contents = activating_contents;
+void PopunderPreventer::AddPotentialPopunder(content::WebContents* popup) {
+  content::WebContents* actual_activating_contents = activating_contents_.get();
 #if BUILDFLAG(ENABLE_EXTENSIONS)
   // If the dialog was triggered via an PDF, get the actual web contents that
   // embeds the PDF.
   guest_view::GuestViewBase* guest =
-      guest_view::GuestViewBase::FromWebContents(activating_contents);
+      guest_view::GuestViewBase::FromWebContents(actual_activating_contents);
   if (guest)
     actual_activating_contents = guest->embedder_web_contents();
 #endif
 
-  WebContentsSet popup_opener_set = BuildOpenerSet(active_popup);
+  WebContentsSet popup_opener_set = BuildOpenerSet(popup);
   WebContentsSet activator_opener_set =
       BuildOpenerSet(actual_activating_contents);
 
@@ -72,17 +87,6 @@
   if (!common_openers.empty()) {
     // The popup is indeed related to the WebContents wanting to activate. Store
     // it, so we can focus it later.
-    popup_ = active_popup->GetWeakPtr();
+    popups_.push_back(popup->GetWeakPtr());
   }
 }
-
-PopunderPreventer::~PopunderPreventer() {
-  if (!popup_)
-    return;
-
-  content::WebContentsDelegate* delegate = popup_->GetDelegate();
-  if (!delegate)
-    return;
-
-  delegate->ActivateContents(popup_.get());
-}
diff --git a/chrome/browser/ui/blocked_content/popunder_preventer.h b/chrome/browser/ui/blocked_content/popunder_preventer.h
index a13ee6ef..038b2d5 100644
--- a/chrome/browser/ui/blocked_content/popunder_preventer.h
+++ b/chrome/browser/ui/blocked_content/popunder_preventer.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_UI_BLOCKED_CONTENT_POPUNDER_PREVENTER_H_
 #define CHROME_BROWSER_UI_BLOCKED_CONTENT_POPUNDER_PREVENTER_H_
 
+#include <vector>
+
 #include "base/memory/weak_ptr.h"
 
 namespace content {
@@ -13,9 +15,10 @@
 
 // An object to block creation of pop-unders.
 //
-// This must be used whenever a window is activated. To use it, simply
-// create an instance of PopunderPreventer *before* a WebContents is activated,
-// and pass to the constructor the WebContents that is about to be activated.
+// This must be used whenever a window is activated. To use it, simply create an
+// instance of PopunderPreventer *before* a WebContents is activated, and pass
+// to the constructor the WebContents that is about to be activated. Additional
+// activations of the same WebContents should call WillActivateWebContents().
 class PopunderPreventer {
  public:
   explicit PopunderPreventer(content::WebContents* activating_contents);
@@ -25,8 +28,19 @@
 
   ~PopunderPreventer();
 
+  // Clients should call this before the WebContents is activated additional
+  // times during prolonged PopunderPreventer lifetimes. This records any other
+  // active popup that should regain activation when the preventer is destroyed.
+  void WillActivateWebContents(content::WebContents* activating_contents);
+
+  // Clients can call this when a potential popunder is discovered, even if it
+  // does not currently have activation; qualifying popups added here will
+  // regain activation when the preventer is destroyed.
+  void AddPotentialPopunder(content::WebContents* popup);
+
  private:
-  base::WeakPtr<content::WebContents> popup_;
+  std::vector<base::WeakPtr<content::WebContents>> popups_;
+  base::WeakPtr<content::WebContents> activating_contents_;
 };
 
 #endif  // CHROME_BROWSER_UI_BLOCKED_CONTENT_POPUNDER_PREVENTER_H_
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index ace0c593..70ee904 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -226,6 +226,7 @@
 #include "net/base/filename_util.h"
 #include "ppapi/buildflags/buildflags.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/security/protocol_handler_security_level.h"
 #include "third_party/blink/public/mojom/frame/blocked_navigation_types.mojom.h"
 #include "third_party/blink/public/mojom/frame/frame.mojom.h"
@@ -1624,13 +1625,14 @@
                              const gfx::Rect& initial_rect,
                              bool user_gesture,
                              bool* was_blocked) {
+  FullscreenController* fullscreen_controller =
+      exclusive_access_manager_->fullscreen_controller();
 #if BUILDFLAG(IS_MAC)
-  // On the Mac, the convention is to turn popups into new tabs when in
+  // On the Mac, the convention is to turn popups into new tabs when in browser
   // fullscreen mode. Only worry about user-initiated fullscreen as showing a
   // popup in HTML5 fullscreen would have kicked the page out of fullscreen.
   if (disposition == WindowOpenDisposition::NEW_POPUP &&
-      exclusive_access_manager_->fullscreen_controller()
-          ->IsFullscreenForBrowser()) {
+      fullscreen_controller->IsFullscreenForBrowser()) {
     disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
   }
 #endif
@@ -1642,8 +1644,22 @@
                                                         source, disposition);
   }
 
+  // Postpone activating popups opened by content-fullscreen tabs. This permits
+  // popups on other screens and retains fullscreen focus for exit accelerators.
+  // Popups are activated when the opener exits fullscreen, which happens
+  // immediately if the popup would overlap the fullscreen window.
+  NavigateParams::WindowAction window_action = NavigateParams::SHOW_WINDOW;
+  if (disposition == WindowOpenDisposition::NEW_POPUP &&
+      fullscreen_controller->IsFullscreenForTabOrPending(source) &&
+      base::FeatureList::IsEnabled(
+          blink::features::kWindowPlacementFullscreenCompanionWindow)) {
+    window_action = NavigateParams::SHOW_WINDOW_INACTIVE;
+    fullscreen_controller->FullscreenTabOpeningPopup(source,
+                                                     new_contents.get());
+  }
+
   chrome::AddWebContents(this, source, std::move(new_contents), target_url,
-                         disposition, initial_rect);
+                         disposition, initial_rect, window_action);
 }
 
 void Browser::ActivateContents(WebContents* contents) {
diff --git a/chrome/browser/ui/browser_tabstrip.cc b/chrome/browser/ui/browser_tabstrip.cc
index 4090767..a804fa9c 100644
--- a/chrome/browser/ui/browser_tabstrip.cc
+++ b/chrome/browser/ui/browser_tabstrip.cc
@@ -57,7 +57,8 @@
                     std::unique_ptr<content::WebContents> new_contents,
                     const GURL& target_url,
                     WindowOpenDisposition disposition,
-                    const gfx::Rect& initial_rect) {
+                    const gfx::Rect& initial_rect,
+                    NavigateParams::WindowAction window_action) {
   // No code for this yet.
   DCHECK(disposition != WindowOpenDisposition::SAVE_TO_DISK);
   // Can't create a new contents for the current tab - invalid case.
@@ -68,7 +69,7 @@
   params.url = target_url;
   params.disposition = disposition;
   params.window_bounds = initial_rect;
-  params.window_action = NavigateParams::SHOW_WINDOW;
+  params.window_action = window_action;
   // At this point, we're already beyond the popup blocker. Even if the popup
   // was created without a user gesture, we have to set |user_gesture| to true,
   // so it gets correctly focused.
diff --git a/chrome/browser/ui/browser_tabstrip.h b/chrome/browser/ui/browser_tabstrip.h
index 3ae6ad7a..6c2a57a1 100644
--- a/chrome/browser/ui/browser_tabstrip.h
+++ b/chrome/browser/ui/browser_tabstrip.h
@@ -39,14 +39,17 @@
 
 // Creates a new tab with the already-created WebContents 'new_contents'.
 // The window for the added contents will be reparented correctly when this
-// method returns.  If |disposition| is NEW_POPUP, |initial_rect| should hold
-// the initial position and size.
-void AddWebContents(Browser* browser,
-                    content::WebContents* source_contents,
-                    std::unique_ptr<content::WebContents> new_contents,
-                    const GURL& target_url,
-                    WindowOpenDisposition disposition,
-                    const gfx::Rect& initial_rect);
+// method returns. If |disposition| is NEW_POPUP, |initial_rect| should hold the
+// initial position and size. |window_action| may optionally specify whether the
+// window should be shown or activated.
+void AddWebContents(
+    Browser* browser,
+    content::WebContents* source_contents,
+    std::unique_ptr<content::WebContents> new_contents,
+    const GURL& target_url,
+    WindowOpenDisposition disposition,
+    const gfx::Rect& initial_rect,
+    NavigateParams::WindowAction window_action = NavigateParams::SHOW_WINDOW);
 
 // Closes the specified WebContents in the specified Browser. If
 // |add_to_history| is true, an entry in the historical tab database is created.
diff --git a/chrome/browser/ui/color/chrome_color_id.h b/chrome/browser/ui/color/chrome_color_id.h
index 4af2cda..2bca4c2 100644
--- a/chrome/browser/ui/color/chrome_color_id.h
+++ b/chrome/browser/ui/color/chrome_color_id.h
@@ -68,6 +68,8 @@
   /* Extension colors. */ \
   E_CPONLY(kColorExtensionIconBadgeBackgroundDefault) \
   E_CPONLY(kColorExtensionIconBadgeForegroundDefault) \
+  E_CPONLY(kColorExtensionIconDecorationAmbientShadow) \
+  E_CPONLY(kColorExtensionIconDecorationKeyShadow) \
   /* Eyedropper colors. */ \
   E_CPONLY(kColorEyedropperBoundary) \
   E_CPONLY(kColorEyedropperCentralPixelInnerRing) \
@@ -101,8 +103,6 @@
   /* Frame caption colors. */ \
   E(kColorFrameCaptionActive, ThemeProperties::COLOR_FRAME_CAPTION_ACTIVE) \
   E(kColorFrameCaptionInactive, ThemeProperties::COLOR_FRAME_CAPTION_INACTIVE) \
-  /* Google branding colors. */ \
-  E_CPONLY(kColorGooglePayLogo) \
   /* InfoBar colors. */ \
   E(kColorInfoBarBackground, ThemeProperties::COLOR_INFOBAR) \
   E(kColorInfoBarContentAreaSeparator, \
@@ -190,20 +190,25 @@
   E(kColorOmniboxText, ThemeProperties::COLOR_OMNIBOX_TEXT) \
   E(kColorOmniboxTextDimmed, ThemeProperties::COLOR_OMNIBOX_TEXT_DIMMED) \
   /* Payments colors. */ \
-  E_CPONLY(kColorPaymentRequestRowBackgroundHighlighted) \
+  E_CPONLY(kColorPaymentsFeedbackTipBackground) \
+  E_CPONLY(kColorPaymentsFeedbackTipBorder) \
+  E_CPONLY(kColorPaymentsFeedbackTipForeground) \
+  E_CPONLY(kColorPaymentsFeedbackTipIcon) \
+  E_CPONLY(kColorPaymentsGooglePayLogo) \
+  E_CPONLY(kColorPaymentsPromoCodeBackground) \
+  E_CPONLY(kColorPaymentsPromoCodeForeground) \
+  E_CPONLY(kColorPaymentsPromoCodeForegroundHovered) \
+  E_CPONLY(kColorPaymentsPromoCodeForegroundPressed) \
+  E_CPONLY(kColorPaymentsPromoCodeInkDrop) \
+  E_CPONLY(kColorPaymentsRequestRowBackgroundHighlighted) \
   /* Picture-in-Picture window colors. */ \
   E_CPONLY(kColorPipWindowBackToTabButtonBackground) \
   E_CPONLY(kColorPipWindowBackground) \
+  E_CPONLY(kColorPipWindowControlsBackground) \
   E_CPONLY(kColorPipWindowForeground) \
   E_CPONLY(kColorPipWindowHangUpButtonForeground) \
   E_CPONLY(kColorPipWindowSkipAdButtonBackground) \
   E_CPONLY(kColorPipWindowSkipAdButtonBorder) \
-  /* Payments promo code colors. */ \
-  E_CPONLY(kColorPromoCodeBackground) \
-  E_CPONLY(kColorPromoCodeForeground) \
-  E_CPONLY(kColorPromoCodeForegroundHovered) \
-  E_CPONLY(kColorPromoCodeForegroundPressed) \
-  E_CPONLY(kColorPromoCodeInkDrop) \
   /* PWA colors. */ \
   E_CPONLY(kColorPwaBackground) \
   E_CPONLY(kColorPwaMenuButtonIcon) \
@@ -363,6 +368,7 @@
     ThemeProperties::COLOR_TAB_STROKE_FRAME_INACTIVE) \
   E_CPONLY(kColorTabstripLoadingProgressBackground) \
   E_CPONLY(kColorTabstripLoadingProgressForeground) \
+  E_CPONLY(kColorTabstripScrollContainerShadow) \
   /* Thumbnail tab colors. */ \
   E_CPONLY(kColorThumbnailTabBackground) \
   E_CPONLY(kColorThumbnailTabForeground) \
diff --git a/chrome/browser/ui/color/chrome_color_mixer.cc b/chrome/browser/ui/color/chrome_color_mixer.cc
index 698db8c5..ef17095 100644
--- a/chrome/browser/ui/color/chrome_color_mixer.cc
+++ b/chrome/browser/ui/color/chrome_color_mixer.cc
@@ -242,6 +242,10 @@
   mixer[kColorExtensionIconBadgeBackgroundDefault] = {ui::kColorAccent};
   mixer[kColorExtensionIconBadgeForegroundDefault] =
       ui::GetColorWithMaxContrast(kColorExtensionIconBadgeBackgroundDefault);
+  mixer[kColorExtensionIconDecorationAmbientShadow] =
+      ui::SetAlpha(ui::kColorShadowBase, 0x26);
+  mixer[kColorExtensionIconDecorationKeyShadow] =
+      ui::SetAlpha(ui::kColorShadowBase, 0x4D);
   mixer[kColorEyedropperBoundary] = {SK_ColorDKGRAY};
   mixer[kColorEyedropperCentralPixelInnerRing] = {SK_ColorBLACK};
   mixer[kColorEyedropperCentralPixelOuterRing] = {SK_ColorWHITE};
@@ -265,10 +269,6 @@
       ui::GetColorWithMaxContrast({ui::kColorFrameActive});
   mixer[kColorFrameCaptionInactive] =
       ui::GetColorWithMaxContrast({ui::kColorFrameInactive});
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-  mixer[kColorGooglePayLogo] = {dark_mode ? SK_ColorWHITE
-                                          : gfx::kGoogleGrey700};
-#endif
   mixer[kColorInfoBarBackground] = {kColorToolbar};
   mixer[kColorInfoBarContentAreaSeparator] =
       ui::AlphaBlend(kColorToolbarButtonIcon, kColorInfoBarBackground, 0x3A);
@@ -316,26 +316,39 @@
       ui::kColorButtonForeground};
   mixer[kColorOmniboxText] =
       ui::GetColorWithMaxContrast(kColorOmniboxBackground);
-  mixer[kColorPaymentRequestRowBackgroundHighlighted] = {
+  mixer[kColorPaymentsFeedbackTipBackground] = {
+      ui::kColorSubtleEmphasisBackground};
+  mixer[kColorPaymentsFeedbackTipBorder] = {ui::kColorBubbleFooterBorder};
+  mixer[kColorPaymentsFeedbackTipForeground] = {
+      ui::kColorLabelForegroundSecondary};
+  mixer[kColorPaymentsFeedbackTipIcon] = {ui::kColorAlertMediumSeverity};
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+  mixer[kColorPaymentsGooglePayLogo] = {dark_mode ? SK_ColorWHITE
+                                                  : gfx::kGoogleGrey700};
+#endif
+  mixer[kColorPaymentsPromoCodeBackground] = {
+      dark_mode ? SkColorSetA(gfx::kGoogleGreen300, 0x1F)
+                : gfx::kGoogleGreen050};
+  mixer[kColorPaymentsPromoCodeForeground] = {dark_mode ? gfx::kGoogleGreen300
+                                                        : gfx::kGoogleGreen800};
+  mixer[kColorPaymentsPromoCodeForegroundHovered] = {
+      dark_mode ? gfx::kGoogleGreen200 : gfx::kGoogleGreen900};
+  mixer[kColorPaymentsPromoCodeForegroundPressed] = {
+      kColorPaymentsPromoCodeForegroundHovered};
+  mixer[kColorPaymentsPromoCodeInkDrop] = {dark_mode ? gfx::kGoogleGreen300
+                                                     : gfx::kGoogleGreen600};
+  mixer[kColorPaymentsRequestRowBackgroundHighlighted] = {
       SkColorSetA(SK_ColorBLACK, 0x0D)};
   mixer[kColorPipWindowBackToTabButtonBackground] = {
       SkColorSetA(SK_ColorBLACK, 0x60)};
   mixer[kColorPipWindowBackground] = {SK_ColorBLACK};
+  mixer[kColorPipWindowControlsBackground] = {
+      SkColorSetA(gfx::kGoogleGrey900, 0xC1)};
   mixer[kColorPipWindowForeground] =
       ui::GetColorWithMaxContrast(kColorPipWindowBackground);
   mixer[kColorPipWindowHangUpButtonForeground] = {gfx::kGoogleRed300};
   mixer[kColorPipWindowSkipAdButtonBackground] = {gfx::kGoogleGrey700};
   mixer[kColorPipWindowSkipAdButtonBorder] = {kColorPipWindowForeground};
-  mixer[kColorPromoCodeBackground] = {
-      dark_mode ? SkColorSetA(gfx::kGoogleGreen300, 0x1F)
-                : gfx::kGoogleGreen050};
-  mixer[kColorPromoCodeForeground] = {dark_mode ? gfx::kGoogleGreen300
-                                                : gfx::kGoogleGreen800};
-  mixer[kColorPromoCodeForegroundHovered] = {dark_mode ? gfx::kGoogleGreen200
-                                                       : gfx::kGoogleGreen900};
-  mixer[kColorPromoCodeForegroundPressed] = {kColorPromoCodeForegroundHovered};
-  mixer[kColorPromoCodeInkDrop] = {dark_mode ? gfx::kGoogleGreen300
-                                             : gfx::kGoogleGreen600};
   mixer[kColorQrCodeBackground] = {SK_ColorWHITE};
   mixer[kColorQrCodeBorder] = {ui::kColorMidground};
   mixer[kColorQuickAnswersReportQueryButtonBackground] =
@@ -519,6 +532,8 @@
   mixer[kColorTabstripLoadingProgressBackground] =
       ui::AlphaBlend(ui::kColorAccent, kColorToolbar, 0x32);
   mixer[kColorTabstripLoadingProgressForeground] = {ui::kColorAccent};
+  mixer[kColorTabstripScrollContainerShadow] =
+      ui::SetAlpha(ui::kColorShadowBase, 0x4D);
   mixer[kColorThumbnailTabBackground] = ui::BlendForMinContrast(
       ui::kColorAccent, ui::kColorFrameActive, absl::nullopt,
       color_utils::kMinimumVisibleContrastRatio);
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
index 8d6f8ae..f1b9597 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
@@ -15,24 +15,22 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "chrome/browser/app_mode/app_mode_utils.h"
-#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/permissions/permission_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/blocked_content/popunder_preventer.h"
 #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h"
 #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h"
 #include "chrome/browser/ui/exclusive_access/fullscreen_within_tab_helper.h"
 #include "chrome/browser/ui/status_bubble.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_switches.h"
-#include "components/content_settings/core/browser/host_content_settings_map.h"
-#include "components/permissions/permission_manager.h"
-#include "components/permissions/permission_result.h"
 #include "content/public/browser/navigation_details.h"
 #include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/permission_controller.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/common/extension.h"
+#include "third_party/blink/public/common/features.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 #include "ui/display/types/display_constants.h"
@@ -163,6 +161,14 @@
     return;
   }
 
+  if (base::FeatureList::IsEnabled(
+          blink::features::kWindowPlacementFullscreenCompanionWindow)) {
+    if (!popunder_preventer_)
+      popunder_preventer_ = std::make_unique<PopunderPreventer>(web_contents);
+    else
+      popunder_preventer_->WillActivateWebContents(web_contents);
+  }
+
   SetTabWithExclusiveAccess(web_contents);
   requesting_origin_ =
       requesting_frame->GetLastCommittedURL().DeprecatedGetOriginAsURL();
@@ -197,6 +203,8 @@
 }
 
 void FullscreenController::ExitFullscreenModeForTab(WebContents* web_contents) {
+  popunder_preventer_.reset();
+
   if (MaybeToggleFullscreenWithinTab(web_contents, false)) {
     // During tab capture of fullscreen-within-tab views, the browser window
     // fullscreen state is unchanged, so return now.
@@ -237,6 +245,16 @@
   PostFullscreenChangeNotification();
 }
 
+void FullscreenController::FullscreenTabOpeningPopup(
+    content::WebContents* opener,
+    content::WebContents* popup) {
+  DCHECK(base::FeatureList::IsEnabled(
+      blink::features::kWindowPlacementFullscreenCompanionWindow));
+  DCHECK_EQ(exclusive_access_tab(), opener);
+  DCHECK(popunder_preventer_);
+  popunder_preventer_->AddPotentialPopunder(popup);
+}
+
 void FullscreenController::OnTabDeactivated(
     content::WebContents* web_contents) {
   base::AutoReset<content::WebContents*> auto_resetter(&deactivated_contents_,
@@ -406,12 +424,13 @@
   if (display_id != display::kInvalidDisplayId) {
     // Check, but do not prompt, for permission to request a specific screen.
     // Sites generally need permission to get the display id in the first place.
-    auto* manager = PermissionManagerFactory::GetForProfile(
-        exclusive_access_manager()->context()->GetProfile());
-    if (!manager || !requesting_frame ||
-        manager->GetPermissionStatusForCurrentDocument(
-                   ContentSettingsType::WINDOW_PLACEMENT, requesting_frame)
-                .content_setting != ContentSetting::CONTENT_SETTING_ALLOW) {
+    if (!requesting_frame ||
+        requesting_frame->GetBrowserContext()
+                ->GetPermissionController()
+                ->GetPermissionStatusForCurrentDocument(
+                    content::PermissionType::WINDOW_PLACEMENT,
+                    requesting_frame) !=
+            blink::mojom::PermissionStatus::GRANTED) {
       display_id = display::kInvalidDisplayId;
     }
   }
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.h b/chrome/browser/ui/exclusive_access/fullscreen_controller.h
index 2c7a32b..7bd40f5 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller.h
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.h
@@ -13,6 +13,7 @@
 #include "ui/display/types/display_constants.h"
 
 class GURL;
+class PopunderPreventer;
 
 namespace content {
 class WebContents;
@@ -132,6 +133,10 @@
     return ptr_factory_.GetWeakPtr();
   }
 
+  // Called when fullscreen tabs open popups, to track potential popunders.
+  void FullscreenTabOpeningPopup(content::WebContents* opener,
+                                 content::WebContents* popup);
+
   // Platform Fullscreen ///////////////////////////////////////////////////////
 
   // Override from ExclusiveAccessControllerBase.
@@ -217,6 +222,11 @@
   // Used in testing to set the state to tab fullscreen.
   bool is_tab_fullscreen_for_testing_ = false;
 
+  // Tracks related popups that lost activation or were shown without activation
+  // during content fullscreen sessions. This also activates the popups when
+  // fullscreen exits, to prevent sites from creating persisent popunders.
+  std::unique_ptr<PopunderPreventer> popunder_preventer_;
+
   base::ObserverList<FullscreenObserver> observer_list_;
 
   base::WeakPtrFactory<FullscreenController> ptr_factory_{this};
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc
index 98d8537..ffa869ced 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h"
 #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h"
@@ -30,6 +31,7 @@
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/switches.h"
 #include "third_party/blink/public/mojom/frame/fullscreen.mojom.h"
 #include "ui/display/screen_base.h"
@@ -645,21 +647,12 @@
   ASSERT_FALSE(IsWindowFullscreenForTabOrPending());
 }
 
-// Tests experimental multi-screen functionality of FullscreenController.
+// Tests FullscreenController support of Multi-Screen Window Placement features.
 // Sites with the Window Placement permission can request fullscreen on a
-// specific screen, move fullscreen windows to different displays, and gain new
-// affordances to request fullscreen on permission grants and screen changes.
-class ExperimentalFullscreenControllerInteractiveTest
-    : public FullscreenControllerInteractiveTest,
-      public testing::WithParamInterface<bool> {
+// specific screen, move fullscreen windows to different displays, and more.
+class MultiScreenFullscreenControllerInteractiveTest
+    : public FullscreenControllerInteractiveTest {
  public:
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-        switches::kEnableBlinkFeatures,
-        (GetParam() ? "WindowPlacementV2" : "WindowPlacement"));
-    FullscreenControllerInteractiveTest::SetUpCommandLine(command_line);
-  }
-
   // Perform common setup operations for multi-screen fullscreen testing:
   // Mock a screen with two displays, move the browser onto the first display,
   // and auto-grant the Window Placement permission on its active tab.
@@ -778,6 +771,8 @@
 #endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
  private:
+  base::test::ScopedFeatureList feature_list_{
+      blink::features::kWindowPlacement};
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
   raw_ptr<display::Screen> original_screen_ = nullptr;
   display::ScreenBase screen_;
@@ -796,7 +791,7 @@
 #define MAYBE_SeparateDisplay SeparateDisplay
 #endif
 // Test requesting fullscreen on a separate display.
-IN_PROC_BROWSER_TEST_P(ExperimentalFullscreenControllerInteractiveTest,
+IN_PROC_BROWSER_TEST_F(MultiScreenFullscreenControllerInteractiveTest,
                        MAYBE_SeparateDisplay) {
   SetUpTestScreenAndWindowPlacementTab();
   const gfx::Rect original_bounds = browser()->window()->GetBounds();
@@ -824,7 +819,7 @@
 #define MAYBE_SeparateDisplayMaximized SeparateDisplayMaximized
 #endif
 // Test requesting fullscreen on a separate display from a maximized window.
-IN_PROC_BROWSER_TEST_P(ExperimentalFullscreenControllerInteractiveTest,
+IN_PROC_BROWSER_TEST_F(MultiScreenFullscreenControllerInteractiveTest,
                        MAYBE_SeparateDisplayMaximized) {
   SetUpTestScreenAndWindowPlacementTab();
   const gfx::Rect original_bounds = browser()->window()->GetBounds();
@@ -859,7 +854,7 @@
 #define MAYBE_SameDisplayAndSwap SameDisplayAndSwap
 #endif
 // Test requesting fullscreen on the current display and then swapping displays.
-IN_PROC_BROWSER_TEST_P(ExperimentalFullscreenControllerInteractiveTest,
+IN_PROC_BROWSER_TEST_F(MultiScreenFullscreenControllerInteractiveTest,
                        MAYBE_SameDisplayAndSwap) {
   SetUpTestScreenAndWindowPlacementTab();
   const gfx::Rect original_bounds = browser()->window()->GetBounds();
@@ -889,7 +884,7 @@
 #endif
 // Test requesting fullscreen on the current display and then swapping displays
 // from a maximized window.
-IN_PROC_BROWSER_TEST_P(ExperimentalFullscreenControllerInteractiveTest,
+IN_PROC_BROWSER_TEST_F(MultiScreenFullscreenControllerInteractiveTest,
                        MAYBE_SameDisplayAndSwapMaximized) {
   SetUpTestScreenAndWindowPlacementTab();
   const gfx::Rect original_bounds = browser()->window()->GetBounds();
@@ -928,7 +923,7 @@
 #define MAYBE_SeparateDisplayAndSwap SeparateDisplayAndSwap
 #endif
 // Test requesting fullscreen on a separate display and then swapping displays.
-IN_PROC_BROWSER_TEST_P(ExperimentalFullscreenControllerInteractiveTest,
+IN_PROC_BROWSER_TEST_F(MultiScreenFullscreenControllerInteractiveTest,
                        MAYBE_SeparateDisplayAndSwap) {
   SetUpTestScreenAndWindowPlacementTab();
   const gfx::Rect original_bounds = browser()->window()->GetBounds();
@@ -961,7 +956,7 @@
 #define MAYBE_SwapShowsBubble SwapShowsBubble
 #endif
 // Test requesting fullscreen on the current display and then swapping displays.
-IN_PROC_BROWSER_TEST_P(ExperimentalFullscreenControllerInteractiveTest,
+IN_PROC_BROWSER_TEST_F(MultiScreenFullscreenControllerInteractiveTest,
                        MAYBE_SwapShowsBubble) {
   SetUpTestScreenAndWindowPlacementTab();
 
@@ -994,62 +989,13 @@
 
 // TODO(crbug.com/1134731): Disabled on Windows, where RenderWidgetHostViewAura
 // blindly casts display::Screen::GetScreen() to display::win::ScreenWin*.
-// TODO(crbug.com/1183791): Disabled on Mac due to flaky ObserverList crashes.
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
-#define MAYBE_FullscreenOnScreensChange DISABLED_FullscreenOnScreensChange
-#else
-#define MAYBE_FullscreenOnScreensChange FullscreenOnScreensChange
-#endif
-// Tests async fullscreen requests on screenschange event.
-IN_PROC_BROWSER_TEST_P(ExperimentalFullscreenControllerInteractiveTest,
-                       MAYBE_FullscreenOnScreensChange) {
-  content::WebContents* tab = SetUpTestScreenAndWindowPlacementTab();
-
-  // Add a screenschange handler to requestFullscreen using the transient
-  // affordance granted on screen change events, after user activation expiry.
-  const std::string request_fullscreen_script = R"(
-    (async () => {
-      const screenDetails = await window.getScreenDetails();
-      screenDetails.onscreenschange = async () => {
-        if (!navigator.userActivation.isActive)
-          await document.body.requestFullscreen();
-      };
-    })();
-  )";
-  EXPECT_TRUE(ExecJs(tab, request_fullscreen_script));
-  EXPECT_FALSE(browser()->window()->IsFullscreen());
-  WaitForUserActivationExpiry();
-
-  // Update the display configuration to trigger window.onscreenschange.
-  FullscreenNotificationObserver fullscreen_observer(browser());
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  display::test::DisplayManagerTestApi(ash::Shell::Get()->display_manager())
-      .UpdateDisplay("0+0-800x800");
-#else
-  display_list().RemoveDisplay(2);
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-  if (GetParam())  // The request will only be honored with WindowPlacementV2.
-    fullscreen_observer.Wait();
-  EXPECT_EQ(GetParam(), browser()->window()->IsFullscreen());
-
-  // Close all tabs to avoid assertions failing when their cached screen info
-  // differs from the restored original Screen instance.
-  browser()->tab_strip_model()->CloseAllTabs();
-}
-
-INSTANTIATE_TEST_SUITE_P(V2,
-                         ExperimentalFullscreenControllerInteractiveTest,
-                         testing::Bool());
-
-// TODO(crbug.com/1134731): Disabled on Windows, where RenderWidgetHostViewAura
-// blindly casts display::Screen::GetScreen() to display::win::ScreenWin*.
 #if BUILDFLAG(IS_WIN)
 #define MAYBE_FullscreenOnPermissionGrant DISABLED_FullscreenOnPermissionGrant
 #else
 #define MAYBE_FullscreenOnPermissionGrant FullscreenOnPermissionGrant
 #endif
 // Test requesting fullscreen using the permission grant's transient activation.
-IN_PROC_BROWSER_TEST_P(ExperimentalFullscreenControllerInteractiveTest,
+IN_PROC_BROWSER_TEST_F(MultiScreenFullscreenControllerInteractiveTest,
                        MAYBE_FullscreenOnPermissionGrant) {
   EXPECT_TRUE(embedded_test_server()->Start());
   const GURL url(embedded_test_server()->GetURL("/simple.html"));
@@ -1075,3 +1021,132 @@
   RequestContentFullscreenFromScript(request_fullscreen_from_prompt_script,
                                      content::EXECUTE_SCRIPT_NO_USER_GESTURE);
 }
+
+// Tests FullscreenController support for fullscreen companion windows.
+class FullscreenCompanionWindowFullscreenControllerInteractiveTest
+    : public MultiScreenFullscreenControllerInteractiveTest,
+      public testing::WithParamInterface<bool> {
+ public:
+  FullscreenCompanionWindowFullscreenControllerInteractiveTest() {
+    feature_list_.InitWithFeatureState(
+        blink::features::kWindowPlacementFullscreenCompanionWindow, GetParam());
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+// TODO(crbug.com/1034772): Disabled on Windows, where views::FullscreenHandler
+// implements fullscreen by directly obtaining MONITORINFO, ignoring the mocked
+// display::Screen configuration used in this test. Disabled on Mac and Linux,
+// where the window server's async handling of the fullscreen window state may
+// transition the window into fullscreen on the actual (non-mocked) display
+// bounds before or after the window bounds checks, yielding flaky results.
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
+#define MAYBE_FullscreenCompanionWindow DISABLED_FullscreenCompanionWindow
+#else
+#define MAYBE_FullscreenCompanionWindow FullscreenCompanionWindow
+#endif
+// Test requesting fullscreen on a specific screen and opening a cross-screen
+// popup window from one gesture. Check the expected window activation pattern.
+IN_PROC_BROWSER_TEST_P(
+    FullscreenCompanionWindowFullscreenControllerInteractiveTest,
+    MAYBE_FullscreenCompanionWindow) {
+  SetUpTestScreenAndWindowPlacementTab();
+
+  // Execute JS to request fullscreen and open a popup on separate screens.
+  const std::string fullscreen_and_popup_script = R"(
+    (async () => {
+      if (!window.screenDetails)
+          window.screenDetails = await window.getScreenDetails();
+      const options = { screen: window.screenDetails.screens[0] };
+      await document.body.requestFullscreen(options);
+      if (navigator.userActivation.isActive)
+        return false;
+      const s = window.screenDetails.screens[1];
+      const f = `left=${s.availLeft},top=${s.availTop},width=300,height=200`;
+      window.open('.', '', f);
+      return !!document.fullscreenElement;
+    })();
+  )";
+  BrowserList* browser_list = BrowserList::GetInstance();
+  EXPECT_EQ(1u, browser_list->size());
+  RequestContentFullscreenFromScript(fullscreen_and_popup_script);
+  EXPECT_EQ(gfx::Rect(0, 0, 800, 800), browser()->window()->GetBounds());
+  // The popup opens iff kWindowPlacementFullscreenCompanionWindow is enabled.
+  EXPECT_EQ(GetParam() ? 2u : 1u, browser_list->size());
+  // Popup window activation is delayed until its opener exits fullscreen.
+  EXPECT_EQ(browser(), browser_list->GetLastActive());
+  ToggleTabFullscreen(/*enter_fullscreen=*/false);
+  EXPECT_EQ(GetParam(), browser() != browser_list->GetLastActive());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    ,
+    FullscreenCompanionWindowFullscreenControllerInteractiveTest,
+    ::testing::Bool());
+
+// Tests FullscreenController support for fullscreen on screenschange events.
+class FullscreenOnScreensChangeFullscreenControllerInteractiveTest
+    : public MultiScreenFullscreenControllerInteractiveTest,
+      public testing::WithParamInterface<bool> {
+ public:
+  FullscreenOnScreensChangeFullscreenControllerInteractiveTest() {
+    feature_list_.InitWithFeatureState(
+        blink::features::kWindowPlacementFullscreenOnScreensChange, GetParam());
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+// TODO(crbug.com/1134731): Disabled on Windows, where RenderWidgetHostViewAura
+// blindly casts display::Screen::GetScreen() to display::win::ScreenWin*.
+// TODO(crbug.com/1183791): Disabled on Mac due to flaky ObserverList crashes.
+#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
+#define MAYBE_FullscreenOnScreensChange DISABLED_FullscreenOnScreensChange
+#else
+#define MAYBE_FullscreenOnScreensChange FullscreenOnScreensChange
+#endif
+// Tests async fullscreen requests on screenschange event.
+IN_PROC_BROWSER_TEST_P(
+    FullscreenOnScreensChangeFullscreenControllerInteractiveTest,
+    MAYBE_FullscreenOnScreensChange) {
+  content::WebContents* tab = SetUpTestScreenAndWindowPlacementTab();
+
+  // Add a screenschange handler to requestFullscreen using the transient
+  // affordance granted on screen change events, after user activation expiry.
+  const std::string request_fullscreen_script = R"(
+    (async () => {
+      const screenDetails = await window.getScreenDetails();
+      screenDetails.onscreenschange = async () => {
+        if (!navigator.userActivation.isActive)
+          await document.body.requestFullscreen();
+      };
+    })();
+  )";
+  EXPECT_TRUE(ExecJs(tab, request_fullscreen_script));
+  EXPECT_FALSE(browser()->window()->IsFullscreen());
+  WaitForUserActivationExpiry();
+
+  // Update the display configuration to trigger window.onscreenschange.
+  FullscreenNotificationObserver fullscreen_observer(browser());
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  display::test::DisplayManagerTestApi(ash::Shell::Get()->display_manager())
+      .UpdateDisplay("0+0-800x800");
+#else
+  display_list().RemoveDisplay(2);
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+  if (GetParam())  // The request will only be honored with the flag enabled.
+    fullscreen_observer.Wait();
+  EXPECT_EQ(GetParam(), browser()->window()->IsFullscreen());
+
+  // Close all tabs to avoid assertions failing when their cached screen info
+  // differs from the restored original Screen instance.
+  browser()->tab_strip_model()->CloseAllTabs();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    ,
+    FullscreenOnScreensChangeFullscreenControllerInteractiveTest,
+    ::testing::Bool());
diff --git a/chrome/browser/ui/extensions/extension_action_view_controller_unittest.cc b/chrome/browser/ui/extensions/extension_action_view_controller_unittest.cc
index f3f8fe7..877bd19 100644
--- a/chrome/browser/ui/extensions/extension_action_view_controller_unittest.cc
+++ b/chrome/browser/ui/extensions/extension_action_view_controller_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/extensions/extension_action_view_controller.h"
+#include <memory>
 
 #include "base/bind.h"
 #include "base/callback_helpers.h"
@@ -110,11 +111,25 @@
   scoped_refptr<const extensions::Extension> CreateAndAddExtension(
       const std::string& name,
       extensions::ActionInfo::Type action_type) {
+    return CreateAndAddExtensionWithGrantedHostPermissions(name, action_type,
+                                                           {});
+  }
+
+  scoped_refptr<const extensions::Extension>
+  CreateAndAddExtensionWithGrantedHostPermissions(
+      const std::string& name,
+      extensions::ActionInfo::Type action_type,
+      const std::vector<std::string>& permissions) {
     scoped_refptr<const extensions::Extension> extension =
         extensions::ExtensionBuilder(name)
             .SetAction(action_type)
             .SetLocation(ManifestLocation::kInternal)
+            .AddPermissions(permissions)
             .Build();
+
+    if (!permissions.empty())
+      extension_service()->GrantPermissions(extension.get());
+
     extension_service()->AddExtension(extension.get());
     return extension;
   }
@@ -168,15 +183,10 @@
 
 // Tests the appearance of browser actions with blocked script actions.
 TEST_F(ExtensionActionViewControllerUnitTest, BrowserActionBlockedActions) {
-  scoped_refptr<const extensions::Extension> extension =
-      extensions::ExtensionBuilder("browser action")
-          .SetAction(extensions::ActionInfo::TYPE_BROWSER)
-          .SetLocation(ManifestLocation::kInternal)
-          .AddPermission("https://www.google.com/*")
-          .Build();
+  auto extension = CreateAndAddExtensionWithGrantedHostPermissions(
+      "browser_action", extensions::ActionInfo::TYPE_BROWSER,
+      {"https://www.google.com/*"});
 
-  extension_service()->GrantPermissions(extension.get());
-  extension_service()->AddExtension(extension.get());
   extensions::ScriptingPermissionsModifier permissions_modifier(profile(),
                                                                 extension);
   permissions_modifier.SetWithholdHostPermissions(true);
@@ -216,15 +226,10 @@
 
 // Tests the appearance of page actions with blocked script actions.
 TEST_F(ExtensionActionViewControllerUnitTest, PageActionBlockedActions) {
-  scoped_refptr<const extensions::Extension> extension =
-      extensions::ExtensionBuilder("page action")
-          .SetAction(extensions::ActionInfo::TYPE_PAGE)
-          .SetLocation(ManifestLocation::kInternal)
-          .AddPermission("https://www.google.com/*")
-          .Build();
+  auto extension = CreateAndAddExtensionWithGrantedHostPermissions(
+      "page_action", extensions::ActionInfo::TYPE_PAGE,
+      {"https://www.google.com/*"});
 
-  extension_service()->GrantPermissions(extension.get());
-  extension_service()->AddExtension(extension.get());
   extensions::ScriptingPermissionsModifier permissions_modifier(profile(),
                                                                 extension);
   permissions_modifier.SetWithholdHostPermissions(true);
@@ -576,14 +581,9 @@
 }
 
 TEST_F(ExtensionActionViewControllerUnitTest, RuntimeHostsTooltip) {
-  scoped_refptr<const extensions::Extension> extension =
-      extensions::ExtensionBuilder("extension name")
-          .SetAction(extensions::ActionInfo::TYPE_BROWSER)
-          .SetLocation(ManifestLocation::kInternal)
-          .AddPermission("https://www.google.com/*")
-          .Build();
-  extension_service()->GrantPermissions(extension.get());
-  extension_service()->AddExtension(extension.get());
+  auto extension = CreateAndAddExtensionWithGrantedHostPermissions(
+      "extension name", extensions::ActionInfo::TYPE_BROWSER,
+      {"https://www.google.com/*"});
 
   extensions::ScriptingPermissionsModifier permissions_modifier(profile(),
                                                                 extension);
@@ -695,12 +695,8 @@
 // Tests that an extension with the activeTab permission is shown to be pending
 // user approval for normal web pages, but not for restricted URLs.
 TEST_F(ExtensionActionViewControllerUnitTest, GetSiteInteractionWithActiveTab) {
-  scoped_refptr<const extensions::Extension> extension =
-      extensions::ExtensionBuilder("active tab")
-          .SetAction(extensions::ActionInfo::TYPE_BROWSER)
-          .AddPermission("activeTab")
-          .Build();
-  extension_service()->AddExtension(extension.get());
+  auto extension = CreateAndAddExtensionWithGrantedHostPermissions(
+      "active tab", extensions::ActionInfo::TYPE_BROWSER, {"activeTab"});
 
   // Navigate the browser to google.com. Since clicking the extension would
   // grant access to the page, the page interaction status should show as
@@ -793,14 +789,9 @@
 // (though it's a bit unclear when this is the case).
 // See https://crbug.com/888121
 TEST_F(ExtensionActionViewControllerUnitTest, TestGetIconWithNullWebContents) {
-  scoped_refptr<const extensions::Extension> extension =
-      extensions::ExtensionBuilder("extension name")
-          .SetAction(extensions::ActionInfo::TYPE_BROWSER)
-          .AddPermission("https://example.com/")
-          .Build();
-
-  extension_service()->GrantPermissions(extension.get());
-  extension_service()->AddExtension(extension.get());
+  auto extension = CreateAndAddExtensionWithGrantedHostPermissions(
+      "extension name", extensions::ActionInfo::TYPE_BROWSER,
+      {"https://example.com/"});
 
   extensions::ScriptingPermissionsModifier permissions_modifier(profile(),
                                                                 extension);
diff --git a/chrome/browser/ui/extensions/icon_with_badge_image_source.cc b/chrome/browser/ui/extensions/icon_with_badge_image_source.cc
index 536d512b..f065e8ac 100644
--- a/chrome/browser/ui/extensions/icon_with_badge_image_source.cc
+++ b/chrome/browser/ui/extensions/icon_with_badge_image_source.cc
@@ -204,20 +204,21 @@
 
 void IconWithBadgeImageSource::PaintBlockedActionDecoration(
     gfx::Canvas* canvas) {
+  // TODO(elainechien): This looks like it's trying to match the GM2 elevation
+  // +2 spec.  Move to ShadowValue::MakeShadowValues() and systematize.
+
   // To match the CSS notion of blur (spread outside the bounding box) to the
   // Skia notion of blur (spread outside and inside the bounding box), we have
   // to double the CSS-based blur values.
   constexpr int kBlurCorrection = 2;
 
-  constexpr int kKeyShadowOpacity = 0x4D;  // 30%
   const gfx::ShadowValue key_shadow(
       gfx::Vector2d(0, 1), kBlurCorrection * 2 /*blur*/,
-      SkColorSetA(gfx::kGoogleGrey800, kKeyShadowOpacity));
+      color_provider_->GetColor(kColorExtensionIconDecorationKeyShadow));
 
-  constexpr int kAmbientShadowOpacity = 0x26;  // 15%
   const gfx::ShadowValue ambient_shadow(
       gfx::Vector2d(0, 2), kBlurCorrection * 6 /*blur*/,
-      SkColorSetA(gfx::kGoogleGrey800, kAmbientShadowOpacity));
+      color_provider_->GetColor(kColorExtensionIconDecorationAmbientShadow));
 
   const float blocked_action_badge_radius = GetBlockedActionBadgeRadius();
 
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc
index 6785b53b6..208ac32 100644
--- a/chrome/browser/ui/search/search_tab_helper.cc
+++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -22,11 +22,11 @@
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
-#include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/bookmarks/bookmark_stats.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
+#include "chrome/browser/ui/color/chrome_color_id.h"
 #include "chrome/browser/ui/location_bar/location_bar.h"
 #include "chrome/browser/ui/search/omnibox_utils.h"
 #include "chrome/browser/ui/search/search_ipc_router_policy_impl.h"
@@ -60,7 +60,7 @@
 #include "extensions/common/constants.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/base/theme_provider.h"
+#include "ui/color/color_provider.h"
 #include "ui/gfx/vector_icon_types.h"
 #include "url/gurl.h"
 
@@ -264,22 +264,10 @@
 
 void SearchTabHelper::NtpThemeChanged(NtpTheme theme) {
   // Populate theme colors for this tab.
-  const auto* browser_window =
-      BrowserWindow::FindBrowserWindowWithWebContents(web_contents());
-  const auto* theme_provider =
-      browser_window ? browser_window->GetThemeProvider() : nullptr;
-  if (theme_provider) {
-    theme.background_color =
-        theme_provider->GetColor(ThemeProperties::COLOR_NTP_BACKGROUND);
-    theme.text_color =
-        theme_provider->GetColor(ThemeProperties::COLOR_NTP_TEXT);
-    theme.text_color_light =
-        theme_provider->GetColor(ThemeProperties::COLOR_NTP_TEXT_LIGHT);
-  } else {
-    theme.background_color = SK_ColorWHITE;
-    theme.text_color = SK_ColorBLACK;
-    theme.text_color_light = gfx::kGoogleGrey700;
-  }
+  const auto& color_provider = web_contents()->GetColorProvider();
+  theme.background_color = color_provider.GetColor(kColorNewTabPageBackground);
+  theme.text_color = color_provider.GetColor(kColorNewTabPageText);
+  theme.text_color_light = color_provider.GetColor(kColorNewTabPageTextLight);
 
   ipc_router_.SendNtpTheme(theme);
 }
diff --git a/chrome/browser/ui/views/autofill/payments/local_card_migration_bubble_views.cc b/chrome/browser/ui/views/autofill/payments/local_card_migration_bubble_views.cc
index 86a1783..1454c42 100644
--- a/chrome/browser/ui/views/autofill/payments/local_card_migration_bubble_views.cc
+++ b/chrome/browser/ui/views/autofill/payments/local_card_migration_bubble_views.cc
@@ -108,8 +108,9 @@
   // kGooglePayLogoIcon is square, and CreateTiledImage() will clip it whereas
   // setting the icon size would rescale it incorrectly.
   gfx::ImageSkia image = gfx::ImageSkiaOperations::CreateTiledImage(
-      gfx::CreateVectorIcon(kGooglePayLogoIcon,
-                            GetColorProvider()->GetColor(kColorGooglePayLogo)),
+      gfx::CreateVectorIcon(
+          kGooglePayLogoIcon,
+          GetColorProvider()->GetColor(kColorPaymentsGooglePayLogo)),
       /*x=*/0, /*y=*/0, kMigrationBubbleGooglePayLogoWidth,
       kMigrationBubbleGooglePayLogoHeight);
 #else
diff --git a/chrome/browser/ui/views/autofill/payments/local_card_migration_dialog_view.cc b/chrome/browser/ui/views/autofill/payments/local_card_migration_dialog_view.cc
index 4bc17c5..6fbda01 100644
--- a/chrome/browser/ui/views/autofill/payments/local_card_migration_dialog_view.cc
+++ b/chrome/browser/ui/views/autofill/payments/local_card_migration_dialog_view.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/ui/autofill/payments/local_card_migration_dialog_factory.h"
 #include "chrome/browser/ui/autofill/payments/local_card_migration_dialog_state.h"
 #include "chrome/browser/ui/autofill/payments/payments_ui_constants.h"
+#include "chrome/browser/ui/color/chrome_color_id.h"
 #include "chrome/browser/ui/views/autofill/payments/migratable_card_view.h"
 #include "chrome/browser/ui/views/autofill/payments/payments_view_util.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
@@ -100,11 +101,13 @@
     SetLayoutManager(std::make_unique<views::BoxLayout>(
         views::BoxLayout::Orientation::kHorizontal,
         gfx::Insets(container_insets), container_child_space));
+    SetBackground(views::CreateThemedSolidBackground(
+        this, kColorPaymentsFeedbackTipBackground));
 
     constexpr int kTipImageSize = 16;
     auto* lightbulb_outline_image = AddChildView(
         std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
-            vector_icons::kLightbulbOutlineIcon, ui::kColorAlertMediumSeverity,
+            vector_icons::kLightbulbOutlineIcon, kColorPaymentsFeedbackTipIcon,
             kTipImageSize)));
     lightbulb_outline_image->SetVerticalAlignment(
         views::ImageView::Alignment::kLeading);
@@ -123,28 +126,14 @@
   // views::Label:
   void OnThemeChanged() override {
     View::OnThemeChanged();
-    const bool should_use_dark_colors = GetNativeTheme()->ShouldUseDarkColors();
 
-    // TODO(tluk): We should not be using hard coded color constants and
-    // switching colors based on the dark mode flag. We should instead
-    // systematize these into color ids and simply call GetColor() for these
-    // ids.
-    SetBackground(views::CreateSolidBackground(
-        should_use_dark_colors ? gfx::kGoogleGrey800 : gfx::kGoogleGrey050));
-
-    // Do not add the border if it is not using dark colors.
     constexpr int kTipValuePromptBorderThickness = 1;
-    SetBorder(should_use_dark_colors
-                  ? views::NullBorder()
-                  : views::CreateSolidBorder(kTipValuePromptBorderThickness,
-                                             gfx::kGoogleGrey100));
-
-    // If it is in dark mode, set the font color to GG200 since it is on a
-    // lighter shade of grey background.
+    const auto* const color_provider = GetColorProvider();
+    SetBorder(views::CreateSolidBorder(
+        kTipValuePromptBorderThickness,
+        color_provider->GetColor(kColorPaymentsFeedbackTipBorder)));
     tip_->SetEnabledColor(
-        should_use_dark_colors
-            ? gfx::kGoogleGrey200
-            : GetColorProvider()->GetColor(ui::kColorLabelForegroundSecondary));
+        color_provider->GetColor(kColorPaymentsFeedbackTipForeground));
   }
 
  private:
diff --git a/chrome/browser/ui/views/autofill/payments/payments_view_util.cc b/chrome/browser/ui/views/autofill/payments/payments_view_util.cc
index fe0cc0f..423c09fa 100644
--- a/chrome/browser/ui/views/autofill/payments/payments_view_util.cc
+++ b/chrome/browser/ui/views/autofill/payments/payments_view_util.cc
@@ -71,7 +71,7 @@
         image = gfx::ImageSkiaOperations::CreateTiledImage(
             gfx::CreateVectorIcon(
                 kGooglePayLogoIcon,
-                GetColorProvider()->GetColor(kColorGooglePayLogo)),
+                GetColorProvider()->GetColor(kColorPaymentsGooglePayLogo)),
             /*x=*/0, /*y=*/0, kGooglePayLogoWidth, kIconHeight);
         break;
       case TitleWithIconAndSeparatorView::Icon::GOOGLE_G:
diff --git a/chrome/browser/ui/views/autofill/payments/promo_code_label_button.cc b/chrome/browser/ui/views/autofill/payments/promo_code_label_button.cc
index 97fe282..606a3bb0 100644
--- a/chrome/browser/ui/views/autofill/payments/promo_code_label_button.cc
+++ b/chrome/browser/ui/views/autofill/payments/promo_code_label_button.cc
@@ -30,31 +30,35 @@
 
   const auto* const color_provider = GetColorProvider();
   SetTextColor(views::Button::STATE_NORMAL,
-               color_provider->GetColor(kColorPromoCodeForeground));
-  SetTextColor(views::Button::STATE_HOVERED,
-               color_provider->GetColor(kColorPromoCodeForegroundHovered));
-  SetTextColor(views::Button::STATE_PRESSED,
-               color_provider->GetColor(kColorPromoCodeForegroundPressed));
+               color_provider->GetColor(kColorPaymentsPromoCodeForeground));
+  SetTextColor(
+      views::Button::STATE_HOVERED,
+      color_provider->GetColor(kColorPaymentsPromoCodeForegroundHovered));
+  SetTextColor(
+      views::Button::STATE_PRESSED,
+      color_provider->GetColor(kColorPaymentsPromoCodeForegroundPressed));
   SetImageModel(views::Button::STATE_NORMAL,
-                ui::ImageModel::FromVectorIcon(vector_icons::kContentCopyIcon,
-                                               kColorPromoCodeForeground,
-                                               kContentCopyIconSizePx));
-  SetImageModel(views::Button::STATE_HOVERED,
-                ui::ImageModel::FromVectorIcon(vector_icons::kContentCopyIcon,
-                                               kColorPromoCodeForegroundHovered,
-                                               kContentCopyIconSizePx));
-  SetImageModel(views::Button::STATE_PRESSED,
-                ui::ImageModel::FromVectorIcon(vector_icons::kContentCopyIcon,
-                                               kColorPromoCodeForegroundPressed,
-                                               kContentCopyIconSizePx));
+                ui::ImageModel::FromVectorIcon(
+                    vector_icons::kContentCopyIcon,
+                    kColorPaymentsPromoCodeForeground, kContentCopyIconSizePx));
+  SetImageModel(
+      views::Button::STATE_HOVERED,
+      ui::ImageModel::FromVectorIcon(vector_icons::kContentCopyIcon,
+                                     kColorPaymentsPromoCodeForegroundHovered,
+                                     kContentCopyIconSizePx));
+  SetImageModel(
+      views::Button::STATE_PRESSED,
+      ui::ImageModel::FromVectorIcon(vector_icons::kContentCopyIcon,
+                                     kColorPaymentsPromoCodeForegroundPressed,
+                                     kContentCopyIconSizePx));
   SetBackground(views::CreateRoundedRectBackground(
-      color_provider->GetColor(kColorPromoCodeBackground),
+      color_provider->GetColor(kColorPaymentsPromoCodeBackground),
       ChromeLayoutProvider::Get()->GetCornerRadiusMetric(
           views::Emphasis::kMedium)));
 
   views::InkDrop::Get(this)->SetMode(views::InkDropHost::InkDropMode::ON);
   views::InkDrop::Get(this)->SetBaseColor(
-      color_provider->GetColor(kColorPromoCodeInkDrop));
+      color_provider->GetColor(kColorPaymentsPromoCodeInkDrop));
   SetHasInkDropActionOnClick(true);
 
   SetHorizontalAlignment(gfx::ALIGN_CENTER);
diff --git a/chrome/browser/ui/views/bluetooth_device_credentials_view.cc b/chrome/browser/ui/views/bluetooth_device_credentials_view.cc
index 8088b78..e188244c8 100644
--- a/chrome/browser/ui/views/bluetooth_device_credentials_view.cc
+++ b/chrome/browser/ui/views/bluetooth_device_credentials_view.cc
@@ -17,9 +17,8 @@
 #include "device/bluetooth/strings/grit/bluetooth_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/color/color_id.h"
 #include "ui/compositor/layer.h"
-#include "ui/gfx/color_utils.h"
-#include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/flex_layout.h"
@@ -111,9 +110,8 @@
 
   constexpr int kIconSize = 48;  // width and height.
   auto icon_view = std::make_unique<views::ImageView>();
-  icon_view->SetImage(gfx::CreateVectorIcon(
-      vector_icons::kBluetoothIcon, kIconSize,
-      color_utils::DeriveDefaultIconColor(gfx::kGoogleGrey700)));
+  icon_view->SetImage(ui::ImageModel::FromVectorIcon(
+      vector_icons::kBluetoothIcon, ui::kColorIcon, kIconSize));
   icon_view_ = AddChildView(std::move(icon_view));
 
   auto contents_wrapper = std::make_unique<views::View>();
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
index aed90b3b..1685f0c8 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -1917,18 +1917,12 @@
   if (tp) {
     tab_groups::TabGroupColorId tab_group_color_id = saved_group.color;
 
-    // In most cases our text color will match the hover border color.
-    // However, for yellow, orange, and custom colors/themes this may not be
-    // true with respect to contrast and visibility, so a default grey color may
-    // be more appropriate.
     SkColor background_color =
         tp->GetColor(GetTabGroupBookmarkColorId(tab_group_color_id));
     text_color = tp->GetColor(GetTabGroupDialogColorId(tab_group_color_id));
-    bool meets_contrast_req =
-        color_utils::GetContrastRatio(background_color, text_color) >=
-        color_utils::kMinimumVisibleContrastRatio;
-    if (!meets_contrast_req)
-      text_color = gfx::kGoogleGrey800;
+    text_color = color_utils::PickGoogleColor(
+        text_color, background_color,
+        color_utils::kMinimumReadableContrastRatio);
 
     // Set empty border using the default horizontal padding (but leaving
     // vertical empty). This provides enough space to render some
diff --git a/chrome/browser/ui/views/borealis/borealis_installer_view.cc b/chrome/browser/ui/views/borealis/borealis_installer_view.cc
index 822e5f7..0158417 100644
--- a/chrome/browser/ui/views/borealis/borealis_installer_view.cc
+++ b/chrome/browser/ui/views/borealis/borealis_installer_view.cc
@@ -157,7 +157,6 @@
   installation_progress_message_label_ =
       new views::Label(std::u16string(), CONTEXT_DIALOG_BODY_TEXT_SMALL,
                        views::style::STYLE_SECONDARY);
-  installation_progress_message_label_->SetEnabledColor(gfx::kGoogleGrey700);
   installation_progress_message_label_->SetProperty(
       views::kMarginsKey,
       gfx::Insets(kInstallationProgressMessageHeight, 0, 0, 0));
diff --git a/chrome/browser/ui/views/extensions/settings_overridden_dialog_view.cc b/chrome/browser/ui/views/extensions/settings_overridden_dialog_view.cc
index 707188a9..aa432c0 100644
--- a/chrome/browser/ui/views/extensions/settings_overridden_dialog_view.cc
+++ b/chrome/browser/ui/views/extensions/settings_overridden_dialog_view.cc
@@ -13,6 +13,7 @@
 #include "components/constrained_window/constrained_window_views.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/color/color_id.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/controls/label.h"
@@ -28,8 +29,7 @@
                  l10n_util::GetStringUTF16(
                      IDS_EXTENSION_SETTINGS_OVERRIDDEN_DIALOG_KEEP_IT));
   SetLayoutManager(std::make_unique<views::FillLayout>());
-  ChromeLayoutProvider* const layout_provider = ChromeLayoutProvider::Get();
-  set_margins(layout_provider->GetDialogInsetsForContentType(
+  set_margins(ChromeLayoutProvider::Get()->GetDialogInsetsForContentType(
       views::DialogContentType::kText, views::DialogContentType::kText));
 
   using DialogResult = SettingsOverriddenDialogController::DialogResult;
@@ -51,20 +51,9 @@
 
   SettingsOverriddenDialogController::ShowParams show_params =
       controller_->GetShowParams();
-
   SetTitle(show_params.dialog_title);
-
-  if (show_params.icon) {
+  if (show_params.icon)
     SetShowIcon(true);
-    // Note: Any icons added *should* fully specify their own color, so this
-    // will be a no-op. But, the call requires a color, and this enables testing
-    // with other icons and a reasonable fallback.
-    constexpr SkColor kPlaceholderColor = gfx::kGoogleGrey500;
-    SetIcon(gfx::CreateVectorIcon(*show_params.icon,
-                                  layout_provider->GetDistanceMetric(
-                                      DISTANCE_BUBBLE_HEADER_VECTOR_ICON_SIZE),
-                                  kPlaceholderColor));
-  }
 
   auto message_label = std::make_unique<views::Label>(
       show_params.message, views::style::CONTEXT_DIALOG_BODY_TEXT,
@@ -85,6 +74,19 @@
   }
 }
 
+void SettingsOverriddenDialogView::OnThemeChanged() {
+  views::DialogDelegateView::OnThemeChanged();
+
+  const gfx::VectorIcon* icon = controller_->GetShowParams().icon;
+  if (icon) {
+    SetIcon(
+        gfx::CreateVectorIcon(*icon,
+                              ChromeLayoutProvider::Get()->GetDistanceMetric(
+                                  DISTANCE_BUBBLE_HEADER_VECTOR_ICON_SIZE),
+                              GetColorProvider()->GetColor(ui::kColorIcon)));
+  }
+}
+
 void SettingsOverriddenDialogView::Show(gfx::NativeWindow parent) {
   constrained_window::CreateBrowserModalDialogViews(this, parent)->Show();
   controller_->OnDialogShown();
diff --git a/chrome/browser/ui/views/extensions/settings_overridden_dialog_view.h b/chrome/browser/ui/views/extensions/settings_overridden_dialog_view.h
index 3c0faf92..2c8ae93 100644
--- a/chrome/browser/ui/views/extensions/settings_overridden_dialog_view.h
+++ b/chrome/browser/ui/views/extensions/settings_overridden_dialog_view.h
@@ -25,6 +25,8 @@
       delete;
   ~SettingsOverriddenDialogView() override;
 
+  void OnThemeChanged() override;
+
   // Displays the dialog with the given |parent|.
   void Show(gfx::NativeWindow parent);
 
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index bbf4a79..ca085457 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -3999,9 +3999,8 @@
         // occluding the active window receiving key events on Mac and Linux,
         // and also prevents an inactive fullscreen window and its exit bubble
         // from being occluded by the active window on Windows and Chrome OS.
-        // Initial content fullscreen requests require user activation (so the
-        // window should already be active), but swapping the screen used for
-        // fullscreen does not require user activation on the fullscreen window.
+        // Content fullscreen requests require user activation (so the window
+        // should already be active), but it is safer to ensure activation here.
         Activate();
       }
 
diff --git a/chrome/browser/ui/views/overlay/close_image_button.cc b/chrome/browser/ui/views/overlay/close_image_button.cc
index d3400d7..a3d9c0f0 100644
--- a/chrome/browser/ui/views/overlay/close_image_button.cc
+++ b/chrome/browser/ui/views/overlay/close_image_button.cc
@@ -15,18 +15,19 @@
 
 namespace {
 
-constexpr int kCloseButtonMargin = 8;
-constexpr int kCloseButtonSize = 16;
+constexpr int kCloseButtonMargin = 4;
+constexpr int kCloseButtonSize = 24;
+constexpr int kCloseButtonIconSize = 16;
 
 }  // namespace
 
 CloseImageButton::CloseImageButton(PressedCallback callback)
     : OverlayWindowImageButton(std::move(callback)) {
   SetSize(gfx::Size(kCloseButtonSize, kCloseButtonSize));
-  SetImageModel(
-      views::Button::STATE_NORMAL,
-      ui::ImageModel::FromVectorIcon(
-          views::kIcCloseIcon, kColorPipWindowForeground, kCloseButtonSize));
+  SetImageModel(views::Button::STATE_NORMAL,
+                ui::ImageModel::FromVectorIcon(views::kIcCloseIcon,
+                                               kColorPipWindowForeground,
+                                               kCloseButtonIconSize));
 
   // Accessibility.
   const std::u16string close_button_label(
diff --git a/chrome/browser/ui/views/overlay/constants.h b/chrome/browser/ui/views/overlay/constants.h
new file mode 100644
index 0000000..8e977d9
--- /dev/null
+++ b/chrome/browser/ui/views/overlay/constants.h
@@ -0,0 +1,10 @@
+// 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_UI_VIEWS_OVERLAY_CONSTANTS_H_
+#define CHROME_BROWSER_UI_VIEWS_OVERLAY_CONSTANTS_H_
+
+constexpr int kPipWindowIconPadding = 8;
+
+#endif  // CHROME_BROWSER_UI_VIEWS_OVERLAY_CONSTANTS_H_
diff --git a/chrome/browser/ui/views/overlay/hang_up_button.cc b/chrome/browser/ui/views/overlay/hang_up_button.cc
index 26f8f5ff..75bfe0f 100644
--- a/chrome/browser/ui/views/overlay/hang_up_button.cc
+++ b/chrome/browser/ui/views/overlay/hang_up_button.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/views/overlay/hang_up_button.h"
 
 #include "chrome/browser/ui/color/chrome_color_id.h"
+#include "chrome/browser/ui/views/overlay/constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -27,10 +28,11 @@
 }
 
 void HangUpButton::UpdateImage() {
+  const int icon_size = std::max(0, width() - (2 * kPipWindowIconPadding));
   SetImageModel(views::Button::STATE_NORMAL,
                 ui::ImageModel::FromVectorIcon(
                     vector_icons::kCallEndIcon,
-                    kColorPipWindowHangUpButtonForeground, width()));
+                    kColorPipWindowHangUpButtonForeground, icon_size));
 }
 
 BEGIN_METADATA(HangUpButton, OverlayWindowImageButton)
diff --git a/chrome/browser/ui/views/overlay/overlay_window_image_button.cc b/chrome/browser/ui/views/overlay/overlay_window_image_button.cc
index 6c140ae..59a4710 100644
--- a/chrome/browser/ui/views/overlay/overlay_window_image_button.cc
+++ b/chrome/browser/ui/views/overlay/overlay_window_image_button.cc
@@ -10,6 +10,7 @@
 #include "ui/color/color_provider.h"
 #include "ui/views/animation/ink_drop.h"
 #include "ui/views/controls/button/image_button_factory.h"
+#include "ui/views/controls/highlight_path_generator.h"
 #include "ui/views/native_cursor.h"
 
 OverlayWindowImageButton::OverlayWindowImageButton(PressedCallback callback)
@@ -18,6 +19,7 @@
   SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
 
   views::ConfigureVectorImageButton(this);
+  views::InstallCircleHighlightPathGenerator(this);
 
   SetInstallFocusRingOnFocus(true);
 }
diff --git a/chrome/browser/ui/views/overlay/playback_image_button.cc b/chrome/browser/ui/views/overlay/playback_image_button.cc
index bcd3b2e1..cb1621a9d 100644
--- a/chrome/browser/ui/views/overlay/playback_image_button.cc
+++ b/chrome/browser/ui/views/overlay/playback_image_button.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/ui/color/chrome_color_id.h"
+#include "chrome/browser/ui/views/overlay/constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -24,12 +25,13 @@
 }
 
 void PlaybackImageButton::OnBoundsChanged(const gfx::Rect& rect) {
+  const int icon_size = std::max(0, width() - (2 * kPipWindowIconPadding));
   play_image_ = ui::ImageModel::FromVectorIcon(
-      vector_icons::kPlayArrowIcon, kColorPipWindowForeground, size().width());
+      vector_icons::kPlayArrowIcon, kColorPipWindowForeground, icon_size);
   pause_image_ = ui::ImageModel::FromVectorIcon(
-      vector_icons::kPauseIcon, kColorPipWindowForeground, size().width());
+      vector_icons::kPauseIcon, kColorPipWindowForeground, icon_size);
   replay_image_ = ui::ImageModel::FromVectorIcon(
-      vector_icons::kReplayIcon, kColorPipWindowForeground, size().width());
+      vector_icons::kReplayIcon, kColorPipWindowForeground, icon_size);
 
   UpdateImageAndTooltipText();
 }
diff --git a/chrome/browser/ui/views/overlay/toggle_camera_button.cc b/chrome/browser/ui/views/overlay/toggle_camera_button.cc
index 46ec4441..20b82ff4 100644
--- a/chrome/browser/ui/views/overlay/toggle_camera_button.cc
+++ b/chrome/browser/ui/views/overlay/toggle_camera_button.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/views/overlay/toggle_camera_button.h"
 
 #include "chrome/browser/ui/color/chrome_color_id.h"
+#include "chrome/browser/ui/views/overlay/constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -37,10 +38,11 @@
                                    : vector_icons::kVideocamOffIcon;
   auto text = is_turned_on_ ? IDS_PICTURE_IN_PICTURE_TURN_OFF_CAMERA_TEXT
                             : IDS_PICTURE_IN_PICTURE_TURN_ON_CAMERA_TEXT;
+  const int icon_size = std::max(0, width() - (2 * kPipWindowIconPadding));
 
-  SetImageModel(
-      views::Button::STATE_NORMAL,
-      ui::ImageModel::FromVectorIcon(icon, kColorPipWindowForeground, width()));
+  SetImageModel(views::Button::STATE_NORMAL,
+                ui::ImageModel::FromVectorIcon(icon, kColorPipWindowForeground,
+                                               icon_size));
   SetTooltipText(l10n_util::GetStringUTF16(text));
 }
 
diff --git a/chrome/browser/ui/views/overlay/toggle_microphone_button.cc b/chrome/browser/ui/views/overlay/toggle_microphone_button.cc
index 59b9a544..1a1edb6 100644
--- a/chrome/browser/ui/views/overlay/toggle_microphone_button.cc
+++ b/chrome/browser/ui/views/overlay/toggle_microphone_button.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/views/overlay/toggle_microphone_button.h"
 
 #include "chrome/browser/ui/color/chrome_color_id.h"
+#include "chrome/browser/ui/views/overlay/constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -37,10 +38,11 @@
       is_muted_ ? vector_icons::kMicOffIcon : vector_icons::kMicIcon;
   auto text = is_muted_ ? IDS_PICTURE_IN_PICTURE_UNMUTE_MICROPHONE_TEXT
                         : IDS_PICTURE_IN_PICTURE_MUTE_MICROPHONE_TEXT;
+  const int icon_size = std::max(0, width() - (2 * kPipWindowIconPadding));
 
-  SetImageModel(
-      views::Button::STATE_NORMAL,
-      ui::ImageModel::FromVectorIcon(icon, kColorPipWindowForeground, width()));
+  SetImageModel(views::Button::STATE_NORMAL,
+                ui::ImageModel::FromVectorIcon(icon, kColorPipWindowForeground,
+                                               icon_size));
   SetTooltipText(l10n_util::GetStringUTF16(text));
 }
 
diff --git a/chrome/browser/ui/views/overlay/video_overlay_window_views.cc b/chrome/browser/ui/views/overlay/video_overlay_window_views.cc
index b2e2818..6d2744b6 100644
--- a/chrome/browser/ui/views/overlay/video_overlay_window_views.cc
+++ b/chrome/browser/ui/views/overlay/video_overlay_window_views.cc
@@ -71,28 +71,25 @@
 
 namespace {
 
-// The opacity of the controls scrim.
-constexpr double kControlsScrimOpacity = 0.76;
-
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 // The opacity of the resize handle control.
 constexpr double kResizeHandleOpacity = 0.38;
 #endif
 
 // Size of a primary control.
-constexpr gfx::Size kPrimaryControlSize(36, 36);
+constexpr gfx::Size kPrimaryControlSize(52, 52);
 
 // Margin from the bottom of the window for primary controls.
-constexpr int kPrimaryControlBottomMargin = 8;
+constexpr int kPrimaryControlBottomMargin = 0;
 
 // Size of a secondary control.
-constexpr gfx::Size kSecondaryControlSize(20, 20);
+constexpr gfx::Size kSecondaryControlSize(36, 36);
 
 // Margin from the bottom of the window for secondary controls.
-constexpr int kSecondaryControlBottomMargin = 16;
+constexpr int kSecondaryControlBottomMargin = 8;
 
 // Margin between controls.
-constexpr int kControlMargin = 32;
+constexpr int kControlMargin = 16;
 
 template <typename T>
 T* AddChildView(std::vector<std::unique_ptr<views::View>>* views,
@@ -119,6 +116,28 @@
 BEGIN_METADATA(WindowBackgroundView, views::View)
 END_METADATA
 
+class ControlsBackgroundView : public views::View {
+ public:
+  METADATA_HEADER(ControlsBackgroundView);
+
+  ControlsBackgroundView() = default;
+  ControlsBackgroundView(const ControlsBackgroundView&) = delete;
+  ControlsBackgroundView& operator=(const ControlsBackgroundView&) = delete;
+  ~ControlsBackgroundView() override = default;
+
+  void OnThemeChanged() override {
+    views::View::OnThemeChanged();
+    const SkColor color =
+        GetColorProvider()->GetColor(kColorPipWindowControlsBackground);
+    layer()->SetColor(SkColorSetA(color, SK_AlphaOPAQUE));
+    layer()->SetOpacity(static_cast<float>(SkColorGetA(color)) /
+                        SK_AlphaOPAQUE);
+  }
+};
+
+BEGIN_METADATA(ControlsBackgroundView, views::View)
+END_METADATA
+
 }  // namespace
 
 // static
@@ -222,7 +241,7 @@
   // entirely window when platform has fractional scale applied.
   auto window_background_view = std::make_unique<WindowBackgroundView>();
   auto video_view = std::make_unique<views::View>();
-  auto controls_scrim_view = std::make_unique<views::View>();
+  auto controls_scrim_view = std::make_unique<ControlsBackgroundView>();
   auto controls_container_view = std::make_unique<views::View>();
   auto close_controls_view =
       std::make_unique<CloseImageButton>(base::BindRepeating(
@@ -322,8 +341,6 @@
   // views::View that holds the scrim, which appears with the controls. -------
   controls_scrim_view->SetPaintToLayer(ui::LAYER_SOLID_COLOR);
   controls_scrim_view->layer()->SetName("ControlsScrimView");
-  controls_scrim_view->layer()->SetColor(gfx::kGoogleGrey900);
-  controls_scrim_view->layer()->SetOpacity(kControlsScrimOpacity);
 
   // views::View that is a parent of all the controls. Makes hiding and showing
   // all the controls at once easier.
diff --git a/chrome/browser/ui/views/payments/payment_request_row_view.cc b/chrome/browser/ui/views/payments/payment_request_row_view.cc
index baf7d07..2f3ff220 100644
--- a/chrome/browser/ui/views/payments/payment_request_row_view.cc
+++ b/chrome/browser/ui/views/payments/payment_request_row_view.cc
@@ -115,7 +115,7 @@
 void PaymentRequestRowView::SetHighlighted(bool highlighted) {
   if (highlighted) {
     SetBackground(views::CreateThemedSolidBackground(
-        this, kColorPaymentRequestRowBackgroundHighlighted));
+        this, kColorPaymentsRequestRowBackgroundHighlighted));
     SetBottomSeparatorVisible(false);
     if (previous_row_)
       previous_row_->SetBottomSeparatorVisible(false);
diff --git a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.cc b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.cc
index eb5b8fe..55acec13 100644
--- a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.cc
+++ b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.cc
@@ -31,6 +31,7 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/text/bytes_formatting.h"
 #include "ui/chromeos/devicetype_utils.h"
+#include "ui/color/color_id.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/border.h"
@@ -182,7 +183,6 @@
 
   download_progress_message_label_ =
       new views::Label(std::u16string(), {kDownloadProgressMessageFont});
-  download_progress_message_label_->SetEnabledColor(gfx::kGoogleGrey700);
   download_progress_message_label_->SetProperty(
       views::kMarginsKey, gfx::Insets(kDownloadProgressMessageHeight -
                                           kDownloadProgressMessageFontSize,
@@ -521,6 +521,12 @@
   OnStateUpdated();
 }
 
+void PluginVmInstallerView::OnThemeChanged() {
+  views::BubbleDialogDelegateView::OnThemeChanged();
+  download_progress_message_label_->SetEnabledColor(
+      GetColorProvider()->GetColor(ui::kColorSecondaryForeground));
+}
+
 void PluginVmInstallerView::OnStateUpdated() {
   LOG_FUNCTION_CALL() << " with state_ = " << static_cast<int>(state_)
                       << ", installing_state_ = "
diff --git a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.h b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.h
index cef1827..4db59f9c 100644
--- a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.h
+++ b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.h
@@ -79,6 +79,7 @@
   void OnLinkClicked();
   // views::BubbleDialogDelegateView implementation.
   void AddedToWidget() override;
+  void OnThemeChanged() override;
 
   std::u16string GetDownloadProgressMessage(uint64_t bytes_downloaded,
                                             int64_t content_length) const;
diff --git a/chrome/browser/ui/views/privacy_sandbox/privacy_sandbox_dialog_view_browsertest.cc b/chrome/browser/ui/views/privacy_sandbox/privacy_sandbox_dialog_view_browsertest.cc
index ca59070..02a1c2bb 100644
--- a/chrome/browser/ui/views/privacy_sandbox/privacy_sandbox_dialog_view_browsertest.cc
+++ b/chrome/browser/ui/views/privacy_sandbox/privacy_sandbox_dialog_view_browsertest.cc
@@ -8,8 +8,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/privacy_sandbox/privacy_sandbox_dialog.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/test/test_browser_dialog.h"
-#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/privacy_sandbox/privacy_sandbox_dialog_view.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "content/public/browser/web_contents.h"
@@ -20,9 +18,6 @@
 
 namespace {
 
-constexpr int kAverageBrowserWidth = 800;
-constexpr int kAverageBrowserHeight = 800;
-
 class MockPrivacySandboxService : public PrivacySandboxService {
  public:
   MOCK_METHOD(void,
@@ -38,7 +33,7 @@
 
 }  // namespace
 
-class PrivacySandboxDialogViewBrowserTest : public DialogBrowserTest {
+class PrivacySandboxDialogViewBrowserTest : public InProcessBrowserTest {
  public:
   void SetUpOnMainThread() override {
     mock_service_ = static_cast<MockPrivacySandboxService*>(
@@ -47,31 +42,6 @@
             base::BindRepeating(&BuildMockPrivacySandboxService)));
   }
 
-  // DialogBrowserTest:
-  void ShowUi(const std::string& name) override {
-    PrivacySandboxService::DialogType dialog_type =
-        PrivacySandboxService::DialogType::kNone;
-    if (name == "Consent") {
-      dialog_type = PrivacySandboxService::DialogType::kConsent;
-    }
-    if (name == "Notice") {
-      dialog_type = PrivacySandboxService::DialogType::kNotice;
-    }
-    ASSERT_NE(dialog_type, PrivacySandboxService::DialogType::kNone);
-
-    // Resize the browser window to guarantee enough space for the dialog.
-    BrowserView::GetBrowserViewForBrowser(browser())->GetWidget()->SetSize(
-        {kAverageBrowserWidth, kAverageBrowserHeight});
-
-    views::NamedWidgetShownWaiter waiter(
-        views::test::AnyWidgetTestPasskey{},
-        PrivacySandboxDialogView::kViewClassName);
-    ShowPrivacySandboxDialog(browser(), dialog_type);
-    waiter.WaitIfNeededAndGet();
-
-    base::RunLoop().RunUntilIdle();
-  }
-
   MockPrivacySandboxService* mock_service() { return mock_service_; }
 
  private:
@@ -131,25 +101,3 @@
   // expectations before that happens.
   testing::Mock::VerifyAndClearExpectations(mock_service());
 }
-
-IN_PROC_BROWSER_TEST_F(PrivacySandboxDialogViewBrowserTest, InvokeUi_Consent) {
-  EXPECT_CALL(
-      *mock_service(),
-      DialogActionOccurred(PrivacySandboxService::DialogAction::kConsentShown));
-  EXPECT_CALL(
-      *mock_service(),
-      DialogActionOccurred(
-          PrivacySandboxService::DialogAction::kConsentClosedNoDecision));
-  ShowAndVerifyUi();
-}
-
-IN_PROC_BROWSER_TEST_F(PrivacySandboxDialogViewBrowserTest, InvokeUi_Notice) {
-  EXPECT_CALL(
-      *mock_service(),
-      DialogActionOccurred(PrivacySandboxService::DialogAction::kNoticeShown));
-  EXPECT_CALL(
-      *mock_service(),
-      DialogActionOccurred(
-          PrivacySandboxService::DialogAction::kNoticeClosedNoInteraction));
-  ShowAndVerifyUi();
-}
diff --git a/chrome/browser/ui/views/profiles/badged_profile_photo.cc b/chrome/browser/ui/views/profiles/badged_profile_photo.cc
index 5b036ab6..ac6a13e 100644
--- a/chrome/browser/ui/views/profiles/badged_profile_photo.cc
+++ b/chrome/browser/ui/views/profiles/badged_profile_photo.cc
@@ -71,37 +71,33 @@
     ::views::ImageView::OnThemeChanged();
     switch (badge_type_) {
       case BadgedProfilePhoto::BADGE_TYPE_SUPERVISOR:
-        SetImage(gfx::CreateVectorIcon(
-            kSupervisorAccountCircleIcon, kBadgeIconSize,
-            GetColorProvider()->GetColor(ui::kColorIcon)));
+        SetImage(ui::ImageModel::FromVectorIcon(
+            kSupervisorAccountCircleIcon, ui::kColorIcon, kBadgeIconSize));
         break;
       case BadgedProfilePhoto::BADGE_TYPE_CHILD:
-        SetImage(gfx::CreateVectorIcon(
-            kAccountChildCircleIcon, kBadgeIconSize,
-            GetColorProvider()->GetColor(ui::kColorIcon)));
+        SetImage(ui::ImageModel::FromVectorIcon(
+            kAccountChildCircleIcon, ui::kColorIcon, kBadgeIconSize));
         break;
       case BadgedProfilePhoto::BADGE_TYPE_SYNC_COMPLETE:
-        SetImage(gfx::CreateVectorIcon(
-            kSyncCircleIcon, kBadgeIconSize,
-            GetColorProvider()->GetColor(ui::kColorAlertLowSeverity)));
+        SetImage(ui::ImageModel::FromVectorIcon(
+            kSyncCircleIcon, ui::kColorAlertLowSeverity, kBadgeIconSize));
         break;
       case BadgedProfilePhoto::BADGE_TYPE_SYNC_ERROR:
-        SetImage(gfx::CreateVectorIcon(
-            kSyncErrorCircleIcon, kBadgeIconSize,
-            GetColorProvider()->GetColor(ui::kColorAlertHighSeverity)));
+        SetImage(ui::ImageModel::FromVectorIcon(
+            kSyncErrorCircleIcon, ui::kColorAlertHighSeverity, kBadgeIconSize));
         break;
       case BadgedProfilePhoto::BADGE_TYPE_SYNC_PAUSED:
-        SetImage(gfx::CreateVectorIcon(
-            kSyncPausedCircleIcon, kBadgeIconSize,
-            GetColorProvider()->GetColor(ui::kColorButtonBackgroundProminent)));
+        SetImage(ui::ImageModel::FromVectorIcon(
+            kSyncPausedCircleIcon,
+            ui::kColorButtonBackgroundProminent, kBadgeIconSize));
         break;
       case BadgedProfilePhoto::BADGE_TYPE_SYNC_DISABLED:
-        SetImage(gfx::CreateVectorIcon(kSyncCircleIcon, kBadgeIconSize,
-                                       gfx::kGoogleGrey400));
+        SetImage(ui::ImageModel::FromVectorIcon(
+            kSyncCircleIcon, ui::kColorIconDisabled, kBadgeIconSize));
         break;
       case BadgedProfilePhoto::BADGE_TYPE_SYNC_OFF:
-        SetImage(gfx::CreateVectorIcon(kSyncPausedCircleIcon, kBadgeIconSize,
-                                       gfx::kGoogleGrey600));
+        SetImage(ui::ImageModel::FromVectorIcon(
+            kSyncPausedCircleIcon, ui::kColorIcon, kBadgeIconSize));
         break;
       case BadgedProfilePhoto::BADGE_TYPE_NONE:
         NOTREACHED();
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.cc b/chrome/browser/ui/views/profiles/profile_menu_view.cc
index f2178c7b..9110cb3 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view.cc
@@ -187,21 +187,17 @@
     // This is done regardless of GetAvatarSyncErrorType() because the icon
     // should reflect that sync-the-feature is off. The error will still be
     // highlighted by other parts of the UI.
-    return ColoredImageForMenu(kSyncPausedCircleIcon, gfx::kGoogleGrey500);
+    return ColoredImageForMenu(kSyncPausedCircleIcon, ui::kColorIcon);
   }
 
   absl::optional<AvatarSyncErrorType> error = GetAvatarSyncErrorType(profile);
-  const auto* color_provider = GetColorProvider();
-  if (!error) {
-    return ColoredImageForMenu(
-        kSyncCircleIcon, color_provider->GetColor(ui::kColorAlertLowSeverity));
-  }
+  if (!error)
+    return ColoredImageForMenu(kSyncCircleIcon, ui::kColorAlertLowSeverity);
 
   ui::ColorId color_id = error == AvatarSyncErrorType::kAuthError
                              ? ui::kColorButtonBackgroundProminent
                              : ui::kColorAlertHighSeverity;
-  return ColoredImageForMenu(kSyncPausedCircleIcon,
-                             color_provider->GetColor(color_id));
+  return ColoredImageForMenu(kSyncPausedCircleIcon, color_id);
 }
 
 std::u16string ProfileMenuView::GetAccessibleWindowTitle() const {
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
index 25d4974e..39ad60b0 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
@@ -903,8 +903,9 @@
 
 gfx::ImageSkia ProfileMenuViewBase::ColoredImageForMenu(
     const gfx::VectorIcon& icon,
-    SkColor color) const {
-  return gfx::CreateVectorIcon(icon, kMaxImageSize, color);
+    ui::ColorId color) const {
+  return gfx::CreateVectorIcon(icon, kMaxImageSize,
+                               GetColorProvider()->GetColor(color));
 }
 
 void ProfileMenuViewBase::RecordClick(ActionableItem item) {
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.h b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
index e621345a..745238a 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_base.h
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
@@ -152,7 +152,7 @@
                                          base::RepeatingClosure action);
 
   gfx::ImageSkia ColoredImageForMenu(const gfx::VectorIcon& icon,
-                                     SkColor color) const;
+                                     ui::ColorId color) const;
   // Should be called inside each button/link action.
   void RecordClick(ActionableItem item);
 
diff --git a/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.cc b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.cc
index 1637a272..8e2d09ed 100644
--- a/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.cc
+++ b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.cc
@@ -33,15 +33,6 @@
 // with arrow keys possible.
 constexpr int kActionButtonGroup = 0;
 
-views::Separator* GetSeparator() {
-  auto* separator = new views::Separator();
-  separator->SetColor(gfx::kGoogleGrey300);
-  const int kIndent = 16;
-  const int kPadding = 8;
-  constexpr auto kSeperatorBorder = gfx::Insets(kPadding, kIndent, 0, kIndent);
-  separator->SetBorder(views::CreateEmptyBorder(kSeperatorBorder));
-  return separator;
-}
 }  // namespace
 
 SharingHubBubbleViewImpl::SharingHubBubbleViewImpl(
@@ -149,12 +140,16 @@
     view->SetGroup(kActionButtonGroup);
   }
 
-  action_list_view->AddChildView(GetSeparator());
+  auto* separator =
+      action_list_view->AddChildView(std::make_unique<views::Separator>());
+  constexpr int kIndent = 16;
+  constexpr int kPadding = 8;
+  separator->SetBorder(
+      views::CreateEmptyBorder(gfx::Insets(kPadding, kIndent, 0, kIndent)));
 
-  const int kLabelLineHeight = 22;
-  const int kLabelLinePaddingTop = 8;
-  const int kLabelLinePaddingBottom = 4;
-  const int kIndent = 16;
+  constexpr int kLabelLineHeight = 22;
+  constexpr int kLabelLinePaddingTop = 8;
+  constexpr int kLabelLinePaddingBottom = 4;
 
   auto* share_link_label =
       new views::Label(l10n_util::GetStringUTF16(IDS_SHARING_HUB_SHARE_LABEL));
diff --git a/chrome/browser/ui/views/tabs/tab_strip_scroll_container.cc b/chrome/browser/ui/views/tabs/tab_strip_scroll_container.cc
index f663cbb..aa54057 100644
--- a/chrome/browser/ui/views/tabs/tab_strip_scroll_container.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip_scroll_container.cc
@@ -7,6 +7,7 @@
 #include "base/memory/raw_ptr.h"
 #include "cc/paint/paint_shader.h"
 #include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/ui/color/chrome_color_id.h"
 #include "chrome/browser/ui/views/tabs/tab_strip.h"
 #include "chrome/browser/ui/views/tabs/tab_strip_controller.h"
 #include "chrome/grit/generated_resources.h"
@@ -90,10 +91,9 @@
   // views::View overrides:
   void OnPaint(gfx::Canvas* canvas) override {
     // TODO(tbergquist): Handle themes with titlebar background images.
-    // TODO(tbergquist): Handle dark themes where GG800 doesn't contrast well.
     SkColor frame_color = tab_strip_->controller()->GetFrameColor(
         BrowserFrameActiveState::kUseCurrent);
-    SkColor shadow_color = gfx::kGoogleGrey800;
+    SkColor shadow_color = GetColorProvider()->GetColor(ui::kColorShadowBase);
 
     // Mirror how the indicator is painted for the right vs left sides.
     SkPoint points[2];
@@ -114,8 +114,8 @@
     color_positions[1] = static_cast<float>(kOpaqueWidth) / kTotalWidth;
 
     // Paint a shadow-like gradient on the inside.
-    colors[2] = SkColorSetA(shadow_color, 0x4D);
-    colors[3] = SkColorSetA(shadow_color, 0x4D);
+    colors[2] = shadow_color;
+    colors[3] = shadow_color;
     colors[4] = SkColorSetA(shadow_color, SK_AlphaTRANSPARENT);
     color_positions[2] = static_cast<float>(kOpaqueWidth) / kTotalWidth;
     color_positions[3] =
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc
index 0090aff..5d26859 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc
@@ -75,14 +75,48 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_32SiteA_12SiteA_37SiteA_20) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_39SiteB_16_27_14) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.NavigatePwaSiteATo("SiteB");
+  helper_.CheckCustomToolbar();
+  helper_.CloseCustomToolbar();
+  helper_.CheckAppNavigationIsStartUrl();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_39SiteB_16_71_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.NavigatePwaSiteATo("SiteB");
+  helper_.CheckCustomToolbar();
+  helper_.OpenInChrome();
+  helper_.CheckTabCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_37SiteA_20) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.NavigateBrowser("SiteA");
   helper_.CheckLaunchIconShown();
@@ -90,14 +124,50 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_32SiteA_12SiteA_34SiteA_24) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_69SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_35SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_34SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
   helper_.CheckWindowCreated();
@@ -105,42 +175,49 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_32SiteA_12SiteA_44SiteA_12SiteA) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_33SiteA_44SiteA_12SiteA) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_33SiteA_7SiteA_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppWindowedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_48SiteA_12SiteA_37SiteA_20) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_37SiteA_20) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.NavigateBrowser("SiteA");
@@ -149,13 +226,46 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_48SiteA_12SiteA_34SiteA_24) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_69SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppTabbedShortcut("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_35SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppTabbedShortcut("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_34SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
@@ -164,27 +274,31 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_48SiteA_12SiteA_44SiteA_12SiteA) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_30SiteA_24_12SiteA_37SiteA_17_20) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_37SiteA_17_20) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.NavigateBrowser("SiteA");
   helper_.CheckInstallIconNotShown();
   helper_.CheckLaunchIconShown();
@@ -192,27 +306,146 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_28_36SiteA_34SiteA_25) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_28_70SiteA_69SiteA_94_24_25) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.ClosePwa();
+  helper_.ManifestUpdateDisplayBrowser("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckTabNotCreated();
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_28_70SiteA_35SiteA_94_24_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.ClosePwa();
+  helper_.ManifestUpdateDisplayBrowser("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckTabNotCreated();
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_28_70SiteA_34SiteA_94_24_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.ClosePwa();
+  helper_.ManifestUpdateDisplayBrowser("SiteA");
+  helper_.LaunchFromChromeApps("SiteA");
+  helper_.CheckTabNotCreated();
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_28_36SiteA_69SiteA_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.ClosePwa();
+  helper_.ManifestUpdateDisplayMinimal("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_28_36SiteA_35SiteA_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.ClosePwa();
+  helper_.ManifestUpdateDisplayMinimal("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_28_36SiteA_34SiteA_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.ClosePwa();
   helper_.ManifestUpdateDisplayMinimal("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
   helper_.CheckWindowDisplayMinimal();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_30SiteA_24_12SiteA_34SiteA_24_26) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_69SiteA_24_26) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayStandalone();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_35SiteA_24_26) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayStandalone();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_34SiteA_24_26) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckWindowDisplayStandalone();
@@ -220,13 +453,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_50SiteA_11SiteA_34SiteA_22) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_50SiteA_11SiteA_34SiteA_22) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SetOpenInTab("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
@@ -235,69 +469,140 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_50SiteA_11SiteA_37SiteA_18) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_50SiteA_11SiteA_37SiteA_18) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SetOpenInTab("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
   helper_.NavigateBrowser("SiteA");
   helper_.CheckInstallIconShown();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_30SiteA_24_12SiteA_37SiteAFoo_17_20) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_37SiteAFoo_17_20) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.NavigateBrowser("SiteAFoo");
   helper_.CheckInstallIconNotShown();
   helper_.CheckLaunchIconShown();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_30SiteA_24_12SiteA_37SiteB_18_19) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_37SiteB_18_19) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.NavigateBrowser("SiteB");
   helper_.CheckInstallIconShown();
   helper_.CheckLaunchIconNotShown();
 }
 
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_30SiteA_24_12SiteA_7SiteA_71_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.OpenInChrome();
+  helper_.CheckTabCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_10SiteA_15SiteA_37SiteA_18_19) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.UninstallFromList("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconShown();
+  helper_.CheckLaunchIconNotShown();
+}
+
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_49SiteA_44SiteA_12SiteA) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_49SiteA_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppWindowedShortcut("SiteA");
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_32SiteA_12SiteA_37SiteA_20) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_39SiteB_16_27_14) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.NavigatePwaSiteATo("SiteB");
+  helper_.CheckCustomToolbar();
+  helper_.CloseCustomToolbar();
+  helper_.CheckAppNavigationIsStartUrl();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_39SiteB_16_71_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.NavigatePwaSiteATo("SiteB");
+  helper_.CheckCustomToolbar();
+  helper_.OpenInChrome();
+  helper_.CheckTabCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_37SiteA_20) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.NavigateBrowser("SiteA");
   helper_.CheckLaunchIconShown();
@@ -305,14 +610,50 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_32SiteA_12SiteA_34SiteA_24) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_69SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_35SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_34SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
   helper_.CheckWindowCreated();
@@ -320,42 +661,49 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_32SiteA_12SiteA_44SiteA_12SiteA) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_33SiteA_44SiteA_12SiteA) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_33SiteA_7SiteA_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppWindowedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_48SiteA_12SiteA_37SiteA_20) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_37SiteA_20) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.NavigateBrowser("SiteA");
@@ -364,13 +712,46 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_48SiteA_12SiteA_34SiteA_24) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_69SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppTabbedShortcut("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_35SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppTabbedShortcut("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_34SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
@@ -379,27 +760,31 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_48SiteA_12SiteA_44SiteA_12SiteA) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_31SiteA_24_12SiteA_37SiteA_17_20) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_37SiteA_17_20) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.NavigateBrowser("SiteA");
   helper_.CheckInstallIconNotShown();
   helper_.CheckLaunchIconShown();
@@ -407,27 +792,146 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_28_36SiteA_34SiteA_25) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_28_70SiteA_69SiteA_94_24_25) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.ClosePwa();
+  helper_.ManifestUpdateDisplayBrowser("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckTabNotCreated();
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_28_70SiteA_35SiteA_94_24_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.ClosePwa();
+  helper_.ManifestUpdateDisplayBrowser("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckTabNotCreated();
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_28_70SiteA_34SiteA_94_24_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.ClosePwa();
+  helper_.ManifestUpdateDisplayBrowser("SiteA");
+  helper_.LaunchFromChromeApps("SiteA");
+  helper_.CheckTabNotCreated();
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_28_36SiteA_69SiteA_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.ClosePwa();
+  helper_.ManifestUpdateDisplayMinimal("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_28_36SiteA_35SiteA_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.ClosePwa();
+  helper_.ManifestUpdateDisplayMinimal("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_28_36SiteA_34SiteA_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.ClosePwa();
   helper_.ManifestUpdateDisplayMinimal("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
   helper_.CheckWindowDisplayMinimal();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_31SiteA_24_12SiteA_34SiteA_24_26) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_69SiteA_24_26) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayStandalone();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_35SiteA_24_26) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayStandalone();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_34SiteA_24_26) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckWindowDisplayStandalone();
@@ -435,13 +939,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_50SiteA_11SiteA_34SiteA_22) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_50SiteA_11SiteA_34SiteA_22) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SetOpenInTab("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
@@ -450,69 +955,140 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_50SiteA_11SiteA_37SiteA_18) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_50SiteA_11SiteA_37SiteA_18) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SetOpenInTab("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
   helper_.NavigateBrowser("SiteA");
   helper_.CheckInstallIconShown();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_31SiteA_24_12SiteA_37SiteAFoo_17_20) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_37SiteAFoo_17_20) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.NavigateBrowser("SiteAFoo");
   helper_.CheckInstallIconNotShown();
   helper_.CheckLaunchIconShown();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_31SiteA_24_12SiteA_37SiteB_18_19) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_37SiteB_18_19) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.NavigateBrowser("SiteB");
   helper_.CheckInstallIconShown();
   helper_.CheckLaunchIconNotShown();
 }
 
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_31SiteA_24_12SiteA_7SiteA_71_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.OpenInChrome();
+  helper_.CheckTabCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_10SiteA_15SiteA_37SiteA_18_19) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.UninstallFromList("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconShown();
+  helper_.CheckLaunchIconNotShown();
+}
+
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_49SiteA_44SiteA_12SiteA) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_49SiteA_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppWindowedShortcut("SiteA");
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_32SiteA_12SiteA_37SiteA_20) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_39SiteB_16_27_14) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.NavigatePwaSiteATo("SiteB");
+  helper_.CheckCustomToolbar();
+  helper_.CloseCustomToolbar();
+  helper_.CheckAppNavigationIsStartUrl();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_39SiteB_16_71_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.NavigatePwaSiteATo("SiteB");
+  helper_.CheckCustomToolbar();
+  helper_.OpenInChrome();
+  helper_.CheckTabCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_37SiteA_20) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.NavigateBrowser("SiteA");
   helper_.CheckLaunchIconShown();
@@ -520,14 +1096,50 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_32SiteA_12SiteA_34SiteA_24) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_69SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_35SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_34SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
   helper_.CheckWindowCreated();
@@ -535,42 +1147,49 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_32SiteA_12SiteA_44SiteA_12SiteA) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_33SiteA_44SiteA_12SiteA) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_33SiteA_7SiteA_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppWindowedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_48SiteA_12SiteA_37SiteA_20) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_37SiteA_20) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.NavigateBrowser("SiteA");
@@ -579,13 +1198,46 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_48SiteA_12SiteA_34SiteA_24) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_69SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppTabbedShortcut("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_35SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppTabbedShortcut("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_34SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
@@ -594,27 +1246,31 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_48SiteA_12SiteA_44SiteA_12SiteA) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_47SiteA_24_12SiteA_37SiteA_17_20) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_37SiteA_17_20) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.NavigateBrowser("SiteA");
   helper_.CheckInstallIconNotShown();
   helper_.CheckLaunchIconShown();
@@ -622,27 +1278,146 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_28_36SiteA_34SiteA_25) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_28_70SiteA_69SiteA_94_24_25) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.ClosePwa();
+  helper_.ManifestUpdateDisplayBrowser("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckTabNotCreated();
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_28_70SiteA_35SiteA_94_24_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.ClosePwa();
+  helper_.ManifestUpdateDisplayBrowser("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckTabNotCreated();
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_28_70SiteA_34SiteA_94_24_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.ClosePwa();
+  helper_.ManifestUpdateDisplayBrowser("SiteA");
+  helper_.LaunchFromChromeApps("SiteA");
+  helper_.CheckTabNotCreated();
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_28_36SiteA_69SiteA_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.ClosePwa();
+  helper_.ManifestUpdateDisplayMinimal("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_28_36SiteA_35SiteA_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.ClosePwa();
+  helper_.ManifestUpdateDisplayMinimal("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_28_36SiteA_34SiteA_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.ClosePwa();
   helper_.ManifestUpdateDisplayMinimal("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
   helper_.CheckWindowDisplayMinimal();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_47SiteA_24_12SiteA_34SiteA_24_26) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_69SiteA_24_26) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayStandalone();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_35SiteA_24_26) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayStandalone();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_34SiteA_24_26) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckWindowDisplayStandalone();
@@ -650,13 +1425,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_50SiteA_11SiteA_34SiteA_22) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_50SiteA_11SiteA_34SiteA_22) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SetOpenInTab("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
@@ -665,58 +1441,326 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_50SiteA_11SiteA_37SiteA_18) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_50SiteA_11SiteA_37SiteA_18) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SetOpenInTab("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
   helper_.NavigateBrowser("SiteA");
   helper_.CheckInstallIconShown();
 }
 
-// TODO(crbug.com/1279704): Test is consistently failing on Mac and Win7.
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_47SiteA_24_12SiteA_37SiteAFoo_17_20) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_37SiteAFoo_17_20) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.NavigateBrowser("SiteAFoo");
   helper_.CheckInstallIconNotShown();
   helper_.CheckLaunchIconShown();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_47SiteA_24_12SiteA_37SiteB_18_19) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_37SiteB_18_19) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.NavigateBrowser("SiteB");
   helper_.CheckInstallIconShown();
   helper_.CheckLaunchIconNotShown();
 }
 
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_47SiteA_24_12SiteA_7SiteA_71_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.OpenInChrome();
+  helper_.CheckTabCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_10SiteA_15SiteA_37SiteA_18_19) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.UninstallFromList("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconShown();
+  helper_.CheckLaunchIconNotShown();
+}
+
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_49SiteA_44SiteA_12SiteA) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_49SiteA_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppWindowedShortcut("SiteA");
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_33SiteA_7SiteA_11SiteA_37SiteA_18) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppWindowedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconShown();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_33SiteA_7SiteA_11SiteA_34SiteA_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppWindowedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.LaunchFromChromeApps("SiteA");
+  helper_.CheckTabCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_33SiteA_7SiteA_11SiteA_44SiteA_11SiteA_7SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppWindowedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.UninstallPolicyApp("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_49SiteA_7SiteA_11SiteA_37SiteA_18) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppWindowedShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconShown();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_49SiteA_7SiteA_11SiteA_34SiteA_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppWindowedShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.LaunchFromChromeApps("SiteA");
+  helper_.CheckTabCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_49SiteA_7SiteA_11SiteA_44SiteA_11SiteA_7SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppWindowedShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.UninstallPolicyApp("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_29SiteA_11SiteA_7SiteA_37SiteA_18_19) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconShown();
+  helper_.CheckLaunchIconNotShown();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_51SiteA_12SiteA_69SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SetOpenInWindow("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_51SiteA_12SiteA_35SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SetOpenInWindow("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_51SiteA_12SiteA_34SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SetOpenInWindow("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromChromeApps("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_51SiteA_12SiteA_37SiteA_17_20) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SetOpenInWindow("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconNotShown();
+  helper_.CheckLaunchIconShown();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_10SiteA_15SiteA_37SiteA_18_19) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.UninstallFromList("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconShown();
+  helper_.CheckLaunchIconNotShown();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_32SiteA_44SiteA_11SiteA_7SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.UninstallPolicyApp("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_48SiteA_44SiteA_11SiteA_7SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.InstallPolicyAppTabbedShortcut("SiteA");
+  helper_.UninstallPolicyApp("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+}
+
+// TODO(https://crbug.com/1306779) test is flaky
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    DISABLED_WebAppIntegration_33SiteA_12SiteA_39SiteB_27_14) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppWindowedNoShortcut("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.NavigatePwaSiteATo("SiteB");
+  helper_.CloseCustomToolbar();
+  helper_.CheckAppNavigationIsStartUrl();
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
@@ -732,6 +1776,30 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_33SiteA_12SiteA_69SiteA_24_26) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppWindowedNoShortcut("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayStandalone();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_33SiteA_12SiteA_35SiteA_24_26) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppWindowedNoShortcut("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayStandalone();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
                        WebAppIntegration_33SiteA_12SiteA_34SiteA_24_26) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
@@ -778,68 +1846,117 @@
   helper_.CheckAppNotInList("SiteA");
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_49SiteA_12SiteA_37SiteA_17_20) {
+// TODO(https://crbug.com/1306779) test is flaky
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    DISABLED_WebAppIntegration_49SiteA_12SiteA_7SiteA_39SiteB_27_14) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppWindowedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.NavigatePwaSiteATo("SiteB");
+  helper_.CloseCustomToolbar();
+  helper_.CheckAppNavigationIsStartUrl();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_49SiteA_12SiteA_7SiteA_37SiteA_17_20) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppWindowedShortcut("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.NavigateBrowser("SiteA");
   helper_.CheckInstallIconNotShown();
   helper_.CheckLaunchIconShown();
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_49SiteA_12SiteA_34SiteA_24_26) {
+                       WebAppIntegration_49SiteA_12SiteA_7SiteA_69SiteA_24_26) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppWindowedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromChromeApps("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckWindowDisplayStandalone();
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_49SiteA_12SiteA_50SiteA_34SiteA_22) {
+                       WebAppIntegration_49SiteA_12SiteA_7SiteA_35SiteA_24_26) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppWindowedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayStandalone();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_49SiteA_12SiteA_7SiteA_34SiteA_24_26) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppWindowedShortcut("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.LaunchFromChromeApps("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayStandalone();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_49SiteA_12SiteA_7SiteA_50SiteA_34SiteA_22) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppWindowedShortcut("SiteA");
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SetOpenInTab("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
   helper_.CheckTabCreated();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_49SiteA_12SiteA_37SiteAFoo_17_20) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_49SiteA_12SiteA_7SiteA_37SiteAFoo_17_20) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppWindowedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.NavigateBrowser("SiteAFoo");
   helper_.CheckInstallIconNotShown();
   helper_.CheckLaunchIconShown();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_49SiteA_12SiteA_44SiteA_15SiteA) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_49SiteA_12SiteA_7SiteA_44SiteA_15SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppWindowedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppNotInList("SiteA");
 }
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_32SiteA_11SiteA_30SiteA_12SiteA_24_44SiteA_12SiteA) {
+    WebAppIntegration_32SiteA_11SiteA_30SiteA_12SiteA_7SiteA_24_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
@@ -847,14 +1964,16 @@
   helper_.CheckAppInListTabbed("SiteA");
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_32SiteA_11SiteA_31SiteA_12SiteA_24_44SiteA_12SiteA) {
+    WebAppIntegration_32SiteA_11SiteA_31SiteA_12SiteA_7SiteA_24_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
@@ -862,14 +1981,16 @@
   helper_.CheckAppInListTabbed("SiteA");
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_32SiteA_11SiteA_47SiteA_12SiteA_24_44SiteA_12SiteA) {
+    WebAppIntegration_32SiteA_11SiteA_47SiteA_12SiteA_7SiteA_24_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
@@ -877,9 +1998,11 @@
   helper_.CheckAppInListTabbed("SiteA");
   helper_.InstallMenuOption("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
@@ -895,6 +2018,30 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_32SiteA_11SiteA_51SiteA_69SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.SetOpenInWindow("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_32SiteA_11SiteA_51SiteA_35SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.SetOpenInWindow("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
                        WebAppIntegration_32SiteA_11SiteA_51SiteA_34SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
@@ -919,219 +2066,108 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_29SiteA_11SiteA_33SiteA_11SiteA_37SiteA_18) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.InstallPolicyAppWindowedNoShortcut("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconShown();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_29SiteA_11SiteA_33SiteA_11SiteA_34SiteA_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.InstallPolicyAppWindowedNoShortcut("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.LaunchFromChromeApps("SiteA");
-  helper_.CheckTabCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_29SiteA_11SiteA_33SiteA_11SiteA_44SiteA_11SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.InstallPolicyAppWindowedNoShortcut("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.UninstallPolicyApp("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_29SiteA_11SiteA_49SiteA_11SiteA_37SiteA_18) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.InstallPolicyAppWindowedShortcut("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconShown();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_29SiteA_11SiteA_49SiteA_11SiteA_34SiteA_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.InstallPolicyAppWindowedShortcut("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.LaunchFromChromeApps("SiteA");
-  helper_.CheckTabCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_29SiteA_11SiteA_49SiteA_11SiteA_44SiteA_11SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.InstallPolicyAppWindowedShortcut("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.UninstallPolicyApp("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_29SiteA_11SiteA_37SiteA_18_19) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconShown();
-  helper_.CheckLaunchIconNotShown();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_29SiteA_11SiteA_51SiteA_12SiteA_34SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.SetOpenInWindow("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromChromeApps("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_29SiteA_11SiteA_51SiteA_12SiteA_37SiteA_17_20) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.SetOpenInWindow("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconNotShown();
-  helper_.CheckLaunchIconShown();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_29SiteA_11SiteA_32SiteA_44SiteA_11SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
-  helper_.UninstallPolicyApp("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_29SiteA_11SiteA_48SiteA_44SiteA_11SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.InstallPolicyAppTabbedShortcut("SiteA");
-  helper_.UninstallPolicyApp("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_48SiteA_11SiteA_30SiteA_12SiteA_24_44SiteA_12SiteA) {
+    WebAppIntegration_48SiteA_11SiteA_7SiteA_30SiteA_12SiteA_7SiteA_24_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_48SiteA_11SiteA_31SiteA_12SiteA_24_44SiteA_12SiteA) {
+    WebAppIntegration_48SiteA_11SiteA_7SiteA_31SiteA_12SiteA_7SiteA_24_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_48SiteA_11SiteA_47SiteA_12SiteA_24_44SiteA_12SiteA) {
+    WebAppIntegration_48SiteA_11SiteA_7SiteA_47SiteA_12SiteA_7SiteA_24_44SiteA_12SiteA_7SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallMenuOption("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_48SiteA_11SiteA_37SiteA_18_19) {
+                       WebAppIntegration_48SiteA_11SiteA_7SiteA_37SiteA_18_19) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.NavigateBrowser("SiteA");
   helper_.CheckInstallIconShown();
   helper_.CheckLaunchIconNotShown();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_48SiteA_11SiteA_51SiteA_34SiteA_24) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_48SiteA_11SiteA_7SiteA_51SiteA_69SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SetOpenInWindow("SiteA");
+  helper_.LaunchFromMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_48SiteA_11SiteA_7SiteA_51SiteA_35SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppTabbedShortcut("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.SetOpenInWindow("SiteA");
+  helper_.LaunchFromLaunchIcon("SiteA");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_48SiteA_11SiteA_7SiteA_51SiteA_34SiteA_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppTabbedShortcut("SiteA");
+  helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SetOpenInWindow("SiteA");
   helper_.LaunchFromChromeApps("SiteA");
   helper_.CheckWindowCreated();
@@ -1139,12 +2175,13 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTest,
-    WebAppIntegration_48SiteA_11SiteA_44SiteA_15SiteA_37SiteA_18_19) {
+    WebAppIntegration_48SiteA_11SiteA_7SiteA_44SiteA_15SiteA_37SiteA_18_19) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.UninstallPolicyApp("SiteA");
   helper_.CheckAppNotInList("SiteA");
   helper_.NavigateBrowser("SiteA");
@@ -1153,51 +2190,105 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_30SiteC_12SiteC_37SiteC_17_20) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteC");
-  helper_.CheckAppInListWindowed("SiteC");
-  helper_.NavigateBrowser("SiteC");
-  helper_.CheckInstallIconNotShown();
-  helper_.CheckLaunchIconShown();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_30SiteC_12SiteC_34SiteC_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteC");
-  helper_.CheckAppInListWindowed("SiteC");
-  helper_.LaunchFromChromeApps("SiteC");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_29SiteC_11SiteC_37SiteC_17_19) {
+                       WebAppIntegration_29SiteC_11SiteC_7SiteC_37SiteC_17_19) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutTabbed("SiteC");
   helper_.CheckAppInListTabbed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
   helper_.NavigateBrowser("SiteC");
   helper_.CheckInstallIconNotShown();
   helper_.CheckLaunchIconNotShown();
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_29SiteC_11SiteC_34SiteC_22) {
+                       WebAppIntegration_29SiteC_11SiteC_7SiteC_34SiteC_22) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutTabbed("SiteC");
   helper_.CheckAppInListTabbed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
   helper_.LaunchFromChromeApps("SiteC");
   helper_.CheckTabCreated();
 }
 
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_29SiteC_11SiteC_7SiteC_10SiteC_15SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutTabbed("SiteC");
+  helper_.CheckAppInListTabbed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
+  helper_.UninstallFromList("SiteC");
+  helper_.CheckAppNotInList("SiteA");
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_30SiteC_12SiteC_7SiteC_37SiteC_17_20) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteC");
+  helper_.CheckAppInListWindowed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
+  helper_.NavigateBrowser("SiteC");
+  helper_.CheckInstallIconNotShown();
+  helper_.CheckLaunchIconShown();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_30SiteC_12SiteC_7SiteC_69SiteC_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteC");
+  helper_.CheckAppInListWindowed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
+  helper_.LaunchFromMenuOption("SiteC");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_30SiteC_12SiteC_7SiteC_35SiteC_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteC");
+  helper_.CheckAppInListWindowed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
+  helper_.LaunchFromLaunchIcon("SiteC");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_30SiteC_12SiteC_7SiteC_34SiteC_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteC");
+  helper_.CheckAppInListWindowed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
+  helper_.LaunchFromChromeApps("SiteC");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTest,
+    WebAppIntegration_30SiteC_12SiteC_7SiteC_10SiteC_15SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteC");
+  helper_.CheckAppInListWindowed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
+  helper_.UninstallFromList("SiteC");
+  helper_.CheckAppNotInList("SiteA");
+}
+
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
                        WebAppIntegration_33SiteC_12SiteC_37SiteC_17_20) {
   // Test contents are generated by script. Please do not modify!
@@ -1211,6 +2302,28 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_33SiteC_12SiteC_69SiteC_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppWindowedNoShortcut("SiteC");
+  helper_.CheckAppInListWindowed("SiteC");
+  helper_.LaunchFromMenuOption("SiteC");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_33SiteC_12SiteC_35SiteC_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppWindowedNoShortcut("SiteC");
+  helper_.CheckAppInListWindowed("SiteC");
+  helper_.LaunchFromLaunchIcon("SiteC");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
                        WebAppIntegration_33SiteC_12SiteC_34SiteC_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
@@ -1245,24 +2358,26 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_48SiteC_11SiteC_37SiteC_17_19) {
+                       WebAppIntegration_48SiteC_11SiteC_7SiteC_37SiteC_17_19) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppTabbedShortcut("SiteC");
   helper_.CheckAppInListTabbed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
   helper_.NavigateBrowser("SiteC");
   helper_.CheckInstallIconNotShown();
   helper_.CheckLaunchIconNotShown();
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_48SiteC_11SiteC_34SiteC_22) {
+                       WebAppIntegration_48SiteC_11SiteC_7SiteC_34SiteC_22) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppTabbedShortcut("SiteC");
   helper_.CheckAppInListTabbed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
   helper_.LaunchFromChromeApps("SiteC");
   helper_.CheckTabCreated();
 }
@@ -1278,6 +2393,26 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_30SiteB_69SiteB_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteB");
+  helper_.LaunchFromMenuOption("SiteB");
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_30SiteB_35SiteB_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteB");
+  helper_.LaunchFromLaunchIcon("SiteB");
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
                        WebAppIntegration_30SiteB_34SiteB_25) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
@@ -1298,6 +2433,26 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_31SiteB_69SiteB_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteB");
+  helper_.LaunchFromMenuOption("SiteB");
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_31SiteB_35SiteB_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteB");
+  helper_.LaunchFromLaunchIcon("SiteB");
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
                        WebAppIntegration_31SiteB_34SiteB_25) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
@@ -1318,6 +2473,26 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_33SiteB_69SiteB_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppWindowedNoShortcut("SiteB");
+  helper_.LaunchFromMenuOption("SiteB");
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_33SiteB_35SiteB_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppWindowedNoShortcut("SiteB");
+  helper_.LaunchFromLaunchIcon("SiteB");
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
                        WebAppIntegration_33SiteB_34SiteB_25) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
@@ -1338,6 +2513,26 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_49SiteB_69SiteB_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppWindowedShortcut("SiteB");
+  helper_.LaunchFromMenuOption("SiteB");
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_49SiteB_35SiteB_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppWindowedShortcut("SiteB");
+  helper_.LaunchFromLaunchIcon("SiteB");
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
                        WebAppIntegration_49SiteB_34SiteB_25) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
@@ -1358,6 +2553,26 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_47SiteB_69SiteB_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteB");
+  helper_.LaunchFromMenuOption("SiteB");
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_47SiteB_35SiteB_25) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteB");
+  helper_.LaunchFromLaunchIcon("SiteB");
+  helper_.CheckWindowDisplayMinimal();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
                        WebAppIntegration_47SiteB_34SiteB_25) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
@@ -1368,24 +2583,50 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_49SiteC_12SiteC_37SiteC_17_20) {
+                       WebAppIntegration_49SiteC_12SiteC_7SiteC_37SiteC_17_20) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppWindowedShortcut("SiteC");
   helper_.CheckAppInListWindowed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
   helper_.NavigateBrowser("SiteC");
   helper_.CheckInstallIconNotShown();
   helper_.CheckLaunchIconShown();
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_49SiteC_12SiteC_34SiteC_24) {
+                       WebAppIntegration_49SiteC_12SiteC_7SiteC_69SiteC_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppWindowedShortcut("SiteC");
   helper_.CheckAppInListWindowed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
+  helper_.LaunchFromMenuOption("SiteC");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_49SiteC_12SiteC_7SiteC_35SiteC_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppWindowedShortcut("SiteC");
+  helper_.CheckAppInListWindowed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
+  helper_.LaunchFromLaunchIcon("SiteC");
+  helper_.CheckWindowCreated();
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_49SiteC_12SiteC_7SiteC_34SiteC_24) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyAppWindowedShortcut("SiteC");
+  helper_.CheckAppInListWindowed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
   helper_.LaunchFromChromeApps("SiteC");
   helper_.CheckWindowCreated();
 }
@@ -1451,6 +2692,15 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
+                       WebAppIntegration_37SiteA_15SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
                        WebAppIntegration_33SiteAFoo_37SiteABar_18_19) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
@@ -1482,15 +2732,6 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_37SiteA_15SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
                        WebAppIntegration_37SiteC_15SiteA_17) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
@@ -1500,326 +2741,6 @@
   helper_.CheckInstallIconNotShown();
 }
 
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_32SiteA_12SiteA_35SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_48SiteA_12SiteA_35SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.InstallPolicyAppTabbedShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_28_36SiteA_35SiteA_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.ClosePwa();
-  helper_.ManifestUpdateDisplayMinimal("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckWindowDisplayMinimal();
-}
-
-// TODO(crbug.com/1279704): Test is consistently failing on Mac and Win7.
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_30SiteA_24_12SiteA_35SiteA_24_26) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayStandalone();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_32SiteA_12SiteA_35SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_48SiteA_12SiteA_35SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.InstallPolicyAppTabbedShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_28_36SiteA_35SiteA_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.ClosePwa();
-  helper_.ManifestUpdateDisplayMinimal("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_31SiteA_24_12SiteA_35SiteA_24_26) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayStandalone();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_32SiteA_12SiteA_35SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_48SiteA_12SiteA_35SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.InstallPolicyAppTabbedShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_28_36SiteA_35SiteA_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.ClosePwa();
-  helper_.ManifestUpdateDisplayMinimal("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_47SiteA_24_12SiteA_35SiteA_24_26) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayStandalone();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_33SiteA_12SiteA_35SiteA_24_26) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppWindowedNoShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayStandalone();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_49SiteA_12SiteA_35SiteA_24_26) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppWindowedShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayStandalone();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_32SiteA_11SiteA_51SiteA_35SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.SetOpenInWindow("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_29SiteA_11SiteA_51SiteA_12SiteA_35SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.SetOpenInWindow("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_48SiteA_11SiteA_51SiteA_35SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppTabbedShortcut("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.SetOpenInWindow("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_30SiteC_12SiteC_35SiteC_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteC");
-  helper_.CheckAppInListWindowed("SiteC");
-  helper_.LaunchFromLaunchIcon("SiteC");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_33SiteC_12SiteC_35SiteC_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppWindowedNoShortcut("SiteC");
-  helper_.CheckAppInListWindowed("SiteC");
-  helper_.LaunchFromLaunchIcon("SiteC");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_30SiteB_35SiteB_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteB");
-  helper_.LaunchFromLaunchIcon("SiteB");
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_31SiteB_35SiteB_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteB");
-  helper_.LaunchFromLaunchIcon("SiteB");
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_33SiteB_35SiteB_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppWindowedNoShortcut("SiteB");
-  helper_.LaunchFromLaunchIcon("SiteB");
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_49SiteB_35SiteB_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppWindowedShortcut("SiteB");
-  helper_.LaunchFromLaunchIcon("SiteB");
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_47SiteB_35SiteB_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteB");
-  helper_.LaunchFromLaunchIcon("SiteB");
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_49SiteC_12SiteC_35SiteC_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppWindowedShortcut("SiteC");
-  helper_.CheckAppInListWindowed("SiteC");
-  helper_.LaunchFromLaunchIcon("SiteC");
-  helper_.CheckWindowCreated();
-}
-
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest, WebAppIntegration_38_17) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
@@ -1828,708 +2749,4 @@
   helper_.CheckInstallIconNotShown();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_30SiteA_24_12SiteA_39SiteB_16_27_14) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.NavigatePwaSiteATo("SiteB");
-  helper_.CheckCustomToolbar();
-  helper_.CloseCustomToolbar();
-  helper_.CheckAppNavigationIsStartUrl();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_31SiteA_24_12SiteA_39SiteB_16_27_14) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.NavigatePwaSiteATo("SiteB");
-  helper_.CheckCustomToolbar();
-  helper_.CloseCustomToolbar();
-  helper_.CheckAppNavigationIsStartUrl();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_47SiteA_24_12SiteA_39SiteB_16_27_14) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.NavigatePwaSiteATo("SiteB");
-  helper_.CheckCustomToolbar();
-  helper_.CloseCustomToolbar();
-  helper_.CheckAppNavigationIsStartUrl();
-}
-
-// TODO(https://crbug.com/1306779) test is flaky
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    DISABLED_WebAppIntegration_33SiteA_12SiteA_39SiteB_27_14) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppWindowedNoShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.NavigatePwaSiteATo("SiteB");
-  helper_.CloseCustomToolbar();
-  helper_.CheckAppNavigationIsStartUrl();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    DISABLED_WebAppIntegration_49SiteA_12SiteA_39SiteB_27_14) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppWindowedShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.NavigatePwaSiteATo("SiteB");
-  helper_.CloseCustomToolbar();
-  helper_.CheckAppNavigationIsStartUrl();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_10SiteA_15SiteA_37SiteA_18_19) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.UninstallFromList("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconShown();
-  helper_.CheckLaunchIconNotShown();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_10SiteA_15SiteA_37SiteA_18_19) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.UninstallFromList("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconShown();
-  helper_.CheckLaunchIconNotShown();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_10SiteA_15SiteA_37SiteA_18_19) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.UninstallFromList("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconShown();
-  helper_.CheckLaunchIconNotShown();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_29SiteA_11SiteA_10SiteA_15SiteA_37SiteA_18_19) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.UninstallFromList("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconShown();
-  helper_.CheckLaunchIconNotShown();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_30SiteC_12SiteC_10SiteC_15SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteC");
-  helper_.CheckAppInListWindowed("SiteC");
-  helper_.UninstallFromList("SiteC");
-  helper_.CheckAppNotInList("SiteA");
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_29SiteC_11SiteC_10SiteC_15SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteC");
-  helper_.CheckAppInListTabbed("SiteC");
-  helper_.UninstallFromList("SiteC");
-  helper_.CheckAppNotInList("SiteA");
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_28_70SiteA_35SiteA_94_24_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.ClosePwa();
-  helper_.ManifestUpdateDisplayBrowser("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckTabNotCreated();
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_28_70SiteA_34SiteA_94_24_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.ClosePwa();
-  helper_.ManifestUpdateDisplayBrowser("SiteA");
-  helper_.LaunchFromChromeApps("SiteA");
-  helper_.CheckTabNotCreated();
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_28_70SiteA_35SiteA_94_24_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.ClosePwa();
-  helper_.ManifestUpdateDisplayBrowser("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckTabNotCreated();
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_28_70SiteA_34SiteA_94_24_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.ClosePwa();
-  helper_.ManifestUpdateDisplayBrowser("SiteA");
-  helper_.LaunchFromChromeApps("SiteA");
-  helper_.CheckTabNotCreated();
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_28_70SiteA_35SiteA_94_24_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.ClosePwa();
-  helper_.ManifestUpdateDisplayBrowser("SiteA");
-  helper_.LaunchFromLaunchIcon("SiteA");
-  helper_.CheckTabNotCreated();
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_28_70SiteA_34SiteA_94_24_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.ClosePwa();
-  helper_.ManifestUpdateDisplayBrowser("SiteA");
-  helper_.LaunchFromChromeApps("SiteA");
-  helper_.CheckTabNotCreated();
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_30SiteA_24_12SiteA_39SiteB_16_71_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.NavigatePwaSiteATo("SiteB");
-  helper_.CheckCustomToolbar();
-  helper_.OpenInChrome();
-  helper_.CheckTabCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_30SiteA_24_12SiteA_71_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.OpenInChrome();
-  helper_.CheckTabCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_31SiteA_24_12SiteA_39SiteB_16_71_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.NavigatePwaSiteATo("SiteB");
-  helper_.CheckCustomToolbar();
-  helper_.OpenInChrome();
-  helper_.CheckTabCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_31SiteA_24_12SiteA_71_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.OpenInChrome();
-  helper_.CheckTabCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_47SiteA_24_12SiteA_39SiteB_16_71_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.NavigatePwaSiteATo("SiteB");
-  helper_.CheckCustomToolbar();
-  helper_.OpenInChrome();
-  helper_.CheckTabCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_47SiteA_24_12SiteA_71_22) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.OpenInChrome();
-  helper_.CheckTabCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_32SiteA_12SiteA_69SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_48SiteA_12SiteA_69SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.InstallPolicyAppTabbedShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_28_70SiteA_69SiteA_94_24_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.ClosePwa();
-  helper_.ManifestUpdateDisplayBrowser("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckTabNotCreated();
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_30SiteA_24_12SiteA_28_36SiteA_69SiteA_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.ClosePwa();
-  helper_.ManifestUpdateDisplayMinimal("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_30SiteA_24_12SiteA_69SiteA_24_26) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayStandalone();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_32SiteA_12SiteA_69SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_48SiteA_12SiteA_69SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.InstallPolicyAppTabbedShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_28_70SiteA_69SiteA_94_24_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.ClosePwa();
-  helper_.ManifestUpdateDisplayBrowser("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckTabNotCreated();
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_31SiteA_24_12SiteA_28_36SiteA_69SiteA_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.ClosePwa();
-  helper_.ManifestUpdateDisplayMinimal("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_31SiteA_24_12SiteA_69SiteA_24_26) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayStandalone();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_32SiteA_12SiteA_69SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_48SiteA_12SiteA_69SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.InstallPolicyAppTabbedShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_28_70SiteA_69SiteA_94_24_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.ClosePwa();
-  helper_.ManifestUpdateDisplayBrowser("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckTabNotCreated();
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_47SiteA_24_12SiteA_28_36SiteA_69SiteA_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.ClosePwa();
-  helper_.ManifestUpdateDisplayMinimal("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_47SiteA_24_12SiteA_69SiteA_24_26) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayStandalone();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTest,
-    WebAppIntegration_29SiteA_11SiteA_51SiteA_12SiteA_69SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutTabbed("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.SetOpenInWindow("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_33SiteA_12SiteA_69SiteA_24_26) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppWindowedNoShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayStandalone();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_49SiteA_12SiteA_69SiteA_24_26) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppWindowedShortcut("SiteA");
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckWindowDisplayStandalone();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_32SiteA_11SiteA_51SiteA_69SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.SetOpenInWindow("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_48SiteA_11SiteA_51SiteA_69SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppTabbedShortcut("SiteA");
-  helper_.CheckAppInListTabbed("SiteA");
-  helper_.SetOpenInWindow("SiteA");
-  helper_.LaunchFromMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_30SiteC_12SiteC_69SiteC_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteC");
-  helper_.CheckAppInListWindowed("SiteC");
-  helper_.LaunchFromMenuOption("SiteC");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_33SiteC_12SiteC_69SiteC_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppWindowedNoShortcut("SiteC");
-  helper_.CheckAppInListWindowed("SiteC");
-  helper_.LaunchFromMenuOption("SiteC");
-  helper_.CheckWindowCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_30SiteB_69SiteB_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteB");
-  helper_.LaunchFromMenuOption("SiteB");
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_31SiteB_69SiteB_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteB");
-  helper_.LaunchFromMenuOption("SiteB");
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_33SiteB_69SiteB_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppWindowedNoShortcut("SiteB");
-  helper_.LaunchFromMenuOption("SiteB");
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_49SiteB_69SiteB_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppWindowedShortcut("SiteB");
-  helper_.LaunchFromMenuOption("SiteB");
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_47SiteB_69SiteB_25) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteB");
-  helper_.LaunchFromMenuOption("SiteB");
-  helper_.CheckWindowDisplayMinimal();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest,
-                       WebAppIntegration_49SiteC_12SiteC_69SiteC_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyAppWindowedShortcut("SiteC");
-  helper_.CheckAppInListWindowed("SiteC");
-  helper_.LaunchFromMenuOption("SiteC");
-  helper_.CheckWindowCreated();
-}
-
 }  // namespace web_app
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc
index 7b0b481d..8f5b2a2 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc
@@ -153,132 +153,16 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_31SiteA_24_12SiteA_43SiteA_15SiteA_37SiteA_18_19) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.UninstallFromMenu("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconShown();
-  helper_.CheckLaunchIconNotShown();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_47SiteA_24_12SiteA_43SiteA_15SiteA_37SiteA_18_19) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.UninstallFromMenu("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconShown();
-  helper_.CheckLaunchIconNotShown();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_30SiteA_24_12SiteA_43SiteA_15SiteA_37SiteA_18_19) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_1SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
-  helper_.UninstallFromMenu("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconShown();
-  helper_.CheckLaunchIconNotShown();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTestMacWinLinux,
-                       WebAppIntegration_30SiteC_12SiteC_43SiteC_15SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteC");
-  helper_.CheckAppInListWindowed("SiteC");
-  helper_.UninstallFromMenu("SiteC");
-  helper_.CheckAppNotInList("SiteA");
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_30SiteA_24_12SiteA_98SiteA_15SiteA_37SiteA_18_19) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.UninstallFromAppSettings("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconShown();
-  helper_.CheckLaunchIconNotShown();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_31SiteA_24_12SiteA_98SiteA_15SiteA_37SiteA_18_19) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallOmniboxIcon("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.UninstallFromAppSettings("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconShown();
-  helper_.CheckLaunchIconNotShown();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_47SiteA_24_12SiteA_98SiteA_15SiteA_37SiteA_18_19) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallMenuOption("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
-  helper_.UninstallFromAppSettings("SiteA");
-  helper_.CheckAppNotInList("SiteA");
-  helper_.NavigateBrowser("SiteA");
-  helper_.CheckInstallIconShown();
-  helper_.CheckLaunchIconNotShown();
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTestMacWinLinux,
-                       WebAppIntegration_30SiteC_12SiteC_98SiteC_15SiteA) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteC");
-  helper_.CheckAppInListWindowed("SiteC");
-  helper_.UninstallFromAppSettings("SiteC");
-  helper_.CheckAppNotInList("SiteA");
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_30SiteA_24_12SiteA_32SiteA_12SiteA_1SiteA_24) {
-  // Test contents are generated by script. Please do not modify!
-  // See `chrome/test/webapps/README.md` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallCreateShortcutWindowed("SiteA");
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
   helper_.CheckWindowCreated();
@@ -286,13 +170,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_30SiteA_24_12SiteA_48SiteA_12SiteA_1SiteA_24) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_1SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
@@ -301,13 +186,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_30SiteA_24_12SiteA_28_70SiteA_1SiteA_94_24_25) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_28_70SiteA_1SiteA_94_24_25) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.ClosePwa();
   helper_.ManifestUpdateDisplayBrowser("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
@@ -318,27 +204,30 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_30SiteA_24_12SiteA_28_36SiteA_1SiteA_25) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_28_36SiteA_1SiteA_25) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.ClosePwa();
   helper_.ManifestUpdateDisplayMinimal("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
   helper_.CheckWindowDisplayMinimal();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTestMacWinLinux,
-                       WebAppIntegration_30SiteA_24_12SiteA_1SiteA_24_26) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTestMacWinLinux,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_1SiteA_24_26) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckWindowDisplayStandalone();
@@ -346,13 +235,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_30SiteA_24_12SiteA_50SiteA_11SiteA_1SiteA_22) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_50SiteA_11SiteA_1SiteA_22) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SetOpenInTab("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
@@ -361,14 +251,50 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_31SiteA_24_12SiteA_32SiteA_12SiteA_1SiteA_24) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_43SiteA_15SiteA_37SiteA_18_19) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.UninstallFromMenu("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconShown();
+  helper_.CheckLaunchIconNotShown();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTestMacWinLinux,
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_98SiteA_15SiteA_37SiteA_18_19) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.UninstallFromAppSettings("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconShown();
+  helper_.CheckLaunchIconNotShown();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTestMacWinLinux,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_1SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
   helper_.CheckWindowCreated();
@@ -376,13 +302,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_31SiteA_24_12SiteA_48SiteA_12SiteA_1SiteA_24) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_1SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
@@ -391,13 +318,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_31SiteA_24_12SiteA_28_70SiteA_1SiteA_94_24_25) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_28_70SiteA_1SiteA_94_24_25) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.ClosePwa();
   helper_.ManifestUpdateDisplayBrowser("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
@@ -408,27 +336,30 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_31SiteA_24_12SiteA_28_36SiteA_1SiteA_25) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_28_36SiteA_1SiteA_25) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.ClosePwa();
   helper_.ManifestUpdateDisplayMinimal("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
   helper_.CheckWindowDisplayMinimal();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTestMacWinLinux,
-                       WebAppIntegration_31SiteA_24_12SiteA_1SiteA_24_26) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTestMacWinLinux,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_1SiteA_24_26) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckWindowDisplayStandalone();
@@ -436,13 +367,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_31SiteA_24_12SiteA_50SiteA_11SiteA_1SiteA_22) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_50SiteA_11SiteA_1SiteA_22) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SetOpenInTab("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
@@ -451,14 +383,50 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_47SiteA_24_12SiteA_32SiteA_12SiteA_1SiteA_24) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_43SiteA_15SiteA_37SiteA_18_19) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.UninstallFromMenu("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconShown();
+  helper_.CheckLaunchIconNotShown();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTestMacWinLinux,
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_98SiteA_15SiteA_37SiteA_18_19) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallOmniboxIcon("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.UninstallFromAppSettings("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconShown();
+  helper_.CheckLaunchIconNotShown();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTestMacWinLinux,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_32SiteA_7SiteA_12SiteA_1SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
   helper_.CheckWindowCreated();
@@ -466,13 +434,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_47SiteA_24_12SiteA_48SiteA_12SiteA_1SiteA_24) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_48SiteA_12SiteA_1SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
@@ -481,13 +450,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_47SiteA_24_12SiteA_28_70SiteA_1SiteA_94_24_25) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_28_70SiteA_1SiteA_94_24_25) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.ClosePwa();
   helper_.ManifestUpdateDisplayBrowser("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
@@ -498,27 +468,30 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_47SiteA_24_12SiteA_28_36SiteA_1SiteA_25) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_28_36SiteA_1SiteA_25) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.ClosePwa();
   helper_.ManifestUpdateDisplayMinimal("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
   helper_.CheckWindowDisplayMinimal();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTestMacWinLinux,
-                       WebAppIntegration_47SiteA_24_12SiteA_1SiteA_24_26) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTestMacWinLinux,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_1SiteA_24_26) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckWindowDisplayStandalone();
@@ -526,13 +499,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_47SiteA_24_12SiteA_50SiteA_11SiteA_1SiteA_22) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_50SiteA_11SiteA_1SiteA_22) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SetOpenInTab("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
@@ -541,13 +515,49 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_29SiteA_11SiteA_33SiteA_11SiteA_1SiteA_22) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_43SiteA_15SiteA_37SiteA_18_19) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.UninstallFromMenu("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconShown();
+  helper_.CheckLaunchIconNotShown();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTestMacWinLinux,
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_98SiteA_15SiteA_37SiteA_18_19) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallMenuOption("SiteA");
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
+  helper_.UninstallFromAppSettings("SiteA");
+  helper_.CheckAppNotInList("SiteA");
+  helper_.NavigateBrowser("SiteA");
+  helper_.CheckInstallIconShown();
+  helper_.CheckLaunchIconNotShown();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTestMacWinLinux,
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_33SiteA_7SiteA_11SiteA_1SiteA_22) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutTabbed("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppWindowedNoShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
   helper_.CheckTabCreated();
@@ -555,13 +565,15 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_29SiteA_11SiteA_49SiteA_11SiteA_1SiteA_22) {
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_49SiteA_7SiteA_11SiteA_1SiteA_22) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutTabbed("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.InstallPolicyAppWindowedShortcut("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
   helper_.CheckTabCreated();
@@ -569,12 +581,13 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestMacWinLinux,
-    WebAppIntegration_29SiteA_11SiteA_51SiteA_12SiteA_1SiteA_24) {
+    WebAppIntegration_29SiteA_11SiteA_7SiteA_51SiteA_12SiteA_1SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutTabbed("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SetOpenInWindow("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
@@ -606,24 +619,27 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTestMacWinLinux,
-                       WebAppIntegration_49SiteA_12SiteA_1SiteA_24_26) {
+                       WebAppIntegration_49SiteA_12SiteA_7SiteA_1SiteA_24_26) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppWindowedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckWindowDisplayStandalone();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTestMacWinLinux,
-                       WebAppIntegration_49SiteA_12SiteA_50SiteA_1SiteA_22) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTestMacWinLinux,
+    WebAppIntegration_49SiteA_12SiteA_7SiteA_50SiteA_1SiteA_22) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppWindowedShortcut("SiteA");
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SetOpenInTab("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
   helper_.CheckTabCreated();
@@ -641,40 +657,70 @@
   helper_.CheckWindowCreated();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTestMacWinLinux,
-                       WebAppIntegration_48SiteA_11SiteA_51SiteA_1SiteA_24) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTestMacWinLinux,
+    WebAppIntegration_48SiteA_11SiteA_7SiteA_51SiteA_1SiteA_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppTabbedShortcut("SiteA");
   helper_.CheckAppInListTabbed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.SetOpenInWindow("SiteA");
   helper_.LaunchFromPlatformShortcut("SiteA");
   helper_.CheckWindowCreated();
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTestMacWinLinux,
-                       WebAppIntegration_29SiteC_11SiteC_1SiteC_22) {
+                       WebAppIntegration_29SiteC_11SiteC_7SiteC_1SiteC_22) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutTabbed("SiteC");
   helper_.CheckAppInListTabbed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
   helper_.LaunchFromPlatformShortcut("SiteC");
   helper_.CheckTabCreated();
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTestMacWinLinux,
-                       WebAppIntegration_30SiteC_12SiteC_1SiteC_24) {
+                       WebAppIntegration_30SiteC_12SiteC_7SiteC_1SiteC_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteC");
   helper_.CheckAppInListWindowed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
   helper_.LaunchFromPlatformShortcut("SiteC");
   helper_.CheckWindowCreated();
 }
 
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTestMacWinLinux,
+    WebAppIntegration_30SiteC_12SiteC_7SiteC_43SiteC_15SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteC");
+  helper_.CheckAppInListWindowed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
+  helper_.UninstallFromMenu("SiteC");
+  helper_.CheckAppNotInList("SiteA");
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTestMacWinLinux,
+    WebAppIntegration_30SiteC_12SiteC_7SiteC_98SiteC_15SiteA) {
+  // Test contents are generated by script. Please do not modify!
+  // See `chrome/test/webapps/README.md` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallCreateShortcutWindowed("SiteC");
+  helper_.CheckAppInListWindowed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
+  helper_.UninstallFromAppSettings("SiteC");
+  helper_.CheckAppNotInList("SiteA");
+}
+
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTestMacWinLinux,
                        WebAppIntegration_33SiteC_12SiteC_1SiteC_24) {
   // Test contents are generated by script. Please do not modify!
@@ -698,12 +744,13 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTestMacWinLinux,
-                       WebAppIntegration_48SiteC_11SiteC_1SiteC_22) {
+                       WebAppIntegration_48SiteC_11SiteC_7SiteC_1SiteC_22) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppTabbedShortcut("SiteC");
   helper_.CheckAppInListTabbed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
   helper_.LaunchFromPlatformShortcut("SiteC");
   helper_.CheckTabCreated();
 }
@@ -759,12 +806,13 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTestMacWinLinux,
-                       WebAppIntegration_49SiteC_12SiteC_1SiteC_24) {
+                       WebAppIntegration_49SiteC_12SiteC_7SiteC_1SiteC_24) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallPolicyAppWindowedShortcut("SiteC");
   helper_.CheckAppInListWindowed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
   helper_.LaunchFromPlatformShortcut("SiteC");
   helper_.CheckWindowCreated();
 }
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_win.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_win.cc
index 78e21f3..da23d614 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_win.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_win.cc
@@ -23,13 +23,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestWin,
-    WebAppIntegration_30SiteA_24_12SiteA_87SiteA_15SiteA_37SiteA_18_19) {
+    WebAppIntegration_30SiteA_24_12SiteA_7SiteA_87SiteA_15SiteA_37SiteA_18_19) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.UninstallFromOs("SiteA");
   helper_.CheckAppNotInList("SiteA");
   helper_.NavigateBrowser("SiteA");
@@ -39,13 +40,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestWin,
-    WebAppIntegration_31SiteA_24_12SiteA_87SiteA_15SiteA_37SiteA_18_19) {
+    WebAppIntegration_31SiteA_24_12SiteA_7SiteA_87SiteA_15SiteA_37SiteA_18_19) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallOmniboxIcon("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.UninstallFromOs("SiteA");
   helper_.CheckAppNotInList("SiteA");
   helper_.NavigateBrowser("SiteA");
@@ -55,13 +57,14 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegrationBrowserTestWin,
-    WebAppIntegration_47SiteA_24_12SiteA_87SiteA_15SiteA_37SiteA_18_19) {
+    WebAppIntegration_47SiteA_24_12SiteA_7SiteA_87SiteA_15SiteA_37SiteA_18_19) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallMenuOption("SiteA");
   helper_.CheckWindowCreated();
   helper_.CheckAppInListWindowed("SiteA");
+  helper_.CheckPlatformShortcutAndIcon("SiteA");
   helper_.UninstallFromOs("SiteA");
   helper_.CheckAppNotInList("SiteA");
   helper_.NavigateBrowser("SiteA");
@@ -69,13 +72,15 @@
   helper_.CheckLaunchIconNotShown();
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTestWin,
-                       WebAppIntegration_30SiteC_12SiteC_87SiteC_15SiteA) {
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegrationBrowserTestWin,
+    WebAppIntegration_30SiteC_12SiteC_7SiteC_87SiteC_15SiteA) {
   // Test contents are generated by script. Please do not modify!
   // See `chrome/test/webapps/README.md` for more info.
   // Sheriffs: Disabling this test is supported.
   helper_.InstallCreateShortcutWindowed("SiteC");
   helper_.CheckAppInListWindowed("SiteC");
+  helper_.CheckPlatformShortcutAndIcon("SiteC");
   helper_.UninstallFromOs("SiteC");
   helper_.CheckAppNotInList("SiteA");
 }
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
index 6addf9e..518cba9 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -171,6 +171,16 @@
     {"Site A Bar", SkColorSetARGB(0xFF, 0x00, 0xFF, 0x00)},
     {"Site A - Updated name", SkColorSetARGB(0xFF, 0x00, 0xFF, 0x00)}};
 
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
+const base::flat_map<std::string, std::vector<int>> g_app_name_icon_sizes = {
+    {"Site A", {32, 48, 64, 96, 128, 192, 256}},
+    {"Site B", {32, 48, 96, 128, 192, 256}},
+    {"Site C", {64, 96, 128, 256}},
+    {"Site A Foo", {32, 48, 64, 96, 128, 192, 256}},
+    {"Site A Bar", {32, 48, 64, 96, 128, 192, 256}},
+    {"Site A - Updated name", {32, 48, 64, 96, 128, 192, 256}}};
+#endif
+
 #if !BUILDFLAG(IS_CHROMEOS)
 class TestAppLauncherHandler : public AppLauncherHandler {
  public:
@@ -2205,10 +2215,12 @@
       shortcut_override_->desktop.GetPath().Append(shortcut_filename);
   if (base::PathExists(desktop_shortcut_path))
     is_shortcut_and_icon_correct = IconManagerCheckIconTopLeftColor(
-        provider()->icon_manager(), id, {192, 48}, expected_icon_pxiel_color);
+        provider()->icon_manager(), id,
+        g_app_name_icon_sizes.find(name)->second, expected_icon_pxiel_color);
 #elif BUILDFLAG(IS_CHROMEOS)
   is_shortcut_and_icon_correct = IconManagerCheckIconTopLeftColor(
-      provider()->icon_manager(), id, {192, 48}, expected_icon_pxiel_color);
+      provider()->icon_manager(), id, g_app_name_icon_sizes.find(name)->second,
+      expected_icon_pxiel_color);
 #endif
   return is_shortcut_and_icon_correct;
 }
diff --git a/chrome/browser/ui/views/webauthn/hover_list_view.cc b/chrome/browser/ui/views/webauthn/hover_list_view.cc
index 5c36c98..0c7460b0 100644
--- a/chrome/browser/ui/views/webauthn/hover_list_view.cc
+++ b/chrome/browser/ui/views/webauthn/hover_list_view.cc
@@ -144,15 +144,6 @@
       std::move(secondary_view), is_two_line_item, item_type);
 }
 
-views::Separator* AddSeparatorAsChild(views::View* view) {
-  auto separator = std::make_unique<views::Separator>();
-  // TODO(tluk): kGoogleGrey300 is the default light mode separator color so
-  // setting the color below should be unnecessary. Remove the hardcoded color
-  // and this helper as it should not be needed.
-  separator->SetColor(gfx::kGoogleGrey300);
-  return view->AddChildView(std::move(separator));
-}
-
 }  // namespace
 
 // HoverListView ---------------------------------------------------------
@@ -168,7 +159,7 @@
       0 /* betweeen_child_spacing */));
 
   item_container_ = item_container.get();
-  AddSeparatorAsChild(item_container_);
+  item_container_->AddChildView(std::make_unique<views::Separator>());
 
   for (const auto item_tag : model_->GetThrobberTags()) {
     auto button = CreateHoverButtonForListItem(
@@ -179,7 +170,7 @@
         true, ItemType::kThrobber);
     throbber_views_.push_back(button.get());
     item_container_->AddChildView(button.release());
-    AddSeparatorAsChild(item_container_);
+    item_container_->AddChildView(std::make_unique<views::Separator>());
   }
 
   for (const auto item_tag : model_->GetButtonTags()) {
@@ -218,7 +209,8 @@
 
   auto* list_item_view_ptr = hover_button.release();
   item_container_->AddChildView(list_item_view_ptr);
-  auto* separator = AddSeparatorAsChild(item_container_);
+  auto* separator =
+      item_container_->AddChildView(std::make_unique<views::Separator>());
   tags_to_list_item_views_.emplace(
       item_tag, ListItemViews{list_item_view_ptr, separator});
 }
@@ -229,7 +221,8 @@
       std::u16string(), views::Button::PressedCallback(),
       /*is_two_line_item=*/false, ItemType::kPlaceholder);
   item_container_->AddChildView(placeholder_item.get());
-  auto* separator = AddSeparatorAsChild(item_container_);
+  auto* separator =
+      item_container_->AddChildView(std::make_unique<views::Separator>());
   placeholder_list_item_view_.emplace(
       ListItemViews{placeholder_item.release(), separator});
 }
diff --git a/chrome/browser/ui/webauthn/other_mechanisms_menu_model.cc b/chrome/browser/ui/webauthn/other_mechanisms_menu_model.cc
index 2b88695f..42fc471 100644
--- a/chrome/browser/ui/webauthn/other_mechanisms_menu_model.cc
+++ b/chrome/browser/ui/webauthn/other_mechanisms_menu_model.cc
@@ -6,8 +6,7 @@
 
 #include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
 #include "ui/base/models/image_model.h"
-#include "ui/gfx/color_palette.h"
-#include "ui/gfx/paint_vector_icon.h"
+#include "ui/color/color_id.h"
 
 OtherMechanismsMenuModel::OtherMechanismsMenuModel(
     AuthenticatorRequestDialogModel* dialog_model)
@@ -25,10 +24,8 @@
 
     const auto& m = mechanisms[i];
     AddItemWithIcon(static_cast<int>(i), m.short_name,
-                    // TODO (kylixrd): Review the use of the hard-coded color
-                    // for possible change to using a ColorProvider color id.
-                    ui::ImageModel::FromImageSkia(gfx::CreateVectorIcon(
-                        *m.icon, kTransportIconSize, gfx::kGoogleGrey700)));
+                    ui::ImageModel::FromVectorIcon(
+                        *m.icon, ui::kColorMenuIcon, kTransportIconSize));
   }
 }
 
diff --git a/chrome/browser/ui/webui/history/history_ui.cc b/chrome/browser/ui/webui/history/history_ui.cc
index db386729..823c438 100644
--- a/chrome/browser/ui/webui/history/history_ui.cc
+++ b/chrome/browser/ui/webui/history/history_ui.cc
@@ -147,7 +147,6 @@
   static constexpr webui::LocalizedString kHistoryClustersStrings[] = {
       {"disableHistoryClusters", IDS_HISTORY_CLUSTERS_DISABLE_MENU_ITEM_LABEL},
       {"enableHistoryClusters", IDS_HISTORY_CLUSTERS_ENABLE_MENU_ITEM_LABEL},
-      {"headerText", IDS_HISTORY_CLUSTERS_HEADER_TEXT},
       {"historyClustersTabLabel", IDS_HISTORY_CLUSTERS_JOURNEYS_TAB_LABEL},
       {"historyListTabLabel", IDS_HISTORY_CLUSTERS_LIST_TAB_LABEL},
       {"loadMoreButtonLabel", IDS_HISTORY_CLUSTERS_LOAD_MORE_BUTTON_LABEL},
diff --git a/chrome/browser/ui/webui/read_later/side_panel/read_anything/read_anything_constants.h b/chrome/browser/ui/webui/read_later/side_panel/read_anything/read_anything_constants.h
index fd06525..cf1ff48e 100644
--- a/chrome/browser/ui/webui/read_later/side_panel/read_anything/read_anything_constants.h
+++ b/chrome/browser/ui/webui/read_later/side_panel/read_anything/read_anything_constants.h
@@ -5,16 +5,11 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_READ_LATER_SIDE_PANEL_READ_ANYTHING_READ_ANYTHING_CONSTANTS_H_
 #define CHROME_BROWSER_UI_WEBUI_READ_LATER_SIDE_PANEL_READ_ANYTHING_READ_ANYTHING_CONSTANTS_H_
 
-#include "ui/gfx/color_palette.h"
-#include "ui/views/layout/flex_layout.h"
-
 // Various constants used throughout the Read Anything feature.
 namespace {
 
 // Visual constants for Read Anything feature.
 // TODO(1226555): Replace these with final values provided by UI.
-const SkColor kReadAnythingBackgroundColor = SK_ColorWHITE;
-const SkColor kReadAnythingSeperatorColor = gfx::kGoogleGrey700;
 const int kInternalInsets = 6;
 const int kFontSize = 16;
 const int kIconSize = 16;
diff --git a/chrome/browser/ui/webui/read_later/side_panel/read_anything/read_anything_container_view.cc b/chrome/browser/ui/webui/read_later/side_panel/read_anything/read_anything_container_view.cc
index 714930c..7b2c63a 100644
--- a/chrome/browser/ui/webui/read_later/side_panel/read_anything/read_anything_container_view.cc
+++ b/chrome/browser/ui/webui/read_later/side_panel/read_anything/read_anything_container_view.cc
@@ -25,7 +25,8 @@
       .SetInteriorMargin(gfx::Insets(kInternalInsets));
 
   SetLayoutManager(std::move(layout));
-  SetBackground(views::CreateSolidBackground(kReadAnythingBackgroundColor));
+  SetBackground(
+      views::CreateThemedSolidBackground(this, ui::kColorPrimaryBackground));
 
   // Create the toolbar for the side panel.
   auto toolbar = std::make_unique<ReadAnythingToolbarView>();
@@ -37,7 +38,6 @@
 
   // Create a separator.
   auto separator = std::make_unique<views::Separator>();
-  separator->SetColor(kReadAnythingSeperatorColor);
   separator->SetProperty(
       views::kFlexBehaviorKey,
       views::FlexSpecification(views::MinimumFlexSizeRule::kPreferred,
diff --git a/chrome/browser/ui/webui/settings/ash/os_apps_page/app_notification_handler_unittest.cc b/chrome/browser/ui/webui/settings/ash/os_apps_page/app_notification_handler_unittest.cc
index 4a48dce..08d155b28 100644
--- a/chrome/browser/ui/webui/settings/ash/os_apps_page/app_notification_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/ash/os_apps_page/app_notification_handler_unittest.cc
@@ -16,6 +16,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "components/services/app_service/public/cpp/app_types.h"
+#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/cpp/permission.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -120,37 +121,42 @@
     handler_->SetQuietMode(quiet_mode_enabled);
   }
 
-  void CreateAndStoreFakeApp(
-      std::string fake_id,
-      apps::mojom::AppType app_type,
-      apps::mojom::PermissionType permission_type,
-      bool permission_value = true) {
-    std::vector<apps::mojom::PermissionPtr> fake_permissions;
-    apps::mojom::PermissionPtr fake_permission = apps::mojom::Permission::New();
-    fake_permission->permission_type = permission_type;
-    fake_permission->value = apps::mojom::PermissionValue::New();
-    fake_permission->value->set_bool_value(permission_value);
-    fake_permission->is_managed = false;
+  void CreateAndStoreFakeApp(std::string fake_id,
+                             apps::AppType app_type,
+                             apps::PermissionType permission_type,
+                             bool permission_value = true) {
+    apps::PermissionValuePtr fake_permission_value =
+        std::make_unique<apps::PermissionValue>(permission_value);
+    apps::PermissionPtr fake_permission = std::make_unique<apps::Permission>(
+        permission_type, std::move(fake_permission_value),
+        /*is_managed=*/false);
+    std::vector<apps::PermissionPtr> fake_permissions;
+    fake_permissions.push_back(std::move(fake_permission));
 
-    fake_permissions.push_back(fake_permission.Clone());
-
-    std::vector<apps::mojom::AppPtr> fake_apps;
-    apps::mojom::AppPtr fake_app = apps::mojom::App::New();
-    fake_app->app_type = app_type;
-    fake_app->app_id = fake_id;
-    fake_app->show_in_management = apps::mojom::OptionalBool::kTrue;
-    fake_app->readiness = apps::mojom::Readiness::kReady;
+    std::vector<apps::AppPtr> fake_apps;
+    apps::AppPtr fake_app = std::make_unique<apps::App>(app_type, fake_id);
+    fake_app->show_in_management = true;
+    fake_app->readiness = apps::Readiness::kReady;
     fake_app->permissions = std::move(fake_permissions);
 
-    fake_apps.push_back(fake_app.Clone());
+    fake_apps.push_back(std::move(fake_app));
 
     UpdateAppRegistryCache(fake_apps, app_type);
   }
 
-  void UpdateAppRegistryCache(std::vector<apps::mojom::AppPtr>& fake_apps,
-                              apps::mojom::AppType app_type) {
-    app_service_proxy_->AppRegistryCache().OnApps(std::move(fake_apps),
-                                                  app_type, false);
+  void UpdateAppRegistryCache(std::vector<apps::AppPtr>& fake_apps,
+                              apps::AppType app_type) {
+    if (base::FeatureList::IsEnabled(
+            apps::kAppServiceOnAppUpdateWithoutMojom)) {
+      app_service_proxy_->AppRegistryCache().OnApps(std::move(fake_apps),
+                                                    app_type, false);
+    } else {
+      std::vector<apps::mojom::AppPtr> mojom_apps;
+      mojom_apps.push_back(apps::ConvertAppToMojomApp(fake_apps[0]));
+      app_service_proxy_->AppRegistryCache().OnApps(
+          std::move(mojom_apps), apps::mojom::AppType::kUnknown,
+          /*should_notify_initialized=*/false);
+    }
   }
 
   bool CheckIfFakeAppInList(std::string fake_id) {
@@ -201,8 +207,8 @@
 // Tests notifying observers with only kArc and kWeb apps that have the
 // NOTIFICATIONS permission.
 TEST_F(AppNotificationHandlerTest, TestAppListUpdated) {
-  CreateAndStoreFakeApp("arcAppWithNotifications", apps::mojom::AppType::kArc,
-                        apps::mojom::PermissionType::kNotifications,
+  CreateAndStoreFakeApp("arcAppWithNotifications", apps::AppType::kArc,
+                        apps::PermissionType::kNotifications,
                         /*permission_value=*/true);
 
   base::RunLoop().RunUntilIdle();
@@ -212,8 +218,8 @@
                   ->recently_updated_app()
                   ->notification_permission->value->bool_value.value());
 
-  CreateAndStoreFakeApp("webAppWithNotifications", apps::mojom::AppType::kWeb,
-                        apps::mojom::PermissionType::kNotifications,
+  CreateAndStoreFakeApp("webAppWithNotifications", apps::AppType::kWeb,
+                        apps::PermissionType::kNotifications,
                         /*permission_value=*/true);
 
   base::RunLoop().RunUntilIdle();
@@ -223,27 +229,26 @@
                   ->recently_updated_app()
                   ->notification_permission->value->bool_value.value());
 
-  CreateAndStoreFakeApp("arcAppWithCamera", apps::mojom::AppType::kArc,
-                        apps::mojom::PermissionType::kCamera);
+  CreateAndStoreFakeApp("arcAppWithCamera", apps::AppType::kArc,
+                        apps::PermissionType::kCamera);
 
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(observer()->app_list_changed(), 2);
 
-  CreateAndStoreFakeApp("webAppWithGeolocation", apps::mojom::AppType::kWeb,
-                        apps::mojom::PermissionType::kLocation);
+  CreateAndStoreFakeApp("webAppWithGeolocation", apps::AppType::kWeb,
+                        apps::PermissionType::kLocation);
 
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(observer()->app_list_changed(), 2);
 
-  CreateAndStoreFakeApp("pluginVmAppWithPrinting",
-                        apps::mojom::AppType::kPluginVm,
-                        apps::mojom::PermissionType::kPrinting);
+  CreateAndStoreFakeApp("pluginVmAppWithPrinting", apps::AppType::kPluginVm,
+                        apps::PermissionType::kPrinting);
 
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(observer()->app_list_changed(), 2);
 
-  CreateAndStoreFakeApp("arcAppWithNotifications", apps::mojom::AppType::kArc,
-                        apps::mojom::PermissionType::kNotifications,
+  CreateAndStoreFakeApp("arcAppWithNotifications", apps::AppType::kArc,
+                        apps::PermissionType::kNotifications,
                         /*permission_value=*/false);
 
   base::RunLoop().RunUntilIdle();
@@ -253,8 +258,8 @@
                    ->recently_updated_app()
                    ->notification_permission->value->bool_value.value());
 
-  CreateAndStoreFakeApp("webAppWithNotifications", apps::mojom::AppType::kWeb,
-                        apps::mojom::PermissionType::kNotifications,
+  CreateAndStoreFakeApp("webAppWithNotifications", apps::AppType::kWeb,
+                        apps::PermissionType::kNotifications,
                         /*permission_value=*/false);
 
   base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
index 5f065d9..89280a54 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -275,7 +275,10 @@
       profile, ppd_provider, std::move(printer_configurer), printers_manager));
 }
 
-CupsPrintersHandler::~CupsPrintersHandler() = default;
+CupsPrintersHandler::~CupsPrintersHandler() {
+  if (select_file_dialog_)
+    select_file_dialog_->ListenerDestroyed();
+}
 
 void CupsPrintersHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
@@ -876,6 +879,10 @@
 }
 
 void CupsPrintersHandler::HandleSelectPPDFile(const base::Value::List& args) {
+  // Early return if the select file dialog is already active.
+  if (select_file_dialog_)
+    return;
+
   CHECK_EQ(1U, args.size());
   webui_callback_id_ = args[0].GetString();
 
@@ -940,7 +947,9 @@
                                        void* params) {
   DCHECK(!webui_callback_id_.empty());
 
-  // Load the beggining contents of the file located at |path| and callback into
+  select_file_dialog_ = nullptr;
+
+  // Load the beginning contents of the file located at |path| and callback into
   // VerifyPpdContents() in order to determine whether the file appears to be a
   // PPD file. The task's priority is USER_BLOCKING because the this task
   // updates the UI as a result of a direct user action.
@@ -951,6 +960,10 @@
                      weak_factory_.GetWeakPtr(), path));
 }
 
+void CupsPrintersHandler::FileSelectionCanceled(void* params) {
+  select_file_dialog_ = nullptr;
+}
+
 void CupsPrintersHandler::VerifyPpdContents(const base::FilePath& path,
                                             const std::string& contents) {
   std::string result;
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
index 19a382d..a271068 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
@@ -201,6 +201,7 @@
   void FileSelected(const base::FilePath& path,
                     int index,
                     void* params) override;
+  void FileSelectionCanceled(void* params) override;
 
   // Used by FileSelected() in order to verify whether the beginning contents of
   // the selected file contain the magic number present in all PPD files. |path|
diff --git a/chrome/browser/user_notes/OWNERS b/chrome/browser/user_notes/OWNERS
new file mode 100644
index 0000000..fa6f7875
--- /dev/null
+++ b/chrome/browser/user_notes/OWNERS
@@ -0,0 +1,3 @@
+bokan@chromium.org
+gujen@google.com
+sebsg@chromium.org
diff --git a/chrome/browser/user_notes/user_note_service_factory.cc b/chrome/browser/user_notes/user_note_service_factory.cc
new file mode 100644
index 0000000..b838265
--- /dev/null
+++ b/chrome/browser/user_notes/user_note_service_factory.cc
@@ -0,0 +1,53 @@
+// 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/user_notes/user_note_service_factory.h"
+
+#include <utility>
+
+#include "base/memory/singleton.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/user_notes/browser/user_note_service.h"
+#include "components/user_notes/user_notes_features.h"
+#include "content/public/browser/browser_context.h"
+
+namespace user_notes {
+
+// static
+UserNoteService* UserNoteServiceFactory::GetForContext(
+    content::BrowserContext* context) {
+  return static_cast<UserNoteService*>(
+      GetInstance()->GetServiceForBrowserContext(context,
+                                                 /*create=*/true));
+}
+
+// static
+UserNoteServiceFactory* UserNoteServiceFactory::GetInstance() {
+  return base::Singleton<UserNoteServiceFactory>::get();
+}
+
+UserNoteServiceFactory::UserNoteServiceFactory()
+    : BrowserContextKeyedServiceFactory(
+          "UserNoteService",
+          BrowserContextDependencyManager::GetInstance()) {}
+
+UserNoteServiceFactory::~UserNoteServiceFactory() = default;
+
+KeyedService* UserNoteServiceFactory::BuildServiceInstanceFor(
+    content::BrowserContext* context) const {
+  DCHECK(IsUserNotesEnabled());
+  return new UserNoteService();
+}
+
+content::BrowserContext* UserNoteServiceFactory::GetBrowserContextToUse(
+    content::BrowserContext* context) const {
+  // For now, the feature is not supported in Incognito mode.
+  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
new file mode 100644
index 0000000..7225152d
--- /dev/null
+++ b/chrome/browser/user_notes/user_note_service_factory.h
@@ -0,0 +1,45 @@
+// 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_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"
+
+namespace base {
+template <typename>
+struct DefaultSingletonTraits;
+}  // namespace base
+
+namespace user_notes {
+
+class UserNoteService;
+
+// Factory to get or create a UserNoteService instance for the current browser
+// context.
+class UserNoteServiceFactory : public BrowserContextKeyedServiceFactory {
+ public:
+  static UserNoteService* GetForContext(content::BrowserContext* context);
+
+  UserNoteServiceFactory(const UserNoteServiceFactory&) = delete;
+  UserNoteServiceFactory& operator=(const UserNoteServiceFactory&) = delete;
+
+ private:
+  friend struct base::DefaultSingletonTraits<UserNoteServiceFactory>;
+
+  static UserNoteServiceFactory* GetInstance();
+
+  UserNoteServiceFactory();
+  ~UserNoteServiceFactory() override;
+
+  // BrowserContextKeyedServiceFactory implementation.
+  KeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* context) const override;
+  content::BrowserContext* GetBrowserContextToUse(
+      content::BrowserContext* context) const override;
+};
+
+}  // namespace user_notes
+
+#endif  // CHROME_BROWSER_USER_NOTES_USER_NOTE_SERVICE_FACTORY_H_
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
index 857204d..72b8c214 100644
--- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
+++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
@@ -610,7 +610,7 @@
     // displayed is up to the UI.
     qr_generator_key.emplace();
     crypto::RandBytes(*qr_generator_key);
-    qr_string = device::cablev2::qr::Encode(*qr_generator_key);
+    qr_string = device::cablev2::qr::Encode(*qr_generator_key, request_type);
 
     auto linking_handler = std::make_unique<CableLinkingEventHandler>(
         Profile::FromBrowserContext(GetBrowserContext()));
diff --git a/chrome/browser/webid/federated_identity_active_session_permission_context.cc b/chrome/browser/webid/federated_identity_active_session_permission_context.cc
index 3090159..ea271dd 100644
--- a/chrome/browser/webid/federated_identity_active_session_permission_context.cc
+++ b/chrome/browser/webid/federated_identity_active_session_permission_context.cc
@@ -85,6 +85,10 @@
     const std::string& account_identifier) {
   auto idp_string = identity_provider.Serialize();
   const auto object = GetGrantedObject(relying_party, idp_string);
+  // TODO(cbiesinger): if the provided |account_identifier| does not match the
+  // one we used when granting the permission, return early will leave an entry
+  // in the storage that cannot be removed afterwards. This should be fixed as
+  // part of https://crbug.com/1306852.
   if (!object)
     return;
   auto new_object = object->value.Clone();
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index db53191..1994a6b 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1648208631-2960f826baf74c8fc4e2467da376a585f5489a94.profdata
+chrome-linux-main-1648231192-00a79f1e146c27c001ea594e843d589ee70a8fec.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index f154f00..36b2253 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1648187939-42b0fe3811b3081ce1958f642076e2e290dc2502.profdata
+chrome-mac-arm-main-1648231192-3c2490485831b0f09c86bd23d8256a0603a99ece.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 0bf6663..9f484b0e 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1648208631-2579fa27dac66c10696a26b9d46bb64445561b7c.profdata
+chrome-mac-main-1648231192-d0c8cc3c32150d711191de27df7aad35f66e8ced.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 06ec3b7a..86373fb 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1648220175-12933e7a7719a4e64e7e62bd8bbf06b39897611b.profdata
+chrome-win32-main-1648231192-59d0208f446bf0d15979bd5241c3f83c74869aee.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index e15e137..3bb852b 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1648208631-520357a64fc742f8618f23ffa0ff7a80a2f82c33.profdata
+chrome-win64-main-1648231192-cf18dea6c5392b66b22b709e088251e1b107f6c7.profdata
diff --git a/chrome/common/net/x509_certificate_model.cc b/chrome/common/net/x509_certificate_model.cc
index 86664e7..bd45c8f9 100644
--- a/chrome/common/net/x509_certificate_model.cc
+++ b/chrome/common/net/x509_certificate_model.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/common/net/x509_certificate_model.h"
 
+#include "base/containers/adapters.h"
 #include "base/hash/sha1.h"
 #include "base/i18n/number_formatting.h"
 #include "base/strings/string_number_conversions.h"
@@ -18,6 +19,57 @@
 
 namespace x509_certificate_model {
 
+namespace {
+
+// The certificate viewer may be used to view client certificates, so use the
+// relaxed parsing mode. See crbug.com/770323 and crbug.com/788655.
+constexpr auto kNameStringHandling =
+    net::X509NameAttribute::PrintableStringHandling::kAsUTF8Hack;
+
+OptionalStringOrError FindAttributeOfType(
+    net::der::Input oid,
+    const net::RelativeDistinguishedName& rdn) {
+  // In X.509, RelativeDistinguishedName is a Set, so order has no meaning, and
+  // generally only has one element anyway. Just traverse in encoded order.
+  for (const net::X509NameAttribute& name_attribute : rdn) {
+    if (name_attribute.type == oid) {
+      std::string rv;
+      if (!name_attribute.ValueAsStringWithUnsafeOptions(kNameStringHandling,
+                                                         &rv)) {
+        return Error();
+      }
+      return rv;
+    }
+  }
+  return NotPresent();
+}
+
+// Returns the value of the most general name of |oid| type.
+// Distinguished Names are specified in least to most specific.
+OptionalStringOrError FindFirstNameOfType(net::der::Input oid,
+                                          const net::RDNSequence& rdns) {
+  for (const net::RelativeDistinguishedName& rdn : rdns) {
+    OptionalStringOrError r = FindAttributeOfType(oid, rdn);
+    if (!absl::holds_alternative<NotPresent>(r))
+      return r;
+  }
+  return NotPresent();
+}
+
+// Returns the value of the most specific name of |oid| type.
+// Distinguished Names are specified in least to most specific.
+OptionalStringOrError FindLastNameOfType(net::der::Input oid,
+                                         const net::RDNSequence& rdns) {
+  for (const net::RelativeDistinguishedName& rdn : base::Reversed(rdns)) {
+    OptionalStringOrError r = FindAttributeOfType(oid, rdn);
+    if (!absl::holds_alternative<NotPresent>(r))
+      return r;
+  }
+  return NotPresent();
+}
+
+}  // namespace
+
 X509CertificateModel::X509CertificateModel(
     bssl::UniquePtr<CRYPTO_BUFFER> cert_data,
     std::string nickname)
@@ -76,6 +128,52 @@
                                        tbs_.serial_number.Length(), ':', ':');
 }
 
+OptionalStringOrError X509CertificateModel::GetIssuerCommonName() const {
+  DCHECK(parsed_successfully_);
+  // Return the last (most specific) commonName. This matches NSS
+  // CERT_GetCommonName.
+  return FindLastNameOfType(net::der::Input(net::kTypeCommonNameOid),
+                            issuer_rdns_);
+}
+
+OptionalStringOrError X509CertificateModel::GetIssuerOrgName() const {
+  DCHECK(parsed_successfully_);
+  // Return the first (most general) orgName. This matches NSS CERT_GetOrgName.
+  return FindFirstNameOfType(net::der::Input(net::kTypeOrganizationNameOid),
+                             issuer_rdns_);
+}
+
+OptionalStringOrError X509CertificateModel::GetIssuerOrgUnitName() const {
+  DCHECK(parsed_successfully_);
+  // Return the first (most general) orgUnitName. This matches NSS
+  // CERT_GetOrgUnitName.
+  return FindFirstNameOfType(net::der::Input(net::kTypeOrganizationUnitNameOid),
+                             issuer_rdns_);
+}
+
+OptionalStringOrError X509CertificateModel::GetSubjectCommonName() const {
+  DCHECK(parsed_successfully_);
+  // Return the last (most specific) commonName. This matches NSS
+  // CERT_GetCommonName.
+  return FindLastNameOfType(net::der::Input(net::kTypeCommonNameOid),
+                            subject_rdns_);
+}
+
+OptionalStringOrError X509CertificateModel::GetSubjectOrgName() const {
+  DCHECK(parsed_successfully_);
+  // Return the first (most general) orgName. This matches NSS CERT_GetOrgName.
+  return FindFirstNameOfType(net::der::Input(net::kTypeOrganizationNameOid),
+                             subject_rdns_);
+}
+
+OptionalStringOrError X509CertificateModel::GetSubjectOrgUnitName() const {
+  DCHECK(parsed_successfully_);
+  // Return the first (most general) orgUnitName. This matches NSS
+  // CERT_GetOrgUnitName.
+  return FindFirstNameOfType(net::der::Input(net::kTypeOrganizationUnitNameOid),
+                             subject_rdns_);
+}
+
 bool X509CertificateModel::ParseExtensions(
     const net::der::Input& extensions_tlv) {
   net::CertErrors unused_errors;
diff --git a/chrome/common/net/x509_certificate_model.h b/chrome/common/net/x509_certificate_model.h
index c172fc73..bd5ad06 100644
--- a/chrome/common/net/x509_certificate_model.h
+++ b/chrome/common/net/x509_certificate_model.h
@@ -10,12 +10,17 @@
 
 #include "net/cert/internal/parse_certificate.h"
 #include "net/cert/internal/parse_name.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
 #include "third_party/boringssl/src/include/openssl/pool.h"
 
 // This namespace defines a set of functions to be used in UI-related bits of
 // X509 certificates.
 namespace x509_certificate_model {
 
+struct NotPresent : absl::monostate {};
+struct Error : absl::monostate {};
+using OptionalStringOrError = absl::variant<Error, NotPresent, std::string>;
+
 class X509CertificateModel {
  public:
   // Construct an X509CertificateModel from |cert_data|, which must must not be
@@ -36,6 +41,20 @@
   std::string GetVersion() const;
   std::string GetSerialNumberHexified() const;
 
+  // These methods returns the issuer/subject commonName/orgName/orgUnitName
+  // formatted as a string, if present. Returns NotPresent if the attribute
+  // type was not present, or Error if there was a parsing error.
+  // The Get{Issuer,Subject}CommonName methods return the last (most specific)
+  // commonName, while the other methods return the first (most general) value.
+  // This matches the NSS behaviour of CERT_GetCommonName, CERT_GetOrgName,
+  // CERT_GetOrgUnitName.
+  OptionalStringOrError GetIssuerCommonName() const;
+  OptionalStringOrError GetIssuerOrgName() const;
+  OptionalStringOrError GetIssuerOrgUnitName() const;
+  OptionalStringOrError GetSubjectCommonName() const;
+  OptionalStringOrError GetSubjectOrgName() const;
+  OptionalStringOrError GetSubjectOrgUnitName() const;
+
  private:
   bool ParseExtensions(const net::der::Input& extensions_tlv);
 
diff --git a/chrome/common/net/x509_certificate_model_unittest.cc b/chrome/common/net/x509_certificate_model_unittest.cc
index 963cc80..9f0788c3 100644
--- a/chrome/common/net/x509_certificate_model_unittest.cc
+++ b/chrome/common/net/x509_certificate_model_unittest.cc
@@ -5,12 +5,17 @@
 #include "chrome/common/net/x509_certificate_model.h"
 
 #include "net/cert/x509_util.h"
+#include "net/test/cert_builder.h"
 #include "net/test/cert_test_util.h"
 #include "net/test/test_data_directory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 class X509CertificateModel : public testing::TestWithParam<std::string> {};
 
+using x509_certificate_model::Error;
+using x509_certificate_model::NotPresent;
+using x509_certificate_model::OptionalStringOrError;
+
 TEST_P(X509CertificateModel, InvalidCert) {
   x509_certificate_model::X509CertificateModel model(
       net::x509_util::CreateCryptoBuffer(
@@ -43,6 +48,16 @@
   EXPECT_EQ("3", model.GetVersion());
   EXPECT_EQ("2F:DF:BC:F6:AE:91:52:6D:0F:9A:A3:DF:40:34:3E:9A",
             model.GetSerialNumberHexified());
+  EXPECT_EQ(OptionalStringOrError("Thawte SGC CA"),
+            model.GetIssuerCommonName());
+  EXPECT_EQ(OptionalStringOrError("Thawte Consulting (Pty) Ltd."),
+            model.GetIssuerOrgName());
+  EXPECT_EQ(OptionalStringOrError(NotPresent()), model.GetIssuerOrgUnitName());
+
+  EXPECT_EQ(OptionalStringOrError("www.google.com"),
+            model.GetSubjectCommonName());
+  EXPECT_EQ(OptionalStringOrError("Google Inc"), model.GetSubjectOrgName());
+  EXPECT_EQ(OptionalStringOrError(NotPresent()), model.GetSubjectOrgUnitName());
 }
 
 TEST_P(X509CertificateModel, GetNDNCertFields) {
@@ -56,6 +71,46 @@
   // The model just returns the hex of the DER bytes, so the leading zeros are
   // included.
   EXPECT_EQ("00:DB:B7:C6:06:47:AF:37:A2", model.GetSerialNumberHexified());
+
+  EXPECT_EQ(OptionalStringOrError("New Dream Network Certificate Authority"),
+            model.GetIssuerCommonName());
+  EXPECT_EQ(OptionalStringOrError("New Dream Network, LLC"),
+            model.GetIssuerOrgName());
+  EXPECT_EQ(OptionalStringOrError("Security"), model.GetIssuerOrgUnitName());
+  EXPECT_EQ(OptionalStringOrError("New Dream Network Certificate Authority"),
+            model.GetSubjectCommonName());
+  EXPECT_EQ(OptionalStringOrError("New Dream Network, LLC"),
+            model.GetSubjectOrgName());
+  EXPECT_EQ(OptionalStringOrError("Security"), model.GetSubjectOrgUnitName());
+}
+
+TEST_P(X509CertificateModel, SubjectIA5StringInvalidCharacters) {
+  base::FilePath certs_dir = net::GetTestCertsDirectory();
+  std::unique_ptr<net::CertBuilder> builder =
+      net::CertBuilder::FromFile(certs_dir.AppendASCII("ok_cert.pem"), nullptr);
+  ASSERT_TRUE(builder);
+
+  // SEQUENCE {
+  //   SET {
+  //     SEQUENCE {
+  //       # commonName
+  //       OBJECT_IDENTIFIER { 2.5.4.3 }
+  //       # Not a valid IA5String:
+  //       IA5String { "a \xf6 b" }
+  //     }
+  //   }
+  // }
+  const uint8_t kSubject[] = {0x30, 0x10, 0x31, 0x0e, 0x30, 0x0c,
+                              0x06, 0x03, 0x55, 0x04, 0x03, 0x16,
+                              0x05, 0x61, 0x20, 0xf6, 0x20, 0x62};
+  builder->SetSubject(kSubject);
+
+  x509_certificate_model::X509CertificateModel model(
+      bssl::UpRef(builder->GetCertBuffer()), "");
+  ASSERT_TRUE(model.is_valid());
+  EXPECT_EQ(OptionalStringOrError(Error()), model.GetSubjectCommonName());
+  EXPECT_EQ(OptionalStringOrError(NotPresent()), model.GetSubjectOrgName());
+  EXPECT_EQ(OptionalStringOrError(NotPresent()), model.GetSubjectOrgUnitName());
 }
 
 INSTANTIATE_TEST_SUITE_P(All,
diff --git a/chrome/renderer/cart/commerce_hint_agent.cc b/chrome/renderer/cart/commerce_hint_agent.cc
index ddb1b92c..0db35e9 100644
--- a/chrome/renderer/cart/commerce_hint_agent.cc
+++ b/chrome/renderer/cart/commerce_hint_agent.cc
@@ -997,37 +997,31 @@
   }
 }
 
-void CommerceHintAgent::OnNavigation(const GURL& url,
-                                     OnNavigationCallback callback) {
-  if (!commerce::kOptimizeRendererSignal.Get()) {
-    std::move(callback).Run(false);
-    return;
-  }
-  if (!navigation_observer_.is_bound() ||
-      !navigation_observer_.is_connected()) {
-    navigation_observer_ = GetObserver(render_frame());
-  }
-  navigation_observer_->OnNavigation(url, std::move(callback));
-}
-
 void CommerceHintAgent::DidStartNavigation(
     const GURL& url,
     absl::optional<blink::WebNavigationType> navigation_type) {
   if (!url.SchemeIsHTTPOrHTTPS())
     return;
   has_finished_loading_ = false;
-  OnNavigation(url,
-               base::BindOnce(&CommerceHintAgent::DidStartNavigationCallback,
-                              weak_factory_.GetWeakPtr(), url,
-                              std::move(navigation_type)));
+  starting_url_ = url;
+  mojo::Remote<mojom::CommerceHintObserver> observer =
+      GetObserver(render_frame());
+  if (!commerce::kOptimizeRendererSignal.Get()) {
+    DidStartNavigationCallback(url, std::move(observer), false);
+    return;
+  }
+  auto* observer_ptr = observer.get();
+  observer_ptr->OnNavigation(
+      url,
+      base::BindOnce(&CommerceHintAgent::DidStartNavigationCallback,
+                     weak_factory_.GetWeakPtr(), url, std::move(observer)));
 }
 
 void CommerceHintAgent::DidStartNavigationCallback(
     const GURL& url,
-    absl::optional<blink::WebNavigationType> navigation_type,
+    mojo::Remote<mojom::CommerceHintObserver> observer,
     bool should_skip) {
   should_skip_ = should_skip;
-  starting_url_ = url;
 }
 
 void CommerceHintAgent::DidCommitProvisionalLoad(
@@ -1061,18 +1055,29 @@
   const GURL& url(frame->GetDocument().Url());
   if (!url.SchemeIs(url::kHttpsScheme))
     return;
-  OnNavigation(url, base::BindOnce(&CommerceHintAgent::DidFinishLoadCallback,
-                                   weak_factory_.GetWeakPtr()));
+  mojo::Remote<mojom::CommerceHintObserver> observer =
+      GetObserver(render_frame());
+  if (!commerce::kOptimizeRendererSignal.Get()) {
+    DidFinishLoadCallback(url, std::move(observer), false);
+    return;
+  }
+  auto* observer_ptr = observer.get();
+  observer_ptr->OnNavigation(
+      url,
+      base::BindOnce(&CommerceHintAgent::DidFinishLoadCallback,
+                     weak_factory_.GetWeakPtr(), url, std::move(observer)));
 }
 
-void CommerceHintAgent::DidFinishLoadCallback(bool should_skip) {
+void CommerceHintAgent::DidFinishLoadCallback(
+    const GURL& url,
+    mojo::Remote<mojom::CommerceHintObserver> observer,
+    bool should_skip) {
   should_skip_ = should_skip;
   if (should_skip_) {
     return;
   }
   has_finished_loading_ = true;
   extraction_count_ = 0;
-  const GURL& url(render_frame()->GetWebFrame()->GetDocument().Url());
   // Some URLs might satisfy the patterns for both cart and checkout (e.g.
   // https://www.foo.com/cart/checkout). In those cases, cart has higher
   // priority.
diff --git a/chrome/renderer/cart/commerce_hint_agent.h b/chrome/renderer/cart/commerce_hint_agent.h
index 08821a2..85be0bdf 100644
--- a/chrome/renderer/cart/commerce_hint_agent.h
+++ b/chrome/renderer/cart/commerce_hint_agent.h
@@ -57,8 +57,6 @@
       const blink::WebFormElement& form);
 
  private:
-  using OnNavigationCallback = base::OnceCallback<void(bool)>;
-
   void MaybeExtractProducts();
   void ExtractProducts();
   void ExtractCartFromCurrentFrame();
@@ -72,7 +70,6 @@
   bool is_extraction_pending_{false};
   bool is_extraction_running_{false};
   bool should_skip_{false};
-  mojo::Remote<mojom::CommerceHintObserver> navigation_observer_;
   base::WeakPtrFactory<CommerceHintAgent> weak_factory_{this};
 
   class JavaScriptRequest : public blink::WebScriptExecutionCallback {
@@ -102,18 +99,17 @@
   void DidObserveLayoutShift(double score, bool after_input_or_scroll) override;
   void OnMainFrameIntersectionChanged(const gfx::Rect& intersect_rect) override;
 
-  void OnNavigation(const GURL& url, OnNavigationCallback callback);
   // Callbacks with business logics for handling navigation-related observer
   // calls. These callbacks are triggered when navigation-related signals are
   // captured and carry an extra bool |should_act| indicating whether commerce
   // hint signals should be collected on current URL or not.
   void DidStartNavigationCallback(
       const GURL& url,
-      absl::optional<blink::WebNavigationType> navigation_type,
+      mojo::Remote<mojom::CommerceHintObserver> observer,
       bool should_skip);
-  void DidCommitProvisionalLoadCallback(ui::PageTransition transition,
-                                        bool should_skip);
-  void DidFinishLoadCallback(bool should_skip);
+  void DidFinishLoadCallback(const GURL& url,
+                             mojo::Remote<mojom::CommerceHintObserver> observer,
+                             bool should_skip);
 };
 
 }  // namespace cart
diff --git a/chrome/renderer/cart/commerce_hint_agent_browsertest.cc b/chrome/renderer/cart/commerce_hint_agent_browsertest.cc
index 9870b8f..82761d3e 100644
--- a/chrome/renderer/cart/commerce_hint_agent_browsertest.cc
+++ b/chrome/renderer/cart/commerce_hint_agent_browsertest.cc
@@ -669,7 +669,43 @@
   SendXHR("/add-to-cart", "product: 123");
   base::PlatformThread::Sleep(TestTimeouts::tiny_timeout() * 30);
   WaitForCartCount(kEmptyExpected);
+  WaitForUmaCount("Commerce.Carts.AddToCartByURL", 0);
+
+  NavigateToURL("https://www.guitarcenter.com/cart.html");
+  WaitForCartCount(kEmptyExpected);
+  WaitForUmaCount("Commerce.Carts.VisitCart", 0);
+}
+
+class CommerceHintOptimizeRendererDisabledTest : public CommerceHintAgentTest {
+ public:
+  void SetUpInProcessBrowserTestFixture() override {
+    scoped_feature_list_.InitWithFeaturesAndParameters(
+        {{ntp_features::kNtpChromeCartModule,
+          {{"optimize-renderer-signal", "false"}}},
+         {optimization_guide::features::kOptimizationHints, {{}}}},
+        {});
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+// If command line argument "optimization_guide_hints_override" is not given,
+// nothing is specified in AddHintForTesting(), and the real hints are not
+// downloaded, all the URLs are considered non-shopping.
+IN_PROC_BROWSER_TEST_F(CommerceHintOptimizeRendererDisabledTest, Rejected) {
+  NavigateToURL("https://www.guitarcenter.com/");
+  SendXHR("/add-to-cart", "product: 123");
+  base::PlatformThread::Sleep(TestTimeouts::tiny_timeout() * 30);
+  WaitForCartCount(kEmptyExpected);
+  // The cart won't be added on browser side because of Cacao rejection either
+  // way, but when optimize-renderer-signal is disabled, renderer will still
+  // observer and process commerce signals on this site.
   WaitForUmaCount("Commerce.Carts.AddToCartByURL", 1);
+
+  NavigateToURL("https://www.guitarcenter.com/cart.html");
+  WaitForCartCount(kEmptyExpected);
+  WaitForUmaCount("Commerce.Carts.VisitCart", 1);
 }
 
 class CommerceHintProductInfoTest : public CommerceHintAgentTest {
diff --git a/chrome/renderer/chrome_render_frame_observer.cc b/chrome/renderer/chrome_render_frame_observer.cc
index 0b8dd3e..7b583ccd 100644
--- a/chrome/renderer/chrome_render_frame_observer.cc
+++ b/chrome/renderer/chrome_render_frame_observer.cc
@@ -9,6 +9,7 @@
 
 #include <limits>
 #include <map>
+#include <set>
 #include <utility>
 
 #include "base/bind.h"
@@ -37,6 +38,7 @@
 #include "content/public/common/bindings_policy.h"
 #include "content/public/common/content_features.h"
 #include "content/public/renderer/render_frame.h"
+#include "content/public/renderer/render_frame_visitor.h"
 #include "content/public/renderer/render_thread.h"
 #include "content/public/renderer/render_view.h"
 #include "content/public/renderer/window_features_converter.h"
@@ -121,6 +123,52 @@
 }
 #endif
 
+// Renderers can handle multiple pages, especially in low-memory conditions.
+// Record crash keys for a few origins, in the hope of finding more culprit
+// origins for OOM crashes. Keys are recorded here and not via
+// ChromeContentClient::SetActiveURL() because that method is only invoked in
+// response to IPC messages and most OOMs do not occur in response to an IPC.
+// https://crbug.com/1310046
+void UpdateLoadedOriginCrashKeys() {
+  // Capture the origin for each RenderFrame.
+  struct Visitor : public content::RenderFrameVisitor {
+    bool Visit(RenderFrame* render_frame) override {
+      if (render_frame) {
+        WebLocalFrame* web_frame = render_frame->GetWebFrame();
+        if (web_frame) {
+          frame_count_++;
+          origins_.insert(web_frame->GetSecurityOrigin().ToString().Utf8());
+        }
+      }
+      return true;  // Keep going.
+    }
+    int frame_count_ = 0;
+    std::set<std::string> origins_;  // Use set to collapse duplicate origins.
+  } visitor;
+  RenderFrame::ForEach(&visitor);
+
+  static crash_reporter::CrashKeyString<8> frame_count("web-frame-count");
+  frame_count.Set(base::NumberToString(visitor.frame_count_));
+
+  // Record 3 recently-loaded origins in crash keys (which 3 is arbitrary).
+  using ArrayItemKey = crash_reporter::CrashKeyString<64>;
+  static ArrayItemKey crash_keys[] = {
+      {"loaded-origin-0", ArrayItemKey::Tag::kArray},
+      {"loaded-origin-1", ArrayItemKey::Tag::kArray},
+      {"loaded-origin-2", ArrayItemKey::Tag::kArray},
+  };
+  for (auto& crash_key : crash_keys) {
+    if (!visitor.origins_.empty()) {
+      auto origin_it = visitor.origins_.begin();
+      crash_key.Set(*origin_it);
+      visitor.origins_.erase(origin_it);
+    } else {
+      // If there are fewer than 3 origins, clear the remaining keys.
+      crash_key.Clear();
+    }
+  }
+}
+
 }  // namespace
 
 ChromeRenderFrameObserver::ChromeRenderFrameObserver(
@@ -241,6 +289,9 @@
 
 void ChromeRenderFrameObserver::DidCommitProvisionalLoad(
     ui::PageTransition transition) {
+  // Update crash keys on any frame transition, not just the main frame.
+  UpdateLoadedOriginCrashKeys();
+
   WebLocalFrame* frame = render_frame()->GetWebFrame();
 
   // Don't do anything for subframes.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index d78523c8..d91d4dd2d 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -221,6 +221,7 @@
     "//chrome/utility",
     "//components/autofill/core/browser:test_support",
     "//components/bookmarks/test",
+    "//components/browsing_topics:test_support",
     "//components/captive_portal/core:test_support",
     "//components/consent_auditor:test_support",
     "//components/content_settings/core/browser",
@@ -238,6 +239,7 @@
     "//components/network_time",
     "//components/network_time:network_time_test_support",
     "//components/omnibox/browser:test_support",
+    "//components/optimization_guide/content/browser:test_support",
     "//components/os_crypt",
     "//components/password_manager/core/browser:test_support",
     "//components/payments/core:test_support",
@@ -1421,7 +1423,7 @@
       "//testing/perf",
       "//third_party/blink/public:blink_headers",
       "//third_party/blink/public:buildflags",
-      "//third_party/blink/public/common:headers",
+      "//third_party/blink/public/common",
       "//third_party/blink/public/mojom:web_feature_mojo_bindings",
       "//third_party/icu",
       "//third_party/leveldatabase",
@@ -4750,7 +4752,9 @@
 }
 
 if (is_fuchsia) {
-  # Currently no perf tests for Fuchsia.
+  # TODO(crbug.com/1310086): Split performance_web_engine_test_suite
+  # into fuchsia-chrome and web_engine test, and put fuchsia-chrome
+  # test target here.
 } else if (!is_android) {
   performance_test_suite_template("performance_test_suite") {
   }
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index 0de6f1e..5f0ffaa6 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -944,7 +944,8 @@
 
 content::PermissionControllerDelegate*
 TestingProfile::GetPermissionControllerDelegate() {
-  return nullptr;
+  return permission_controller_delegate_ ? permission_controller_delegate_.get()
+                                         : nullptr;
 }
 
 content::ClientHintsControllerDelegate*
diff --git a/chrome/test/base/testing_profile.h b/chrome/test/base/testing_profile.h
index 66e5695..9ddec38a 100644
--- a/chrome/test/base/testing_profile.h
+++ b/chrome/test/base/testing_profile.h
@@ -26,6 +26,7 @@
 #include "components/keyed_service/core/simple_dependency_manager.h"
 #include "components/keyed_service/core/simple_factory_key.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/permission_controller_delegate.h"
 #include "extensions/buildflags/buildflags.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
 #include "net/cookies/cookie_store.h"
@@ -407,6 +408,11 @@
     profile_destruction_callback_ = std::move(callback);
   }
 
+  void SetPermissionControllerDelegate(
+      std::unique_ptr<content::PermissionControllerDelegate> delegate) {
+    permission_controller_delegate_ = std::move(delegate);
+  }
+
  private:
   // Called when profile is deleted.
   ProfileDestructionCallback profile_destruction_callback_;
@@ -469,6 +475,9 @@
 
   scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
 
+  std::unique_ptr<content::PermissionControllerDelegate>
+      permission_controller_delegate_;
+
   base::FilePath last_selected_directory_;
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
diff --git a/chrome/test/data/browsing_topics/one_iframe_page_sandboxed.html.mock-http-headers b/chrome/test/data/browsing_topics/one_iframe_page_sandboxed.html.mock-http-headers
new file mode 100644
index 0000000..3dd48ca
--- /dev/null
+++ b/chrome/test/data/browsing_topics/one_iframe_page_sandboxed.html.mock-http-headers
@@ -0,0 +1,2 @@
+HTTP/1.1 200 OK
+Content-Security-Policy: sandbox allow-scripts;
diff --git a/chrome/test/data/browsing_topics/one_sandboxed_iframe_page.html b/chrome/test/data/browsing_topics/one_sandboxed_iframe_page.html
new file mode 100644
index 0000000..3e94c6aa
--- /dev/null
+++ b/chrome/test/data/browsing_topics/one_sandboxed_iframe_page.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+  <iframe src="empty_page.html" sandbox="allow-scripts" id="frame"></iframe>
+</body>
+</html>
diff --git a/chrome/test/webapps/coverage/coverage_cros.tsv b/chrome/test/webapps/coverage/coverage_cros.tsv
index 9b3d75d5..c45fcb5 100644
--- a/chrome/test/webapps/coverage/coverage_cros.tsv
+++ b/chrome/test/webapps/coverage/coverage_cros.tsv
@@ -1,5 +1,5 @@
 # This is a generated file.
-# Full coverage: 52%, with partial coverage: 70%
+# Full coverage: 52%, with partial coverage: 72%
 install_create_shortcut_windowed_SiteA🌕	manifest_update_title_SiteA🌑	accept_app_update_dialog🌑	close_pwa🌑	launch_from_menu_option_SiteA🌑	check_window_title_site_a_is_SiteAUpdated🌑
 install_create_shortcut_windowed_SiteA🌕	manifest_update_title_SiteA🌑	accept_app_update_dialog🌑	close_pwa🌑	launch_from_launch_icon_SiteA🌑	check_window_title_site_a_is_SiteAUpdated🌑
 install_create_shortcut_windowed_SiteA🌕	manifest_update_title_SiteA🌑	accept_app_update_dialog🌑	close_pwa🌑	launch_from_chrome_apps_SiteA🌑	check_window_title_site_a_is_SiteAUpdated🌑
@@ -58,12 +58,12 @@
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_app_in_list_windowed_SiteA🌓
-install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
 install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_window_created🌕
 install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_window_created🌕
 install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_window_created🌕
@@ -77,14 +77,14 @@
 install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_not_exists_SiteA🌑
 install_policy_app_windowed_no_shortcut_SiteC🌓	check_platform_shortcut_not_exists_SiteC🌑
 install_policy_app_tabbed_no_shortcut_SiteC🌓	check_platform_shortcut_not_exists_SiteC🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	check_app_in_list_windowed_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_app_in_list_windowed_SiteA🌓
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	check_app_in_list_windowed_SiteA🌓
@@ -162,8 +162,16 @@
 install_create_shortcut_windowed_SiteC🌕	navigate_browser_SiteC🌕	check_launch_icon_shown🌕
 install_policy_app_windowed_no_shortcut_SiteC🌓	navigate_browser_SiteC🌕	check_launch_icon_shown🌕
 install_policy_app_windowed_shortcut_SiteC🌓	navigate_browser_SiteC🌕	check_launch_icon_shown🌕
-install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteC🌑
+install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_windowed_shortcut_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌓
+install_policy_app_tabbed_shortcut_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌓
+install_create_shortcut_windowed_SiteC🌕	check_platform_shortcut_and_icon_SiteC🌓
+install_create_shortcut_tabbed_SiteC🌕	check_platform_shortcut_and_icon_SiteC🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
@@ -483,10 +491,10 @@
 install_omnibox_icon_SiteA🌕	switch_incognito_profile🌑	navigate_browser_SiteA🌑	check_launch_icon_not_shown🌑
 install_menu_option_SiteA🌕	switch_incognito_profile🌑	navigate_browser_SiteA🌑	check_launch_icon_not_shown🌑
 switch_incognito_profile🌑	navigate_browser_SiteA🌑	check_install_icon_not_shown🌑
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_and_icon_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	check_app_in_list_tabbed_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	check_app_in_list_windowed_SiteA🌓
 install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	check_app_in_list_windowed_SiteA🌓
@@ -501,7 +509,7 @@
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_app_in_list_tabbed_SiteA🌑
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_app_in_list_tabbed_SiteA🌑
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_app_settings_SiteA🌑	sync_turn_on🌑	check_app_in_list_tabbed_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_SiteA🌕	sync_turn_on🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_SiteA🌕	sync_turn_on🌕	check_platform_shortcut_and_icon_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_and_icon_SiteA🌑
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_and_icon_SiteA🌑
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_app_settings_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_and_icon_SiteA🌑
@@ -517,15 +525,15 @@
 install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_app_in_list_windowed_SiteA🌑
 install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_app_in_list_windowed_SiteA🌑
 install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_app_settings_SiteA🌑	sync_turn_on🌑	check_app_in_list_windowed_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_SiteA🌕	sync_turn_on🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_SiteA🌕	sync_turn_on🌕	check_platform_shortcut_and_icon_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_and_icon_SiteA🌑
 install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_and_icon_SiteA🌑
 install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_app_settings_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_SiteA🌕	sync_turn_on🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_SiteA🌕	sync_turn_on🌕	check_platform_shortcut_and_icon_SiteA🌓
 install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_and_icon_SiteA🌑
 install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_and_icon_SiteA🌑
 install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_app_settings_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_SiteA🌕	sync_turn_on🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_SiteA🌕	sync_turn_on🌕	check_platform_shortcut_and_icon_SiteA🌓
 install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_and_icon_SiteA🌑
 install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_and_icon_SiteA🌑
 install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_app_settings_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_and_icon_SiteA🌑
@@ -561,10 +569,10 @@
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_tabbed_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_tabbed_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_tabbed_SiteA🌓
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
@@ -577,18 +585,18 @@
 install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_menu_option_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
 install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_not_in_list_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_not_in_list_SiteA🌓
 install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_not_in_list_SiteA🌓
@@ -605,9 +613,9 @@
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
-install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
diff --git a/chrome/test/webapps/coverage/coverage_linux.tsv b/chrome/test/webapps/coverage/coverage_linux.tsv
index 65e1e8b2..686fbdf8 100644
--- a/chrome/test/webapps/coverage/coverage_linux.tsv
+++ b/chrome/test/webapps/coverage/coverage_linux.tsv
@@ -1,5 +1,5 @@
 # This is a generated file.
-# Full coverage: 55%, with partial coverage: 74%
+# Full coverage: 55%, with partial coverage: 76%
 install_create_shortcut_windowed_SiteA🌕	manifest_update_title_SiteA🌑	accept_app_update_dialog🌑	close_pwa🌑	launch_from_menu_option_SiteA🌑	check_window_title_site_a_is_SiteAUpdated🌑
 install_create_shortcut_windowed_SiteA🌕	manifest_update_title_SiteA🌑	accept_app_update_dialog🌑	close_pwa🌑	launch_from_launch_icon_SiteA🌑	check_window_title_site_a_is_SiteAUpdated🌑
 install_create_shortcut_windowed_SiteA🌕	manifest_update_title_SiteA🌑	accept_app_update_dialog🌑	close_pwa🌑	launch_from_chrome_apps_SiteA🌑	check_window_title_site_a_is_SiteAUpdated🌑
@@ -58,12 +58,12 @@
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_app_in_list_windowed_SiteA🌓
-install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
 install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_window_created🌕
 install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_window_created🌕
 install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_window_created🌕
@@ -73,10 +73,10 @@
 install_create_shortcut_windowed_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	check_window_created🌕
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_app_in_list_tabbed_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	navigate_browser_SiteA🌕	check_install_icon_shown🌕
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	navigate_browser_SiteA🌕	check_launch_icon_not_shown🌕
@@ -94,20 +94,20 @@
 install_create_shortcut_windowed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	check_app_in_list_windowed_SiteC🌓
 install_create_shortcut_windowed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	navigate_browser_SiteC🌕	check_install_icon_not_shown🌕
 install_create_shortcut_windowed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	navigate_browser_SiteC🌕	check_launch_icon_shown🌕
-install_create_shortcut_windowed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌑
-install_create_shortcut_tabbed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌑
+install_create_shortcut_windowed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌓
+install_create_shortcut_tabbed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌓
 install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_not_exists_SiteA🌑
 install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_not_exists_SiteA🌑
 install_policy_app_windowed_no_shortcut_SiteC🌓	check_platform_shortcut_not_exists_SiteC🌑
 install_policy_app_tabbed_no_shortcut_SiteC🌓	check_platform_shortcut_not_exists_SiteC🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	check_app_in_list_windowed_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_app_in_list_windowed_SiteA🌓
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	check_app_in_list_windowed_SiteA🌓
@@ -185,8 +185,16 @@
 install_create_shortcut_windowed_SiteC🌕	navigate_browser_SiteC🌕	check_launch_icon_shown🌕
 install_policy_app_windowed_no_shortcut_SiteC🌓	navigate_browser_SiteC🌕	check_launch_icon_shown🌕
 install_policy_app_windowed_shortcut_SiteC🌓	navigate_browser_SiteC🌕	check_launch_icon_shown🌕
-install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteC🌑
+install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_windowed_shortcut_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌓
+install_policy_app_tabbed_shortcut_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌓
+install_create_shortcut_windowed_SiteC🌕	check_platform_shortcut_and_icon_SiteC🌓
+install_create_shortcut_tabbed_SiteC🌕	check_platform_shortcut_and_icon_SiteC🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
@@ -648,10 +656,10 @@
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_tabbed_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_tabbed_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_tabbed_SiteA🌓
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
@@ -664,18 +672,18 @@
 install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_menu_option_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
 install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_not_in_list_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_not_in_list_SiteA🌓
 install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_not_in_list_SiteA🌓
@@ -692,12 +700,12 @@
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
-install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	open_app_settings_from_chrome_apps_SiteA🌑	check_browser_navigation_is_app_settings_SiteA🌑	enable_run_on_os_login_SiteA🌑	check_run_on_os_login_enabled_SiteA🌑	check_app_settings_app_state_SiteA🌑
 install_omnibox_icon_SiteA🌕	open_app_settings_from_chrome_apps_SiteA🌑	check_browser_navigation_is_app_settings_SiteA🌑	enable_run_on_os_login_SiteA🌑	check_run_on_os_login_enabled_SiteA🌑	check_app_settings_app_state_SiteA🌑
 install_policy_app_windowed_no_shortcut_SiteA🌓	open_app_settings_from_chrome_apps_SiteA🌑	check_browser_navigation_is_app_settings_SiteA🌑	enable_run_on_os_login_SiteA🌑	check_run_on_os_login_enabled_SiteA🌑	check_app_settings_app_state_SiteA🌑
diff --git a/chrome/test/webapps/coverage/coverage_mac.tsv b/chrome/test/webapps/coverage/coverage_mac.tsv
index c8dcc2e..8beceaf9 100644
--- a/chrome/test/webapps/coverage/coverage_mac.tsv
+++ b/chrome/test/webapps/coverage/coverage_mac.tsv
@@ -1,5 +1,5 @@
 # This is a generated file.
-# Full coverage: 51%, with partial coverage: 69%
+# Full coverage: 50%, with partial coverage: 66%
 install_create_shortcut_windowed_SiteA🌕	manifest_update_title_SiteA🌑	accept_app_update_dialog🌑	close_pwa🌑	launch_from_menu_option_SiteA🌑	check_window_title_site_a_is_SiteAUpdated🌑
 install_create_shortcut_windowed_SiteA🌕	manifest_update_title_SiteA🌑	accept_app_update_dialog🌑	close_pwa🌑	launch_from_launch_icon_SiteA🌑	check_window_title_site_a_is_SiteAUpdated🌑
 install_create_shortcut_windowed_SiteA🌕	manifest_update_title_SiteA🌑	accept_app_update_dialog🌑	close_pwa🌑	launch_from_chrome_apps_SiteA🌑	check_window_title_site_a_is_SiteAUpdated🌑
@@ -58,12 +58,12 @@
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_app_in_list_windowed_SiteA🌓
-install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
 install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_window_created🌕
 install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_window_created🌕
 install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_window_created🌕
@@ -73,41 +73,41 @@
 install_create_shortcut_windowed_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	check_window_created🌕
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	check_platform_shortcut_and_icon_SiteA🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	check_platform_shortcut_and_icon_SiteA🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌕
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_app_in_list_tabbed_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	navigate_browser_SiteA🌕	check_install_icon_shown🌕
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	navigate_browser_SiteA🌕	check_launch_icon_not_shown🌕
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_app_in_list_windowed_SiteA🌓
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_app_in_list_windowed_SiteA🌓
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_app_in_list_windowed_SiteA🌓
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	navigate_browser_SiteA🌑	check_install_icon_not_shown🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	navigate_browser_SiteA🌑	check_install_icon_not_shown🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	navigate_browser_SiteA🌑	check_install_icon_not_shown🌑
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	navigate_browser_SiteA🌑	check_launch_icon_shown🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	navigate_browser_SiteA🌑	check_launch_icon_shown🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	navigate_browser_SiteA🌑	check_launch_icon_shown🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	check_app_in_list_windowed_SiteA🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	check_app_in_list_windowed_SiteA🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	check_app_in_list_windowed_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	navigate_browser_SiteA🌑	check_install_icon_not_shown🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	navigate_browser_SiteA🌑	check_install_icon_not_shown🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	navigate_browser_SiteA🌑	check_install_icon_not_shown🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	navigate_browser_SiteA🌑	check_launch_icon_shown🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	navigate_browser_SiteA🌑	check_launch_icon_shown🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	navigate_browser_SiteA🌑	check_launch_icon_shown🌑
 install_create_shortcut_tabbed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	check_app_in_list_tabbed_SiteC🌓
 install_create_shortcut_tabbed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	navigate_browser_SiteC🌕	check_launch_icon_not_shown🌕
 install_create_shortcut_windowed_SiteC🌕	switch_profile_clients_Client2🌑	install_locally_SiteC🌑	check_app_in_list_windowed_SiteC🌑
 install_create_shortcut_windowed_SiteC🌕	switch_profile_clients_Client2🌑	install_locally_SiteC🌑	navigate_browser_SiteC🌑	check_install_icon_not_shown🌑
 install_create_shortcut_windowed_SiteC🌕	switch_profile_clients_Client2🌑	install_locally_SiteC🌑	navigate_browser_SiteC🌑	check_launch_icon_shown🌑
 install_create_shortcut_windowed_SiteC🌕	switch_profile_clients_Client2🌑	install_locally_SiteC🌑	check_platform_shortcut_and_icon_SiteC🌑
-install_create_shortcut_tabbed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌑
+install_create_shortcut_tabbed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_not_exists_SiteA🌑
 install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_not_exists_SiteA🌑
 install_policy_app_windowed_no_shortcut_SiteC🌓	check_platform_shortcut_not_exists_SiteC🌑
 install_policy_app_tabbed_no_shortcut_SiteC🌓	check_platform_shortcut_not_exists_SiteC🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌕
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌕
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌕
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌕
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌕
+install_omnibox_icon_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌕
+install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌕
+install_menu_option_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	check_app_in_list_windowed_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_app_in_list_windowed_SiteA🌓
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	check_app_in_list_windowed_SiteA🌓
@@ -185,8 +185,16 @@
 install_create_shortcut_windowed_SiteC🌕	navigate_browser_SiteC🌕	check_launch_icon_shown🌕
 install_policy_app_windowed_no_shortcut_SiteC🌓	navigate_browser_SiteC🌕	check_launch_icon_shown🌕
 install_policy_app_windowed_shortcut_SiteC🌓	navigate_browser_SiteC🌕	check_launch_icon_shown🌕
-install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteC🌑
+install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌕
+install_policy_app_tabbed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌕
+install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_create_shortcut_tabbed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_policy_app_windowed_shortcut_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌕
+install_policy_app_tabbed_shortcut_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌕
+install_create_shortcut_windowed_SiteC🌕	check_platform_shortcut_and_icon_SiteC🌕
+install_create_shortcut_tabbed_SiteC🌕	check_platform_shortcut_and_icon_SiteC🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
@@ -271,18 +279,18 @@
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_platform_shortcut_SiteA🌓	check_window_display_minimal🌕
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	launch_from_launch_icon_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	launch_from_chrome_apps_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	launch_from_platform_shortcut_SiteA🌓	check_window_created🌕
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	launch_from_launch_icon_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	launch_from_chrome_apps_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	launch_from_platform_shortcut_SiteA🌓	check_window_created🌕
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	launch_from_launch_icon_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	launch_from_chrome_apps_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	launch_from_platform_shortcut_SiteA🌓	check_window_created🌕
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	launch_from_menu_option_SiteA🌑	check_window_created🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	launch_from_launch_icon_SiteA🌑	check_window_created🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	launch_from_chrome_apps_SiteA🌑	check_window_created🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	launch_from_menu_option_SiteA🌑	check_window_created🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	launch_from_launch_icon_SiteA🌑	check_window_created🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	launch_from_chrome_apps_SiteA🌑	check_window_created🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	launch_from_menu_option_SiteA🌑	check_window_created🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	launch_from_launch_icon_SiteA🌑	check_window_created🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	launch_from_chrome_apps_SiteA🌑	check_window_created🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	install_locally_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
 install_create_shortcut_tabbed_SiteA🌕	set_open_in_window_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
 install_create_shortcut_tabbed_SiteA🌕	set_open_in_window_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_create_shortcut_tabbed_SiteA🌕	set_open_in_window_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
@@ -348,15 +356,15 @@
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌓	check_tab_created🌕
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
-install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	launch_from_platform_shortcut_SiteA🌓	check_tab_created🌕
+install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
-install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	launch_from_platform_shortcut_SiteA🌓	check_tab_created🌕
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	launch_from_chrome_apps_SiteA🌑	check_tab_created🌑
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	launch_from_platform_shortcut_SiteA🌓	check_tab_created🌕
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	launch_from_chrome_apps_SiteA🌑	check_tab_created🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	launch_from_platform_shortcut_SiteA🌓	check_tab_created🌕
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	launch_from_chrome_apps_SiteA🌑	check_tab_created🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	launch_from_platform_shortcut_SiteA🌓	check_tab_created🌕
+install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	launch_from_chrome_apps_SiteA🌑	check_tab_created🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	launch_from_chrome_apps_SiteA🌑	check_tab_created🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	launch_from_chrome_apps_SiteA🌑	check_tab_created🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
 install_create_shortcut_windowed_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_create_shortcut_windowed_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_platform_shortcut_SiteA🌓	check_tab_created🌕
 install_omnibox_icon_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
@@ -526,20 +534,20 @@
 install_omnibox_icon_SiteA🌕	switch_incognito_profile🌑	navigate_browser_SiteA🌑	check_launch_icon_not_shown🌑
 install_menu_option_SiteA🌕	switch_incognito_profile🌑	navigate_browser_SiteA🌑	check_launch_icon_not_shown🌑
 switch_incognito_profile🌑	navigate_browser_SiteA🌑	check_install_icon_not_shown🌑
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_SiteA🌓
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_SiteA🌓
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	check_app_in_list_not_locally_installed_SiteA🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	check_app_in_list_not_locally_installed_SiteA🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	check_app_in_list_not_locally_installed_SiteA🌑
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_SiteA🌓
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_not_exists_SiteA🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_not_exists_SiteA🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_not_exists_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	check_platform_shortcut_not_exists_SiteA🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	check_platform_shortcut_not_exists_SiteA🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	check_platform_shortcut_not_exists_SiteA🌑
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_not_exists_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	navigate_browser_SiteA🌑	check_install_icon_shown🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	navigate_browser_SiteA🌑	check_install_icon_shown🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	navigate_browser_SiteA🌑	check_install_icon_shown🌑
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	navigate_browser_SiteA🌑	check_launch_icon_not_shown🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	navigate_browser_SiteA🌑	check_launch_icon_not_shown🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	navigate_browser_SiteA🌑	check_launch_icon_not_shown🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	navigate_browser_SiteA🌑	check_install_icon_shown🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	navigate_browser_SiteA🌑	check_install_icon_shown🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	navigate_browser_SiteA🌑	check_install_icon_shown🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	navigate_browser_SiteA🌑	check_launch_icon_not_shown🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	navigate_browser_SiteA🌑	check_launch_icon_not_shown🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	navigate_browser_SiteA🌑	check_launch_icon_not_shown🌑
 install_create_shortcut_windowed_SiteC🌕	switch_profile_clients_Client2🌑	check_app_in_list_not_locally_installed_SiteC🌑
 install_create_shortcut_tabbed_SiteC🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_SiteC🌓
 install_create_shortcut_windowed_SiteC🌕	switch_profile_clients_Client2🌑	check_platform_shortcut_not_exists_SiteC🌑
@@ -550,27 +558,27 @@
 sync_turn_off🌕	install_create_shortcut_tabbed_SiteA🌕	sync_turn_on🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_SiteA🌓
 sync_turn_off🌕	install_create_shortcut_windowed_SiteC🌑	sync_turn_on🌑	switch_profile_clients_Client2🌑	check_app_in_list_not_locally_installed_SiteC🌑
 sync_turn_off🌕	install_create_shortcut_tabbed_SiteC🌕	sync_turn_on🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_SiteC🌓
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_list_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_list_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_list_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_list_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_list_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_list_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_SiteA🌕	sync_turn_on🌕	check_app_in_list_not_locally_installed_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_list_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_list_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_list_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌑	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_list_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_list_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_list_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_SiteA🌕	sync_turn_on🌕	check_platform_shortcut_not_exists_SiteA🌑
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_menu_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_os_SiteA🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_SiteA🌑
@@ -630,13 +638,13 @@
 install_create_shortcut_windowed_SiteC🌕	uninstall_from_menu_SiteC🌕	check_platform_shortcut_not_exists_SiteC🌑
 install_create_shortcut_windowed_SiteC🌕	uninstall_from_os_SiteC🌑	check_platform_shortcut_not_exists_SiteC🌑
 install_create_shortcut_windowed_SiteC🌕	uninstall_from_app_settings_SiteC🌕	check_platform_shortcut_not_exists_SiteC🌑
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	uninstall_from_list_SiteA🌑	check_app_not_in_list_SiteA🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	uninstall_from_list_SiteA🌑	check_app_not_in_list_SiteA🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	uninstall_from_list_SiteA🌑	check_app_not_in_list_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	uninstall_from_list_SiteA🌑	check_app_not_in_list_SiteA🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	uninstall_from_list_SiteA🌑	check_app_not_in_list_SiteA🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	uninstall_from_list_SiteA🌑	check_app_not_in_list_SiteA🌑
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	uninstall_from_list_SiteA🌕	check_app_not_in_list_SiteA🌓
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	uninstall_from_list_SiteA🌑	switch_profile_clients_Client1🌑	check_app_not_in_list_SiteA🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	uninstall_from_list_SiteA🌑	switch_profile_clients_Client1🌑	check_app_not_in_list_SiteA🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	uninstall_from_list_SiteA🌑	switch_profile_clients_Client1🌑	check_app_not_in_list_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌑	uninstall_from_list_SiteA🌑	switch_profile_clients_Client1🌑	check_app_not_in_list_SiteA🌑
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌑	uninstall_from_list_SiteA🌑	switch_profile_clients_Client1🌑	check_app_not_in_list_SiteA🌑
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌑	uninstall_from_list_SiteA🌑	switch_profile_clients_Client1🌑	check_app_not_in_list_SiteA🌑
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	uninstall_from_list_SiteA🌕	switch_profile_clients_Client1🌕	check_app_not_in_list_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	uninstall_from_list_SiteA🌕	check_app_not_in_list_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	uninstall_from_list_SiteA🌕	navigate_browser_SiteA🌕	check_install_icon_shown🌕
@@ -648,10 +656,10 @@
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_tabbed_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_tabbed_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_tabbed_SiteA🌓
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
@@ -664,18 +672,18 @@
 install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_menu_option_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_omnibox_icon_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_omnibox_icon_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_menu_option_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_menu_option_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_not_in_list_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_not_in_list_SiteA🌓
 install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_not_in_list_SiteA🌓
@@ -692,12 +700,12 @@
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
-install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌕
 install_create_shortcut_windowed_SiteA🌕	open_app_settings_from_chrome_apps_SiteA🌑	check_browser_navigation_is_app_settings_SiteA🌑	enable_run_on_os_login_SiteA🌑	check_run_on_os_login_enabled_SiteA🌑	check_app_settings_app_state_SiteA🌑
 install_omnibox_icon_SiteA🌕	open_app_settings_from_chrome_apps_SiteA🌑	check_browser_navigation_is_app_settings_SiteA🌑	enable_run_on_os_login_SiteA🌑	check_run_on_os_login_enabled_SiteA🌑	check_app_settings_app_state_SiteA🌑
 install_policy_app_windowed_no_shortcut_SiteA🌓	open_app_settings_from_chrome_apps_SiteA🌑	check_browser_navigation_is_app_settings_SiteA🌑	enable_run_on_os_login_SiteA🌑	check_run_on_os_login_enabled_SiteA🌑	check_app_settings_app_state_SiteA🌑
diff --git a/chrome/test/webapps/coverage/coverage_win.tsv b/chrome/test/webapps/coverage/coverage_win.tsv
index 1fb0a88d..2f98c8b5 100644
--- a/chrome/test/webapps/coverage/coverage_win.tsv
+++ b/chrome/test/webapps/coverage/coverage_win.tsv
@@ -1,5 +1,5 @@
 # This is a generated file.
-# Full coverage: 56%, with partial coverage: 76%
+# Full coverage: 56%, with partial coverage: 77%
 install_create_shortcut_windowed_SiteA🌕	manifest_update_title_SiteA🌑	accept_app_update_dialog🌑	close_pwa🌑	launch_from_menu_option_SiteA🌑	check_window_title_site_a_is_SiteAUpdated🌑
 install_create_shortcut_windowed_SiteA🌕	manifest_update_title_SiteA🌑	accept_app_update_dialog🌑	close_pwa🌑	launch_from_launch_icon_SiteA🌑	check_window_title_site_a_is_SiteAUpdated🌑
 install_create_shortcut_windowed_SiteA🌕	manifest_update_title_SiteA🌑	accept_app_update_dialog🌑	close_pwa🌑	launch_from_chrome_apps_SiteA🌑	check_window_title_site_a_is_SiteAUpdated🌑
@@ -58,12 +58,12 @@
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_app_in_list_windowed_SiteA🌓
-install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
 install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	check_window_created🌕
 install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	check_window_created🌕
 install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	check_window_created🌕
@@ -73,10 +73,10 @@
 install_create_shortcut_windowed_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	check_window_created🌕
-install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	check_app_in_list_tabbed_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	navigate_browser_SiteA🌕	check_install_icon_shown🌕
 install_create_shortcut_tabbed_SiteA🌕	switch_profile_clients_Client2🌕	install_locally_SiteA🌓	navigate_browser_SiteA🌕	check_launch_icon_not_shown🌕
@@ -94,20 +94,20 @@
 install_create_shortcut_windowed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	check_app_in_list_windowed_SiteC🌓
 install_create_shortcut_windowed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	navigate_browser_SiteC🌕	check_install_icon_not_shown🌕
 install_create_shortcut_windowed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	navigate_browser_SiteC🌕	check_launch_icon_shown🌕
-install_create_shortcut_windowed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌑
-install_create_shortcut_tabbed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌑
+install_create_shortcut_windowed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌓
+install_create_shortcut_tabbed_SiteC🌕	switch_profile_clients_Client2🌕	install_locally_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌓
 install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_not_exists_SiteA🌑
 install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_not_exists_SiteA🌑
 install_policy_app_windowed_no_shortcut_SiteC🌓	check_platform_shortcut_not_exists_SiteC🌑
 install_policy_app_tabbed_no_shortcut_SiteC🌓	check_platform_shortcut_not_exists_SiteC🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	check_app_in_list_windowed_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	check_app_in_list_windowed_SiteA🌓
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	check_app_in_list_windowed_SiteA🌓
@@ -185,8 +185,16 @@
 install_create_shortcut_windowed_SiteC🌕	navigate_browser_SiteC🌕	check_launch_icon_shown🌕
 install_policy_app_windowed_no_shortcut_SiteC🌓	navigate_browser_SiteC🌕	check_launch_icon_shown🌕
 install_policy_app_windowed_shortcut_SiteC🌓	navigate_browser_SiteC🌕	check_launch_icon_shown🌕
-install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteC🌑
+install_policy_app_windowed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_shortcut_SiteA🌓	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_windowed_shortcut_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌓
+install_policy_app_tabbed_shortcut_SiteC🌓	check_platform_shortcut_and_icon_SiteC🌓
+install_create_shortcut_windowed_SiteC🌕	check_platform_shortcut_and_icon_SiteC🌓
+install_create_shortcut_tabbed_SiteC🌕	check_platform_shortcut_and_icon_SiteC🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
@@ -648,10 +656,10 @@
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_tabbed_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_tabbed_SiteA🌓
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_tabbed_SiteA🌓
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
@@ -664,18 +672,18 @@
 install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_menu_option_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
 install_policy_app_windowed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_not_in_list_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_not_in_list_SiteA🌓
 install_policy_app_windowed_shortcut_SiteA🌓	uninstall_policy_app_SiteA🌕	check_app_not_in_list_SiteA🌓
@@ -692,12 +700,12 @@
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
 install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_app_in_list_windowed_SiteA🌓
-install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌑
+install_policy_app_tabbed_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_create_shortcut_windowed_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_omnibox_icon_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
+install_policy_app_tabbed_no_shortcut_SiteA🌓	install_menu_option_SiteA🌕	uninstall_policy_app_SiteA🌕	check_platform_shortcut_and_icon_SiteA🌓
 install_create_shortcut_windowed_SiteA🌕	open_app_settings_from_chrome_apps_SiteA🌑	check_browser_navigation_is_app_settings_SiteA🌑	enable_run_on_os_login_SiteA🌑	check_run_on_os_login_enabled_SiteA🌑	check_app_settings_app_state_SiteA🌑
 install_omnibox_icon_SiteA🌕	open_app_settings_from_chrome_apps_SiteA🌑	check_browser_navigation_is_app_settings_SiteA🌑	enable_run_on_os_login_SiteA🌑	check_run_on_os_login_enabled_SiteA🌑	check_app_settings_app_state_SiteA🌑
 install_policy_app_windowed_no_shortcut_SiteA🌓	open_app_settings_from_chrome_apps_SiteA🌑	check_browser_navigation_is_app_settings_SiteA🌑	enable_run_on_os_login_SiteA🌑	check_run_on_os_login_enabled_SiteA🌑	check_app_settings_app_state_SiteA🌑
diff --git a/chrome/test/webapps/data/actions.csv b/chrome/test/webapps/data/actions.csv
index 253200d..f8a20796 100644
--- a/chrome/test/webapps/data/actions.csv
+++ b/chrome/test/webapps/data/actions.csv
@@ -5,7 +5,7 @@
 clear_app_badge,SiteA* | SiteB,,4,,,,,Awaiting Platform Integration,The WebApp clears the 'badge' value from it's icon,
 drag_url_to_apps_list,,,5,,,,,Awaiting Platform Integration,"Open chrome://apps in a separage window, and drag a url (highlight & drag url from the omnibox) to the chrome://apps page",
 set_app_badge,SiteA* | SiteB,,6,,,,,Awaiting Platform Integration,Set the app badge for the given site to a value.,
-check_platform_shortcut_and_icon,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,,7,,,,,Awaiting Script Processing,The icon of the platform shortcut (on the desktop) is correct,"cliffordcheng@, doc"
+check_platform_shortcut_and_icon,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,,7,,,,,Implemented,The icon of the platform shortcut (on the desktop) is correct,"cliffordcheng@, doc"
 manifest_update_scope_site_a_foo_to,SiteA* | SiteAFoo | SiteABar,,8,,,,,Awaiting Script Processing,"Update the scope of site a/foo/, to the given scope",
 navigate_pwa_site_a_foo_to,SiteA* | SiteAFoo | SiteABar | SiteB,,9,,,,,Awaiting Script Processing,Navigates the PWA window of the SiteAFoo pwa to a given site.,
 uninstall_from_list,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,,10,,,,,Implemented,"Uninstall the webapp from wherever apps are listed by chrome. On WML, this is from chrome://apps, and on ChromeOS, this is from the 'launcher'",
@@ -71,10 +71,10 @@
 manifest_update_display_browser,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,,70,,,,,Implemented,Updates the display property of the manifest to 'browser' on the given site's manifest,"cliffordcheng@, P1"
 check_tab_not_created,,,94,,,,,Implemented,A tab was not created by the last state change action,"cliffordcheng@, P1"
 open_in_chrome,,,71,,,,,Implemented,Click on the 'open in chrome' link in the 3-dot menu of the app window,"cliffordcheng@, P1"
-create_shortcuts,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,,72,,,,,Not Yet Implemented,create shortcut in app list,P2
+create_shortcuts,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,,72,,,,,Not Yet Implemented,"""create shortcuts"" in chrome://apps",P2
 switch_incognito_profile,,,73,,,,,Not Yet Implemented,Switch to using incognito mode,P2
 delete_platform_shortcut,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,,74,,,,,Not Yet Implemented,Delete the shortcut that lives on the operating system,P2
-check_app_in_list_icon_correct,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,,75,,,,,Not Yet Implemented,"Find the app in the app list (on desktop, this is chrome://apps, and on ChromeOS, this is the app drawer). Check that the icon for the given app in the app list is correct.",P3
+check_app_in_list_icon_correct,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,,75,,,,,Not Yet Implemented,"Find the app in the app list (on desktop, this is chrome://apps, and on ChromeOS, this is the app drawer). Check that the icon for the given app in the app list is correct.",P2 (dmurph modified - should be easy to fetch icon using web request for chrome://app-icon/<app-id>/<dip> I believe)
 check_theme_color,SiteA* | SiteAFoo | SiteABar | SiteB,,76,,,,,Not Yet Implemented,Asserts that the theme color of the given app window is correct.,P3
 check_window_color_correct,,,77,,,,,Not Yet Implemented,The color of the window is correct.,P3
 check_window_icon_correct,,,78,,,,,Not Yet Implemented,,P3
diff --git a/chrome/test/webapps/data/coverage_required.csv b/chrome/test/webapps/data/coverage_required.csv
index 09fb430e..3ffb07ab 100644
--- a/chrome/test/webapps/data/coverage_required.csv
+++ b/chrome/test/webapps/data/coverage_required.csv
@@ -49,8 +49,8 @@
 WMLC,,install_windowed(SiteC),check_create_shortcut_not_shown,install_windowed(SiteC),navigate_browser(SiteC),check_create_shortcut_not_shown,,,,,
 WMLC,,install_windowed(SiteC),check_install_icon_not_shown,install_windowed(SiteC),navigate_browser(SiteC),check_install_icon_not_shown,,,,,
 WMLC,,install_windowed(SiteC),check_launch_icon_shown,install_windowed(SiteC),navigate_browser(SiteC),check_launch_icon_shown,,,,,
-WMLC,,install_with_shortcut,check_platform_shortcut_and_icon,install_policy_app_windowed_shortcut,check_platform_shortcut_and_icon,,,,,,
-WMLC,,install_with_shortcut(SiteC),check_platform_shortcut_and_icon(SiteC),install_policy_app_windowed_shortcut,check_platform_shortcut_and_icon(SiteC),,,,,,
+WMLC,,install_with_shortcut,check_platform_shortcut_and_icon,install_with_shortcut,check_platform_shortcut_and_icon,,,,,,
+WMLC,,install_with_shortcut(SiteC),check_platform_shortcut_and_icon(SiteC),install_with_shortcut(SiteC),check_platform_shortcut_and_icon(SiteC),,,,,,
 WMLC,install_by_user_windowed & install_policy_app_tabbed,launch,check_window_created,install_by_user_windowed,install_policy_app_tabbed,launch,check_window_created,,,,
 WMLC,install_by_user_windowed & manifest_update_colors,launch,check_window_color_correct,install_by_user_windowed,close_pwa,manifest_update_colors,launch,check_window_color_correct,,,
 WMLC,install_by_user_windowed & manifest_update_display_browser,launch,check_tab_not_created,install_by_user_windowed,close_pwa,manifest_update_display_browser,launch,check_tab_not_created,,,
diff --git a/chrome/test/webapps/data/framework_supported_actions.csv b/chrome/test/webapps/data/framework_supported_actions.csv
index 8f7d889d..5d4a4fd 100644
--- a/chrome/test/webapps/data/framework_supported_actions.csv
+++ b/chrome/test/webapps/data/framework_supported_actions.csv
@@ -4,15 +4,16 @@
 check_app_in_list_windowed,                            🌓, 🌓,  🌓,   🌓,
 check_app_list_empty,                                  🌓, 🌓,  🌓,   🌓,
 check_app_not_in_list,                                 🌓, 🌓,  🌓,   🌓,
+check_custom_toolbar,                                  🌕, 🌕,  🌕,   🌕,
 check_install_icon_not_shown,                          🌕, 🌕,  🌕,   🌕,
 check_install_icon_shown,                              🌕, 🌕,  🌕,   🌕,
 check_launch_icon_not_shown,                           🌕, 🌕,  🌕,   🌕,
 check_launch_icon_shown,                               🌕, 🌕,  🌕,   🌕,
 check_app_navigation_is_start_url,                     🌕, 🌕,  🌕,   🌕,
 check_no_toolbar,                                      🌕, 🌕,  🌕,   🌕,
+check_platform_shortcut_and_icon,                      🌕, 🌓,  🌓,   🌓,
 check_tab_created,                                     🌕, 🌕,  🌕,   🌕,
 check_tab_not_created,                                 🌕, 🌕,  🌕,   🌕,
-check_custom_toolbar,                                  🌕, 🌕,  🌕,   🌕,
 check_window_closed,                                   🌕, 🌕,  🌕,   🌕,
 check_window_created,                                  🌕, 🌕,  🌕,   🌕,
 check_window_display_minimal,                          🌕, 🌕,  🌕,   🌕,
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd
index 3b4f23a..27e15290 100644
--- a/chromeos/chromeos_strings.grd
+++ b/chromeos/chromeos_strings.grd
@@ -2665,8 +2665,8 @@
       <message name="IDS_SHIMLESS_RMA_PROVISIONING_TITLE" translateable="false" desc="Title for the device provisioning page. Provisioning is when component specific data is set e.g. erasing fingerprint data from the thumb reader or regenerating the device stable secret before returning the device to a new owner.">
         Provisioning the device...
       </message>
-      <message name="IDS_SHIMLESS_RMA_PROVISIONING_PROGRESS" translateable="false" desc="Message to display current progress of provisioning.">
-        Progress <ph name="PROGRESS_PERCENT">$1<ex>25</ex></ph>%.
+      <message name="IDS_SHIMLESS_RMA_PROVISIONING_IN_PROGRESS" translateable="false" desc="Message to display while the device is provisioning.">
+        Provisioning the device. Do not turn off the power.
       </message>
       <message name="IDS_SHIMLESS_RMA_PROVISIONING_COMPLETE" translateable="false" desc="Message to display when provisioning is complete.">
         Complete.
diff --git a/chromeos/dbus/fwupd/fwupd_client.cc b/chromeos/dbus/fwupd/fwupd_client.cc
index 2016e88..fc9a02a 100644
--- a/chromeos/dbus/fwupd/fwupd_client.cc
+++ b/chromeos/dbus/fwupd/fwupd_client.cc
@@ -268,17 +268,39 @@
         sha_checksum = ParseCheckSum(checksum->GetString());
       }
 
-      const bool success = version && description && priority &&
-                           !filepath.empty() && !sha_checksum.empty();
+      std::string description_value = "";
+
+      if (description) {
+        description_value = description->GetString();
+      } else {
+        VLOG(1) << "Device: " << device_id
+                << " is missing its description text.";
+      }
+
+      const bool success =
+          version && priority && !filepath.empty() && !sha_checksum.empty();
       // TODO(michaelcheco): Confirm that this is the expected behavior.
       if (success) {
         VLOG(1) << "fwupd: Found update version for device: " << device_id
                 << " with version: " << version->GetString();
-        updates.emplace_back(version->GetString(), description->GetString(),
+        updates.emplace_back(version->GetString(), description_value,
                              priority->GetInt(), filepath, sha_checksum);
       } else {
-        LOG(ERROR) << "Update version, description, filepath, checksum or "
-                   << "priority is not found.";
+        if (!version) {
+          LOG(ERROR) << "Device: " << device_id
+                     << " is missing its version field.";
+        }
+        if (!priority) {
+          LOG(ERROR) << "Device: " << device_id
+                     << " is missing its priority field.";
+        }
+        if (!uri) {
+          LOG(ERROR) << "Device: " << device_id << " is missing its URI field.";
+        }
+        if (!checksum) {
+          LOG(ERROR) << "Device: " << device_id
+                     << " is missing its checksum field.";
+        }
       }
     }
 
diff --git a/chromeos/dbus/fwupd/fwupd_client_unittest.cc b/chromeos/dbus/fwupd/fwupd_client_unittest.cc
index ec2f310b..22f5ee8 100644
--- a/chromeos/dbus/fwupd/fwupd_client_unittest.cc
+++ b/chromeos/dbus/fwupd/fwupd_client_unittest.cc
@@ -139,6 +139,7 @@
     dict_writer.AppendString(kDescriptionKey);
     dict_writer.AppendVariantOfString(kFakeUpdateDescriptionForTesting);
     device_array_writer.CloseContainer(&dict_writer);
+    SetExpectedDescription(kFakeUpdateDescriptionForTesting);
 
     device_array_writer.OpenDictEntry(&dict_writer);
     dict_writer.AppendString(kVersionKey);
@@ -166,6 +167,46 @@
     return response;
   }
 
+  std::unique_ptr<dbus::Response> CreateOneUpdateResponseWithNoDescription() {
+    auto response = dbus::Response::CreateEmpty();
+
+    dbus::MessageWriter response_writer(response.get());
+    dbus::MessageWriter response_array_writer(nullptr);
+    dbus::MessageWriter device_array_writer(nullptr);
+    dbus::MessageWriter dict_writer(nullptr);
+
+    // The response is an array of arrays of dictionaries. Each dictionary is
+    // one device description.
+    response_writer.OpenArray("a{sv}", &response_array_writer);
+    response_array_writer.OpenArray("{sv}", &device_array_writer);
+
+    device_array_writer.OpenDictEntry(&dict_writer);
+    dict_writer.AppendString(kVersionKey);
+    dict_writer.AppendVariantOfString(kFakeUpdateVersionForTesting);
+    device_array_writer.CloseContainer(&dict_writer);
+
+    device_array_writer.OpenDictEntry(&dict_writer);
+    dict_writer.AppendString(kPriorityKey);
+    dict_writer.AppendVariantOfUint32(kFakeUpdatePriorityForTesting);
+    device_array_writer.CloseContainer(&dict_writer);
+
+    device_array_writer.OpenDictEntry(&dict_writer);
+    dict_writer.AppendString(kUriKey);
+    dict_writer.AppendVariantOfString(kFakeUpdateUriForTesting);
+    device_array_writer.CloseContainer(&dict_writer);
+
+    device_array_writer.OpenDictEntry(&dict_writer);
+    dict_writer.AppendString(kChecksumKey);
+    dict_writer.AppendVariantOfString(kFakeSha256ForTesting);
+    device_array_writer.CloseContainer(&dict_writer);
+    SetExpectedChecksum(kFakeSha256ForTesting);
+
+    response_array_writer.CloseContainer(&device_array_writer);
+    response_writer.CloseContainer(&response_array_writer);
+
+    return response;
+  }
+
   void CheckDevices(FwupdDeviceList* devices) {
     CHECK_EQ(kFakeDeviceNameForTesting, (*devices)[0].device_name);
     CHECK_EQ(kFakeDeviceIdForTesting, (*devices)[0].id);
@@ -179,7 +220,7 @@
 
     CHECK_EQ(kFakeDeviceIdForTesting, device_id);
     CHECK_EQ(kFakeUpdateVersionForTesting, (*updates)[0].version);
-    CHECK_EQ(kFakeUpdateDescriptionForTesting, (*updates)[0].description);
+    CHECK_EQ(expected_description_, (*updates)[0].description);
     // This value is returned by DBus as a uint32_t and is added to a dictionary
     // that doesn't support unsigned numbers. So it needs to be casted to int.
     CHECK_EQ(static_cast<int>(kFakeUpdatePriorityForTesting),
@@ -196,6 +237,10 @@
     expected_checksum_ = checksum;
   }
 
+  void SetExpectedDescription(const std::string& description) {
+    expected_description_ = description;
+  }
+
   void SetExpectNoUpdates(bool no_updates) { expect_no_updates_ = no_updates; }
 
   void CheckPropertyChanged(FwupdProperties* properties) {
@@ -269,6 +314,7 @@
   bool expect_no_updates_ = false;
 
   std::string expected_checksum_;
+  std::string expected_description_;
 };
 
 // TODO (swifton): Rewrite this test with an observer when it's available.
@@ -350,6 +396,7 @@
   dict_writer.AppendString(kDescriptionKey);
   dict_writer.AppendVariantOfString(kFakeUpdateDescriptionForTesting);
   device_array_writer.CloseContainer(&dict_writer);
+  SetExpectedDescription(kFakeUpdateDescriptionForTesting);
 
   device_array_writer.OpenDictEntry(&dict_writer);
   dict_writer.AppendString(kVersionKey);
@@ -542,4 +589,25 @@
   GetProperties()->status.ReplaceValue(expected_status);
 }
 
+TEST_F(FwupdClientTest, NoDescription) {
+  // The observer will check that the update description is parsed and passed
+  // correctly.
+  MockObserver observer;
+  EXPECT_CALL(observer, OnUpdateListResponse(_, _))
+      .Times(1)
+      .WillRepeatedly(Invoke(this, &FwupdClientTest::CheckUpdates));
+  fwupd_client_->AddObserver(&observer);
+
+  EXPECT_CALL(*proxy_, DoCallMethodWithErrorResponse(_, _, _))
+      .WillRepeatedly(Invoke(this, &FwupdClientTest::OnMethodCalled));
+
+  AddDbusMethodCallResultSimulation(CreateOneUpdateResponseWithNoDescription(),
+                                    nullptr);
+  SetExpectedDescription("");
+
+  fwupd_client_->RequestUpdates(kFakeDeviceIdForTesting);
+
+  base::RunLoop().RunUntilIdle();
+}
+
 }  // namespace chromeos
diff --git a/chromeos/dbus/rmad/rmad_client.cc b/chromeos/dbus/rmad/rmad_client.cc
index ce2f7b5..79a0a3c 100644
--- a/chromeos/dbus/rmad/rmad_client.cc
+++ b/chromeos/dbus/rmad/rmad_client.cc
@@ -218,25 +218,25 @@
 void RmadClientImpl::CalibrationOverallProgressReceived(dbus::Signal* signal) {
   DCHECK_EQ(signal->GetMember(), rmad::kCalibrationOverallSignal);
   dbus::MessageReader reader(signal);
-  uint32_t overall_progress;
-  if (!reader.PopUint32(&overall_progress)) {
-    LOG(ERROR) << "Unable to decode overall progress uint32 from "
+  int32_t overall_progress_status;
+  if (!reader.PopInt32(&overall_progress_status)) {
+    LOG(ERROR) << "Unable to decode overall progress status int32 from "
                << signal->GetMember() << " signal";
     return;
   }
   DCHECK(!reader.HasMoreData());
   for (auto& observer : observers_) {
     observer.CalibrationOverallProgress(
-        static_cast<rmad::CalibrationOverallStatus>(overall_progress));
+        static_cast<rmad::CalibrationOverallStatus>(overall_progress_status));
   }
 }
 
 void RmadClientImpl::ErrorReceived(dbus::Signal* signal) {
   DCHECK_EQ(signal->GetMember(), rmad::kErrorSignal);
   dbus::MessageReader reader(signal);
-  uint32_t error;
-  if (!reader.PopUint32(&error)) {
-    LOG(ERROR) << "Unable to decode error uint32 from " << signal->GetMember()
+  int32_t error;
+  if (!reader.PopInt32(&error)) {
+    LOG(ERROR) << "Unable to decode error int32 from " << signal->GetMember()
                << " signal";
     return;
   }
diff --git a/chromeos/dbus/rmad/rmad_client_unittest.cc b/chromeos/dbus/rmad/rmad_client_unittest.cc
index d44951f..c8cb298 100644
--- a/chromeos/dbus/rmad/rmad_client_unittest.cc
+++ b/chromeos/dbus/rmad/rmad_client_unittest.cc
@@ -106,7 +106,7 @@
   // Passes an error signal to |client_|.
   void EmitErrorSignal(rmad::RmadErrorCode error) {
     dbus::Signal signal(rmad::kRmadInterfaceName, rmad::kErrorSignal);
-    dbus::MessageWriter(&signal).AppendUint32(static_cast<uint32_t>(error));
+    dbus::MessageWriter(&signal).AppendInt32(static_cast<int32_t>(error));
     EmitSignal(&signal);
   }
 
@@ -132,7 +132,7 @@
       rmad::CalibrationOverallStatus status) {
     dbus::Signal signal(rmad::kRmadInterfaceName,
                         rmad::kCalibrationOverallSignal);
-    dbus::MessageWriter(&signal).AppendUint32(static_cast<uint32_t>(status));
+    dbus::MessageWriter(&signal).AppendInt32(static_cast<int32_t>(status));
     EmitSignal(&signal);
   }
 
diff --git a/chromeos/network/cellular_esim_uninstall_handler_unittest.cc b/chromeos/network/cellular_esim_uninstall_handler_unittest.cc
index 6b434c4..d0783239 100644
--- a/chromeos/network/cellular_esim_uninstall_handler_unittest.cc
+++ b/chromeos/network/cellular_esim_uninstall_handler_unittest.cc
@@ -79,6 +79,7 @@
                                          cellular_inhibitor_.get());
     managed_cellular_pref_handler_ =
         std::make_unique<ManagedCellularPrefHandler>();
+    managed_cellular_pref_handler_->Init(network_state_handler_.get());
     ManagedCellularPrefHandler::RegisterLocalStatePrefs(
         device_prefs_.registry());
     managed_cellular_pref_handler_->SetDevicePrefs(&device_prefs_);
diff --git a/chromeos/network/cellular_policy_handler_unittest.cc b/chromeos/network/cellular_policy_handler_unittest.cc
index 55f45a8..f3fdae84 100644
--- a/chromeos/network/cellular_policy_handler_unittest.cc
+++ b/chromeos/network/cellular_policy_handler_unittest.cc
@@ -140,6 +140,7 @@
             /*UIProxyConfigService=*/nullptr);
     managed_cellular_pref_handler_ =
         std::make_unique<ManagedCellularPrefHandler>();
+    managed_cellular_pref_handler_->Init(network_state_handler_.get());
     ManagedCellularPrefHandler::RegisterLocalStatePrefs(
         device_prefs_.registry());
     managed_cellular_pref_handler_->SetDevicePrefs(&device_prefs_);
diff --git a/chromeos/network/fake_stub_cellular_networks_provider.cc b/chromeos/network/fake_stub_cellular_networks_provider.cc
index f34774b..e031ffa 100644
--- a/chromeos/network/fake_stub_cellular_networks_provider.cc
+++ b/chromeos/network/fake_stub_cellular_networks_provider.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 
+#include "base/containers/contains.h"
 #include "base/guid.h"
 #include "chromeos/network/cellular_utils.h"
 
@@ -16,13 +17,17 @@
 FakeStubCellularNetworksProvider::~FakeStubCellularNetworksProvider() = default;
 
 void FakeStubCellularNetworksProvider::AddStub(const std::string& stub_iccid,
-                                               const std::string& stub_eid) {
+                                               const std::string& stub_eid,
+                                               bool is_managed) {
   stub_iccid_and_eid_pairs_.emplace(stub_iccid, stub_eid);
+  if (is_managed)
+    managed_iccids_.insert(stub_iccid);
 }
 
 void FakeStubCellularNetworksProvider::RemoveStub(const std::string& stub_iccid,
                                                   const std::string& stub_eid) {
   stub_iccid_and_eid_pairs_.erase(std::make_pair(stub_iccid, stub_eid));
+  managed_iccids_.erase(stub_iccid);
 }
 
 bool FakeStubCellularNetworksProvider::AddOrRemoveStubCellularNetworks(
@@ -39,7 +44,8 @@
     changed = true;
     for (const IccidEidPair& pair : stubs_to_add) {
       new_stub_networks.push_back(NetworkState::CreateNonShillCellularNetwork(
-          pair.first, pair.second, GetGuidForStubIccid(pair.first), device));
+          pair.first, pair.second, GetGuidForStubIccid(pair.first),
+          base::Contains(managed_iccids_, pair.first), device));
       stub_networks_add_count_++;
     }
   }
diff --git a/chromeos/network/fake_stub_cellular_networks_provider.h b/chromeos/network/fake_stub_cellular_networks_provider.h
index 7ca37a1..2485c68 100644
--- a/chromeos/network/fake_stub_cellular_networks_provider.h
+++ b/chromeos/network/fake_stub_cellular_networks_provider.h
@@ -25,7 +25,8 @@
   // used when a subsequent call to AddOrRemoveStubCellularNetworks() is made.
   // Note that an empty EID refers to a pSIM network.
   void AddStub(const std::string& stub_iccid,
-               const std::string& eid = std::string());
+               const std::string& eid = std::string(),
+               bool is_managed = false);
 
   // Removes a stub network with the provided ICCID and EID, reversing a
   // previous call to AddStub().
@@ -54,6 +55,7 @@
   size_t stub_networks_add_count_ = 0;
   base::flat_set<IccidEidPair> stub_iccid_and_eid_pairs_;
   base::flat_map<std::string, std::string> iccid_to_guid_map_;
+  base::flat_set<std::string> managed_iccids_;
 };
 
 }  // namespace chromeos
diff --git a/chromeos/network/managed_cellular_pref_handler.cc b/chromeos/network/managed_cellular_pref_handler.cc
index 659fb6b..dd4eae7 100644
--- a/chromeos/network/managed_cellular_pref_handler.cc
+++ b/chromeos/network/managed_cellular_pref_handler.cc
@@ -6,6 +6,7 @@
 
 #include "ash/constants/ash_pref_names.h"
 #include "chromeos/network/network_event_log.h"
+#include "chromeos/network/network_state_handler.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "services/preferences/public/cpp/dictionary_value_update.h"
 #include "services/preferences/public/cpp/scoped_pref_update.h"
@@ -21,6 +22,11 @@
 ManagedCellularPrefHandler::ManagedCellularPrefHandler() = default;
 ManagedCellularPrefHandler::~ManagedCellularPrefHandler() = default;
 
+void ManagedCellularPrefHandler::Init(
+    NetworkStateHandler* network_state_handler) {
+  network_state_handler_ = network_state_handler;
+}
+
 void ManagedCellularPrefHandler::SetDevicePrefs(PrefService* device_prefs) {
   device_prefs_ = device_prefs;
 }
@@ -41,6 +47,7 @@
   ::prefs::ScopedDictionaryPrefUpdate update(
       device_prefs_, ash::prefs::kManagedCellularIccidSmdpPair);
   update->SetString(iccid, smdp_address);
+  network_state_handler_->SyncStubCellularNetworks();
 }
 
 void ManagedCellularPrefHandler::RemovePairWithIccid(const std::string& iccid) {
@@ -57,6 +64,7 @@
   ::prefs::ScopedDictionaryPrefUpdate update(
       device_prefs_, ash::prefs::kManagedCellularIccidSmdpPair);
   update->Remove(iccid);
+  network_state_handler_->SyncStubCellularNetworks();
 }
 
 const std::string* ManagedCellularPrefHandler::GetSmdpAddressFromIccid(
diff --git a/chromeos/network/managed_cellular_pref_handler.h b/chromeos/network/managed_cellular_pref_handler.h
index 97e0506a..fd0d30a 100644
--- a/chromeos/network/managed_cellular_pref_handler.h
+++ b/chromeos/network/managed_cellular_pref_handler.h
@@ -13,6 +13,8 @@
 
 namespace chromeos {
 
+class NetworkStateHandler;
+
 // This class provides the ability to add, remove and get ICCID and SMDP+
 // address pair for managed cellular networks and stores it persistently in
 // prefs.
@@ -26,6 +28,7 @@
 
   static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
 
+  void Init(NetworkStateHandler* network_state_handler);
   void SetDevicePrefs(PrefService* device_prefs);
 
   // Add a new ICCID and SMDP+ address pair to device pref for a managed
@@ -42,6 +45,7 @@
   const std::string* GetSmdpAddressFromIccid(const std::string& iccid) const;
 
  private:
+  NetworkStateHandler* network_state_handler_ = nullptr;
   // Initialized to null and set once SetDevicePrefs() is called.
   PrefService* device_prefs_ = nullptr;
 };
diff --git a/chromeos/network/managed_cellular_pref_handler_unittest.cc b/chromeos/network/managed_cellular_pref_handler_unittest.cc
index f636051..44d40c3 100644
--- a/chromeos/network/managed_cellular_pref_handler_unittest.cc
+++ b/chromeos/network/managed_cellular_pref_handler_unittest.cc
@@ -34,6 +34,7 @@
   void Init() {
     managed_cellular_pref_handler_ =
         std::make_unique<ManagedCellularPrefHandler>();
+    managed_cellular_pref_handler_->Init(helper_.network_state_handler());
   }
 
   void SetDevicePrefs(bool set_to_null = false) {
@@ -57,6 +58,7 @@
  private:
   base::test::TaskEnvironment task_environment_{
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+  NetworkStateTestHelper helper_{/*use_default_devices_and_services=*/false};
   TestingPrefServiceSimple device_prefs_;
 
   std::unique_ptr<ManagedCellularPrefHandler> managed_cellular_pref_handler_;
diff --git a/chromeos/network/managed_network_configuration_handler_unittest.cc b/chromeos/network/managed_network_configuration_handler_unittest.cc
index d4db1e1..c7451d31 100644
--- a/chromeos/network/managed_network_configuration_handler_unittest.cc
+++ b/chromeos/network/managed_network_configuration_handler_unittest.cc
@@ -182,6 +182,7 @@
 
     managed_cellular_pref_handler_ =
         std::make_unique<ManagedCellularPrefHandler>();
+    managed_cellular_pref_handler_->Init(network_state_handler_.get());
     ManagedCellularPrefHandler::RegisterLocalStatePrefs(
         device_prefs_.registry());
     managed_cellular_pref_handler_->SetDevicePrefs(&device_prefs_);
diff --git a/chromeos/network/network_connection_handler_impl_unittest.cc b/chromeos/network/network_connection_handler_impl_unittest.cc
index 03e603d..d85ccb1a 100644
--- a/chromeos/network/network_connection_handler_impl_unittest.cc
+++ b/chromeos/network/network_connection_handler_impl_unittest.cc
@@ -212,7 +212,8 @@
     stub_cellular_networks_provider_ =
         std::make_unique<StubCellularNetworksProvider>();
     stub_cellular_networks_provider_->Init(
-        helper_.network_state_handler(), cellular_esim_profile_handler_.get());
+        helper_.network_state_handler(), cellular_esim_profile_handler_.get(),
+        /*managed_cellular_pref_handler=*/nullptr);
 
     cellular_connection_handler_.reset(new CellularConnectionHandler());
     cellular_connection_handler_->Init(helper_.network_state_handler(),
diff --git a/chromeos/network/network_handler.cc b/chromeos/network/network_handler.cc
index 3da0b75..3be0dca 100644
--- a/chromeos/network/network_handler.cc
+++ b/chromeos/network/network_handler.cc
@@ -89,7 +89,8 @@
   cellular_esim_profile_handler_->Init(network_state_handler_.get(),
                                        cellular_inhibitor_.get());
   stub_cellular_networks_provider_->Init(network_state_handler_.get(),
-                                         cellular_esim_profile_handler_.get());
+                                         cellular_esim_profile_handler_.get(),
+                                         managed_cellular_pref_handler_.get());
   cellular_connection_handler_->Init(network_state_handler_.get(),
                                      cellular_inhibitor_.get(),
                                      cellular_esim_profile_handler_.get());
@@ -120,6 +121,7 @@
         network_profile_handler_.get(), network_state_handler_.get(),
         managed_cellular_pref_handler_.get(),
         managed_network_configuration_handler_.get());
+    managed_cellular_pref_handler_->Init(network_state_handler_.get());
     esim_policy_login_metrics_logger_->Init(
         network_state_handler_.get(),
         managed_network_configuration_handler_.get());
diff --git a/chromeos/network/network_state.cc b/chromeos/network/network_state.cc
index 2067a60..38543c4 100644
--- a/chromeos/network/network_state.cc
+++ b/chromeos/network/network_state.cc
@@ -622,6 +622,7 @@
     const std::string& iccid,
     const std::string& eid,
     const std::string& guid,
+    bool is_managed,
     const DeviceState* cellular_device) {
   std::string path = GenerateStubCellularServicePath(iccid);
   auto new_state = std::make_unique<NetworkState>(path);
@@ -632,6 +633,9 @@
   new_state->iccid_ = iccid;
   new_state->eid_ = eid;
   new_state->guid_ = guid;
+  if (is_managed) {
+    new_state->onc_source_ = ::onc::ONCSource::ONC_SOURCE_DEVICE_POLICY;
+  }
   new_state->activation_state_ = shill::kActivationStateActivated;
   return new_state;
 }
diff --git a/chromeos/network/network_state.h b/chromeos/network/network_state.h
index c843211..c09f05a06 100644
--- a/chromeos/network/network_state.h
+++ b/chromeos/network/network_state.h
@@ -283,6 +283,7 @@
       const std::string& iccid,
       const std::string& eid,
       const std::string& guid,
+      bool is_managed,
       const DeviceState* cellular_device);
 
   // Ignore changes to signal strength less than this value.
diff --git a/chromeos/network/network_state_handler_unittest.cc b/chromeos/network/network_state_handler_unittest.cc
index 2791278..b97f24c 100644
--- a/chromeos/network/network_state_handler_unittest.cc
+++ b/chromeos/network/network_state_handler_unittest.cc
@@ -2203,6 +2203,7 @@
   ASSERT_TRUE(cellular);
   EXPECT_FALSE(cellular->guid().empty());
   EXPECT_TRUE(cellular->IsNonShillCellularNetwork());
+  EXPECT_FALSE(cellular->IsManagedByPolicy());
   EXPECT_EQ(kStubCellularIccid, cellular->iccid());
   EXPECT_EQ(1u, test_observer_->network_list_changed_count());
 
@@ -2227,6 +2228,31 @@
   EXPECT_EQ(1u, test_observer_->network_list_changed_count());
 }
 
+TEST_F(NetworkStateHandlerTest, SyncManagedStubCellularNetworks) {
+  const char kStubCellularIccid[] = "test_iccid";
+  const char kStubCellularEid[] = "1234567890";
+  // Clear existing cellular networks.
+  service_test_->RemoveService(kShillManagerClientStubCellular);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(
+      network_state_handler_->GetNetworkState(kShillManagerClientStubCellular));
+
+  test_observer_->reset_change_counts();
+  fake_stub_cellular_networks_provider_.AddStub(
+      kStubCellularIccid, kStubCellularEid, /*is_managed=*/true);
+
+  // Verify that managed stub cellular network was added and notified.
+  network_state_handler_->SyncStubCellularNetworks();
+  const NetworkState* cellular = network_state_handler_->FirstNetworkByType(
+      NetworkTypePattern::Cellular());
+  ASSERT_TRUE(cellular);
+  EXPECT_FALSE(cellular->guid().empty());
+  EXPECT_TRUE(cellular->IsNonShillCellularNetwork());
+  EXPECT_TRUE(cellular->IsManagedByPolicy());
+  EXPECT_EQ(kStubCellularIccid, cellular->iccid());
+  EXPECT_EQ(1u, test_observer_->network_list_changed_count());
+}
+
 TEST_F(NetworkStateHandlerTest,
        SyncStubCellularNetworks_ManagedStateListChange) {
   const char kTestCellularServicePath1[] = "test_cellular_service_path1";
diff --git a/chromeos/network/network_state_unittest.cc b/chromeos/network/network_state_unittest.cc
index d98d11a..9b19ec9 100644
--- a/chromeos/network/network_state_unittest.cc
+++ b/chromeos/network/network_state_unittest.cc
@@ -459,16 +459,31 @@
 
   std::unique_ptr<NetworkState> non_shill_cellular =
       NetworkState::CreateNonShillCellularNetwork(
-          kTestIccid, kTestEid, kTestGuid, GetCellularDevice());
+          kTestIccid, kTestEid, kTestGuid, /*is_managed=*/false,
+          GetCellularDevice());
   EXPECT_EQ(kTestIccid, non_shill_cellular->iccid());
   EXPECT_EQ(kTestEid, non_shill_cellular->eid());
   EXPECT_EQ(kTestGuid, non_shill_cellular->guid());
+  EXPECT_FALSE(non_shill_cellular->IsManagedByPolicy());
 
   base::Value dictionary(base::Value::Type::DICTIONARY);
   non_shill_cellular->GetStateProperties(&dictionary);
   EXPECT_EQ(kTestIccid, *dictionary.FindStringKey(shill::kIccidProperty));
   EXPECT_EQ(kTestEid, *dictionary.FindStringKey(shill::kEidProperty));
   EXPECT_EQ(kTestGuid, *dictionary.FindStringKey(shill::kGuidProperty));
+
+  non_shill_cellular = NetworkState::CreateNonShillCellularNetwork(
+      kTestIccid, kTestEid, kTestGuid, /*is_managed=*/true,
+      GetCellularDevice());
+  EXPECT_EQ(kTestIccid, non_shill_cellular->iccid());
+  EXPECT_EQ(kTestEid, non_shill_cellular->eid());
+  EXPECT_EQ(kTestGuid, non_shill_cellular->guid());
+  EXPECT_TRUE(non_shill_cellular->IsManagedByPolicy());
+
+  non_shill_cellular->GetStateProperties(&dictionary);
+  EXPECT_EQ(kTestIccid, *dictionary.FindStringKey(shill::kIccidProperty));
+  EXPECT_EQ(kTestEid, *dictionary.FindStringKey(shill::kEidProperty));
+  EXPECT_EQ(kTestGuid, *dictionary.FindStringKey(shill::kGuidProperty));
 }
 
 }  // namespace chromeos
diff --git a/chromeos/network/stub_cellular_networks_provider.cc b/chromeos/network/stub_cellular_networks_provider.cc
index 2aec8df8..9730437 100644
--- a/chromeos/network/stub_cellular_networks_provider.cc
+++ b/chromeos/network/stub_cellular_networks_provider.cc
@@ -10,6 +10,7 @@
 #include "chromeos/network/cellular_esim_profile_handler.h"
 #include "chromeos/network/cellular_utils.h"
 #include "chromeos/network/device_state.h"
+#include "chromeos/network/managed_cellular_pref_handler.h"
 #include "chromeos/network/network_event_log.h"
 
 namespace chromeos {
@@ -52,9 +53,11 @@
 
 void StubCellularNetworksProvider::Init(
     NetworkStateHandler* network_state_handler,
-    CellularESimProfileHandler* cellular_esim_profile_handler) {
+    CellularESimProfileHandler* cellular_esim_profile_handler,
+    ManagedCellularPrefHandler* managed_cellular_pref_handler) {
   network_state_handler_ = network_state_handler;
   cellular_esim_profile_handler_ = cellular_esim_profile_handler;
+  managed_cellular_pref_handler_ = managed_cellular_pref_handler;
   network_state_handler_->set_stub_cellular_networks_provider(this);
   network_state_handler_->SyncStubCellularNetworks();
 }
@@ -166,12 +169,19 @@
     if (base::Contains(all_iccids, iccid_eid_pair.first))
       continue;
 
+    bool is_managed = false;
+    if (managed_cellular_pref_handler_) {
+      is_managed = managed_cellular_pref_handler_->GetSmdpAddressFromIccid(
+          iccid_eid_pair.first);
+    }
     NET_LOG(EVENT) << "Adding stub cellular network for ICCID="
-                   << iccid_eid_pair.first << " EID=" << iccid_eid_pair.second;
+                   << iccid_eid_pair.first << " EID=" << iccid_eid_pair.second
+                   << ", is managed: " << is_managed;
     network_added = true;
     new_stub_networks.push_back(NetworkState::CreateNonShillCellularNetwork(
         iccid_eid_pair.first, iccid_eid_pair.second,
-        GetGuidForStubIccid(iccid_eid_pair.first), cellular_device));
+        GetGuidForStubIccid(iccid_eid_pair.first), is_managed,
+        cellular_device));
   }
 
   return network_added;
diff --git a/chromeos/network/stub_cellular_networks_provider.h b/chromeos/network/stub_cellular_networks_provider.h
index 02c0323..a8b768c 100644
--- a/chromeos/network/stub_cellular_networks_provider.h
+++ b/chromeos/network/stub_cellular_networks_provider.h
@@ -25,7 +25,8 @@
   ~StubCellularNetworksProvider() override;
 
   void Init(NetworkStateHandler* network_state_handler,
-            CellularESimProfileHandler* cellular_esim_profile_handler);
+            CellularESimProfileHandler* cellular_esim_profile_handler,
+            ManagedCellularPrefHandler* managed_cellular_pref_handler);
 
  private:
   friend class StubCellularNetworksProviderTest;
@@ -71,6 +72,7 @@
 
   NetworkStateHandler* network_state_handler_ = nullptr;
   CellularESimProfileHandler* cellular_esim_profile_handler_ = nullptr;
+  ManagedCellularPrefHandler* managed_cellular_pref_handler_ = nullptr;
 
   // Map which stores the GUID used for stubs created by this class. Each
   // network should use a consistent GUID throughout a session.
diff --git a/chromeos/network/stub_cellular_networks_provider_unittest.cc b/chromeos/network/stub_cellular_networks_provider_unittest.cc
index 30be209..62a6a72 100644
--- a/chromeos/network/stub_cellular_networks_provider_unittest.cc
+++ b/chromeos/network/stub_cellular_networks_provider_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/test/task_environment.h"
 #include "base/values.h"
 #include "chromeos/network/cellular_utils.h"
+#include "chromeos/network/managed_cellular_pref_handler.h"
 #include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/network/test_cellular_esim_profile_handler.h"
 #include "components/prefs/testing_pref_service.h"
@@ -50,11 +51,17 @@
   }
 
   void Init() {
-    handler_.Init(helper_.network_state_handler(),
-                  /*cellular_inhibitor=*/nullptr);
+    cellular_esim_profile_handler_.Init(helper_.network_state_handler(),
+                                        /*cellular_inhibitor=*/nullptr);
+    managed_cellular_pref_handler_.Init(helper_.network_state_handler());
+    ManagedCellularPrefHandler::RegisterLocalStatePrefs(
+        device_prefs_.registry());
+    managed_cellular_pref_handler_.SetDevicePrefs(&device_prefs_);
 
     provider_ = std::make_unique<StubCellularNetworksProvider>();
-    provider_->Init(helper_.network_state_handler(), &handler_);
+    provider_->Init(helper_.network_state_handler(),
+                    &cellular_esim_profile_handler_,
+                    &managed_cellular_pref_handler_);
   }
 
   void AddEuicc(int euicc_num) {
@@ -127,12 +134,22 @@
     base::RunLoop().RunUntilIdle();
   }
 
+  void AddIccidSmdpPairToPref(const std::string& iccid,
+                              const std::string& smdp_address) {
+    managed_cellular_pref_handler_.AddIccidSmdpPair(iccid, smdp_address);
+  }
+
+  void RemoveIccidSmdpPairFromPref(const std::string& iccid) {
+    managed_cellular_pref_handler_.RemovePairWithIccid(iccid);
+  }
+
  private:
   base::test::SingleThreadTaskEnvironment task_environment_;
   NetworkStateTestHelper helper_;
-  TestCellularESimProfileHandler handler_;
-
+  TestCellularESimProfileHandler cellular_esim_profile_handler_;
+  ManagedCellularPrefHandler managed_cellular_pref_handler_;
   std::unique_ptr<StubCellularNetworksProvider> provider_;
+  TestingPrefServiceSimple device_prefs_;
 };
 
 TEST_F(StubCellularNetworksProviderTest, AddOrRemoveStubCellularNetworks) {
@@ -145,15 +162,22 @@
   dbus::ObjectPath profile2_path =
       AddProfile(/*euicc_num=*/1, hermes::profile::State::kInactive,
                  /*activation_code=*/"code1");
+  dbus::ObjectPath profile3_path =
+      AddProfile(/*euicc_num=*/1, hermes::profile::State::kInactive,
+                 /*activation_code=*/"code1");
   HermesProfileClient::Properties* profile1_properties =
       HermesProfileClient::Get()->GetProperties(profile1_path);
   HermesProfileClient::Properties* profile2_properties =
       HermesProfileClient::Get()->GetProperties(profile2_path);
+  HermesProfileClient::Properties* profile3_properties =
+      HermesProfileClient::Get()->GetProperties(profile3_path);
 
   CallGetStubNetworkMetadata(profile1_properties->iccid().value(),
                              /*should_exist=*/false);
   CallGetStubNetworkMetadata(profile2_properties->iccid().value(),
                              /*should_exist=*/true);
+  CallGetStubNetworkMetadata(profile3_properties->iccid().value(),
+                             /*should_exist=*/true);
   CallGetStubNetworkMetadata(kTestPSimIccid, /*should_exist=*/true);
   CallGetStubNetworkMetadata("nonexistent_iccid", /*should_exist=*/false);
 
@@ -161,14 +185,30 @@
 
   // Verify that stub services are created for eSIM profiles and pSIM iccids
   // on sim slot info.
+  AddIccidSmdpPairToPref(profile3_properties->iccid().value(), "smdp_address");
   AddOrRemoveStubCellularNetworks(network_list, new_stub_networks);
-  EXPECT_EQ(2u, new_stub_networks.size());
+  EXPECT_EQ(3u, new_stub_networks.size());
   NetworkState* network1 = new_stub_networks[0]->AsNetworkState();
   NetworkState* network2 = new_stub_networks[1]->AsNetworkState();
+  NetworkState* network3 = new_stub_networks[2]->AsNetworkState();
   EXPECT_TRUE(network1->IsNonShillCellularNetwork());
   EXPECT_TRUE(network2->IsNonShillCellularNetwork());
+  EXPECT_TRUE(network3->IsNonShillCellularNetwork());
   EXPECT_EQ(network1->iccid(), profile2_properties->iccid().value());
-  EXPECT_EQ(network2->iccid(), kTestPSimIccid);
+  EXPECT_FALSE(network1->IsManagedByPolicy());
+  EXPECT_EQ(network2->iccid(), profile3_properties->iccid().value());
+  EXPECT_TRUE(network2->IsManagedByPolicy());
+  EXPECT_EQ(network3->iccid(), kTestPSimIccid);
+
+  // Verify the stub networks becomes unmanaged once the iccid and smdp address
+  // pair is removed from pref.
+  new_stub_networks.clear();
+  RemoveIccidSmdpPairFromPref(profile3_properties->iccid().value());
+  AddOrRemoveStubCellularNetworks(network_list, new_stub_networks);
+  EXPECT_EQ(3u, new_stub_networks.size());
+  network2 = new_stub_networks[1]->AsNetworkState();
+  EXPECT_EQ(network2->iccid(), profile3_properties->iccid().value());
+  EXPECT_FALSE(network2->IsManagedByPolicy());
 
   // Verify the stub networks are removed when corresponding slot is no longer
   // present. e.g. SIM removed.
@@ -177,7 +217,7 @@
   SetPSimSlotInfo(/*iccid=*/std::string());
   base::RunLoop().RunUntilIdle();
   AddOrRemoveStubCellularNetworks(network_list, new_stub_networks);
-  EXPECT_EQ(1u, network_list.size());
+  EXPECT_EQ(2u, network_list.size());
 
   // Verify that stub networks are removed when real networks are added to the
   // list.
@@ -190,7 +230,7 @@
   test_network->set_update_received();
   network_list.push_back(std::move(test_network));
   AddOrRemoveStubCellularNetworks(network_list, new_stub_networks);
-  EXPECT_EQ(1u, network_list.size());
+  EXPECT_EQ(2u, network_list.size());
 }
 
 TEST_F(StubCellularNetworksProviderTest, RemoveStubWhenCellularDisabled) {
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.cc b/components/autofill/core/browser/payments/credit_card_access_manager.cc
index 0aa199b..699090c 100644
--- a/components/autofill/core/browser/payments/credit_card_access_manager.cc
+++ b/components/autofill/core/browser/payments/credit_card_access_manager.cc
@@ -616,27 +616,6 @@
         unmask_auth_flow_type_);
   }
 
-  // Local boolean denotes whether to call AdditionallyPerformFidoAuth which
-  // delays the form filling and invokes an Authorization flow. If
-  // |unmask_auth_flow_type_| is kCvcThenFido, then the user is already opted-in
-  // and the new card must additionally be authorized through WebAuthn. Note
-  // that this and |should_respond_immediately| are mutually exclusive (can not
-  // both be true).
-  bool should_authorize_with_fido =
-      unmask_auth_flow_type_ == UnmaskAuthFlowType::kCvcThenFido;
-#if BUILDFLAG(IS_ANDROID)
-  // For Android, we will delay the form filling for both intent-to-opt-in user
-  // opting in and opted-in user registering a new card (kCvcThenFido). So we
-  // check one more scenario for Android here. If the GetRealPan response
-  // includes |request_options|, that means the user showed intention to opt-in
-  // while unmasking and must complete the challenge before successfully
-  // opting-in and filling the form.
-  should_authorize_with_fido |= response.request_options.has_value();
-#endif
-  // Card authorization token is required in order to call
-  // AdditionallyPerformFidoAuth.
-  should_authorize_with_fido &= !response.card_authorization_token.empty();
-
   // Local boolean denotes whether to show the dialog that offers opting-in to
   // FIDO authentication after the CVC check. Note that this and
   // |should_respond_immediately| are NOT mutually exclusive. If both are true,
@@ -652,17 +631,18 @@
                                 ->GetOrCreateFidoAuthenticationStrikeDatabase()
                                 ->IsMaxStrikesLimitReached();
 #endif
-
+  bool should_register_card_with_fido = ShouldRegisterCardWithFido(response);
   if (ShouldRespondImmediately(response)) {
-    // If ShouldRespondImmediately() returns true, |should_authorize_with_fido|
-    // should be false.
-    DCHECK(!should_authorize_with_fido);
+    // If ShouldRespondImmediately() returns true,
+    // |should_register_card_with_fido| should be false.
+    DCHECK(!should_register_card_with_fido);
     accessor_->OnCreditCardFetched(response.did_succeed
                                        ? CreditCardFetchResult::kSuccess
                                        : CreditCardFetchResult::kTransientError,
                                    response.card, response.cvc);
     unmask_auth_flow_type_ = UnmaskAuthFlowType::kNone;
-  } else if (should_authorize_with_fido) {
+  } else if (should_register_card_with_fido) {
+#if !BUILDFLAG(IS_IOS)
     absl::optional<base::Value> request_options = absl::nullopt;
     if (unmask_details_.fido_request_options.has_value()) {
       // For opted-in user (CVC then FIDO case), request options are returned in
@@ -673,7 +653,17 @@
       // user has chosen to opt-in.
       request_options = response.request_options->Clone();
     }
-    AdditionallyPerformFidoAuth(response, request_options->Clone());
+
+    // Save credit card for after authorization.
+    card_ = std::make_unique<CreditCard>(*(response.card));
+    cvc_ = response.cvc;
+
+    // Additionally authorizes the card with FIDO. It also delays the form
+    // filling.
+    GetOrCreateFIDOAuthenticator()->Authorize(weak_ptr_factory_.GetWeakPtr(),
+                                              response.card_authorization_token,
+                                              request_options->Clone());
+#endif
   }
   if (should_offer_fido_auth) {
     // CreditCardFIDOAuthenticator will handle enrollment completely.
@@ -877,6 +867,34 @@
   return !response.did_succeed || response.card_authorization_token.empty();
 }
 
+bool CreditCardAccessManager::ShouldRegisterCardWithFido(
+    const CreditCardCVCAuthenticator::CVCAuthenticationResponse& response) {
+  // Card authorization token is required in order to call
+  // CreditCardFIDOAuthenticator::Authorize(), so if we do not have a card
+  // authorization token populated we immediately return false.
+  if (response.card_authorization_token.empty())
+    return false;
+
+  // |unmask_auth_flow_type_| is kCvcThenFido, then the user is already opted-in
+  // and the new card must additionally be authorized through WebAuthn.
+  if (unmask_auth_flow_type_ == UnmaskAuthFlowType::kCvcThenFido)
+    return true;
+
+#if BUILDFLAG(IS_ANDROID)
+  // For Android, we will delay the form filling for both intent-to-opt-in user
+  // opting in and opted-in user registering a new card (kCvcThenFido). So we
+  // check one more scenario for Android here. If the GetRealPan response
+  // includes |request_options|, that means the user showed intention to opt-in
+  // while unmasking and must complete the challenge before successfully
+  // opting-in and filling the form.
+  if (response.request_options.has_value())
+    return true;
+#endif
+
+  // No conditions to offer FIDO registration are met, so we return false.
+  return false;
+}
+
 void CreditCardAccessManager::ShowWebauthnOfferDialog(
     std::string card_authorization_token) {
 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
@@ -925,19 +943,6 @@
 }
 #endif
 
-void CreditCardAccessManager::AdditionallyPerformFidoAuth(
-    const CreditCardCVCAuthenticator::CVCAuthenticationResponse& response,
-    base::Value request_options) {
-#if !BUILDFLAG(IS_IOS)
-  // Save credit card for after authorization.
-  card_ = std::make_unique<CreditCard>(*(response.card));
-  cvc_ = response.cvc;
-  GetOrCreateFIDOAuthenticator()->Authorize(weak_ptr_factory_.GetWeakPtr(),
-                                            response.card_authorization_token,
-                                            request_options.Clone());
-#endif
-}
-
 std::string CreditCardAccessManager::GetKeyForUnmaskedCardsCache(
     const CreditCard& card) const {
   std::string key = card.server_id();
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.h b/components/autofill/core/browser/payments/credit_card_access_manager.h
index 5e3662b..55f0251 100644
--- a/components/autofill/core/browser/payments/credit_card_access_manager.h
+++ b/components/autofill/core/browser/payments/credit_card_access_manager.h
@@ -311,10 +311,18 @@
   // Returns true if there should be an immediate response after a CVC
   // Authentication. The cases where we would have an immediate response is if
   // there is no need for FIDO authentication after a successful CVC
-  // authentication, or the CVC authentication was unsuccessful.
+  // authentication, or the CVC authentication was unsuccessful. The result of
+  // this function and ShouldRegisterCardWithFido() are mutually exclusive (can
+  // not both be true).
   bool ShouldRespondImmediately(
       const CreditCardCVCAuthenticator::CVCAuthenticationResponse& response);
 
+  // Returns true if FIDO registration should occur. The result of this function
+  // and ShouldRespondImmediately() are mutually exclusive (can not both be
+  // true).
+  bool ShouldRegisterCardWithFido(
+      const CreditCardCVCAuthenticator::CVCAuthenticationResponse& response);
+
   // TODO(crbug.com/991037): Move this function under the build flags after the
   // refactoring is done. Offer the option to use WebAuthn for authenticating
   // future card unmasking.
@@ -330,13 +338,6 @@
   void HandleDialogUserResponse(WebauthnDialogCallbackType type);
 #endif
 
-  // Additionlly authorizes the card with FIDO. It also delays the form filling.
-  // It should only be called when registering a new card or opting-in from
-  // Android.
-  void AdditionallyPerformFidoAuth(
-      const CreditCardCVCAuthenticator::CVCAuthenticationResponse& response,
-      base::Value request_options);
-
   // Returns the key for the given card to be used for inserting or querying the
   // `unmasked_card_cache_`.
   std::string GetKeyForUnmaskedCardsCache(const CreditCard& card) const;
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
index 7349b36..53e16969 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
@@ -356,9 +356,9 @@
       ComputeAutofillWalletDiff(existing_cards, wallet_cards);
 
   if (!diff.IsEmpty()) {
-    // Check if there is any update on cards' virtual card metadata. If so, make
-    // changes to the credit card art image table and log it.
-    ProcessVirtualCardMetadataChanges(existing_cards, wallet_cards);
+    // Check if there is any update on cards' virtual card metadata. If so log
+    // it.
+    LogVirtualCardMetadataChanges(existing_cards, wallet_cards);
 
     table->SetServerCardsData(wallet_cards);
 
@@ -541,10 +541,9 @@
   change_processor()->ModelReadyToSync(std::move(batch));
 }
 
-void AutofillWalletSyncBridge::ProcessVirtualCardMetadataChanges(
+void AutofillWalletSyncBridge::LogVirtualCardMetadataChanges(
     const std::vector<std::unique_ptr<CreditCard>>& old_data,
     const std::vector<CreditCard>& new_data) {
-  std::vector<std::string> updated_server_ids;
   for (const CreditCard& new_card : new_data) {
     // Try to find the old card with same server id.
     auto old_data_iterator =
@@ -555,7 +554,6 @@
 
     // No existing card with the same ID found.
     if (old_data_iterator == old_data.end()) {
-      updated_server_ids.push_back(new_card.server_id());
       // log the newly-synced card.
       AutofillMetrics::LogVirtualCardMetadataSynced(/*existing_card=*/false);
       continue;
@@ -566,15 +564,9 @@
     if ((*old_data_iterator)->virtual_card_enrollment_state() !=
             new_card.virtual_card_enrollment_state() ||
         (*old_data_iterator)->card_art_url() != new_card.card_art_url()) {
-      updated_server_ids.push_back(new_card.server_id());
       AutofillMetrics::LogVirtualCardMetadataSynced(/*existing_card=*/true);
     }
   }
-
-  // After traversing all the new cards, notify the observer the ids of card
-  // whose image should be updated.
-  if (!updated_server_ids.empty() && web_data_backend_)
-    web_data_backend_->NotifyOfCreditCardArtImagesChanged(updated_server_ids);
 }
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
index fdd3cd9..97dbab6 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
+++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
@@ -138,11 +138,8 @@
   // processor so that it can start tracking changes.
   void LoadMetadata();
 
-  // TODO(crbug/com/1196021): Clean up duplicate functions and use it for
-  // logging only.
-  // Checks whether any virtual card metadata for new_data is new and make
-  // corresponding changes.
-  void ProcessVirtualCardMetadataChanges(
+  // Logs virtual card metadata changes.
+  void LogVirtualCardMetadataChanges(
       const std::vector<std::unique_ptr<CreditCard>>& old_data,
       const std::vector<CreditCard>& new_data);
 
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
index fa9fa08..2085d07e 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
@@ -1095,7 +1095,6 @@
 
   std::vector<std::string> server_ids = {"card2_server_id", "card3_server_id",
                                          "card4_server_id"};
-  EXPECT_CALL(*backend(), NotifyOfCreditCardArtImagesChanged(server_ids));
 
   // Trigger sync.
   base::HistogramTester histogram_tester;
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend.h b/components/autofill/core/browser/webdata/autofill_webdata_backend.h
index 200e893..e7c5f09 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_backend.h
+++ b/components/autofill/core/browser/webdata/autofill_webdata_backend.h
@@ -67,13 +67,6 @@
   // NOTE: This method is intended to be called from the DB sequence. The UI
   // sequence notifications are asynchronous.
   virtual void NotifyThatSyncHasStarted(syncer::ModelType model_type) = 0;
-
-  // Notifies listeners on the UI sequence that the credit cards with
-  // |server_ids| have new card art images. NOTE: This method is intended to be
-  // called from the DB sequence. The UI sequence notifications are
-  // asynchronous.
-  virtual void NotifyOfCreditCardArtImagesChanged(
-      const std::vector<std::string>& server_ids) = 0;
 };
 
 } // namespace autofill
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
index 55f150d..141895fe 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
+++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
@@ -75,13 +75,6 @@
   on_autofill_profile_changed_cb_ = std::move(change_cb);
 }
 
-void AutofillWebDataBackendImpl::SetCardArtImagesChangedCallback(
-    base::RepeatingCallback<void(const std::vector<std::string>&)>
-        on_card_art_image_change_callback) {
-  on_card_art_image_change_callback_ =
-      std::move(on_card_art_image_change_callback);
-}
-
 WebDatabase* AutofillWebDataBackendImpl::GetDatabase() {
   DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
   return web_database_backend_->database();
@@ -154,19 +147,6 @@
       FROM_HERE, base::BindOnce(on_sync_started_callback_, model_type));
 }
 
-void AutofillWebDataBackendImpl::NotifyOfCreditCardArtImagesChanged(
-    const std::vector<std::string>& server_ids) {
-  DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
-
-  if (on_card_art_image_change_callback_.is_null())
-    return;
-
-  // UI sequence notification.
-  ui_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(on_card_art_image_change_callback_, server_ids));
-}
-
 base::SupportsUserData* AutofillWebDataBackendImpl::GetDBUserData() {
   DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
   if (!user_data_)
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
index 617a27b..dcd5b16 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
+++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
@@ -64,9 +64,6 @@
   void SetAutofillProfileChangedCallback(
       base::RepeatingCallback<void(const AutofillProfileDeepChange&)>
           change_cb);
-  void SetCardArtImagesChangedCallback(
-      base::RepeatingCallback<void(const std::vector<std::string>&)>
-          on_card_art_image_change_callback);
 
   // AutofillWebDataBackend implementation.
   void AddObserver(
@@ -80,8 +77,6 @@
   void NotifyOfMultipleAutofillChanges() override;
   void NotifyOfAddressConversionCompleted() override;
   void NotifyThatSyncHasStarted(syncer::ModelType model_type) override;
-  void NotifyOfCreditCardArtImagesChanged(
-      const std::vector<std::string>& server_ids) override;
   void CommitChanges() override;
 
   // Returns a SupportsUserData object that may be used to store data accessible
@@ -272,8 +267,6 @@
   base::RepeatingCallback<void(syncer::ModelType)> on_sync_started_callback_;
   base::RepeatingCallback<void(const AutofillProfileDeepChange&)>
       on_autofill_profile_changed_cb_;
-  base::RepeatingCallback<void(const std::vector<std::string>&)>
-      on_card_art_image_change_callback_;
 };
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_service.cc b/components/autofill/core/browser/webdata/autofill_webdata_service.cc
index 3fa22d51..1621156 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_service.cc
+++ b/components/autofill/core/browser/webdata/autofill_webdata_service.cc
@@ -123,13 +123,6 @@
   autofill_backend_->SetAutofillProfileChangedCallback(std::move(change_cb));
 }
 
-void AutofillWebDataService::SetCardArtImagesChangedCallback(
-    base::RepeatingCallback<void(const std::vector<std::string>&)>
-        on_card_art_image_change_callback) {
-  autofill_backend_->SetCardArtImagesChangedCallback(
-      std::move(on_card_art_image_change_callback));
-}
-
 void AutofillWebDataService::UpdateAutofillProfile(
     const AutofillProfile& profile) {
   wdbs_->ScheduleDBTask(
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_service.h b/components/autofill/core/browser/webdata/autofill_webdata_service.h
index bc99f3a..cb92fee 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_service.h
+++ b/components/autofill/core/browser/webdata/autofill_webdata_service.h
@@ -113,9 +113,6 @@
   void SetAutofillProfileChangedCallback(
       base::RepeatingCallback<void(const AutofillProfileDeepChange&)>
           change_cb);
-  void SetCardArtImagesChangedCallback(
-      base::RepeatingCallback<void(const std::vector<std::string>&)>
-          on_card_art_image_change_callback);
 
   // Schedules a task to add credit card to the web database.
   void AddCreditCard(const CreditCard& credit_card);
diff --git a/components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h b/components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h
index 8ef17f4..f563a874 100644
--- a/components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h
+++ b/components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h
@@ -50,10 +50,6 @@
               NotifyThatSyncHasStarted,
               (syncer::ModelType model_type),
               (override));
-  MOCK_METHOD(void,
-              NotifyOfCreditCardArtImagesChanged,
-              (const std::vector<std::string>& server_ids),
-              (override));
 };
 
 }  // namespace autofill
diff --git a/components/breadcrumbs/core/application_breadcrumbs_logger_unittest.cc b/components/breadcrumbs/core/application_breadcrumbs_logger_unittest.cc
index 481b6b9..51028303 100644
--- a/components/breadcrumbs/core/application_breadcrumbs_logger_unittest.cc
+++ b/components/breadcrumbs/core/application_breadcrumbs_logger_unittest.cc
@@ -36,9 +36,13 @@
         std::make_unique<ApplicationBreadcrumbsLogger>(temp_dir_.GetPath());
   }
 
+  // This must be created before `task_environment_`, to ensure that any tasks
+  // that depend on the directory existing (e.g., those posted by `logger_`)
+  // have finished.
+  base::ScopedTempDir temp_dir_;
+
   base::test::TaskEnvironment task_environment_;
   std::unique_ptr<ApplicationBreadcrumbsLogger> logger_;
-  base::ScopedTempDir temp_dir_;
 };
 
 // Tests that a recorded UserAction is logged by the
@@ -79,7 +83,7 @@
 
 // Tests that memory pressure events are logged by ApplicationBreadcrumbsLogger.
 // Test is flaky (https://crbug.com/1305253)
-TEST_F(ApplicationBreadcrumbsLoggerTest, DISABLED_MemoryPressure) {
+TEST_F(ApplicationBreadcrumbsLoggerTest, MemoryPressure) {
   ASSERT_EQ(1U, logger_->GetEventsForTesting().size());  // startup event
 
   base::MemoryPressureListener::SimulatePressureNotification(
diff --git a/components/browsing_topics/BUILD.gn b/components/browsing_topics/BUILD.gn
index 0d028813..ffa5838c 100644
--- a/components/browsing_topics/BUILD.gn
+++ b/components/browsing_topics/BUILD.gn
@@ -6,6 +6,8 @@
   sources = [
     "browsing_topics_calculator.cc",
     "browsing_topics_calculator.h",
+    "browsing_topics_page_load_data_tracker.cc",
+    "browsing_topics_page_load_data_tracker.h",
     "browsing_topics_service.h",
     "browsing_topics_service_impl.cc",
     "browsing_topics_service_impl.h",
@@ -28,7 +30,9 @@
     "//components/optimization_guide/content/browser",
     "//components/privacy_sandbox",
     "//content/public/browser",
+    "//content/public/common:common",
     "//crypto",
+    "//net/base/registry_controlled_domains",
     "//third_party/blink/public/common",
   ]
 }
@@ -42,13 +46,19 @@
 
   public_deps = [ "//base" ]
 
-  deps = [ ":browsing_topics" ]
+  deps = [
+    ":browsing_topics",
+    "//base/test:test_support",
+    "//components/history/core/browser:browser",
+  ]
 }
 
 source_set("unit_tests") {
   testonly = true
   sources = [
     "browsing_topics_calculator_unittest.cc",
+    "browsing_topics_page_load_data_tracker_unittest.cc",
+    "browsing_topics_service_impl_unittest.cc",
     "browsing_topics_state_unittest.cc",
     "epoch_topics_unittest.cc",
     "topic_and_domains_unittest.cc",
@@ -61,6 +71,7 @@
     "//base",
     "//base/test:test_support",
     "//components/content_settings/core/test:test_support",
+    "//components/history/content/browser:browser",
     "//components/history/core/browser:browser",
     "//components/history/core/test",
     "//components/optimization_guide/content/browser:browser",
diff --git a/components/browsing_topics/DEPS b/components/browsing_topics/DEPS
index 26ef4ba..48e8027 100644
--- a/components/browsing_topics/DEPS
+++ b/components/browsing_topics/DEPS
@@ -5,8 +5,10 @@
   "+components/privacy_sandbox",
   "+content/public/browser",
   "+content/public/test",
+  "+content/test",
   "+crypto",
-  "+third_party/blink/public/common",
+  "+net/base/registry_controlled_domains",
+  "+third_party/blink/public",
 ]
 
 specific_include_rules = {
diff --git a/components/browsing_topics/browsing_topics_calculator.cc b/components/browsing_topics/browsing_topics_calculator.cc
index 88ade005..a7e9dc0 100644
--- a/components/browsing_topics/browsing_topics_calculator.cc
+++ b/components/browsing_topics/browsing_topics_calculator.cc
@@ -277,6 +277,11 @@
 
   std::vector<std::string> raw_hosts_vector(raw_hosts.begin(), raw_hosts.end());
 
+  if (raw_hosts_vector.empty()) {
+    OnGetTopicsForHostsCompleted(/*raw_hosts=*/{}, /*results=*/{});
+    return;
+  }
+
   annotations_service_->BatchAnnotatePageTopics(
       base::BindOnce(&BrowsingTopicsCalculator::OnGetTopicsForHostsCompleted,
                      weak_ptr_factory_.GetWeakPtr(), raw_hosts_vector),
@@ -303,7 +308,7 @@
     return;
   }
 
-  const int model_version = base::checked_cast<int>(model_info->GetVersion());
+  const int64_t model_version = model_info->GetVersion();
   DCHECK_GT(model_version, 0);
 
   std::map<HashedHost, std::set<Topic>> host_topics_map;
@@ -356,8 +361,7 @@
 void BrowsingTopicsCalculator::OnCalculateCompleted(
     CalculatorResultStatus status,
     EpochTopics epoch_topics) {
-  DCHECK(status != CalculatorResultStatus::kSuccess ||
-         epoch_topics.HasValidTopics());
+  DCHECK(status != CalculatorResultStatus::kSuccess || !epoch_topics.empty());
 
   base::UmaHistogramEnumeration(
       "BrowsingTopics.EpochTopicsCalculation.CalculatorResultStatus", status);
diff --git a/components/browsing_topics/browsing_topics_calculator.h b/components/browsing_topics/browsing_topics_calculator.h
index 1232da3..c7b8e82 100644
--- a/components/browsing_topics/browsing_topics_calculator.h
+++ b/components/browsing_topics/browsing_topics_calculator.h
@@ -76,6 +76,7 @@
  protected:
   // This method exists for the purposes of overriding in tests.
   virtual uint64_t GenerateRandUint64();
+  virtual void CheckCanCalculate();
 
  private:
   // Get the top `kBrowsingTopicsNumberOfTopTopicsPerEpoch` topics. If there
@@ -91,8 +92,6 @@
       std::vector<Topic>& top_topics,
       size_t& padded_top_topics_start_index);
 
-  void CheckCanCalculate();
-
   void OnGetRecentBrowsingTopicsApiUsagesCompleted(
       browsing_topics::ApiUsageContextQueryResult result);
 
diff --git a/components/browsing_topics/browsing_topics_calculator_unittest.cc b/components/browsing_topics/browsing_topics_calculator_unittest.cc
index 3f0a05c..2ebe8b1 100644
--- a/components/browsing_topics/browsing_topics_calculator_unittest.cc
+++ b/components/browsing_topics/browsing_topics_calculator_unittest.cc
@@ -33,22 +33,22 @@
 
 namespace {
 
-const size_t kTaxonomySize = 349;
-const int kTaxonomyVersion = 1;
+constexpr size_t kTaxonomySize = 349;
+constexpr int kTaxonomyVersion = 1;
 
-const std::string kHost1 = "www.foo1.com";
-const std::string kHost2 = "www.foo2.com";
-const std::string kHost3 = "www.foo3.com";
-const std::string kHost4 = "www.foo4.com";
-const std::string kHost5 = "www.foo5.com";
-const std::string kHost6 = "www.foo6.com";
+constexpr char kHost1[] = "www.foo1.com";
+constexpr char kHost2[] = "www.foo2.com";
+constexpr char kHost3[] = "www.foo3.com";
+constexpr char kHost4[] = "www.foo4.com";
+constexpr char kHost5[] = "www.foo5.com";
+constexpr char kHost6[] = "www.foo6.com";
 
-const std::string kTokenizedHost1 = "foo1 com";
-const std::string kTokenizedHost2 = "foo2 com";
-const std::string kTokenizedHost3 = "foo3 com";
-const std::string kTokenizedHost4 = "foo4 com";
-const std::string kTokenizedHost5 = "foo5 com";
-const std::string kTokenizedHost6 = "foo6 com";
+constexpr char kTokenizedHost1[] = "foo1 com";
+constexpr char kTokenizedHost2[] = "foo2 com";
+constexpr char kTokenizedHost3[] = "foo3 com";
+constexpr char kTokenizedHost4[] = "foo4 com";
+constexpr char kTokenizedHost5[] = "foo5 com";
+constexpr char kTokenizedHost6[] = "foo6 com";
 
 }  // namespace
 
@@ -62,10 +62,10 @@
     HostContentSettingsMap::RegisterProfilePrefs(prefs_.registry());
     privacy_sandbox::RegisterProfilePrefs(prefs_.registry());
 
-    host_content_settings_map_ = new HostContentSettingsMap(
+    host_content_settings_map_ = base::MakeRefCounted<HostContentSettingsMap>(
         &prefs_, /*is_off_the_record=*/false, /*store_last_modified=*/false,
         /*restore_session=*/false);
-    cookie_settings_ = new content_settings::CookieSettings(
+    cookie_settings_ = base::MakeRefCounted<content_settings::CookieSettings>(
         host_content_settings_map_.get(), &prefs_, false, "chrome-extension");
     auto privacy_sandbox_delegate = std::make_unique<
         privacy_sandbox_test_util::MockPrivacySandboxSettingsDelegate>();
@@ -146,21 +146,22 @@
   }
 
   void AddApiUsageContextEntries(
-      std::vector<std::pair<std::string, std::set<HashedDomain>>>
+      const std::vector<std::pair<std::string, std::set<HashedDomain>>>&
           main_frame_hosts_with_context_domains) {
     for (auto& [main_frame_host, context_domains] :
          main_frame_hosts_with_context_domains) {
       topics_site_data_manager_->OnBrowsingTopicsApiUsed(
           HashMainFrameHostForStorage(main_frame_host),
           base::flat_set<HashedDomain>(context_domains.begin(),
-                                       context_domains.end()));
+                                       context_domains.end()),
+          base::Time::Now());
     }
 
     task_environment_.RunUntilIdle();
   }
 
   std::vector<optimization_guide::WeightedIdentifier> TopicsAndWeight(
-      std::vector<int32_t> topics,
+      const std::vector<int32_t>& topics,
       double weight) {
     std::vector<optimization_guide::WeightedIdentifier> result;
     for (int32_t topic : topics) {
@@ -213,7 +214,7 @@
   privacy_sandbox_settings_->SetPrivacySandboxEnabled(false);
 
   EpochTopics result = CalculateTopics();
-  EXPECT_FALSE(result.HasValidTopics());
+  EXPECT_TRUE(result.empty());
 
   histograms.ExpectUniqueSample(
       "BrowsingTopics.EpochTopicsCalculation.CalculatorResultStatus",
@@ -227,7 +228,7 @@
   topics_site_data_manager_->SetQueryFailureOverride();
 
   EpochTopics result = CalculateTopics();
-  EXPECT_FALSE(result.HasValidTopics());
+  EXPECT_TRUE(result.empty());
 
   histograms.ExpectUniqueSample(
       "BrowsingTopics.EpochTopicsCalculation.CalculatorResultStatus",
@@ -239,7 +240,7 @@
   base::HistogramTester histograms;
 
   EpochTopics result = CalculateTopics();
-  EXPECT_FALSE(result.HasValidTopics());
+  EXPECT_TRUE(result.empty());
 
   histograms.ExpectUniqueSample(
       "BrowsingTopics.EpochTopicsCalculation.CalculatorResultStatus",
@@ -267,7 +268,7 @@
       *optimization_guide::TestModelInfoBuilder().SetVersion(1).Build(), {});
 
   EpochTopics result = CalculateTopics();
-  EXPECT_FALSE(result.HasValidTopics());
+  EXPECT_TRUE(result.empty());
 
   histograms.ExpectUniqueSample(
       "BrowsingTopics.EpochTopicsCalculation.CalculatorResultStatus",
@@ -283,7 +284,7 @@
       *optimization_guide::TestModelInfoBuilder().SetVersion(1).Build(), {});
 
   EpochTopics result1 = CalculateTopics();
-  EXPECT_TRUE(result1.HasValidTopics());
+  EXPECT_FALSE(result1.empty());
   EXPECT_EQ(result1.taxonomy_size(), kTaxonomySize);
   EXPECT_EQ(result1.taxonomy_version(), kTaxonomyVersion);
   EXPECT_EQ(result1.model_version(), 1);
@@ -300,7 +301,7 @@
       *optimization_guide::TestModelInfoBuilder().SetVersion(50).Build(), {});
 
   EpochTopics result2 = CalculateTopics();
-  EXPECT_TRUE(result2.HasValidTopics());
+  EXPECT_FALSE(result2.empty());
   EXPECT_EQ(result2.taxonomy_size(), kTaxonomySize);
   EXPECT_EQ(result2.taxonomy_version(), kTaxonomyVersion);
   EXPECT_EQ(result2.model_version(), 50);
diff --git a/components/browsing_topics/browsing_topics_page_load_data_tracker.cc b/components/browsing_topics/browsing_topics_page_load_data_tracker.cc
new file mode 100644
index 0000000..8e351b4
--- /dev/null
+++ b/components/browsing_topics/browsing_topics_page_load_data_tracker.cc
@@ -0,0 +1,93 @@
+// 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 "components/browsing_topics/browsing_topics_page_load_data_tracker.h"
+
+#include "components/browsing_topics/util.h"
+#include "components/history/content/browser/history_context_helper.h"
+#include "components/history/core/browser/history_service.h"
+#include "content/public/browser/browsing_topics_site_data_manager.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/browser/web_contents.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom.h"
+
+namespace browsing_topics {
+
+BrowsingTopicsPageLoadDataTracker::~BrowsingTopicsPageLoadDataTracker() =
+    default;
+
+BrowsingTopicsPageLoadDataTracker::BrowsingTopicsPageLoadDataTracker(
+    content::Page& page)
+    : content::PageUserData<BrowsingTopicsPageLoadDataTracker>(page),
+      hashed_main_frame_host_(HashMainFrameHostForStorage(
+          page.GetMainDocument().GetLastCommittedOrigin().host())) {
+  DCHECK(page.IsPrimary());
+
+  // TODO(yaoxia): consider dropping the permissions policy checks. We require
+  // that the API is used in the page, and that already implies that the
+  // permissions policy is allowed.
+
+  if ((page.GetMainDocument().IsLastCommitIPAddressPubliclyRoutable() ||
+       base::FeatureList::IsEnabled(
+           blink::features::kBrowsingTopicsBypassIPIsPubliclyRoutableCheck)) &&
+      page.GetMainDocument().IsFeatureEnabled(
+          blink::mojom::PermissionsPolicyFeature::kBrowsingTopics) &&
+      page.GetMainDocument().IsFeatureEnabled(
+          blink::mojom::PermissionsPolicyFeature::
+              kBrowsingTopicsBackwardCompatible)) {
+    eligible_to_commit_ = true;
+  }
+}
+
+void BrowsingTopicsPageLoadDataTracker::OnBrowsingTopicsApiUsed(
+    const HashedDomain& hashed_context_domain,
+    history::HistoryService* history_service) {
+  if (!eligible_to_commit_)
+    return;
+
+  // On the first API usage in the page, set the allowed bit in history.
+  if (observed_hashed_context_domains_.empty()) {
+    content::WebContents* web_contents =
+        content::WebContents::FromRenderFrameHost(&page().GetMainDocument());
+
+    history_service->SetBrowsingTopicsAllowed(
+        history::ContextIDForWebContents(web_contents),
+        web_contents->GetController().GetLastCommittedEntry()->GetUniqueID(),
+        web_contents->GetLastCommittedURL());
+  }
+
+  // Ignore this context if we've already added it.
+  if (observed_hashed_context_domains_.count(hashed_context_domain))
+    return;
+
+  // Cap the number of context domains per page load. This is used to limit
+  // disk memory usage.
+  if (observed_hashed_context_domains_.size() >=
+      static_cast<size_t>(
+          blink::features::
+              kBrowsingTopicsMaxNumberOfApiUsageContextDomainsToStorePerPageLoad
+                  .Get())) {
+    return;
+  }
+
+  // Persist the usage now rather than at the end of the page load, as when the
+  // app enters background, it may be killed without further notification.
+  page()
+      .GetMainDocument()
+      .GetProcess()
+      ->GetStoragePartition()
+      ->GetBrowsingTopicsSiteDataManager()
+      ->OnBrowsingTopicsApiUsed(hashed_main_frame_host_,
+                                {hashed_context_domain}, base::Time::Now());
+
+  observed_hashed_context_domains_.insert(hashed_context_domain);
+}
+
+PAGE_USER_DATA_KEY_IMPL(BrowsingTopicsPageLoadDataTracker);
+
+}  // namespace browsing_topics
diff --git a/components/browsing_topics/browsing_topics_page_load_data_tracker.h b/components/browsing_topics/browsing_topics_page_load_data_tracker.h
new file mode 100644
index 0000000..256efbd4
--- /dev/null
+++ b/components/browsing_topics/browsing_topics_page_load_data_tracker.h
@@ -0,0 +1,53 @@
+// 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 COMPONENTS_BROWSING_TOPICS_BROWSING_TOPICS_PAGE_LOAD_DATA_TRACKER_H_
+#define COMPONENTS_BROWSING_TOPICS_BROWSING_TOPICS_PAGE_LOAD_DATA_TRACKER_H_
+
+#include "base/containers/flat_set.h"
+#include "components/browsing_topics/common/common_types.h"
+#include "content/public/browser/page_user_data.h"
+
+namespace history {
+class HistoryService;
+}  // namespace history
+
+namespace browsing_topics {
+
+// Tracks page-level (i.e. primary main frame document) signals to determine
+// whether the page is eligible to be included in browsing topics calculation.
+// Also tracks the context domains that have used the Topics API in the page.
+class BrowsingTopicsPageLoadDataTracker
+    : public content::PageUserData<BrowsingTopicsPageLoadDataTracker> {
+ public:
+  BrowsingTopicsPageLoadDataTracker(const BrowsingTopicsPageLoadDataTracker&) =
+      delete;
+  BrowsingTopicsPageLoadDataTracker& operator=(
+      const BrowsingTopicsPageLoadDataTracker&) = delete;
+
+  ~BrowsingTopicsPageLoadDataTracker() override;
+
+  // Called when the document.browsingTopics() API is used in the page.
+  void OnBrowsingTopicsApiUsed(const HashedDomain& hashed_context_domain,
+                               history::HistoryService* history_service);
+
+ private:
+  friend class PageUserData;
+
+  explicit BrowsingTopicsPageLoadDataTracker(content::Page& page);
+
+  // |eligible_to_commit_| means all the commit time prerequisites are met
+  // (i.e. IP was publicly routable AND permissions policy is "allow").
+  bool eligible_to_commit_ = false;
+
+  HashedHost hashed_main_frame_host_;
+
+  base::flat_set<HashedDomain> observed_hashed_context_domains_;
+
+  PAGE_USER_DATA_KEY_DECL();
+};
+
+}  // namespace browsing_topics
+
+#endif  // COMPONENTS_BROWSING_TOPICS_BROWSING_TOPICS_PAGE_LOAD_DATA_TRACKER_H_
diff --git a/components/browsing_topics/browsing_topics_page_load_data_tracker_unittest.cc b/components/browsing_topics/browsing_topics_page_load_data_tracker_unittest.cc
new file mode 100644
index 0000000..131f839e
--- /dev/null
+++ b/components/browsing_topics/browsing_topics_page_load_data_tracker_unittest.cc
@@ -0,0 +1,266 @@
+// 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 "components/browsing_topics/browsing_topics_page_load_data_tracker.h"
+
+#include "base/memory/raw_ptr.h"
+#include "base/test/bind.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/browsing_topics/test_util.h"
+#include "components/history/content/browser/history_context_helper.h"
+#include "components/history/core/browser/history_database_params.h"
+#include "components/history/core/browser/history_service.h"
+#include "components/history/core/test/test_history_database.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/test/browsing_topics_test_util.h"
+#include "content/public/test/navigation_simulator.h"
+#include "content/public/test/test_utils.h"
+#include "content/public/test/web_contents_tester.h"
+#include "content/test/test_render_view_host.h"
+
+namespace browsing_topics {
+
+class BrowsingTopicsPageLoadDataTrackerTest
+    : public content::RenderViewHostTestHarness {
+ public:
+  BrowsingTopicsPageLoadDataTrackerTest() {
+    scoped_feature_list_.InitWithFeatures(
+        /*enabled_features=*/{blink::features::kBrowsingTopics},
+        /*disabled_features=*/{});
+
+    EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+    history_service_ = std::make_unique<history::HistoryService>();
+    history_service_->Init(
+        history::TestHistoryDatabaseParamsForPath(temp_dir_.GetPath()));
+  }
+
+  ~BrowsingTopicsPageLoadDataTrackerTest() override = default;
+
+  void TearDown() override {
+    DCHECK(history_service_);
+
+    base::RunLoop run_loop;
+    history_service_->SetOnBackendDestroyTask(run_loop.QuitClosure());
+    history_service_.reset();
+    run_loop.Run();
+
+    content::RenderViewHostTestHarness::TearDown();
+  }
+
+  void NavigateToPage(const GURL& url,
+                      bool publicly_routable,
+                      bool browsing_topics_permissions_policy_allowed,
+                      bool interest_cohort_permissions_policy_allowed) {
+    auto simulator = content::NavigationSimulator::CreateBrowserInitiated(
+        url, web_contents());
+    simulator->SetTransition(ui::PageTransition::PAGE_TRANSITION_TYPED);
+
+    if (!publicly_routable) {
+      net::IPAddress address;
+      EXPECT_TRUE(address.AssignFromIPLiteral("0.0.0.0"));
+      simulator->SetSocketAddress(net::IPEndPoint(address, /*port=*/0));
+    }
+
+    blink::ParsedPermissionsPolicy policy;
+
+    if (!browsing_topics_permissions_policy_allowed) {
+      policy.emplace_back(
+          blink::mojom::PermissionsPolicyFeature::kBrowsingTopics,
+          /*values=*/std::vector<url::Origin>(), /*matches_all_origins=*/false,
+          /*matches_opaque_src=*/false);
+    }
+
+    if (!interest_cohort_permissions_policy_allowed) {
+      policy.emplace_back(blink::mojom::PermissionsPolicyFeature::
+                              kBrowsingTopicsBackwardCompatible,
+                          /*values=*/std::vector<url::Origin>(),
+                          /*matches_all_origins=*/false,
+                          /*matches_opaque_src=*/false);
+    }
+
+    simulator->SetPermissionsPolicyHeader(std::move(policy));
+
+    simulator->Commit();
+
+    history_service_->AddPage(
+        url, base::Time::Now(),
+        history::ContextIDForWebContents(web_contents()),
+        web_contents()->GetController().GetLastCommittedEntry()->GetUniqueID(),
+        /*referrer=*/GURL(),
+        /*redirects=*/{}, ui::PageTransition::PAGE_TRANSITION_TYPED,
+        history::VisitSource::SOURCE_BROWSED,
+        /*did_replace_entry=*/false,
+        /*floc_allowed=*/false);
+  }
+
+  BrowsingTopicsPageLoadDataTracker* GetBrowsingTopicsPageLoadDataTracker() {
+    return BrowsingTopicsPageLoadDataTracker::GetOrCreateForPage(
+        web_contents()->GetMainFrame()->GetPage());
+  }
+
+  content::BrowsingTopicsSiteDataManager* topics_site_data_manager() {
+    return web_contents()
+        ->GetMainFrame()
+        ->GetProcess()
+        ->GetStoragePartition()
+        ->GetBrowsingTopicsSiteDataManager();
+  }
+
+ protected:
+  base::test::ScopedFeatureList scoped_feature_list_;
+
+  std::unique_ptr<history::HistoryService> history_service_;
+
+  base::ScopedTempDir temp_dir_;
+};
+
+TEST_F(BrowsingTopicsPageLoadDataTrackerTest, OneUsage) {
+  GURL url("https://foo.com");
+  NavigateToPage(url, /*publicly_routable=*/true,
+                 /*browsing_topics_permissions_policy_allowed=*/true,
+                 /*interest_cohort_permissions_policy_allowed=*/true);
+
+  EXPECT_FALSE(BrowsingTopicsEligibleForURLVisit(history_service_.get(), url));
+  EXPECT_TRUE(
+      content::GetBrowsingTopicsApiUsage(topics_site_data_manager()).empty());
+
+  GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
+      HashedDomain(123), history_service_.get());
+
+  EXPECT_TRUE(BrowsingTopicsEligibleForURLVisit(history_service_.get(), url));
+
+  std::vector<ApiUsageContext> api_usage_contexts =
+      content::GetBrowsingTopicsApiUsage(topics_site_data_manager());
+  EXPECT_EQ(api_usage_contexts.size(), 1u);
+  EXPECT_EQ(api_usage_contexts[0].hashed_main_frame_host,
+            HashMainFrameHostForStorage("foo.com"));
+  EXPECT_EQ(api_usage_contexts[0].hashed_context_domain, HashedDomain(123));
+}
+
+TEST_F(BrowsingTopicsPageLoadDataTrackerTest, TwoUsages) {
+  GURL url("https://foo.com");
+  NavigateToPage(url, /*publicly_routable=*/true,
+                 /*browsing_topics_permissions_policy_allowed=*/true,
+                 /*interest_cohort_permissions_policy_allowed=*/true);
+
+  GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
+      HashedDomain(123), history_service_.get());
+  GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
+      HashedDomain(456), history_service_.get());
+
+  EXPECT_TRUE(BrowsingTopicsEligibleForURLVisit(history_service_.get(), url));
+
+  std::vector<ApiUsageContext> api_usage_contexts =
+      content::GetBrowsingTopicsApiUsage(topics_site_data_manager());
+  EXPECT_EQ(api_usage_contexts.size(), 2u);
+  EXPECT_EQ(api_usage_contexts[0].hashed_main_frame_host,
+            HashMainFrameHostForStorage("foo.com"));
+  EXPECT_EQ(api_usage_contexts[0].hashed_context_domain, HashedDomain(123));
+  EXPECT_EQ(api_usage_contexts[1].hashed_main_frame_host,
+            HashMainFrameHostForStorage("foo.com"));
+  EXPECT_EQ(api_usage_contexts[1].hashed_context_domain, HashedDomain(456));
+}
+
+TEST_F(BrowsingTopicsPageLoadDataTrackerTest, DuplicateDomains) {
+  GURL url("https://foo.com");
+  NavigateToPage(url, /*publicly_routable=*/true,
+                 /*browsing_topics_permissions_policy_allowed=*/true,
+                 /*interest_cohort_permissions_policy_allowed=*/true);
+
+  GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
+      HashedDomain(123), history_service_.get());
+  GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
+      HashedDomain(456), history_service_.get());
+  GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
+      HashedDomain(123), history_service_.get());
+
+  EXPECT_TRUE(BrowsingTopicsEligibleForURLVisit(history_service_.get(), url));
+
+  std::vector<ApiUsageContext> api_usage_contexts =
+      content::GetBrowsingTopicsApiUsage(topics_site_data_manager());
+  EXPECT_EQ(api_usage_contexts.size(), 2u);
+  EXPECT_EQ(api_usage_contexts[0].hashed_main_frame_host,
+            HashMainFrameHostForStorage("foo.com"));
+  EXPECT_EQ(api_usage_contexts[0].hashed_context_domain, HashedDomain(123));
+  EXPECT_EQ(api_usage_contexts[1].hashed_main_frame_host,
+            HashMainFrameHostForStorage("foo.com"));
+  EXPECT_EQ(api_usage_contexts[1].hashed_context_domain, HashedDomain(456));
+
+  // The second HashedDomain(123) shouldn't update the database. Verify this by
+  // verifying that the timestamp for HashedDomain(123) is no greater than the
+  // timestamp for HashedDomain(456).
+  EXPECT_LE(api_usage_contexts[0].time, api_usage_contexts[1].time);
+}
+
+TEST_F(BrowsingTopicsPageLoadDataTrackerTest, NumberOfDomainsExceedsLimit) {
+  GURL url("https://foo.com");
+  NavigateToPage(url, /*publicly_routable=*/true,
+                 /*browsing_topics_permissions_policy_allowed=*/true,
+                 /*interest_cohort_permissions_policy_allowed=*/true);
+
+  for (int i = 0; i < 31; ++i) {
+    GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
+        HashedDomain(i), history_service_.get());
+  }
+
+  EXPECT_TRUE(BrowsingTopicsEligibleForURLVisit(history_service_.get(), url));
+
+  std::vector<ApiUsageContext> api_usage_contexts =
+      content::GetBrowsingTopicsApiUsage(topics_site_data_manager());
+
+  EXPECT_EQ(api_usage_contexts.size(), 30u);
+
+  for (int i = 0; i < 30; ++i) {
+    EXPECT_EQ(api_usage_contexts[i].hashed_main_frame_host,
+              HashMainFrameHostForStorage("foo.com"));
+    EXPECT_EQ(api_usage_contexts[i].hashed_context_domain, HashedDomain(i));
+  }
+}
+
+TEST_F(BrowsingTopicsPageLoadDataTrackerTest, NotPubliclyRoutable) {
+  GURL url("https://foo.com");
+  NavigateToPage(url, /*publicly_routable=*/false,
+                 /*browsing_topics_permissions_policy_allowed=*/true,
+                 /*interest_cohort_permissions_policy_allowed=*/true);
+
+  GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
+      HashedDomain(123), history_service_.get());
+
+  EXPECT_FALSE(BrowsingTopicsEligibleForURLVisit(history_service_.get(), url));
+  EXPECT_TRUE(
+      content::GetBrowsingTopicsApiUsage(topics_site_data_manager()).empty());
+}
+
+TEST_F(BrowsingTopicsPageLoadDataTrackerTest,
+       BrowsingTopicsPermissionsPolicyNotAllowed) {
+  GURL url("https://foo.com");
+  NavigateToPage(url, /*publicly_routable=*/true,
+                 /*browsing_topics_permissions_policy_allowed=*/false,
+                 /*interest_cohort_permissions_policy_allowed=*/true);
+
+  GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
+      HashedDomain(123), history_service_.get());
+
+  EXPECT_FALSE(BrowsingTopicsEligibleForURLVisit(history_service_.get(), url));
+  EXPECT_TRUE(
+      content::GetBrowsingTopicsApiUsage(topics_site_data_manager()).empty());
+}
+
+TEST_F(BrowsingTopicsPageLoadDataTrackerTest,
+       InterestCohortPermissionsPolicyNotAllowed) {
+  GURL url("https://foo.com");
+  NavigateToPage(url, /*publicly_routable=*/true,
+                 /*browsing_topics_permissions_policy_allowed=*/true,
+                 /*interest_cohort_permissions_policy_allowed=*/false);
+
+  GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
+      HashedDomain(123), history_service_.get());
+
+  EXPECT_FALSE(BrowsingTopicsEligibleForURLVisit(history_service_.get(), url));
+  EXPECT_TRUE(
+      content::GetBrowsingTopicsApiUsage(topics_site_data_manager()).empty());
+}
+
+}  // namespace browsing_topics
diff --git a/components/browsing_topics/browsing_topics_service.h b/components/browsing_topics/browsing_topics_service.h
index 9dc40e9..b0faf1f0 100644
--- a/components/browsing_topics/browsing_topics_service.h
+++ b/components/browsing_topics/browsing_topics_service.h
@@ -7,6 +7,8 @@
 
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/privacy_sandbox/canonical_topic.h"
+#include "content/public/browser/render_frame_host.h"
+#include "third_party/blink/public/mojom/browsing_topics/browsing_topics.mojom-forward.h"
 #include "url/origin.h"
 
 namespace browsing_topics {
@@ -15,6 +17,14 @@
 // to other internal components (e.g. UX).
 class BrowsingTopicsService : public KeyedService {
  public:
+  // Return the browsing topics for a particular requesting context. The
+  // calling context and top context information will also be used for the
+  // access permission check, and for the `BrowsingTopicsPageLoadDataTracker` to
+  // track the API usage.
+  virtual std::vector<blink::mojom::EpochTopicPtr> GetBrowsingTopicsForJsApi(
+      const url::Origin& context_origin,
+      content::RenderFrameHost* main_frame) = 0;
+
   // Return the topics (i.e. one topic from each epoch) that can be potentially
   // exposed to a given site. Up to `kBrowsingTopicsNumberOfEpochsToExpose`
   // epochs' topics can be returned.
diff --git a/components/browsing_topics/browsing_topics_service_impl.cc b/components/browsing_topics/browsing_topics_service_impl.cc
index bd8ec9fb..3da4b7d2 100644
--- a/components/browsing_topics/browsing_topics_service_impl.cc
+++ b/components/browsing_topics/browsing_topics_service_impl.cc
@@ -4,21 +4,366 @@
 
 #include "components/browsing_topics/browsing_topics_service_impl.h"
 
+#include <random>
+
+#include "base/rand_util.h"
+#include "components/browsing_topics/browsing_topics_calculator.h"
+#include "components/browsing_topics/browsing_topics_page_load_data_tracker.h"
+#include "components/browsing_topics/util.h"
+#include "components/optimization_guide/content/browser/page_content_annotations_service.h"
+#include "content/public/browser/browsing_topics_site_data_manager.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/browsing_topics/browsing_topics.mojom.h"
+
 namespace browsing_topics {
 
+namespace {
+
+bool ShouldClearTopicsOnTopicsDataAccessibleSinceUpdated(
+    const BrowsingTopicsState& browsing_topics_state,
+    base::Time browsing_topics_data_accessible_since) {
+  // Here we rely on the fact that `browsing_topics_data_accessible_since` can
+  // only be updated to base::Time::Now() due to data deletion. So we'll either
+  // need to clear all topics data, or no-op. If this assumption no longer
+  // holds, we'd need to iterate over all epochs, check their calculation time,
+  // and selectively delete the epochs.
+  return !browsing_topics_state.epochs().empty() &&
+         browsing_topics_data_accessible_since >
+             browsing_topics_state.epochs().back().calculation_time();
+}
+
+struct StartupCalculateDecision {
+  bool clear_topics_data = true;
+  base::TimeDelta next_calculation_delay;
+};
+
+StartupCalculateDecision GetStartupCalculationDecision(
+    const BrowsingTopicsState& browsing_topics_state,
+    base::Time browsing_topics_data_accessible_since) {
+  // The topics have never been calculated. This could happen with a fresh
+  // profile or the if the config has updated. In case of a config update, the
+  // topics should have already been cleared when initializing the
+  // `BrowsingTopicsState`.
+  if (browsing_topics_state.next_scheduled_calculation_time().is_null()) {
+    return StartupCalculateDecision{
+        .clear_topics_data = false,
+        .next_calculation_delay = base::TimeDelta()};
+  }
+
+  // This could happen when clear-on-exit is turned on and has caused the
+  // cookies to be deleted on startup.
+  bool should_clear_topics_data =
+      ShouldClearTopicsOnTopicsDataAccessibleSinceUpdated(
+          browsing_topics_state, browsing_topics_data_accessible_since);
+
+  base::TimeDelta presumed_next_calculation_delay =
+      browsing_topics_state.next_scheduled_calculation_time() -
+      base::Time::Now();
+
+  // The scheduled calculation time was reached before the startup.
+  if (presumed_next_calculation_delay <= base::TimeDelta()) {
+    return StartupCalculateDecision{
+        .clear_topics_data = should_clear_topics_data,
+        .next_calculation_delay = base::TimeDelta()};
+  }
+
+  // This could happen if the machine time has changed since the last
+  // calculation. Recalculate immediately to align with the expected schedule
+  // rather than potentially stop computing for a very long time.
+  if (presumed_next_calculation_delay >=
+      2 * blink::features::kBrowsingTopicsTimePeriodPerEpoch.Get()) {
+    return StartupCalculateDecision{
+        .clear_topics_data = should_clear_topics_data,
+        .next_calculation_delay = base::TimeDelta()};
+  }
+
+  return StartupCalculateDecision{
+      .clear_topics_data = should_clear_topics_data,
+      .next_calculation_delay = presumed_next_calculation_delay};
+}
+
+}  // namespace
+
 BrowsingTopicsServiceImpl::~BrowsingTopicsServiceImpl() = default;
 
-BrowsingTopicsServiceImpl::BrowsingTopicsServiceImpl() = default;
+BrowsingTopicsServiceImpl::BrowsingTopicsServiceImpl(
+    const base::FilePath& profile_path,
+    privacy_sandbox::PrivacySandboxSettings* privacy_sandbox_settings,
+    history::HistoryService* history_service,
+    content::BrowsingTopicsSiteDataManager* site_data_manager,
+    optimization_guide::PageContentAnnotationsService* annotations_service)
+    : privacy_sandbox_settings_(privacy_sandbox_settings),
+      history_service_(history_service),
+      site_data_manager_(site_data_manager),
+      annotations_service_(annotations_service),
+      browsing_topics_state_(
+          profile_path,
+          base::BindOnce(
+              &BrowsingTopicsServiceImpl::OnBrowsingTopicsStateLoaded,
+              base::Unretained(this))) {
+  privacy_sandbox_settings_observation_.Observe(privacy_sandbox_settings);
+  history_service_observation_.Observe(history_service);
+
+  // Request the model now, to be able to run BatchAnnotatePageTopics() later.
+  // No need to wait for the callback (i.e. this is the expected usage).
+  annotations_service_->RequestAndNotifyWhenModelAvailable(
+      optimization_guide::AnnotationType::kPageTopics, base::DoNothing());
+}
+
+std::vector<blink::mojom::EpochTopicPtr>
+BrowsingTopicsServiceImpl::GetBrowsingTopicsForJsApi(
+    const url::Origin& context_origin,
+    content::RenderFrameHost* main_frame) {
+  if (!browsing_topics_state_loaded_)
+    return {};
+
+  if (!privacy_sandbox_settings_->IsTopicsAllowed())
+    return {};
+
+  if (!privacy_sandbox_settings_->IsTopicsAllowedForContext(
+          context_origin.GetURL(), main_frame->GetLastCommittedOrigin())) {
+    return {};
+  }
+
+  std::string context_domain =
+      net::registry_controlled_domains::GetDomainAndRegistry(
+          context_origin.GetURL(),
+          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+
+  HashedDomain hashed_context_domain = HashContextDomainForStorage(
+      browsing_topics_state_.hmac_key(), context_domain);
+
+  // Track the API usage context after the permissions check.
+  BrowsingTopicsPageLoadDataTracker::GetOrCreateForPage(main_frame->GetPage())
+      ->OnBrowsingTopicsApiUsed(hashed_context_domain, history_service_);
+
+  std::string top_domain =
+      net::registry_controlled_domains::GetDomainAndRegistry(
+          main_frame->GetLastCommittedOrigin().GetURL(),
+          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+
+  std::vector<blink::mojom::EpochTopicPtr> result_topics;
+  for (const EpochTopics* epoch :
+       browsing_topics_state_.EpochsForSite(top_domain)) {
+    absl::optional<Topic> topic = epoch->TopicForSite(
+        top_domain, hashed_context_domain, browsing_topics_state_.hmac_key());
+
+    // Only add a non-empty topic to the result.
+    if (!topic)
+      continue;
+
+    if (!privacy_sandbox_settings_->IsTopicAllowed(
+            privacy_sandbox::CanonicalTopic(*topic,
+                                            epoch->taxonomy_version()))) {
+      return {};
+    }
+
+    blink::mojom::EpochTopicPtr result_topic = blink::mojom::EpochTopic::New();
+    result_topic->topic = topic.value().value();
+    result_topic->config_version = base::StrCat(
+        {"chrome.", base::NumberToString(
+                        blink::features::kBrowsingTopicsConfigVersion.Get())});
+    result_topic->model_version = base::NumberToString(epoch->model_version());
+    result_topic->taxonomy_version =
+        base::NumberToString(epoch->taxonomy_version());
+    result_topic->version = base::StrCat({result_topic->config_version, ":",
+                                          result_topic->taxonomy_version, ":",
+                                          result_topic->model_version});
+    result_topics.push_back(std::move(result_topic));
+  }
+
+  // Remove duplicate entries.
+  std::sort(result_topics.begin(), result_topics.end());
+  result_topics.erase(std::unique(result_topics.begin(), result_topics.end()),
+                      result_topics.end());
+
+  // Shuffle the entries.
+  base::RandomShuffle(result_topics.begin(), result_topics.end());
+
+  return result_topics;
+}
 
 std::vector<privacy_sandbox::CanonicalTopic>
 BrowsingTopicsServiceImpl::GetTopicsForSiteForDisplay(
     const url::Origin& top_origin) const {
-  return {};
+  if (!browsing_topics_state_loaded_)
+    return {};
+
+  std::string top_domain =
+      net::registry_controlled_domains::GetDomainAndRegistry(
+          top_origin.GetURL(),
+          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+
+  std::vector<privacy_sandbox::CanonicalTopic> result;
+
+  for (const EpochTopics* epoch :
+       browsing_topics_state_.EpochsForSite(top_domain)) {
+    absl::optional<Topic> topic = epoch->TopicForSiteNoFiltering(
+        top_domain, browsing_topics_state_.hmac_key());
+
+    if (!topic)
+      continue;
+
+    result.emplace_back(*topic, epoch->taxonomy_version());
+  }
+
+  return result;
 }
 
 std::vector<privacy_sandbox::CanonicalTopic>
 BrowsingTopicsServiceImpl::GetTopTopicsForDisplay() const {
-  return {};
+  if (!browsing_topics_state_loaded_)
+    return {};
+
+  std::vector<privacy_sandbox::CanonicalTopic> result;
+
+  for (const EpochTopics& epoch : browsing_topics_state_.epochs()) {
+    for (const TopicAndDomains& topic :
+         epoch.top_topics_and_observing_domains()) {
+      if (!topic.IsValid())
+        continue;
+
+      result.emplace_back(topic.topic(), epoch.taxonomy_version());
+    }
+  }
+
+  return result;
+}
+
+std::unique_ptr<BrowsingTopicsCalculator>
+BrowsingTopicsServiceImpl::CreateCalculator(
+    privacy_sandbox::PrivacySandboxSettings* privacy_sandbox_settings,
+    history::HistoryService* history_service,
+    content::BrowsingTopicsSiteDataManager* site_data_manager,
+    optimization_guide::PageContentAnnotationsService* annotations_service,
+    BrowsingTopicsCalculator::CalculateCompletedCallback callback) {
+  return std::make_unique<BrowsingTopicsCalculator>(
+      privacy_sandbox_settings, history_service, site_data_manager,
+      annotations_service, std::move(callback));
+}
+
+const BrowsingTopicsState& BrowsingTopicsServiceImpl::browsing_topics_state() {
+  return browsing_topics_state_;
+}
+
+void BrowsingTopicsServiceImpl::ScheduleBrowsingTopicsCalculation(
+    base::TimeDelta delay) {
+  DCHECK(browsing_topics_state_loaded_);
+
+  // `this` owns the timer, which is automatically cancelled on destruction, so
+  // base::Unretained(this) is safe.
+  schedule_calculate_timer_.Start(
+      FROM_HERE, delay,
+      base::BindOnce(&BrowsingTopicsServiceImpl::CalculateBrowsingTopics,
+                     base::Unretained(this)));
+}
+
+void BrowsingTopicsServiceImpl::CalculateBrowsingTopics() {
+  DCHECK(browsing_topics_state_loaded_);
+
+  DCHECK(!topics_calculator_);
+
+  // `this` owns `topics_calculator_` so `topics_calculator_` should not invoke
+  // the callback once it's destroyed.
+  topics_calculator_ = CreateCalculator(
+      privacy_sandbox_settings_, history_service_, site_data_manager_,
+      annotations_service_,
+      base::BindOnce(
+          &BrowsingTopicsServiceImpl::OnCalculateBrowsingTopicsCompleted,
+          base::Unretained(this)));
+}
+
+void BrowsingTopicsServiceImpl::OnCalculateBrowsingTopicsCompleted(
+    EpochTopics epoch_topics) {
+  DCHECK(browsing_topics_state_loaded_);
+
+  DCHECK(topics_calculator_);
+  topics_calculator_.reset();
+
+  browsing_topics_state_.AddEpoch(std::move(epoch_topics));
+  browsing_topics_state_.UpdateNextScheduledCalculationTime();
+
+  ScheduleBrowsingTopicsCalculation(
+      blink::features::kBrowsingTopicsTimePeriodPerEpoch.Get());
+}
+
+void BrowsingTopicsServiceImpl::OnBrowsingTopicsStateLoaded() {
+  DCHECK(!browsing_topics_state_loaded_);
+  browsing_topics_state_loaded_ = true;
+
+  base::Time browsing_topics_data_sccessible_since =
+      privacy_sandbox_settings_->TopicsDataAccessibleSince();
+
+  StartupCalculateDecision decision = GetStartupCalculationDecision(
+      browsing_topics_state_, browsing_topics_data_sccessible_since);
+
+  if (decision.clear_topics_data)
+    browsing_topics_state_.ClearAllTopics();
+
+  site_data_manager_->ExpireDataBefore(browsing_topics_data_sccessible_since);
+
+  ScheduleBrowsingTopicsCalculation(decision.next_calculation_delay);
+}
+
+void BrowsingTopicsServiceImpl::Shutdown() {
+  privacy_sandbox_settings_observation_.Reset();
+  history_service_observation_.Reset();
+}
+
+void BrowsingTopicsServiceImpl::OnTopicsDataAccessibleSinceUpdated() {
+  if (!browsing_topics_state_loaded_)
+    return;
+
+  if (ShouldClearTopicsOnTopicsDataAccessibleSinceUpdated(
+          browsing_topics_state_,
+          privacy_sandbox_settings_->TopicsDataAccessibleSince())) {
+    browsing_topics_state_.ClearAllTopics();
+    site_data_manager_->ExpireDataBefore(
+        privacy_sandbox_settings_->TopicsDataAccessibleSince());
+  }
+
+  // Abort the outstanding topics calculation and restart immediately.
+  if (topics_calculator_) {
+    DCHECK(!schedule_calculate_timer_.IsRunning());
+
+    topics_calculator_.reset();
+    CalculateBrowsingTopics();
+  }
+}
+
+void BrowsingTopicsServiceImpl::OnURLsDeleted(
+    history::HistoryService* history_service,
+    const history::DeletionInfo& deletion_info) {
+  if (!browsing_topics_state_loaded_)
+    return;
+
+  // Ignore invalid time_range.
+  if (!deletion_info.IsAllHistory() && !deletion_info.time_range().IsValid())
+    return;
+
+  for (size_t i = 0; i < browsing_topics_state_.epochs().size(); ++i) {
+    const EpochTopics& epoch_topics = browsing_topics_state_.epochs()[i];
+
+    if (epoch_topics.empty())
+      continue;
+
+    bool time_range_overlap =
+        epoch_topics.calculation_time() >= deletion_info.time_range().begin() &&
+        DeriveHistoryDataStartTime(epoch_topics.calculation_time()) <=
+            deletion_info.time_range().end();
+
+    if (time_range_overlap)
+      browsing_topics_state_.ClearOneEpoch(i);
+  }
+
+  // If there's an outstanding topics calculation, abort and restart it.
+  if (topics_calculator_) {
+    DCHECK(!schedule_calculate_timer_.IsRunning());
+
+    topics_calculator_.reset();
+    CalculateBrowsingTopics();
+  }
 }
 
 }  // namespace browsing_topics
diff --git a/components/browsing_topics/browsing_topics_service_impl.h b/components/browsing_topics/browsing_topics_service_impl.h
index cd722584..0aaa045 100644
--- a/components/browsing_topics/browsing_topics_service_impl.h
+++ b/components/browsing_topics/browsing_topics_service_impl.h
@@ -6,13 +6,35 @@
 #define COMPONENTS_BROWSING_TOPICS_BROWSING_TOPICS_SERVICE_IMPL_H_
 
 #include "base/memory/weak_ptr.h"
+#include "base/scoped_observation.h"
+#include "base/timer/timer.h"
+#include "components/browsing_topics/browsing_topics_calculator.h"
 #include "components/browsing_topics/browsing_topics_service.h"
+#include "components/browsing_topics/browsing_topics_state.h"
+#include "components/history/core/browser/history_service.h"
+#include "components/history/core/browser/history_service_observer.h"
+#include "components/privacy_sandbox/privacy_sandbox_settings.h"
+
+namespace content {
+class BrowsingTopicsSiteDataManager;
+}  // namespace content
+
+namespace optimization_guide {
+class PageContentAnnotationsService;
+}  // namespace optimization_guide
 
 namespace browsing_topics {
 
-// A profile keyed service for providing the topics to a requesting context or
-// to other internal components (e.g. UX).
-class BrowsingTopicsServiceImpl : public BrowsingTopicsService {
+// A profile keyed service for scheduling browsing topics calculation,
+// calculating the topics to give to a requesting context or to other internal
+// components (e.g. UX), and handling relevant data deletion. Browsing topics
+// calculation will happen periodically every time period of
+// `kBrowsingTopicsTimePeriodPerEpoch`. See the `BrowsingTopicsCalculator` class
+// for the calculation details.
+class BrowsingTopicsServiceImpl
+    : public BrowsingTopicsService,
+      public privacy_sandbox::PrivacySandboxSettings::Observer,
+      public history::HistoryServiceObserver {
  public:
   BrowsingTopicsServiceImpl(const BrowsingTopicsServiceImpl&) = delete;
   BrowsingTopicsServiceImpl& operator=(const BrowsingTopicsServiceImpl&) =
@@ -22,16 +44,109 @@
 
   ~BrowsingTopicsServiceImpl() override;
 
+  std::vector<blink::mojom::EpochTopicPtr> GetBrowsingTopicsForJsApi(
+      const url::Origin& context_origin,
+      content::RenderFrameHost* main_frame) override;
+
   std::vector<privacy_sandbox::CanonicalTopic> GetTopicsForSiteForDisplay(
       const url::Origin& top_origin) const override;
 
   std::vector<privacy_sandbox::CanonicalTopic> GetTopTopicsForDisplay()
       const override;
 
+ protected:
+  // The following methods are marked protected so that they may be overridden
+  // by tests.
+
+  virtual std::unique_ptr<BrowsingTopicsCalculator> CreateCalculator(
+      privacy_sandbox::PrivacySandboxSettings* privacy_sandbox_settings,
+      history::HistoryService* history_service,
+      content::BrowsingTopicsSiteDataManager* site_data_manager,
+      optimization_guide::PageContentAnnotationsService* annotations_service,
+      BrowsingTopicsCalculator::CalculateCompletedCallback callback);
+
+  // Allow tests to access `browsing_topics_state_`.
+  virtual const BrowsingTopicsState& browsing_topics_state();
+
+  // privacy_sandbox::PrivacySandboxSettings::Observer:
+  //
+  // When the floc-accessible-since time is updated (due to e.g. cookies
+  // deletion), we'll invalidate the underlying browsing topics.
+  void OnTopicsDataAccessibleSinceUpdated() override;
+
+  // history::HistoryServiceObserver:
+  //
+  // On history deletion, the top topics of history epochs will be invalidated
+  // if the deletion time range overlaps with the time range of the underlying
+  // data used to derive the topics.
+  void OnURLsDeleted(history::HistoryService* history_service,
+                     const history::DeletionInfo& deletion_info) override;
+
+  // Called when the outstanding calculation completes. It's going to reset
+  // `topics_calculator_`, add the new `epoch_topics` to `browsing_topics_`, and
+  // schedule the next calculation.
+  virtual void OnCalculateBrowsingTopicsCompleted(EpochTopics epoch_topics);
+
  private:
   friend class BrowsingTopicsServiceFactory;
+  friend class BrowsingTopicsBrowserTest;
+  friend class TesterBrowsingTopicsService;
 
-  BrowsingTopicsServiceImpl();
+  BrowsingTopicsServiceImpl(
+      const base::FilePath& profile_path,
+      privacy_sandbox::PrivacySandboxSettings* privacy_sandbox_settings,
+      history::HistoryService* history_service,
+      content::BrowsingTopicsSiteDataManager* site_data_manager,
+      optimization_guide::PageContentAnnotationsService* annotations_service);
+
+  void ScheduleBrowsingTopicsCalculation(base::TimeDelta delay);
+
+  // Initialize `topics_calculator_` to start calculating this epoch's top
+  // topics and context observed topics.
+  void CalculateBrowsingTopics();
+
+  // Set `browsing_topics_state_loaded_` to true. Start scheduling the topics
+  // calculation.
+  void OnBrowsingTopicsStateLoaded();
+
+  // KeyedService:
+  void Shutdown() override;
+
+  // These pointers are safe to hold and use throughout the lifetime of
+  // `this`:
+  // - For `privacy_sandbox_settings_`, `history_service_` and
+  // `annotations_service_`: the dependency declared in
+  // `BrowsingTopicsServiceFactory`'s constructor guarantees that
+  // `BrowsingTopicsService` will be destroyed first before those depend-on
+  // services.
+  // - For `site_data_manager_`: it lives in the StoragePartition which lives
+  // in the BrowserContext, and thus outlives all BrowserContext's KeyedService.
+  raw_ptr<privacy_sandbox::PrivacySandboxSettings> privacy_sandbox_settings_;
+  raw_ptr<history::HistoryService> history_service_;
+  raw_ptr<content::BrowsingTopicsSiteDataManager> site_data_manager_;
+  raw_ptr<optimization_guide::PageContentAnnotationsService>
+      annotations_service_;
+
+  BrowsingTopicsState browsing_topics_state_;
+
+  // Whether the `browsing_topics_state_` has finished loading. Before the
+  // loading finishes, accessor methods will use a default handling (i.e. return
+  // an empty value; skip usage tracking; ignore data deletions). This is fine
+  // in practice, as the loading should be reasonably fast, and normally the API
+  // usage or data deletion won't happen at the browser start.
+  bool browsing_topics_state_loaded_ = false;
+
+  std::unique_ptr<BrowsingTopicsCalculator> topics_calculator_;
+
+  base::OneShotTimer schedule_calculate_timer_;
+
+  base::ScopedObservation<privacy_sandbox::PrivacySandboxSettings,
+                          privacy_sandbox::PrivacySandboxSettings::Observer>
+      privacy_sandbox_settings_observation_{this};
+
+  base::ScopedObservation<history::HistoryService,
+                          history::HistoryServiceObserver>
+      history_service_observation_{this};
 
   base::WeakPtrFactory<BrowsingTopicsServiceImpl> weak_ptr_factory_{this};
 };
diff --git a/components/browsing_topics/browsing_topics_service_impl_unittest.cc b/components/browsing_topics/browsing_topics_service_impl_unittest.cc
new file mode 100644
index 0000000..1f5c02e
--- /dev/null
+++ b/components/browsing_topics/browsing_topics_service_impl_unittest.cc
@@ -0,0 +1,1222 @@
+// 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 "components/browsing_topics/browsing_topics_service_impl.h"
+
+#include "base/json/json_file_value_serializer.h"
+#include "base/json/values_util.h"
+#include "base/memory/raw_ptr.h"
+#include "base/test/bind.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/browsing_topics/test_util.h"
+#include "components/browsing_topics/util.h"
+#include "components/content_settings/core/browser/cookie_settings.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/history/core/browser/history_database_params.h"
+#include "components/history/core/browser/history_service.h"
+#include "components/history/core/test/test_history_database.h"
+#include "components/optimization_guide/content/browser/page_content_annotations_service.h"
+#include "components/optimization_guide/content/browser/test_page_content_annotator.h"
+#include "components/optimization_guide/core/test_model_info_builder.h"
+#include "components/optimization_guide/core/test_optimization_guide_model_provider.h"
+#include "components/privacy_sandbox/privacy_sandbox_prefs.h"
+#include "components/privacy_sandbox/privacy_sandbox_settings.h"
+#include "components/privacy_sandbox/privacy_sandbox_test_util.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "content/public/browser/browsing_topics_site_data_manager.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/test/browsing_topics_test_util.h"
+#include "content/public/test/navigation_simulator.h"
+#include "content/public/test/test_utils.h"
+#include "content/public/test/web_contents_tester.h"
+#include "content/test/test_render_view_host.h"
+#include "third_party/blink/public/mojom/browsing_topics/browsing_topics.mojom.h"
+
+namespace browsing_topics {
+
+namespace {
+
+constexpr base::TimeDelta kCalculatorDelay = base::Seconds(10);
+
+constexpr browsing_topics::HmacKey kTestKey = {1};
+
+constexpr base::Time kTime1 =
+    base::Time::FromDeltaSinceWindowsEpoch(base::Days(1));
+constexpr base::Time kTime2 =
+    base::Time::FromDeltaSinceWindowsEpoch(base::Days(2));
+
+constexpr size_t kTaxonomySize = 349;
+constexpr int kTaxonomyVersion = 1;
+constexpr int64_t kModelVersion = 5000000000LL;
+constexpr size_t kPaddedTopTopicsStartIndex = 3;
+
+EpochTopics CreateTestEpochTopics(
+    const std::vector<std::pair<Topic, std::set<HashedDomain>>>& topics,
+    base::Time calculation_time) {
+  DCHECK_EQ(topics.size(), 5u);
+
+  std::vector<TopicAndDomains> top_topics_and_observing_domains;
+  for (size_t i = 0; i < 5; ++i) {
+    top_topics_and_observing_domains.emplace_back(topics[i].first,
+                                                  topics[i].second);
+  }
+
+  return EpochTopics(std::move(top_topics_and_observing_domains),
+                     kPaddedTopTopicsStartIndex, kTaxonomySize,
+                     kTaxonomyVersion, kModelVersion, calculation_time);
+}
+
+}  // namespace
+
+// A tester class that allows mocking the topics calculators (i.e. the result
+// and the finish delay).
+class TesterBrowsingTopicsService : public BrowsingTopicsServiceImpl {
+ public:
+  TesterBrowsingTopicsService(
+      const base::FilePath& profile_path,
+      privacy_sandbox::PrivacySandboxSettings* privacy_sandbox_settings,
+      history::HistoryService* history_service,
+      content::BrowsingTopicsSiteDataManager* site_data_manager,
+      optimization_guide::PageContentAnnotationsService* annotations_service,
+      base::queue<EpochTopics> mock_calculator_results,
+      base::TimeDelta calculator_finish_delay)
+      : BrowsingTopicsServiceImpl(profile_path,
+                                  privacy_sandbox_settings,
+                                  history_service,
+                                  site_data_manager,
+                                  annotations_service),
+        mock_calculator_results_(std::move(mock_calculator_results)),
+        calculator_finish_delay_(calculator_finish_delay) {}
+
+  ~TesterBrowsingTopicsService() override = default;
+
+  TesterBrowsingTopicsService(const TesterBrowsingTopicsService&) = delete;
+  TesterBrowsingTopicsService& operator=(const TesterBrowsingTopicsService&) =
+      delete;
+  TesterBrowsingTopicsService(TesterBrowsingTopicsService&&) = delete;
+  TesterBrowsingTopicsService& operator=(TesterBrowsingTopicsService&&) =
+      delete;
+
+  std::unique_ptr<BrowsingTopicsCalculator> CreateCalculator(
+      privacy_sandbox::PrivacySandboxSettings* privacy_sandbox_settings,
+      history::HistoryService* history_service,
+      content::BrowsingTopicsSiteDataManager* site_data_manager,
+      optimization_guide::PageContentAnnotationsService* annotations_service,
+      BrowsingTopicsCalculator::CalculateCompletedCallback callback) override {
+    DCHECK(!mock_calculator_results_.empty());
+
+    ++started_calculations_count_;
+
+    EpochTopics next_epoch = std::move(mock_calculator_results_.front());
+    mock_calculator_results_.pop();
+
+    return std::make_unique<TesterBrowsingTopicsCalculator>(
+        std::move(callback), std::move(next_epoch), calculator_finish_delay_);
+  }
+
+  const BrowsingTopicsState& browsing_topics_state() override {
+    return BrowsingTopicsServiceImpl::browsing_topics_state();
+  }
+
+  void OnTopicsDataAccessibleSinceUpdated() override {
+    BrowsingTopicsServiceImpl::OnTopicsDataAccessibleSinceUpdated();
+  }
+
+  void OnURLsDeleted(history::HistoryService* history_service,
+                     const history::DeletionInfo& deletion_info) override {
+    BrowsingTopicsServiceImpl::OnURLsDeleted(history_service, deletion_info);
+  }
+
+  // The number of calculations that have started, including those that have
+  // finished, those that are ongoing, and those that have been canceled.
+  size_t started_calculations_count() const {
+    return started_calculations_count_;
+  }
+
+ private:
+  base::queue<EpochTopics> mock_calculator_results_;
+  base::TimeDelta calculator_finish_delay_;
+
+  size_t started_calculations_count_ = 0u;
+};
+
+class BrowsingTopicsServiceImplTest
+    : public content::RenderViewHostTestHarness {
+ public:
+  BrowsingTopicsServiceImplTest()
+      : content::RenderViewHostTestHarness(
+            base::test::TaskEnvironment::TimeSource::MOCK_TIME) {
+    scoped_feature_list_.InitWithFeatures(
+        /*enabled_features=*/{blink::features::kBrowsingTopics},
+        /*disabled_features=*/{});
+
+    OverrideHmacKeyForTesting(kTestKey);
+
+    EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+    content_settings::CookieSettings::RegisterProfilePrefs(prefs_.registry());
+    HostContentSettingsMap::RegisterProfilePrefs(prefs_.registry());
+    privacy_sandbox::RegisterProfilePrefs(prefs_.registry());
+
+    host_content_settings_map_ = base::MakeRefCounted<HostContentSettingsMap>(
+        &prefs_, /*is_off_the_record=*/false, /*store_last_modified=*/false,
+        /*restore_session=*/false);
+    cookie_settings_ = base::MakeRefCounted<content_settings::CookieSettings>(
+        host_content_settings_map_.get(), &prefs_, false, "chrome-extension");
+
+    auto privacy_sandbox_delegate = std::make_unique<
+        privacy_sandbox_test_util::MockPrivacySandboxSettingsDelegate>();
+    privacy_sandbox_delegate->SetupDefaultResponse(/*restricted=*/false,
+                                                   /*confirmed=*/true);
+    privacy_sandbox_settings_ =
+        std::make_unique<privacy_sandbox::PrivacySandboxSettings>(
+            std::move(privacy_sandbox_delegate),
+            host_content_settings_map_.get(), cookie_settings_, &prefs_,
+            /*incognito_profile=*/false);
+
+    history_service_ = std::make_unique<history::HistoryService>();
+    history_service_->Init(
+        history::TestHistoryDatabaseParamsForPath(temp_dir_.GetPath()));
+
+    optimization_guide_model_provider_ = std::make_unique<
+        optimization_guide::TestOptimizationGuideModelProvider>();
+    page_content_annotations_service_ =
+        std::make_unique<optimization_guide::PageContentAnnotationsService>(
+            "en-US", optimization_guide_model_provider_.get(),
+            history_service_.get(), nullptr, base::FilePath(), nullptr);
+
+    page_content_annotations_service_->OverridePageContentAnnotatorForTesting(
+        &test_page_content_annotator_);
+
+    task_environment()->RunUntilIdle();
+  }
+
+  ~BrowsingTopicsServiceImplTest() override = default;
+
+  void TearDown() override {
+    DCHECK(history_service_);
+
+    browsing_topics_service_.reset();
+
+    base::RunLoop run_loop;
+    history_service_->SetOnBackendDestroyTask(run_loop.QuitClosure());
+    history_service_->Shutdown();
+    run_loop.Run();
+
+    page_content_annotations_service_.reset();
+    optimization_guide_model_provider_.reset();
+    task_environment()->RunUntilIdle();
+
+    host_content_settings_map_->ShutdownOnUIThread();
+
+    content::RenderViewHostTestHarness::TearDown();
+  }
+
+  void NavigateToPage(const GURL& url) {
+    auto simulator = content::NavigationSimulator::CreateBrowserInitiated(
+        url, web_contents());
+    simulator->SetTransition(ui::PageTransition::PAGE_TRANSITION_TYPED);
+    simulator->Commit();
+  }
+
+  content::BrowsingTopicsSiteDataManager* topics_site_data_manager() {
+    return web_contents()
+        ->GetMainFrame()
+        ->GetProcess()
+        ->GetStoragePartition()
+        ->GetBrowsingTopicsSiteDataManager();
+  }
+
+  base::FilePath BrowsingTopicsStateFilePath() {
+    return temp_dir_.GetPath().Append(FILE_PATH_LITERAL("BrowsingTopicsState"));
+  }
+
+  void CreateBrowsingTopicsStateFile(
+      const std::vector<EpochTopics>& epochs,
+      base::Time next_scheduled_calculation_time) {
+    base::Value::List epochs_list;
+    for (const EpochTopics& epoch : epochs) {
+      epochs_list.Append(epoch.ToDictValue());
+    }
+
+    base::Value::Dict dict;
+    dict.Set("epochs", std::move(epochs_list));
+    dict.Set("next_scheduled_calculation_time",
+             base::TimeToValue(next_scheduled_calculation_time));
+    dict.Set("hex_encoded_hmac_key", base::HexEncode(kTestKey));
+    dict.Set("config_version", 1);
+
+    JSONFileValueSerializer(BrowsingTopicsStateFilePath()).Serialize(dict);
+  }
+
+  void InitializeBrowsingTopicsService(
+      base::queue<EpochTopics> mock_calculator_results) {
+    browsing_topics_service_ = std::make_unique<TesterBrowsingTopicsService>(
+        temp_dir_.GetPath(), privacy_sandbox_settings_.get(),
+        history_service_.get(), topics_site_data_manager(),
+        page_content_annotations_service_.get(),
+        std::move(mock_calculator_results), kCalculatorDelay);
+  }
+
+  const BrowsingTopicsState& browsing_topics_state() {
+    DCHECK(browsing_topics_service_);
+    return browsing_topics_service_->browsing_topics_state();
+  }
+
+  HashedDomain GetHashedDomain(const std::string& domain) {
+    return HashContextDomainForStorage(kTestKey, domain);
+  }
+
+ protected:
+  base::test::ScopedFeatureList scoped_feature_list_;
+
+  base::ScopedTempDir temp_dir_;
+
+  sync_preferences::TestingPrefServiceSyncable prefs_;
+  scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
+  scoped_refptr<content_settings::CookieSettings> cookie_settings_;
+  std::unique_ptr<privacy_sandbox::PrivacySandboxSettings>
+      privacy_sandbox_settings_;
+
+  std::unique_ptr<history::HistoryService> history_service_;
+
+  std::unique_ptr<optimization_guide::TestOptimizationGuideModelProvider>
+      optimization_guide_model_provider_;
+  std::unique_ptr<optimization_guide::PageContentAnnotationsService>
+      page_content_annotations_service_;
+
+  optimization_guide::TestPageContentAnnotator test_page_content_annotator_;
+
+  std::unique_ptr<TesterBrowsingTopicsService> browsing_topics_service_;
+};
+
+TEST_F(BrowsingTopicsServiceImplTest, EmptyInitialState_CalculationScheduling) {
+  base::Time start_time = base::Time::Now();
+
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(CreateTestEpochTopics({{Topic(1), {}},
+                                                      {Topic(2), {}},
+                                                      {Topic(3), {}},
+                                                      {Topic(4), {}},
+                                                      {Topic(5), {}}},
+                                                     kTime1));
+  mock_calculator_results.push(CreateTestEpochTopics({{Topic(6), {}},
+                                                      {Topic(7), {}},
+                                                      {Topic(8), {}},
+                                                      {Topic(9), {}},
+                                                      {Topic(10), {}}},
+                                                     kTime2));
+
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  EXPECT_EQ(browsing_topics_service_->started_calculations_count(), 0u);
+
+  // Finish file loading.
+  task_environment()->RunUntilIdle();
+
+  EXPECT_EQ(browsing_topics_service_->started_calculations_count(), 1u);
+
+  EXPECT_TRUE(browsing_topics_state().epochs().empty());
+
+  // Finish the calculation.
+  task_environment()->FastForwardBy(kCalculatorDelay);
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 1u);
+  EXPECT_EQ(browsing_topics_state().epochs()[0].calculation_time(), kTime1);
+  EXPECT_EQ(browsing_topics_state().next_scheduled_calculation_time(),
+            start_time + kCalculatorDelay + base::Days(7));
+
+  // Advance the time to right before the next scheduled calculation. The next
+  // calculation should not happen.
+  task_environment()->FastForwardBy(base::Days(7) - base::Seconds(1));
+
+  EXPECT_EQ(browsing_topics_service_->started_calculations_count(), 1u);
+
+  // Advance the time to the scheduled calculation time. A calculation should
+  // happen.
+  task_environment()->FastForwardBy(base::Seconds(1));
+
+  EXPECT_EQ(browsing_topics_service_->started_calculations_count(), 2u);
+
+  // Finish the calculation.
+  task_environment()->FastForwardBy(kCalculatorDelay);
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 2u);
+  EXPECT_EQ(browsing_topics_state().epochs()[1].calculation_time(), kTime2);
+  EXPECT_EQ(browsing_topics_state().next_scheduled_calculation_time(),
+            start_time + 2 * kCalculatorDelay + 2 * base::Days(7));
+}
+
+TEST_F(BrowsingTopicsServiceImplTest,
+       StartFromPreexistingState_CalculateAtScheduledTime) {
+  base::Time start_time = base::Time::Now();
+
+  std::vector<EpochTopics> preexisting_epochs;
+  preexisting_epochs.push_back(CreateTestEpochTopics({{Topic(1), {}},
+                                                      {Topic(2), {}},
+                                                      {Topic(3), {}},
+                                                      {Topic(4), {}},
+                                                      {Topic(5), {}}},
+                                                     kTime1));
+
+  CreateBrowsingTopicsStateFile(
+      std::move(preexisting_epochs),
+      /*next_scheduled_calculation_time=*/start_time + base::Days(1));
+
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(CreateTestEpochTopics({{Topic(6), {}},
+                                                      {Topic(7), {}},
+                                                      {Topic(8), {}},
+                                                      {Topic(9), {}},
+                                                      {Topic(10), {}}},
+                                                     kTime2));
+
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  // Finish file loading.
+  task_environment()->RunUntilIdle();
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 1u);
+  EXPECT_EQ(browsing_topics_state().epochs()[0].calculation_time(), kTime1);
+  EXPECT_EQ(browsing_topics_state().next_scheduled_calculation_time(),
+            start_time + base::Days(1));
+
+  EXPECT_EQ(browsing_topics_service_->started_calculations_count(), 0u);
+
+  // Advance the time to the scheduled calculation time. A calculation should
+  // happen.
+  task_environment()->FastForwardBy(base::Days(1));
+
+  EXPECT_EQ(browsing_topics_service_->started_calculations_count(), 1u);
+  // Finish the calculation.
+  task_environment()->FastForwardBy(kCalculatorDelay);
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 2u);
+  EXPECT_EQ(browsing_topics_state().epochs()[1].calculation_time(), kTime2);
+  EXPECT_EQ(browsing_topics_state().next_scheduled_calculation_time(),
+            start_time + base::Days(1) + kCalculatorDelay + base::Days(7));
+}
+
+TEST_F(
+    BrowsingTopicsServiceImplTest,
+    StartFromPreexistingState_ScheduledTimeReachedBeforeStartup_CalculateImmediately) {
+  base::Time start_time = base::Time::Now();
+
+  std::vector<EpochTopics> preexisting_epochs;
+  preexisting_epochs.push_back(CreateTestEpochTopics({{Topic(1), {}},
+                                                      {Topic(2), {}},
+                                                      {Topic(3), {}},
+                                                      {Topic(4), {}},
+                                                      {Topic(5), {}}},
+                                                     kTime1));
+
+  CreateBrowsingTopicsStateFile(
+      std::move(preexisting_epochs),
+      /*next_scheduled_calculation_time=*/start_time - base::Seconds(1));
+
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(CreateTestEpochTopics({{Topic(6), {}},
+                                                      {Topic(7), {}},
+                                                      {Topic(8), {}},
+                                                      {Topic(9), {}},
+                                                      {Topic(10), {}}},
+                                                     kTime2));
+
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  // Finish file loading.
+  task_environment()->RunUntilIdle();
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 1u);
+  EXPECT_EQ(browsing_topics_state().epochs()[0].calculation_time(), kTime1);
+  EXPECT_EQ(browsing_topics_state().next_scheduled_calculation_time(),
+            start_time - base::Seconds(1));
+
+  EXPECT_EQ(browsing_topics_service_->started_calculations_count(), 1u);
+}
+
+TEST_F(
+    BrowsingTopicsServiceImplTest,
+    StartFromPreexistingState_TopicsAccessibleSinceUpdated_ResetStateAndStorage_CalculateAtScheduledTime) {
+  base::Time start_time = base::Time::Now();
+
+  std::vector<EpochTopics> preexisting_epochs;
+  preexisting_epochs.push_back(
+      CreateTestEpochTopics({{Topic(1), {}},
+                             {Topic(2), {}},
+                             {Topic(3), {}},
+                             {Topic(4), {}},
+                             {Topic(5), {}}},
+                            start_time - base::Days(1)));
+
+  // Add some arbitrary data to site data storage. The intent is just to test
+  // data deletion.
+  topics_site_data_manager()->OnBrowsingTopicsApiUsed(
+      HashMainFrameHostForStorage("a.com"), {HashedDomain(1)},
+      base::Time::Now());
+
+  task_environment()->FastForwardBy(base::Seconds(1));
+  privacy_sandbox_settings_->OnCookiesCleared();
+
+  EXPECT_EQ(
+      content::GetBrowsingTopicsApiUsage(topics_site_data_manager()).size(),
+      1u);
+
+  CreateBrowsingTopicsStateFile(
+      std::move(preexisting_epochs),
+      /*next_scheduled_calculation_time=*/start_time + base::Days(1));
+
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(6), {}},
+                             {Topic(7), {}},
+                             {Topic(8), {}},
+                             {Topic(9), {}},
+                             {Topic(10), {}}},
+                            start_time - base::Days(1)));
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  // Finish file loading.
+  task_environment()->RunUntilIdle();
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 0u);
+  EXPECT_EQ(browsing_topics_service_->started_calculations_count(), 0u);
+  EXPECT_EQ(
+      content::GetBrowsingTopicsApiUsage(topics_site_data_manager()).size(),
+      0u);
+}
+
+TEST_F(
+    BrowsingTopicsServiceImplTest,
+    StartFromPreexistingState_UnexpectedNextCalculationDelay_ResetState_CalculateImmediately) {
+  base::Time start_time = base::Time::Now();
+
+  std::vector<EpochTopics> preexisting_epochs;
+  preexisting_epochs.push_back(
+      CreateTestEpochTopics({{Topic(1), {}},
+                             {Topic(2), {}},
+                             {Topic(3), {}},
+                             {Topic(4), {}},
+                             {Topic(5), {}}},
+                            start_time - base::Days(1)));
+
+  privacy_sandbox_settings_->OnCookiesCleared();
+
+  CreateBrowsingTopicsStateFile(
+      std::move(preexisting_epochs),
+      /*next_scheduled_calculation_time=*/start_time + base::Days(15));
+
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(CreateTestEpochTopics({{Topic(6), {}},
+                                                      {Topic(7), {}},
+                                                      {Topic(8), {}},
+                                                      {Topic(9), {}},
+                                                      {Topic(10), {}}},
+                                                     kTime2));
+
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  // Finish file loading.
+  task_environment()->RunUntilIdle();
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 0u);
+  EXPECT_EQ(browsing_topics_service_->started_calculations_count(), 1u);
+}
+
+TEST_F(BrowsingTopicsServiceImplTest,
+       StartFromPreexistingState_DefaultHandlingBeforeLoadFinish) {
+  base::Time start_time = base::Time::Now();
+
+  std::vector<EpochTopics> preexisting_epochs;
+  preexisting_epochs.push_back(
+      CreateTestEpochTopics({{Topic(1), {GetHashedDomain("bar.com")}},
+                             {Topic(2), {GetHashedDomain("bar.com")}},
+                             {Topic(3), {GetHashedDomain("bar.com")}},
+                             {Topic(4), {GetHashedDomain("bar.com")}},
+                             {Topic(5), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+
+  CreateBrowsingTopicsStateFile(
+      std::move(preexisting_epochs),
+      /*next_scheduled_calculation_time=*/start_time + base::Days(1));
+
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(CreateTestEpochTopics({{Topic(6), {}},
+                                                      {Topic(7), {}},
+                                                      {Topic(8), {}},
+                                                      {Topic(9), {}},
+                                                      {Topic(10), {}}},
+                                                     kTime2));
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  NavigateToPage(GURL("https://www.foo.com"));
+
+  EXPECT_TRUE(browsing_topics_service_
+                  ->GetBrowsingTopicsForJsApi(
+                      /*context_origin=*/url::Origin::Create(
+                          GURL("https://www.bar.com")),
+                      web_contents()->GetMainFrame())
+                  .empty());
+  EXPECT_TRUE(browsing_topics_service_
+                  ->GetTopicsForSiteForDisplay(
+                      url::Origin::Create(GURL("https://www.bar.com")))
+                  .empty());
+  EXPECT_TRUE(browsing_topics_service_->GetTopTopicsForDisplay().empty());
+
+  // Finish file loading.
+  task_environment()->RunUntilIdle();
+
+  EXPECT_FALSE(browsing_topics_service_
+                   ->GetBrowsingTopicsForJsApi(
+                       /*context_origin=*/url::Origin::Create(
+                           GURL("https://www.bar.com")),
+                       web_contents()->GetMainFrame())
+                   .empty());
+  EXPECT_FALSE(browsing_topics_service_
+                   ->GetTopicsForSiteForDisplay(
+                       url::Origin::Create(GURL("https://www.bar.com")))
+                   .empty());
+  EXPECT_FALSE(browsing_topics_service_->GetTopTopicsForDisplay().empty());
+}
+
+TEST_F(
+    BrowsingTopicsServiceImplTest,
+    OnTopicsDataAccessibleSinceUpdated_ResetState_ClearTopicsSiteDataStorage) {
+  base::Time start_time = base::Time::Now();
+
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(CreateTestEpochTopics({{Topic(1), {}},
+                                                      {Topic(2), {}},
+                                                      {Topic(3), {}},
+                                                      {Topic(4), {}},
+                                                      {Topic(5), {}}},
+                                                     start_time));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(6), {}},
+                             {Topic(7), {}},
+                             {Topic(8), {}},
+                             {Topic(9), {}},
+                             {Topic(10), {}}},
+                            start_time + kCalculatorDelay + base::Days(7)));
+
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  // Finish file loading and two calculations.
+  task_environment()->FastForwardBy(2 * kCalculatorDelay + base::Days(7));
+
+  // Add some arbitrary data to site data storage. The intent is just to test
+  // data deletion.
+  topics_site_data_manager()->OnBrowsingTopicsApiUsed(
+      HashMainFrameHostForStorage("a.com"), {HashedDomain(1)},
+      base::Time::Now());
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 2u);
+  EXPECT_EQ(
+      content::GetBrowsingTopicsApiUsage(topics_site_data_manager()).size(),
+      1u);
+
+  task_environment()->FastForwardBy(base::Seconds(1));
+  privacy_sandbox_settings_->OnCookiesCleared();
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 0u);
+  EXPECT_EQ(
+      content::GetBrowsingTopicsApiUsage(topics_site_data_manager()).size(),
+      0u);
+}
+
+TEST_F(BrowsingTopicsServiceImplTest,
+       OnURLsDeleted_TimeRangeOverlapWithOneEpoch) {
+  base::Time start_time = base::Time::Now();
+
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(CreateTestEpochTopics({{Topic(1), {}},
+                                                      {Topic(2), {}},
+                                                      {Topic(3), {}},
+                                                      {Topic(4), {}},
+                                                      {Topic(5), {}}},
+                                                     start_time));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(6), {}},
+                             {Topic(7), {}},
+                             {Topic(8), {}},
+                             {Topic(9), {}},
+                             {Topic(10), {}}},
+                            start_time + kCalculatorDelay + base::Days(7)));
+
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  // Finish file loading and two calculations.
+  task_environment()->FastForwardBy(2 * kCalculatorDelay + base::Days(7));
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 2u);
+  EXPECT_FALSE(browsing_topics_state().epochs()[0].empty());
+  EXPECT_FALSE(browsing_topics_state().epochs()[1].empty());
+
+  history::DeletionInfo deletion_info(
+      history::DeletionTimeRange(start_time + base::Days(5),
+                                 start_time + base::Days(6)),
+      /*is_from_expiration=*/false, /*deleted_rows=*/{}, /*favicon_urls=*/{},
+      /*restrict_urls=*/absl::nullopt);
+
+  browsing_topics_service_->OnURLsDeleted(history_service_.get(),
+                                          deletion_info);
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 2u);
+  EXPECT_FALSE(browsing_topics_state().epochs()[0].empty());
+  EXPECT_TRUE(browsing_topics_state().epochs()[1].empty());
+}
+
+TEST_F(BrowsingTopicsServiceImplTest,
+       OnURLsDeleted_TimeRangeOverlapWithAllEpochs) {
+  base::Time start_time = base::Time::Now();
+
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(CreateTestEpochTopics({{Topic(1), {}},
+                                                      {Topic(2), {}},
+                                                      {Topic(3), {}},
+                                                      {Topic(4), {}},
+                                                      {Topic(5), {}}},
+                                                     start_time));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(6), {}},
+                             {Topic(7), {}},
+                             {Topic(8), {}},
+                             {Topic(9), {}},
+                             {Topic(10), {}}},
+                            start_time + kCalculatorDelay + base::Days(7)));
+
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  // Finish file loading and two calculations.
+  task_environment()->FastForwardBy(2 * kCalculatorDelay + base::Days(7));
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 2u);
+  EXPECT_FALSE(browsing_topics_state().epochs()[0].empty());
+  EXPECT_FALSE(browsing_topics_state().epochs()[1].empty());
+
+  history::DeletionInfo deletion_info(
+      history::DeletionTimeRange(start_time, start_time + base::Days(2)),
+      /*is_from_expiration=*/false, /*deleted_rows=*/{}, /*favicon_urls=*/{},
+      /*restrict_urls=*/absl::nullopt);
+
+  browsing_topics_service_->OnURLsDeleted(history_service_.get(),
+                                          deletion_info);
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 2u);
+  EXPECT_TRUE(browsing_topics_state().epochs()[0].empty());
+  EXPECT_TRUE(browsing_topics_state().epochs()[1].empty());
+}
+
+TEST_F(BrowsingTopicsServiceImplTest, Recalculate) {
+  base::Time start_time = base::Time::Now();
+
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(CreateTestEpochTopics({{Topic(1), {}},
+                                                      {Topic(2), {}},
+                                                      {Topic(3), {}},
+                                                      {Topic(4), {}},
+                                                      {Topic(5), {}}},
+                                                     kTime1));
+  mock_calculator_results.push(CreateTestEpochTopics({{Topic(6), {}},
+                                                      {Topic(7), {}},
+                                                      {Topic(8), {}},
+                                                      {Topic(9), {}},
+                                                      {Topic(10), {}}},
+                                                     kTime2));
+
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  task_environment()->FastForwardBy(kCalculatorDelay - base::Seconds(1));
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 0u);
+  EXPECT_EQ(browsing_topics_service_->started_calculations_count(), 1u);
+
+  // History deletion during a calculation should trigger the re-calculation.
+  history::DeletionInfo deletion_info(
+      history::DeletionTimeRange(start_time, start_time + base::Days(2)),
+      /*is_from_expiration=*/false, /*deleted_rows=*/{}, /*favicon_urls=*/{},
+      /*restrict_urls=*/absl::nullopt);
+  browsing_topics_service_->OnURLsDeleted(history_service_.get(),
+                                          deletion_info);
+
+  // The calculation shouldn't finish at the originally expected time, as it was
+  // dropped and a new calculation has started.
+  task_environment()->FastForwardBy(base::Seconds(1));
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 0u);
+  EXPECT_EQ(browsing_topics_service_->started_calculations_count(), 2u);
+
+  // Finish the re-started calculation.
+  task_environment()->FastForwardBy(kCalculatorDelay - base::Seconds(1));
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 1u);
+
+  // Expect that the result comes from the re-started calculator.
+  EXPECT_EQ(browsing_topics_state().epochs()[0].calculation_time(), kTime2);
+  EXPECT_EQ(browsing_topics_state().next_scheduled_calculation_time(),
+            base::Time::Now() + base::Days(7));
+}
+
+TEST_F(BrowsingTopicsServiceImplTest,
+       GetBrowsingTopicsForJsApi_PrivacySandboxSettingsDisabled) {
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(1), {GetHashedDomain("bar.com")}},
+                             {Topic(2), {GetHashedDomain("bar.com")}},
+                             {Topic(3), {GetHashedDomain("bar.com")}},
+                             {Topic(4), {GetHashedDomain("bar.com")}},
+                             {Topic(5), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  task_environment()->RunUntilIdle();
+
+  privacy_sandbox_settings_->SetPrivacySandboxEnabled(false);
+
+  NavigateToPage(GURL("https://www.foo.com"));
+
+  EXPECT_TRUE(browsing_topics_service_
+                  ->GetBrowsingTopicsForJsApi(
+                      /*context_origin=*/url::Origin::Create(
+                          GURL("https://www.bar.com")),
+                      web_contents()->GetMainFrame())
+                  .empty());
+}
+
+TEST_F(BrowsingTopicsServiceImplTest, GetBrowsingTopicsForJsApi_OneEpoch) {
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(1), {GetHashedDomain("bar.com")}},
+                             {Topic(2), {GetHashedDomain("bar.com")}},
+                             {Topic(3), {GetHashedDomain("bar.com")}},
+                             {Topic(4), {GetHashedDomain("bar.com")}},
+                             {Topic(5), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  task_environment()->FastForwardBy(kCalculatorDelay);
+
+  NavigateToPage(GURL("https://www.foo.com"));
+
+  // Current time is before the epoch switch time.
+  std::vector<blink::mojom::EpochTopicPtr> result =
+      browsing_topics_service_->GetBrowsingTopicsForJsApi(
+          /*context_origin=*/url::Origin::Create(GURL("https://www.bar.com")),
+          web_contents()->GetMainFrame());
+
+  EXPECT_TRUE(result.empty());
+
+  // Advance to the time after the epoch switch time.
+  task_environment()->AdvanceClock(base::Days(7) - base::Seconds(1));
+
+  result = browsing_topics_service_->GetBrowsingTopicsForJsApi(
+      /*context_origin=*/url::Origin::Create(GURL("https://www.bar.com")),
+      web_contents()->GetMainFrame());
+
+  EXPECT_EQ(result.size(), 1u);
+  EXPECT_EQ(result[0]->topic, 2);
+  EXPECT_EQ(result[0]->config_version, "chrome.1");
+  EXPECT_EQ(result[0]->taxonomy_version, "1");
+  EXPECT_EQ(result[0]->model_version, "5000000000");
+  EXPECT_EQ(result[0]->version, "chrome.1:1:5000000000");
+}
+
+TEST_F(BrowsingTopicsServiceImplTest,
+       GetBrowsingTopicsForJsApi_TopicNotAllowedByPrivacySandboxSettings) {
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(1), {GetHashedDomain("bar.com")}},
+                             {Topic(2), {GetHashedDomain("bar.com")}},
+                             {Topic(3), {GetHashedDomain("bar.com")}},
+                             {Topic(4), {GetHashedDomain("bar.com")}},
+                             {Topic(5), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  task_environment()->FastForwardBy(kCalculatorDelay);
+
+  NavigateToPage(GURL("https://www.foo.com"));
+
+  // Current time is before the epoch switch time.
+  std::vector<blink::mojom::EpochTopicPtr> result =
+      browsing_topics_service_->GetBrowsingTopicsForJsApi(
+          /*context_origin=*/url::Origin::Create(GURL("https://www.bar.com")),
+          web_contents()->GetMainFrame());
+
+  EXPECT_TRUE(result.empty());
+
+  // Advance to the time after the epoch switch time.
+  task_environment()->AdvanceClock(base::Days(7) - base::Seconds(1));
+
+  privacy_sandbox_settings_->SetTopicAllowed(
+      privacy_sandbox::CanonicalTopic(Topic(2), /*taxonomy_version=*/1), false);
+
+  result = browsing_topics_service_->GetBrowsingTopicsForJsApi(
+      /*context_origin=*/url::Origin::Create(GURL("https://www.bar.com")),
+      web_contents()->GetMainFrame());
+
+  EXPECT_TRUE(result.empty());
+}
+
+TEST_F(BrowsingTopicsServiceImplTest, GetBrowsingTopicsForJsApi_FourEpochs) {
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(1), {GetHashedDomain("bar.com")}},
+                             {Topic(2), {GetHashedDomain("bar.com")}},
+                             {Topic(3), {GetHashedDomain("bar.com")}},
+                             {Topic(4), {GetHashedDomain("bar.com")}},
+                             {Topic(5), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(6), {GetHashedDomain("bar.com")}},
+                             {Topic(7), {GetHashedDomain("bar.com")}},
+                             {Topic(8), {GetHashedDomain("bar.com")}},
+                             {Topic(9), {GetHashedDomain("bar.com")}},
+                             {Topic(10), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(11), {GetHashedDomain("bar.com")}},
+                             {Topic(12), {GetHashedDomain("bar.com")}},
+                             {Topic(13), {GetHashedDomain("bar.com")}},
+                             {Topic(14), {GetHashedDomain("bar.com")}},
+                             {Topic(15), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(16), {GetHashedDomain("bar.com")}},
+                             {Topic(17), {GetHashedDomain("bar.com")}},
+                             {Topic(18), {GetHashedDomain("bar.com")}},
+                             {Topic(19), {GetHashedDomain("bar.com")}},
+                             {Topic(20), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  // Finish all calculations.
+  task_environment()->FastForwardBy(4 * kCalculatorDelay + 3 * base::Days(7));
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 4u);
+
+  NavigateToPage(GURL("https://www.foo.com"));
+
+  // Current time is before the epoch switch time.
+  std::vector<blink::mojom::EpochTopicPtr> result =
+      browsing_topics_service_->GetBrowsingTopicsForJsApi(
+          /*context_origin=*/url::Origin::Create(GURL("https://www.bar.com")),
+          web_contents()->GetMainFrame());
+
+  EXPECT_EQ(result.size(), 3u);
+  std::set<int> result_set;
+  result_set.insert(result[0]->topic);
+  result_set.insert(result[1]->topic);
+  result_set.insert(result[2]->topic);
+  EXPECT_EQ(result_set, std::set<int>({2, 7, 12}));
+
+  // Advance to the time after the epoch switch time.
+  task_environment()->AdvanceClock(base::Days(7) - base::Seconds(1));
+
+  result = browsing_topics_service_->GetBrowsingTopicsForJsApi(
+      /*context_origin=*/url::Origin::Create(GURL("https://www.bar.com")),
+      web_contents()->GetMainFrame());
+
+  EXPECT_EQ(result.size(), 3u);
+  result_set.clear();
+  result_set.insert(result[0]->topic);
+  result_set.insert(result[1]->topic);
+  result_set.insert(result[2]->topic);
+  EXPECT_EQ(result_set, std::set<int>({7, 12, 17}));
+}
+
+TEST_F(BrowsingTopicsServiceImplTest,
+       GetBrowsingTopicsForJsApi_DuplicateTopicsRemoved) {
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(1), {GetHashedDomain("bar.com")}},
+                             {Topic(2), {GetHashedDomain("bar.com")}},
+                             {Topic(3), {GetHashedDomain("bar.com")}},
+                             {Topic(4), {GetHashedDomain("bar.com")}},
+                             {Topic(5), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(6), {GetHashedDomain("bar.com")}},
+                             {Topic(7), {GetHashedDomain("bar.com")}},
+                             {Topic(8), {GetHashedDomain("bar.com")}},
+                             {Topic(9), {GetHashedDomain("bar.com")}},
+                             {Topic(10), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(1), {GetHashedDomain("bar.com")}},
+                             {Topic(2), {GetHashedDomain("bar.com")}},
+                             {Topic(3), {GetHashedDomain("bar.com")}},
+                             {Topic(4), {GetHashedDomain("bar.com")}},
+                             {Topic(5), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(6), {GetHashedDomain("bar.com")}},
+                             {Topic(7), {GetHashedDomain("bar.com")}},
+                             {Topic(8), {GetHashedDomain("bar.com")}},
+                             {Topic(9), {GetHashedDomain("bar.com")}},
+                             {Topic(10), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  // Finish all calculations.
+  task_environment()->FastForwardBy(4 * kCalculatorDelay + 3 * base::Days(7));
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 4u);
+
+  NavigateToPage(GURL("https://www.foo.com"));
+
+  // Current time is before the epoch switch time.
+  std::vector<blink::mojom::EpochTopicPtr> result =
+      browsing_topics_service_->GetBrowsingTopicsForJsApi(
+          /*context_origin=*/url::Origin::Create(GURL("https://www.bar.com")),
+          web_contents()->GetMainFrame());
+
+  EXPECT_EQ(result.size(), 2u);
+  std::set<int> result_set;
+  result_set.insert(result[0]->topic);
+  result_set.insert(result[1]->topic);
+  EXPECT_EQ(result_set, std::set<int>({2, 7}));
+
+  // Advance to the time after the epoch switch time.
+  task_environment()->AdvanceClock(base::Days(7) - base::Seconds(1));
+
+  result = browsing_topics_service_->GetBrowsingTopicsForJsApi(
+      /*context_origin=*/url::Origin::Create(GURL("https://www.bar.com")),
+      web_contents()->GetMainFrame());
+
+  EXPECT_EQ(result.size(), 2u);
+  result_set.clear();
+  result_set.insert(result[0]->topic);
+  result_set.insert(result[1]->topic);
+  EXPECT_EQ(result_set, std::set<int>({2, 7}));
+}
+
+// TODO(yaoxia): Re-enable. This test currently fails solely due to it's
+// generating a lot of GMOCK WARNING output.
+TEST_F(BrowsingTopicsServiceImplTest,
+       DISABLED_GetBrowsingTopicsForJsApi_TopicsReturnedInRandomOrder) {
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(1), {GetHashedDomain("bar.com")}},
+                             {Topic(2), {GetHashedDomain("bar.com")}},
+                             {Topic(3), {GetHashedDomain("bar.com")}},
+                             {Topic(4), {GetHashedDomain("bar.com")}},
+                             {Topic(5), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(6), {GetHashedDomain("bar.com")}},
+                             {Topic(7), {GetHashedDomain("bar.com")}},
+                             {Topic(8), {GetHashedDomain("bar.com")}},
+                             {Topic(9), {GetHashedDomain("bar.com")}},
+                             {Topic(10), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(1), {GetHashedDomain("bar.com")}},
+                             {Topic(2), {GetHashedDomain("bar.com")}},
+                             {Topic(3), {GetHashedDomain("bar.com")}},
+                             {Topic(4), {GetHashedDomain("bar.com")}},
+                             {Topic(5), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(6), {GetHashedDomain("bar.com")}},
+                             {Topic(7), {GetHashedDomain("bar.com")}},
+                             {Topic(8), {GetHashedDomain("bar.com")}},
+                             {Topic(9), {GetHashedDomain("bar.com")}},
+                             {Topic(10), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  // Finish all calculations.
+  task_environment()->FastForwardBy(4 * kCalculatorDelay + 3 * base::Days(7));
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 4u);
+
+  NavigateToPage(GURL("https://www.foo.com"));
+
+  // Current time is before the epoch switch time.
+
+  // Expect that in 100 rounds, both Topic(2) and Topic(7) should be seen being
+  // at the front.
+  bool seen_topic_2_at_front = false;
+  bool seen_topic_7_at_front = false;
+
+  for (int i = 0; i < 100; ++i) {
+    std::vector<blink::mojom::EpochTopicPtr> result =
+        browsing_topics_service_->GetBrowsingTopicsForJsApi(
+            /*context_origin=*/url::Origin::Create(GURL("https://www.bar.com")),
+            web_contents()->GetMainFrame());
+
+    EXPECT_EQ(result.size(), 2u);
+    std::set<int> result_set;
+    result_set.insert(result[0]->topic);
+    result_set.insert(result[1]->topic);
+    EXPECT_EQ(result_set, std::set<int>({2, 7}));
+
+    seen_topic_2_at_front = seen_topic_2_at_front || (result[0]->topic == 2);
+    seen_topic_7_at_front = seen_topic_2_at_front || (result[0]->topic == 7);
+  }
+
+  EXPECT_TRUE(seen_topic_2_at_front);
+  EXPECT_TRUE(seen_topic_7_at_front);
+}
+
+TEST_F(BrowsingTopicsServiceImplTest,
+       GetBrowsingTopicsForJsApi_TrackedUsageContext) {
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(1), {GetHashedDomain("bar.com")}},
+                             {Topic(2), {GetHashedDomain("bar.com")}},
+                             {Topic(3), {GetHashedDomain("bar.com")}},
+                             {Topic(4), {GetHashedDomain("bar.com")}},
+                             {Topic(5), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  task_environment()->RunUntilIdle();
+
+  EXPECT_EQ(
+      content::GetBrowsingTopicsApiUsage(topics_site_data_manager()).size(),
+      0u);
+
+  NavigateToPage(GURL("https://www.foo.com"));
+  browsing_topics_service_->GetBrowsingTopicsForJsApi(
+      /*context_origin=*/url::Origin::Create(GURL("https://www.bar.com")),
+      web_contents()->GetMainFrame());
+
+  std::vector<ApiUsageContext> api_usage_contexts =
+      content::GetBrowsingTopicsApiUsage(topics_site_data_manager());
+  EXPECT_EQ(api_usage_contexts.size(), 1u);
+  EXPECT_EQ(api_usage_contexts[0].hashed_main_frame_host,
+            HashMainFrameHostForStorage("www.foo.com"));
+  EXPECT_EQ(api_usage_contexts[0].hashed_context_domain,
+            GetHashedDomain("bar.com"));
+}
+
+TEST_F(BrowsingTopicsServiceImplTest, GetTopicsForSiteForDisplay) {
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(1), {GetHashedDomain("bar.com")}},
+                             {Topic(2), {GetHashedDomain("bar.com")}},
+                             {Topic(3), {GetHashedDomain("bar.com")}},
+                             {Topic(4), {GetHashedDomain("bar.com")}},
+                             {Topic(5), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(6), {GetHashedDomain("bar.com")}},
+                             {Topic(7), {GetHashedDomain("bar.com")}},
+                             {Topic(8), {GetHashedDomain("bar.com")}},
+                             {Topic(9), {GetHashedDomain("bar.com")}},
+                             {Topic(10), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(1), {GetHashedDomain("bar.com")}},
+                             {Topic(2), {GetHashedDomain("bar.com")}},
+                             {Topic(3), {GetHashedDomain("bar.com")}},
+                             {Topic(4), {GetHashedDomain("bar.com")}},
+                             {Topic(5), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(6), {GetHashedDomain("bar.com")}},
+                             {Topic(7), {GetHashedDomain("bar.com")}},
+                             {Topic(8), {GetHashedDomain("bar.com")}},
+                             {Topic(9), {GetHashedDomain("bar.com")}},
+                             {Topic(10), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  // Finish all calculations.
+  task_environment()->FastForwardBy(4 * kCalculatorDelay + 3 * base::Days(7));
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 4u);
+
+  NavigateToPage(GURL("https://www.foo.com"));
+
+  // Current time is before the epoch switch time.
+  std::vector<privacy_sandbox::CanonicalTopic> result =
+      browsing_topics_service_->GetTopicsForSiteForDisplay(
+          web_contents()->GetMainFrame()->GetLastCommittedOrigin());
+
+  EXPECT_EQ(result.size(), 3u);
+  EXPECT_EQ(result[0].topic_id(), Topic(2));
+  EXPECT_EQ(result[1].topic_id(), Topic(7));
+  EXPECT_EQ(result[2].topic_id(), Topic(2));
+  EXPECT_EQ(result[0].taxonomy_version(), 1);
+  EXPECT_EQ(result[1].taxonomy_version(), 1);
+  EXPECT_EQ(result[2].taxonomy_version(), 1);
+}
+
+TEST_F(BrowsingTopicsServiceImplTest, GetTopTopicsForDisplay) {
+  base::queue<EpochTopics> mock_calculator_results;
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(1), {GetHashedDomain("bar.com")}},
+                             {Topic(2), {GetHashedDomain("bar.com")}},
+                             {Topic(3), {GetHashedDomain("bar.com")}},
+                             {Topic(4), {GetHashedDomain("bar.com")}},
+                             {Topic(5), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(6), {GetHashedDomain("bar.com")}},
+                             {Topic(7), {GetHashedDomain("bar.com")}},
+                             {Topic(8), {GetHashedDomain("bar.com")}},
+                             {Topic(9), {GetHashedDomain("bar.com")}},
+                             {Topic(10), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(1), {GetHashedDomain("bar.com")}},
+                             {Topic(2), {GetHashedDomain("bar.com")}},
+                             {Topic(3), {GetHashedDomain("bar.com")}},
+                             {Topic(4), {GetHashedDomain("bar.com")}},
+                             {Topic(5), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+  mock_calculator_results.push(
+      CreateTestEpochTopics({{Topic(6), {GetHashedDomain("bar.com")}},
+                             {Topic(7), {GetHashedDomain("bar.com")}},
+                             {Topic(8), {GetHashedDomain("bar.com")}},
+                             {Topic(9), {GetHashedDomain("bar.com")}},
+                             {Topic(10), {GetHashedDomain("bar.com")}}},
+                            kTime1));
+
+  InitializeBrowsingTopicsService(std::move(mock_calculator_results));
+
+  // Finish all calculations.
+  task_environment()->FastForwardBy(4 * kCalculatorDelay + 3 * base::Days(7));
+
+  EXPECT_EQ(browsing_topics_state().epochs().size(), 4u);
+
+  NavigateToPage(GURL("https://www.foo.com"));
+
+  // Current time is before the epoch switch time.
+  std::vector<privacy_sandbox::CanonicalTopic> result =
+      browsing_topics_service_->GetTopTopicsForDisplay();
+
+  EXPECT_EQ(result.size(), 20u);
+  EXPECT_EQ(result[0].topic_id(), Topic(1));
+  EXPECT_EQ(result[1].topic_id(), Topic(2));
+  EXPECT_EQ(result[2].topic_id(), Topic(3));
+  EXPECT_EQ(result[3].topic_id(), Topic(4));
+  EXPECT_EQ(result[4].topic_id(), Topic(5));
+  EXPECT_EQ(result[5].topic_id(), Topic(6));
+  EXPECT_EQ(result[6].topic_id(), Topic(7));
+  EXPECT_EQ(result[7].topic_id(), Topic(8));
+  EXPECT_EQ(result[8].topic_id(), Topic(9));
+  EXPECT_EQ(result[9].topic_id(), Topic(10));
+  EXPECT_EQ(result[10].topic_id(), Topic(1));
+  EXPECT_EQ(result[11].topic_id(), Topic(2));
+  EXPECT_EQ(result[12].topic_id(), Topic(3));
+  EXPECT_EQ(result[13].topic_id(), Topic(4));
+  EXPECT_EQ(result[14].topic_id(), Topic(5));
+  EXPECT_EQ(result[15].topic_id(), Topic(6));
+  EXPECT_EQ(result[16].topic_id(), Topic(7));
+  EXPECT_EQ(result[17].topic_id(), Topic(8));
+  EXPECT_EQ(result[18].topic_id(), Topic(9));
+  EXPECT_EQ(result[19].topic_id(), Topic(10));
+}
+
+}  // namespace browsing_topics
diff --git a/components/browsing_topics/browsing_topics_state.cc b/components/browsing_topics/browsing_topics_state.cc
index f0238f2..a8309414 100644
--- a/components/browsing_topics/browsing_topics_state.cc
+++ b/components/browsing_topics/browsing_topics_state.cc
@@ -109,18 +109,75 @@
   ScheduleSave();
 }
 
-void BrowsingTopicsState::UpdateNextScheduledCalculationTime(
-    base::Time next_scheduled_calculation_time) {
+void BrowsingTopicsState::UpdateNextScheduledCalculationTime() {
   DCHECK(loaded_);
 
-  next_scheduled_calculation_time_ = next_scheduled_calculation_time;
+  next_scheduled_calculation_time_ =
+      base::Time::Now() +
+      blink::features::kBrowsingTopicsTimePeriodPerEpoch.Get();
+
   ScheduleSave();
 }
 
+std::vector<const EpochTopics*> BrowsingTopicsState::EpochsForSite(
+    const std::string& top_domain) const {
+  DCHECK(loaded_);
+
+  const size_t kNumberOfEpochsToExpose = static_cast<size_t>(
+      blink::features::kBrowsingTopicsNumberOfEpochsToExpose.Get());
+
+  DCHECK_GT(kNumberOfEpochsToExpose, 0u);
+
+  // Derive a per-user per-site time delta in the range of
+  // [0, kBrowsingTopicsTimePeriodPerEpoch). The latest epoch will be switched
+  // to use when the current time is within `site_sticky_time_delta` apart from
+  // the `next_scheduled_calculation_time_`. This way, each site will see a
+  // different epoch switch time.
+  base::TimeDelta site_sticky_time_delta =
+      CalculateSiteStickyTimeDelta(top_domain);
+
+  size_t end_epoch_index = 0;
+
+  if (base::Time::Now() + site_sticky_time_delta <
+      next_scheduled_calculation_time_) {
+    if (epochs_.size() < 2)
+      return {};
+
+    end_epoch_index = epochs_.size() - 2;
+  } else {
+    if (epochs_.empty())
+      return {};
+
+    end_epoch_index = epochs_.size() - 1;
+  }
+
+  size_t start_epoch_index = (end_epoch_index + 1 >= kNumberOfEpochsToExpose)
+                                 ? end_epoch_index + 1 - kNumberOfEpochsToExpose
+                                 : 0;
+
+  std::vector<const EpochTopics*> result;
+
+  for (size_t i = start_epoch_index; i <= end_epoch_index; ++i) {
+    result.emplace_back(&epochs_[i]);
+  }
+
+  return result;
+}
+
 bool BrowsingTopicsState::HasScheduledSaveForTesting() const {
   return writer_.HasPendingWrite();
 }
 
+base::TimeDelta BrowsingTopicsState::CalculateSiteStickyTimeDelta(
+    const std::string& top_domain) const {
+  uint64_t epoch_switch_time_decision_hash =
+      HashTopDomainForEpochSwitchTimeDecision(hmac_key_, top_domain);
+
+  return base::Seconds(
+      epoch_switch_time_decision_hash %
+      blink::features::kBrowsingTopicsTimePeriodPerEpoch.Get().InSeconds());
+}
+
 base::ImportantFileWriter::BackgroundDataProducerCallback
 BrowsingTopicsState::GetSerializedDataProducerForBackgroundSequence() {
   DCHECK(loaded_);
diff --git a/components/browsing_topics/browsing_topics_state.h b/components/browsing_topics/browsing_topics_state.h
index 0e2ec56..38ff641 100644
--- a/components/browsing_topics/browsing_topics_state.h
+++ b/components/browsing_topics/browsing_topics_state.h
@@ -69,13 +69,20 @@
   // remove the entry from `epochs_`.
   void ClearOneEpoch(size_t epoch_index);
 
-  // Append `epoch_topics` to `epochs_`.
+  // Append `epoch_topics` to `epochs_`. This is invoked at the end of each
+  // epoch calculation.
   void AddEpoch(EpochTopics epoch_topics);
 
-  // Set `next_scheduled_calculation_time_` to
-  // `next_scheduled_calculation_time`.
-  void UpdateNextScheduledCalculationTime(
-      base::Time next_scheduled_calculation_time);
+  // Set `next_scheduled_calculation_time_` to one epoch later from
+  // base::Time::Now(). This is invoked at the end of each epoch calculation.
+  void UpdateNextScheduledCalculationTime();
+
+  // Calculate the candidate epochs to derive the topics from on `top_domain`.
+  // The caller (i.e. BrowsingTopicsServiceImpl, which also holds `this`) is
+  // responsible for ensuring that the `EpochTopic` objects that the pointers
+  // refer to remain alive when the caller is accessing them.
+  std::vector<const EpochTopics*> EpochsForSite(
+      const std::string& top_domain) const;
 
   const base::circular_deque<EpochTopics>& epochs() const {
     DCHECK(loaded_);
@@ -95,6 +102,14 @@
   bool HasScheduledSaveForTesting() const;
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(BrowsingTopicsStateTest,
+                           EpochsForSite_OneEpoch_SwitchTimeNotArrived);
+  FRIEND_TEST_ALL_PREFIXES(BrowsingTopicsStateTest,
+                           EpochsForSite_OneEpoch_SwitchTimeArrived);
+
+  base::TimeDelta CalculateSiteStickyTimeDelta(
+      const std::string& top_domain) const;
+
   // ImportantFileWriter::BackgroundDataSerializer implementation.
   base::ImportantFileWriter::BackgroundDataProducerCallback
   GetSerializedDataProducerForBackgroundSequence() override;
@@ -127,10 +142,8 @@
   base::circular_deque<EpochTopics> epochs_;
 
   // The next time a calculation should occur. This will be updated when a
-  // calculation is scheduled:
-  // - at the start of a browser session.
-  // - or, after a topics calculation.
-  // - or, when the user explicitly resets the timer from the UX.
+  // calculation is scheduled at the end of a topics calculation and is always
+  // synchronously updated with `epochs_`.
   //
   // next_scheduled_calculation_time_.is_null() indicates this is a new profile
   // or there was an update to the configuration version when this
diff --git a/components/browsing_topics/browsing_topics_state_unittest.cc b/components/browsing_topics/browsing_topics_state_unittest.cc
index 7cd1073..bd91b33 100644
--- a/components/browsing_topics/browsing_topics_state_unittest.cc
+++ b/components/browsing_topics/browsing_topics_state_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/json/values_util.h"
+#include "base/strings/strcat.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
@@ -21,20 +22,25 @@
 
 namespace {
 
-const base::Time kTime1 = base::Time::FromDeltaSinceWindowsEpoch(base::Days(1));
-const base::Time kTime2 = base::Time::FromDeltaSinceWindowsEpoch(base::Days(2));
-const base::Time kTime3 = base::Time::FromDeltaSinceWindowsEpoch(base::Days(3));
-const base::Time kTime4 = base::Time::FromDeltaSinceWindowsEpoch(base::Days(4));
-const base::Time kTime5 = base::Time::FromDeltaSinceWindowsEpoch(base::Days(5));
+constexpr base::Time kTime1 =
+    base::Time::FromDeltaSinceWindowsEpoch(base::Days(1));
+constexpr base::Time kTime2 =
+    base::Time::FromDeltaSinceWindowsEpoch(base::Days(2));
+constexpr base::Time kTime3 =
+    base::Time::FromDeltaSinceWindowsEpoch(base::Days(3));
+constexpr base::Time kTime4 =
+    base::Time::FromDeltaSinceWindowsEpoch(base::Days(4));
+constexpr base::Time kTime5 =
+    base::Time::FromDeltaSinceWindowsEpoch(base::Days(5));
 
-const browsing_topics::HmacKey kZeroKey = {};
-const browsing_topics::HmacKey kTestKey = {1};
-const browsing_topics::HmacKey kTestKey2 = {2};
+constexpr browsing_topics::HmacKey kZeroKey = {};
+constexpr browsing_topics::HmacKey kTestKey = {1};
+constexpr browsing_topics::HmacKey kTestKey2 = {2};
 
-const size_t kTaxonomySize = 349;
-const int kTaxonomyVersion = 1;
-const int kModelVersion = 2;
-const size_t kPaddedTopTopicsStartIndex = 3;
+constexpr size_t kTaxonomySize = 349;
+constexpr int kTaxonomyVersion = 1;
+constexpr int64_t kModelVersion = 2;
+constexpr size_t kPaddedTopTopicsStartIndex = 3;
 
 EpochTopics CreateTestEpochTopics(base::Time calculation_time) {
   std::vector<TopicAndDomains> top_topics_and_observing_domains;
@@ -101,8 +107,7 @@
     dict.Set("hex_encoded_hmac_key", std::move(hex_encoded_hmac_key));
     dict.Set("config_version", config_version);
 
-    JSONFileValueSerializer(TestFilePath())
-        .Serialize(base::Value(std::move(dict)));
+    JSONFileValueSerializer(TestFilePath()).Serialize(dict);
   }
 
   void OnBrowsingTopicsStateLoaded() { observed_state_loaded_ = true; }
@@ -172,10 +177,11 @@
   task_environment_->FastForwardBy(base::Milliseconds(3000));
   EXPECT_FALSE(state.HasScheduledSaveForTesting());
 
-  state.UpdateNextScheduledCalculationTime(kTime1);
+  state.UpdateNextScheduledCalculationTime();
 
   EXPECT_TRUE(state.epochs().empty());
-  EXPECT_EQ(state.next_scheduled_calculation_time(), kTime1);
+  EXPECT_EQ(state.next_scheduled_calculation_time(),
+            base::Time::Now() + base::Days(7));
   EXPECT_TRUE(std::equal(state.hmac_key().begin(), state.hmac_key().end(),
                          kTestKey.begin()));
 
@@ -187,11 +193,16 @@
   task_environment_->FastForwardBy(base::Milliseconds(1));
   EXPECT_FALSE(state.HasScheduledSaveForTesting());
 
-  EXPECT_EQ(
-      GetTestFileContent(),
-      "{\"config_version\": 123,\"epochs\": [ ],\"hex_encoded_hmac_key\": "
-      "\"0100000000000000000000000000000000000000000000000000000000000000\","
-      "\"next_scheduled_calculation_time\": \"86400000000\"}");
+  std::string expected_content = base::StrCat(
+      {"{\"config_version\": 123,\"epochs\": [ ],\"hex_encoded_hmac_key\": "
+       "\"0100000000000000000000000000000000000000000000000000000000000000"
+       "\",\"next_scheduled_calculation_time\": \"",
+       base::NumberToString(state.next_scheduled_calculation_time()
+                                .ToDeltaSinceWindowsEpoch()
+                                .InMicroseconds()),
+       "\"}"});
+
+  EXPECT_EQ(GetTestFileContent(), expected_content);
 }
 
 TEST_F(BrowsingTopicsStateTest, AddEpoch) {
@@ -202,47 +213,47 @@
   state.AddEpoch(CreateTestEpochTopics(kTime1));
 
   EXPECT_EQ(state.epochs().size(), 1u);
-  EXPECT_TRUE(state.epochs()[0].HasValidTopics());
+  EXPECT_FALSE(state.epochs()[0].empty());
   EXPECT_EQ(state.epochs()[0].calculation_time(), kTime1);
 
   // Successful topics calculation at `kTime2`.
   state.AddEpoch(CreateTestEpochTopics(kTime2));
   EXPECT_EQ(state.epochs().size(), 2u);
-  EXPECT_TRUE(state.epochs()[0].HasValidTopics());
+  EXPECT_FALSE(state.epochs()[0].empty());
   EXPECT_EQ(state.epochs()[0].calculation_time(), kTime1);
-  EXPECT_TRUE(state.epochs()[1].HasValidTopics());
+  EXPECT_FALSE(state.epochs()[1].empty());
   EXPECT_EQ(state.epochs()[1].calculation_time(), kTime2);
 
   // Failed topics calculation.
   state.AddEpoch(EpochTopics());
   EXPECT_EQ(state.epochs().size(), 3u);
-  EXPECT_TRUE(state.epochs()[0].HasValidTopics());
+  EXPECT_FALSE(state.epochs()[0].empty());
   EXPECT_EQ(state.epochs()[0].calculation_time(), kTime1);
-  EXPECT_TRUE(state.epochs()[1].HasValidTopics());
+  EXPECT_FALSE(state.epochs()[1].empty());
   EXPECT_EQ(state.epochs()[1].calculation_time(), kTime2);
-  EXPECT_FALSE(state.epochs()[2].HasValidTopics());
+  EXPECT_TRUE(state.epochs()[2].empty());
 
   // Successful topics calculation at `kTime4`.
   state.AddEpoch(CreateTestEpochTopics(kTime4));
   EXPECT_EQ(state.epochs().size(), 4u);
-  EXPECT_TRUE(state.epochs()[0].HasValidTopics());
+  EXPECT_FALSE(state.epochs()[0].empty());
   EXPECT_EQ(state.epochs()[0].calculation_time(), kTime1);
-  EXPECT_TRUE(state.epochs()[1].HasValidTopics());
+  EXPECT_FALSE(state.epochs()[1].empty());
   EXPECT_EQ(state.epochs()[1].calculation_time(), kTime2);
-  EXPECT_FALSE(state.epochs()[2].HasValidTopics());
-  EXPECT_TRUE(state.epochs()[3].HasValidTopics());
+  EXPECT_TRUE(state.epochs()[2].empty());
+  EXPECT_FALSE(state.epochs()[3].empty());
   EXPECT_EQ(state.epochs()[3].calculation_time(), kTime4);
 
   // Successful topics calculation at `kTime5`. When this epoch is added, the
   // first one should be evicted.
   state.AddEpoch(CreateTestEpochTopics(kTime5));
   EXPECT_EQ(state.epochs().size(), 4u);
-  EXPECT_TRUE(state.epochs()[0].HasValidTopics());
+  EXPECT_FALSE(state.epochs()[0].empty());
   EXPECT_EQ(state.epochs()[0].calculation_time(), kTime2);
-  EXPECT_FALSE(state.epochs()[1].HasValidTopics());
-  EXPECT_TRUE(state.epochs()[2].HasValidTopics());
+  EXPECT_TRUE(state.epochs()[1].empty());
+  EXPECT_FALSE(state.epochs()[2].empty());
   EXPECT_EQ(state.epochs()[2].calculation_time(), kTime4);
-  EXPECT_TRUE(state.epochs()[3].HasValidTopics());
+  EXPECT_FALSE(state.epochs()[3].empty());
   EXPECT_EQ(state.epochs()[3].calculation_time(), kTime5);
 
   // The `next_scheduled_calculation_time` and `hmac_key` are unaffected.
@@ -251,6 +262,123 @@
                          kTestKey.begin()));
 }
 
+TEST_F(BrowsingTopicsStateTest, EpochsForSite_Empty) {
+  BrowsingTopicsState state(temp_dir_.GetPath(), base::DoNothing());
+  task_environment_->RunUntilIdle();
+
+  EXPECT_TRUE(state.EpochsForSite(/*top_domain=*/"foo.com").empty());
+}
+
+TEST_F(BrowsingTopicsStateTest, EpochsForSite_OneEpoch_SwitchTimeNotArrived) {
+  BrowsingTopicsState state(temp_dir_.GetPath(), base::DoNothing());
+  task_environment_->RunUntilIdle();
+
+  state.AddEpoch(CreateTestEpochTopics(kTime1));
+  state.UpdateNextScheduledCalculationTime();
+
+  ASSERT_LT(state.CalculateSiteStickyTimeDelta("foo.com") + base::Hours(1),
+            base::Days(7));
+
+  task_environment_->FastForwardBy(base::Hours(1));
+  EXPECT_TRUE(state.EpochsForSite(/*top_domain=*/"foo.com").empty());
+}
+
+TEST_F(BrowsingTopicsStateTest, EpochsForSite_OneEpoch_SwitchTimeArrived) {
+  BrowsingTopicsState state(temp_dir_.GetPath(), base::DoNothing());
+  task_environment_->RunUntilIdle();
+
+  state.AddEpoch(CreateTestEpochTopics(kTime1));
+  state.UpdateNextScheduledCalculationTime();
+
+  ASSERT_GT(state.CalculateSiteStickyTimeDelta("foo.com") + base::Days(1),
+            base::Days(7));
+
+  task_environment_->FastForwardBy(base::Days(1));
+
+  std::vector<const EpochTopics*> epochs_for_site =
+      state.EpochsForSite(/*top_domain=*/"foo.com");
+  EXPECT_EQ(epochs_for_site.size(), 1u);
+  EXPECT_EQ(epochs_for_site[0], &state.epochs()[0]);
+}
+
+TEST_F(BrowsingTopicsStateTest,
+       EpochsForSite_ThreeEpochs_SwitchTimeNotArrived) {
+  BrowsingTopicsState state(temp_dir_.GetPath(), base::DoNothing());
+  task_environment_->RunUntilIdle();
+
+  state.AddEpoch(CreateTestEpochTopics(kTime1));
+  state.AddEpoch(CreateTestEpochTopics(kTime2));
+  state.AddEpoch(CreateTestEpochTopics(kTime3));
+  state.UpdateNextScheduledCalculationTime();
+
+  task_environment_->FastForwardBy(base::Hours(1));
+
+  std::vector<const EpochTopics*> epochs_for_site =
+      state.EpochsForSite(/*top_domain=*/"foo.com");
+  EXPECT_EQ(epochs_for_site.size(), 2u);
+  EXPECT_EQ(epochs_for_site[0], &state.epochs()[0]);
+  EXPECT_EQ(epochs_for_site[1], &state.epochs()[1]);
+}
+
+TEST_F(BrowsingTopicsStateTest, EpochsForSite_ThreeEpochs_SwitchTimeArrived) {
+  BrowsingTopicsState state(temp_dir_.GetPath(), base::DoNothing());
+  task_environment_->RunUntilIdle();
+
+  state.AddEpoch(CreateTestEpochTopics(kTime1));
+  state.AddEpoch(CreateTestEpochTopics(kTime2));
+  state.AddEpoch(CreateTestEpochTopics(kTime3));
+  state.UpdateNextScheduledCalculationTime();
+
+  task_environment_->FastForwardBy(base::Days(1));
+
+  std::vector<const EpochTopics*> epochs_for_site =
+      state.EpochsForSite(/*top_domain=*/"foo.com");
+  EXPECT_EQ(epochs_for_site.size(), 3u);
+  EXPECT_EQ(epochs_for_site[0], &state.epochs()[0]);
+  EXPECT_EQ(epochs_for_site[1], &state.epochs()[1]);
+  EXPECT_EQ(epochs_for_site[2], &state.epochs()[2]);
+}
+
+TEST_F(BrowsingTopicsStateTest, EpochsForSite_FourEpochs_SwitchTimeNotArrived) {
+  BrowsingTopicsState state(temp_dir_.GetPath(), base::DoNothing());
+  task_environment_->RunUntilIdle();
+
+  state.AddEpoch(CreateTestEpochTopics(kTime1));
+  state.AddEpoch(CreateTestEpochTopics(kTime2));
+  state.AddEpoch(CreateTestEpochTopics(kTime3));
+  state.AddEpoch(CreateTestEpochTopics(kTime4));
+  state.UpdateNextScheduledCalculationTime();
+
+  task_environment_->FastForwardBy(base::Hours(1));
+
+  std::vector<const EpochTopics*> epochs_for_site =
+      state.EpochsForSite(/*top_domain=*/"foo.com");
+  EXPECT_EQ(epochs_for_site.size(), 3u);
+  EXPECT_EQ(epochs_for_site[0], &state.epochs()[0]);
+  EXPECT_EQ(epochs_for_site[1], &state.epochs()[1]);
+  EXPECT_EQ(epochs_for_site[2], &state.epochs()[2]);
+}
+
+TEST_F(BrowsingTopicsStateTest, EpochsForSite_FourEpochs_SwitchTimeArrived) {
+  BrowsingTopicsState state(temp_dir_.GetPath(), base::DoNothing());
+  task_environment_->RunUntilIdle();
+
+  state.AddEpoch(CreateTestEpochTopics(kTime1));
+  state.AddEpoch(CreateTestEpochTopics(kTime2));
+  state.AddEpoch(CreateTestEpochTopics(kTime3));
+  state.AddEpoch(CreateTestEpochTopics(kTime4));
+  state.UpdateNextScheduledCalculationTime();
+
+  task_environment_->FastForwardBy(base::Days(1));
+
+  std::vector<const EpochTopics*> epochs_for_site =
+      state.EpochsForSite(/*top_domain=*/"foo.com");
+  EXPECT_EQ(epochs_for_site.size(), 3u);
+  EXPECT_EQ(epochs_for_site[0], &state.epochs()[1]);
+  EXPECT_EQ(epochs_for_site[1], &state.epochs()[2]);
+  EXPECT_EQ(epochs_for_site[2], &state.epochs()[3]);
+}
+
 TEST_F(BrowsingTopicsStateTest, InitFromPreexistingFile_CorruptedHmacKey) {
   base::HistogramTester histograms;
 
@@ -290,7 +418,7 @@
   task_environment_->RunUntilIdle();
 
   EXPECT_EQ(state.epochs().size(), 1u);
-  EXPECT_TRUE(state.epochs()[0].HasValidTopics());
+  EXPECT_FALSE(state.epochs()[0].empty());
   EXPECT_EQ(state.epochs()[0].model_version(), kModelVersion);
   EXPECT_EQ(state.next_scheduled_calculation_time(), kTime2);
   EXPECT_TRUE(std::equal(state.hmac_key().begin(), state.hmac_key().end(),
@@ -333,25 +461,26 @@
   state.AddEpoch(CreateTestEpochTopics(kTime1));
 
   EXPECT_EQ(state.epochs().size(), 1u);
-  EXPECT_TRUE(state.epochs()[0].HasValidTopics());
+  EXPECT_FALSE(state.epochs()[0].empty());
   EXPECT_EQ(state.epochs()[0].calculation_time(), kTime1);
 
   state.AddEpoch(CreateTestEpochTopics(kTime2));
   EXPECT_EQ(state.epochs().size(), 2u);
-  EXPECT_TRUE(state.epochs()[0].HasValidTopics());
+  EXPECT_FALSE(state.epochs()[0].empty());
   EXPECT_EQ(state.epochs()[0].calculation_time(), kTime1);
-  EXPECT_TRUE(state.epochs()[1].HasValidTopics());
+  EXPECT_FALSE(state.epochs()[1].empty());
   EXPECT_EQ(state.epochs()[1].calculation_time(), kTime2);
 
-  state.UpdateNextScheduledCalculationTime(kTime3);
-
   state.ClearOneEpoch(/*epoch_index=*/0);
   EXPECT_EQ(state.epochs().size(), 2u);
-  EXPECT_FALSE(state.epochs()[0].HasValidTopics());
-  EXPECT_TRUE(state.epochs()[1].HasValidTopics());
+  EXPECT_TRUE(state.epochs()[0].empty());
+  EXPECT_FALSE(state.epochs()[1].empty());
   EXPECT_EQ(state.epochs()[1].calculation_time(), kTime2);
 
-  EXPECT_EQ(state.next_scheduled_calculation_time(), kTime3);
+  state.UpdateNextScheduledCalculationTime();
+
+  EXPECT_EQ(state.next_scheduled_calculation_time(),
+            base::Time::Now() + base::Days(7));
   EXPECT_TRUE(std::equal(state.hmac_key().begin(), state.hmac_key().end(),
                          kTestKey.begin()));
 }
@@ -363,22 +492,23 @@
   state.AddEpoch(CreateTestEpochTopics(kTime1));
 
   EXPECT_EQ(state.epochs().size(), 1u);
-  EXPECT_TRUE(state.epochs()[0].HasValidTopics());
+  EXPECT_FALSE(state.epochs()[0].empty());
   EXPECT_EQ(state.epochs()[0].calculation_time(), kTime1);
 
   state.AddEpoch(CreateTestEpochTopics(kTime2));
   EXPECT_EQ(state.epochs().size(), 2u);
-  EXPECT_TRUE(state.epochs()[0].HasValidTopics());
+  EXPECT_FALSE(state.epochs()[0].empty());
   EXPECT_EQ(state.epochs()[0].calculation_time(), kTime1);
-  EXPECT_TRUE(state.epochs()[1].HasValidTopics());
+  EXPECT_FALSE(state.epochs()[1].empty());
   EXPECT_EQ(state.epochs()[1].calculation_time(), kTime2);
 
-  state.UpdateNextScheduledCalculationTime(kTime3);
+  state.UpdateNextScheduledCalculationTime();
 
   state.ClearAllTopics();
   EXPECT_EQ(state.epochs().size(), 0u);
 
-  EXPECT_EQ(state.next_scheduled_calculation_time(), kTime3);
+  EXPECT_EQ(state.next_scheduled_calculation_time(),
+            base::Time::Now() + base::Days(7));
   EXPECT_TRUE(std::equal(state.hmac_key().begin(), state.hmac_key().end(),
                          kTestKey.begin()));
 }
diff --git a/components/browsing_topics/epoch_topics.cc b/components/browsing_topics/epoch_topics.cc
index 9d04943c..e70d102 100644
--- a/components/browsing_topics/epoch_topics.cc
+++ b/components/browsing_topics/epoch_topics.cc
@@ -38,7 +38,7 @@
     size_t padded_top_topics_start_index,
     size_t taxonomy_size,
     int taxonomy_version,
-    int model_version,
+    int64_t model_version,
     base::Time calculation_time)
     : top_topics_and_observing_domains_(
           std::move(top_topics_and_observing_domains)),
@@ -105,12 +105,17 @@
 
   int taxonomy_version = *taxonomy_version_value;
 
-  absl::optional<int> model_version_value =
-      dict_value.FindInt(kModelVersionNameKey);
+  const base::Value* model_version_value =
+      dict_value.Find(kModelVersionNameKey);
   if (!model_version_value)
     return EpochTopics();
 
-  int model_version = *model_version_value;
+  absl::optional<int64_t> model_version_int64_value =
+      base::ValueToInt64(model_version_value);
+  if (!model_version_int64_value)
+    return EpochTopics();
+
+  int64_t model_version = *model_version_int64_value;
 
   const base::Value* calculation_time_value =
       dict_value.Find(kCalculationTimeNameKey);
@@ -141,7 +146,7 @@
   result_dict.Set(kTaxonomySizeNameKey,
                   base::checked_cast<int>(taxonomy_size_));
   result_dict.Set(kTaxonomyVersionNameKey, taxonomy_version_);
-  result_dict.Set(kModelVersionNameKey, model_version_);
+  result_dict.Set(kModelVersionNameKey, base::Int64ToValue(model_version_));
   result_dict.Set(kCalculationTimeNameKey,
                   base::TimeToValue(calculation_time_));
   return result_dict;
@@ -151,8 +156,29 @@
     const std::string& top_domain,
     const HashedDomain& hashed_context_domain,
     ReadOnlyHmacKey hmac_key) const {
+  return TopicForSiteHelper(top_domain, /*need_filtering=*/true,
+                            hashed_context_domain, hmac_key);
+}
+
+absl::optional<Topic> EpochTopics::TopicForSiteNoFiltering(
+    const std::string& top_domain,
+    ReadOnlyHmacKey hmac_key) const {
+  return TopicForSiteHelper(top_domain, /*need_filtering=*/false,
+                            /*hashed_context_domain=*/{}, hmac_key);
+}
+
+void EpochTopics::ClearTopics() {
+  top_topics_and_observing_domains_.clear();
+  padded_top_topics_start_index_ = 0;
+}
+
+absl::optional<Topic> EpochTopics::TopicForSiteHelper(
+    const std::string& top_domain,
+    bool need_filtering,
+    const HashedDomain& hashed_context_domain,
+    ReadOnlyHmacKey hmac_key) const {
   // The topics calculation failed, or the topics has been cleared.
-  if (!HasValidTopics())
+  if (empty())
     return absl::nullopt;
 
   uint64_t random_or_top_topic_decision_hash =
@@ -179,18 +205,16 @@
   const TopicAndDomains& topic_and_observing_domains =
       top_topics_and_observing_domains_[top_topic_index];
 
+  if (!topic_and_observing_domains.IsValid())
+    return absl::nullopt;
+
   // Only add the topic if the context has observed it before.
-  if (!topic_and_observing_domains.hashed_domains().count(
-          hashed_context_domain)) {
+  if (need_filtering && !topic_and_observing_domains.hashed_domains().count(
+                            hashed_context_domain)) {
     return absl::nullopt;
   }
 
   return topic_and_observing_domains.topic();
 }
 
-void EpochTopics::ClearTopics() {
-  top_topics_and_observing_domains_.clear();
-  padded_top_topics_start_index_ = 0;
-}
-
 }  // namespace browsing_topics
diff --git a/components/browsing_topics/epoch_topics.h b/components/browsing_topics/epoch_topics.h
index d38a3c2..88bea0a 100644
--- a/components/browsing_topics/epoch_topics.h
+++ b/components/browsing_topics/epoch_topics.h
@@ -24,7 +24,7 @@
               size_t padded_top_topics_start_index,
               size_t taxonomy_size,
               int taxonomy_version,
-              int model_version,
+              int64_t model_version,
               base::Time calculation_time);
 
   EpochTopics(const EpochTopics&) = delete;
@@ -49,9 +49,14 @@
                                      const HashedDomain& hashed_context_domain,
                                      ReadOnlyHmacKey hmac_key) const;
 
-  bool HasValidTopics() const {
-    return !top_topics_and_observing_domains_.empty();
-  }
+  // Similar to `TopicForSite`, but without applying the filtering based on a
+  // calling context. This method is used for displaying the candidate topics
+  // for a site for the UX.
+  absl::optional<Topic> TopicForSiteNoFiltering(const std::string& top_domain,
+                                                ReadOnlyHmacKey hmac_key) const;
+
+  // Whether `top_topics_and_observing_domains_` is empty.
+  bool empty() const { return top_topics_and_observing_domains_.empty(); }
 
   // Clear `top_topics_and_observing_domains_` and
   // reset `padded_top_topics_start_index_` to 0.
@@ -69,11 +74,17 @@
 
   int taxonomy_version() const { return taxonomy_version_; }
 
-  int model_version() const { return model_version_; }
+  int64_t model_version() const { return model_version_; }
 
   base::Time calculation_time() const { return calculation_time_; }
 
  private:
+  absl::optional<Topic> TopicForSiteHelper(
+      const std::string& top_domain,
+      bool need_filtering,
+      const HashedDomain& hashed_context_domain,
+      ReadOnlyHmacKey hmac_key) const;
+
   // The top topics for this epoch, and the context domains that observed each
   // topic across
   // `kBrowsingTopicsNumberOfEpochsOfObservationDataToUseForFiltering` epochs.
@@ -98,7 +109,7 @@
   int taxonomy_version_ = 0;
 
   // The version of the model used to calculate this epoch's topics.
-  int model_version_ = 0;
+  int64_t model_version_ = 0;
 
   // The calculation start time. This also determines the time range of the
   // underlying topics data.
diff --git a/components/browsing_topics/epoch_topics_unittest.cc b/components/browsing_topics/epoch_topics_unittest.cc
index 52ccb1d..69e2a49 100644
--- a/components/browsing_topics/epoch_topics_unittest.cc
+++ b/components/browsing_topics/epoch_topics_unittest.cc
@@ -12,13 +12,13 @@
 
 namespace {
 
-const base::Time kCalculationTime =
+constexpr base::Time kCalculationTime =
     base::Time::FromDeltaSinceWindowsEpoch(base::Days(1));
-const browsing_topics::HmacKey kTestKey = {1};
-const size_t kTaxonomySize = 349;
-const int kTaxonomyVersion = 1;
-const int kModelVersion = 2;
-const size_t kPaddedTopTopicsStartIndex = 3;
+constexpr browsing_topics::HmacKey kTestKey = {1};
+constexpr size_t kTaxonomySize = 349;
+constexpr int kTaxonomyVersion = 1;
+constexpr int64_t kModelVersion = 2;
+constexpr size_t kPaddedTopTopicsStartIndex = 3;
 
 EpochTopics CreateTestEpochTopics() {
   std::vector<TopicAndDomains> top_topics_and_observing_domains;
@@ -44,10 +44,27 @@
 
 class EpochTopicsTest : public testing::Test {};
 
+TEST_F(EpochTopicsTest, TopicForSite_InvalidIndividualTopics) {
+  std::vector<TopicAndDomains> top_topics_and_observing_domains;
+  for (int i = 0; i < 5; ++i) {
+    top_topics_and_observing_domains.emplace_back(TopicAndDomains());
+  }
+
+  EpochTopics epoch_topics(std::move(top_topics_and_observing_domains),
+                           kPaddedTopTopicsStartIndex, kTaxonomySize,
+                           kTaxonomyVersion, kModelVersion, kCalculationTime);
+  EXPECT_FALSE(epoch_topics.empty());
+
+  std::string top_site = "foo.com";
+
+  EXPECT_EQ(epoch_topics.TopicForSiteNoFiltering(top_site, kTestKey),
+            absl::nullopt);
+}
+
 TEST_F(EpochTopicsTest, TopicForSite) {
   EpochTopics epoch_topics = CreateTestEpochTopics();
 
-  EXPECT_TRUE(epoch_topics.HasValidTopics());
+  EXPECT_FALSE(epoch_topics.empty());
   EXPECT_EQ(epoch_topics.taxonomy_version(), kTaxonomyVersion);
   EXPECT_EQ(epoch_topics.model_version(), kModelVersion);
   EXPECT_EQ(epoch_topics.calculation_time(), kCalculationTime);
@@ -76,6 +93,9 @@
               Topic(2));
     EXPECT_EQ(epoch_topics.TopicForSite(top_site, HashedDomain(3), kTestKey),
               absl::nullopt);
+
+    EXPECT_EQ(epoch_topics.TopicForSiteNoFiltering(top_site, kTestKey),
+              Topic(2));
   }
 
   {
@@ -102,6 +122,9 @@
               absl::nullopt);
     EXPECT_EQ(epoch_topics.TopicForSite(top_site, HashedDomain(3), kTestKey),
               Topic(3));
+
+    EXPECT_EQ(epoch_topics.TopicForSiteNoFiltering(top_site, kTestKey),
+              Topic(3));
   }
 
   {
@@ -127,17 +150,20 @@
               Topic(186));
     EXPECT_EQ(epoch_topics.TopicForSite(top_site, HashedDomain(3), kTestKey),
               Topic(186));
+
+    EXPECT_EQ(epoch_topics.TopicForSiteNoFiltering(top_site, kTestKey),
+              Topic(186));
   }
 }
 
 TEST_F(EpochTopicsTest, ClearTopics) {
   EpochTopics epoch_topics = CreateTestEpochTopics();
 
-  EXPECT_TRUE(epoch_topics.HasValidTopics());
+  EXPECT_FALSE(epoch_topics.empty());
 
   epoch_topics.ClearTopics();
 
-  EXPECT_FALSE(epoch_topics.HasValidTopics());
+  EXPECT_TRUE(epoch_topics.empty());
 
   EXPECT_EQ(epoch_topics.TopicForSite(/*top_domain=*/"foo.com", HashedDomain(1),
                                       kTestKey),
@@ -148,7 +174,7 @@
   EpochTopics read_epoch_topics =
       EpochTopics::FromDictValue(base::Value::Dict());
 
-  EXPECT_FALSE(read_epoch_topics.HasValidTopics());
+  EXPECT_TRUE(read_epoch_topics.empty());
   EXPECT_EQ(read_epoch_topics.taxonomy_version(), 0);
   EXPECT_EQ(read_epoch_topics.model_version(), 0);
   EXPECT_EQ(read_epoch_topics.calculation_time(), base::Time());
@@ -166,7 +192,7 @@
   base::Value::Dict dict_value = epoch_topics.ToDictValue();
   EpochTopics read_epoch_topics = EpochTopics::FromDictValue(dict_value);
 
-  EXPECT_FALSE(read_epoch_topics.HasValidTopics());
+  EXPECT_TRUE(read_epoch_topics.empty());
   EXPECT_EQ(read_epoch_topics.taxonomy_version(), 0);
   EXPECT_EQ(read_epoch_topics.model_version(), 0);
   EXPECT_EQ(read_epoch_topics.calculation_time(), base::Time());
@@ -183,7 +209,7 @@
   base::Value::Dict dict_value = epoch_topics.ToDictValue();
   EpochTopics read_epoch_topics = EpochTopics::FromDictValue(dict_value);
 
-  EXPECT_TRUE(read_epoch_topics.HasValidTopics());
+  EXPECT_FALSE(read_epoch_topics.empty());
   EXPECT_EQ(read_epoch_topics.taxonomy_version(), 1);
   EXPECT_EQ(read_epoch_topics.model_version(), 2);
   EXPECT_EQ(read_epoch_topics.calculation_time(), kCalculationTime);
diff --git a/components/browsing_topics/test_util.cc b/components/browsing_topics/test_util.cc
index e163029..2fff5952 100644
--- a/components/browsing_topics/test_util.cc
+++ b/components/browsing_topics/test_util.cc
@@ -4,8 +4,43 @@
 
 #include "components/browsing_topics/test_util.h"
 
+#include "base/run_loop.h"
+#include "base/test/bind.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "components/history/core/browser/history_service.h"
+
 namespace browsing_topics {
 
+bool BrowsingTopicsEligibleForURLVisit(history::HistoryService* history_service,
+                                       const GURL& url) {
+  bool topics_eligible;
+
+  history::QueryOptions options;
+  options.duplicate_policy = history::QueryOptions::KEEP_ALL_DUPLICATES;
+
+  base::RunLoop run_loop;
+  base::CancelableTaskTracker tracker;
+
+  history_service->QueryHistory(
+      std::u16string(), options,
+      base::BindLambdaForTesting([&](history::QueryResults results) {
+        size_t num_matches = 0;
+        const size_t* match_index = results.MatchesForURL(url, &num_matches);
+
+        DCHECK_EQ(1u, num_matches);
+
+        topics_eligible =
+            results[*match_index].content_annotations().annotation_flags &
+            history::VisitContentAnnotationFlag::kBrowsingTopicsEligible;
+        run_loop.Quit();
+      }),
+      &tracker);
+
+  run_loop.Run();
+
+  return topics_eligible;
+}
+
 TesterBrowsingTopicsCalculator::TesterBrowsingTopicsCalculator(
     privacy_sandbox::PrivacySandboxSettings* privacy_sandbox_settings,
     history::HistoryService* history_service,
@@ -20,6 +55,20 @@
                                std::move(callback)),
       rand_uint64_queue_(std::move(rand_uint64_queue)) {}
 
+TesterBrowsingTopicsCalculator::TesterBrowsingTopicsCalculator(
+    CalculateCompletedCallback callback,
+    EpochTopics mock_result,
+    base::TimeDelta mock_result_delay)
+    : BrowsingTopicsCalculator(nullptr,
+                               nullptr,
+                               nullptr,
+                               nullptr,
+                               base::DoNothing()),
+      use_mock_result_(true),
+      mock_result_(std::move(mock_result)),
+      mock_result_delay_(mock_result_delay),
+      finish_callback_(std::move(callback)) {}
+
 TesterBrowsingTopicsCalculator::~TesterBrowsingTopicsCalculator() = default;
 
 uint64_t TesterBrowsingTopicsCalculator::GenerateRandUint64() {
@@ -31,4 +80,23 @@
   return next_rand_uint64;
 }
 
+void TesterBrowsingTopicsCalculator::CheckCanCalculate() {
+  if (use_mock_result_) {
+    base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+        FROM_HERE,
+        base::BindOnce(&TesterBrowsingTopicsCalculator::MockDelayReached,
+                       weak_ptr_factory_.GetWeakPtr()),
+        mock_result_delay_);
+    return;
+  }
+
+  BrowsingTopicsCalculator::CheckCanCalculate();
+}
+
+void TesterBrowsingTopicsCalculator::MockDelayReached() {
+  DCHECK(use_mock_result_);
+
+  std::move(finish_callback_).Run(std::move(mock_result_));
+}
+
 }  // namespace browsing_topics
diff --git a/components/browsing_topics/test_util.h b/components/browsing_topics/test_util.h
index cc9c2351..f0e6b13 100644
--- a/components/browsing_topics/test_util.h
+++ b/components/browsing_topics/test_util.h
@@ -6,12 +6,20 @@
 #define COMPONENTS_BROWSING_TOPICS_TEST_UTIL_H_
 
 #include "base/containers/queue.h"
+
+#include "base/memory/weak_ptr.h"
 #include "components/browsing_topics/browsing_topics_calculator.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace browsing_topics {
 
-// A tester class that allows mocking the generated random numbers.
+// Returns whether the URL entry is eligible in topics calculation.
+// Precondition: the history visits contain exactly one matching URL.
+bool BrowsingTopicsEligibleForURLVisit(history::HistoryService* history_service,
+                                       const GURL& url);
+
+// A tester class that allows mocking the generated random numbers, or directly
+// returning a mock result with a delay.
 class TesterBrowsingTopicsCalculator : public BrowsingTopicsCalculator {
  public:
   // Initialize a regular `BrowsingTopicsCalculator` with an additional
@@ -24,6 +32,11 @@
       CalculateCompletedCallback callback,
       base::queue<uint64_t> rand_uint64_queue);
 
+  // Initialize a mock `BrowsingTopicsCalculator` (with mock result and delay).
+  TesterBrowsingTopicsCalculator(CalculateCompletedCallback callback,
+                                 EpochTopics mock_result,
+                                 base::TimeDelta mock_result_delay);
+
   ~TesterBrowsingTopicsCalculator() override;
 
   TesterBrowsingTopicsCalculator(const TesterBrowsingTopicsCalculator&) =
@@ -38,8 +51,22 @@
   // `rand_uint64_queue_` is not empty.
   uint64_t GenerateRandUint64() override;
 
+  // If `use_mock_result_` is true, post a task with `mock_result_delay_` to
+  // directly invoke the `finish_callback_` with `mock_result_`; otherwise, use
+  // the default handling for `CheckCanCalculate`.
+  void CheckCanCalculate() override;
+
  private:
+  void MockDelayReached();
+
   base::queue<uint64_t> rand_uint64_queue_;
+
+  bool use_mock_result_ = false;
+  EpochTopics mock_result_;
+  base::TimeDelta mock_result_delay_;
+  CalculateCompletedCallback finish_callback_;
+
+  base::WeakPtrFactory<TesterBrowsingTopicsCalculator> weak_ptr_factory_{this};
 };
 
 }  // namespace browsing_topics
diff --git a/components/commerce/core/commerce_feature_list.h b/components/commerce/core/commerce_feature_list.h
index 82e63e6..10a5bd4 100644
--- a/components/commerce/core/commerce_feature_list.h
+++ b/components/commerce/core/commerce_feature_list.h
@@ -82,7 +82,7 @@
 constexpr base::FeatureParam<bool> kOptimizeRendererSignal(
     &ntp_features::kNtpChromeCartModule,
     "optimize-renderer-signal",
-    false);
+    true);
 
 constexpr base::FeatureParam<base::TimeDelta> kDiscountFetchDelayParam(
     &ntp_features::kNtpChromeCartModule,
diff --git a/components/download/network/android/java/src/org/chromium/components/download/BackgroundNetworkStatusListener.java b/components/download/network/android/java/src/org/chromium/components/download/BackgroundNetworkStatusListener.java
index a636100..0cbfa6c 100644
--- a/components/download/network/android/java/src/org/chromium/components/download/BackgroundNetworkStatusListener.java
+++ b/components/download/network/android/java/src/org/chromium/components/download/BackgroundNetworkStatusListener.java
@@ -101,6 +101,8 @@
         runOnMainThread(() -> { mObserver.onConnectionTypeChanged(newConnectionType); });
     }
     @Override
+    public void onConnectionCostChanged(int newConnectionCost) {}
+    @Override
     public void onConnectionSubtypeChanged(int newConnectionSubtype) {}
     @Override
     public void onNetworkConnect(long netId, int connectionType) {}
diff --git a/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java b/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java
index dd204e7..ec31718b 100644
--- a/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java
+++ b/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java
@@ -84,9 +84,6 @@
      */
     public static ContentView createContentView(Context context,
             @Nullable EventOffsetHandler eventOffsetHandler, @Nullable WebContents webContents) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            return new ContentViewApi23(context, eventOffsetHandler, webContents);
-        }
         return new ContentView(context, eventOffsetHandler, webContents);
     }
 
@@ -96,7 +93,8 @@
      *                access the current theme, resources, etc.
      * @param webContents A pointer to the WebContents managing this content view.
      */
-    ContentView(Context context, EventOffsetHandler eventOffsetHandler, WebContents webContents) {
+    protected ContentView(
+            Context context, EventOffsetHandler eventOffsetHandler, WebContents webContents) {
         super(context, null, android.R.attr.webViewStyle);
 
         if (getScrollBarStyle() == View.SCROLLBARS_INSIDE_OVERLAY) {
@@ -539,6 +537,12 @@
         }
     }
 
+    @Override
+    public void onProvideVirtualStructure(final ViewStructure structure) {
+        WebContentsAccessibility wcax = getWebContentsAccessibility();
+        if (wcax != null) wcax.onProvideVirtualStructure(structure, false);
+    }
+
     ///////////////////////////////////////////////////////////////////////////////////////////////
     //              Start Implementation of ViewEventSink.InternalAccessDelegate                 //
     ///////////////////////////////////////////////////////////////////////////////////////////////
@@ -569,20 +573,4 @@
     private boolean webContentsAttached() {
         return hasValidWebContents() && mWebContents.getTopLevelNativeWindow() != null;
     }
-
-    /**
-     * ContentView on Api23 to override onProvideVirtualStructure.
-     */
-    public static class ContentViewApi23 extends ContentView {
-        protected ContentViewApi23(
-                Context context, EventOffsetHandler eventOffsetHandler, WebContents webContents) {
-            super(context, eventOffsetHandler, webContents);
-        }
-
-        @Override
-        public void onProvideVirtualStructure(final ViewStructure structure) {
-            WebContentsAccessibility wcax = getWebContentsAccessibility();
-            if (wcax != null) wcax.onProvideVirtualStructure(structure, false);
-        }
-    }
 }
diff --git a/components/feature_engagement/README.md b/components/feature_engagement/README.md
index a915d69f..cc3cb051 100644
--- a/components/feature_engagement/README.md
+++ b/components/feature_engagement/README.md
@@ -35,9 +35,9 @@
         might not want to show a different one.
     *   Whether we have shown a particular In-Product Help or not might be a
         precondition for whether we should show different one.
-*   Users should be able to use try out a feature on their own for some time
-    before they see help.
-    *   We should show In-Product Help only if they don't seem use it, but we
+*   Users should be able to try out a feature on their own for some time before
+    they see help.
+    *   We should show In-Product Help only if they don't seem to use it, but we
         believe it would be helpful to them.
 *   Share the same statistics framework across all of Chrome.
     *   Sharing a framework within Chrome makes it easier to track statistics
@@ -82,7 +82,7 @@
 first time a user has an IPH available, that will typically be true, since the
 event just started being tracked so no interactions have been recorded yet. E.g.
 if a precondition is "the user has never opened the menu", and this has not been
-tracked before, the number of times that we have so far have recorded that the
+tracked before, the number of times that we have so far recorded that the
 user has opened the menu is 0, even if that is a common action for the user.
 Therefore, the framework supports requiring the IPH to have been available for a
 certain amount of days before being applicable. With the opening of menu
@@ -107,7 +107,7 @@
     by notifying about events, and checking whether In-Product Help should be
     displayed.
 *   [Configure UMA](#Required-UMA-Changes).
-*   [Add a local field trial testing configuration](#Adding-a-local-field-trial-testing-configuration).
+*   [Add a field trial configuration](#field-trial-configuration).
 
 ### Declaring your feature
 
@@ -590,8 +590,8 @@
   "availability": ">=0",
   "session_rate": "<1",
   "event_used": "name:shopping_list_track_price_from_menu;comparator:==0;window:360;storage:360",
-  "event_trigger": "shopping_list_menu_item_iph_triggered;comparator:==0;window:7;storage:7",
-  "event_trigger_1": "shopping_list_menu_item_iph_triggered;comparator:<3;window:36;storage:360"
+  "event_trigger": "name:shopping_list_menu_item_iph_triggered;comparator:==0;window:7;storage:7",
+  "event_trigger_1": "name:shopping_list_menu_item_iph_triggered;comparator:<3;window:360;storage:360"
 }
 ```
 
@@ -757,7 +757,7 @@
 *   `all` means this feature blocks every other feature regarding their
     `IsBlocked` calculations. This is the default.
 *   `none` means that this feature does not block any other features regarding
-    the `IsBlocked` calculation. 
+    the `IsBlocked` calculation.
 
 **Examples**
 
diff --git a/components/history_clusters/core/on_device_clustering_backend.cc b/components/history_clusters/core/on_device_clustering_backend.cc
index 88a5d3a8..9c25f81 100644
--- a/components/history_clusters/core/on_device_clustering_backend.cc
+++ b/components/history_clusters/core/on_device_clustering_backend.cc
@@ -305,7 +305,8 @@
       for (const auto& entity :
            visit.content_annotations.model_annotations.entities) {
         auto entity_metadata_it = entity_metadata_map.find(entity.id);
-        if (entity_metadata_it == entity_metadata_map.end()) {
+        if (entity_metadata_it == entity_metadata_map.end() ||
+            entity.weight < GetConfig().entity_relevance_threshold) {
           continue;
         }
 
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 951f6542..060b3ab 100644
--- a/components/history_clusters/core/on_device_clustering_backend_unittest.cc
+++ b/components/history_clusters/core/on_device_clustering_backend_unittest.cc
@@ -571,6 +571,9 @@
       3, GURL("http://non-default-engine.com/?q=nometadata#whatever"));
   visit3.content_annotations.model_annotations.entities = {
       history::VisitContentModelAnnotations::Category("nometadata", 100),
+      // This is too low and should not be added as a keyword despite it
+      // being a valid entity for a different visit.
+      history::VisitContentModelAnnotations::Category("foo", 10),
   };
   visit3.content_annotations.search_terms = u"nometadata";
   visit3.content_annotations.search_normalized_url =
diff --git a/components/history_clusters_strings.grdp b/components/history_clusters_strings.grdp
index b23babd..b42b82f 100644
--- a/components/history_clusters_strings.grdp
+++ b/components/history_clusters_strings.grdp
@@ -9,9 +9,6 @@
   <message name="IDS_HISTORY_CLUSTERS_ENABLE_MENU_ITEM_LABEL" desc="A label for the menu item to turn on the Journeys feature, which collects different search and browsing activities related to a single topic into a single place, and organizes them by topic. See glossary entry for meaning of 'Journeys'.">
     Turn on Journeys
   </message>
-  <message name="IDS_HISTORY_CLUSTERS_HEADER_TEXT" desc="Header text shown when the history items related to a given user search term are shown.">
-    Based on activity related to "<ph name="SEARCH_TERM"><ex>dual kitchen range</ex>$1</ph>"
-  </message>
   <message name="IDS_HISTORY_CLUSTERS_JOURNEYS_TAB_LABEL" desc="A label for the section in Chrome History (chrome://history) where Journeys are collected and shown to the user. See glossary entry for meaning of 'Journeys'.">
     Journeys
   </message>
diff --git a/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_HEADER_TEXT.png.sha1 b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_HEADER_TEXT.png.sha1
deleted file mode 100644
index 015683cc..0000000
--- a/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_HEADER_TEXT.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-35373dc4f1bc5cfa770be6f9d591538cf9a79971
\ No newline at end of file
diff --git a/components/js_injection/OWNERS b/components/js_injection/OWNERS
index 5dfb9a2..90b3e80 100644
--- a/components/js_injection/OWNERS
+++ b/components/js_injection/OWNERS
@@ -1,2 +1 @@
-ctzsm@chromium.org
 sky@chromium.org
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn
index e48c97fe..b161388a 100644
--- a/components/omnibox/browser/BUILD.gn
+++ b/components/omnibox/browser/BUILD.gn
@@ -465,6 +465,7 @@
 static_library("test_support") {
   testonly = true
   sources = [
+    "fake_autocomplete_provider.h",
     "fake_autocomplete_provider_client.cc",
     "fake_autocomplete_provider_client.h",
     "history_index_restore_observer.cc",
diff --git a/components/omnibox/browser/autocomplete_match.cc b/components/omnibox/browser/autocomplete_match.cc
index f673126..b54a192 100644
--- a/components/omnibox/browser/autocomplete_match.cc
+++ b/components/omnibox/browser/autocomplete_match.cc
@@ -536,17 +536,26 @@
       return false;
   }
 
-  // Prefer live document suggestions. We check provider type instead of match
-  // type in order to distinguish live suggestions from the document provider
-  // from stale suggestions from the shortcuts providers, because the latter
-  // omits changing metadata such as last access date.
-  if (match1.provider->type() == AutocompleteProvider::TYPE_DOCUMENT &&
-      match2.provider->type() != AutocompleteProvider::TYPE_DOCUMENT) {
-    return true;
-  }
-  if (match1.provider->type() != AutocompleteProvider::TYPE_DOCUMENT &&
-      match2.provider->type() == AutocompleteProvider::TYPE_DOCUMENT) {
-    return false;
+  // Prefer some providers over others.
+  const std::vector<AutocompleteProvider::Type> preferred_providers = {
+      // Prefer live document suggestions. We check provider type instead of
+      // match type in order to distinguish live suggestions from the document
+      // provider from stale suggestions from the shortcuts providers, because
+      // the latter omits changing metadata such as last access date.
+      AutocompleteProvider::TYPE_DOCUMENT,
+      // Prefer bookmark suggestions, as 1) their titles may be explicitly set,
+      // and 2) they may display enhanced information such as the bookmark
+      // folders path.
+      AutocompleteProvider::TYPE_BOOKMARK,
+  };
+
+  if (match1.provider->type() != match2.provider->type()) {
+    for (const auto& preferred_provider : preferred_providers) {
+      if (match1.provider->type() == preferred_provider)
+        return true;
+      if (match2.provider->type() == preferred_provider)
+        return false;
+    }
   }
 
   // By default, simply prefer the more relevant match.
diff --git a/components/omnibox/browser/autocomplete_match_unittest.cc b/components/omnibox/browser/autocomplete_match_unittest.cc
index e38d1a1..8c56e50 100644
--- a/components/omnibox/browser/autocomplete_match_unittest.cc
+++ b/components/omnibox/browser/autocomplete_match_unittest.cc
@@ -11,6 +11,8 @@
 #include "autocomplete_match.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
+#include "components/omnibox/browser/autocomplete_provider.h"
+#include "components/omnibox/browser/fake_autocomplete_provider.h"
 #include "components/omnibox/browser/test_scheme_classifier.h"
 #include "components/omnibox/common/omnibox_features.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -826,3 +828,43 @@
     test("x_y_z", "z_y_x_", "x_z_y_", false, {}, "", false);
   }
 }
+
+TEST(AutocompleteMatchTest, BetterDuplicate) {
+  const auto create_match = [](scoped_refptr<FakeAutocompleteProvider> provider,
+                               int relevance) {
+    return AutocompleteMatch{provider.get(), relevance, false,
+                             AutocompleteMatchType::URL_WHAT_YOU_TYPED};
+  };
+
+  scoped_refptr<FakeAutocompleteProvider> document_provider =
+      new FakeAutocompleteProvider(AutocompleteProvider::Type::TYPE_DOCUMENT);
+
+  scoped_refptr<FakeAutocompleteProvider> bookmark_provider =
+      new FakeAutocompleteProvider(AutocompleteProvider::Type::TYPE_BOOKMARK);
+
+  scoped_refptr<FakeAutocompleteProvider> history_provider =
+      new FakeAutocompleteProvider(
+          AutocompleteProvider::Type::TYPE_HISTORY_QUICK);
+
+  // Prefer document provider matches over other providers, even if scored
+  // lower.
+  EXPECT_TRUE(
+      AutocompleteMatch::BetterDuplicate(create_match(document_provider, 0),
+                                         create_match(history_provider, 1000)));
+
+  // Prefer document provider matches over other providers, even if scored
+  // lower.
+  EXPECT_TRUE(
+      AutocompleteMatch::BetterDuplicate(create_match(bookmark_provider, 0),
+                                         create_match(history_provider, 1000)));
+
+  // Prefer document provider matches over bookmark provider matches.
+  EXPECT_TRUE(AutocompleteMatch::BetterDuplicate(
+      create_match(document_provider, 0),
+      create_match(bookmark_provider, 1000)));
+
+  // Prefer more relevant matches.
+  EXPECT_FALSE(
+      AutocompleteMatch::BetterDuplicate(create_match(history_provider, 500),
+                                         create_match(history_provider, 510)));
+}
diff --git a/components/omnibox/browser/autocomplete_result_unittest.cc b/components/omnibox/browser/autocomplete_result_unittest.cc
index 1f0b547..a38cc54 100644
--- a/components/omnibox/browser/autocomplete_result_unittest.cc
+++ b/components/omnibox/browser/autocomplete_result_unittest.cc
@@ -25,6 +25,7 @@
 #include "components/omnibox/browser/autocomplete_match_type.h"
 #include "components/omnibox/browser/autocomplete_provider.h"
 #include "components/omnibox/browser/autocomplete_provider_client.h"
+#include "components/omnibox/browser/fake_autocomplete_provider.h"
 #include "components/omnibox/browser/fake_autocomplete_provider_client.h"
 #include "components/omnibox/browser/fake_tab_matcher.h"
 #include "components/omnibox/browser/intranet_redirector_state.h"
@@ -80,24 +81,6 @@
   }
 }
 
-// A simple AutocompleteProvider that does nothing.
-class FakeAutocompleteProvider : public AutocompleteProvider {
- public:
-  explicit FakeAutocompleteProvider(Type type) : AutocompleteProvider(type) {}
-
-  void Start(const AutocompleteInput& input, bool minimal_changes) override {}
-
-  // For simplicity, |FakeAutocompleteProvider|'s retrieved through
-  // |GetProvider| have types 0, 1, ... 5. This is fine for most tests, but for
-  // tests where the provider type matters (e.g. tests that involve deduping
-  // document suggestions), provider types need to be consistent with
-  // |AutocompleteProvider::Type|.
-  void SetType(Type type) { type_ = type; }
-
- private:
-  ~FakeAutocompleteProvider() override = default;
-};
-
 }  // namespace
 
 class AutocompleteResultTest : public testing::Test {
@@ -132,11 +115,17 @@
   AutocompleteResultTest() {
     variations::testing::ClearAllVariationParams();
 
-    // Create the list of mock providers.  5 is enough.
-    for (size_t i = 0; i < 5; ++i) {
-      mock_provider_list_.push_back(new FakeAutocompleteProvider(
-          static_cast<AutocompleteProvider::Type>(i)));
-    }
+    // Create the list of mock providers. 5 is enough.
+    mock_provider_list_.push_back(new FakeAutocompleteProvider(
+        AutocompleteProvider::Type::TYPE_HISTORY_QUICK));
+    mock_provider_list_.push_back(new FakeAutocompleteProvider(
+        AutocompleteProvider::Type::TYPE_HISTORY_URL));
+    mock_provider_list_.push_back(
+        new FakeAutocompleteProvider(AutocompleteProvider::Type::TYPE_SEARCH));
+    mock_provider_list_.push_back(new FakeAutocompleteProvider(
+        AutocompleteProvider::Type::TYPE_ON_DEVICE_HEAD));
+    mock_provider_list_.push_back(new FakeAutocompleteProvider(
+        AutocompleteProvider::Type::TYPE_VERBATIM_MATCH));
   }
   AutocompleteResultTest(const AutocompleteResultTest&) = delete;
   AutocompleteResultTest& operator=(const AutocompleteResultTest&) = delete;
diff --git a/components/omnibox/browser/fake_autocomplete_provider.h b/components/omnibox/browser/fake_autocomplete_provider.h
new file mode 100644
index 0000000..cbbd508
--- /dev/null
+++ b/components/omnibox/browser/fake_autocomplete_provider.h
@@ -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.
+
+#ifndef COMPONENTS_OMNIBOX_BROWSER_FAKE_AUTOCOMPLETE_PROVIDER_H_
+#define COMPONENTS_OMNIBOX_BROWSER_FAKE_AUTOCOMPLETE_PROVIDER_H_
+
+#include "components/omnibox/browser/autocomplete_provider.h"
+
+// A simple `AutocompleteProvider` that does nothing. Useful for creating
+// `AutocompleteMatch`s in tests with specific provider types.
+class FakeAutocompleteProvider : public AutocompleteProvider {
+ public:
+  explicit FakeAutocompleteProvider(Type type) : AutocompleteProvider(type) {}
+
+  void Start(const AutocompleteInput& input, bool minimal_changes) override {}
+
+  // Used by some tests that create providers ahead of time and later set the
+  // specific type needed.
+  void SetType(Type type) { type_ = type; }
+
+ private:
+  ~FakeAutocompleteProvider() override = default;
+};
+
+#endif  // COMPONENTS_OMNIBOX_BROWSER_FAKE_AUTOCOMPLETE_PROVIDER_H_
diff --git a/components/omnibox/browser/titled_url_match_utils_unittest.cc b/components/omnibox/browser/titled_url_match_utils_unittest.cc
index 77761e14..7c3b1ea 100644
--- a/components/omnibox/browser/titled_url_match_utils_unittest.cc
+++ b/components/omnibox/browser/titled_url_match_utils_unittest.cc
@@ -15,6 +15,7 @@
 #include "components/omnibox/browser/autocomplete_input.h"
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/omnibox/browser/autocomplete_provider.h"
+#include "components/omnibox/browser/fake_autocomplete_provider.h"
 #include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/omnibox/browser/test_scheme_classifier.h"
 #include "components/omnibox/common/omnibox_features.h"
@@ -26,17 +27,6 @@
 
 namespace {
 
-// A simple AutocompleteProvider that does nothing.
-class FakeAutocompleteProvider : public AutocompleteProvider {
- public:
-  explicit FakeAutocompleteProvider(Type type) : AutocompleteProvider(type) {}
-
-  void Start(const AutocompleteInput& input, bool minimal_changes) override {}
-
- private:
-  ~FakeAutocompleteProvider() override = default;
-};
-
 class MockTitledUrlNode : public bookmarks::TitledUrlNode {
  public:
   MockTitledUrlNode(const std::u16string& title,
diff --git a/components/permissions/BUILD.gn b/components/permissions/BUILD.gn
index 8cbc3d9..9f54146 100644
--- a/components/permissions/BUILD.gn
+++ b/components/permissions/BUILD.gn
@@ -197,6 +197,8 @@
     "test/object_permission_context_base_mock_permission_observer.h",
     "test/permission_request_observer.cc",
     "test/permission_request_observer.h",
+    "test/permission_test_util.cc",
+    "test/permission_test_util.h",
     "test/test_permissions_client.cc",
     "test/test_permissions_client.h",
   ]
diff --git a/components/permissions/permission_manager_unittest.cc b/components/permissions/permission_manager_unittest.cc
index ba27fbd..7fe04975 100644
--- a/components/permissions/permission_manager_unittest.cc
+++ b/components/permissions/permission_manager_unittest.cc
@@ -17,6 +17,7 @@
 #include "components/permissions/permission_request_manager.h"
 #include "components/permissions/permission_result.h"
 #include "components/permissions/test/mock_permission_prompt_factory.h"
+#include "components/permissions/test/permission_test_util.h"
 #include "components/permissions/test/test_permissions_client.h"
 #include "content/public/browser/permission_type.h"
 #include "content/public/test/browser_task_environment.h"
@@ -24,7 +25,6 @@
 #include "content/public/test/test_browser_context.h"
 #include "content/public/test/test_renderer_host.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom.h"
 
 #if BUILDFLAG(IS_ANDROID)
 #include "base/android/build_info.h"
@@ -36,71 +36,6 @@
 namespace permissions {
 namespace {
 
-class FakePermissionContext : public PermissionContextBase {
- public:
-  FakePermissionContext(
-      content::BrowserContext* browser_context,
-      ContentSettingsType content_settings_type,
-      blink::mojom::PermissionsPolicyFeature permissions_policy_feature)
-      : PermissionContextBase(browser_context,
-                              content_settings_type,
-                              permissions_policy_feature) {}
-
-  // PermissionContextBase:
-  bool IsRestrictedToSecureOrigins() const override { return true; }
-};
-
-class FakePermissionContextAlwaysAllow : public FakePermissionContext {
- public:
-  FakePermissionContextAlwaysAllow(
-      content::BrowserContext* browser_context,
-      ContentSettingsType content_settings_type,
-      blink::mojom::PermissionsPolicyFeature permissions_policy_feature)
-      : FakePermissionContext(browser_context,
-                              content_settings_type,
-                              permissions_policy_feature) {}
-
-  // PermissionContextBase:
-  ContentSetting GetPermissionStatusInternal(
-      content::RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin,
-      const GURL& embedding_origin) const override {
-    return CONTENT_SETTING_ALLOW;
-  }
-};
-
-PermissionManager::PermissionContextMap CreatePermissionContexts(
-    content::BrowserContext* browser_context) {
-  PermissionManager::PermissionContextMap permission_contexts;
-  permission_contexts[ContentSettingsType::GEOLOCATION] =
-      std::make_unique<FakePermissionContext>(
-          browser_context, ContentSettingsType::GEOLOCATION,
-          blink::mojom::PermissionsPolicyFeature::kGeolocation);
-  permission_contexts[ContentSettingsType::NOTIFICATIONS] =
-      std::make_unique<FakePermissionContext>(
-          browser_context, ContentSettingsType::NOTIFICATIONS,
-          blink::mojom::PermissionsPolicyFeature::kNotFound);
-  permission_contexts[ContentSettingsType::MIDI_SYSEX] =
-      std::make_unique<FakePermissionContext>(
-          browser_context, ContentSettingsType::MIDI_SYSEX,
-          blink::mojom::PermissionsPolicyFeature::kMidiFeature);
-  permission_contexts[ContentSettingsType::MIDI] =
-      std::make_unique<FakePermissionContextAlwaysAllow>(
-          browser_context, ContentSettingsType::MIDI,
-          blink::mojom::PermissionsPolicyFeature::kMidiFeature);
-  permission_contexts[ContentSettingsType::STORAGE_ACCESS] =
-      std::make_unique<FakePermissionContextAlwaysAllow>(
-          browser_context, ContentSettingsType::STORAGE_ACCESS,
-          blink::mojom::PermissionsPolicyFeature::kStorageAccessAPI);
-#if BUILDFLAG(IS_ANDROID)
-  permission_contexts[ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER] =
-      std::make_unique<FakePermissionContext>(
-          browser_context, ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER,
-          blink::mojom::PermissionsPolicyFeature::kEncryptedMedia);
-#endif
-  return permission_contexts;
-}
-
 #if BUILDFLAG(IS_ANDROID)
 // See https://crbug.com/904883.
 auto GetDefaultProtectedMediaIdentifierPermissionStatus() {
@@ -134,7 +69,7 @@
   PermissionManagerTest()
       : url_("https://example.com"), other_url_("https://foo.com") {}
 
-  PermissionManager* GetPermissionControllerDelegate() {
+  PermissionManager* GetPermissionManager() {
     return static_cast<PermissionManager*>(
         browser_context_->GetPermissionControllerDelegate());
   }
@@ -144,7 +79,7 @@
   }
 
   void CheckPermissionStatus(PermissionType type, PermissionStatus expected) {
-    EXPECT_EQ(expected, GetPermissionControllerDelegate()->GetPermissionStatus(
+    EXPECT_EQ(expected, GetPermissionManager()->GetPermissionStatus(
                             type, url_.DeprecatedGetOriginAsURL(),
                             url_.DeprecatedGetOriginAsURL()));
   }
@@ -152,10 +87,8 @@
   void CheckPermissionResult(ContentSettingsType type,
                              ContentSetting expected_status,
                              PermissionStatusSource expected_status_source) {
-    PermissionResult result =
-        GetPermissionControllerDelegate()->GetPermissionStatus(
-            type, url_.DeprecatedGetOriginAsURL(),
-            url_.DeprecatedGetOriginAsURL());
+    PermissionResult result = GetPermissionManager()->GetPermissionStatus(
+        type, url_.DeprecatedGetOriginAsURL(), url_.DeprecatedGetOriginAsURL());
     EXPECT_EQ(expected_status, result.content_setting);
     EXPECT_EQ(expected_status_source, result.source);
   }
@@ -170,7 +103,7 @@
                          const GURL& origin) {
     base::RunLoop loop;
     quit_closure_ = loop.QuitClosure();
-    GetPermissionControllerDelegate()->RequestPermission(
+    GetPermissionManager()->RequestPermission(
         type, rfh, origin, true,
         base::BindOnce(&PermissionManagerTest::OnPermissionChange,
                        base::Unretained(this)));
@@ -194,7 +127,7 @@
   }
 
   bool PendingRequestsEmpty() {
-    return GetPermissionControllerDelegate()->pending_requests_.IsEmpty();
+    return GetPermissionManager()->pending_requests_.IsEmpty();
   }
 
   // The header policy should only be set once on page load, so we refresh the
@@ -240,14 +173,12 @@
     RenderViewHostTestHarness::SetUp();
     browser_context_ = std::make_unique<content::TestBrowserContext>();
     browser_context_->SetPermissionControllerDelegate(
-        std::make_unique<PermissionManager>(
-            browser_context_.get(),
-            CreatePermissionContexts(browser_context_.get())));
+        permissions::GetPermissionControllerDelegate(browser_context_.get()));
     NavigateAndCommit(url());
   }
 
   void TearDown() override {
-    GetPermissionControllerDelegate()->Shutdown();
+    GetPermissionManager()->Shutdown();
     browser_context_ = nullptr;
     RenderViewHostTestHarness::TearDown();
   }
@@ -338,7 +269,7 @@
 TEST_F(PermissionManagerTest, SubscriptionDestroyedCleanlyWithoutUnsubscribe) {
   // Test that the PermissionManager shuts down cleanly with subscriptions that
   // haven't been removed, crbug.com/720071.
-  GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+  GetPermissionManager()->SubscribePermissionStatusChange(
       PermissionType::GEOLOCATION, main_rfh(), url(),
       base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                           base::Unretained(this)));
@@ -346,7 +277,7 @@
 
 TEST_F(PermissionManagerTest, SubscribeUnsubscribeAfterShutdown) {
   content::PermissionControllerDelegate::SubscriptionId subscription_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::GEOLOCATION, main_rfh(), url(),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
@@ -354,25 +285,23 @@
   // Simulate Keyed Services shutdown pass. Note: Shutdown will be called second
   // time during browser_context destruction. This is ok for now: Shutdown is
   // reenterant.
-  GetPermissionControllerDelegate()->Shutdown();
+  GetPermissionManager()->Shutdown();
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription_id);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id);
 
   // Check that subscribe/unsubscribe after shutdown don't crash.
   content::PermissionControllerDelegate::SubscriptionId subscription2_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::GEOLOCATION, main_rfh(), url(),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription2_id);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription2_id);
 }
 
 TEST_F(PermissionManagerTest, SameTypeChangeNotifies) {
   content::PermissionControllerDelegate::SubscriptionId subscription_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::GEOLOCATION, main_rfh(), url(),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
@@ -383,13 +312,12 @@
   EXPECT_TRUE(callback_called());
   EXPECT_EQ(PermissionStatus::GRANTED, callback_result());
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription_id);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id);
 }
 
 TEST_F(PermissionManagerTest, DifferentTypeChangeDoesNotNotify) {
   content::PermissionControllerDelegate::SubscriptionId subscription_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::GEOLOCATION, main_rfh(), url(),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
@@ -399,19 +327,17 @@
 
   EXPECT_FALSE(callback_called());
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription_id);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id);
 }
 
 TEST_F(PermissionManagerTest, ChangeAfterUnsubscribeDoesNotNotify) {
   content::PermissionControllerDelegate::SubscriptionId subscription_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::GEOLOCATION, main_rfh(), url(),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription_id);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id);
 
   GetHostContentSettingsMap()->SetContentSettingDefaultScope(
       url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW);
@@ -422,18 +348,17 @@
 TEST_F(PermissionManagerTest,
        ChangeAfterUnsubscribeOnlyNotifiesActiveSubscribers) {
   content::PermissionControllerDelegate::SubscriptionId subscription_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::GEOLOCATION, main_rfh(), url(),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
 
-  GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+  GetPermissionManager()->SubscribePermissionStatusChange(
       PermissionType::GEOLOCATION, main_rfh(), url(),
       base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                           base::Unretained(this)));
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription_id);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id);
 
   GetHostContentSettingsMap()->SetContentSettingDefaultScope(
       url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW);
@@ -443,7 +368,7 @@
 
 TEST_F(PermissionManagerTest, DifferentPrimaryUrlDoesNotNotify) {
   content::PermissionControllerDelegate::SubscriptionId subscription_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::GEOLOCATION, main_rfh(), url(),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
@@ -454,13 +379,12 @@
 
   EXPECT_FALSE(callback_called());
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription_id);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id);
 }
 
 TEST_F(PermissionManagerTest, DifferentSecondaryUrlDoesNotNotify) {
   content::PermissionControllerDelegate::SubscriptionId subscription_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::STORAGE_ACCESS_GRANT, main_rfh(), url(),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
@@ -471,13 +395,12 @@
 
   EXPECT_FALSE(callback_called());
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription_id);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id);
 }
 
 TEST_F(PermissionManagerTest, WildCardPatternNotifies) {
   content::PermissionControllerDelegate::SubscriptionId subscription_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::GEOLOCATION, main_rfh(), url(),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
@@ -488,8 +411,7 @@
   EXPECT_TRUE(callback_called());
   EXPECT_EQ(PermissionStatus::GRANTED, callback_result());
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription_id);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id);
 }
 
 TEST_F(PermissionManagerTest, ClearSettingsNotifies) {
@@ -497,7 +419,7 @@
       url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW);
 
   content::PermissionControllerDelegate::SubscriptionId subscription_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::GEOLOCATION, main_rfh(), url(),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
@@ -508,13 +430,12 @@
   EXPECT_TRUE(callback_called());
   EXPECT_EQ(PermissionStatus::ASK, callback_result());
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription_id);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id);
 }
 
 TEST_F(PermissionManagerTest, NewValueCorrectlyPassed) {
   content::PermissionControllerDelegate::SubscriptionId subscription_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::GEOLOCATION, main_rfh(), url(),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
@@ -525,8 +446,7 @@
   EXPECT_TRUE(callback_called());
   EXPECT_EQ(PermissionStatus::DENIED, callback_result());
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription_id);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id);
 }
 
 TEST_F(PermissionManagerTest, ChangeWithoutPermissionChangeDoesNotNotify) {
@@ -534,7 +454,7 @@
       url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW);
 
   content::PermissionControllerDelegate::SubscriptionId subscription_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::GEOLOCATION, main_rfh(), url(),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
@@ -544,8 +464,7 @@
 
   EXPECT_FALSE(callback_called());
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription_id);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id);
 }
 
 TEST_F(PermissionManagerTest, ChangesBackAndForth) {
@@ -553,7 +472,7 @@
       url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ASK);
 
   content::PermissionControllerDelegate::SubscriptionId subscription_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::GEOLOCATION, main_rfh(), url(),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
@@ -572,8 +491,7 @@
   EXPECT_TRUE(callback_called());
   EXPECT_EQ(PermissionStatus::ASK, callback_result());
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription_id);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id);
 }
 
 TEST_F(PermissionManagerTest, ChangesBackAndForthWorker) {
@@ -581,7 +499,7 @@
       url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ASK);
 
   content::PermissionControllerDelegate::SubscriptionId subscription_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::GEOLOCATION, nullptr, url(),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
@@ -600,13 +518,12 @@
   EXPECT_TRUE(callback_called());
   EXPECT_EQ(PermissionStatus::ASK, callback_result());
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription_id);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id);
 }
 
 TEST_F(PermissionManagerTest, SubscribeMIDIPermission) {
   content::PermissionControllerDelegate::SubscriptionId subscription_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::MIDI, main_rfh(), url(),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
@@ -618,8 +535,7 @@
 
   EXPECT_FALSE(callback_called());
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription_id);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id);
 }
 
 TEST_F(PermissionManagerTest, PermissionIgnoredCleanup) {
@@ -631,7 +547,7 @@
 
   NavigateAndCommit(url());
 
-  GetPermissionControllerDelegate()->RequestPermission(
+  GetPermissionManager()->RequestPermission(
       PermissionType::GEOLOCATION, main_rfh(), url(), /*user_gesture=*/true,
       base::BindOnce(&PermissionManagerTest::OnPermissionChange,
                      base::Unretained(this)));
@@ -650,10 +566,9 @@
   GURL insecure_frame("http://www.example.com/geolocation");
   NavigateAndCommit(insecure_frame);
 
-  PermissionResult result =
-      GetPermissionControllerDelegate()->GetPermissionStatusForFrame(
-          ContentSettingsType::GEOLOCATION, web_contents()->GetMainFrame(),
-          insecure_frame);
+  PermissionResult result = GetPermissionManager()->GetPermissionStatusForFrame(
+      ContentSettingsType::GEOLOCATION, web_contents()->GetMainFrame(),
+      insecure_frame);
 
   EXPECT_EQ(CONTENT_SETTING_BLOCK, result.content_setting);
   EXPECT_EQ(PermissionStatusSource::INSECURE_ORIGIN, result.source);
@@ -661,7 +576,7 @@
   GURL secure_frame("https://www.example.com/geolocation");
   NavigateAndCommit(secure_frame);
 
-  result = GetPermissionControllerDelegate()->GetPermissionStatusForFrame(
+  result = GetPermissionManager()->GetPermissionStatusForFrame(
       ContentSettingsType::GEOLOCATION, web_contents()->GetMainFrame(),
       secure_frame);
 
@@ -674,33 +589,28 @@
       url::Origin::Create(GURL("http://example.com/geolocation"));
   const url::Origin kSecureOrigin =
       url::Origin::Create(GURL("https://example.com/geolocation"));
-  EXPECT_FALSE(
-      GetPermissionControllerDelegate()->IsPermissionOverridableByDevTools(
-          PermissionType::GEOLOCATION, kInsecureOrigin));
-  EXPECT_TRUE(
-      GetPermissionControllerDelegate()->IsPermissionOverridableByDevTools(
-          PermissionType::GEOLOCATION, kSecureOrigin));
+  EXPECT_FALSE(GetPermissionManager()->IsPermissionOverridableByDevTools(
+      PermissionType::GEOLOCATION, kInsecureOrigin));
+  EXPECT_TRUE(GetPermissionManager()->IsPermissionOverridableByDevTools(
+      PermissionType::GEOLOCATION, kSecureOrigin));
 }
 
 TEST_F(PermissionManagerTest, MissingContextIsNotOverridable) {
   // Permissions that are not implemented should be denied overridability.
 #if !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID)
-  EXPECT_FALSE(
-      GetPermissionControllerDelegate()->IsPermissionOverridableByDevTools(
-          PermissionType::PROTECTED_MEDIA_IDENTIFIER,
-          url::Origin::Create(GURL("http://localhost"))));
+  EXPECT_FALSE(GetPermissionManager()->IsPermissionOverridableByDevTools(
+      PermissionType::PROTECTED_MEDIA_IDENTIFIER,
+      url::Origin::Create(GURL("http://localhost"))));
 #endif
-  EXPECT_TRUE(
-      GetPermissionControllerDelegate()->IsPermissionOverridableByDevTools(
-          PermissionType::MIDI_SYSEX,
-          url::Origin::Create(GURL("http://localhost"))));
+  EXPECT_TRUE(GetPermissionManager()->IsPermissionOverridableByDevTools(
+      PermissionType::MIDI_SYSEX,
+      url::Origin::Create(GURL("http://localhost"))));
 }
 
 TEST_F(PermissionManagerTest, KillSwitchOnIsNotOverridable) {
   const url::Origin kLocalHost = url::Origin::Create(GURL("http://localhost"));
-  EXPECT_TRUE(
-      GetPermissionControllerDelegate()->IsPermissionOverridableByDevTools(
-          PermissionType::GEOLOCATION, kLocalHost));
+  EXPECT_TRUE(GetPermissionManager()->IsPermissionOverridableByDevTools(
+      PermissionType::GEOLOCATION, kLocalHost));
 
   // Turn on kill switch for GEOLOCATION.
   std::map<std::string, std::string> params;
@@ -713,9 +623,8 @@
   base::FieldTrialList::CreateFieldTrial(
       PermissionContextBase::kPermissionsKillSwitchFieldStudy, "TestGroup");
 
-  EXPECT_FALSE(
-      GetPermissionControllerDelegate()->IsPermissionOverridableByDevTools(
-          PermissionType::GEOLOCATION, kLocalHost));
+  EXPECT_FALSE(GetPermissionManager()->IsPermissionOverridableByDevTools(
+      PermissionType::GEOLOCATION, kLocalHost));
 }
 
 TEST_F(PermissionManagerTest, GetPermissionStatusDelegation) {
@@ -729,12 +638,12 @@
 
   // By default the parent should be able to request access, but not the child.
   EXPECT_EQ(CONTENT_SETTING_ASK,
-            GetPermissionControllerDelegate()
+            GetPermissionManager()
                 ->GetPermissionStatusForFrame(ContentSettingsType::GEOLOCATION,
                                               parent, GURL(kOrigin1))
                 .content_setting);
   EXPECT_EQ(CONTENT_SETTING_BLOCK,
-            GetPermissionControllerDelegate()
+            GetPermissionManager()
                 ->GetPermissionStatusForFrame(ContentSettingsType::GEOLOCATION,
                                               child, GURL(kOrigin2))
                 .content_setting);
@@ -744,7 +653,7 @@
                       blink::mojom::PermissionsPolicyFeature::kGeolocation);
 
   EXPECT_EQ(CONTENT_SETTING_ASK,
-            GetPermissionControllerDelegate()
+            GetPermissionManager()
                 ->GetPermissionStatusForFrame(ContentSettingsType::GEOLOCATION,
                                               child, GURL(kOrigin2))
                 .content_setting);
@@ -764,27 +673,27 @@
 
   // Now the child frame should have location, as well as the parent frame.
   EXPECT_EQ(CONTENT_SETTING_ALLOW,
-            GetPermissionControllerDelegate()
+            GetPermissionManager()
                 ->GetPermissionStatusForFrame(ContentSettingsType::GEOLOCATION,
                                               parent, GURL(kOrigin1))
                 .content_setting);
   EXPECT_EQ(CONTENT_SETTING_ALLOW,
-            GetPermissionControllerDelegate()
+            GetPermissionManager()
                 ->GetPermissionStatusForFrame(ContentSettingsType::GEOLOCATION,
                                               child, GURL(kOrigin2))
                 .content_setting);
 
   // Revoking access from the parent should cause the child not to have access
   // either.
-  GetPermissionControllerDelegate()->ResetPermission(
-      PermissionType::GEOLOCATION, GURL(kOrigin1), GURL(kOrigin1));
+  GetPermissionManager()->ResetPermission(PermissionType::GEOLOCATION,
+                                          GURL(kOrigin1), GURL(kOrigin1));
   EXPECT_EQ(CONTENT_SETTING_ASK,
-            GetPermissionControllerDelegate()
+            GetPermissionManager()
                 ->GetPermissionStatusForFrame(ContentSettingsType::GEOLOCATION,
                                               parent, GURL(kOrigin1))
                 .content_setting);
   EXPECT_EQ(CONTENT_SETTING_ASK,
-            GetPermissionControllerDelegate()
+            GetPermissionManager()
                 ->GetPermissionStatusForFrame(ContentSettingsType::GEOLOCATION,
                                               child, GURL(kOrigin2))
                 .content_setting);
@@ -796,12 +705,12 @@
   child = AddChildRFH(parent, kOrigin2);
 
   EXPECT_EQ(CONTENT_SETTING_ASK,
-            GetPermissionControllerDelegate()
+            GetPermissionManager()
                 ->GetPermissionStatusForFrame(ContentSettingsType::GEOLOCATION,
                                               parent, GURL(kOrigin1))
                 .content_setting);
   EXPECT_EQ(CONTENT_SETTING_BLOCK,
-            GetPermissionControllerDelegate()
+            GetPermissionManager()
                 ->GetPermissionStatusForFrame(ContentSettingsType::GEOLOCATION,
                                               child, GURL(kOrigin2))
                 .content_setting);
@@ -818,7 +727,7 @@
   content::RenderFrameHost* child = AddChildRFH(parent, kOrigin2);
 
   content::PermissionControllerDelegate::SubscriptionId subscription_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::GEOLOCATION, child, GURL(kOrigin2),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
@@ -826,7 +735,7 @@
 
   // Location should be blocked for the child because it's not delegated.
   EXPECT_EQ(CONTENT_SETTING_BLOCK,
-            GetPermissionControllerDelegate()
+            GetPermissionManager()
                 ->GetPermissionStatusForFrame(ContentSettingsType::GEOLOCATION,
                                               child, GURL(kOrigin2))
                 .content_setting);
@@ -837,7 +746,7 @@
 
   // The child's permission should still be block and no callback should be run.
   EXPECT_EQ(CONTENT_SETTING_BLOCK,
-            GetPermissionControllerDelegate()
+            GetPermissionManager()
                 ->GetPermissionStatusForFrame(ContentSettingsType::GEOLOCATION,
                                               child, GURL(kOrigin2))
                 .content_setting);
@@ -849,16 +758,15 @@
                       blink::mojom::PermissionsPolicyFeature::kGeolocation);
 
   EXPECT_EQ(CONTENT_SETTING_ALLOW,
-            GetPermissionControllerDelegate()
+            GetPermissionManager()
                 ->GetPermissionStatusForFrame(ContentSettingsType::GEOLOCATION,
                                               child, GURL(kOrigin2))
                 .content_setting);
 
-  subscription_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
-          PermissionType::GEOLOCATION, child, GURL(kOrigin2),
-          base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
-                              base::Unretained(this)));
+  subscription_id = GetPermissionManager()->SubscribePermissionStatusChange(
+      PermissionType::GEOLOCATION, child, GURL(kOrigin2),
+      base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
+                          base::Unretained(this)));
   EXPECT_FALSE(callback_called());
 
   // Blocking access to the parent should trigger the callback to be run for the
@@ -870,13 +778,12 @@
   EXPECT_EQ(PermissionStatus::DENIED, callback_result());
 
   EXPECT_EQ(CONTENT_SETTING_BLOCK,
-            GetPermissionControllerDelegate()
+            GetPermissionManager()
                 ->GetPermissionStatusForFrame(ContentSettingsType::GEOLOCATION,
                                               child, GURL(kOrigin2))
                 .content_setting);
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription_id);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id);
 }
 
 TEST_F(PermissionManagerTest, SubscribeUnsubscribeAndResubscribe) {
@@ -884,7 +791,7 @@
   NavigateAndCommit(GURL(kOrigin1));
 
   content::PermissionControllerDelegate::SubscriptionId subscription_id =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::GEOLOCATION, main_rfh(), GURL(kOrigin1),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
@@ -896,8 +803,7 @@
   EXPECT_EQ(callback_count(), 1);
   EXPECT_EQ(PermissionStatus::GRANTED, callback_result());
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription_id);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id);
 
   // ensure no callbacks are received when unsubscribed.
   GetHostContentSettingsMap()->SetContentSettingDefaultScope(
@@ -908,7 +814,7 @@
   EXPECT_EQ(callback_count(), 1);
 
   content::PermissionControllerDelegate::SubscriptionId subscription_id_2 =
-      GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+      GetPermissionManager()->SubscribePermissionStatusChange(
           PermissionType::GEOLOCATION, main_rfh(), GURL(kOrigin1),
           base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
                               base::Unretained(this)));
@@ -920,8 +826,7 @@
   EXPECT_EQ(callback_count(), 2);
   EXPECT_EQ(PermissionStatus::DENIED, callback_result());
 
-  GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
-      subscription_id_2);
+  GetPermissionManager()->UnsubscribePermissionStatusChange(subscription_id_2);
 }
 
 }  // namespace permissions
diff --git a/components/permissions/test/permission_test_util.cc b/components/permissions/test/permission_test_util.cc
new file mode 100644
index 0000000..8508c369
--- /dev/null
+++ b/components/permissions/test/permission_test_util.cc
@@ -0,0 +1,88 @@
+// 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 "components/permissions/test/permission_test_util.h"
+
+#include "components/content_settings/core/common/content_settings_types.h"
+#include "components/permissions/permission_manager.h"
+#include "content/public/browser/browser_context.h"
+#include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom.h"
+
+namespace permissions {
+namespace {
+
+class FakePermissionContext : public PermissionContextBase {
+ public:
+  FakePermissionContext(
+      content::BrowserContext* browser_context,
+      ContentSettingsType content_settings_type,
+      blink::mojom::PermissionsPolicyFeature permissions_policy_feature)
+      : PermissionContextBase(browser_context,
+                              content_settings_type,
+                              permissions_policy_feature) {}
+
+  // PermissionContextBase:
+  bool IsRestrictedToSecureOrigins() const override { return true; }
+};
+
+class FakePermissionContextAlwaysAllow : public FakePermissionContext {
+ public:
+  FakePermissionContextAlwaysAllow(
+      content::BrowserContext* browser_context,
+      ContentSettingsType content_settings_type,
+      blink::mojom::PermissionsPolicyFeature permissions_policy_feature)
+      : FakePermissionContext(browser_context,
+                              content_settings_type,
+                              permissions_policy_feature) {}
+
+  // PermissionContextBase:
+  ContentSetting GetPermissionStatusInternal(
+      content::RenderFrameHost* render_frame_host,
+      const GURL& requesting_origin,
+      const GURL& embedding_origin) const override {
+    return CONTENT_SETTING_ALLOW;
+  }
+};
+
+PermissionManager::PermissionContextMap CreatePermissionContexts(
+    content::BrowserContext* browser_context) {
+  PermissionManager::PermissionContextMap permission_contexts;
+  permission_contexts[ContentSettingsType::GEOLOCATION] =
+      std::make_unique<FakePermissionContext>(
+          browser_context, ContentSettingsType::GEOLOCATION,
+          blink::mojom::PermissionsPolicyFeature::kGeolocation);
+  permission_contexts[ContentSettingsType::NOTIFICATIONS] =
+      std::make_unique<FakePermissionContext>(
+          browser_context, ContentSettingsType::NOTIFICATIONS,
+          blink::mojom::PermissionsPolicyFeature::kNotFound);
+  permission_contexts[ContentSettingsType::MIDI_SYSEX] =
+      std::make_unique<FakePermissionContext>(
+          browser_context, ContentSettingsType::MIDI_SYSEX,
+          blink::mojom::PermissionsPolicyFeature::kMidiFeature);
+  permission_contexts[ContentSettingsType::MIDI] =
+      std::make_unique<FakePermissionContextAlwaysAllow>(
+          browser_context, ContentSettingsType::MIDI,
+          blink::mojom::PermissionsPolicyFeature::kMidiFeature);
+  permission_contexts[ContentSettingsType::STORAGE_ACCESS] =
+      std::make_unique<FakePermissionContextAlwaysAllow>(
+          browser_context, ContentSettingsType::STORAGE_ACCESS,
+          blink::mojom::PermissionsPolicyFeature::kStorageAccessAPI);
+#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS)
+  permission_contexts[ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER] =
+      std::make_unique<FakePermissionContext>(
+          browser_context, ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER,
+          blink::mojom::PermissionsPolicyFeature::kEncryptedMedia);
+#endif
+  return permission_contexts;
+}
+
+}  // namespace
+
+std::unique_ptr<content::PermissionControllerDelegate>
+GetPermissionControllerDelegate(content::BrowserContext* context) {
+  return std::make_unique<permissions::PermissionManager>(
+      context, CreatePermissionContexts(context));
+}
+
+}  // namespace permissions
diff --git a/components/permissions/test/permission_test_util.h b/components/permissions/test/permission_test_util.h
new file mode 100644
index 0000000..a0217f5
--- /dev/null
+++ b/components/permissions/test/permission_test_util.h
@@ -0,0 +1,22 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERMISSIONS_TEST_PERMISSION_TEST_UTIL_H_
+#define COMPONENTS_PERMISSIONS_TEST_PERMISSION_TEST_UTIL_H_
+
+#include <memory>
+
+namespace content {
+class PermissionControllerDelegate;
+class BrowserContext;
+}  // namespace content
+
+namespace permissions {
+
+std::unique_ptr<content::PermissionControllerDelegate>
+GetPermissionControllerDelegate(content::BrowserContext* context);
+
+}  // namespace permissions
+
+#endif  // COMPONENTS_PERMISSIONS_TEST_PERMISSION_TEST_UTIL_H_
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 2bebdfb6..5060b85 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -28269,9 +28269,10 @@
       'tags': [],
       'desc': '''This settings enables or disables signin interception.
 
-      When this policy not set or is set to True, the signin interception dialog triggers when a Google account is added on the web, and the user may benefit from moving this account to another (new or existing) profile.
+      When this policy not set or is enabled, the signin interception dialog triggers when a Google account is added on the web, and the user may benefit from moving this account to another (new or existing) profile.
 
-      When this is set to False, the signin interception dialog does not trigger.''',
+      When this is disabled, the signin interception dialog does not trigger.
+      When this is disabled, a dialog will still be shown if managed account profile separation is enforced by <ph name="MANAGED_ACCOUNTS_SIGNIN_RESTRICTION_POLICY_NAME">ManagedAccountsSigninRestriction</ph>.''',
     },
     {
       'name': 'WebXRImmersiveArEnabled',
@@ -29016,8 +29017,6 @@
       'caption': '''Add restrictions on managed accounts''',
       'tags': [],
       'desc': '''
-      This policy requires <ph name="SIGNIN_INTERCEPTION_ENABLED_POLICY_NAME">SigninInterceptionEnabled</ph> to be set to True to take effect.
-
       If this policy is set to <ph name="POLICY_VALUE_PRIMARY_ACCOUNT">'primary_account'</ph> at the machine level, all managed accounts will be forced to be primary.
       If this policy is set to <ph name="POLICY_VALUE_PRIMARY_ACCOUNT">'primary_account'</ph> on an account, that account will always be a primary account, but may have secondary accounts in its profile.
 
diff --git a/components/safe_browsing/core/common/features.cc b/components/safe_browsing/core/common/features.cc
index eaf66e03..095ebcd8 100644
--- a/components/safe_browsing/core/common/features.cc
+++ b/components/safe_browsing/core/common/features.cc
@@ -57,6 +57,9 @@
 const base::Feature kClientSideDetectionReferrerChain{
     "ClientSideDetectionReferrerChain", base::FEATURE_ENABLED_BY_DEFAULT};
 
+const base::Feature kConnectorsScanningAccessToken{
+    "ConnectorsScanningAccessToken", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // TODO(b/197749390): Add tests for this feature being enabled when it's
 // finalized.
 const base::Feature kConnectorsScanningReportOnlyUI{
@@ -109,13 +112,7 @@
                                           base::FEATURE_DISABLED_BY_DEFAULT};
 
 const base::Feature kTailoredSecurityIntegration{
-  "TailoredSecurityIntegration",
-#if BUILDFLAG(IS_ANDROID)
-      base::FEATURE_DISABLED_BY_DEFAULT
-#else
-      base::FEATURE_ENABLED_BY_DEFAULT
-#endif
-};
+    "TailoredSecurityIntegration", base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kOmitNonUserGesturesFromReferrerChain{
     "SafeBrowsingOmitNonUserGesturesFromReferrerChain",
diff --git a/components/safe_browsing/core/common/features.h b/components/safe_browsing/core/common/features.h
index 871748a5..b65da9b 100644
--- a/components/safe_browsing/core/common/features.h
+++ b/components/safe_browsing/core/common/features.h
@@ -58,6 +58,10 @@
 // Enables client side detection referrer chain.
 extern const base::Feature kClientSideDetectionReferrerChain;
 
+// Controls whether an access token is attached to scanning requests triggered
+// by enterprise Connectors.
+extern const base::Feature kConnectorsScanningAccessToken;
+
 // Controls the non-blocking scanning UI for Connectors scanning requests. If
 // this is enabled, the downloaded file(s) will be renamed immediately and the
 // scanning will take place without UI when the policy is set to "non-blocking"
diff --git a/components/search_engines/keyword_table.cc b/components/search_engines/keyword_table.cc
index e607ebf..7f402ad 100644
--- a/components/search_engines/keyword_table.cc
+++ b/components/search_engines/keyword_table.cc
@@ -38,6 +38,7 @@
 
 // Keys used in the meta table.
 const char kBuiltinKeywordVersion[] = "Builtin Keyword Version";
+const char kStarterPackKeywordVersion[] = "Starter Pack Keyword Version";
 
 const std::string ColumnsForVersion(int version, bool concatenated) {
   std::vector<base::StringPiece> columns;
@@ -317,6 +318,16 @@
   return meta_table_->GetValue(kBuiltinKeywordVersion, &version) ? version : 0;
 }
 
+bool KeywordTable::SetStarterPackKeywordVersion(int version) {
+  return meta_table_->SetValue(kStarterPackKeywordVersion, version);
+}
+
+int KeywordTable::GetStarterPackKeywordVersion() {
+  int version = 0;
+  return meta_table_->GetValue(kStarterPackKeywordVersion, &version) ? version
+                                                                     : 0;
+}
+
 // static
 std::string KeywordTable::GetKeywordColumns() {
   return ColumnsForVersion(WebDatabase::kCurrentVersionNumber, false);
diff --git a/components/search_engines/keyword_table.h b/components/search_engines/keyword_table.h
index c83d8a5..593355e 100644
--- a/components/search_engines/keyword_table.h
+++ b/components/search_engines/keyword_table.h
@@ -75,6 +75,7 @@
 //
 // Default Search Provider ID        The id of the default search provider.
 // Builtin Keyword Version           The version of builtin keywords data.
+// Starter Pack Keyword Version      The version of starter pack data.
 //
 class KeywordTable : public WebDatabaseTable {
  public:
@@ -126,6 +127,10 @@
   bool SetBuiltinKeywordVersion(int version);
   int GetBuiltinKeywordVersion();
 
+  // Version of built-in starter pack keywords (@bookmarks, @settings, etc.).
+  bool SetStarterPackKeywordVersion(int version);
+  int GetStarterPackKeywordVersion();
+
   // Returns a comma-separated list of the keyword columns for the current
   // version of the table.
   static std::string GetKeywordColumns();
diff --git a/components/search_engines/keyword_web_data_service.cc b/components/search_engines/keyword_web_data_service.cc
index 19bed6b..6ccf3e4d 100644
--- a/components/search_engines/keyword_web_data_service.cc
+++ b/components/search_engines/keyword_web_data_service.cc
@@ -48,6 +48,14 @@
              : WebDatabase::COMMIT_NOT_NEEDED;
 }
 
+WebDatabase::State SetStarterPackKeywordVersionImpl(int version,
+                                                    WebDatabase* db) {
+  return KeywordTable::FromWebDatabase(db)->SetStarterPackKeywordVersion(
+             version)
+             ? WebDatabase::COMMIT_NEEDED
+             : WebDatabase::COMMIT_NOT_NEEDED;
+}
+
 }  // namespace
 
 WDKeywordsResult::WDKeywordsResult() = default;
@@ -135,6 +143,11 @@
                         base::BindOnce(&SetBuiltinKeywordVersionImpl, version));
 }
 
+void KeywordWebDataService::SetStarterPackKeywordVersion(int version) {
+  wdbs_->ScheduleDBTask(
+      FROM_HERE, base::BindOnce(&SetStarterPackKeywordVersionImpl, version));
+}
+
 void KeywordWebDataService::ShutdownOnUISequence() {
   CommitQueuedOperations();
   WebDataServiceBase::ShutdownOnUISequence();
diff --git a/components/search_engines/keyword_web_data_service.h b/components/search_engines/keyword_web_data_service.h
index 41352b2..deb5d00 100644
--- a/components/search_engines/keyword_web_data_service.h
+++ b/components/search_engines/keyword_web_data_service.h
@@ -92,6 +92,9 @@
   // Sets the version of the builtin keywords.
   void SetBuiltinKeywordVersion(int version);
 
+  // Sets the version of the starter pack keywords.
+  void SetStarterPackKeywordVersion(int version);
+
   // WebDataServiceBase:
   void ShutdownOnUISequence() override;
 
diff --git a/components/value_store/value_store_change.cc b/components/value_store/value_store_change.cc
index b0a71fc..08af72c7 100644
--- a/components/value_store/value_store_change.cc
+++ b/components/value_store/value_store_change.cc
@@ -16,13 +16,13 @@
   base::Value changes_value(base::Value::Type::DICTIONARY);
   for (auto& change : changes) {
     base::Value change_value(base::Value::Type::DICTIONARY);
-    if (change.old_value()) {
-      change_value.SetKey("oldValue", std::move(*change.old_value_));
+    if (change.old_value) {
+      change_value.SetKey("oldValue", std::move(*change.old_value));
     }
-    if (change.new_value()) {
-      change_value.SetKey("newValue", std::move(*change.new_value_));
+    if (change.new_value) {
+      change_value.SetKey("newValue", std::move(*change.new_value));
     }
-    changes_value.SetKey(change.key(), std::move(change_value));
+    changes_value.SetKey(change.key, std::move(change_value));
   }
   return changes_value;
 }
@@ -30,9 +30,9 @@
 ValueStoreChange::ValueStoreChange(const std::string& key,
                                    absl::optional<base::Value> old_value,
                                    absl::optional<base::Value> new_value)
-    : key_(key),
-      old_value_(std::move(old_value)),
-      new_value_(std::move(new_value)) {}
+    : key(key),
+      old_value(std::move(old_value)),
+      new_value(std::move(new_value)) {}
 
 ValueStoreChange::~ValueStoreChange() = default;
 
@@ -40,12 +40,4 @@
 ValueStoreChange& ValueStoreChange::operator=(ValueStoreChange&& other) =
     default;
 
-const base::Value* ValueStoreChange::old_value() const {
-  return base::OptionalOrNullptr(old_value_);
-}
-
-const base::Value* ValueStoreChange::new_value() const {
-  return base::OptionalOrNullptr(new_value_);
-}
-
 }  // namespace value_store
diff --git a/components/value_store/value_store_change.h b/components/value_store/value_store_change.h
index 9c61fb1..d4b21ba3 100644
--- a/components/value_store/value_store_change.h
+++ b/components/value_store/value_store_change.h
@@ -14,12 +14,11 @@
 
 namespace value_store {
 
-class ValueStoreChange;
+struct ValueStoreChange;
 typedef std::vector<ValueStoreChange> ValueStoreChangeList;
 
 // A change to a setting.
-class ValueStoreChange {
- public:
+struct ValueStoreChange {
   // Converts an ValueStoreChangeList into base::Value of the form:
   // { "foo": { "key": "foo", "oldValue": "bar", "newValue": "baz" } }
   static base::Value ToValue(ValueStoreChangeList changes);
@@ -35,21 +34,9 @@
 
   ~ValueStoreChange();
 
-  // Gets the key of the setting which changed.
-  const std::string& key() const { return key_; }
-
-  // Gets the value of the setting before the change, or NULL if there was no
-  // old value.
-  const base::Value* old_value() const;
-
-  // Gets the value of the setting after the change, or NULL if there is no new
-  // value.
-  const base::Value* new_value() const;
-
- private:
-  std::string key_;
-  absl::optional<base::Value> old_value_;
-  absl::optional<base::Value> new_value_;
+  std::string key;
+  absl::optional<base::Value> old_value;
+  absl::optional<base::Value> new_value;
 };
 
 }  // namespace value_store
diff --git a/components/value_store/value_store_change_unittest.cc b/components/value_store/value_store_change_unittest.cc
index da31df6..49e9a3a 100644
--- a/components/value_store/value_store_change_unittest.cc
+++ b/components/value_store/value_store_change_unittest.cc
@@ -3,88 +3,27 @@
 // found in the LICENSE file.
 
 #include "components/value_store/value_store_change.h"
-#include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
 #include "base/values.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using base::DictionaryValue;
 using base::Value;
 
 namespace value_store {
 
-TEST(ValueStoreChangeTest, NullOldValue) {
-  ValueStoreChange change("key", absl::nullopt, base::Value("value"));
-
-  EXPECT_EQ("key", change.key());
-  EXPECT_EQ(nullptr, change.old_value());
-  {
-    base::Value expected("value");
-    EXPECT_EQ(*change.new_value(), expected);
-  }
-}
-
-TEST(ValueStoreChangeTest, NullNewValue) {
-  ValueStoreChange change("key", base::Value("value"), absl::nullopt);
-
-  EXPECT_EQ("key", change.key());
-  {
-    base::Value expected("value");
-    EXPECT_EQ(*change.old_value(), expected);
-  }
-  EXPECT_EQ(nullptr, change.new_value());
-}
-
-TEST(ValueStoreChangeTest, NonNullValues) {
-  ValueStoreChange change("key", base::Value("old_value"),
-                          base::Value("new_value"));
-
-  EXPECT_EQ("key", change.key());
-  {
-    base::Value expected("old_value");
-    EXPECT_EQ(*change.old_value(), expected);
-  }
-  {
-    base::Value expected("new_value");
-    EXPECT_EQ(*change.new_value(), expected);
-  }
-}
-
 TEST(ValueStoreChangeTest, ToValue) {
-  // Create a mildly complicated structure that has dots in it.
-  base::Value inner_dict(base::Value::Type::DICTIONARY);
-  inner_dict.SetKey("you", base::Value("nodots"));
+  ValueStoreChangeList changes;
+  changes.push_back(ValueStoreChange("foo", absl::nullopt, base::Value("bar")));
+  changes.push_back(ValueStoreChange("baz", base::Value("qux"), absl::nullopt));
 
-  base::Value value(base::Value::Type::DICTIONARY);
-  value.SetKey("key", base::Value("value"));
-  value.SetKey("key.with.dots", base::Value("value.with.dots"));
-  value.SetKey("tricked", std::move(inner_dict));
-  value.SetKey("tricked.you", base::Value("with.dots"));
+  base::Value expected(base::Value::Type::DICTIONARY);
+  base::Value expected_foo(base::Value::Type::DICTIONARY);
+  base::Value expected_baz(base::Value::Type::DICTIONARY);
+  expected_foo.SetStringKey("newValue", "bar");
+  expected_baz.SetStringKey("oldValue", "qux");
+  expected.SetKey("foo", std::move(expected_foo));
+  expected.SetKey("baz", std::move(expected_baz));
 
-  ValueStoreChangeList change_list;
-  change_list.push_back(ValueStoreChange("key", value.Clone(), value.Clone()));
-  change_list.push_back(
-      ValueStoreChange("key.with.dots", value.Clone(), value.Clone()));
-
-  base::Value changes_value = ValueStoreChange::ToValue(std::move(change_list));
-
-  base::Value v1(value.Clone());
-  base::Value v2(value.Clone());
-  base::Value v3(value.Clone());
-  base::Value v4(value.Clone());
-
-  base::Value inner_dict2(base::Value::Type::DICTIONARY);
-  base::Value inner_dict3(base::Value::Type::DICTIONARY);
-
-  inner_dict2.SetKey("oldValue", std::move(v1));
-  inner_dict2.SetKey("newValue", std::move(v2));
-  inner_dict3.SetKey("oldValue", std::move(v3));
-  inner_dict3.SetKey("newValue", std::move(v4));
-
-  base::Value expected_from_json(base::Value::Type::DICTIONARY);
-  expected_from_json.SetKey("key", std::move(inner_dict2));
-  expected_from_json.SetKey("key.with.dots", std::move(inner_dict3));
-  EXPECT_EQ(changes_value, expected_from_json);
+  EXPECT_EQ(expected, ValueStoreChange::ToValue(std::move(changes)));
 }
 
 }  // namespace value_store
diff --git a/components/value_store/value_store_test_suite.cc b/components/value_store/value_store_test_suite.cc
index ea23bed..48f2111 100644
--- a/components/value_store/value_store_test_suite.cc
+++ b/components/value_store/value_store_test_suite.cc
@@ -17,150 +17,51 @@
 // To save typing ValueStore::DEFAULTS everywhere.
 const ValueStore::WriteOptions DEFAULTS = ValueStore::DEFAULTS;
 
-// Gets the pretty-printed JSON for a value.
-std::string GetJSON(const base::Value& value) {
-  std::string json;
-  base::JSONWriter::WriteWithOptions(
-      value, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json);
-  return json;
-}
-
 }  // namespace
 
-// Compares two possibly NULL values for equality, filling |error| with an
-// appropriate error message if they're different.
-bool ValuesEqual(const base::Value* expected,
-                 const base::Value* actual,
-                 std::string* error) {
-  if (expected == actual) {
-    return true;
-  }
-  if (expected && !actual) {
-    *error = "Expected: " + GetJSON(*expected) + ", actual: NULL";
-    return false;
-  }
-  if (actual && !expected) {
-    *error = "Expected: NULL, actual: " + GetJSON(*actual);
-    return false;
-  }
-  if (!expected->Equals(actual)) {
-    *error =
-        "Expected: " + GetJSON(*expected) + ", actual: " + GetJSON(*actual);
-    return false;
-  }
-  return true;
-}
-
 // Returns whether the read result of a storage operation has the expected
 // settings.
-testing::AssertionResult SettingsEq(const char* _1,
-                                    const char* _2,
-                                    const base::DictionaryValue& expected,
-                                    ValueStore::ReadResult actual_result) {
-  if (!actual_result.status().ok()) {
-    return testing::AssertionFailure()
-           << "Result has error: " << actual_result.status().message;
-  }
-
-  std::string error;
-  if (!ValuesEqual(&expected, &actual_result.settings(), &error)) {
-    return testing::AssertionFailure() << error;
-  }
-
-  return testing::AssertionSuccess();
+void ExpectSettingsEq(const base::DictionaryValue& expected,
+                      ValueStore::ReadResult actual_result) {
+  ASSERT_TRUE(actual_result.status().ok()) << actual_result.status().message;
+  EXPECT_EQ(expected, actual_result.settings());
 }
 
 // Returns whether the write result of a storage operation has the expected
 // changes.
-testing::AssertionResult ChangesEq(const char* _1,
-                                   const char* _2,
-                                   const ValueStoreChangeList& expected,
-                                   ValueStore::WriteResult actual_result) {
-  if (!actual_result.status().ok()) {
-    return testing::AssertionFailure()
-           << "Result has error: " << actual_result.status().message;
-  }
+void ExpectChangesEq(const ValueStoreChangeList& expected,
+                     ValueStore::WriteResult actual_result) {
+  ASSERT_TRUE(actual_result.status().ok()) << actual_result.status().message;
 
   const ValueStoreChangeList& actual = actual_result.changes();
-  if (expected.size() != actual.size()) {
-    return testing::AssertionFailure()
-           << "Actual has wrong size, expecting " << expected.size()
-           << " but was " << actual.size();
-  }
+  ASSERT_EQ(expected.size(), actual.size());
 
   std::map<std::string, const ValueStoreChange*> expected_as_map;
   for (const ValueStoreChange& change : expected)
-    expected_as_map[change.key()] = &change;
+    expected_as_map[change.key] = &change;
 
   std::set<std::string> keys_seen;
 
   for (const auto& it : actual) {
-    if (keys_seen.count(it.key())) {
-      return testing::AssertionFailure()
-             << "Multiple changes seen for key: " << it.key();
-    }
-    keys_seen.insert(it.key());
+    EXPECT_EQ(keys_seen.count(it.key), 0U);
+    keys_seen.insert(it.key);
 
-    if (!expected_as_map.count(it.key())) {
-      return testing::AssertionFailure()
-             << "Actual has unexpected change for key: " << it.key();
-    }
+    EXPECT_EQ(expected_as_map.count(it.key), 1U);
 
-    const ValueStoreChange* expected_change = expected_as_map[it.key()];
-    std::string error;
-    if (!ValuesEqual(expected_change->new_value(), it.new_value(), &error)) {
-      return testing::AssertionFailure()
-             << "New value for " << it.key() << " was unexpected: " << error;
-    }
-    if (!ValuesEqual(expected_change->old_value(), it.old_value(), &error)) {
-      return testing::AssertionFailure()
-             << "Old value for " << it.key() << " was unexpected: " << error;
-    }
+    const auto* expected_change = expected_as_map[it.key];
+    EXPECT_EQ(expected_change->new_value, it.new_value);
+    EXPECT_EQ(expected_change->old_value, it.old_value);
   }
-
-  return testing::AssertionSuccess();
 }
 
-ValueStoreTestSuite::ValueStoreTestSuite()
-    : key1_("foo"),
-      key2_("bar"),
-      key3_("baz"),
-      empty_dict_(new base::DictionaryValue()),
-      dict1_(new base::DictionaryValue()),
-      dict3_(new base::DictionaryValue()),
-      dict12_(new base::DictionaryValue()),
-      dict123_(new base::DictionaryValue()) {
-  val1_ = std::make_unique<base::Value>(key1_ + "Value");
-  val2_ = std::make_unique<base::Value>(key2_ + "Value");
-  val3_ = std::make_unique<base::Value>(key3_ + "Value");
-
-  list1_.push_back(key1_);
-  list2_.push_back(key2_);
-  list3_.push_back(key3_);
-  list12_.push_back(key1_);
-  list12_.push_back(key2_);
-  list13_.push_back(key1_);
-  list13_.push_back(key3_);
-  list123_.push_back(key1_);
-  list123_.push_back(key2_);
-  list123_.push_back(key3_);
-
-  set1_.insert(list1_.begin(), list1_.end());
-  set2_.insert(list2_.begin(), list2_.end());
-  set3_.insert(list3_.begin(), list3_.end());
-  set12_.insert(list12_.begin(), list12_.end());
-  set13_.insert(list13_.begin(), list13_.end());
-  set123_.insert(list123_.begin(), list123_.end());
-
-  dict1_->SetKey(key1_, val1_->Clone());
-  dict3_->SetKey(key3_, val3_->Clone());
-  dict12_->SetKey(key1_, val1_->Clone());
-  dict12_->SetKey(key2_, val2_->Clone());
-  dict123_->SetKey(key1_, val1_->Clone());
-  dict123_->SetKey(key2_, val2_->Clone());
-  dict123_->SetKey(key3_, val3_->Clone());
+base::DictionaryValue MakeTestMap(std::map<std::string, std::string> pairs) {
+  base::DictionaryValue map;
+  for (const auto& it : pairs)
+    map.GetDict().Set(it.first, std::move(it.second));
+  return map;
 }
 
+ValueStoreTestSuite::ValueStoreTestSuite() = default;
 ValueStoreTestSuite::~ValueStoreTestSuite() = default;
 
 void ValueStoreTestSuite::SetUp() {
@@ -173,303 +74,139 @@
   storage_.reset();
 }
 
-TEST_P(ValueStoreTestSuite, GetWhenEmpty) {
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list123_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get());
+TEST_P(ValueStoreTestSuite, NonexistentKeysReturnOk) {
+  auto result = storage_->Get("key");
+  ASSERT_TRUE(result.status().ok());
+  EXPECT_EQ(result.settings(), base::Value(base::Value::Type::DICTIONARY));
 }
 
-TEST_P(ValueStoreTestSuite, GetWithSingleValue) {
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(ValueStoreChange(key1_, absl::nullopt, val1_->Clone()));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes,
-                        storage_->Set(DEFAULTS, key1_, *val1_));
-  }
-
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(key1_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key2_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key3_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(list123_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get());
+TEST_P(ValueStoreTestSuite, SetProducesMatchingChanges) {
+  ValueStoreChangeList expected_changes;
+  expected_changes.push_back(
+      ValueStoreChange{"foo", absl::nullopt, base::Value{"baz"}});
+  expected_changes.push_back(
+      ValueStoreChange{"bar", absl::nullopt, base::Value{"qux"}});
+  base::DictionaryValue settings =
+      MakeTestMap({{"foo", "baz"}, {"bar", "qux"}});
+  ExpectChangesEq(expected_changes, storage_->Set(DEFAULTS, settings));
 }
 
-TEST_P(ValueStoreTestSuite, GetWithMultipleValues) {
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(ValueStoreChange(key1_, absl::nullopt, val1_->Clone()));
-    changes.push_back(ValueStoreChange(key2_, absl::nullopt, val2_->Clone()));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, *dict12_));
-  }
-
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(key1_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key3_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get(list123_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get());
+TEST_P(ValueStoreTestSuite, RemoveMissingProducesNoChange) {
+  ExpectChangesEq(ValueStoreChangeList{}, storage_->Remove("foo"));
 }
 
-TEST_P(ValueStoreTestSuite, RemoveWhenEmpty) {
-  EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(),
-                      storage_->Remove(key1_));
+TEST_P(ValueStoreTestSuite, RemoveSingleKeyProducesMatchingChanges) {
+  base::DictionaryValue settings =
+      MakeTestMap({{"foo", "baz"}, {"bar", "qux"}});
+  storage_->Set(DEFAULTS, settings);
 
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list1_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get());
+  ValueStoreChangeList changes;
+  changes.push_back(ValueStoreChange{"foo", base::Value{"baz"}, absl::nullopt});
+  ExpectChangesEq(changes, storage_->Remove("foo"));
 }
 
-TEST_P(ValueStoreTestSuite, RemoveWithSingleValue) {
-  storage_->Set(DEFAULTS, *dict1_);
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(ValueStoreChange(key1_, val1_->Clone(), absl::nullopt));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(key1_));
-  }
+TEST_P(ValueStoreTestSuite, RemoveKeyListProducesMatchingChanges) {
+  base::DictionaryValue settings =
+      MakeTestMap({{"foo", "baz"}, {"bar", "qux"}, {"abc", "def"}});
+  storage_->Set(DEFAULTS, settings);
 
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key2_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list1_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list12_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get());
+  ValueStoreChangeList changes;
+  changes.push_back(ValueStoreChange{"foo", base::Value{"baz"}, absl::nullopt});
+  changes.push_back(ValueStoreChange{"bar", base::Value{"qux"}, absl::nullopt});
+  ExpectChangesEq(changes,
+                  storage_->Remove(std::vector<std::string>{"foo", "bar"}));
 }
 
-TEST_P(ValueStoreTestSuite, RemoveWithMultipleValues) {
-  storage_->Set(DEFAULTS, *dict123_);
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(ValueStoreChange(key3_, val3_->Clone(), absl::nullopt));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(key3_));
-  }
-
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(key1_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key3_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(list1_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get(list12_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(list13_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get(list123_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get());
-
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(ValueStoreChange(key1_, val1_->Clone(), absl::nullopt));
-    changes.push_back(ValueStoreChange(key2_, val2_->Clone(), absl::nullopt));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(list12_));
-  }
-
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key3_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list1_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list12_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list13_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list123_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get());
+TEST_P(ValueStoreTestSuite, SetValuesCanBeRetrievedOneAtATime) {
+  base::DictionaryValue settings =
+      MakeTestMap({{"foo", "baz"}, {"bar", "qux"}});
+  storage_->Set(DEFAULTS, settings);
+  ExpectSettingsEq(MakeTestMap({{"foo", "baz"}}), storage_->Get("foo"));
+  ExpectSettingsEq(MakeTestMap({{"bar", "qux"}}), storage_->Get("bar"));
 }
 
-TEST_P(ValueStoreTestSuite, SetWhenOverwriting) {
-  storage_->Set(DEFAULTS, key1_, *val2_);
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(ValueStoreChange(key1_, val2_->Clone(), val1_->Clone()));
-    changes.push_back(ValueStoreChange(key2_, absl::nullopt, val2_->Clone()));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, *dict12_));
-  }
-
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(key1_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key3_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(list1_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get(list12_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(list13_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get(list123_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get());
+TEST_P(ValueStoreTestSuite, SetValuesCanBeRetrievedWithKeyList) {
+  base::DictionaryValue settings =
+      MakeTestMap({{"foo", "baz"}, {"bar", "qux"}});
+  storage_->Set(DEFAULTS, settings);
+  ExpectSettingsEq(settings,
+                   storage_->Get(std::vector<std::string>{"foo", "bar"}));
 }
 
-TEST_P(ValueStoreTestSuite, ClearWhenEmpty) {
-  EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(), storage_->Clear());
-
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list123_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get());
+TEST_P(ValueStoreTestSuite, MissingKeysSkippedInListRetrieve) {
+  base::DictionaryValue settings =
+      MakeTestMap({{"foo", "baz"}, {"bar", "qux"}});
+  storage_->Set(DEFAULTS, settings);
+  ExpectSettingsEq(
+      settings, storage_->Get(std::vector<std::string>{"foo", "bar", "baz"}));
 }
 
-TEST_P(ValueStoreTestSuite, ClearWhenNotEmpty) {
-  storage_->Set(DEFAULTS, *dict12_);
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(ValueStoreChange(key1_, val1_->Clone(), absl::nullopt));
-    changes.push_back(ValueStoreChange(key2_, val2_->Clone(), absl::nullopt));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Clear());
-  }
-
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list123_));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get());
+TEST_P(ValueStoreTestSuite, GetAllDoesGetAll) {
+  base::DictionaryValue settings =
+      MakeTestMap({{"foo", "baz"}, {"bar", "qux"}});
+  storage_->Set(DEFAULTS, settings);
+  ExpectSettingsEq(settings, storage_->Get());
 }
 
-// Dots should be allowed in key names; they shouldn't be interpreted as
-// indexing into a dictionary.
-TEST_P(ValueStoreTestSuite, DotsInKeyNames) {
-  std::string dot_key("foo.bar");
-  base::Value dot_value("baz.qux");
-  std::vector<std::string> dot_list;
-  dot_list.push_back(dot_key);
-  base::DictionaryValue dot_dict;
-  dot_dict.SetKey(dot_key, dot_value.Clone());
-
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(dot_key));
-
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(
-        ValueStoreChange(dot_key, absl::nullopt, dot_value.Clone()));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes,
-                        storage_->Set(DEFAULTS, dot_key, dot_value));
-  }
-  EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(),
-                      storage_->Set(DEFAULTS, dot_key, dot_value));
-
-  EXPECT_PRED_FORMAT2(SettingsEq, dot_dict, storage_->Get(dot_key));
-
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(
-        ValueStoreChange(dot_key, dot_value.Clone(), absl::nullopt));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(dot_key));
-  }
-  EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(),
-                      storage_->Remove(dot_key));
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(
-        ValueStoreChange(dot_key, absl::nullopt, dot_value.Clone()));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, dot_dict));
-  }
-
-  EXPECT_PRED_FORMAT2(SettingsEq, dot_dict, storage_->Get(dot_list));
-  EXPECT_PRED_FORMAT2(SettingsEq, dot_dict, storage_->Get());
-
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(
-        ValueStoreChange(dot_key, dot_value.Clone(), absl::nullopt));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(dot_list));
-  }
-
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(dot_key));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get());
+TEST_P(ValueStoreTestSuite, RemovedSingleValueIsGone) {
+  base::DictionaryValue settings =
+      MakeTestMap({{"foo", "baz"}, {"bar", "qux"}, {"abc", "def"}});
+  storage_->Set(DEFAULTS, settings);
+  ExpectSettingsEq(MakeTestMap({{"foo", "baz"}}), storage_->Get("foo"));
+  storage_->Remove("foo");
+  ExpectSettingsEq({}, storage_->Get("foo"));
+  ExpectSettingsEq(MakeTestMap({{"bar", "qux"}}), storage_->Get("bar"));
 }
 
-TEST_P(ValueStoreTestSuite, DotsInKeyNamesWithDicts) {
-  base::DictionaryValue outer_dict;
-  base::DictionaryValue inner_dict;
-  inner_dict.SetString("bar", "baz");
-  outer_dict.Set("foo", inner_dict.CreateDeepCopy());
-
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(
-        ValueStoreChange("foo", absl::nullopt, inner_dict.Clone()));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes,
-                        storage_->Set(DEFAULTS, outer_dict));
-  }
-
-  EXPECT_PRED_FORMAT2(SettingsEq, outer_dict, storage_->Get("foo"));
-  EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get("foo.bar"));
+TEST_P(ValueStoreTestSuite, RemovedMultipleValuesAreGone) {
+  base::DictionaryValue settings =
+      MakeTestMap({{"foo", "baz"}, {"bar", "qux"}, {"abc", "def"}});
+  storage_->Set(DEFAULTS, settings);
+  ExpectSettingsEq(MakeTestMap({{"foo", "baz"}, {"bar", "qux"}}),
+                   storage_->Get(std::vector<std::string>{"foo", "bar"}));
+  storage_->Remove(std::vector<std::string>{"foo", "bar"});
+  ExpectSettingsEq({}, storage_->Get("foo"));
+  ExpectSettingsEq({}, storage_->Get("bar"));
+  ExpectSettingsEq(MakeTestMap({{"abc", "def"}}), storage_->Get("abc"));
 }
 
-TEST_P(ValueStoreTestSuite, ComplexChangedKeysScenarios) {
-  // Test:
-  //   - Setting over missing/changed/same keys, combinations.
-  //   - Removing over missing and present keys, combinations.
-  //   - Clearing.
-  std::vector<std::string> complex_list;
-  base::DictionaryValue complex_changed_dict;
+TEST_P(ValueStoreTestSuite, SetOverwritesOnlyExistingValue) {
+  storage_->Set(DEFAULTS, MakeTestMap({{"foo", "bar"}, {"abc", "def"}}));
+  storage_->Set(DEFAULTS, MakeTestMap({{"foo", "baz"}}));
+  ExpectSettingsEq(MakeTestMap({{"foo", "baz"}, {"abc", "def"}}),
+                   storage_->Get(std::vector<std::string>{"foo", "abc"}));
+}
 
-  storage_->Set(DEFAULTS, key1_, *val1_);
-  EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(),
-                      storage_->Set(DEFAULTS, key1_, *val1_));
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(ValueStoreChange(key1_, val1_->Clone(), val2_->Clone()));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes,
-                        storage_->Set(DEFAULTS, key1_, *val2_));
-  }
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(ValueStoreChange(key1_, val2_->Clone(), absl::nullopt));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(key1_));
-    EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(),
-                        storage_->Remove(key1_));
-  }
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(ValueStoreChange(key1_, absl::nullopt, val1_->Clone()));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes,
-                        storage_->Set(DEFAULTS, key1_, *val1_));
-  }
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(ValueStoreChange(key1_, val1_->Clone(), absl::nullopt));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Clear());
-    EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(), storage_->Clear());
-  }
+TEST_P(ValueStoreTestSuite, ClearGeneratesNoChangesWhenEmpty) {
+  ExpectChangesEq({}, storage_->Clear());
+}
 
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(ValueStoreChange(key1_, absl::nullopt, val1_->Clone()));
-    changes.push_back(ValueStoreChange(key2_, absl::nullopt, val2_->Clone()));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, *dict12_));
-    EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(),
-                        storage_->Set(DEFAULTS, *dict12_));
-  }
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(ValueStoreChange(key3_, absl::nullopt, val3_->Clone()));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, *dict123_));
-  }
-  {
-    base::DictionaryValue to_set;
-    to_set.SetKey(key1_, val2_->Clone());
-    to_set.SetKey(key2_, val2_->Clone());
-    to_set.SetKey("asdf", val1_->Clone());
-    to_set.SetKey("qwerty", val3_->Clone());
+TEST_P(ValueStoreTestSuite, ClearGeneratesChanges) {
+  storage_->Set(DEFAULTS, MakeTestMap({{"foo", "baz"}, {"bar", "qux"}}));
 
-    ValueStoreChangeList changes;
-    changes.push_back(ValueStoreChange(key1_, val1_->Clone(), val2_->Clone()));
-    changes.push_back(ValueStoreChange("asdf", absl::nullopt, val1_->Clone()));
-    changes.push_back(
-        ValueStoreChange("qwerty", absl::nullopt, val3_->Clone()));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, to_set));
-  }
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(ValueStoreChange(key1_, val2_->Clone(), absl::nullopt));
-    changes.push_back(ValueStoreChange(key2_, val2_->Clone(), absl::nullopt));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(list12_));
-  }
-  {
-    std::vector<std::string> to_remove;
-    to_remove.push_back(key1_);
-    to_remove.push_back("asdf");
+  ValueStoreChangeList changes;
+  changes.push_back(ValueStoreChange("foo", base::Value("baz"), absl::nullopt));
+  changes.push_back(ValueStoreChange("bar", base::Value("qux"), absl::nullopt));
+  ExpectChangesEq(changes, storage_->Clear());
+}
 
-    ValueStoreChangeList changes;
-    changes.push_back(ValueStoreChange("asdf", val1_->Clone(), absl::nullopt));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(to_remove));
-  }
-  {
-    ValueStoreChangeList changes;
-    changes.push_back(ValueStoreChange(key3_, val3_->Clone(), absl::nullopt));
-    changes.push_back(
-        ValueStoreChange("qwerty", val3_->Clone(), absl::nullopt));
-    EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Clear());
-    EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(), storage_->Clear());
-  }
+TEST_P(ValueStoreTestSuite, ClearedValuesAreGone) {
+  storage_->Set(DEFAULTS, MakeTestMap({{"foo", "baz"}, {"bar", "qux"}}));
+  storage_->Clear();
+  ExpectSettingsEq({}, storage_->Get("foo"));
+  ExpectSettingsEq({}, storage_->Get("bar"));
+}
+
+TEST_P(ValueStoreTestSuite, DotsAllowedInKeyNames) {
+  base::DictionaryValue dict;
+  auto inner_dict = std::make_unique<base::DictionaryValue>();
+  inner_dict->SetString("bar", "baz");
+  dict.Set("foo", std::move(inner_dict));
+  dict.SetStringKey("foo.bar", "qux");
+
+  storage_->Set(DEFAULTS, dict);
+
+  ExpectSettingsEq(MakeTestMap({{"foo.bar", "qux"}}), storage_->Get("foo.bar"));
 }
 
 // This test suite is instantiated by implementers of ValueStore.
diff --git a/components/value_store/value_store_test_suite.h b/components/value_store/value_store_test_suite.h
index 450200d..bc0b0ff 100644
--- a/components/value_store/value_store_test_suite.h
+++ b/components/value_store/value_store_test_suite.h
@@ -32,36 +32,6 @@
  protected:
   std::unique_ptr<ValueStore> storage_;
 
-  std::string key1_;
-  std::string key2_;
-  std::string key3_;
-
-  std::unique_ptr<base::Value> val1_;
-  std::unique_ptr<base::Value> val2_;
-  std::unique_ptr<base::Value> val3_;
-
-  std::vector<std::string> empty_list_;
-  std::vector<std::string> list1_;
-  std::vector<std::string> list2_;
-  std::vector<std::string> list3_;
-  std::vector<std::string> list12_;
-  std::vector<std::string> list13_;
-  std::vector<std::string> list123_;
-
-  std::set<std::string> empty_set_;
-  std::set<std::string> set1_;
-  std::set<std::string> set2_;
-  std::set<std::string> set3_;
-  std::set<std::string> set12_;
-  std::set<std::string> set13_;
-  std::set<std::string> set123_;
-
-  std::unique_ptr<base::DictionaryValue> empty_dict_;
-  std::unique_ptr<base::DictionaryValue> dict1_;
-  std::unique_ptr<base::DictionaryValue> dict3_;
-  std::unique_ptr<base::DictionaryValue> dict12_;
-  std::unique_ptr<base::DictionaryValue> dict123_;
-
  private:
   base::ScopedTempDir temp_dir_;
 
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 70885bf..5d89391 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -619,6 +619,8 @@
     "browsing_data/storage_partition_code_cache_data_remover.h",
     "browsing_instance.cc",
     "browsing_instance.h",
+    "browsing_topics/browsing_topics_document_host.cc",
+    "browsing_topics/browsing_topics_document_host.h",
     "browsing_topics/browsing_topics_site_data_manager_impl.cc",
     "browsing_topics/browsing_topics_site_data_manager_impl.h",
     "browsing_topics/browsing_topics_site_data_storage.cc",
@@ -935,8 +937,8 @@
     "first_party_sets/addition_overlaps_union_find.h",
     "first_party_sets/first_party_sets_handler_impl.cc",
     "first_party_sets/first_party_sets_handler_impl.h",
-    "font_access/font_access_manager_impl.cc",
-    "font_access/font_access_manager_impl.h",
+    "font_access/font_access_manager.cc",
+    "font_access/font_access_manager.h",
     "font_access/font_enumeration_cache.cc",
     "font_access/font_enumeration_cache.h",
     "font_access/font_enumeration_data_source.cc",
@@ -1720,6 +1722,8 @@
     "renderer_host/stored_page.h",
     "renderer_host/text_input_manager.cc",
     "renderer_host/text_input_manager.h",
+    "renderer_host/transient_allow_popup.cc",
+    "renderer_host/transient_allow_popup.h",
     "renderer_host/ui_events_helper.cc",
     "renderer_host/ui_events_helper.h",
     "renderer_host/visible_time_request_trigger.cc",
diff --git a/content/browser/android/selection/OWNERS b/content/browser/android/selection/OWNERS
deleted file mode 100644
index 395fd997..0000000
--- a/content/browser/android/selection/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-ctzsm@chromium.org
diff --git a/content/browser/attribution_reporting/attribution_internals.mojom b/content/browser/attribution_reporting/attribution_internals.mojom
index 610fd50..3dcb903 100644
--- a/content/browser/attribution_reporting/attribution_internals.mojom
+++ b/content/browser/attribution_reporting/attribution_internals.mojom
@@ -63,7 +63,6 @@
 // Struct containing stored data that will be sent in a future attribution
 // report.
 struct WebUIAttributionReport {
-  string attribution_destination;
   url.mojom.Url report_url;
   double trigger_time;
   double report_time;
diff --git a/content/browser/attribution_reporting/attribution_internals_browsertest.cc b/content/browser/attribution_reporting/attribution_internals_browsertest.cc
index 4e219d46..15363271 100644
--- a/content/browser/attribution_reporting/attribution_internals_browsertest.cc
+++ b/content/browser/attribution_reporting/attribution_internals_browsertest.cc
@@ -527,18 +527,17 @@
       let table = document.querySelector("#report-table-wrapper tbody");
       let obs = new MutationObserver(() => {
         if (table.children.length === 12 &&
-            table.children[0].children[3].innerText === "https://conversion.test" &&
-            table.children[0].children[4].innerText ===
+            table.children[0].children[3].innerText ===
               "https://report.test/.well-known/attribution-reporting/report-event-attribution" &&
-            table.children[0].children[7].innerText === "13" &&
-            table.children[0].children[8].innerText === "yes" &&
+            table.children[0].children[6].innerText === "13" &&
+            table.children[0].children[7].innerText === "yes" &&
             table.children[0].children[2].innerText === "Pending" &&
-            table.children[1].children[7].innerText === "11" &&
+            table.children[1].children[6].innerText === "11" &&
             table.children[1].children[2].innerText === "Dropped due to low priority" &&
-            table.children[2].children[7].innerText === "12" &&
+            table.children[2].children[6].innerText === "12" &&
             table.children[2].children[2].innerText === "Dropped for noise" &&
-            table.children[3].children[7].innerText === "0" &&
-            table.children[3].children[8].innerText === "no" &&
+            table.children[3].children[6].innerText === "0" &&
+            table.children[3].children[7].innerText === "no" &&
             table.children[3].children[2].innerText === "Sent: HTTP 200" &&
             table.children[4].children[2].innerText === "Prohibited by browser policy" &&
             table.children[5].children[2].innerText === "Network error" &&
@@ -547,7 +546,7 @@
             table.children[8].children[2].innerText === "Deduplicated" &&
             table.children[9].children[2].innerText === "No report capacity for destination site" &&
             table.children[10].children[2].innerText === "Internal error" &&
-            table.children[11].children[4].innerText ===
+            table.children[11].children[3].innerText ===
               "https://report.test/.well-known/attribution-reporting/debug/report-event-attribution") {
           document.title = $1;
         }
@@ -565,18 +564,17 @@
       let table = document.querySelector("#report-table-wrapper tbody");
       let obs = new MutationObserver(() => {
         if (table.children.length === 12 &&
-            table.children[11].children[3].innerText === "https://conversion.test" &&
-            table.children[11].children[4].innerText ===
+            table.children[11].children[3].innerText ===
               "https://report.test/.well-known/attribution-reporting/report-event-attribution" &&
-            table.children[11].children[7].innerText === "13" &&
-            table.children[11].children[8].innerText === "yes" &&
+            table.children[11].children[6].innerText === "13" &&
+            table.children[11].children[7].innerText === "yes" &&
             table.children[11].children[2].innerText === "Pending" &&
-            table.children[10].children[7].innerText === "12" &&
+            table.children[10].children[6].innerText === "12" &&
             table.children[10].children[2].innerText === "Dropped for noise" &&
-            table.children[9].children[7].innerText === "11" &&
+            table.children[9].children[6].innerText === "11" &&
             table.children[9].children[2].innerText === "Dropped due to low priority" &&
-            table.children[8].children[7].innerText === "0" &&
-            table.children[8].children[8].innerText === "no" &&
+            table.children[8].children[6].innerText === "0" &&
+            table.children[8].children[7].innerText === "no" &&
             table.children[8].children[2].innerText === "Sent: HTTP 200" &&
             table.children[7].children[2].innerText === "Prohibited by browser policy" &&
             table.children[6].children[2].innerText === "Network error" &&
@@ -585,7 +583,7 @@
             table.children[3].children[2].innerText === "Deduplicated" &&
             table.children[2].children[2].innerText === "No report capacity for destination site" &&
             table.children[1].children[2].innerText === "Internal error" &&
-            table.children[0].children[4].innerText ===
+            table.children[0].children[3].innerText ===
               "https://report.test/.well-known/attribution-reporting/debug/report-event-attribution") {
           document.title = $1;
         }
@@ -596,7 +594,7 @@
     TitleWatcher title_watcher(shell()->web_contents(), kCompleteTitle2);
     // Sort by priority ascending.
     EXPECT_TRUE(ExecJsInWebUI(
-        "document.querySelectorAll('#report-table-wrapper th')[7].click();"));
+        "document.querySelectorAll('#report-table-wrapper th')[6].click();"));
     EXPECT_EQ(kCompleteTitle2, title_watcher.WaitAndGetTitle());
   }
 
@@ -605,18 +603,17 @@
       let table = document.querySelector("#report-table-wrapper tbody");
       let obs = new MutationObserver(() => {
         if (table.children.length === 12 &&
-            table.children[0].children[3].innerText === "https://conversion.test" &&
-            table.children[0].children[4].innerText ===
+            table.children[0].children[3].innerText ===
               "https://report.test/.well-known/attribution-reporting/report-event-attribution" &&
-            table.children[0].children[7].innerText === "13" &&
-            table.children[0].children[8].innerText === "yes" &&
+            table.children[0].children[6].innerText === "13" &&
+            table.children[0].children[7].innerText === "yes" &&
             table.children[0].children[2].innerText === "Pending" &&
-            table.children[1].children[7].innerText === "12" &&
+            table.children[1].children[6].innerText === "12" &&
             table.children[1].children[2].innerText === "Dropped for noise" &&
-            table.children[2].children[7].innerText === "11" &&
+            table.children[2].children[6].innerText === "11" &&
             table.children[2].children[2].innerText === "Dropped due to low priority" &&
-            table.children[3].children[7].innerText === "0" &&
-            table.children[3].children[8].innerText === "no" &&
+            table.children[3].children[6].innerText === "0" &&
+            table.children[3].children[7].innerText === "no" &&
             table.children[3].children[2].innerText === "Sent: HTTP 200" &&
             table.children[4].children[2].innerText === "Prohibited by browser policy" &&
             table.children[5].children[2].innerText === "Network error" &&
@@ -625,7 +622,7 @@
             table.children[8].children[2].innerText === "Deduplicated" &&
             table.children[9].children[2].innerText === "No report capacity for destination site" &&
             table.children[10].children[2].innerText === "Internal error" &&
-            table.children[11].children[4].innerText ===
+            table.children[11].children[3].innerText ===
               "https://report.test/.well-known/attribution-reporting/debug/report-event-attribution") {
           document.title = $1;
         }
@@ -636,7 +633,7 @@
     TitleWatcher title_watcher(shell()->web_contents(), kCompleteTitle3);
     // Sort by priority descending.
     EXPECT_TRUE(ExecJsInWebUI(
-        "document.querySelectorAll('#report-table-wrapper th')[7].click();"));
+        "document.querySelectorAll('#report-table-wrapper th')[6].click();"));
 
     EXPECT_EQ(kCompleteTitle3, title_watcher.WaitAndGetTitle());
   }
@@ -675,7 +672,7 @@
     let table = document.querySelector("#report-table-wrapper tbody");
     let obs = new MutationObserver(() => {
       if (table.children.length === 2 &&
-          table.children[0].children[7].innerText === "7" &&
+          table.children[0].children[6].innerText === "7" &&
           table.children[1].children[2].innerText === "Sent: HTTP 200") {
         document.title = $1;
       }
@@ -786,7 +783,7 @@
     let table = document.querySelector("#report-table-wrapper tbody");
     let obs = new MutationObserver(() => {
       if (table.children.length === 1 &&
-          table.children[0].children[7].innerText === "7") {
+          table.children[0].children[6].innerText === "7") {
         document.title = $1;
       }
     });
@@ -981,11 +978,10 @@
       let table = document.querySelector("#aggregatable-report-table-wrapper tbody");
       let obs = new MutationObserver(() => {
         if (table.children.length === 11 &&
-            table.children[0].children[3].innerText === "https://conversion.test" &&
-            table.children[0].children[4].innerText ===
+            table.children[0].children[3].innerText ===
               "https://report.test/.well-known/attribution-reporting/report-aggregate-attribution" &&
             table.children[0].children[2].innerText === "Pending" &&
-            table.children[0].children[7].innerText === '[\n {\n  "key": {\n   "highBits": "0",\n   "lowBits": "1"\n  },\n  "value": 2\n }\n]' &&
+            table.children[0].children[6].innerText === '[\n {\n  "key": {\n   "highBits": "0",\n   "lowBits": "1"\n  },\n  "value": 2\n }\n]' &&
             table.children[1].children[2].innerText === "Dropped due to insufficient aggregatable budget" &&
             table.children[2].children[2].innerText === "No report capacity for destination site" &&
             table.children[3].children[2].innerText === "Sent: HTTP 200" &&
@@ -995,7 +991,7 @@
             table.children[7].children[2].innerText === "Dropped due to excessive attributions" &&
             table.children[8].children[2].innerText === "Dropped due to excessive reporting origins" &&
             table.children[9].children[2].innerText === "Internal error" &&
-            table.children[10].children[4].innerText ===
+            table.children[10].children[3].innerText ===
               "https://report.test/.well-known/attribution-reporting/debug/report-aggregate-attribution") {
           document.title = $1;
         }
@@ -1114,8 +1110,8 @@
       let label = document.querySelector('#show-debug-event-reports span');
       let obs = new MutationObserver(() => {
         if (table.children.length === 2 &&
-            table.children[0].children[7].innerText === "1" &&
-            table.children[1].children[7].innerText === "2" &&
+            table.children[0].children[6].innerText === "1" &&
+            table.children[1].children[6].innerText === "2" &&
             label.innerText === '') {
           document.title = $1;
         }
@@ -1151,7 +1147,7 @@
       let label = document.querySelector('#show-debug-event-reports span');
       let obs = new MutationObserver(() => {
         if (table.children.length === 1 &&
-            table.children[0].children[7].innerText === "2" &&
+            table.children[0].children[6].innerText === "2" &&
             label.innerText === ' (2 hidden)') {
           document.title = $1;
         }
@@ -1177,9 +1173,9 @@
       let label = document.querySelector('#show-debug-event-reports span');
       let obs = new MutationObserver(() => {
         if (table.children.length === 3 &&
-            table.children[0].children[7].innerText === "1" &&
-            table.children[1].children[7].innerText === "2" &&
-            table.children[2].children[7].innerText === "3" &&
+            table.children[0].children[6].innerText === "1" &&
+            table.children[1].children[6].innerText === "2" &&
+            table.children[2].children[6].innerText === "3" &&
             label.innerText === '') {
           document.title = $1;
         }
diff --git a/content/browser/attribution_reporting/attribution_internals_handler_impl.cc b/content/browser/attribution_reporting/attribution_internals_handler_impl.cc
index e9e172a..d9e61a3 100644
--- a/content/browser/attribution_reporting/attribution_internals_handler_impl.cc
+++ b/content/browser/attribution_reporting/attribution_internals_handler_impl.cc
@@ -148,7 +148,6 @@
       Visitor{.attribution_logic = attribution_info.source.attribution_logic()},
       report.data());
   return mojom::WebUIAttributionReport::New(
-      attribution_info.source.common_info().ConversionDestination().Serialize(),
       report.ReportURL(is_debug_report),
       /*trigger_time=*/attribution_info.time.ToJsTime(),
       /*report_time=*/report.report_time().ToJsTime(),
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h
index 21756b9..3209677 100644
--- a/content/browser/bad_message.h
+++ b/content/browser/bad_message.h
@@ -296,6 +296,7 @@
   RFH_UNLOAD_HANDLER_NOT_ALLOWED_IN_FENCED_FRAME = 269,
   RFH_BEFOREUNLOAD_HANDLER_NOT_ALLOWED_IN_FENCED_FRAME = 270,
   MSDH_GET_OPEN_DEVICE_USE_WITHOUT_FEATURE = 271,
+  RFHI_SUBFRAME_NAV_WOULD_CHANGE_MAINFRAME_ORIGIN = 272,
 
   // Please add new elements here. The naming convention is abbreviated class
   // name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc
index 3401a2c..350350a 100644
--- a/content/browser/browser_interface_binders.cc
+++ b/content/browser/browser_interface_binders.cc
@@ -20,6 +20,7 @@
 #include "content/browser/bad_message.h"
 #include "content/browser/browser_context_impl.h"
 #include "content/browser/browser_main_loop.h"
+#include "content/browser/browsing_topics/browsing_topics_document_host.h"
 #include "content/browser/contacts/contacts_manager_impl.h"
 #include "content/browser/content_index/content_index_service_impl.h"
 #include "content/browser/cookie_store/cookie_store_manager.h"
@@ -845,11 +846,9 @@
                             base::Unretained(host)));
   }
 
-  if (IsFedCmEnabled()) {
-    map->Add<blink::mojom::FederatedAuthRequest>(base::BindRepeating(
-        &RenderFrameHostImpl::BindFederatedAuthRequestReceiver,
-        base::Unretained(host)));
-  }
+  map->Add<blink::mojom::FederatedAuthRequest>(base::BindRepeating(
+      &RenderFrameHostImpl::BindFederatedAuthRequestReceiver,
+      base::Unretained(host)));
 
   map->Add<blink::mojom::WebUsbService>(base::BindRepeating(
       &RenderFrameHostImpl::CreateWebUsbService, base::Unretained(host)));
@@ -1095,6 +1094,10 @@
               media::mojom::SpeechRecognitionClientBrowserInterface>));
   map->Add<media::mojom::MediaFoundationRendererNotifier>(base::BindRepeating(
       &EmptyBinderForFrame<media::mojom::MediaFoundationRendererNotifier>));
+  if (base::FeatureList::IsEnabled(blink::features::kBrowsingTopics)) {
+    map->Add<blink::mojom::BrowsingTopicsDocumentService>(
+        base::BindRepeating(&BrowsingTopicsDocumentHost::CreateMojoService));
+  }
   map->Add<media::mojom::MediaPlayerObserverClient>(base::BindRepeating(
       &EmptyBinderForFrame<media::mojom::MediaPlayerObserverClient>));
 #endif
diff --git a/content/browser/browser_process_io_thread.h b/content/browser/browser_process_io_thread.h
index ccc12294..b6ec6e6 100644
--- a/content/browser/browser_process_io_thread.h
+++ b/content/browser/browser_process_io_thread.h
@@ -22,6 +22,7 @@
 #endif
 
 namespace content {
+class BrowserThreadImpl;
 class NotificationService;
 }
 
diff --git a/content/browser/browsing_topics/browsing_topics_document_host.cc b/content/browser/browsing_topics/browsing_topics_document_host.cc
new file mode 100644
index 0000000..cb42dbf
--- /dev/null
+++ b/content/browser/browsing_topics/browsing_topics_document_host.cc
@@ -0,0 +1,61 @@
+// 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 "content/browser/browsing_topics/browsing_topics_document_host.h"
+
+#include "base/bind.h"
+#include "content/browser/renderer_host/render_frame_host_impl.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/document_service.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_client.h"
+#include "third_party/blink/public/mojom/browsing_topics/browsing_topics.mojom.h"
+
+namespace content {
+
+BrowsingTopicsDocumentHost::BrowsingTopicsDocumentHost(
+    RenderFrameHost* render_frame_host,
+    mojo::PendingReceiver<blink::mojom::BrowsingTopicsDocumentService> receiver)
+    : DocumentService(render_frame_host, std::move(receiver)) {}
+
+// static
+void BrowsingTopicsDocumentHost::CreateMojoService(
+    RenderFrameHost* render_frame_host,
+    mojo::PendingReceiver<blink::mojom::BrowsingTopicsDocumentService>
+        receiver) {
+  DCHECK(render_frame_host);
+
+  if (render_frame_host->GetLastCommittedOrigin().opaque()) {
+    mojo::ReportBadMessage(
+        "Unexpected BrowsingTopicsDocumentHost::CreateMojoService in an opaque "
+        "origin document");
+    return;
+  }
+
+  if (!render_frame_host->GetMainFrame()->IsInPrimaryMainFrame()) {
+    mojo::ReportBadMessage(
+        "Unexpected BrowsingTopicsDocumentHost::CreateMojoService in a "
+        "non-primary main frame context.");
+    return;
+  }
+
+  // The object is bound to the lifetime of |render_frame_host| and the mojo
+  // connection. See DocumentService for details.
+  new BrowsingTopicsDocumentHost(render_frame_host, std::move(receiver));
+}
+
+void BrowsingTopicsDocumentHost::GetBrowsingTopics(
+    GetBrowsingTopicsCallback callback) {
+  std::vector<blink::mojom::EpochTopicPtr> browsing_topics =
+      GetContentClient()->browser()->GetBrowsingTopicsForJsApi(
+          render_frame_host()->GetLastCommittedOrigin(),
+          render_frame_host()->GetMainFrame());
+
+  std::move(callback).Run(std::move(browsing_topics));
+}
+
+BrowsingTopicsDocumentHost::~BrowsingTopicsDocumentHost() = default;
+
+}  // namespace content
diff --git a/content/browser/browsing_topics/browsing_topics_document_host.h b/content/browser/browsing_topics/browsing_topics_document_host.h
new file mode 100644
index 0000000..a41e252
--- /dev/null
+++ b/content/browser/browsing_topics/browsing_topics_document_host.h
@@ -0,0 +1,48 @@
+// 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 CONTENT_BROWSER_BROWSING_TOPICS_BROWSING_TOPICS_DOCUMENT_HOST_H_
+#define CONTENT_BROWSER_BROWSING_TOPICS_BROWSING_TOPICS_DOCUMENT_HOST_H_
+
+#include "content/common/content_export.h"
+#include "content/public/browser/document_service.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "third_party/blink/public/mojom/browsing_topics/browsing_topics.mojom.h"
+
+namespace content {
+
+class RenderFrameHost;
+
+// The object can only be bound to a document if the `kBrowsingTopics` feature
+// is enabled, and if the document does not have an opaque origin.
+class CONTENT_EXPORT BrowsingTopicsDocumentHost final
+    : public DocumentService<blink::mojom::BrowsingTopicsDocumentService> {
+ public:
+  BrowsingTopicsDocumentHost(
+      RenderFrameHost* render_frame_host,
+      mojo::PendingReceiver<blink::mojom::BrowsingTopicsDocumentService>
+          receiver);
+
+  BrowsingTopicsDocumentHost(const BrowsingTopicsDocumentHost&) = delete;
+  BrowsingTopicsDocumentHost& operator=(const BrowsingTopicsDocumentHost&) =
+      delete;
+  BrowsingTopicsDocumentHost(BrowsingTopicsDocumentHost&&) = delete;
+  BrowsingTopicsDocumentHost& operator=(BrowsingTopicsDocumentHost&&) = delete;
+
+  static void CreateMojoService(
+      RenderFrameHost* render_frame_host,
+      mojo::PendingReceiver<blink::mojom::BrowsingTopicsDocumentService>
+          receiver);
+
+  // blink::mojom::BrowsingTopicsDocumentService.
+  void GetBrowsingTopics(GetBrowsingTopicsCallback callback) override;
+
+ private:
+  // |this| can only be destroyed by DocumentService.
+  ~BrowsingTopicsDocumentHost() override;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_BROWSING_TOPICS_BROWSING_TOPICS_DOCUMENT_HOST_H_
diff --git a/content/browser/browsing_topics/browsing_topics_site_data_manager_impl.cc b/content/browser/browsing_topics/browsing_topics_site_data_manager_impl.cc
index 157ca86..70a78fa 100644
--- a/content/browser/browsing_topics/browsing_topics_site_data_manager_impl.cc
+++ b/content/browser/browsing_topics/browsing_topics_site_data_manager_impl.cc
@@ -54,10 +54,10 @@
 
 void BrowsingTopicsSiteDataManagerImpl::OnBrowsingTopicsApiUsed(
     const browsing_topics::HashedHost& hashed_main_frame_host,
-    const base::flat_set<browsing_topics::HashedDomain>&
-        hashed_context_domains) {
+    const base::flat_set<browsing_topics::HashedDomain>& hashed_context_domains,
+    base::Time time) {
   storage_.AsyncCall(&BrowsingTopicsSiteDataStorage::OnBrowsingTopicsApiUsed)
-      .WithArgs(hashed_main_frame_host, hashed_context_domains);
+      .WithArgs(hashed_main_frame_host, hashed_context_domains, time);
 }
 
 }  // namespace content
diff --git a/content/browser/browsing_topics/browsing_topics_site_data_manager_impl.h b/content/browser/browsing_topics/browsing_topics_site_data_manager_impl.h
index 10dc0a5..3118a8ed 100644
--- a/content/browser/browsing_topics/browsing_topics_site_data_manager_impl.h
+++ b/content/browser/browsing_topics/browsing_topics_site_data_manager_impl.h
@@ -41,7 +41,8 @@
   void OnBrowsingTopicsApiUsed(
       const browsing_topics::HashedHost& hashed_main_frame_host,
       const base::flat_set<browsing_topics::HashedDomain>&
-          hashed_context_domains) override;
+          hashed_context_domains,
+      base::Time time) override;
 
  private:
   base::SequenceBound<BrowsingTopicsSiteDataStorage> storage_;
diff --git a/content/browser/browsing_topics/browsing_topics_site_data_manager_impl_unittest.cc b/content/browser/browsing_topics/browsing_topics_site_data_manager_impl_unittest.cc
index 43990e01..911dadc7 100644
--- a/content/browser/browsing_topics/browsing_topics_site_data_manager_impl_unittest.cc
+++ b/content/browser/browsing_topics/browsing_topics_site_data_manager_impl_unittest.cc
@@ -37,7 +37,8 @@
 
   topics_manager_->OnBrowsingTopicsApiUsed(
       /*hashed_main_frame_host=*/browsing_topics::HashedHost(123),
-      /*hashed_context_domains=*/{browsing_topics::HashedDomain(456)});
+      /*hashed_context_domains=*/{browsing_topics::HashedDomain(456)},
+      initial_time);
 
   size_t query_result_count = 0;
 
diff --git a/content/browser/browsing_topics/browsing_topics_site_data_storage.cc b/content/browser/browsing_topics/browsing_topics_site_data_storage.cc
index 2454ae7..af8a94c3 100644
--- a/content/browser/browsing_topics/browsing_topics_site_data_storage.cc
+++ b/content/browser/browsing_topics/browsing_topics_site_data_storage.cc
@@ -105,8 +105,8 @@
 
 void BrowsingTopicsSiteDataStorage::OnBrowsingTopicsApiUsed(
     const browsing_topics::HashedHost& hashed_main_frame_host,
-    const base::flat_set<browsing_topics::HashedDomain>&
-        hashed_context_domains) {
+    const base::flat_set<browsing_topics::HashedDomain>& hashed_context_domains,
+    base::Time time) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!LazyInit())
@@ -116,8 +116,6 @@
   if (!transaction.Begin())
     return;
 
-  base::Time current_time = base::Time::Now();
-
   for (const browsing_topics::HashedDomain& hashed_context_domain :
        hashed_context_domains) {
     static constexpr char kInsertApiUsageSql[] =
@@ -131,7 +129,7 @@
         db_->GetCachedStatement(SQL_FROM_HERE, kInsertApiUsageSql));
     insert_api_usage_statement.BindInt64(0, hashed_context_domain.value());
     insert_api_usage_statement.BindInt64(1, hashed_main_frame_host.value());
-    insert_api_usage_statement.BindTime(2, current_time);
+    insert_api_usage_statement.BindTime(2, time);
 
     if (!insert_api_usage_statement.Run())
       return;
diff --git a/content/browser/browsing_topics/browsing_topics_site_data_storage.h b/content/browser/browsing_topics/browsing_topics_site_data_storage.h
index 590d3b58..36c8a379 100644
--- a/content/browser/browsing_topics/browsing_topics_site_data_storage.h
+++ b/content/browser/browsing_topics/browsing_topics_site_data_storage.h
@@ -58,7 +58,8 @@
   void OnBrowsingTopicsApiUsed(
       const browsing_topics::HashedHost& hashed_main_frame_host,
       const base::flat_set<browsing_topics::HashedDomain>&
-          hashed_context_domains);
+          hashed_context_domains,
+      base::Time time);
 
  private:
   enum class InitStatus {
diff --git a/content/browser/browsing_topics/browsing_topics_site_data_storage_unittest.cc b/content/browser/browsing_topics/browsing_topics_site_data_storage_unittest.cc
index 1e3bec1..33f9444 100644
--- a/content/browser/browsing_topics/browsing_topics_site_data_storage_unittest.cc
+++ b/content/browser/browsing_topics/browsing_topics_site_data_storage_unittest.cc
@@ -207,7 +207,8 @@
   OpenDatabase();
   topics_storage()->OnBrowsingTopicsApiUsed(
       /*hashed_main_frame_host=*/browsing_topics::HashedHost(123),
-      /*hashed_context_domains=*/{browsing_topics::HashedDomain(456)});
+      /*hashed_context_domains=*/{browsing_topics::HashedDomain(456)},
+      base::Time::Now());
   CloseDatabase();
 
   sql::Database db;
@@ -237,17 +238,20 @@
   OpenDatabase();
   topics_storage()->OnBrowsingTopicsApiUsed(
       /*hashed_main_frame_host=*/browsing_topics::HashedHost(123),
-      /*hashed_context_domains=*/{browsing_topics::HashedDomain(123)});
+      /*hashed_context_domains=*/{browsing_topics::HashedDomain(123)},
+      base::Time::Now());
 
   task_environment_.FastForwardBy(base::Seconds(1));
 
   topics_storage()->OnBrowsingTopicsApiUsed(
       /*hashed_main_frame_host=*/browsing_topics::HashedHost(123),
-      /*hashed_context_domains=*/{browsing_topics::HashedDomain(456),
-                                  browsing_topics::HashedDomain(789)});
+      /*hashed_context_domains=*/
+      {browsing_topics::HashedDomain(456), browsing_topics::HashedDomain(789)},
+      base::Time::Now());
   topics_storage()->OnBrowsingTopicsApiUsed(
       /*hashed_main_frame_host=*/browsing_topics::HashedHost(456),
-      /*hashed_context_domains=*/{browsing_topics::HashedDomain(789)});
+      /*hashed_context_domains=*/{browsing_topics::HashedDomain(789)},
+      base::Time::Now());
   CloseDatabase();
 
   sql::Database db;
@@ -318,13 +322,15 @@
 
   topics_storage()->OnBrowsingTopicsApiUsed(
       /*hashed_main_frame_host=*/browsing_topics::HashedHost(123),
-      /*hashed_context_domains=*/{browsing_topics::HashedDomain(123)});
+      /*hashed_context_domains=*/{browsing_topics::HashedDomain(123)},
+      base::Time::Now());
 
   task_environment_.FastForwardBy(base::Seconds(1));
 
   topics_storage()->OnBrowsingTopicsApiUsed(
       /*hashed_main_frame_host=*/browsing_topics::HashedHost(123),
-      /*hashed_context_domains=*/{browsing_topics::HashedDomain(456)});
+      /*hashed_context_domains=*/{browsing_topics::HashedDomain(456)},
+      base::Time::Now());
 
   task_environment_.FastForwardBy(base::Seconds(1));
 
@@ -358,13 +364,15 @@
 
   topics_storage()->OnBrowsingTopicsApiUsed(
       /*hashed_main_frame_host=*/browsing_topics::HashedHost(123),
-      /*hashed_context_domains=*/{browsing_topics::HashedDomain(123)});
+      /*hashed_context_domains=*/{browsing_topics::HashedDomain(123)},
+      base::Time::Now());
 
   task_environment_.FastForwardBy(base::Seconds(1));
 
   topics_storage()->OnBrowsingTopicsApiUsed(
       /*hashed_main_frame_host=*/browsing_topics::HashedHost(123),
-      /*hashed_context_domains=*/{browsing_topics::HashedDomain(456)});
+      /*hashed_context_domains=*/{browsing_topics::HashedDomain(456)},
+      base::Time::Now());
 
   task_environment_.FastForwardBy(base::Seconds(1));
 
@@ -395,13 +403,15 @@
 
   topics_storage()->OnBrowsingTopicsApiUsed(
       /*hashed_main_frame_host=*/browsing_topics::HashedHost(123),
-      /*hashed_context_domains=*/{browsing_topics::HashedDomain(123)});
+      /*hashed_context_domains=*/{browsing_topics::HashedDomain(123)},
+      base::Time::Now());
 
   task_environment_.FastForwardBy(base::Seconds(1));
 
   topics_storage()->OnBrowsingTopicsApiUsed(
       /*hashed_main_frame_host=*/browsing_topics::HashedHost(123),
-      /*hashed_context_domains=*/{browsing_topics::HashedDomain(456)});
+      /*hashed_context_domains=*/{browsing_topics::HashedDomain(456)},
+      base::Time::Now());
 
   task_environment_.FastForwardBy(base::Seconds(1));
 
@@ -449,13 +459,15 @@
 
   topics_storage()->OnBrowsingTopicsApiUsed(
       /*hashed_main_frame_host=*/browsing_topics::HashedHost(123),
-      /*hashed_context_domains=*/{browsing_topics::HashedDomain(123)});
+      /*hashed_context_domains=*/{browsing_topics::HashedDomain(123)},
+      base::Time::Now());
 
   task_environment_.FastForwardBy(base::Seconds(1));
 
   topics_storage()->OnBrowsingTopicsApiUsed(
       /*hashed_main_frame_host=*/browsing_topics::HashedHost(123),
-      /*hashed_context_domains=*/{browsing_topics::HashedDomain(456)});
+      /*hashed_context_domains=*/{browsing_topics::HashedDomain(456)},
+      base::Time::Now());
 
   task_environment_.FastForwardBy(base::Seconds(1));
 
diff --git a/content/browser/font_access/font_access_manager_impl.cc b/content/browser/font_access/font_access_manager.cc
similarity index 84%
rename from content/browser/font_access/font_access_manager_impl.cc
rename to content/browser/font_access/font_access_manager.cc
index 95c9e974..d9c50d8 100644
--- a/content/browser/font_access/font_access_manager_impl.cc
+++ b/content/browser/font_access/font_access_manager.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/font_access/font_access_manager_impl.h"
+#include "content/browser/font_access/font_access_manager.h"
 
 #include <limits>
 #include <memory>
@@ -33,30 +33,29 @@
 namespace content {
 
 // static
-std::unique_ptr<FontAccessManagerImpl> FontAccessManagerImpl::Create() {
-  return std::make_unique<FontAccessManagerImpl>(
-      FontEnumerationCache::Create(), base::PassKey<FontAccessManagerImpl>());
+std::unique_ptr<FontAccessManager> FontAccessManager::Create() {
+  return std::make_unique<FontAccessManager>(
+      FontEnumerationCache::Create(), base::PassKey<FontAccessManager>());
 }
 
 // static
-std::unique_ptr<FontAccessManagerImpl> FontAccessManagerImpl::CreateForTesting(
+std::unique_ptr<FontAccessManager> FontAccessManager::CreateForTesting(
     base::SequenceBound<FontEnumerationCache> font_enumeration_cache) {
-  return std::make_unique<FontAccessManagerImpl>(
-      std::move(font_enumeration_cache),
-      base::PassKey<FontAccessManagerImpl>());
+  return std::make_unique<FontAccessManager>(
+      std::move(font_enumeration_cache), base::PassKey<FontAccessManager>());
 }
 
-FontAccessManagerImpl::FontAccessManagerImpl(
+FontAccessManager::FontAccessManager(
     base::SequenceBound<FontEnumerationCache> font_enumeration_cache,
-    base::PassKey<FontAccessManagerImpl>)
+    base::PassKey<FontAccessManager>)
     : font_enumeration_cache_(std::move(font_enumeration_cache)),
       results_task_runner_(content::GetUIThreadTaskRunner({})) {}
 
-FontAccessManagerImpl::~FontAccessManagerImpl() {
+FontAccessManager::~FontAccessManager() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
-void FontAccessManagerImpl::BindReceiver(
+void FontAccessManager::BindReceiver(
     GlobalRenderFrameHostId frame_id,
     mojo::PendingReceiver<blink::mojom::FontAccessManager> receiver) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -67,7 +66,7 @@
                  });
 }
 
-void FontAccessManagerImpl::EnumerateLocalFonts(
+void FontAccessManager::EnumerateLocalFonts(
     EnumerateLocalFontsCallback callback) {
   DCHECK(base::FeatureList::IsEnabled(blink::features::kFontAccess));
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -125,11 +124,11 @@
   permission_controller->RequestPermissionFromCurrentDocument(
       PermissionType::FONT_ACCESS, rfh,
       /*user_gesture=*/true,
-      base::BindOnce(&FontAccessManagerImpl::DidRequestPermission,
+      base::BindOnce(&FontAccessManager::DidRequestPermission,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-void FontAccessManagerImpl::DidRequestPermission(
+void FontAccessManager::DidRequestPermission(
     EnumerateLocalFontsCallback callback,
     blink::mojom::PermissionStatus status) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -141,8 +140,8 @@
     return;
   }
 
-// Per-platform delegation for obtaining cached font enumeration data occurs
-// here, after the permission has been granted.
+  // Per-platform delegation for obtaining cached font enumeration data occurs
+  // here, after the permission has been granted.
   font_enumeration_cache_
       .AsyncCall(&FontEnumerationCache::GetFontEnumerationData)
       .Then(base::BindOnce(
diff --git a/content/browser/font_access/font_access_manager_impl.h b/content/browser/font_access/font_access_manager.h
similarity index 66%
rename from content/browser/font_access/font_access_manager_impl.h
rename to content/browser/font_access/font_access_manager.h
index 0064e27c..bf578f4cb 100644
--- a/content/browser/font_access/font_access_manager_impl.h
+++ b/content/browser/font_access/font_access_manager.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_BROWSER_FONT_ACCESS_FONT_ACCESS_MANAGER_IMPL_H_
-#define CONTENT_BROWSER_FONT_ACCESS_FONT_ACCESS_MANAGER_IMPL_H_
+#ifndef CONTENT_BROWSER_FONT_ACCESS_FONT_ACCESS_MANAGER_H_
+#define CONTENT_BROWSER_FONT_ACCESS_FONT_ACCESS_MANAGER_H_
 
 #include <map>
 #include <memory>
@@ -27,9 +27,9 @@
 
 // The ownership hierarchy for this class is:
 //
-// StoragePartitionImpl (1) <- (1) FontAccessManagerImpl
+// StoragePartitionImpl (1) <- (1) FontAccessManager
 //
-// FontAccessManagerImpl (1) <- (*) BindingContext
+// FontAccessManager (1) <- (*) BindingContext
 //
 // BindingContext (1) <- (1) GlobalRenderFrameHostId
 //
@@ -40,34 +40,30 @@
 // (N) : N is a number or *, which denotes zero or more
 //
 // In English:
-// * There's one FontAccessManagerImpl per StoragePartitionImpl
-// * Frames are bound to FontAccessManangerImpl via a BindingContext
-// * The FontAccessManagerImpl owns the lifetimes of FontAccessChoosers
-// * There is one FontAccessChooser for each Frame via its
-// GlobalRenderFrameHostId,
-//   obtained from a corresponding BindingContext
-class CONTENT_EXPORT FontAccessManagerImpl
+// * There's one FontAccessManager per StoragePartitionImpl
+// * Frames are bound to FontAccessManager via a BindingContext.
+class CONTENT_EXPORT FontAccessManager
     : public blink::mojom::FontAccessManager {
  public:
   // Factory method for production instances.
-  static std::unique_ptr<FontAccessManagerImpl> Create();
+  static std::unique_ptr<FontAccessManager> Create();
 
   // Factory method with dependency injection support for testing.
-  static std::unique_ptr<FontAccessManagerImpl> CreateForTesting(
+  static std::unique_ptr<FontAccessManager> CreateForTesting(
       base::SequenceBound<FontEnumerationCache> font_enumeration_cache);
 
   // The constructor is public for internal use of std::make_unique.
   //
-  // Production code should call FontAccessManagerImpl::Create(). Testing code
-  // should call FontAccessManagerImpl::CreateForTesting().
-  FontAccessManagerImpl(
+  // Production code should call FontAccessManager::Create(). Testing code
+  // should call FontAccessManager::CreateForTesting().
+  FontAccessManager(
       base::SequenceBound<FontEnumerationCache> font_enumeration_cache,
-      base::PassKey<FontAccessManagerImpl>);
+      base::PassKey<FontAccessManager>);
 
-  FontAccessManagerImpl(const FontAccessManagerImpl&) = delete;
-  FontAccessManagerImpl& operator=(const FontAccessManagerImpl&) = delete;
+  FontAccessManager(const FontAccessManager&) = delete;
+  FontAccessManager& operator=(const FontAccessManager&) = delete;
 
-  ~FontAccessManagerImpl() override;
+  ~FontAccessManager() override;
 
   void BindReceiver(
       GlobalRenderFrameHostId frame_id,
@@ -103,10 +99,10 @@
   bool skip_privacy_checks_for_testing_ GUARDED_BY_CONTEXT(sequence_checker_) =
       false;
 
-  base::WeakPtrFactory<FontAccessManagerImpl> weak_ptr_factory_
+  base::WeakPtrFactory<FontAccessManager> weak_ptr_factory_
       GUARDED_BY_CONTEXT(sequence_checker_){this};
 };
 
 }  // namespace content
 
-#endif  // CONTENT_BROWSER_FONT_ACCESS_FONT_ACCESS_MANAGER_IMPL_H_
+#endif  // CONTENT_BROWSER_FONT_ACCESS_FONT_ACCESS_MANAGER_H_
diff --git a/content/browser/font_access/font_access_manager_impl_browsertest.cc b/content/browser/font_access/font_access_manager_browsertest.cc
similarity index 89%
rename from content/browser/font_access/font_access_manager_impl_browsertest.cc
rename to content/browser/font_access/font_access_manager_browsertest.cc
index 99dd6ca..52213fb 100644
--- a/content/browser/font_access/font_access_manager_impl_browsertest.cc
+++ b/content/browser/font_access/font_access_manager_browsertest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/font_access/font_access_manager_impl.h"
+#include "content/browser/font_access/font_access_manager.h"
 
 #include <memory>
 #include <string>
@@ -37,9 +37,9 @@
 // This class exists so that tests can be written without enabling
 // the kFontAccess feature flag. This will be redundant once the flag
 // goes away.
-class FontAccessManagerImplBrowserBase : public ContentBrowserTest {
+class FontAccessManagerBrowserBase : public ContentBrowserTest {
  public:
-  FontAccessManagerImplBrowserBase() {
+  FontAccessManagerBrowserBase() {
     scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
   }
 
@@ -51,7 +51,7 @@
     return shell()->web_contents()->GetMainFrame();
   }
 
-  FontAccessManagerImpl* font_access_manager() {
+  FontAccessManager* font_access_manager() {
     auto* storage_partition =
         static_cast<StoragePartitionImpl*>(main_rfh()->GetStoragePartition());
     return storage_partition->GetFontAccessManager();
@@ -73,8 +73,7 @@
     auto* storage_partition =
         static_cast<StoragePartitionImpl*>(main_rfh()->GetStoragePartition());
     storage_partition->SetFontAccessManagerForTesting(
-        FontAccessManagerImpl::CreateForTesting(
-            std::move(font_enumeration_cache)));
+        FontAccessManager::CreateForTesting(std::move(font_enumeration_cache)));
   }
 
  protected:
@@ -82,10 +81,9 @@
   std::unique_ptr<FontEnumerationCache> enumeration_cache_;
 };
 
-class FontAccessManagerImplBrowserTest
-    : public FontAccessManagerImplBrowserBase {
+class FontAccessManagerBrowserTest : public FontAccessManagerBrowserBase {
  public:
-  FontAccessManagerImplBrowserTest() {
+  FontAccessManagerBrowserTest() {
     std::vector<base::Feature> enabled_features({
         blink::features::kFontAccess,
     });
@@ -95,7 +93,7 @@
 };
 
 // Disabled test: https://crbug.com/1224238
-IN_PROC_BROWSER_TEST_F(FontAccessManagerImplBrowserBase,
+IN_PROC_BROWSER_TEST_F(FontAccessManagerBrowserBase,
                        DISABLED_RendererInterfaceIsBound) {
   ASSERT_TRUE(NavigateToURL(shell(), GetTestUrl(nullptr, "simple_page.html")));
   // This tests that the renderer interface is bound even if the kFontAccess
@@ -114,7 +112,7 @@
       << "FontAccessManager remote is expected to be bound and connected.";
 }
 
-IN_PROC_BROWSER_TEST_F(FontAccessManagerImplBrowserTest, EnumerationTest) {
+IN_PROC_BROWSER_TEST_F(FontAccessManagerBrowserTest, EnumerationTest) {
   ASSERT_TRUE(NavigateToURL(shell(), GetTestUrl(nullptr, "simple_page.html")));
   font_access_manager()->SkipPrivacyChecksForTesting(true);
 
@@ -133,7 +131,7 @@
   }
 }
 
-IN_PROC_BROWSER_TEST_F(FontAccessManagerImplBrowserTest,
+IN_PROC_BROWSER_TEST_F(FontAccessManagerBrowserTest,
                        EnumerationTestWithInvalidSelect) {
   ASSERT_TRUE(NavigateToURL(shell(), GetTestUrl(nullptr, "simple_page.html")));
   font_access_manager()->SkipPrivacyChecksForTesting(true);
@@ -151,7 +149,7 @@
 }
 
 #if BUILDFLAG(IS_WIN)
-IN_PROC_BROWSER_TEST_F(FontAccessManagerImplBrowserTest, LocaleTest) {
+IN_PROC_BROWSER_TEST_F(FontAccessManagerBrowserTest, LocaleTest) {
   ASSERT_TRUE(NavigateToURL(shell(), GetTestUrl(nullptr, "simple_page.html")));
   OverrideFontAccessLocale("zh-cn");
   font_access_manager()->SkipPrivacyChecksForTesting(true);
@@ -173,8 +171,7 @@
   EXPECT_EQ(ms_yahei_utf8, result);
 }
 
-IN_PROC_BROWSER_TEST_F(FontAccessManagerImplBrowserTest,
-                       UnlocalizedFamilyTest) {
+IN_PROC_BROWSER_TEST_F(FontAccessManagerBrowserTest, UnlocalizedFamilyTest) {
   ASSERT_TRUE(NavigateToURL(shell(), GetTestUrl(nullptr, "simple_page.html")));
   OverrideFontAccessLocale("zh-cn");
   font_access_manager()->SkipPrivacyChecksForTesting(true);
@@ -197,4 +194,4 @@
 }
 #endif  // BUILDFLAG(IS_WIN)
 
-}  // namespace content
+}  // namespace content
\ No newline at end of file
diff --git a/content/browser/font_access/font_access_manager_impl_unittest.cc b/content/browser/font_access/font_access_manager_unittest.cc
similarity index 86%
rename from content/browser/font_access/font_access_manager_impl_unittest.cc
rename to content/browser/font_access/font_access_manager_unittest.cc
index f53eba1b..cfdeff1 100644
--- a/content/browser/font_access/font_access_manager_impl_unittest.cc
+++ b/content/browser/font_access/font_access_manager_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/font_access/font_access_manager_impl.h"
+#include "content/browser/font_access/font_access_manager.h"
 
 #include <memory>
 #include <utility>
@@ -45,16 +45,17 @@
 // Synchronous proxy to a blink::mojom::FontAccessManager.
 class FontAccessManagerSync {
  public:
-  explicit FontAccessManagerSync(blink::mojom::FontAccessManager* manager)
-      : manager_(manager) {
-    DCHECK(manager);
+  explicit FontAccessManagerSync(
+      blink::mojom::FontAccessManager* manager_remote)
+      : manager_remote_(manager_remote) {
+    DCHECK(manager_remote);
   }
   std::pair<FontEnumerationStatus, base::ReadOnlySharedMemoryRegion>
   EnumerateLocalFonts() {
     std::pair<FontEnumerationStatus, base::ReadOnlySharedMemoryRegion> result;
 
     base::RunLoop run_loop;
-    manager_->EnumerateLocalFonts(base::BindLambdaForTesting(
+    manager_remote_->EnumerateLocalFonts(base::BindLambdaForTesting(
         [&](FontEnumerationStatus status,
             base::ReadOnlySharedMemoryRegion region) {
           result.first = status;
@@ -67,12 +68,12 @@
   }
 
  private:
-  const raw_ptr<blink::mojom::FontAccessManager> manager_;
+  const raw_ptr<blink::mojom::FontAccessManager> manager_remote_;
 };
 
-class FontAccessManagerImplTest : public RenderViewHostImplTestHarness {
+class FontAccessManagerTest : public RenderViewHostImplTestHarness {
  public:
-  FontAccessManagerImplTest() {
+  FontAccessManagerTest() {
     scoped_feature_list_.InitAndEnableFeature(blink::features::kFontAccess);
   }
 
@@ -90,11 +91,12 @@
         FontEnumerationCache::CreateForTesting(
             cache_task_runner_, FontEnumerationDataSource::Create(),
             /* locale_override= */ absl::nullopt);
-    manager_impl_ = FontAccessManagerImpl::CreateForTesting(
-        std::move(font_enumeration_cache));
-    manager_impl_->BindReceiver(main_frame_id,
-                                manager_.BindNewPipeAndPassReceiver());
-    manager_sync_ = std::make_unique<FontAccessManagerSync>(manager_.get());
+    manager_ =
+        FontAccessManager::CreateForTesting(std::move(font_enumeration_cache));
+    manager_->BindReceiver(main_frame_id,
+                           manager_remote_.BindNewPipeAndPassReceiver());
+    manager_sync_ =
+        std::make_unique<FontAccessManagerSync>(manager_remote_.get());
 
     // Set up permission mock.
     TestBrowserContext* browser_context =
@@ -109,8 +111,8 @@
     // Ensure that the FontEnumerationCache instance is destroyed before the
     // test ends. This avoids ASAN failures.
     manager_sync_ = nullptr;
-    manager_.reset();
-    manager_impl_ = nullptr;
+    manager_remote_.reset();
+    manager_ = nullptr;
     base::RunLoop run_loop;
     cache_task_runner_->PostTask(FROM_HERE, run_loop.QuitClosure());
     run_loop.Run();
@@ -168,8 +170,8 @@
   const url::Origin kTestOrigin = url::Origin::Create(GURL(kTestUrl));
 
   std::unique_ptr<PermissionControllerImpl> permission_controller_;
-  std::unique_ptr<FontAccessManagerImpl> manager_impl_;
-  mojo::Remote<blink::mojom::FontAccessManager> manager_;
+  std::unique_ptr<FontAccessManager> manager_;
+  mojo::Remote<blink::mojom::FontAccessManager> manager_remote_;
   std::unique_ptr<FontAccessManagerSync> manager_sync_;
   scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
 
@@ -206,7 +208,7 @@
 
 }  // namespace
 
-TEST_F(FontAccessManagerImplTest, FailsIfFrameNotInViewport) {
+TEST_F(FontAccessManagerTest, FailsIfFrameNotInViewport) {
   AutoGrantPermission();
   SetFrameHidden();
 
@@ -215,7 +217,7 @@
   EXPECT_FALSE(region.IsValid());
 }
 
-TEST_F(FontAccessManagerImplTest, EnumerationConsumesUserActivation) {
+TEST_F(FontAccessManagerTest, EnumerationConsumesUserActivation) {
   AskGrantPermission();
   SimulateUserActivation();
 
@@ -237,7 +239,7 @@
   }
 }
 
-TEST_F(FontAccessManagerImplTest, PreviouslyGrantedValidateEnumerationBasic) {
+TEST_F(FontAccessManagerTest, PreviouslyGrantedValidateEnumerationBasic) {
   AutoGrantPermission();
   SimulateUserActivation();
 
@@ -250,7 +252,7 @@
   }
 }
 
-TEST_F(FontAccessManagerImplTest, UserActivationRequiredBeforeGrant) {
+TEST_F(FontAccessManagerTest, UserActivationRequiredBeforeGrant) {
   AskGrantPermission();
   SimulateUserActivation();
 
@@ -262,14 +264,14 @@
   }
 }
 
-TEST_F(FontAccessManagerImplTest, EnumerationFailsIfNoActivation) {
+TEST_F(FontAccessManagerTest, EnumerationFailsIfNoActivation) {
   AskGrantPermission();
 
   const auto [status, region] = manager_sync_->EnumerateLocalFonts();
   EXPECT_EQ(status, FontEnumerationStatus::kNeedsUserActivation);
 }
 
-TEST_F(FontAccessManagerImplTest, PermissionDeniedOnAskErrors) {
+TEST_F(FontAccessManagerTest, PermissionDeniedOnAskErrors) {
   AskDenyPermission();
   SimulateUserActivation();
 
@@ -277,7 +279,7 @@
   EXPECT_EQ(status, FontEnumerationStatus::kPermissionDenied);
 }
 
-TEST_F(FontAccessManagerImplTest, PermissionPreviouslyDeniedErrors) {
+TEST_F(FontAccessManagerTest, PermissionPreviouslyDeniedErrors) {
   AutoDenyPermission();
   SimulateUserActivation();
 
@@ -287,4 +289,4 @@
 
 }  // namespace
 
-}  // namespace content
+}  // namespace content
\ No newline at end of file
diff --git a/content/browser/interest_group/ad_auction_service_impl_unittest.cc b/content/browser/interest_group/ad_auction_service_impl_unittest.cc
index 0cfbdceb..d9c955f 100644
--- a/content/browser/interest_group/ad_auction_service_impl_unittest.cc
+++ b/content/browser/interest_group/ad_auction_service_impl_unittest.cc
@@ -3102,7 +3102,6 @@
   interest_group.ads.emplace();
   blink::InterestGroup::Ad ad(
       /*render_url=*/GURL("https://example.com/render"),
-      // TODO: update
       /*metadata=*/absl::nullopt);
   interest_group.ads->emplace_back(std::move(ad));
   JoinInterestGroupAndFlush(interest_group);
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index dc75ab59..9e820792 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -68,7 +68,7 @@
 #include "content/browser/file_system/file_system_manager_impl.h"
 #include "content/browser/file_system/file_system_url_loader_factory.h"
 #include "content/browser/file_system_access/file_system_access_manager_impl.h"
-#include "content/browser/font_access/font_access_manager_impl.h"
+#include "content/browser/font_access/font_access_manager.h"
 #include "content/browser/generic_sensor/sensor_provider_proxy_impl.h"
 #include "content/browser/geolocation/geolocation_service_impl.h"
 #include "content/browser/idle/idle_manager_impl.h"
@@ -243,6 +243,7 @@
 #include "ui/accessibility/ax_action_handler_registry.h"
 #include "ui/accessibility/ax_common.h"
 #include "ui/accessibility/ax_tree_update.h"
+#include "ui/display/screen.h"
 #include "ui/events/event_constants.h"
 #include "url/gurl.h"
 #include "url/origin.h"
@@ -1058,6 +1059,17 @@
          !IsAvoidUnnecessaryBeforeUnloadCheckSyncEnabled();
 }
 
+// Returns true if `host` has the Window Placement permission granted.
+bool IsWindowPlacementGranted(RenderFrameHost* host) {
+  content::PermissionController* permission_controller =
+      host->GetBrowserContext()->GetPermissionController();
+  DCHECK(permission_controller);
+
+  return permission_controller->GetPermissionStatusForCurrentDocument(
+             PermissionType::WINDOW_PLACEMENT, host) ==
+         blink::mojom::PermissionStatus::GRANTED;
+}
+
 }  // namespace
 
 class RenderFrameHostImpl::SubresourceLoaderFactoriesConfig {
@@ -6238,6 +6250,20 @@
     std::move(callback).Run(/*granted=*/false);
     return;
   }
+
+  // Allow sites with the window-placement permission to open a popup window
+  // after requesting fullscreen on a specific screen of a multi-screen device.
+  // This enables multi-screen content experiences from a single user gesture.
+  const display::Screen* screen = display::Screen::GetScreen();
+  display::Display display;
+  if (base::FeatureList::IsEnabled(
+          blink::features::kWindowPlacementFullscreenCompanionWindow) &&
+      screen && screen->GetNumDisplays() > 1 &&
+      screen->GetDisplayWithDisplayId(options->display_id, &display) &&
+      IsWindowPlacementGranted(this)) {
+    transient_allow_popup_.Activate();
+  }
+
   std::move(callback).Run(/*granted=*/true);
 
   // Entering fullscreen from a cross-process subframe also affects all
@@ -6868,7 +6894,9 @@
   GetProcess()->FilterURL(false, &params->target_url);
 
   bool effective_transient_activation_state =
-      params->allow_popup || frame_tree_node_->HasTransientUserActivation();
+      params->allow_popup || frame_tree_node_->HasTransientUserActivation() ||
+      (transient_allow_popup_.IsActive() &&
+       params->disposition == WindowOpenDisposition::NEW_POPUP);
 
   // Ignore window creation when sent from a frame that's not active or
   // created.
@@ -6997,6 +7025,8 @@
       delegate_->CreateNewWindow(this, *params, is_new_browsing_instance,
                                  was_consumed, cloned_namespace.get());
 
+  transient_allow_popup_.Deactivate();
+
   if (is_new_browsing_instance || !new_frame_tree) {
     // Opener suppressed, Javascript access disabled, or delegate did not
     // provide a handle to any windows it created. In these cases, never tell
@@ -9196,6 +9226,14 @@
   GetRenderWidgetHost()->InsertVisualStateCallback(std::move(callback));
 }
 
+bool RenderFrameHostImpl::IsLastCommitIPAddressPubliclyRoutable() const {
+  net::IPEndPoint ip_end_point =
+      last_response_head().get() ? last_response_head().get()->remote_endpoint
+                                 : net::IPEndPoint();
+
+  return ip_end_point.address().IsPubliclyRoutable();
+}
+
 bool RenderFrameHostImpl::IsRenderFrameCreated() {
   return is_render_frame_created();
 }
@@ -9385,16 +9423,8 @@
 }
 
 bool RenderFrameHostImpl::WindowPlacementAllowsFullscreen() {
-  if (!delegate_->IsTransientAllowFullscreenActive())
-    return false;
-
-  content::PermissionController* permission_controller =
-      GetBrowserContext()->GetPermissionController();
-  DCHECK(permission_controller);
-
-  return permission_controller->GetPermissionStatusForCurrentDocument(
-             PermissionType::WINDOW_PLACEMENT, this) ==
-         blink::mojom::PermissionStatus::GRANTED;
+  return IsWindowPlacementGranted(this) &&
+         delegate_->IsTransientAllowFullscreenActive();
 }
 
 mojo::AssociatedRemote<mojom::NavigationClient>
@@ -10100,7 +10130,6 @@
 
 void RenderFrameHostImpl::BindFederatedAuthRequestReceiver(
     mojo::PendingReceiver<blink::mojom::FederatedAuthRequest> receiver) {
-  DCHECK(IsFedCmEnabled());
   FederatedAuthRequestService::Create(this, std::move(receiver));
 }
 
@@ -10664,10 +10693,11 @@
   // Check(s) specific to sub-frame navigation.
   if (navigation_request && !is_main_frame()) {
     if (!CanSubframeCommitOriginAndUrl(navigation_request)) {
-      // TODO(crbug.com/1303184): Prefer to terminate a renderer process if
-      // it makes invalid requests, so switch DumpWithoutCrashing to
-      // ReportBadMessage if this looks stable.
-      base::debug::DumpWithoutCrashing();
+      // Terminate the renderer if allowing this subframe navigation to commit
+      // would change the origin of the main frame.
+      bad_message::ReceivedBadMessage(
+          GetProcess(),
+          bad_message::RFHI_SUBFRAME_NAV_WOULD_CHANGE_MAINFRAME_ORIGIN);
       return false;
     }
   }
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
index 06b5de3..d7eae7b 100644
--- a/content/browser/renderer_host/render_frame_host_impl.h
+++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -53,6 +53,7 @@
 #include "content/browser/renderer_host/page_impl.h"
 #include "content/browser/renderer_host/policy_container_host.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/transient_allow_popup.h"
 #include "content/browser/site_instance_group.h"
 #include "content/browser/site_instance_impl.h"
 #include "content/browser/storage_partition_impl.h"
@@ -387,6 +388,7 @@
   service_manager::InterfaceProvider* GetRemoteInterfaces() override;
   blink::AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces() override;
   content::PageVisibilityState GetVisibilityState() override;
+  bool IsLastCommitIPAddressPubliclyRoutable() const override;
   bool IsRenderFrameCreated() override;
   bool IsRenderFrameLive() override;
   LifecycleState GetLifecycleState() override;
@@ -4159,6 +4161,9 @@
   std::unique_ptr<AXScreenAIAnnotator> ax_screen_ai_annotator_;
 #endif
 
+  // Manages a transient affordance for this frame or subframes to open a popup.
+  TransientAllowPopup transient_allow_popup_;
+
   // BrowserInterfaceBroker implementation through which this
   // RenderFrameHostImpl exposes document-scoped Mojo services to the currently
   // active document in the corresponding RenderFrame.
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index cc5f7c8..a188b12 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -4913,10 +4913,7 @@
   // Update the priority of the process running the controller service worker
   // when client's background state changed. We can make the service worker
   // process backgrounded if all of its clients are backgrounded.
-  if (background_state_changed &&
-      base::FeatureList::IsEnabled(
-          features::
-              kChangeServiceWorkerPriorityForClientForegroundStateChange)) {
+  if (background_state_changed) {
     UpdateControllerServiceWorkerProcessPriority();
   }
 }
diff --git a/content/browser/renderer_host/render_widget_host_view_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
index 82bb3f9..491168d 100644
--- a/content/browser/renderer_host/render_widget_host_view_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
@@ -625,14 +625,8 @@
 
 // Tests that the callback passed to CopyFromSurface is always called, even
 // when the RenderWidgetHostView is deleting in the middle of an async copy.
-//
-// TODO(https://crbug.com/1033066): On some bots (e.g., ChromeOS and Cast
-// Shell), this test fails because the RunLoop quits before its QuitClosure() is
-// run. This is because the call to WebContents::Close() leads to something that
-// makes the current thread's RunLoop::Delegate constantly report "should quit."
-// We'll need to find a better way of testing this functionality.
 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
-                       DISABLED_CopyFromSurface_CallbackDespiteDelete) {
+                       CopyFromSurface_CallbackDespiteDelete) {
   SET_UP_SURFACE_OR_PASS_TEST(nullptr);
 
   base::RunLoop run_loop;
@@ -642,6 +636,8 @@
                      base::Unretained(this), run_loop.QuitClosure()));
   shell()->web_contents()->Close();
   run_loop.Run();
+  while (callback_invoke_count() == 0)
+    GiveItSomeTime();
 
   EXPECT_EQ(1, callback_invoke_count());
 }
diff --git a/content/browser/renderer_host/transient_allow_popup.cc b/content/browser/renderer_host/transient_allow_popup.cc
new file mode 100644
index 0000000..3db0dad9
--- /dev/null
+++ b/content/browser/renderer_host/transient_allow_popup.cc
@@ -0,0 +1,23 @@
+// 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 "content/browser/renderer_host/transient_allow_popup.h"
+
+namespace content {
+
+TransientAllowPopup::TransientAllowPopup() = default;
+
+void TransientAllowPopup::Activate() {
+  transient_state_expiry_time_ = base::TimeTicks::Now() + kActivationLifespan;
+}
+
+void TransientAllowPopup::Deactivate() {
+  transient_state_expiry_time_ = base::TimeTicks();
+}
+
+bool TransientAllowPopup::IsActive() const {
+  return base::TimeTicks::Now() <= transient_state_expiry_time_;
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/transient_allow_popup.h b/content/browser/renderer_host/transient_allow_popup.h
new file mode 100644
index 0000000..4f3e9d3
--- /dev/null
+++ b/content/browser/renderer_host/transient_allow_popup.h
@@ -0,0 +1,39 @@
+// 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 CONTENT_BROWSER_RENDERER_HOST_TRANSIENT_ALLOW_POPUP_H_
+#define CONTENT_BROWSER_RENDERER_HOST_TRANSIENT_ALLOW_POPUP_H_
+
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// This class manages a transient affordance for a frame to open a popup window.
+// Sites with window-placement permission may open a popup on another screen
+// after requesting fullscreen on a specific screen of a multi-screen device.
+// This enables multi-screen content experiences from a single user gesture.
+class CONTENT_EXPORT TransientAllowPopup {
+ public:
+  TransientAllowPopup();
+
+  // The lifespan should be just long enough to allow brief async script calls.
+  static constexpr base::TimeDelta kActivationLifespan = base::Seconds(1);
+
+  // Activate the transient state.
+  void Activate();
+
+  // Deactivate the transient state.
+  void Deactivate();
+
+  // Returns the transient state; |true| if this object was recently activated.
+  bool IsActive() const;
+
+ private:
+  base::TimeTicks transient_state_expiry_time_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_TRANSIENT_ALLOW_POPUP_H_
diff --git a/content/browser/renderer_host/transient_allow_popup_unittest.cc b/content/browser/renderer_host/transient_allow_popup_unittest.cc
new file mode 100644
index 0000000..1bf130e
--- /dev/null
+++ b/content/browser/renderer_host/transient_allow_popup_unittest.cc
@@ -0,0 +1,46 @@
+// 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 "content/browser/renderer_host/transient_allow_popup.h"
+
+#include "base/test/task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+using TransientAllowPopupTest = testing::Test;
+
+// A test of basic functionality.
+TEST_F(TransientAllowPopupTest, Basic) {
+  base::test::TaskEnvironment task_environment(
+      base::test::TaskEnvironment::TimeSource::MOCK_TIME);
+
+  // By default, the object is not active.
+  TransientAllowPopup transient_allow_popup;
+  EXPECT_FALSE(transient_allow_popup.IsActive());
+
+  // Activation works as expected.
+  transient_allow_popup.Activate();
+  EXPECT_TRUE(transient_allow_popup.IsActive());
+
+  // Test the activation state immediately before expiration.
+  const base::TimeDelta kEpsilon = base::Milliseconds(10);
+  task_environment.FastForwardBy(TransientAllowPopup::kActivationLifespan -
+                                 kEpsilon);
+  EXPECT_TRUE(transient_allow_popup.IsActive());
+
+  // Test the activation state immediately after expiration.
+  task_environment.FastForwardBy(2 * kEpsilon);
+  EXPECT_FALSE(transient_allow_popup.IsActive());
+
+  // Repeated activation works as expected.
+  transient_allow_popup.Activate();
+  EXPECT_TRUE(transient_allow_popup.IsActive());
+
+  // Deactivation works as expected.
+  transient_allow_popup.Deactivate();
+  EXPECT_FALSE(transient_allow_popup.IsActive());
+}
+
+}  // namespace content
diff --git a/content/browser/resources/attribution_reporting/attribution_internals.js b/content/browser/resources/attribution_reporting/attribution_internals.js
index bb3f647e..9f75580c 100644
--- a/content/browser/resources/attribution_reporting/attribution_internals.js
+++ b/content/browser/resources/attribution_reporting/attribution_internals.js
@@ -549,7 +549,6 @@
 
     this.id = id;
     this.reportBody = mojo.reportBody;
-    this.attributionDestination = mojo.attributionDestination;
     this.reportUrl = mojo.reportUrl.url;
     this.triggerTime = new Date(mojo.triggerTime);
     this.reportTime = new Date(mojo.reportTime);
@@ -753,7 +752,6 @@
       this.selectionColumn,
       new CodeColumn('Report Body', (e) => e.reportBody),
       new ValueColumn('Status', (e) => e.status),
-      new ValueColumn('Destination', (e) => e.attributionDestination),
       new ReportUrlColumn(),
       new DateColumn('Trigger Time', (e) => e.triggerTime),
       new DateColumn('Report Time', (e) => e.reportTime),
@@ -763,7 +761,7 @@
     ];
 
     // Sort by report time by default.
-    this.sortIdx = 6;
+    this.sortIdx = 5;
   }
 }
 
@@ -779,7 +777,6 @@
       this.selectionColumn,
       new CodeColumn('Report Body', (e) => e.reportBody),
       new ValueColumn('Status', (e) => e.status),
-      new ValueColumn('Destination', (e) => e.attributionDestination),
       new ReportUrlColumn(),
       new DateColumn('Trigger Time', (e) => e.triggerTime),
       new DateColumn('Report Time', (e) => e.reportTime),
@@ -787,7 +784,7 @@
     ];
 
     // Sort by report time by default.
-    this.sortIdx = 6;
+    this.sortIdx = 5;
   }
 }
 
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 2d8b451..d184a22 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -2460,10 +2460,7 @@
     // Require foreground if the controllee is in different process and is
     // foreground.
     if (controllee_process_id != worker_process_id &&
-        (!base::FeatureList::IsEnabled(
-             features::
-                 kChangeServiceWorkerPriorityForClientForegroundStateChange) ||
-         !render_host->IsProcessBackgrounded())) {
+        !render_host->IsProcessBackgrounded()) {
       return true;
     }
   }
diff --git a/content/browser/service_worker/service_worker_version_unittest.cc b/content/browser/service_worker/service_worker_version_unittest.cc
index 1eef4366..19e09ac1 100644
--- a/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/content/browser/service_worker/service_worker_version_unittest.cc
@@ -1322,19 +1322,7 @@
       helper_->mock_render_process_host()->foreground_service_worker_count());
 }
 
-class ChangeServiceWorkerPriorityForClientForegroundStateChangeTest
-    : public ServiceWorkerVersionTest {
- public:
-  ChangeServiceWorkerPriorityForClientForegroundStateChangeTest() {
-    feature_list_.InitAndEnableFeature(
-        features::kChangeServiceWorkerPriorityForClientForegroundStateChange);
-  }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
-
-TEST_F(ChangeServiceWorkerPriorityForClientForegroundStateChangeTest,
+TEST_F(ServiceWorkerVersionTest,
        ForegroundServiceWorkerCountUpdatedByControlleeForegroundStateChange) {
   // Start the worker before we have a controllee.
   ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk,
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index 621016b94..790bb0ef 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -64,7 +64,7 @@
 #include "content/browser/devtools/devtools_url_loader_interceptor.h"
 #include "content/browser/file_system/browser_file_system_helper.h"
 #include "content/browser/file_system_access/file_system_access_manager_impl.h"
-#include "content/browser/font_access/font_access_manager_impl.h"
+#include "content/browser/font_access/font_access_manager.h"
 #include "content/browser/gpu/shader_cache_factory.h"
 #include "content/browser/host_zoom_level_context.h"
 #include "content/browser/indexed_db/indexed_db_control_wrapper.h"
@@ -1356,7 +1356,7 @@
                                                settings.size_in_bytes());
   }
 
-  font_access_manager_ = FontAccessManagerImpl::Create();
+  font_access_manager_ = FontAccessManager::Create();
   compute_pressure_manager_ = ComputePressureManager::Create();
 
   if (base::FeatureList::IsEnabled(kPrivacySandboxAggregationService)) {
@@ -1641,13 +1641,13 @@
   return attribution_manager_.get();
 }
 
-FontAccessManagerImpl* StoragePartitionImpl::GetFontAccessManager() {
+FontAccessManager* StoragePartitionImpl::GetFontAccessManager() {
   DCHECK(initialized_);
   return font_access_manager_.get();
 }
 
 void StoragePartitionImpl::SetFontAccessManagerForTesting(
-    std::unique_ptr<FontAccessManagerImpl> font_access_manager) {
+    std::unique_ptr<FontAccessManager> font_access_manager) {
   DCHECK(initialized_);
   DCHECK(font_access_manager);
   font_access_manager_ = std::move(font_access_manager);
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
index f0c5b5e..8b123a2 100644
--- a/content/browser/storage_partition_impl.h
+++ b/content/browser/storage_partition_impl.h
@@ -71,7 +71,7 @@
 class DevToolsBackgroundServicesContextImpl;
 class FileSystemAccessEntryFactory;
 class FileSystemAccessManagerImpl;
-class FontAccessManagerImpl;
+class FontAccessManager;
 class GeneratedCodeCacheContext;
 class HostZoomLevelContext;
 class IndexedDBControlWrapper;
@@ -243,11 +243,11 @@
   QuotaContext* GetQuotaContext();
   AttributionManagerImpl* GetAttributionManager();
   void SetFontAccessManagerForTesting(
-      std::unique_ptr<FontAccessManagerImpl> font_access_manager);
+      std::unique_ptr<FontAccessManager> font_access_manager);
   ComputePressureManager* GetComputePressureManager();
   std::string GetPartitionDomain();
   AggregationServiceImpl* GetAggregationService();
-  FontAccessManagerImpl* GetFontAccessManager();
+  FontAccessManager* GetFontAccessManager();
 #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
   MediaLicenseManager* GetMediaLicenseManager();
 #endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
@@ -635,7 +635,7 @@
   scoped_refptr<ContentIndexContextImpl> content_index_context_;
   scoped_refptr<NativeIOContextImpl> native_io_context_;
   std::unique_ptr<AttributionManagerImpl> attribution_manager_;
-  std::unique_ptr<FontAccessManagerImpl> font_access_manager_;
+  std::unique_ptr<FontAccessManager> font_access_manager_;
   std::unique_ptr<InterestGroupManagerImpl> interest_group_manager_;
   std::unique_ptr<BrowsingTopicsSiteDataManager>
       browsing_topics_site_data_manager_;
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index c21b0c44..143dc4b 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -479,7 +479,7 @@
   return set_holder->set();
 }
 
-// Returns true if |host| has the Window Placement permission granted.
+// Returns true if `host` has the Window Placement permission granted.
 bool IsWindowPlacementGranted(RenderFrameHost* host) {
   content::PermissionController* permission_controller =
       host->GetBrowserContext()->GetPermissionController();
diff --git a/content/browser/webid/fedcm_metrics.h b/content/browser/webid/fedcm_metrics.h
index 75bfc5a..6670fea 100644
--- a/content/browser/webid/fedcm_metrics.h
+++ b/content/browser/webid/fedcm_metrics.h
@@ -39,8 +39,9 @@
   kClientMetadataMissingPrivacyPolicyUrl,
   kThirdPartyCookiesBlocked,
   kDisabledInSettings,
+  kDisabledInFlags,
 
-  kMaxValue = kDisabledInSettings
+  kMaxValue = kDisabledInFlags
 };
 
 // This enum describes the status of a revocation call to the FedCM API.
@@ -58,8 +59,9 @@
   kManifestNoResponse,
   kManifestInvalidResponse,
   kDisabledInSettings,
+  kDisabledInFlags,
 
-  kMaxValue = kDisabledInSettings
+  kMaxValue = kDisabledInFlags
 };
 
 // Records the time from when a call to the API was made to when the accounts
diff --git a/content/browser/webid/federated_auth_request_impl.cc b/content/browser/webid/federated_auth_request_impl.cc
index 078010de..1e1fcba 100644
--- a/content/browser/webid/federated_auth_request_impl.cc
+++ b/content/browser/webid/federated_auth_request_impl.cc
@@ -257,6 +257,14 @@
   start_time_ = base::TimeTicks::Now();
   delay_timer_.Reset();
 
+  if (!IsFedCmEnabled()) {
+    RecordRequestIdTokenStatus(IdTokenStatus::kDisabledInFlags,
+                               render_frame_host_->GetPageUkmSourceId());
+    CompleteRequest(FederatedAuthRequestResult::kError, "",
+                    /*should_call_callback=*/false);
+    return;
+  }
+
   // TODO(npm): FedCM is currently restricted to contexts where third party
   // cookies are not blocked.  Once the privacy improvements for the API are
   // implemented, remove this restriction. See https://crbug.com/1304396.
@@ -298,6 +306,13 @@
   if (!auth_request_callback_)
     return;
 
+  if (!IsFedCmEnabled()) {
+    RecordRequestIdTokenStatus(IdTokenStatus::kDisabledInFlags,
+                               render_frame_host_->GetPageUkmSourceId());
+    CompleteRequest(FederatedAuthRequestResult::kError, "",
+                    /*should_call_callback=*/false);
+  }
+
   if (GetApiPermissionContext() &&
       !GetApiPermissionContext()->HasApiPermission()) {
     RecordRequestIdTokenStatus(IdTokenStatus::kDisabledInSettings,
@@ -333,6 +348,14 @@
   delay_timer_.Reset();
   revoke_callback_ = std::move(callback);
 
+  if (!IsFedCmEnabled()) {
+    RecordRevokeStatus(RevokeStatusForMetrics::kDisabledInFlags,
+                       render_frame_host_->GetPageUkmSourceId());
+    CompleteRevokeRequest(RevokeStatus::kError,
+                          /*should_call_callback=*/false);
+    return;
+  }
+
   network_manager_ = CreateNetworkManager(provider);
   if (!network_manager_) {
     RecordRevokeStatus(RevokeStatusForMetrics::kNoNetworkManager,
@@ -371,7 +394,8 @@
     blink::mojom::FederatedAuthRequest::LogoutCallback callback) {
   url::Origin idp_origin(url::Origin::Create(provider));
   auto* context = GetActiveSessionPermissionContext();
-  if (!context || !context->HasActiveSession(origin_, idp_origin, account_id)) {
+  if (!context || !context->HasActiveSession(origin_, idp_origin, account_id) ||
+      !IsFedCmEnabled()) {
     std::move(callback).Run(LogoutStatus::kNotLoggedIn);
     return;
   }
@@ -388,6 +412,11 @@
 void FederatedAuthRequestImpl::LogoutRps(
     std::vector<blink::mojom::LogoutRpsRequestPtr> logout_requests,
     blink::mojom::FederatedAuthRequest::LogoutRpsCallback callback) {
+  if (!IsFedCmEnabled()) {
+    std::move(callback).Run(LogoutRpsStatus::kError);
+    return;
+  }
+
   if (!IsFedCmIdpSignoutEnabled()) {
     std::move(callback).Run(LogoutRpsStatus::kError);
     return;
diff --git a/content/browser/webid/federated_auth_request_impl_unittest.cc b/content/browser/webid/federated_auth_request_impl_unittest.cc
index f11b6886..b126e3f7 100644
--- a/content/browser/webid/federated_auth_request_impl_unittest.cc
+++ b/content/browser/webid/federated_auth_request_impl_unittest.cc
@@ -65,8 +65,6 @@
 
 namespace {
 
-constexpr bool kPreferAutoSignIn = true;
-constexpr bool kNotPreferAutoSignIn = false;
 constexpr char kRpTestOrigin[] = "https://rp.example";
 constexpr char kIdpTestOrigin[] = "https://idp.example";
 constexpr char kProviderUrl[] = "https://idp.example";
@@ -116,20 +114,33 @@
 };
 
 typedef struct {
-  absl::optional<FetchStatus> accounts_response;
-  AccountList accounts;
-  absl::optional<FetchStatus> token_response;
-  absl::optional<bool> customized_dialog;
-} MockMediatedConfiguration;
-
-typedef struct {
-  const char* token;
-  absl::optional<FetchStatus> manifest_fetch_status;
-  absl::optional<MockClientIdConfiguration> client_metadata;
+  FetchStatus fetch_status;
   const char* accounts_endpoint;
   const char* token_endpoint;
   const char* client_metadata_endpoint;
-  MockMediatedConfiguration Mediated_conf;
+} MockManifest;
+
+enum FetchedEndpoint {
+  MANIFEST = 1,
+  CLIENT_METADATA = 1 << 1,
+  ACCOUNTS = 1 << 2,
+  TOKEN = 1 << 3
+};
+
+int FETCH_ENDPOINT_ALL = FetchedEndpoint::MANIFEST |
+                         FetchedEndpoint::CLIENT_METADATA |
+                         FetchedEndpoint::ACCOUNTS | FetchedEndpoint::TOKEN;
+
+typedef struct {
+  // Any combination of FetchedEndpoint flags.
+  int expected_fetched_endpoints;
+  const char* token;
+  MockManifest manifest;
+  MockClientIdConfiguration client_metadata;
+  FetchStatus accounts_response;
+  AccountList accounts;
+  FetchStatus token_response;
+  bool customized_dialog;
 } MockConfiguration;
 
 // absl::optional fields should be nullopt to prevent the corresponding
@@ -140,49 +151,35 @@
   MockConfiguration config;
 } AuthRequestTestCase;
 
-static const MockMediatedConfiguration kMediatedNoop{absl::nullopt, kAccounts,
-                                                     absl::nullopt};
-static const MockClientIdConfiguration kSuccessfulClientId{
+static const MockClientIdConfiguration kDefaultClientMetadata{
     FetchStatus::kSuccess, kPrivacyPolicyUrl, kTermsOfServiceUrl};
 
-static const MockClientIdConfiguration kClientMetadataHttpNotFound{
-    FetchStatus::kHttpNotFoundError, "", ""};
+static const RequestParameters kDefaultRequestParameters{
+    kIdpTestOrigin, kClientId, kNonce, /*prefer_auto_sign_in=*/false};
 
-static const MockClientIdConfiguration kClientMetadataNoResponse{
-    FetchStatus::kNoResponseError, "", ""};
+static const MockConfiguration kConfigurationValid{
+    FETCH_ENDPOINT_ALL,
+    kToken,
+    {
+        FetchStatus::kSuccess,
+        kAccountsEndpoint,
+        kTokenEndpoint,
+        kClientMetadataEndpoint,
+    },
+    kDefaultClientMetadata,
+    FetchStatus::kSuccess,
+    kAccounts,
+    FetchStatus::kSuccess,
+    false /* customized_dialog */};
 
-static const MockClientIdConfiguration kClientMetadataInvalidResponse{
-    FetchStatus::kInvalidResponseError, "", ""};
+static const RequestExpectations kExpectationSuccess{
+    RequestIdTokenStatus::kSuccess, FederatedAuthRequestResult::kSuccess,
+    kToken};
 
-static const MockClientIdConfiguration kClientMetadataNoPrivacyPolicyUrl{
-    FetchStatus::kSuccess, "", ""};
-
-// Error parsing FedCM manifest due to missing token endpoint.
-static const AuthRequestTestCase kMissingTokenEndpoint{
-    {kIdpTestOrigin, kClientId, kNonce},
-    {RequestIdTokenStatus::kError,
-     FederatedAuthRequestResult::kErrorFetchingManifestInvalidResponse,
-     kEmptyToken},
-    {kToken, FetchStatus::kSuccess, absl::nullopt, kAccountsEndpoint, "",
-     kClientMetadataEndpoint, kMediatedNoop}};
-
-// Error parsing FedCM manifest due to missing accounts endpoint.
-static const AuthRequestTestCase kMissingAccountsEndpoint{
-    {kIdpTestOrigin, kClientId, kNonce},
-    {RequestIdTokenStatus::kError,
-     FederatedAuthRequestResult::kErrorFetchingManifestInvalidResponse,
-     kEmptyToken},
-    {kToken, FetchStatus::kSuccess, absl::nullopt, "", kTokenEndpoint,
-     kClientMetadataEndpoint, kMediatedNoop}};
-
-// Error parsing FedCM manifest due to missing client metadata endpoint.
-static const AuthRequestTestCase kMissingClientMetadata{
-    {kIdpTestOrigin, kClientId, kNonce},
-    {RequestIdTokenStatus::kError,
-     FederatedAuthRequestResult::kErrorFetchingManifestInvalidResponse,
-     kEmptyToken},
-    {kToken, FetchStatus::kSuccess, absl::nullopt, kAccountsEndpoint,
-     kTokenEndpoint, "", kMediatedNoop}};
+MockClientIdConfiguration BuildClientMetadataErrorResponse(
+    FetchStatus fetch_status) {
+  return {fetch_status, "", ""};
+}
 
 // Helper class for receiving the mojo method callback.
 class AuthRequestCallbackHelper {
@@ -322,19 +319,52 @@
   }
   ~FederatedAuthRequestImplTest() override = default;
 
-  void RunAuthTest(const AuthRequestTestCase& test_case) {
-    CreateAuthRequest(GURL(test_case.inputs.provider));
-    SetMockExpectations(test_case);
-    auto auth_response =
-        PerformAuthRequest(test_case.inputs.client_id, test_case.inputs.nonce,
-                           test_case.inputs.prefer_auto_sign_in);
-    EXPECT_EQ(auth_response.first, test_case.expected.return_status);
-    EXPECT_EQ(auth_response.second, test_case.expected.token);
+  void SetUp() override {
+    RenderViewHostImplTestHarness::SetUp();
+    mock_sharing_permission_delegate_ =
+        std::make_unique<NiceMock<MockSharingPermissionDelegate>>();
+    mock_request_permission_delegate_ =
+        std::make_unique<NiceMock<MockRequestPermissionDelegate>>();
+    mock_active_session_permission_delegate_ =
+        std::make_unique<NiceMock<MockActiveSessionPermissionDelegate>>();
 
-    EXPECT_EQ(main_test_rfh()->GetFederatedAuthRequestIssueCount(
-                  test_case.expected.devtools_issue_status),
-              auth_response.first == RequestIdTokenStatus::kSuccess ? 0 : 1);
-    CheckConsoleMessages(test_case.expected.devtools_issue_status);
+    // `FederatedAuthRequestService` derives from `DocumentService` and
+    // controls its own lifetime.
+    federated_auth_request_impl_ =
+        (new FederatedAuthRequestService(
+             main_test_rfh(), request_remote_.BindNewPipeAndPassReceiver()))
+            ->GetImplForTesting();
+    auto mock_dialog_controller =
+        std::make_unique<NiceMock<MockIdentityRequestDialogController>>();
+    mock_dialog_controller_ = mock_dialog_controller.get();
+    federated_auth_request_impl_->SetDialogControllerForTests(
+        std::move(mock_dialog_controller));
+
+    federated_auth_request_impl_->SetSharingPermissionDelegateForTests(
+        mock_sharing_permission_delegate_.get());
+  }
+
+  void RunAuthTest(const RequestParameters& request_parameters,
+                   const RequestExpectations& expectation,
+                   const MockConfiguration& configuration) {
+    AuthRequestTestCase test_case = {request_parameters, expectation,
+                                     configuration};
+    SetupIdpNetworkRequestManager(GURL(request_parameters.provider));
+    SetMockExpectations(test_case);
+    auto auth_response = PerformAuthRequest(
+        GURL(request_parameters.provider), request_parameters.client_id,
+        request_parameters.nonce, request_parameters.prefer_auto_sign_in);
+    EXPECT_EQ(auth_response.first, expectation.return_status);
+    EXPECT_EQ(auth_response.second, expectation.token);
+
+    int issue_count = main_test_rfh()->GetFederatedAuthRequestIssueCount(
+        expectation.devtools_issue_status);
+    if (auth_response.first == RequestIdTokenStatus::kSuccess) {
+      EXPECT_EQ(0, issue_count);
+    } else {
+      EXPECT_LT(0, issue_count);
+    }
+    CheckConsoleMessages(expectation.devtools_issue_status);
   }
 
   void CheckConsoleMessages(FederatedAuthRequestResult devtools_issue_status) {
@@ -377,7 +407,10 @@
             {FederatedAuthRequestResult::
                  kErrorClientMetadataMissingPrivacyPolicyUrl,
              "Provider's client metadata is missing or has an invalid privacy "
-             "policy url."}};
+             "policy url."},
+            {FederatedAuthRequestResult::kErrorFetchingIdTokenInvalidResponse,
+             "Provider's id token is invalid."},
+        };
     std::vector<std::string> messages =
         RenderFrameHostTester::For(main_rfh())->GetConsoleMessages();
     absl::optional<std::string> expected_message =
@@ -390,45 +423,22 @@
     }
   }
 
-  FederatedAuthRequestImpl& CreateAuthRequest(const GURL& provider) {
-    provider_ = provider;
-    // `FederatedAuthRequestService` derives from `DocumentService` and
-    // controls its own lifetime.
-    auth_request_service_ = new FederatedAuthRequestService(
-        main_test_rfh(), request_remote_.BindNewPipeAndPassReceiver());
+  void SetupIdpNetworkRequestManager(const GURL& provider) {
     auto mock_request_manager =
         std::make_unique<NiceMock<MockIdpNetworkRequestManager>>(
             provider, url::Origin::Create(GURL(kRpTestOrigin)));
     mock_request_manager_ = mock_request_manager.get();
-    auth_request_service_->GetImplForTesting()->SetNetworkManagerForTests(
+    federated_auth_request_impl()->SetNetworkManagerForTests(
         std::move(mock_request_manager));
-    auto mock_dialog_controller =
-        std::make_unique<NiceMock<MockIdentityRequestDialogController>>();
-    mock_dialog_controller_ = mock_dialog_controller.get();
-    auth_request_service_->GetImplForTesting()->SetDialogControllerForTests(
-        std::move(mock_dialog_controller));
-
-    mock_request_permission_delegate_ =
-        std::make_unique<NiceMock<MockRequestPermissionDelegate>>();
-
-    mock_active_session_permission_delegate_ =
-        std::make_unique<NiceMock<MockActiveSessionPermissionDelegate>>();
-
-    mock_sharing_permission_delegate_ =
-        std::make_unique<NiceMock<MockSharingPermissionDelegate>>();
-
-    auth_request_service_->GetImplForTesting()
-        ->SetSharingPermissionDelegateForTests(
-            mock_sharing_permission_delegate_.get());
-    return *auth_request_service_->GetImplForTesting();
   }
 
   std::pair<RequestIdTokenStatus, absl::optional<std::string>>
-  PerformAuthRequest(const std::string& client_id,
+  PerformAuthRequest(const GURL& provider,
+                     const std::string& client_id,
                      const std::string& nonce,
                      bool prefer_auto_sign_in) {
     AuthRequestCallbackHelper auth_helper;
-    request_remote_->RequestIdToken(provider_, client_id, nonce,
+    request_remote_->RequestIdToken(provider, client_id, nonce,
                                     prefer_auto_sign_in,
                                     auth_helper.callback());
     auth_helper.WaitForCallback();
@@ -437,9 +447,8 @@
 
   LogoutRpsStatus PerformLogoutRequest(
       std::vector<LogoutRpsRequestPtr> logout_requests) {
-    auth_request_service_->GetImplForTesting()
-        ->SetActiveSessionPermissionDelegateForTests(
-            mock_active_session_permission_delegate_.get());
+    federated_auth_request_impl()->SetActiveSessionPermissionDelegateForTests(
+        mock_active_session_permission_delegate_.get());
 
     LogoutRpsRequestCallbackHelper logout_helper;
     request_remote_->LogoutRps(std::move(logout_requests),
@@ -456,22 +465,28 @@
     return revoke_helper.status();
   }
 
-  void SetMediatedMockExpectations(const MockMediatedConfiguration& conf,
+  bool IsExpectedFetched(MockConfiguration conf,
+                         FetchedEndpoint expected_endpoint) {
+    return (conf.expected_fetched_endpoints & expected_endpoint) != 0;
+  }
+
+  void SetMediatedMockExpectations(const MockConfiguration& conf,
                                    std::string token,
                                    bool prefer_auto_sign_in) {
-    if (conf.accounts_response) {
+    if (IsExpectedFetched(conf, FetchedEndpoint::ACCOUNTS)) {
       EXPECT_CALL(*mock_request_manager_, SendAccountsRequest(_, _, _))
           .WillOnce(Invoke(
               [&](const GURL&, const std::string&,
                   IdpNetworkRequestManager::AccountsRequestCallback callback) {
-                std::move(callback).Run(*conf.accounts_response, conf.accounts);
+                std::move(callback).Run(conf.accounts_response, conf.accounts);
               }));
     } else {
       EXPECT_CALL(*mock_request_manager_, SendAccountsRequest(_, _, _))
           .Times(0);
     }
 
-    if (conf.accounts_response == FetchStatus::kSuccess) {
+    if (IsExpectedFetched(conf, FetchedEndpoint::ACCOUNTS) &&
+        conf.accounts_response == FetchStatus::kSuccess) {
       if (!prefer_auto_sign_in && !conf.customized_dialog) {
         // Expects a dialog if prefer_auto_sign_in is not set by RP. However,
         // even though the bit is set we may not exercise the AutoSignIn flow.
@@ -500,7 +515,7 @@
           .Times(0);
     }
 
-    if (conf.token_response) {
+    if (IsExpectedFetched(conf, FetchedEndpoint::TOKEN)) {
       auto delivered_token =
           conf.token_response == FetchStatus::kSuccess ? token : std::string();
       EXPECT_CALL(*mock_request_manager_, SendTokenRequest(_, _, _, _))
@@ -508,7 +523,7 @@
               [=](const GURL& idp_signin_url, const std::string& account_id,
                   const std::string& request,
                   IdpNetworkRequestManager::TokenRequestCallback callback) {
-                std::move(callback).Run(*conf.token_response, delivered_token);
+                std::move(callback).Run(conf.token_response, delivered_token);
               }));
       task_environment()->FastForwardBy(base::Seconds(3));
     } else {
@@ -518,24 +533,25 @@
   }
 
   void SetMockExpectations(const AuthRequestTestCase& test_case) {
-    if (test_case.config.manifest_fetch_status) {
+    if (IsExpectedFetched(test_case.config, FetchedEndpoint::MANIFEST)) {
       EXPECT_CALL(*mock_request_manager_, FetchManifest(_, _, _))
           .WillOnce(Invoke(
               [&](absl::optional<int>, absl::optional<int>,
                   IdpNetworkRequestManager::FetchManifestCallback callback) {
                 IdpNetworkRequestManager::Endpoints endpoints;
-                endpoints.accounts = test_case.config.accounts_endpoint;
-                endpoints.token = test_case.config.token_endpoint;
+                endpoints.accounts =
+                    test_case.config.manifest.accounts_endpoint;
+                endpoints.token = test_case.config.manifest.token_endpoint;
                 endpoints.client_metadata =
-                    test_case.config.client_metadata_endpoint;
-                std::move(callback).Run(*test_case.config.manifest_fetch_status,
+                    test_case.config.manifest.client_metadata_endpoint;
+                std::move(callback).Run(test_case.config.manifest.fetch_status,
                                         endpoints, IdentityProviderMetadata());
               }));
     } else {
       EXPECT_CALL(*mock_request_manager_, FetchManifest(_, _, _)).Times(0);
     }
 
-    if (test_case.config.client_metadata) {
+    if (IsExpectedFetched(test_case.config, FetchedEndpoint::CLIENT_METADATA)) {
       EXPECT_CALL(*mock_request_manager_, FetchClientMetadata(_, _, _))
           .WillOnce(
               Invoke([&](const GURL&, const std::string& client_id,
@@ -543,19 +559,17 @@
                              callback) {
                 EXPECT_EQ(test_case.inputs.client_id, client_id);
                 std::move(callback).Run(
-                    test_case.config.client_metadata->fetch_status,
+                    test_case.config.client_metadata.fetch_status,
                     IdpNetworkRequestManager::ClientMetadata{
-                        test_case.config.client_metadata->privacy_policy_url,
-                        test_case.config.client_metadata
-                            ->terms_of_service_url});
+                        test_case.config.client_metadata.privacy_policy_url,
+                        test_case.config.client_metadata.terms_of_service_url});
               }));
     } else {
       EXPECT_CALL(*mock_request_manager_, FetchClientMetadata(_, _, _))
           .Times(0);
     }
 
-    SetMediatedMockExpectations(test_case.config.Mediated_conf,
-                                test_case.config.token,
+    SetMediatedMockExpectations(test_case.config, test_case.config.token,
                                 test_case.inputs.prefer_auto_sign_in);
   }
 
@@ -581,6 +595,10 @@
     }
   }
 
+  FederatedAuthRequestImpl* federated_auth_request_impl() {
+    return federated_auth_request_impl_;
+  }
+
   int& logout_return_count() { return logout_return_count_; }
   std::vector<LogoutRpsRequestPtr>& logout_requests() {
     return logout_requests_;
@@ -662,11 +680,12 @@
 
  protected:
   mojo::Remote<blink::mojom::FederatedAuthRequest> request_remote_;
-  // Note: `auth_request_service_` owns itself, and will generally be deleted
-  // with the TestRenderFrameHost is torn down at `TearDown()` time.
-  raw_ptr<FederatedAuthRequestService> auth_request_service_;
+  // |federated_auth_request_impl_| is owned by FederatedAuthRequestService
+  // which owns itself and will generally be deleted when the
+  // TestRenderFrameHost is torn down at `TearDown()` time.
+  raw_ptr<FederatedAuthRequestImpl> federated_auth_request_impl_;
 
-  // Owned by `auth_request_service_`.
+  // Owned by |federated_auth_request_impl_|.
   raw_ptr<NiceMock<MockIdpNetworkRequestManager>> mock_request_manager_;
   raw_ptr<NiceMock<MockIdentityRequestDialogController>>
       mock_dialog_controller_;
@@ -688,8 +707,6 @@
   // Storage for displayed accounts
   AccountList displayed_accounts_;
 
-  GURL provider_;
-
   base::HistogramTester histogram_tester_;
 
  private:
@@ -701,23 +718,20 @@
 
 // Test successful FedCM request.
 TEST_F(BasicFederatedAuthRequestImplTest, SuccessfulRequest) {
-  AuthRequestTestCase test_case = {
-      {kIdpTestOrigin, kClientId, kNonce},
-      {RequestIdTokenStatus::kSuccess, FederatedAuthRequestResult::kSuccess,
-       kToken},
-      {kToken,
-       FetchStatus::kSuccess,
-       kSuccessfulClientId,
-       kAccountsEndpoint,
-       kTokenEndpoint,
-       kClientMetadataEndpoint,
-       {FetchStatus::kSuccess, kAccounts, FetchStatus::kSuccess}}};
-  RunAuthTest(test_case);
+  RunAuthTest(kDefaultRequestParameters, kExpectationSuccess,
+              kConfigurationValid);
 }
 
 // Test that request fails if manifest is missing token endpoint.
 TEST_F(BasicFederatedAuthRequestImplTest, MissingTokenEndpoint) {
-  RunAuthTest(kMissingTokenEndpoint);
+  MockConfiguration configuration = kConfigurationValid;
+  configuration.manifest.token_endpoint = "";
+  configuration.expected_fetched_endpoints = FetchedEndpoint::MANIFEST;
+  RequestExpectations expectations = {
+      RequestIdTokenStatus::kError,
+      FederatedAuthRequestResult::kErrorFetchingManifestInvalidResponse,
+      kEmptyToken};
+  RunAuthTest(kDefaultRequestParameters, expectations, configuration);
 
   std::vector<std::string> messages =
       RenderFrameHostTester::For(main_rfh())->GetConsoleMessages();
@@ -732,7 +746,14 @@
 
 // Test that request fails if manifest is missing accounts endpoint.
 TEST_F(BasicFederatedAuthRequestImplTest, MissingAccountsEndpoint) {
-  RunAuthTest(kMissingAccountsEndpoint);
+  MockConfiguration configuration = kConfigurationValid;
+  configuration.manifest.accounts_endpoint = "";
+  configuration.expected_fetched_endpoints = FetchedEndpoint::MANIFEST;
+  RequestExpectations expectations = {
+      RequestIdTokenStatus::kError,
+      FederatedAuthRequestResult::kErrorFetchingManifestInvalidResponse,
+      kEmptyToken};
+  RunAuthTest(kDefaultRequestParameters, expectations, configuration);
 
   std::vector<std::string> messages =
       RenderFrameHostTester::For(main_rfh())->GetConsoleMessages();
@@ -747,7 +768,14 @@
 
 // Test that request fails if manifest is missing client metadata endpoint.
 TEST_F(BasicFederatedAuthRequestImplTest, MissingClientMetadataEndpoint) {
-  RunAuthTest(kMissingClientMetadata);
+  MockConfiguration configuration = kConfigurationValid;
+  configuration.manifest.client_metadata_endpoint = "";
+  configuration.expected_fetched_endpoints = FetchedEndpoint::MANIFEST;
+  RequestExpectations expectations = {
+      RequestIdTokenStatus::kError,
+      FederatedAuthRequestResult::kErrorFetchingManifestInvalidResponse,
+      kEmptyToken};
+  RunAuthTest(kDefaultRequestParameters, expectations, configuration);
 
   std::vector<std::string> messages =
       RenderFrameHostTester::For(main_rfh())->GetConsoleMessages();
@@ -763,120 +791,116 @@
 // Test that request fails if the accounts endpoint is in a different origin
 // than identity provider.
 TEST_F(BasicFederatedAuthRequestImplTest, AccountEndpointDifferentOriginIdp) {
-  AuthRequestTestCase test_case = {
-      {kIdpTestOrigin, kClientId, kNonce},
-      {RequestIdTokenStatus::kError,
-       FederatedAuthRequestResult::kErrorFetchingManifestInvalidResponse,
-       kEmptyToken},
-      {kToken, FetchStatus::kSuccess, absl::nullopt,
-       kCrossOriginAccountsEndpoint, kTokenEndpoint, kClientMetadataEndpoint,
-       kMediatedNoop}};
-  RunAuthTest(test_case);
+  MockConfiguration configuration = kConfigurationValid;
+  configuration.manifest.accounts_endpoint = kCrossOriginAccountsEndpoint;
+  configuration.expected_fetched_endpoints = FetchedEndpoint::MANIFEST;
+  RequestExpectations expectations = {
+      RequestIdTokenStatus::kError,
+      FederatedAuthRequestResult::kErrorFetchingManifestInvalidResponse,
+      kEmptyToken};
+  RunAuthTest(kDefaultRequestParameters, expectations, configuration);
 }
 
 // Test that request fails if accounts endpoint cannot be reached.
 TEST_F(BasicFederatedAuthRequestImplTest, AccountEndpointCannotBeReached) {
-  AuthRequestTestCase test_case = {
-      {kIdpTestOrigin, kClientId, kNonce},
-      {RequestIdTokenStatus::kError,
-       FederatedAuthRequestResult::kErrorFetchingAccountsNoResponse,
-       kEmptyToken},
-      {kEmptyToken,
-       FetchStatus::kSuccess,
-       kSuccessfulClientId,
-       kAccountsEndpoint,
-       kTokenEndpoint,
-       kClientMetadataEndpoint,
-       {FetchStatus::kNoResponseError, kAccounts, absl::nullopt}}};
-  RunAuthTest(test_case);
+  MockConfiguration configuration = kConfigurationValid;
+  configuration.accounts_response = FetchStatus::kNoResponseError;
+  configuration.expected_fetched_endpoints = FetchedEndpoint::MANIFEST |
+                                             FetchedEndpoint::CLIENT_METADATA |
+                                             FetchedEndpoint::ACCOUNTS;
+  RequestExpectations expectations = {
+      RequestIdTokenStatus::kError,
+      FederatedAuthRequestResult::kErrorFetchingAccountsNoResponse,
+      kEmptyToken};
+  RunAuthTest(kDefaultRequestParameters, expectations, configuration);
 }
 
 // Test that request fails if account endpoint response cannot be parsed.
 TEST_F(BasicFederatedAuthRequestImplTest, AccountsCannotBeParsed) {
-  AuthRequestTestCase test_case = {
-      {kIdpTestOrigin, kClientId, kNonce},
-      {RequestIdTokenStatus::kError,
-       FederatedAuthRequestResult::kErrorFetchingAccountsInvalidResponse,
-       kEmptyToken},
-      {kToken,
-       FetchStatus::kSuccess,
-       kSuccessfulClientId,
-       kAccountsEndpoint,
-       kTokenEndpoint,
-       kClientMetadataEndpoint,
-       {FetchStatus::kInvalidResponseError, kAccounts, absl::nullopt}}};
-  RunAuthTest(test_case);
+  MockConfiguration configuration = kConfigurationValid;
+  configuration.accounts_response = FetchStatus::kInvalidResponseError;
+  configuration.expected_fetched_endpoints = FetchedEndpoint::MANIFEST |
+                                             FetchedEndpoint::CLIENT_METADATA |
+                                             FetchedEndpoint::ACCOUNTS;
+  RequestExpectations expectations = {
+      RequestIdTokenStatus::kError,
+      FederatedAuthRequestResult::kErrorFetchingAccountsInvalidResponse,
+      kEmptyToken};
+  RunAuthTest(kDefaultRequestParameters, expectations, configuration);
 }
 
 // Test that request fails if client metadata cannot be found.
 TEST_F(BasicFederatedAuthRequestImplTest, ClientMetadataNotFound) {
-  AuthRequestTestCase test_case = {
-      {kIdpTestOrigin, kClientId, kNonce},
-      {RequestIdTokenStatus::kError,
-       FederatedAuthRequestResult::kErrorFetchingClientMetadataHttpNotFound,
-       kEmptyToken},
-      {kToken, FetchStatus::kSuccess, kClientMetadataHttpNotFound,
-       kAccountsEndpoint, kTokenEndpoint, kClientMetadataEndpoint,
-       kMediatedNoop}};
-  RunAuthTest(test_case);
+  MockConfiguration configuration = kConfigurationValid;
+  configuration.client_metadata =
+      BuildClientMetadataErrorResponse(FetchStatus::kHttpNotFoundError);
+  configuration.expected_fetched_endpoints =
+      FetchedEndpoint::MANIFEST | FetchedEndpoint::CLIENT_METADATA;
+  RequestExpectations expectations = {
+      RequestIdTokenStatus::kError,
+      FederatedAuthRequestResult::kErrorFetchingClientMetadataHttpNotFound,
+      kEmptyToken};
+  RunAuthTest(kDefaultRequestParameters, expectations, configuration);
 }
 
 // Test that request fails if client metadata endpoint returns empty response.
 TEST_F(BasicFederatedAuthRequestImplTest, ClientMetadataEmptyResponse) {
-  AuthRequestTestCase test_case = {
-      {kIdpTestOrigin, kClientId, kNonce},
-      {RequestIdTokenStatus::kError,
-       FederatedAuthRequestResult::kErrorFetchingClientMetadataNoResponse,
-       kEmptyToken},
-      {kToken, FetchStatus::kSuccess, kClientMetadataNoResponse,
-       kAccountsEndpoint, kTokenEndpoint, kClientMetadataEndpoint,
-       kMediatedNoop}};
-  RunAuthTest(test_case);
+  MockConfiguration configuration = kConfigurationValid;
+  configuration.client_metadata =
+      BuildClientMetadataErrorResponse(FetchStatus::kNoResponseError);
+  configuration.expected_fetched_endpoints =
+      FetchedEndpoint::MANIFEST | FetchedEndpoint::CLIENT_METADATA;
+  RequestExpectations expectations = {
+      RequestIdTokenStatus::kError,
+      FederatedAuthRequestResult::kErrorFetchingClientMetadataNoResponse,
+      kEmptyToken};
+  RunAuthTest(kDefaultRequestParameters, expectations, configuration);
 }
 
 // Test that request fails if client metadata returns invalid response.
 TEST_F(BasicFederatedAuthRequestImplTest, ClientMetadataInvalidResponse) {
-  AuthRequestTestCase test_case = {
-      {kIdpTestOrigin, kClientId, kNonce},
-      {RequestIdTokenStatus::kError,
-       FederatedAuthRequestResult::kErrorFetchingClientMetadataInvalidResponse,
-       kEmptyToken},
-      {kToken, FetchStatus::kSuccess, kClientMetadataInvalidResponse,
-       kAccountsEndpoint, kTokenEndpoint, kClientMetadataEndpoint,
-       kMediatedNoop}};
-  RunAuthTest(test_case);
+  MockConfiguration configuration = kConfigurationValid;
+  configuration.client_metadata =
+      BuildClientMetadataErrorResponse(FetchStatus::kInvalidResponseError);
+  configuration.expected_fetched_endpoints =
+      FetchedEndpoint::MANIFEST | FetchedEndpoint::CLIENT_METADATA;
+  RequestExpectations expectations = {
+      RequestIdTokenStatus::kError,
+      FederatedAuthRequestResult::kErrorFetchingClientMetadataInvalidResponse,
+      kEmptyToken};
+  RunAuthTest(kDefaultRequestParameters, expectations, configuration);
 }
 
 // Test that request fails if client metadata does not contain a privacy policy
 // URL.
 TEST_F(BasicFederatedAuthRequestImplTest, ClientMetadataNoPrivacyUrl) {
-  AuthRequestTestCase test_case = {
-      {kIdpTestOrigin, kClientId, kNonce},
-      {RequestIdTokenStatus::kError,
-       FederatedAuthRequestResult::kErrorClientMetadataMissingPrivacyPolicyUrl,
-       kEmptyToken},
-      {kToken, FetchStatus::kSuccess, kClientMetadataNoPrivacyPolicyUrl,
-       kAccountsEndpoint, kTokenEndpoint, kClientMetadataEndpoint,
-       kMediatedNoop}};
-  RunAuthTest(test_case);
+  MockConfiguration configuration = kConfigurationValid;
+  configuration.client_metadata = kDefaultClientMetadata;
+  configuration.client_metadata.privacy_policy_url = "";
+  configuration.client_metadata.terms_of_service_url = "";
+  configuration.expected_fetched_endpoints =
+      FetchedEndpoint::MANIFEST | FetchedEndpoint::CLIENT_METADATA;
+  RequestExpectations expectations = {
+      RequestIdTokenStatus::kError,
+      FederatedAuthRequestResult::kErrorClientMetadataMissingPrivacyPolicyUrl,
+      kEmptyToken};
+  RunAuthTest(kDefaultRequestParameters, expectations, configuration);
 }
 
 // Test that request fails if all of the endpoints in the manifest are invalid.
 TEST_F(BasicFederatedAuthRequestImplTest, AllInvalidEndpoints) {
   // Both an empty url and cross origin urls are invalid endpoints.
-  AuthRequestTestCase test_case = {
-      {kIdpTestOrigin, kClientId, kNonce},
-      {RequestIdTokenStatus::kError,
-       FederatedAuthRequestResult::kErrorFetchingManifestInvalidResponse,
-       kEmptyToken},
-      {kToken, FetchStatus::kSuccess, absl::nullopt,
-       "https://cross-origin-1.com", "", "https://cross-origin-2.com",
-       kMediatedNoop}};
-  CreateAuthRequest(GURL(test_case.inputs.provider));
-  SetMockExpectations(test_case);
-  auto auth_response =
-      PerformAuthRequest(test_case.inputs.client_id, test_case.inputs.nonce,
-                         test_case.inputs.prefer_auto_sign_in);
+  MockConfiguration configuration = kConfigurationValid;
+  configuration.manifest.accounts_endpoint = "https://cross-origin-1.com";
+  configuration.manifest.token_endpoint = "";
+  configuration.manifest.client_metadata_endpoint =
+      "https://cross-origin-2.com";
+  configuration.expected_fetched_endpoints = FetchedEndpoint::MANIFEST;
+  RequestExpectations expectations = {
+      RequestIdTokenStatus::kError,
+      FederatedAuthRequestResult::kErrorFetchingManifestInvalidResponse,
+      kEmptyToken};
+  RunAuthTest(kDefaultRequestParameters, expectations, configuration);
   std::vector<std::string> messages =
       RenderFrameHostTester::For(main_rfh())->GetConsoleMessages();
   ASSERT_EQ(2U, messages.size());
@@ -897,7 +921,7 @@
       features::kFedCm,
       {{features::kFedCmIdpSignoutFieldTrialParamName, "true"}});
 
-  CreateAuthRequest(GURL(kIdpTestOrigin));
+  SetupIdpNetworkRequestManager(GURL(kIdpTestOrigin));
 
   auto request1 = MakeLogoutRequest("https://rp1.example", "user123");
   logout_requests().push_back(std::move(request1));
@@ -922,7 +946,7 @@
       features::kFedCm,
       {{features::kFedCmIdpSignoutFieldTrialParamName, "true"}});
 
-  CreateAuthRequest(GURL(kIdpTestOrigin));
+  SetupIdpNetworkRequestManager(GURL(kIdpTestOrigin));
 
   // logout_return_count is not set here because there should be no
   // attempt at dispatch.
@@ -937,7 +961,7 @@
 
 // Test Logout method with an empty endpoint vector.
 TEST_F(BasicFederatedAuthRequestImplTest, LogoutNoEndpoints) {
-  CreateAuthRequest(GURL(kIdpTestOrigin));
+  SetupIdpNetworkRequestManager(GURL(kIdpTestOrigin));
 
   SetLogoutMockExpectations();
   auto logout_response = PerformLogoutRequest(std::move(logout_requests()));
@@ -945,64 +969,15 @@
 }
 
 // Tests for Login State
-
-// Successful mediated flow with one account.
-static const AuthRequestTestCase kSuccessfulMediatedSignUpTestCase{
-    {kIdpTestOrigin, kClientId, kNonce, kNotPreferAutoSignIn},
-    {RequestIdTokenStatus::kSuccess, FederatedAuthRequestResult::kSuccess,
-     kToken},
-    {kToken,
-     FetchStatus::kSuccess,
-     kSuccessfulClientId,
-     kAccountsEndpoint,
-     kTokenEndpoint,
-     kClientMetadataEndpoint,
-     {FetchStatus::kSuccess, kAccounts, FetchStatus::kSuccess}}};
-
-// Failed mediated flow with one account.
-static const AuthRequestTestCase kFailedMediatedSignUpTestCase{
-    {kIdpTestOrigin, kClientId, kNonce, kNotPreferAutoSignIn},
-    {RequestIdTokenStatus::kSuccess, FederatedAuthRequestResult::kSuccess,
-     kToken},
-    {kToken,
-     FetchStatus::kSuccess,
-     kSuccessfulClientId,
-     kAccountsEndpoint,
-     kTokenEndpoint,
-     kClientMetadataEndpoint,
-     {FetchStatus::kSuccess, kAccounts, FetchStatus::kInvalidResponseError}}};
-
-// Successful mediated flow with one account.
-static const AuthRequestTestCase kSuccessfulMediatedAutoSignInTestCase{
-    {kIdpTestOrigin, kClientId, kNonce, kPreferAutoSignIn},
-    {RequestIdTokenStatus::kSuccess, FederatedAuthRequestResult::kSuccess,
-     kToken},
-    {kToken,
-     FetchStatus::kSuccess,
-     kSuccessfulClientId,
-     kAccountsEndpoint,
-     kTokenEndpoint,
-     kClientMetadataEndpoint,
-     {FetchStatus::kSuccess, kAccounts, FetchStatus::kSuccess}}};
-
 TEST_F(BasicFederatedAuthRequestImplTest,
        LoginStateShouldBeSignUpForFirstTimeUser) {
-  const auto& test_case = kSuccessfulMediatedSignUpTestCase;
-  CreateAuthRequest(GURL(test_case.inputs.provider));
-  SetMockExpectations(test_case);
-  auto auth_response =
-      PerformAuthRequest(test_case.inputs.client_id, test_case.inputs.nonce,
-                         test_case.inputs.prefer_auto_sign_in);
-
+  RunAuthTest(kDefaultRequestParameters, kExpectationSuccess,
+              kConfigurationValid);
   EXPECT_EQ(LoginState::kSignUp, displayed_accounts()[0].login_state);
 }
 
 TEST_F(BasicFederatedAuthRequestImplTest,
        LoginStateShouldBeSignInForReturningUser) {
-  const auto& test_case = kSuccessfulMediatedSignUpTestCase;
-  CreateAuthRequest(GURL(test_case.inputs.provider));
-  SetMockExpectations(test_case);
-
   // Pretend the sharing permission has been granted for this account.
   //
   // TODO(majidvp): Ideally we would use the kRpTestOrigin for second argument
@@ -1012,19 +987,13 @@
               HasSharingPermission(_, url::Origin::Create(GURL(kIdpTestOrigin)),
                                    "1234"))
       .WillOnce(Return(true));
-
-  auto auth_response =
-      PerformAuthRequest(test_case.inputs.client_id, test_case.inputs.nonce,
-                         test_case.inputs.prefer_auto_sign_in);
+  RunAuthTest(kDefaultRequestParameters, kExpectationSuccess,
+              kConfigurationValid);
   EXPECT_EQ(LoginState::kSignIn, displayed_accounts()[0].login_state);
 }
 
 TEST_F(BasicFederatedAuthRequestImplTest,
        LoginStateSuccessfulSignUpGrantsSharingPermission) {
-  const auto& test_case = kSuccessfulMediatedSignUpTestCase;
-  CreateAuthRequest(GURL(test_case.inputs.provider));
-  SetMockExpectations(test_case);
-
   EXPECT_CALL(*mock_sharing_permission_delegate_, HasSharingPermission(_, _, _))
       .WillOnce(Return(false));
   // TODO(majidvp): Ideally we would use the kRpTestOrigin for second argument
@@ -1034,27 +1003,25 @@
               GrantSharingPermission(
                   _, url::Origin::Create(GURL(kIdpTestOrigin)), "1234"))
       .Times(1);
-
-  auto auth_response =
-      PerformAuthRequest(test_case.inputs.client_id, test_case.inputs.nonce,
-                         test_case.inputs.prefer_auto_sign_in);
+  RunAuthTest(kDefaultRequestParameters, kExpectationSuccess,
+              kConfigurationValid);
 }
 
 TEST_F(BasicFederatedAuthRequestImplTest,
        LoginStateFailedSignUpNotGrantSharingPermission) {
-  const auto& test_case = kFailedMediatedSignUpTestCase;
-  CreateAuthRequest(GURL(test_case.inputs.provider));
-  SetMockExpectations(test_case);
-
   EXPECT_CALL(*mock_sharing_permission_delegate_, HasSharingPermission(_, _, _))
       .WillOnce(Return(false));
   EXPECT_CALL(*mock_sharing_permission_delegate_,
               GrantSharingPermission(_, _, _))
       .Times(0);
 
-  auto auth_response =
-      PerformAuthRequest(test_case.inputs.client_id, test_case.inputs.nonce,
-                         test_case.inputs.prefer_auto_sign_in);
+  MockConfiguration configuration = kConfigurationValid;
+  configuration.token_response = FetchStatus::kInvalidResponseError;
+  RequestExpectations expectations = {
+      RequestIdTokenStatus::kError,
+      FederatedAuthRequestResult::kErrorFetchingIdTokenInvalidResponse,
+      kEmptyToken};
+  RunAuthTest(kDefaultRequestParameters, expectations, configuration);
 }
 
 TEST_F(BasicFederatedAuthRequestImplTest, AutoSignInForReturningUser) {
@@ -1064,9 +1031,6 @@
       {{features::kFedCmAutoSigninFieldTrialParamName, "true"}});
 
   AccountList displayed_accounts;
-  const auto& test_case = kSuccessfulMediatedAutoSignInTestCase;
-  CreateAuthRequest(GURL(test_case.inputs.provider));
-  SetMockExpectations(test_case);
 
   // Pretend the sharing permission has been granted for this account.
   //
@@ -1092,14 +1056,13 @@
             std::move(on_selected).Run(accounts[0].id, /*is_sign_in=*/true);
           }));
 
-  EXPECT_EQ(test_case.config.Mediated_conf.accounts.size(), 1u);
-  auto auth_response =
-      PerformAuthRequest(test_case.inputs.client_id, test_case.inputs.nonce,
-                         test_case.inputs.prefer_auto_sign_in);
+  ASSERT_EQ(kConfigurationValid.accounts.size(), 1u);
+  RequestParameters request_parameters = kDefaultRequestParameters;
+  request_parameters.prefer_auto_sign_in = true;
+  RunAuthTest(request_parameters, kExpectationSuccess, kConfigurationValid);
 
   ASSERT_FALSE(displayed_accounts.empty());
   EXPECT_EQ(displayed_accounts[0].login_state, LoginState::kSignIn);
-  EXPECT_EQ(auth_response.second.value(), kToken);
 }
 
 TEST_F(BasicFederatedAuthRequestImplTest, AutoSignInForFirstTimeUser) {
@@ -1109,8 +1072,6 @@
       {{features::kFedCmAutoSigninFieldTrialParamName, "true"}});
 
   AccountList displayed_accounts;
-  const auto& test_case = kSuccessfulMediatedAutoSignInTestCase;
-  CreateAuthRequest(GURL(test_case.inputs.provider));
   EXPECT_CALL(*mock_dialog_controller(),
               ShowAccountsDialog(_, _, _, _, _, _, _))
       .WillOnce(Invoke(
@@ -1125,14 +1086,12 @@
             std::move(on_selected).Run(accounts[0].id, /*is_sign_in=*/true);
           }));
 
-  SetMockExpectations(test_case);
-  auto auth_response =
-      PerformAuthRequest(test_case.inputs.client_id, test_case.inputs.nonce,
-                         test_case.inputs.prefer_auto_sign_in);
+  RequestParameters request_parameters = kDefaultRequestParameters;
+  request_parameters.prefer_auto_sign_in = true;
+  RunAuthTest(request_parameters, kExpectationSuccess, kConfigurationValid);
 
   ASSERT_FALSE(displayed_accounts.empty());
   EXPECT_EQ(displayed_accounts[0].login_state, LoginState::kSignUp);
-  EXPECT_EQ(auth_response.second.value(), kToken);
 }
 
 TEST_F(BasicFederatedAuthRequestImplTest, AutoSignInWithScreenReader) {
@@ -1145,9 +1104,6 @@
       ui::AXMode::kScreenReader);
 
   AccountList displayed_accounts;
-  const auto& test_case = kSuccessfulMediatedAutoSignInTestCase;
-  CreateAuthRequest(GURL(test_case.inputs.provider));
-  SetMockExpectations(test_case);
 
   // Pretend the sharing permission has been granted for this account.
   //
@@ -1174,21 +1130,20 @@
             std::move(on_selected).Run(accounts[0].id, /*is_sign_in=*/true);
           }));
 
-  EXPECT_EQ(test_case.config.Mediated_conf.accounts.size(), 1u);
-  auto auth_response =
-      PerformAuthRequest(test_case.inputs.client_id, test_case.inputs.nonce,
-                         test_case.inputs.prefer_auto_sign_in);
+  EXPECT_EQ(kConfigurationValid.accounts.size(), 1u);
+  RequestParameters request_parameters = kDefaultRequestParameters;
+  request_parameters.prefer_auto_sign_in = true;
+  RunAuthTest(request_parameters, kExpectationSuccess, kConfigurationValid);
 
   ASSERT_FALSE(displayed_accounts.empty());
   EXPECT_EQ(displayed_accounts[0].login_state, LoginState::kSignIn);
-  EXPECT_EQ(auth_response.second.value(), kToken);
 }
 
 TEST_F(FederatedAuthRequestImplTest, Revoke) {
   constexpr char kHint[] = "foo@bar.com";
 
-  auto& auth_request = CreateAuthRequest(GURL(kProviderUrl));
-  auth_request.SetRequestPermissionDelegateForTests(
+  SetupIdpNetworkRequestManager(GURL(kProviderUrl));
+  federated_auth_request_impl()->SetRequestPermissionDelegateForTests(
       mock_request_permission_delegate_.get());
 
   // Pretend the request permission has been granted for this account.
@@ -1237,8 +1192,8 @@
 TEST_F(FederatedAuthRequestImplTest, RevokeNoPermission) {
   constexpr char kHint[] = "foo@bar.com";
 
-  auto& auth_request = CreateAuthRequest(GURL(kProviderUrl));
-  auth_request.SetRequestPermissionDelegateForTests(
+  SetupIdpNetworkRequestManager(GURL(kProviderUrl));
+  federated_auth_request_impl()->SetRequestPermissionDelegateForTests(
       mock_request_permission_delegate_.get());
 
   // Pretend the request permission has been denied for this account.
@@ -1263,20 +1218,13 @@
 }
 
 TEST_F(BasicFederatedAuthRequestImplTest, MetricsForSuccessfulSignUpCase) {
-  const auto& test_case = kSuccessfulMediatedSignUpTestCase;
-  CreateAuthRequest(GURL(test_case.inputs.provider));
-  SetMockExpectations(test_case);
-
-  EXPECT_EQ(test_case.config.Mediated_conf.accounts.size(), 1u);
-
   base::RunLoop ukm_loop;
   ukm_recorder()->SetOnAddEntryCallback(Entry::kEntryName,
                                         ukm_loop.QuitClosure());
 
-  auto auth_response =
-      PerformAuthRequest(test_case.inputs.client_id, test_case.inputs.nonce,
-                         test_case.inputs.prefer_auto_sign_in);
-  EXPECT_EQ(auth_response.second.value(), kToken);
+  EXPECT_EQ(kConfigurationValid.accounts.size(), 1u);
+  RunAuthTest(kDefaultRequestParameters, kExpectationSuccess,
+              kConfigurationValid);
 
   ukm_loop.Run();
 
@@ -1302,10 +1250,6 @@
 }
 
 TEST_F(BasicFederatedAuthRequestImplTest, MetricsForSuccessfulSignInCase) {
-  const auto& test_case = kSuccessfulMediatedSignUpTestCase;
-  CreateAuthRequest(GURL(test_case.inputs.provider));
-  SetMockExpectations(test_case);
-
   // Pretends that the sharing permission has been granted for this account.
   EXPECT_CALL(*mock_sharing_permission_delegate_,
               HasSharingPermission(_, url::Origin::Create(GURL(kIdpTestOrigin)),
@@ -1316,9 +1260,8 @@
   ukm_recorder()->SetOnAddEntryCallback(Entry::kEntryName,
                                         ukm_loop.QuitClosure());
 
-  auto auth_response =
-      PerformAuthRequest(test_case.inputs.client_id, test_case.inputs.nonce,
-                         test_case.inputs.prefer_auto_sign_in);
+  RunAuthTest(kDefaultRequestParameters, kExpectationSuccess,
+              kConfigurationValid);
   EXPECT_EQ(LoginState::kSignIn, displayed_accounts()[0].login_state);
 
   ukm_loop.Run();
@@ -1349,21 +1292,6 @@
   base::HistogramTester histogram_tester_;
 
   AccountList displayed_accounts;
-  const AuthRequestTestCase test_case = {
-      {kIdpTestOrigin, kClientId, kNonce, kNotPreferAutoSignIn},
-      {RequestIdTokenStatus::kSuccess, FederatedAuthRequestResult::kSuccess,
-       kToken},
-      {kToken,
-       FetchStatus::kSuccess,
-       kSuccessfulClientId,
-       kAccountsEndpoint,
-       kTokenEndpoint,
-       kClientMetadataEndpoint,
-       {FetchStatus::kSuccess, kAccounts, absl::nullopt,
-        /*customized_dialog=*/true}}};
-  CreateAuthRequest(GURL(test_case.inputs.provider));
-  SetMockExpectations(test_case);
-
   EXPECT_CALL(*mock_dialog_controller(),
               ShowAccountsDialog(_, _, _, _, _, _, _))
       .WillOnce(Invoke(
@@ -1378,15 +1306,17 @@
             std::move(on_selected).Run("", /*is_sign_in=*/false);
           }));
 
-  EXPECT_EQ(test_case.config.Mediated_conf.accounts.size(), 1u);
-
   base::RunLoop ukm_loop;
   ukm_recorder()->SetOnAddEntryCallback(Entry::kEntryName,
                                         ukm_loop.QuitClosure());
 
-  auto auth_response =
-      PerformAuthRequest(test_case.inputs.client_id, test_case.inputs.nonce,
-                         test_case.inputs.prefer_auto_sign_in);
+  EXPECT_EQ(kConfigurationValid.accounts.size(), 1u);
+  MockConfiguration configuration = kConfigurationValid;
+  configuration.expected_fetched_endpoints &= ~FetchedEndpoint::TOKEN;
+  configuration.customized_dialog = true;
+  RequestExpectations expectations = {RequestIdTokenStatus::kError,
+                                      FederatedAuthRequestResult::kError, ""};
+  RunAuthTest(kDefaultRequestParameters, expectations, configuration);
 
   ukm_loop.Run();
 
@@ -1420,19 +1350,14 @@
   web_contents_impl->UpdateWebContentsVisibility(Visibility::VISIBLE);
   ASSERT_EQ(web_contents_impl->GetVisibility(), Visibility::VISIBLE);
 
-  const auto& test_case = kSuccessfulMediatedSignUpTestCase;
-  CreateAuthRequest(GURL(test_case.inputs.provider));
-  SetMockExpectations(test_case);
-
   // Pretends that the sharing permission has been granted for this account.
   EXPECT_CALL(*mock_sharing_permission_delegate_,
               HasSharingPermission(_, url::Origin::Create(GURL(kIdpTestOrigin)),
                                    "1234"))
       .WillOnce(Return(true));
 
-  auto auth_response =
-      PerformAuthRequest(test_case.inputs.client_id, test_case.inputs.nonce,
-                         test_case.inputs.prefer_auto_sign_in);
+  RunAuthTest(kDefaultRequestParameters, kExpectationSuccess,
+              kConfigurationValid);
   EXPECT_EQ(LoginState::kSignIn, displayed_accounts()[0].login_state);
 
   histogram_tester_.ExpectUniqueSample("Blink.FedCm.WebContentsVisible", 1, 1);
@@ -1446,46 +1371,33 @@
   web_contents_impl->UpdateWebContentsVisibility(Visibility::VISIBLE);
   ASSERT_EQ(web_contents_impl->GetVisibility(), Visibility::VISIBLE);
 
-  const AuthRequestTestCase test_case = {
-      {kIdpTestOrigin, kClientId, kNonce, kNotPreferAutoSignIn},
-      {RequestIdTokenStatus::kSuccess, FederatedAuthRequestResult::kSuccess,
-       kToken},
-      {kToken,
-       FetchStatus::kSuccess,
-       kSuccessfulClientId,
-       kAccountsEndpoint,
-       kTokenEndpoint,
-       kClientMetadataEndpoint,
-       {FetchStatus::kSuccess, kAccounts, absl::nullopt,
-        /*customized_dialog=*/true}}};
-  CreateAuthRequest(GURL(test_case.inputs.provider));
-  SetMockExpectations(test_case);
-
   // Sets the WebContents to invisible
   web_contents_impl->UpdateWebContentsVisibility(Visibility::HIDDEN);
   ASSERT_NE(web_contents_impl->GetVisibility(), Visibility::VISIBLE);
 
-  PerformAuthRequest(test_case.inputs.client_id, test_case.inputs.nonce,
-                     test_case.inputs.prefer_auto_sign_in);
+  MockConfiguration configuration = kConfigurationValid;
+  configuration.expected_fetched_endpoints &= ~FetchedEndpoint::TOKEN;
+  configuration.customized_dialog = true;
+  RequestExpectations expectations = {RequestIdTokenStatus::kError,
+                                      FederatedAuthRequestResult::kError, ""};
+  RunAuthTest(kDefaultRequestParameters, expectations, configuration);
 
   histogram_tester_.ExpectUniqueSample("Blink.FedCm.WebContentsVisible", 0, 1);
 }
 
 TEST_F(BasicFederatedAuthRequestImplTest,
        DisabledWhenThirdPartyCookiesBlocked) {
-  const auto& test_case = kSuccessfulMediatedAutoSignInTestCase;
-  CreateAuthRequest(GURL(test_case.inputs.provider));
   NiceMock<MockApiPermissionDelegate> mock_api_permission_delegate;
-  auth_request_service_->GetImplForTesting()->SetApiPermissionDelegateForTests(
+  federated_auth_request_impl()->SetApiPermissionDelegateForTests(
       &mock_api_permission_delegate);
-  // Not calling SetMockExpectations(test_case) because the testcase is rejected
-  // early on, before the network manager is actually created.
   EXPECT_CALL(mock_api_permission_delegate, AreThirdPartyCookiesBlocked())
       .WillOnce(Return(true));
-  auto auth_response =
-      PerformAuthRequest(test_case.inputs.client_id, test_case.inputs.nonce,
-                         test_case.inputs.prefer_auto_sign_in);
-  EXPECT_EQ(auth_response.first, RequestIdTokenStatus::kError);
+
+  MockConfiguration configuration = kConfigurationValid;
+  configuration.expected_fetched_endpoints = 0;
+  RequestExpectations expectations = {RequestIdTokenStatus::kError,
+                                      FederatedAuthRequestResult::kError, ""};
+  RunAuthTest(kDefaultRequestParameters, expectations, configuration);
 
   histogram_tester_.ExpectUniqueSample("Blink.FedCm.Status.RequestIdToken",
                                        IdTokenStatus::kThirdPartyCookiesBlocked,
@@ -1493,4 +1405,19 @@
   ExpectRequestIdTokenStatusUKM(IdTokenStatus::kThirdPartyCookiesBlocked);
 }
 
+TEST_F(BasicFederatedAuthRequestImplTest, MetricsForFeatureIsDisabled) {
+  base::test::ScopedFeatureList list;
+  list.InitAndDisableFeature(features::kFedCm);
+
+  MockConfiguration configuration = kConfigurationValid;
+  configuration.expected_fetched_endpoints = 0;
+  RequestExpectations expectations = {RequestIdTokenStatus::kError,
+                                      FederatedAuthRequestResult::kError, ""};
+  RunAuthTest(kDefaultRequestParameters, expectations, configuration);
+
+  histogram_tester_.ExpectUniqueSample("Blink.FedCm.Status.RequestIdToken",
+                                       IdTokenStatus::kDisabledInFlags, 1);
+  ExpectRequestIdTokenStatusUKM(IdTokenStatus::kDisabledInFlags);
+}
+
 }  // namespace content
diff --git a/content/browser/webid/federated_auth_request_service.cc b/content/browser/webid/federated_auth_request_service.cc
index fcb214a..965b9c3 100644
--- a/content/browser/webid/federated_auth_request_service.cc
+++ b/content/browser/webid/federated_auth_request_service.cc
@@ -18,9 +18,9 @@
     mojo::PendingReceiver<blink::mojom::FederatedAuthRequest> receiver) {
   DCHECK(host);
 
-  // TODO(kenrb): This should also be verified in the renderer process before
-  // the mojo method is invoked, causing the promise to be rejected.
-  // https://crbug.com/1141125
+  // TODO(yigu): Once cross-orign support is implemented, we should reject the
+  // request with specific error messages instead of crashing the renderer.
+  // https://crbug.com/1286839.
   // It is safe to access host->GetLastCommittedOrigin during construction
   // but DocumentService::origin() should be used thereafter.
   if (!IsSameOriginWithAncestors(host, host->GetLastCommittedOrigin())) {
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 9ee1655..0a49c57d 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -414,6 +414,8 @@
           {"ClientHintPartitiondCookies",
            blink::features::kClientHintsPartitionedCookies},
           {"WindowPlacement", blink::features::kWindowPlacement},
+          {"WindowPlacementFullscreenOnScreensChange",
+           blink::features::kWindowPlacementFullscreenOnScreensChange},
           {"EventPath", blink::features::kEventPath},
       };
   for (const auto& mapping : runtimeFeatureNameToChromiumFeatureMapping) {
diff --git a/content/public/android/java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java b/content/public/android/java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java
index 72505bc..4c7c1249 100644
--- a/content/public/android/java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java
+++ b/content/public/android/java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java
@@ -143,6 +143,9 @@
     }
 
     @Override
+    public void onConnectionCostChanged(int newConnectionCost) {}
+
+    @Override
     public void onConnectionSubtypeChanged(int newConnectionSubtype) {}
 
     @Override
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
index 48f455c..27bc5b96 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
@@ -38,7 +38,6 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.base.annotations.NativeMethods;
-import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.blink.mojom.EventType;
 import org.chromium.blink.mojom.FocusType;
 import org.chromium.blink_public.web.WebInputEventModifier;
@@ -142,7 +141,6 @@
     private int mLastCompositionStart;
     private int mLastCompositionEnd;
     private boolean mRestartInputOnNextStateUpdate;
-    private boolean mLogNextStateUpdate;
 
     // True if ImeAdapter is connected to render process.
     private boolean mIsConnected;
@@ -540,11 +538,6 @@
                 mInputConnection.updateStateOnUiThread(text, selectionStart, selectionEnd,
                         compositionStart, compositionEnd, singleLine, replyToRequest);
             }
-
-            if (mLogNextStateUpdate) {
-                logNodeEditableType(editable);
-            }
-
         } finally {
             TraceEvent.end("ImeAdapter.updateState");
         }
@@ -989,27 +982,6 @@
         if (mTextInputType != TextInputType.NONE && mInputConnection != null && isEditable) {
             mRestartInputOnNextStateUpdate = true;
         }
-        mLogNextStateUpdate = true;
-    }
-
-    private void logNodeEditableType(boolean isEditable) {
-        mLogNextStateUpdate = false;
-        if (!isEditable) {
-            RecordHistogram.recordEnumeratedHistogram("Android.Input.EditableContentTypes",
-                    /* sample=Not editable */ 0, /* max= */ 3);
-        } else if (mTextInputType == TextInputType.CONTENT_EDITABLE) {
-            RecordHistogram.recordEnumeratedHistogram("Android.Input.EditableContentTypes",
-                    /* sample=Content editable */ 1, /* max= */ 3);
-        } else if (mTextInputType == TextInputType.TEXT_AREA) {
-            RecordHistogram.recordEnumeratedHistogram(
-                    "Android.Input.EditableContentTypes", /* sample=Text area */ 2, /* max= */ 3);
-        } else if (mTextInputType == TextInputType.TEXT || mTextInputType == TextInputType.PASSWORD
-                || mTextInputType == TextInputType.SEARCH || mTextInputType == TextInputType.NUMBER
-                || mTextInputType == TextInputType.TELEPHONE
-                || mTextInputType == TextInputType.URL) {
-            RecordHistogram.recordEnumeratedHistogram(
-                    "Android.Input.EditableContentTypes", /* sample=Input */ 3, /* max= */ 3);
-        }
     }
 
     /**
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/OWNERS b/content/public/android/java/src/org/chromium/content/browser/input/OWNERS
deleted file mode 100644
index 395fd997..0000000
--- a/content/public/android/java/src/org/chromium/content/browser/input/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-ctzsm@chromium.org
diff --git a/content/public/android/java/src/org/chromium/content/browser/remoteobjects/OWNERS b/content/public/android/java/src/org/chromium/content/browser/remoteobjects/OWNERS
index 7da9970..56ec958 100644
--- a/content/public/android/java/src/org/chromium/content/browser/remoteobjects/OWNERS
+++ b/content/public/android/java/src/org/chromium/content/browser/remoteobjects/OWNERS
@@ -1,2 +1 @@
-ctzsm@chromium.org
 oksamyt@chromium.org
diff --git a/content/public/android/java/src/org/chromium/content/browser/selection/OWNERS b/content/public/android/java/src/org/chromium/content/browser/selection/OWNERS
deleted file mode 100644
index 395fd997..0000000
--- a/content/public/android/java/src/org/chromium/content/browser/selection/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-ctzsm@chromium.org
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
index e1f7301..7d29e742 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
@@ -31,7 +31,6 @@
 import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
 
-import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Criteria;
@@ -1822,52 +1821,4 @@
         Assert.assertArrayEquals(
                 new String[] {"sometext", "othertext"}, mRule.getLastTextHistory());
     }
-
-    private void assertHasEditableContentValues(
-            int notEditableSample, int contentEditableSample, int textAreaSample, int inputSample) {
-        Assert.assertEquals(notEditableSample,
-                RecordHistogram.getHistogramValueCountForTesting(
-                        "Android.Input.EditableContentTypes", /* sample=Not editable */ 0));
-        Assert.assertEquals(contentEditableSample,
-                RecordHistogram.getHistogramValueCountForTesting(
-                        "Android.Input.EditableContentTypes", /* sample=Content editable */ 1));
-        Assert.assertEquals(textAreaSample,
-                RecordHistogram.getHistogramValueCountForTesting(
-                        "Android.Input.EditableContentTypes", /* sample=Text area */ 2));
-        Assert.assertEquals(inputSample,
-                RecordHistogram.getHistogramValueCountForTesting(
-                        "Android.Input.EditableContentTypes", /* sample=Input */ 3));
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"TextInput"})
-    public void testLogsHasEditableContent() throws Exception {
-        final int notEditableStartingValue = RecordHistogram.getHistogramValueCountForTesting(
-                "Android.Input.EditableContentTypes", /* sample=Not editable */ 0);
-        final int contentEditableStartingValue = RecordHistogram.getHistogramValueCountForTesting(
-                "Android.Input.EditableContentTypes", /* sample=Content editable */ 1);
-        final int textAreaStartingValue = RecordHistogram.getHistogramValueCountForTesting(
-                "Android.Input.EditableContentTypes", /* sample=Text area */ 2);
-        final int inputStartingValue = RecordHistogram.getHistogramValueCountForTesting(
-                "Android.Input.EditableContentTypes", /* sample=Input */ 3);
-
-        DOMUtils.focusNode(mRule.getWebContents(), "link");
-        mRule.assertWaitForKeyboardStatus(false);
-        assertHasEditableContentValues(notEditableStartingValue + 1, contentEditableStartingValue,
-                textAreaStartingValue, inputStartingValue);
-        DOMUtils.focusNode(mRule.getWebContents(), "contenteditable1");
-        mRule.assertWaitForKeyboardStatus(true);
-        assertHasEditableContentValues(notEditableStartingValue + 1,
-                contentEditableStartingValue + 1, textAreaStartingValue, inputStartingValue);
-        DOMUtils.focusNode(mRule.getWebContents(), "textarea");
-        mRule.assertWaitForKeyboardStatus(true);
-        assertHasEditableContentValues(notEditableStartingValue + 1,
-                contentEditableStartingValue + 1, textAreaStartingValue + 1, inputStartingValue);
-        DOMUtils.focusNode(mRule.getWebContents(), "input_text1");
-        mRule.assertWaitForKeyboardStatus(true);
-        assertHasEditableContentValues(notEditableStartingValue + 1,
-                contentEditableStartingValue + 1, textAreaStartingValue + 1,
-                inputStartingValue + 1);
-    }
 }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/OWNERS b/content/public/android/javatests/src/org/chromium/content/browser/input/OWNERS
deleted file mode 100644
index 395fd997..0000000
--- a/content/public/android/javatests/src/org/chromium/content/browser/input/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-ctzsm@chromium.org
diff --git a/content/public/android/junit/src/org/chromium/content/browser/input/OWNERS b/content/public/android/junit/src/org/chromium/content/browser/input/OWNERS
deleted file mode 100644
index 395fd997..0000000
--- a/content/public/android/junit/src/org/chromium/content/browser/input/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-ctzsm@chromium.org
diff --git a/content/public/android/junit/src/org/chromium/content/browser/selection/OWNERS b/content/public/android/junit/src/org/chromium/content/browser/selection/OWNERS
deleted file mode 100644
index 395fd997..0000000
--- a/content/public/android/junit/src/org/chromium/content/browser/selection/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-ctzsm@chromium.org
diff --git a/content/public/browser/browser_thread.h b/content/public/browser/browser_thread.h
index d14e86c..a81aa08 100644
--- a/content/public/browser/browser_thread.h
+++ b/content/public/browser/browser_thread.h
@@ -28,8 +28,6 @@
 // browser_task_traits.h on BrowserThread::ID is broken.
 class BrowserTaskTraits;
 
-class BrowserThreadImpl;
-
 // Use DCHECK_CURRENTLY_ON(BrowserThread::ID) to assert that a function can only
 // be called on the named BrowserThread.
 #define DCHECK_CURRENTLY_ON(thread_identifier)                      \
diff --git a/content/public/browser/browsing_topics_site_data_manager.h b/content/public/browser/browsing_topics_site_data_manager.h
index 0b194814..edc52280 100644
--- a/content/public/browser/browsing_topics_site_data_manager.h
+++ b/content/public/browser/browsing_topics_site_data_manager.h
@@ -42,7 +42,8 @@
   virtual void OnBrowsingTopicsApiUsed(
       const browsing_topics::HashedHost& hashed_main_frame_host,
       const base::flat_set<browsing_topics::HashedDomain>&
-          hashed_context_domains) = 0;
+          hashed_context_domains,
+      base::Time time) = 0;
 };
 
 }  // namespace content
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index d832c0c3..fbf68174 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -67,6 +67,7 @@
 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
 #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
+#include "third_party/blink/public/mojom/browsing_topics/browsing_topics.mojom.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/shell_dialogs/select_file_policy.h"
 #include "url/gurl.h"
@@ -1157,6 +1158,13 @@
     bool user_gesture,
     blink::NavigationDownloadPolicy* download_policy) {}
 
+std::vector<blink::mojom::EpochTopicPtr>
+ContentBrowserClient::GetBrowsingTopicsForJsApi(
+    const url::Origin& context_origin,
+    RenderFrameHost* main_frame) {
+  return {};
+}
+
 bool ContentBrowserClient::IsBluetoothScanningBlocked(
     content::BrowserContext* browser_context,
     const url::Origin& requesting_origin,
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index e142bc6..f5c434fd 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -61,6 +61,7 @@
 #include "storage/browser/file_system/file_system_context.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
+#include "third_party/blink/public/mojom/browsing_topics/browsing_topics.mojom-forward.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom-forward.h"
 #include "ui/accessibility/ax_mode.h"
 #include "ui/base/page_transition_types.h"
@@ -2008,6 +2009,12 @@
       bool user_gesture,
       blink::NavigationDownloadPolicy* download_policy);
 
+  // Returns the browsing topics associated with the browser context of
+  // |main_frame|.
+  virtual std::vector<blink::mojom::EpochTopicPtr> GetBrowsingTopicsForJsApi(
+      const url::Origin& context_origin,
+      RenderFrameHost* main_frame);
+
   // Returns whether a site is blocked to use Bluetooth scanning API.
   virtual bool IsBluetoothScanningBlocked(
       content::BrowserContext* browser_context,
diff --git a/content/public/browser/context_menu_params.h b/content/public/browser/context_menu_params.h
index e49084b6..77af91c 100644
--- a/content/public/browser/context_menu_params.h
+++ b/content/public/browser/context_menu_params.h
@@ -11,8 +11,6 @@
 
 namespace content {
 
-class RenderFrameHostImpl;
-
 // FIXME(beng): This would be more useful in the future and more efficient
 //              if the parameters here weren't so literally mapped to what
 //              they contain for the ContextMenu task. It might be better
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h
index e78074f..81a4a0b3 100644
--- a/content/public/browser/render_frame_host.h
+++ b/content/public/browser/render_frame_host.h
@@ -621,6 +621,9 @@
   // of a frame are defined in Blink.
   virtual blink::mojom::PageVisibilityState GetVisibilityState() = 0;
 
+  // Returns whether the IP address of the last commit was publicly routable.
+  virtual bool IsLastCommitIPAddressPubliclyRoutable() const = 0;
+
   // Returns true if WebContentsObserver::RenderFrameCreated notification has
   // been dispatched for this frame, and so a RenderFrameDeleted notification
   // will later be dispatched for this frame.
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
index 9c70cc9..85335ff 100644
--- a/content/public/browser/web_contents_delegate.h
+++ b/content/public/browser/web_contents_delegate.h
@@ -60,7 +60,6 @@
 class RenderWidgetHost;
 class SessionStorageNamespace;
 class SiteInstance;
-class WebContentsImpl;
 struct ContextMenuParams;
 struct DropData;
 struct MediaPlayerWatchTime;
diff --git a/content/public/browser/web_ui_message_handler.h b/content/public/browser/web_ui_message_handler.h
index d8a699f..066f62da 100644
--- a/content/public/browser/web_ui_message_handler.h
+++ b/content/public/browser/web_ui_message_handler.h
@@ -24,7 +24,6 @@
 
 class TestWebUI;
 class WebUI;
-class WebUIImpl;
 
 // Messages sent from the DOM are forwarded via the WebUI to handler
 // classes. These objects are owned by WebUI and destroyed when the
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index fdcce6e..9b77dbd 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -1156,12 +1156,6 @@
 const base::Feature kWebXrArModule{"WebXRARModule",
                                    base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Controls whether service worker process priority is affected by client
-// process fore/background state change.
-const base::Feature kChangeServiceWorkerPriorityForClientForegroundStateChange{
-    "ChangeServiceWorkerPriorityForClientForegroundStateChange",
-    base::FEATURE_ENABLED_BY_DEFAULT};
-
 #if BUILDFLAG(IS_ANDROID)
 // Allows the use of page zoom in place of accessibility text autosizing, and
 // updated UI to replace existing Chrome Accessibility Settings.
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 4114347..5bd9df5 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -283,8 +283,6 @@
 CONTENT_EXPORT extern const base::Feature kWebUsb;
 CONTENT_EXPORT extern const base::Feature kWebXr;
 CONTENT_EXPORT extern const base::Feature kWebXrArModule;
-CONTENT_EXPORT extern const base::Feature
-    kChangeServiceWorkerPriorityForClientForegroundStateChange;
 
 #if BUILDFLAG(IS_ANDROID)
 CONTENT_EXPORT extern const base::Feature kAccessibilityPageZoom;
diff --git a/content/public/renderer/render_frame_observer.h b/content/public/renderer/render_frame_observer.h
index 19c936b..d55a1b4 100644
--- a/content/public/renderer/render_frame_observer.h
+++ b/content/public/renderer/render_frame_observer.h
@@ -55,7 +55,6 @@
 
 class RendererPpapiHost;
 class RenderFrame;
-class RenderFrameImpl;
 
 // Base class for objects that want to filter incoming IPCs, and also get
 // notified of changes to the frame.
diff --git a/content/public/test/browsing_topics_test_util.cc b/content/public/test/browsing_topics_test_util.cc
index bba7d29c..909ce14aa 100644
--- a/content/public/test/browsing_topics_test_util.cc
+++ b/content/public/test/browsing_topics_test_util.cc
@@ -4,10 +4,46 @@
 
 #include "content/public/test/browsing_topics_test_util.h"
 
+#include "base/test/bind.h"
 #include "content/browser/browsing_topics/browsing_topics_site_data_manager_impl.h"
 
 namespace content {
 
+std::vector<browsing_topics::ApiUsageContext> GetBrowsingTopicsApiUsage(
+    content::BrowsingTopicsSiteDataManager* topics_site_data_manager) {
+  browsing_topics::ApiUsageContextQueryResult query_result;
+
+  base::RunLoop run_loop;
+  topics_site_data_manager->GetBrowsingTopicsApiUsage(
+      base::Time(), base::Time::Now() + base::Days(1),
+      base::BindLambdaForTesting(
+          [&](browsing_topics::ApiUsageContextQueryResult result) {
+            query_result = std::move(result);
+            run_loop.Quit();
+          }));
+
+  run_loop.Run();
+
+  DCHECK(query_result.success);
+
+  std::vector<browsing_topics::ApiUsageContext> api_usage_contexts =
+      std::move(query_result.api_usage_contexts);
+
+  std::sort(api_usage_contexts.begin(), api_usage_contexts.end(),
+            [](auto& left, auto& right) {
+              return left.hashed_context_domain != right.hashed_context_domain
+                         ? left.hashed_context_domain <
+                               right.hashed_context_domain
+                         : (left.hashed_main_frame_host !=
+                                    right.hashed_main_frame_host
+                                ? left.hashed_main_frame_host <
+                                      right.hashed_main_frame_host
+                                : left.time < right.time);
+            });
+
+  return api_usage_contexts;
+}
+
 TesterBrowsingTopicsSiteDataManager::TesterBrowsingTopicsSiteDataManager(
     const base::FilePath& user_data_directory)
     : manager_impl_(
@@ -22,10 +58,10 @@
 
 void TesterBrowsingTopicsSiteDataManager::OnBrowsingTopicsApiUsed(
     const browsing_topics::HashedHost& hashed_top_host,
-    const base::flat_set<browsing_topics::HashedDomain>&
-        hashed_context_domains) {
+    const base::flat_set<browsing_topics::HashedDomain>& hashed_context_domains,
+    base::Time time) {
   manager_impl_->OnBrowsingTopicsApiUsed(hashed_top_host,
-                                         hashed_context_domains);
+                                         hashed_context_domains, time);
 }
 
 void TesterBrowsingTopicsSiteDataManager::GetBrowsingTopicsApiUsage(
diff --git a/content/public/test/browsing_topics_test_util.h b/content/public/test/browsing_topics_test_util.h
index eab0e193..0f986050 100644
--- a/content/public/test/browsing_topics_test_util.h
+++ b/content/public/test/browsing_topics_test_util.h
@@ -12,6 +12,11 @@
 
 class BrowsingTopicsSiteDataManagerImpl;
 
+// Synchrnously get all the browsing topics api usage contexts. Entries are
+// sorted based on [hashed_context_domain, hashed_main_frame_host, time]
+std::vector<browsing_topics::ApiUsageContext> GetBrowsingTopicsApiUsage(
+    BrowsingTopicsSiteDataManager* topics_site_data_manager);
+
 // A tester class that allows mocking a query failure (e.g. database error).
 class TesterBrowsingTopicsSiteDataManager
     : public BrowsingTopicsSiteDataManager {
@@ -37,7 +42,8 @@
   void OnBrowsingTopicsApiUsed(
       const browsing_topics::HashedHost& hashed_top_host,
       const base::flat_set<browsing_topics::HashedDomain>&
-          hashed_context_domains) override;
+          hashed_context_domains,
+      base::Time time) override;
 
   void SetQueryFailureOverride() { query_failure_override_ = true; }
 
diff --git a/content/public/test/mock_permission_controller.cc b/content/public/test/mock_permission_controller.cc
new file mode 100644
index 0000000..97107861
--- /dev/null
+++ b/content/public/test/mock_permission_controller.cc
@@ -0,0 +1,27 @@
+// 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 "content/public/test/mock_permission_controller.h"
+#include "url/gurl.h"
+
+namespace content {
+
+MockPermissionController::MockPermissionController() = default;
+
+MockPermissionController::~MockPermissionController() = default;
+
+void MockPermissionController::RequestPermission(
+    PermissionType permission,
+    RenderFrameHost* render_frame_host,
+    const GURL& requesting_origin,
+    bool user_gesture,
+    base::OnceCallback<void(blink::mojom::PermissionStatus)> callback) {}
+
+void MockPermissionController::RequestPermissionFromCurrentDocument(
+    PermissionType permission,
+    RenderFrameHost* render_frame_host,
+    bool user_gesture,
+    base::OnceCallback<void(blink::mojom::PermissionStatus)> callback) {}
+
+}  // namespace content
diff --git a/content/public/test/mock_permission_controller.h b/content/public/test/mock_permission_controller.h
new file mode 100644
index 0000000..16b215d
--- /dev/null
+++ b/content/public/test/mock_permission_controller.h
@@ -0,0 +1,65 @@
+// 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 CONTENT_PUBLIC_TEST_MOCK_PERMISSION_CONTROLLER_H_
+#define CONTENT_PUBLIC_TEST_MOCK_PERMISSION_CONTROLLER_H_
+
+#include "content/public/browser/permission_controller.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+class GURL;
+
+namespace url {
+class Origin;
+}
+
+namespace content {
+
+enum class PermissionType;
+
+// Mock of the permission controller for unit tests.
+class MockPermissionController : public PermissionController {
+ public:
+  MockPermissionController();
+
+  MockPermissionController(const MockPermissionController&) = delete;
+  MockPermissionController& operator=(const MockPermissionController&) = delete;
+
+  ~MockPermissionController() override;
+
+  // PermissionController:
+  MOCK_METHOD3(DeprecatedGetPermissionStatus,
+               blink::mojom::PermissionStatus(PermissionType permission,
+                                              const GURL& requesting_origin,
+                                              const GURL& embedding_origin));
+  MOCK_METHOD2(
+      GetPermissionStatusForServiceWorker,
+      blink::mojom::PermissionStatus(PermissionType permission,
+                                     const url::Origin& requesting_origin));
+  MOCK_METHOD2(
+      GetPermissionStatusForCurrentDocument,
+      blink::mojom::PermissionStatus(PermissionType permission,
+                                     RenderFrameHost* render_frame_host));
+  MOCK_METHOD2(
+      GetPermissionStatusForOriginWithoutContext,
+      blink::mojom::PermissionStatus(PermissionType permission,
+                                     const url::Origin& requesting_origin));
+  void RequestPermission(
+      PermissionType permission,
+      RenderFrameHost* render_frame_host,
+      const GURL& requesting_origin,
+      bool user_gesture,
+      base::OnceCallback<void(blink::mojom::PermissionStatus)> callback)
+      override;
+  void RequestPermissionFromCurrentDocument(
+      PermissionType permission,
+      RenderFrameHost* render_frame_host,
+      bool user_gesture,
+      base::OnceCallback<void(blink::mojom::PermissionStatus)> callback)
+      override;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_TEST_MOCK_PERMISSION_CONTROLLER_H_
diff --git a/content/public/test/mock_permission_manager.cc b/content/public/test/mock_permission_manager.cc
index f04d8e6e..aa6f6fa 100644
--- a/content/public/test/mock_permission_manager.cc
+++ b/content/public/test/mock_permission_manager.cc
@@ -9,9 +9,9 @@
 
 namespace content {
 
-MockPermissionManager::MockPermissionManager() {}
+MockPermissionManager::MockPermissionManager() = default;
 
-MockPermissionManager::~MockPermissionManager() {}
+MockPermissionManager::~MockPermissionManager() = default;
 
 void MockPermissionManager::RequestPermission(
     PermissionType permission,
diff --git a/content/services/auction_worklet/BUILD.gn b/content/services/auction_worklet/BUILD.gn
index d312737..96f033f 100644
--- a/content/services/auction_worklet/BUILD.gn
+++ b/content/services/auction_worklet/BUILD.gn
@@ -54,6 +54,8 @@
     "report_bindings.h",
     "seller_worklet.cc",
     "seller_worklet.h",
+    "set_bid_bindings.cc",
+    "set_bid_bindings.h",
     "trusted_signals.cc",
     "trusted_signals.h",
     "trusted_signals_request_manager.cc",
diff --git a/content/services/auction_worklet/bidder_worklet.cc b/content/services/auction_worklet/bidder_worklet.cc
index 9c9b8fa1..548616d4 100644
--- a/content/services/auction_worklet/bidder_worklet.cc
+++ b/content/services/auction_worklet/bidder_worklet.cc
@@ -22,6 +22,7 @@
 #include "content/services/auction_worklet/for_debugging_only_bindings.h"
 #include "content/services/auction_worklet/public/mojom/auction_worklet_service.mojom.h"
 #include "content/services/auction_worklet/report_bindings.h"
+#include "content/services/auction_worklet/set_bid_bindings.h"
 #include "content/services/auction_worklet/trusted_signals.h"
 #include "content/services/auction_worklet/trusted_signals_request_manager.h"
 #include "content/services/auction_worklet/worklet_loader.h"
@@ -118,32 +119,6 @@
   return true;
 }
 
-// Checks that `url` is a valid URL and is in `ads`. Appends an error to
-// `out_errors` if not. `script_source_url` is used in output error messages
-// only.
-bool IsAllowedAdUrl(const GURL& url,
-                    const GURL& script_source_url,
-                    const char* argument_name,
-                    const std::vector<blink::InterestGroup::Ad>& ads,
-                    std::vector<std::string>& out_errors) {
-  if (!url.is_valid() || !url.SchemeIs(url::kHttpsScheme)) {
-    out_errors.push_back(
-        base::StrCat({script_source_url.spec(), " generateBid() returned ",
-                      argument_name, " URL that isn't a valid https:// URL."}));
-    return false;
-  }
-
-  for (const auto& ad : ads) {
-    if (url == ad.render_url)
-      return true;
-  }
-  out_errors.push_back(base::StrCat({script_source_url.spec(),
-                                     " generateBid() returned ", argument_name,
-                                     " URL that isn't one "
-                                     "of the registered creative URLs."}));
-  return false;
-}
-
 }  // namespace
 
 BidderWorklet::BidderWorklet(
@@ -191,10 +166,6 @@
   debug_id_->AbortDebuggerPauses();
 }
 
-bool BidderWorklet::IsValidBid(double bid) {
-  return !std::isnan(bid) && std::isfinite(bid) && bid > 0;
-}
-
 int BidderWorklet::context_group_id_for_testing() const {
   return debug_id_->context_group_id();
 }
@@ -442,6 +413,11 @@
       v8::ObjectTemplate::New(isolate);
   ForDebuggingOnlyBindings for_debugging_only_bindings(v8_helper_.get(),
                                                        global_template);
+  SetBidBindings set_bid_bindings(
+      v8_helper_.get(), global_template, start,
+      browser_signal_top_level_seller_origin.has_value(),
+      bidder_worklet_non_shared_params->ads,
+      bidder_worklet_non_shared_params->ad_components);
 
   // Short lived context, to avoid leaking data at global scope between either
   // repeated calls to this worklet, or to calls to any other worklet.
@@ -562,143 +538,34 @@
   std::vector<std::string> errors_out;
   v8_helper_->MaybeTriggerInstrumentationBreakpoint(
       *debug_id_, "beforeBidderWorkletBiddingStart");
-  if (!v8_helper_
-           ->RunScript(context, worklet_script_.Get(isolate), debug_id_.get(),
-                       "generateBid", args, std::move(per_buyer_timeout),
-                       errors_out)
-           .ToLocal(&generate_bid_result)) {
+  bool got_return_value =
+      v8_helper_
+          ->RunScript(context, worklet_script_.Get(isolate), debug_id_.get(),
+                      "generateBid", args, std::move(per_buyer_timeout),
+                      errors_out)
+          .ToLocal(&generate_bid_result);
+
+  if (got_return_value) {
+    set_bid_bindings.SetBid(
+        generate_bid_result,
+        base::StrCat({script_source_url_.spec(), " generateBid() "}),
+        errors_out);
+  }
+
+  if (!set_bid_bindings.has_bid()) {
+    // If we either don't have a valid return value, or we have no return value
+    // and no intermediate result was given through setBid, return an error.
     PostErrorBidCallbackToUserThread(std::move(callback),
                                      std::move(errors_out));
     return;
   }
 
-  if (!generate_bid_result->IsObject()) {
-    errors_out.push_back(
-        base::StrCat({script_source_url_.spec(),
-                      " generateBid() return value not an object."}));
-    PostErrorBidCallbackToUserThread(std::move(callback),
-                                     std::move(errors_out));
-    return;
-  }
-
-  gin::Dictionary result_dict(isolate, generate_bid_result.As<v8::Object>());
-
-  v8::Local<v8::Value> ad_object;
-  std::string ad_json;
-  double bid;
-  std::string render_url_string;
-  // Parse and validate values.
-  if (!result_dict.Get("ad", &ad_object) ||
-      !v8_helper_->ExtractJson(context, ad_object, &ad_json) ||
-      !result_dict.Get("bid", &bid) ||
-      !result_dict.Get("render", &render_url_string)) {
-    errors_out.push_back(
-        base::StrCat({script_source_url_.spec(),
-                      " generateBid() return value has incorrect structure."}));
-    PostErrorBidCallbackToUserThread(std::move(callback),
-                                     std::move(errors_out));
-    return;
-  }
-
-  if (browser_signal_top_level_seller_origin) {
-    bool allow_component_auction;
-    if (!result_dict.Get("allowComponentAuction", &allow_component_auction) ||
-        !allow_component_auction) {
-      errors_out.push_back(base::StrCat(
-          {script_source_url_.spec(),
-           " generateBid() return value does not have allowComponentAuction "
-           "set to true. Bid dropped from component auction."}));
-      PostErrorBidCallbackToUserThread(std::move(callback),
-                                       std::move(errors_out));
-      return;
-    }
-  }
-
-  if (!IsValidBid(bid)) {
-    PostErrorBidCallbackToUserThread(std::move(callback),
-                                     std::move(errors_out));
-    return;
-  }
-
-  GURL render_url(render_url_string);
-  if (!IsAllowedAdUrl(render_url, script_source_url_, "render",
-                      *bidder_worklet_non_shared_params->ads, errors_out)) {
-    PostErrorBidCallbackToUserThread(std::move(callback),
-                                     std::move(errors_out));
-    return;
-  }
-
-  absl::optional<std::vector<GURL>> ad_component_urls;
-  v8::Local<v8::Value> ad_components;
-  if (result_dict.Get("adComponents", &ad_components) &&
-      !ad_components->IsNullOrUndefined()) {
-    if (!bidder_worklet_non_shared_params->ad_components) {
-      errors_out.push_back(
-          base::StrCat({script_source_url_.spec(),
-                        " generateBid() return value contains adComponents but "
-                        "InterestGroup has no adComponents."}));
-      PostErrorBidCallbackToUserThread(std::move(callback),
-                                       std::move(errors_out));
-      return;
-    }
-
-    if (!ad_components->IsArray()) {
-      errors_out.push_back(base::StrCat(
-          {script_source_url_.spec(),
-           " generateBid() returned adComponents value must be an array."}));
-      PostErrorBidCallbackToUserThread(std::move(callback),
-                                       std::move(errors_out));
-      return;
-    }
-
-    v8::Local<v8::Array> ad_components_array = ad_components.As<v8::Array>();
-    if (ad_components_array->Length() > blink::kMaxAdAuctionAdComponents) {
-      errors_out.push_back(base::StringPrintf(
-          "%s generateBid() returned adComponents with over %zu items.",
-          script_source_url_.spec().c_str(), blink::kMaxAdAuctionAdComponents));
-      PostErrorBidCallbackToUserThread(std::move(callback),
-                                       std::move(errors_out));
-      return;
-    }
-
-    ad_component_urls.emplace();
-    for (size_t i = 0; i < ad_components_array->Length(); ++i) {
-      std::string url_string;
-      if (!gin::ConvertFromV8(
-              isolate, ad_components_array->Get(context, i).ToLocalChecked(),
-              &url_string)) {
-        errors_out.push_back(
-            base::StrCat({script_source_url_.spec(),
-                          " generateBid() returned adComponents value must be "
-                          "an array of strings."}));
-        PostErrorBidCallbackToUserThread(std::move(callback),
-                                         std::move(errors_out));
-        return;
-      }
-
-      GURL ad_component_url(url_string);
-      if (!IsAllowedAdUrl(ad_component_url, script_source_url_, "adComponents",
-                          *bidder_worklet_non_shared_params->ad_components,
-                          errors_out)) {
-        PostErrorBidCallbackToUserThread(std::move(callback),
-                                         std::move(errors_out));
-        return;
-      }
-      ad_component_urls->emplace_back(std::move(ad_component_url));
-    }
-  }
-
   user_thread_->PostTask(
-      FROM_HERE,
-      base::BindOnce(std::move(callback),
-                     mojom::BidderWorkletBid::New(
-                         std::move(ad_json), bid, std::move(render_url),
-                         std::move(ad_component_urls),
-                         /*bid_duration=*/base::TimeTicks::Now() - start),
-                     bidding_signals_data_version,
-                     for_debugging_only_bindings.TakeLossReportUrl(),
-                     for_debugging_only_bindings.TakeWinReportUrl(),
-                     std::move(errors_out)));
+      FROM_HERE, base::BindOnce(std::move(callback), set_bid_bindings.TakeBid(),
+                                bidding_signals_data_version,
+                                for_debugging_only_bindings.TakeLossReportUrl(),
+                                for_debugging_only_bindings.TakeWinReportUrl(),
+                                std::move(errors_out)));
 }
 
 void BidderWorklet::V8State::ConnectDevToolsAgent(
diff --git a/content/services/auction_worklet/bidder_worklet.h b/content/services/auction_worklet/bidder_worklet.h
index cf9b400..c301e64f 100644
--- a/content/services/auction_worklet/bidder_worklet.h
+++ b/content/services/auction_worklet/bidder_worklet.h
@@ -79,11 +79,6 @@
   ~BidderWorklet() override;
   BidderWorklet& operator=(const BidderWorklet&) = delete;
 
-  // Returns true if `bid` is a valid bid value. Bids of "0" and other values
-  // that mean no bid was offered are considered invalid, for the purposes of
-  // this method.
-  static bool IsValidBid(double bid);
-
   // Sets the callback to be invoked on errors which require closing the pipe.
   // Callback will also immediately delete `this`. Not an argument to
   // constructor because the Mojo ReceiverId needs to be bound to the callback,
diff --git a/content/services/auction_worklet/bidder_worklet_unittest.cc b/content/services/auction_worklet/bidder_worklet_unittest.cc
index 46614731..95ac4ad 100644
--- a/content/services/auction_worklet/bidder_worklet_unittest.cc
+++ b/content/services/auction_worklet/bidder_worklet_unittest.cc
@@ -601,13 +601,13 @@
       R"({ad: globalThis.not_defined, bid:1, render:"https://response.test/"})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() return value "
+      {"https://url.test/ generateBid() bid "
        "has incorrect structure."});
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: function() {return 1;}, bid:1, render:"https://response.test/"})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() return value "
+      {"https://url.test/ generateBid() bid "
        "has incorrect structure."});
 
   // Make sure recursive structures aren't allowed in ad field.
@@ -621,7 +621,7 @@
       )",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() return value "
+      {"https://url.test/ generateBid() bid "
        "has incorrect structure."});
 
   // --------
@@ -651,34 +651,45 @@
       mojom::BidderWorkletBidPtr() /* expected_bid */);
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: ["ad"], bid:-10, render:"https://response.test/"})",
-      mojom::BidderWorkletBidPtr() /* expected_bid */);
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/ generateBid() bid of -10.000000 is not a valid "
+       "bid."});
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: ["ad"], bid:-1.5, render:"https://response.test/"})",
-      mojom::BidderWorkletBidPtr() /* expected_bid */);
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/ generateBid() bid of -1.500000 is not a valid bid."});
 
   // Infinite and NaN bid.
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: ["ad"], bid:1/0, render:"https://response.test/"})",
-      mojom::BidderWorkletBidPtr() /* expected_bid */);
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/ generateBid() bid of inf is not a valid bid."});
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: ["ad"], bid:-1/0, render:"https://response.test/"})",
-      mojom::BidderWorkletBidPtr() /* expected_bid */);
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/ generateBid() bid of -inf is not a valid bid."});
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: ["ad"], bid:0/0, render:"https://response.test/"})",
-      mojom::BidderWorkletBidPtr() /* expected_bid */);
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/ generateBid() bid of nan is not a valid bid."});
 
   // Non-numeric bid.
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: ["ad"], bid:"1", render:"https://response.test/"})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() return value "
+      {"https://url.test/ generateBid() bid "
        "has incorrect structure."});
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: ["ad"], bid:[1], render:"https://response.test/"})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() return value "
+      {"https://url.test/ generateBid() bid "
        "has incorrect structure."});
 
   // ---------
@@ -696,51 +707,51 @@
       R"({ad: ["ad"], bid:1, render:"http://response.test/"})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() returned "
-       "render URL that isn't a valid https:// URL."});
+      {"https://url.test/ generateBid() bid render URL 'http://response.test/' "
+       "isn't a valid https:// URL."});
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: ["ad"], bid:1, render:"chrome-extension://response.test/"})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() returned "
-       "render URL that isn't a valid https:// URL."});
+      {"https://url.test/ generateBid() bid render URL "
+       "'chrome-extension://response.test/' isn't a valid https:// URL."});
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: ["ad"], bid:1, render:"about:blank"})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() returned "
-       "render URL that isn't a valid https:// URL."});
+      {"https://url.test/ generateBid() bid render URL 'about:blank' isn't a "
+       "valid https:// URL."});
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: ["ad"], bid:1, render:"data:,foo"})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() returned "
-       "render URL that isn't a valid https:// URL."});
+      {"https://url.test/ generateBid() bid render URL 'data:,foo' isn't a "
+       "valid https:// URL."});
 
   // Invalid render URLs.
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: ["ad"], bid:1, render:"test"})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() returned "
-       "render URL that isn't a valid https:// URL."});
+      {"https://url.test/ generateBid() bid render URL '' isn't a valid "
+       "https:// URL."});
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: ["ad"], bid:1, render:"http://"})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() returned "
-       "render URL that isn't a valid https:// URL."});
+      {"https://url.test/ generateBid() bid render URL 'http:' isn't a valid "
+       "https:// URL."});
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: ["ad"], bid:1, render:["http://response.test/"]})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() return value "
+      {"https://url.test/ generateBid() bid "
        "has incorrect structure."});
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: ["ad"], bid:1, render:9})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() return value "
+      {"https://url.test/ generateBid() bid "
        "has incorrect structure."});
 
   // ----------------------
@@ -757,7 +768,7 @@
         adComponents:["http://response.test/"]})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() return value contains adComponents but "
+      {"https://url.test/ generateBid() bid contains adComponents but "
        "InterestGroup has no adComponents."});
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: "ad",
@@ -766,7 +777,7 @@
         adComponents:[]})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() return value contains adComponents but "
+      {"https://url.test/ generateBid() bid contains adComponents but "
        "InterestGroup has no adComponents."});
 
   // Auction should fail if adComponents in return value is an unexpected type.
@@ -777,7 +788,7 @@
         adComponents:5})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() return value contains adComponents but "
+      {"https://url.test/ generateBid() bid contains adComponents but "
        "InterestGroup has no adComponents."});
 
   // Not present and null adComponents fields should result in success.
@@ -820,8 +831,8 @@
         adComponents:5})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() returned adComponents value must be "
-       "an array."});
+      {"https://url.test/ generateBid() bid adComponents value must be an "
+       "array."});
 
   // Unexpected value types in adComponents should fail.
   RunGenerateBidWithReturnValueExpectingResult(
@@ -831,7 +842,7 @@
         adComponents:[{}]})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() returned adComponents value must be an "
+      {"https://url.test/ generateBid() bid adComponents value must be an "
        "array of strings."});
 
   // Up to 20 values in the output adComponents output array are allowed (And
@@ -921,8 +932,7 @@
         ]})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() returned adComponents with over 20 "
-       "items."});
+      {"https://url.test/ generateBid() bid adComponents with over 20 items."});
 
   // ------------
   // Other cases.
@@ -932,26 +942,26 @@
   RunGenerateBidWithReturnValueExpectingResult(
       "", /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() return value not an object."});
+      {"https://url.test/ generateBid() bid not an object."});
 
   // Missing value.
   RunGenerateBidWithReturnValueExpectingResult(
       R"({bid:"a", render:"https://response.test/"})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() return value "
+      {"https://url.test/ generateBid() bid "
        "has incorrect structure."});
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: ["ad"], render:"https://response.test/"})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() return value "
+      {"https://url.test/ generateBid() bid "
        "has incorrect structure."});
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: ["ad"], bid:"a"})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() return value "
+      {"https://url.test/ generateBid() bid "
        "has incorrect structure."});
 
   // Valid JS, but missing function.
@@ -981,6 +991,311 @@
        "shrimp is not defined."});
 }
 
+// Test parsing of setBid arguments.
+TEST_F(BidderWorkletTest, GenerateBidSetBidThrows) {
+  // --------
+  // Vary ad
+  // --------
+
+  // Other values JSON can't represent result in failing instead of null.
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: globalThis.not_defined, bid:1, render:"https://response.test/"});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid has incorrect structure."});
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: function() {return 1;}, bid:1, render:"https://response.test/"});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid has incorrect structure."});
+
+  // Make sure recursive structures aren't allowed in ad field.
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(
+        function generateBid() {
+          var a = [];
+          a[0] = a;
+          setBid({ad: a, bid:1, render:"https://response.test/"});
+          return {};
+        }
+      )",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:5 Uncaught TypeError: bid has incorrect structure."});
+
+  // --------
+  // Vary bid
+  // --------
+
+  // Non-numeric bid.
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: ["ad"], bid:"1", render:"https://response.test/"});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid "
+       "has incorrect structure."});
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: ["ad"], bid:[1], render:"https://response.test/"});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid has incorrect structure."});
+
+  // ---------
+  // Vary URL.
+  // ---------
+
+  // Disallowed render schemes.
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: ["ad"], bid:1, render:"http://response.test/"});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid render URL "
+       "'http://response.test/' isn't a valid https:// URL."});
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: ["ad"],
+                 bid:1,
+                 render:"chrome-extension://response.test/"});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid render URL "
+       "'chrome-extension://response.test/' isn't a valid https:// URL."});
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: ["ad"], bid:1, render:"about:blank"});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid render URL 'about:blank' "
+       "isn't a valid https:// URL."});
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: ["ad"], bid:1, render:"data:,foo"});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid render URL 'data:,foo' "
+       "isn't a valid https:// URL."});
+
+  // Invalid render URLs.
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: ["ad"], bid:1, render:"test"});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid render URL '' isn't a "
+       "valid https:// URL."});
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: ["ad"], bid:1, render:"http://"});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid render URL 'http:' isn't a "
+       "valid https:// URL."});
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: ["ad"], bid:1, render:["http://response.test/"]});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid has incorrect structure."});
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: ["ad"], bid:1, render:9});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid has incorrect structure."});
+
+  // ----------------------
+  // No adComponents in IG.
+  // ----------------------
+
+  interest_group_ad_components_ = absl::nullopt;
+
+  // Auction should fail if adComponents in return value is an array.
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: "ad",
+                 bid:1,
+                 render:"https://response.test/",
+                 adComponents:["http://response.test/"]});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid contains adComponents but "
+       "InterestGroup has no adComponents."});
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: "ad",
+                 bid:1,
+                 render:"https://response.test/",
+                 adComponents:[]});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid contains adComponents but "
+       "InterestGroup has no adComponents."});
+
+  // Auction should fail if adComponents in return value is an unexpected type.
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: "ad",
+                 bid:1,
+                 render:"https://response.test/",
+                 adComponents:5});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid contains adComponents but "
+       "InterestGroup has no adComponents."});
+
+  SetDefaultParameters();
+
+  // -----------------------------
+  // Non-empty adComponents in IG.
+  // -----------------------------
+
+  // Auction should fail if adComponents in return value is an unexpected type.
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: "ad",
+                 bid:1,
+                 render:"https://response.test/",
+                 adComponents:5});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid adComponents value must be "
+       "an array."});
+
+  // Unexpected value types in adComponents should fail.
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: "ad",
+                 bid:1,
+                 render:"https://response.test/",
+                 adComponents:[{}]});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid adComponents value must be "
+       "an array of strings."});
+
+  // Up to 20 values in the output adComponents output array are allowed (And
+  // they can all be the same URL).
+  static_assert(blink::kMaxAdAuctionAdComponents == 20,
+                "Unexpected value of kMaxAdAuctionAdComponents");
+
+  // Results with 21 or more values are rejected.
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: "ad",
+                 bid:1,
+                 render:"https://response.test/",
+                 adComponents:[
+                   "https://ad_component.test/" /* 1 */,
+                   "https://ad_component.test/" /* 2 */,
+                   "https://ad_component.test/" /* 3 */,
+                   "https://ad_component.test/" /* 4 */,
+                   "https://ad_component.test/" /* 5 */,
+                   "https://ad_component.test/" /* 6 */,
+                   "https://ad_component.test/" /* 7 */,
+                   "https://ad_component.test/" /* 8 */,
+                   "https://ad_component.test/" /* 9 */,
+                   "https://ad_component.test/" /* 10 */,
+                   "https://ad_component.test/" /* 11 */,
+                   "https://ad_component.test/" /* 12 */,
+                   "https://ad_component.test/" /* 13 */,
+                   "https://ad_component.test/" /* 14 */,
+                   "https://ad_component.test/" /* 15 */,
+                   "https://ad_component.test/" /* 16 */,
+                   "https://ad_component.test/" /* 17 */,
+                   "https://ad_component.test/" /* 18 */,
+                   "https://ad_component.test/" /* 19 */,
+                   "https://ad_component.test/" /* 20 */,
+                   "https://ad_component.test/" /* 21 */,
+        ]});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid adComponents with over 20 "
+       "items."});
+
+  // ------------
+  // Other cases.
+  // ------------
+
+  // No return value.
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid(1);
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid not an object."});
+
+  // Missing value.
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({bid:"a", render:"https://response.test/"});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid "
+       "has incorrect structure."});
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: ["ad"], render:"https://response.test/"});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid "
+       "has incorrect structure."});
+  RunGenerateBidWithJavascriptExpectingResult(
+      R"(function generateBid() {
+         setBid({ad: ["ad"], bid:"a"});
+         return {ad: "not_reached", bid: 4, render:"https://response.test/2"};
+       })",
+      /*expected_bid=*/mojom::BidderWorkletBidPtr(),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/:2 Uncaught TypeError: bid has incorrect structure."});
+}
+
 // Make sure Date() is not available when running generateBid().
 TEST_F(BidderWorkletTest, GenerateBidDateNotAvailable) {
   RunGenerateBidWithReturnValueExpectingResult(
@@ -1667,8 +1982,8 @@
       R"({ad: 0, bid:1, render:"https://response2.test/"})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() returned render URL that isn't one of "
-       "the registered creative URLs."});
+      {"https://url.test/ generateBid() bid render URL "
+       "'https://response2.test/' isn't one of the registered creative URLs."});
 
   // Adding an ad with a corresponding `renderUrl` should result in success.
   // Also check the `interestGroup.ads` field passed to Javascript.
@@ -1711,9 +2026,8 @@
       R"({ad: 0, bid:1, render:"https://response.test/", adComponents:["https://response.test/"]})",
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() returned adComponents URL that isn't "
-       "one "
-       "of the registered creative URLs."});
+      {"https://url.test/ generateBid() bid adComponents URL "
+       "'https://response.test/' isn't one of the registered creative URLs."});
 
   // Add a second ad component URL, this time with metadata.
   // Returning a list with both ads should result in success.
@@ -1777,21 +2091,21 @@
       R"({ad: null, bid:1, render:"https://response.test/", allowComponentAuction: false})",
       mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt, /*expected_errors=*/
-      {"https://url.test/ generateBid() return value does not have "
+      {"https://url.test/ generateBid() bid does not have "
        "allowComponentAuction set to true. Bid dropped from component "
        "auction."});
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: null, bid:1, render:"https://response.test/"})",
       mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt, /*expected_errors=*/
-      {"https://url.test/ generateBid() return value does not have "
+      {"https://url.test/ generateBid() bid does not have "
        "allowComponentAuction set to true. Bid dropped from component "
        "auction."});
   RunGenerateBidWithReturnValueExpectingResult(
       R"({ad: null, bid:1, render:"https://response.test/", allowComponentAuction: 0})",
       mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt, /*expected_errors=*/
-      {"https://url.test/ generateBid() return value does not have "
+      {"https://url.test/ generateBid() bid does not have "
        "allowComponentAuction set to true. Bid dropped from component "
        "auction."});
   RunGenerateBidWithReturnValueExpectingResult(
@@ -2148,6 +2462,22 @@
       7u);
 }
 
+// Even though the script had set an intermediate result with setBid, the
+// returned value should be used instead.
+TEST_F(BidderWorkletTest, GenerateBidWithSetBid) {
+  RunGenerateBidWithJavascriptExpectingResult(
+      CreateGenerateBidScript(
+          /*raw_return_value=*/
+          R"({ad: "returned", bid:2, render:"https://response.test/" })",
+          /*extra_code=*/R"(
+            setBid({ad: "ad", bid:1, render:"https://response.test/"})
+          )"),
+      /*expected_bid=*/
+      mojom::BidderWorkletBid::New(
+          "\"returned\"", 2, GURL("https://response.test/"),
+          /*ad_components=*/absl::nullopt, base::TimeDelta()));
+}
+
 TEST_F(BidderWorkletTest, GenerateBidTimedOut) {
   // Use a very long default script timeout, and a short per buyer timeout, so
   // that if the bidder script with endless loop times out, we know that the per
@@ -2172,6 +2502,81 @@
       {"https://url.test/ execution of `generateBid` timed out."});
 }
 
+// Even though the script timed out, it had set an intermediate result with
+// setBid, so we should use that instead.
+TEST_F(BidderWorkletTest, GenerateBidTimedOutWithSetBid) {
+  // Use a very long default script timeout, and a short per buyer timeout, so
+  // that if the bidder script with endless loop times out, we know that the per
+  // buyer timeout overwrote the default script timeout and worked.
+  const base::TimeDelta kScriptTimeout = base::Days(360);
+  v8_helper_->v8_runner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          [](scoped_refptr<AuctionV8Helper> v8_helper,
+             const base::TimeDelta script_timeout) {
+            v8_helper->set_script_timeout_for_testing(script_timeout);
+          },
+          v8_helper_, kScriptTimeout));
+  // Make sure set_script_timeout_for_testing is called.
+  task_environment_.RunUntilIdle();
+
+  per_buyer_timeout_ = base::Milliseconds(20);
+  RunGenerateBidWithJavascriptExpectingResult(
+      CreateGenerateBidScript(
+          /*raw_return_value=*/
+          R"({ad: "not_reached", bid:2, render:"https://response.test/2" })",
+          /*extra_code=*/R"(
+            setBid({ad: "ad", bid:1, render:"https://response.test/"});
+            while (1)
+          )"),
+      /*expected_bid=*/
+      mojom::BidderWorkletBid::New("\"ad\"", 1, GURL("https://response.test/"),
+                                   /*ad_components=*/absl::nullopt,
+                                   base::TimeDelta()),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/ execution of `generateBid` timed out."});
+}
+
+// Even though the script timed out, it had set an intermediate result with
+// setBid, so we should use that instead. The bid value should not change if we
+// mutate the object passed to setBid after it returns.
+TEST_F(BidderWorkletTest, GenerateBidTimedOutWithSetBidMutateAfter) {
+  // Use a very long default script timeout, and a short per buyer timeout, so
+  // that if the bidder script with endless loop times out, we know that the per
+  // buyer timeout overwrote the default script timeout and worked.
+  const base::TimeDelta kScriptTimeout = base::Days(360);
+  v8_helper_->v8_runner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          [](scoped_refptr<AuctionV8Helper> v8_helper,
+             const base::TimeDelta script_timeout) {
+            v8_helper->set_script_timeout_for_testing(script_timeout);
+          },
+          v8_helper_, kScriptTimeout));
+  // Make sure set_script_timeout_for_testing is called.
+  task_environment_.RunUntilIdle();
+
+  per_buyer_timeout_ = base::Milliseconds(20);
+  RunGenerateBidWithJavascriptExpectingResult(
+      CreateGenerateBidScript(
+          /*raw_return_value=*/
+          R"({ad: "not_reached", bid:2, render:"https://response.test/2" })",
+          /*extra_code=*/R"(
+            let result = {ad: "ad", bid:1, render:"https://response.test/"};
+            setBid(result);
+            result.ad = "ad2";
+            result.bid = 3;
+            result.render = "https://response.test/3";
+            while (1)
+          )"),
+      /*expected_bid=*/
+      mojom::BidderWorkletBid::New("\"ad\"", 1, GURL("https://response.test/"),
+                                   /*ad_components=*/absl::nullopt,
+                                   base::TimeDelta()),
+      /*expected_data_version=*/absl::nullopt,
+      {"https://url.test/ execution of `generateBid` timed out."});
+}
+
 TEST_F(BidderWorkletTest, ReportWin) {
   RunReportWinWithFunctionBodyExpectingResult(
       "", /*expected_report_url =*/absl::nullopt);
@@ -3053,7 +3458,7 @@
             forDebuggingOnly.reportAdAuctionWin("https://win.url"))"),
       /*expected_bid=*/mojom::BidderWorkletBidPtr(),
       /*expected_data_version=*/absl::nullopt,
-      {"https://url.test/ generateBid() return value has incorrect structure."},
+      {"https://url.test/ generateBid() bid has incorrect structure."},
       /*expected_debug_loss_report_url=*/absl::nullopt,
       /*expected_debug_win_report_url=*/absl::nullopt);
 }
diff --git a/content/services/auction_worklet/for_debugging_only_bindings.h b/content/services/auction_worklet/for_debugging_only_bindings.h
index 8ca9b19..c429eb56 100644
--- a/content/services/auction_worklet/for_debugging_only_bindings.h
+++ b/content/services/auction_worklet/for_debugging_only_bindings.h
@@ -24,8 +24,7 @@
   // ForDebuggingOnlyBindings must outlive the template.
   ForDebuggingOnlyBindings(AuctionV8Helper* v8_helper,
                            v8::Local<v8::ObjectTemplate> global_template);
-  ForDebuggingOnlyBindings WorkletLoader(const ForDebuggingOnlyBindings&) =
-      delete;
+  ForDebuggingOnlyBindings(const ForDebuggingOnlyBindings&) = delete;
   ForDebuggingOnlyBindings& operator=(const ForDebuggingOnlyBindings&) = delete;
   ~ForDebuggingOnlyBindings();
 
diff --git a/content/services/auction_worklet/report_bindings.h b/content/services/auction_worklet/report_bindings.h
index 6c79bc9..8b82d11e 100644
--- a/content/services/auction_worklet/report_bindings.h
+++ b/content/services/auction_worklet/report_bindings.h
@@ -24,7 +24,7 @@
   // the template.
   ReportBindings(AuctionV8Helper* v8_helper,
                  v8::Local<v8::ObjectTemplate> global_template);
-  ReportBindings WorkletLoader(const ReportBindings&) = delete;
+  ReportBindings(const ReportBindings&) = delete;
   ReportBindings& operator=(const ReportBindings&) = delete;
   ~ReportBindings();
 
diff --git a/content/services/auction_worklet/seller_worklet.cc b/content/services/auction_worklet/seller_worklet.cc
index 59a0fa0d..2d84c5f 100644
--- a/content/services/auction_worklet/seller_worklet.cc
+++ b/content/services/auction_worklet/seller_worklet.cc
@@ -17,7 +17,6 @@
 #include "base/strings/strcat.h"
 #include "base/time/time.h"
 #include "content/services/auction_worklet/auction_v8_helper.h"
-#include "content/services/auction_worklet/bidder_worklet.h"
 #include "content/services/auction_worklet/for_debugging_only_bindings.h"
 #include "content/services/auction_worklet/public/mojom/auction_worklet_service.mojom.h"
 #include "content/services/auction_worklet/public/mojom/seller_worklet.mojom.h"
@@ -548,9 +547,9 @@
       component_auction_modified_bid_params->has_bid =
           result_dict.Get("bid", &component_auction_modified_bid_params->bid);
       if (component_auction_modified_bid_params->has_bid) {
-        // Fail if the new bid is not valid.
-        if (!BidderWorklet::IsValidBid(
-                component_auction_modified_bid_params->bid)) {
+        // Fail if the new bid is not valid or is 0 or less.
+        if (!std::isfinite(component_auction_modified_bid_params->bid) ||
+            component_auction_modified_bid_params->bid <= 0.0) {
           errors_out.push_back(
               base::StrCat({decision_logic_url_.spec(),
                             " scoreAd() returned an invalid bid."}));
diff --git a/content/services/auction_worklet/set_bid_bindings.cc b/content/services/auction_worklet/set_bid_bindings.cc
new file mode 100644
index 0000000..29c9f11d
--- /dev/null
+++ b/content/services/auction_worklet/set_bid_bindings.cc
@@ -0,0 +1,221 @@
+// 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 "content/services/auction_worklet/set_bid_bindings.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/strings/strcat.h"
+#include "base/strings/stringprintf.h"
+#include "content/services/auction_worklet/auction_v8_helper.h"
+#include "content/services/auction_worklet/public/mojom/bidder_worklet.mojom.h"
+#include "gin/converter.h"
+#include "gin/dictionary.h"
+#include "third_party/blink/public/common/interest_group/ad_auction_constants.h"
+#include "url/gurl.h"
+#include "url/url_constants.h"
+#include "v8/include/v8-exception.h"
+#include "v8/include/v8-external.h"
+#include "v8/include/v8-function-callback.h"
+#include "v8/include/v8-template.h"
+
+namespace auction_worklet {
+
+namespace {
+
+// Checks that `url` is a valid URL and is in `ads`. Appends an error to
+// `out_errors` if not. `error_prefix` is used in output error messages
+// only.
+bool IsAllowedAdUrl(const GURL& url,
+                    std::string& error_prefix,
+                    const char* argument_name,
+                    const std::vector<blink::InterestGroup::Ad>& ads,
+                    std::vector<std::string>& out_errors) {
+  if (!url.is_valid() || !url.SchemeIs(url::kHttpsScheme)) {
+    out_errors.push_back(base::StrCat({error_prefix, "bid ", argument_name,
+                                       " URL '", url.possibly_invalid_spec(),
+                                       "' isn't a valid https:// URL."}));
+    return false;
+  }
+
+  for (const auto& ad : ads) {
+    if (url == ad.render_url)
+      return true;
+  }
+  out_errors.push_back(
+      base::StrCat({error_prefix, "bid ", argument_name, " URL '",
+                    url.possibly_invalid_spec(),
+                    "' isn't one of the registered creative URLs."}));
+  return false;
+}
+
+}  // namespace
+
+mojom::BidderWorkletBidPtr SetBidBindings::TakeBid() {
+  DCHECK(has_bid());
+  return std::move(bid_);
+}
+
+SetBidBindings::SetBidBindings(
+    AuctionV8Helper* v8_helper,
+    v8::Local<v8::ObjectTemplate> global_template,
+    base::TimeTicks start,
+    bool has_top_level_seller_origin,
+    const absl::optional<std::vector<blink::InterestGroup::Ad>>& ads,
+    const absl::optional<std::vector<blink::InterestGroup::Ad>>& ad_components)
+    : v8_helper_(v8_helper),
+      start_(start),
+      has_top_level_seller_origin_(has_top_level_seller_origin),
+      ads_(ads),
+      ad_components_(ad_components) {
+  v8::Local<v8::External> v8_this =
+      v8::External::New(v8_helper_->isolate(), this);
+  v8::Local<v8::FunctionTemplate> v8_template = v8::FunctionTemplate::New(
+      v8_helper_->isolate(), &SetBidBindings::SetBid, v8_this);
+  v8_template->RemovePrototype();
+  global_template->Set(v8_helper_->CreateStringFromLiteral("setBid"),
+                       v8_template);
+}
+
+SetBidBindings::~SetBidBindings() = default;
+
+void SetBidBindings::SetBid(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  SetBidBindings* bindings =
+      static_cast<SetBidBindings*>(v8::External::Cast(*args.Data())->Value());
+  AuctionV8Helper* v8_helper = bindings->v8_helper_;
+
+  if (args.Length() < 1 || args[0].IsEmpty()) {
+    args.GetIsolate()->ThrowException(
+        v8::Exception::TypeError(v8_helper->CreateStringFromLiteral(
+            "setBid requires 1 object parameter")));
+    return;
+  }
+
+  std::vector<std::string> errors;
+  if (!bindings->SetBid(args[0], /*error_prefix=*/"", errors)) {
+    DCHECK_EQ(1u, errors.size());
+    // Remove the trailing period from the error message.
+    std::string error_msg = errors[0].substr(0, errors[0].length() - 1);
+    args.GetIsolate()->ThrowException(v8::Exception::TypeError(
+        v8_helper->CreateUtf8String(error_msg).ToLocalChecked()));
+    return;
+  }
+}
+
+bool SetBidBindings::SetBid(v8::Local<v8::Value> generate_bid_result,
+                            std::string error_prefix,
+                            std::vector<std::string>& errors_out) {
+  v8::Isolate* isolate = v8_helper_->isolate();
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  bid_.reset();
+
+  if (!generate_bid_result->IsObject()) {
+    errors_out.push_back(base::StrCat({error_prefix, "bid not an object."}));
+    return false;
+  }
+
+  gin::Dictionary result_dict(isolate, generate_bid_result.As<v8::Object>());
+
+  v8::Local<v8::Value> ad_object;
+  std::string ad_json;
+  double bid;
+  std::string render_url_string;
+  // Parse and validate values.
+  if (!result_dict.Get("ad", &ad_object) ||
+      !v8_helper_->ExtractJson(context, ad_object, &ad_json) ||
+      !result_dict.Get("bid", &bid) ||
+      !result_dict.Get("render", &render_url_string)) {
+    errors_out.push_back(
+        base::StrCat({error_prefix, "bid has incorrect structure."}));
+    return false;
+  }
+
+  if (has_top_level_seller_origin_) {
+    bool allow_component_auction;
+    if (!result_dict.Get("allowComponentAuction", &allow_component_auction) ||
+        !allow_component_auction) {
+      errors_out.push_back(
+          base::StrCat({error_prefix,
+                        "bid does not have allowComponentAuction "
+                        "set to true. Bid dropped from component auction."}));
+      return false;
+    }
+  }
+
+  if (!std::isfinite(bid) || bid < 0.0) {
+    // Bids should not be infinite or NaN.
+    errors_out.push_back(base::StringPrintf("%sbid of %lf is not a valid bid.",
+                                            error_prefix.c_str(), bid));
+    return false;
+  }
+  if (bid <= 0.0) {
+    // Not an error, just no bid.
+    return false;
+  }
+
+  GURL render_url(render_url_string);
+  if (!IsAllowedAdUrl(render_url, error_prefix, "render", *ads_, errors_out)) {
+    return false;
+  }
+
+  absl::optional<std::vector<GURL>> ad_component_urls;
+  v8::Local<v8::Value> ad_components;
+  if (result_dict.Get("adComponents", &ad_components) &&
+      !ad_components->IsNullOrUndefined()) {
+    if (!ad_components_) {
+      errors_out.push_back(
+          base::StrCat({error_prefix,
+                        "bid contains adComponents but InterestGroup has no "
+                        "adComponents."}));
+      return false;
+    }
+
+    if (!ad_components->IsArray()) {
+      errors_out.push_back(base::StrCat(
+          {error_prefix, "bid adComponents value must be an array."}));
+      return false;
+    }
+
+    v8::Local<v8::Array> ad_components_array = ad_components.As<v8::Array>();
+    if (ad_components_array->Length() > blink::kMaxAdAuctionAdComponents) {
+      errors_out.push_back(base::StringPrintf(
+          "%sbid adComponents with over %zu items.", error_prefix.c_str(),
+          blink::kMaxAdAuctionAdComponents));
+      return false;
+    }
+
+    ad_component_urls.emplace();
+    for (size_t i = 0; i < ad_components_array->Length(); ++i) {
+      std::string url_string;
+      if (!gin::ConvertFromV8(
+              isolate, ad_components_array->Get(context, i).ToLocalChecked(),
+              &url_string)) {
+        errors_out.push_back(base::StrCat(
+            {error_prefix,
+             "bid adComponents value must be an array of strings."}));
+        return false;
+      }
+
+      GURL ad_component_url(url_string);
+      if (!IsAllowedAdUrl(ad_component_url, error_prefix, "adComponents",
+                          *ad_components_, errors_out)) {
+        return false;
+      }
+      ad_component_urls->emplace_back(std::move(ad_component_url));
+    }
+  }
+
+  bid_ = mojom::BidderWorkletBid::New(
+      std::move(ad_json), bid, std::move(render_url),
+      std::move(ad_component_urls),
+      /*bid_duration=*/base::TimeTicks::Now() - start_);
+  return true;
+}
+
+}  // namespace auction_worklet
diff --git a/content/services/auction_worklet/set_bid_bindings.h b/content/services/auction_worklet/set_bid_bindings.h
new file mode 100644
index 0000000..a405b0e
--- /dev/null
+++ b/content/services/auction_worklet/set_bid_bindings.h
@@ -0,0 +1,59 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_SERVICES_AUCTION_WORKLET_SET_BID_BINDINGS_H_
+#define CONTENT_SERVICES_AUCTION_WORKLET_SET_BID_BINDINGS_H_
+
+#include "base/callback.h"
+#include "base/memory/raw_ptr.h"
+#include "content/services/auction_worklet/auction_v8_helper.h"
+#include "content/services/auction_worklet/public/mojom/bidder_worklet.mojom-forward.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/common/interest_group/interest_group.h"
+#include "url/gurl.h"
+#include "v8/include/v8-forward.h"
+
+namespace auction_worklet {
+
+// Class to manage bindings for setting a bidding result. Expected to be used
+// for a short-lived v8::Context.
+class SetBidBindings {
+ public:
+  // Add setBid method to `global_template`. The SetBidBindings must outlive
+  // the template, ads and ad_components.
+  SetBidBindings(
+      AuctionV8Helper* v8_helper,
+      v8::Local<v8::ObjectTemplate> global_template,
+      base::TimeTicks start,
+      bool has_top_level_seller_origin,
+      const absl::optional<std::vector<blink::InterestGroup::Ad>>& ads,
+      const absl::optional<std::vector<blink::InterestGroup::Ad>>&
+          ad_components);
+  SetBidBindings(const SetBidBindings&) = delete;
+  SetBidBindings& operator=(const SetBidBindings&) = delete;
+  ~SetBidBindings();
+
+  bool has_bid() const { return !bid_.is_null(); }
+  mojom::BidderWorkletBidPtr TakeBid();
+
+  bool SetBid(v8::Local<v8::Value> generate_bid_result,
+              std::string error_prefix,
+              std::vector<std::string>& errors_out);
+
+ private:
+  static void SetBid(const v8::FunctionCallbackInfo<v8::Value>& args);
+
+  const raw_ptr<AuctionV8Helper> v8_helper_;
+
+  base::TimeTicks start_;
+  bool has_top_level_seller_origin_;
+  const absl::optional<std::vector<blink::InterestGroup::Ad>>& ads_;
+  const absl::optional<std::vector<blink::InterestGroup::Ad>>& ad_components_;
+
+  mojom::BidderWorkletBidPtr bid_;
+};
+
+}  // namespace auction_worklet
+
+#endif  // CONTENT_SERVICES_AUCTION_WORKLET_SET_BID_BINDINGS_H_
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index f5e660e..cf80f89a 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -185,6 +185,8 @@
     "../public/test/mock_navigation_handle.h",
     "../public/test/mock_notification_observer.cc",
     "../public/test/mock_notification_observer.h",
+    "../public/test/mock_permission_controller.cc",
+    "../public/test/mock_permission_controller.h",
     "../public/test/mock_permission_manager.cc",
     "../public/test/mock_permission_manager.h",
     "../public/test/mock_policy_container_host.cc",
@@ -711,6 +713,9 @@
 # Fuchsia performance tests on smart displays use web_engine and a browser
 # like shell instead of an actual browser, so Fuchsia needs a separate target.
 if (is_fuchsia) {
+  # TODO(crbug.com/1310086): Split this test suite into chrome/WebEngine
+  # versions.
+  # TODO(crbug.com/1309686): Move WebEngine-specific suites to //fuchsia/engine
   group("performance_web_engine_test_suite") {
     testonly = true
     data = [ "//content/test/gpu/run_telemetry_benchmark_fuchsia.py" ]
@@ -1165,7 +1170,7 @@
     "../browser/file_system/file_system_url_loader_factory_browsertest.cc",
     "../browser/file_system/fileapi_browsertest.cc",
     "../browser/find_request_manager_browsertest.cc",
-    "../browser/font_access/font_access_manager_impl_browsertest.cc",
+    "../browser/font_access/font_access_manager_browsertest.cc",
     "../browser/font_unique_name_lookup/font_unique_name_browsertest.cc",
     "../browser/form_controls_browsertest.cc",
     "../browser/generic_sensor/generic_sensor_browsertest.cc",
@@ -2060,7 +2065,7 @@
     "../browser/file_system_access/safe_move_helper_unittest.cc",
     "../browser/first_party_sets/addition_overlaps_union_find_unittest.cc",
     "../browser/first_party_sets/first_party_sets_handler_impl_unittest.cc",
-    "../browser/font_access/font_access_manager_impl_unittest.cc",
+    "../browser/font_access/font_access_manager_unittest.cc",
     "../browser/font_access/font_enumeration_data_source_unittest.cc",
     "../browser/generic_sensor/sensor_provider_proxy_impl_unittest.cc",
     "../browser/geolocation/geolocation_service_impl_unittest.cc",
@@ -2244,6 +2249,7 @@
     "../browser/renderer_host/render_widget_host_view_base_unittest.cc",
     "../browser/renderer_host/render_widget_host_view_child_frame_unittest.cc",
     "../browser/renderer_host/renderer_sandboxed_process_launcher_delegate_unittest.cc",
+    "../browser/renderer_host/transient_allow_popup_unittest.cc",
     "../browser/renderer_host/visible_time_request_trigger_unittest.cc",
     "../browser/scheduler/browser_io_thread_delegate_unittest.cc",
     "../browser/scheduler/browser_task_executor_unittest.cc",
diff --git a/device/fido/cable/fido_tunnel_device.cc b/device/fido/cable/fido_tunnel_device.cc
index 7a8b1a0a..ecf0342b 100644
--- a/device/fido/cable/fido_tunnel_device.cc
+++ b/device/fido/cable/fido_tunnel_device.cc
@@ -151,16 +151,7 @@
   cbor::Value::MapValue client_payload;
   client_payload.emplace(1, pairing->id);
   client_payload.emplace(2, base::span<const uint8_t>(client_nonce));
-  const char* request_type_str;
-  switch (request_type) {
-    case FidoRequestType::kMakeCredential:
-      request_type_str = "mc";
-      break;
-    case FidoRequestType::kGetAssertion:
-      request_type_str = "ga";
-      break;
-  }
-  client_payload.emplace(3, request_type_str);
+  client_payload.emplace(3, RequestTypeToString(request_type));
   const absl::optional<std::vector<uint8_t>> client_payload_bytes =
       cbor::Writer::Write(cbor::Value(std::move(client_payload)));
   CHECK(client_payload_bytes.has_value());
diff --git a/device/fido/cable/v2_handshake.cc b/device/fido/cable/v2_handshake.cc
index bb5d17266..fd5ef3d2 100644
--- a/device/fido/cable/v2_handshake.cc
+++ b/device/fido/cable/v2_handshake.cc
@@ -424,10 +424,19 @@
     ret.supports_linking = it->second.GetBool();
   }
 
+  it = qr_contents_map.find(cbor::Value(5));
+  if (it != qr_contents_map.end()) {
+    if (!it->second.is_string()) {
+      return absl::nullopt;
+    }
+    ret.request_type = RequestTypeFromString(it->second.GetString());
+  }
+
   return ret;
 }
 
-std::string Encode(base::span<const uint8_t, kQRKeySize> qr_key) {
+std::string Encode(base::span<const uint8_t, kQRKeySize> qr_key,
+                   FidoRequestType request_type) {
   cbor::Value::MapValue qr_contents;
   qr_contents.emplace(
       0, SeedToCompressedPublicKey(
@@ -443,6 +452,8 @@
 
   qr_contents.emplace(4, true);  // client supports storing linking information.
 
+  qr_contents.emplace(5, RequestTypeToString(request_type));
+
   const absl::optional<std::vector<uint8_t>> qr_data =
       cbor::Writer::Write(cbor::Value(std::move(qr_contents)));
   return std::string(kPrefix) + BytesToDigits(*qr_data);
@@ -588,6 +599,24 @@
 
 }  // namespace internal
 
+const char* RequestTypeToString(FidoRequestType request_type) {
+  switch (request_type) {
+    case FidoRequestType::kMakeCredential:
+      return "mc";
+    case FidoRequestType::kGetAssertion:
+      return "ga";
+      // If adding a value here, also update `RequestTypeFromString`.
+  }
+}
+
+FidoRequestType RequestTypeFromString(const std::string& s) {
+  if (s == "mc") {
+    return FidoRequestType::kMakeCredential;
+  }
+  // kGetAssertion is the default if the value is unknown too.
+  return FidoRequestType::kGetAssertion;
+}
+
 bssl::UniquePtr<EC_KEY> IdentityKey(base::span<const uint8_t, 32> root_secret) {
   std::array<uint8_t, 32> seed;
   seed = device::cablev2::Derive<EXTENT(seed)>(
diff --git a/device/fido/cable/v2_handshake.h b/device/fido/cable/v2_handshake.h
index a5740bc..7292e0d 100644
--- a/device/fido/cable/v2_handshake.h
+++ b/device/fido/cable/v2_handshake.h
@@ -119,6 +119,11 @@
   // and later using linking information. If this is false, an authenticator
   // may wish to avoid bothering the user about linking.
   bool supports_linking = false;
+
+  // request_type contains the hinted type of the request. This can
+  // be used to guide UI ahead of receiving the actual request. This defaults to
+  // `kGetAssertion` if not present or if the value in the QR code is unknown.
+  FidoRequestType request_type = FidoRequestType::kGetAssertion;
 };
 
 COMPONENT_EXPORT(DEVICE_FIDO)
@@ -126,7 +131,8 @@
 
 // Encode returns the contents of a QR code that represents |qr_key|.
 COMPONENT_EXPORT(DEVICE_FIDO)
-std::string Encode(base::span<const uint8_t, kQRKeySize> qr_key);
+std::string Encode(base::span<const uint8_t, kQRKeySize> qr_key,
+                   FidoRequestType request_type);
 
 // BytesToDigits returns a base-10 encoding of |in|.
 COMPONENT_EXPORT(DEVICE_FIDO)
@@ -172,6 +178,18 @@
             DerivedValueType type);
 }  // namespace internal
 
+// RequestTypeToString maps |request_type| to either "ga" (for getAssertion) or
+// "mc" (for makeCredential). These strings are encoded in the QR code and
+// client payload to give the phone an early hint about the type of request.
+// This lets it craft better UI.
+COMPONENT_EXPORT(DEVICE_FIDO)
+const char* RequestTypeToString(FidoRequestType request_type);
+
+// RequestTypeFromString performs the inverse of `RequestTypeToString`. If the
+// value of `s` is unknown, `kGetAssertion` is returned.
+COMPONENT_EXPORT(DEVICE_FIDO)
+FidoRequestType RequestTypeFromString(const std::string& s);
+
 // Derive derives a sub-secret from a secret and nonce. It is not possible to
 // learn anything about |secret| from the value of the sub-secret, assuming that
 // |secret| has sufficient size to prevent full enumeration of the
diff --git a/device/fido/cable/v2_handshake_unittest.cc b/device/fido/cable/v2_handshake_unittest.cc
index 5f80410..b46e2c5 100644
--- a/device/fido/cable/v2_handshake_unittest.cc
+++ b/device/fido/cable/v2_handshake_unittest.cc
@@ -79,7 +79,7 @@
 TEST(CableV2Encoding, QRs) {
   std::array<uint8_t, kQRKeySize> qr_key;
   crypto::RandBytes(qr_key);
-  std::string url = qr::Encode(qr_key);
+  std::string url = qr::Encode(qr_key, FidoRequestType::kMakeCredential);
   const absl::optional<qr::Components> decoded = qr::Parse(url);
   ASSERT_TRUE(decoded.has_value()) << url;
   static_assert(EXTENT(qr_key) >= EXTENT(decoded->secret), "");
@@ -94,11 +94,23 @@
   // Chromium always sets this flag.
   EXPECT_TRUE(decoded->supports_linking);
 
+  EXPECT_EQ(decoded->request_type, FidoRequestType::kMakeCredential);
+
   url[0] ^= 4;
   EXPECT_FALSE(qr::Parse(url));
   EXPECT_FALSE(qr::Parse("nonsense"));
 }
 
+TEST(CableV2Encoding, RequestTypeToString) {
+  for (const auto type :
+       {FidoRequestType::kMakeCredential, FidoRequestType::kGetAssertion}) {
+    EXPECT_EQ(type, RequestTypeFromString(RequestTypeToString(type)));
+  }
+
+  EXPECT_EQ(FidoRequestType::kGetAssertion, RequestTypeFromString("nonsense"));
+  EXPECT_EQ(FidoRequestType::kGetAssertion, RequestTypeFromString(""));
+}
+
 TEST(CableV2Encoding, PaddedCBOR) {
   cbor::Value::MapValue map1;
   absl::optional<std::vector<uint8_t>> encoded =
diff --git a/docs/mac_build_instructions.md b/docs/mac_build_instructions.md
index a4b77f4..ce31f21 100644
--- a/docs/mac_build_instructions.md
+++ b/docs/mac_build_instructions.md
@@ -276,7 +276,7 @@
 default, this command:
 
 ```shell
-$ sysctl -a | egrep kern\..*vnodes
+$ sysctl -a | egrep 'kern\..*vnodes'
 ```
 
 Outputs `kern.maxvnodes: 263168` (263168 is 257 * 1024).  To increase this
@@ -287,11 +287,26 @@
 ```
 
 Higher values may be appropriate if you routinely move between different
-Chromium checkouts.  This setting will reset on reboot, the startup setting can
-be set in `/etc/sysctl.conf`:
+Chromium checkouts.  This setting will reset on reboot.  To apply it at startup:
 
 ```shell
-$ echo kern.maxvnodes=$((512*1024)) | sudo tee -a /etc/sysctl.conf
+$ sudo tee /Library/LaunchDaemons/kern.maxvnodes.plist > /dev/null <<EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+  <dict>
+    <key>Label</key>
+      <string>kern.maxvnodes</string>
+    <key>ProgramArguments</key>
+      <array>
+        <string>sysctl</string>
+        <string>kern.maxvnodes=524288</string>
+      </array>
+    <key>RunAtLoad</key>
+      <true/>
+  </dict>
+</plist>
+EOF
 ```
 
 Or edit the file directly.
diff --git a/extensions/browser/guest_view/web_view/web_view_apitest.cc b/extensions/browser/guest_view/web_view/web_view_apitest.cc
index 4a991a09..433e4e7 100644
--- a/extensions/browser/guest_view/web_view/web_view_apitest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_apitest.cc
@@ -903,8 +903,10 @@
     : public WebViewAPITest {
  public:
   void SetUp() override {
-    scoped_feature_list_.InitAndEnableFeature(
-        blink::features::kUserAgentOverrideExperiment);
+    scoped_feature_list_.InitWithFeatures(
+        {blink::features::kUserAgentOverrideExperiment,
+         blink::features::kUACHOverrideBlank},
+        {});
     WebViewAPITest::SetUp();
   }
 
diff --git a/extensions/renderer/resources/web_request_event.js b/extensions/renderer/resources/web_request_event.js
index 31557ca..833b0b63 100644
--- a/extensions/renderer/resources/web_request_event.js
+++ b/extensions/renderer/resources/web_request_event.js
@@ -8,7 +8,7 @@
 var webRequestInternal = getInternalApi('webRequestInternal');
 
 function getUniqueSubEventName(eventName) {
-  return eventName + '/' + idGeneratorNatives.GetNextScopedId();
+  return eventName + '/' + idGeneratorNatives.GetNextId();
 }
 
 // WebRequestEventImpl object. This is used for special webRequest events
diff --git a/fuchsia/engine/browser/content_directory_loader_factory.cc b/fuchsia/engine/browser/content_directory_loader_factory.cc
index a8ae92d7..3ff659d 100644
--- a/fuchsia/engine/browser/content_directory_loader_factory.cc
+++ b/fuchsia/engine/browser/content_directory_loader_factory.cc
@@ -312,9 +312,10 @@
           .Append(content_directory_name)
           .Append(relative_file_path);
 
-  zx_status_t status = fdio_open(absolute_file_path.value().c_str(),
-                                 fuchsia::io::OPEN_RIGHT_READABLE,
-                                 file_request.TakeChannel().release());
+  const zx_status_t status =
+      fdio_open(absolute_file_path.value().c_str(),
+                static_cast<uint32_t>(fuchsia::io::OPEN_RIGHT_READABLE),
+                file_request.TakeChannel().release());
   if (status != ZX_OK) {
     ZX_DLOG(WARNING, status) << "fdio_open";
     return net::ERR_FILE_NOT_FOUND;
diff --git a/fuchsia/engine/context_provider_impl_unittest.cc b/fuchsia/engine/context_provider_impl_unittest.cc
index 78c7be43..5a0d3ff 100644
--- a/fuchsia/engine/context_provider_impl_unittest.cc
+++ b/fuchsia/engine/context_provider_impl_unittest.cc
@@ -166,9 +166,9 @@
     // Bind /tmp in the new Component's flat namespace, to allow it to see
     // the GTest flagfile, if any.
     fuchsia::io::DirectoryHandle tmp_directory;
-    zx_status_t status =
-        fdio_open("/tmp", fuchsia::io::OPEN_RIGHT_READABLE,
-                  tmp_directory.NewRequest().TakeChannel().release());
+    zx_status_t status = fdio_open(
+        "/tmp", static_cast<uint32_t>(fuchsia::io::OPEN_RIGHT_READABLE),
+        tmp_directory.NewRequest().TakeChannel().release());
     ZX_CHECK(status == ZX_OK, status) << "fdio_open(/tmp)";
     launch_info.flat_namespace->paths.push_back("/tmp");
     launch_info.flat_namespace->directories.push_back(
@@ -730,12 +730,12 @@
   base::RunLoop loop;
   provider_->set_config_for_test(std::move(config_dict));
   fake_environment_.fake_launcher().set_create_component_callback(
-      base::BindLambdaForTesting([&loop, kDummyApiKey](
-                                     const base::CommandLine& command) {
-        loop.Quit();
-        EXPECT_EQ(command.GetSwitchValueASCII(switches::kGoogleApiKey),
-                  kDummyApiKey);
-      }));
+      base::BindLambdaForTesting(
+          [&loop, kDummyApiKey](const base::CommandLine& command) {
+            loop.Quit();
+            EXPECT_EQ(command.GetSwitchValueASCII(switches::kGoogleApiKey),
+                      kDummyApiKey);
+          }));
 
   fuchsia::web::ContextPtr context;
   context.set_error_handler([&loop](zx_status_t status) {
diff --git a/fuchsia/engine/test/web_engine_shell.cc b/fuchsia/engine/test/web_engine_shell.cc
index 2f118945..77f5d0b 100644
--- a/fuchsia/engine/test/web_engine_shell.cc
+++ b/fuchsia/engine/test/web_engine_shell.cc
@@ -236,11 +236,12 @@
   } else {
     web_instance_host = std::make_unique<cr_fuchsia::WebInstanceHost>();
     if (enable_web_instance_tmp) {
-      zx_status_t status = fdio_open(
-          "/tmp",
-          fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_RIGHT_WRITABLE |
-              fuchsia::io::OPEN_FLAG_DIRECTORY,
-          tmp_directory.NewRequest().TakeChannel().release());
+      const zx_status_t status =
+          fdio_open("/tmp",
+                    static_cast<uint32_t>(fuchsia::io::OPEN_RIGHT_READABLE |
+                                          fuchsia::io::OPEN_RIGHT_WRITABLE |
+                                          fuchsia::io::OPEN_FLAG_DIRECTORY),
+                    tmp_directory.NewRequest().TakeChannel().release());
       ZX_CHECK(status == ZX_OK, status) << "fdio_open(/tmp)";
       web_instance_host->set_tmp_dir(std::move(tmp_directory));
     }
diff --git a/ios/chrome/browser/prerender/BUILD.gn b/ios/chrome/browser/prerender/BUILD.gn
index ee330f6..4f9d5cf 100644
--- a/ios/chrome/browser/prerender/BUILD.gn
+++ b/ios/chrome/browser/prerender/BUILD.gn
@@ -103,6 +103,7 @@
   sources = [ "prerender_egtest.mm" ]
   deps = [
     "//components/version_info",
+    "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/popup_menu:constants",
     "//ios/chrome/test/earl_grey:eg_test_support+eg2",
     "//ios/testing/earl_grey:eg_test_support+eg2",
diff --git a/ios/chrome/browser/prerender/prerender_egtest.mm b/ios/chrome/browser/prerender/prerender_egtest.mm
index 23d03737..5be7b7f2 100644
--- a/ios/chrome/browser/prerender/prerender_egtest.mm
+++ b/ios/chrome/browser/prerender/prerender_egtest.mm
@@ -12,6 +12,7 @@
 #import "base/test/ios/wait_util.h"
 #include "components/version_info/version_info.h"
 #import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h"
+#include "ios/chrome/browser/ui/ui_feature_flags.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
@@ -170,9 +171,13 @@
   [[EarlGrey
       selectElementWithMatcher:grey_allOf(
                                    grey_accessibilityLabel(pageString),
-                                   grey_kindOfClassName(@"FadeTruncatingLabel"),
+                                   [ChromeEarlGrey isNewOmniboxPopupEnabled]
+                                       ? grey_accessibilityTrait(
+                                             UIAccessibilityTraitStaticText)
+                                       : grey_kindOfClassName(
+                                             @"FadeTruncatingLabel"),
                                    grey_ancestor(grey_accessibilityID(
-                                       @"omnibox suggestion 0")),
+                                       @"omnibox suggestion 0 0")),
                                    grey_sufficientlyVisible(), nil)]
       performAction:grey_tap()];
 
@@ -215,7 +220,7 @@
                                    grey_accessibilityLabel(pageString),
                                    grey_kindOfClassName(@"FadeTruncatingLabel"),
                                    grey_ancestor(grey_accessibilityID(
-                                       @"omnibox suggestion 0")),
+                                       @"omnibox suggestion 0 0")),
                                    grey_sufficientlyVisible(), nil)]
       performAction:grey_tap()];
 
@@ -243,3 +248,21 @@
 }
 
 @end
+
+// Test case for the prerender, except new popup flag is enabled.
+@interface NewOmniboxPopupPrerenderTestCase : PrerenderTestCase
+@end
+
+@implementation NewOmniboxPopupPrerenderTestCase
+
+- (AppLaunchConfiguration)appConfigurationForTestCase {
+  AppLaunchConfiguration config = [super appConfigurationForTestCase];
+  config.features_enabled.push_back(kIOSOmniboxUpdatedPopupUI);
+  return config;
+}
+
+// This is currently needed to prevent this test case from being ignored.
+- (void)testEmpty {
+}
+
+@end
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
index 183aa16..e18c4b2 100644
--- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn
+++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -296,6 +296,7 @@
     "//ios/chrome/app/strings",
     "//ios/chrome/browser:pref_names",
     "//ios/chrome/browser:utils",
+    "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/content_suggestions/cells:constants",
     "//ios/chrome/browser/ui/ntp:constants",
     "//ios/chrome/browser/ui/ntp:feature_flags",
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
index 7019ee9..7dfe671 100644
--- a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
+++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
@@ -21,6 +21,7 @@
 #import "ios/chrome/browser/ui/settings/settings_table_view_controller_constants.h"
 #import "ios/chrome/browser/ui/start_surface/start_surface_features.h"
 #import "ios/chrome/browser/ui/toolbar/public/toolbar_constants.h"
+#include "ios/chrome/browser/ui/ui_feature_flags.h"
 #include "ios/chrome/grit/ios_strings.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h"
@@ -249,8 +250,11 @@
   [[EarlGrey
       selectElementWithMatcher:
           grey_allOf(
-              grey_accessibilityID(@"omnibox suggestion 1"),
-              grey_kindOfClassName(@"OmniboxPopupRowCell"),
+              [ChromeEarlGrey isNewOmniboxPopupEnabled]
+                  ? grey_descendant(
+                        grey_accessibilityID(@"omnibox suggestion 0 1"))
+                  : grey_accessibilityID(@"omnibox suggestion 0 1"),
+              chrome_test_util::OmniboxPopupRow(),
               grey_descendant(
                   chrome_test_util::StaticTextWithAccessibilityLabel(URL)),
               grey_sufficientlyVisible(), nil)] performAction:grey_tap()];
@@ -1053,3 +1057,21 @@
 }
 
 @end
+
+// Test case for the NTP home UI, except the new omnibox popup flag is enabled.
+@interface NewOmniboxPopupNTPHomeTestCase : NTPHomeTestCase
+@end
+
+@implementation NewOmniboxPopupNTPHomeTestCase
+
+- (AppLaunchConfiguration)appConfigurationForTestCase {
+  AppLaunchConfiguration config = [super appConfigurationForTestCase];
+  config.features_enabled.push_back(kIOSOmniboxUpdatedPopupUI);
+  return config;
+}
+
+// This is currently needed to prevent this test case from being ignored.
+- (void)testEmpty {
+}
+
+@end
diff --git a/ios/chrome/browser/ui/first_run/signin/BUILD.gn b/ios/chrome/browser/ui/first_run/signin/BUILD.gn
index b0cc2475..91cd38a1 100644
--- a/ios/chrome/browser/ui/first_run/signin/BUILD.gn
+++ b/ios/chrome/browser/ui/first_run/signin/BUILD.gn
@@ -16,10 +16,16 @@
     "//components/prefs",
     "//ios/chrome/browser:application_context",
     "//ios/chrome/browser/browser_state",
+    "//ios/chrome/browser/first_run",
     "//ios/chrome/browser/main",
     "//ios/chrome/browser/signin",
     "//ios/chrome/browser/sync",
     "//ios/chrome/browser/ui/authentication/enterprise:enterprise_utils",
+    "//ios/chrome/browser/ui/authentication/signin:signin_headers",
+    "//ios/chrome/browser/ui/authentication/unified_consent/identity_chooser",
+    "//ios/chrome/browser/ui/commands",
+    "//ios/chrome/browser/ui/first_run/uma",
+    "//ios/chrome/browser/ui/first_run/welcome",
     "//ios/public/provider/chrome/browser",
     "//ios/public/provider/chrome/browser/signin",
   ]
@@ -35,6 +41,7 @@
   deps = [
     "//ios/chrome/app/strings",
     "//ios/chrome/browser/ui/authentication/views",
+    "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/elements:elements_internal",
     "//ios/chrome/browser/ui/first_run:constants",
     "//ios/chrome/browser/ui/first_run/resources:signin_banner",
diff --git a/ios/chrome/browser/ui/first_run/signin/signin_screen_coordinator.mm b/ios/chrome/browser/ui/first_run/signin/signin_screen_coordinator.mm
index f4612ef..6260e32 100644
--- a/ios/chrome/browser/ui/first_run/signin/signin_screen_coordinator.mm
+++ b/ios/chrome/browser/ui/first_run/signin/signin_screen_coordinator.mm
@@ -7,17 +7,29 @@
 #import "ios/chrome/browser/application_context.h"
 #import "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #import "ios/chrome/browser/main/browser.h"
+#import "ios/chrome/browser/signin/authentication_service.h"
 #import "ios/chrome/browser/signin/authentication_service_factory.h"
+#import "ios/chrome/browser/signin/chrome_account_manager_service.h"
 #import "ios/chrome/browser/signin/chrome_account_manager_service_factory.h"
 #import "ios/chrome/browser/sync/sync_service_factory.h"
+#import "ios/chrome/browser/ui/authentication/signin/signin_coordinator.h"
+#import "ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_coordinator.h"
+#import "ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_coordinator_delegate.h"
+#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
+#import "ios/chrome/browser/ui/commands/tos_commands.h"
 #import "ios/chrome/browser/ui/first_run/signin/signin_screen_mediator.h"
 #import "ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.h"
+#import "ios/chrome/browser/ui/first_run/uma/uma_coordinator.h"
+#import "ios/chrome/browser/ui/first_run/welcome/tos_coordinator.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
-@interface SigninScreenCoordinator () <SigninScreenViewControllerDelegate>
+@interface SigninScreenCoordinator () <IdentityChooserCoordinatorDelegate,
+                                       SigninScreenViewControllerDelegate,
+                                       TOSCommands,
+                                       UMACoordinatorDelegate>
 
 // Show FRE consent.
 @property(nonatomic, assign) BOOL showFREConsent;
@@ -27,6 +39,21 @@
 @property(nonatomic, strong) SigninScreenViewController* viewController;
 // Sign-in screen mediator.
 @property(nonatomic, strong) SigninScreenMediator* mediator;
+// Whether the user tapped on the TOS link.
+@property(nonatomic, assign) BOOL TOSLinkWasTapped;
+// Account manager service.
+@property(nonatomic, assign) ChromeAccountManagerService* accountManagerService;
+// Authentication service.
+@property(nonatomic, assign) AuthenticationService* authenticationService;
+// Coordinator used to manage the TOS page.
+@property(nonatomic, strong) TOSCoordinator* TOSCoordinator;
+// Coordinator to show the metric reportingn dialog.
+@property(nonatomic, strong) UMACoordinator* UMACoordinator;
+// Coordinator to choose an identity.
+@property(nonatomic, strong)
+    IdentityChooserCoordinator* identityChooserCoordinator;
+// Coordinator to add an identity.
+@property(nonatomic, strong) SigninCoordinator* addAccountSigninCoordinator;
 
 @end
 
@@ -52,22 +79,28 @@
 }
 
 - (void)start {
+  [self.browser->GetCommandDispatcher()
+      startDispatchingToTarget:self
+                   forProtocol:@protocol(TOSCommands)];
+  id<TOSCommands> TOSHandler =
+      HandlerForProtocol(self.browser->GetCommandDispatcher(), TOSCommands);
   self.viewController = [[SigninScreenViewController alloc] init];
+  self.viewController.TOSHandler = TOSHandler;
   self.viewController.delegate = self;
   self.viewController.modalInPresentation = YES;
 
   ChromeBrowserState* browserState = self.browser->GetBrowserState();
-  AuthenticationService* authenticationService =
+  self.authenticationService =
       AuthenticationServiceFactory::GetForBrowserState(browserState);
-  ChromeAccountManagerService* accountManagerService =
+  self.accountManagerService =
       ChromeAccountManagerServiceFactory::GetForBrowserState(browserState);
   PrefService* localPrefService = GetApplicationContext()->GetLocalState();
   PrefService* prefService = browserState->GetPrefs();
   syncer::SyncService* syncService =
       SyncServiceFactory::GetForBrowserState(browserState);
   self.mediator = [[SigninScreenMediator alloc]
-      initWithAccountManagerService:accountManagerService
-              authenticationService:authenticationService
+      initWithAccountManagerService:self.accountManagerService
+              authenticationService:self.authenticationService
                    localPrefService:localPrefService
                         prefService:prefService
                         syncService:syncService
@@ -83,20 +116,135 @@
   self.viewController = nil;
   [self.mediator disconnect];
   self.mediator = nil;
+  self.accountManagerService = nil;
+  self.authenticationService = nil;
+}
+
+#pragma mark - Private
+
+// Starts the coordinator to present the Add Account module.
+- (void)triggerAddAccount {
+  self.addAccountSigninCoordinator = [SigninCoordinator
+      addAccountCoordinatorWithBaseViewController:self.viewController
+                                          browser:self.browser
+                                      accessPoint:signin_metrics::AccessPoint::
+                                                      ACCESS_POINT_START_PAGE];
+  __weak __typeof(self) weakSelf = self;
+  self.addAccountSigninCoordinator.signinCompletion =
+      ^(SigninCoordinatorResult signinResult,
+        SigninCompletionInfo* signinCompletionInfo) {
+        [weakSelf addAccountSigninCompleteWithResult:signinResult
+                                      completionInfo:signinCompletionInfo];
+      };
+  [self.addAccountSigninCoordinator start];
+}
+
+// Callback handling the completion of the AddAccount action.
+- (void)addAccountSigninCompleteWithResult:(SigninCoordinatorResult)signinResult
+                            completionInfo:
+                                (SigninCompletionInfo*)signinCompletionInfo {
+  [self.addAccountSigninCoordinator stop];
+  self.addAccountSigninCoordinator = nil;
+  if (signinResult == SigninCoordinatorResultSuccess &&
+      self.accountManagerService->IsValidIdentity(
+          signinCompletionInfo.identity)) {
+    self.mediator.selectedIdentity = signinCompletionInfo.identity;
+  }
+}
+
+#pragma mark - IdentityChooserCoordinatorDelegate
+
+- (void)identityChooserCoordinatorDidClose:
+    (IdentityChooserCoordinator*)coordinator {
+  CHECK_EQ(self.identityChooserCoordinator, coordinator);
+  [self.identityChooserCoordinator stop];
+  self.identityChooserCoordinator = nil;
+}
+
+- (void)identityChooserCoordinatorDidTapOnAddAccount:
+    (IdentityChooserCoordinator*)coordinator {
+  CHECK_EQ(self.identityChooserCoordinator, coordinator);
+  DCHECK(!self.addAccountSigninCoordinator);
+  [self triggerAddAccount];
+}
+
+- (void)identityChooserCoordinator:(IdentityChooserCoordinator*)coordinator
+                 didSelectIdentity:(ChromeIdentity*)identity {
+  CHECK_EQ(self.identityChooserCoordinator, coordinator);
+  self.mediator.selectedIdentity = identity;
+}
+
+#pragma mark - PromoStyleViewControllerDelegate
+
+- (void)didTapPrimaryActionButton {
+  switch (self.authenticationService->GetServiceStatus()) {
+    case AuthenticationService::ServiceStatus::SigninForcedByPolicy:
+    case AuthenticationService::ServiceStatus::SigninAllowed:
+      if (self.mediator.selectedIdentity) {
+        // TODO(crbug.com/1304266): Needs implementation.
+        NOTIMPLEMENTED();
+      } else {
+        [self triggerAddAccount];
+      }
+      break;
+    case AuthenticationService::ServiceStatus::SigninDisabledByUser:
+    case AuthenticationService::ServiceStatus::SigninDisabledByPolicy:
+    case AuthenticationService::ServiceStatus::SigninDisabledByInternal:
+      // TODO(crbug.com/1304266): Needs implementation.
+      return;
+  }
+}
+
+- (void)didTapSecondaryActionButton {
+  // TODO(crbug.com/1304266): Needs implementation.
+  NOTIMPLEMENTED();
 }
 
 #pragma mark - SigninScreenViewControllerDelegate
 
 - (void)showAccountPickerFromPoint:(CGPoint)point {
-  NOTIMPLEMENTED();
-}
-
-- (void)showTOSDialog {
-  NOTIMPLEMENTED();
+  self.identityChooserCoordinator = [[IdentityChooserCoordinator alloc]
+      initWithBaseViewController:self.viewController
+                         browser:self.browser];
+  self.identityChooserCoordinator.delegate = self;
+  self.identityChooserCoordinator.origin = point;
+  [self.identityChooserCoordinator start];
+  self.identityChooserCoordinator.selectedIdentity =
+      self.mediator.selectedIdentity;
 }
 
 - (void)showUMADialog {
-  NOTIMPLEMENTED();
+  DCHECK(!self.UMACoordinator);
+  self.UMACoordinator =
+      [[UMACoordinator alloc] initWithBaseViewController:self.viewController
+                                                 browser:self.browser];
+  self.UMACoordinator.delegate = self;
+  [self.UMACoordinator start];
+}
+
+#pragma mark - TOSCommands
+
+- (void)showTOSPage {
+  DCHECK(!self.TOSCoordinator);
+  self.TOSLinkWasTapped = YES;
+  self.TOSCoordinator =
+      [[TOSCoordinator alloc] initWithBaseViewController:self.viewController
+                                                 browser:self.browser];
+  [self.TOSCoordinator start];
+}
+
+- (void)hideTOSPage {
+  DCHECK(self.TOSCoordinator);
+  [self.TOSCoordinator stop];
+  self.TOSCoordinator = nil;
+}
+
+#pragma mark - UMACoordinatorDelegate
+
+- (void)UMACoordinatorDidRemove:(UMACoordinator*)coordinator {
+  DCHECK(self.UMACoordinator);
+  DCHECK_EQ(self.UMACoordinator, coordinator);
+  self.UMACoordinator = nil;
 }
 
 @end
diff --git a/ios/chrome/browser/ui/first_run/signin/signin_screen_mediator.h b/ios/chrome/browser/ui/first_run/signin/signin_screen_mediator.h
index 6f8f183..07022c8 100644
--- a/ios/chrome/browser/ui/first_run/signin/signin_screen_mediator.h
+++ b/ios/chrome/browser/ui/first_run/signin/signin_screen_mediator.h
@@ -9,6 +9,7 @@
 
 class AuthenticationService;
 class ChromeAccountManagerService;
+@class ChromeIdentity;
 class PrefService;
 @protocol SigninScreenConsumer;
 namespace syncer {
@@ -20,6 +21,8 @@
 
 // Consumer for this mediator.
 @property(nonatomic, weak) id<SigninScreenConsumer> consumer;
+// The identity currently selected.
+@property(nonatomic, strong, readwrite) ChromeIdentity* selectedIdentity;
 
 // The designated initializer.
 // |accountManagerService| account manager service.
diff --git a/ios/chrome/browser/ui/first_run/signin/signin_screen_mediator.mm b/ios/chrome/browser/ui/first_run/signin/signin_screen_mediator.mm
index 1ba4ea4f..05c0074 100644
--- a/ios/chrome/browser/ui/first_run/signin/signin_screen_mediator.mm
+++ b/ios/chrome/browser/ui/first_run/signin/signin_screen_mediator.mm
@@ -32,8 +32,6 @@
 @property(nonatomic, assign) PrefService* prefService;
 // Sync service.
 @property(nonatomic, assign) syncer::SyncService* syncService;
-// The identity currently selected.
-@property(nonatomic, strong) ChromeIdentity* selectedIdentity;
 
 @end
 
diff --git a/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.h b/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.h
index 34fe477..7b0e53ae 100644
--- a/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.h
+++ b/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.h
@@ -10,15 +10,14 @@
 #import "ios/chrome/browser/ui/first_run/signin/signin_screen_consumer.h"
 #import "ios/chrome/common/ui/promo_style/promo_style_view_controller.h"
 
+@protocol TOSCommands;
+
 // Delegate of sign-in screen view controller.
 @protocol SigninScreenViewControllerDelegate <PromoStyleViewControllerDelegate>
 
 // Called when the user taps to see the account picker.
 - (void)showAccountPickerFromPoint:(CGPoint)point;
 
-// Called when the user taps on "terms of service" link.
-- (void)showTOSDialog;
-
 // Called when the user taps on "Manage" related to metric reporting.
 - (void)showUMADialog;
 
@@ -28,6 +27,8 @@
 @interface SigninScreenViewController
     : PromoStyleViewController <SigninScreenConsumer>
 
+// Handler to open the terms of service dialog.
+@property(nonatomic, weak) id<TOSCommands> TOSHandler;
 @property(nonatomic, weak) id<SigninScreenViewControllerDelegate> delegate;
 
 @end
diff --git a/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.mm b/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.mm
index 3cd8e0d6..c2c971f 100644
--- a/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.mm
+++ b/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.mm
@@ -7,6 +7,7 @@
 #import "base/notreached.h"
 #import "base/strings/sys_string_conversions.h"
 #import "ios/chrome/browser/ui/authentication/views/identity_button_control.h"
+#import "ios/chrome/browser/ui/commands/tos_commands.h"
 #import "ios/chrome/browser/ui/elements/activity_overlay_view.h"
 #import "ios/chrome/browser/ui/first_run/first_run_constants.h"
 #import "ios/chrome/browser/ui/settings/elements/enterprise_info_popover_view_controller.h"
@@ -378,7 +379,7 @@
                   inRange:(NSRange)characterRange
               interaction:(UITextItemInteraction)interaction {
   if ([URL.absoluteString isEqualToString:kTermsOfServiceURL]) {
-    [self.delegate showTOSDialog];
+    [self.TOSHandler showTOSPage];
   } else if ([URL.absoluteString isEqualToString:kMetricReportingURL]) {
     [self.delegate showUMADialog];
   } else {
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm
index 17647c4..5f724a3 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm
@@ -428,9 +428,7 @@
       performAction:grey_typeText(@"Obama")];
 
   // The popup should open.
-  [[EarlGrey
-      selectElementWithMatcher:
-          grey_accessibilityID(kOmniboxPopupTableViewAccessibilityIdentifier)]
+  [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxPopupList()]
       assertWithMatcher:grey_notNil()];
 
   // Switch to the first tab.
@@ -439,9 +437,7 @@
 
   // The omnibox shouldn't be focused and the popup should be closed.
   [self checkLocationBarSteadyState];
-  [[EarlGrey
-      selectElementWithMatcher:
-          grey_accessibilityID(kOmniboxPopupTableViewAccessibilityIdentifier)]
+  [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxPopupList()]
       assertWithMatcher:grey_notVisible()];
 }
 
@@ -465,9 +461,7 @@
       performAction:grey_typeText(@"Obama")];
 
   // The popup should open.
-  [[EarlGrey
-      selectElementWithMatcher:
-          grey_accessibilityID(kOmniboxPopupTableViewAccessibilityIdentifier)]
+  [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxPopupList()]
       assertWithMatcher:grey_notNil()];
 
   // Switch to the first tab.
@@ -476,9 +470,7 @@
 
   // The omnibox shouldn't be focused and the popup should be closed.
   [self checkLocationBarSteadyState];
-  [[EarlGrey
-      selectElementWithMatcher:
-          grey_accessibilityID(kOmniboxPopupTableViewAccessibilityIdentifier)]
+  [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxPopupList()]
       assertWithMatcher:grey_notVisible()];
 }
 
@@ -512,6 +504,25 @@
 
 @end
 
+// Test case for the NTP home UI, except the new omnibox popup flag is enabled.
+@interface NewOmniboxPopupLocationBarSteadyStateTestCase
+    : LocationBarSteadyStateTestCase
+@end
+
+@implementation NewOmniboxPopupLocationBarSteadyStateTestCase
+
+- (AppLaunchConfiguration)appConfigurationForTestCase {
+  AppLaunchConfiguration config = [super appConfigurationForTestCase];
+  config.features_enabled.push_back(kIOSOmniboxUpdatedPopupUI);
+  return config;
+}
+
+// This is currently needed to prevent this test case from being ignored.
+- (void)testEmpty {
+}
+
+@end
+
 #pragma mark - Edit state tests
 
 @interface LocationBarEditStateTestCase : ChromeTestCase
diff --git a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
index d448f11..065bf561 100644
--- a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
+++ b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
@@ -217,6 +217,7 @@
   deps = [
     ":popup_accessibility_identifier_constants",
     "//base",
+    "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/content_suggestions:content_suggestions_constant",
     "//ios/chrome/test/earl_grey:eg_test_support+eg2",
     "//ios/testing/earl_grey:eg_test_support+eg2",
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_accessibility_identifier_constants.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_accessibility_identifier_constants.h
index c7e72ed9f..21e8d2b 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_accessibility_identifier_constants.h
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_accessibility_identifier_constants.h
@@ -10,7 +10,18 @@
 // Accessibility identifier for the Switch to Open Tab button.
 extern NSString* const kOmniboxPopupRowSwitchTabAccessibilityIdentifier;
 
+// Accessibility identifier for the Append button.
+extern NSString* const kOmniboxPopupRowAppendAccessibilityIdentifier;
+
 // A11y identifier for the table view containing suggestions.
 extern NSString* const kOmniboxPopupTableViewAccessibilityIdentifier;
 
+// Helper to generate omnibox popup accessibility identifiers.
+@interface OmniboxPopupAccessibilityIdentifierHelper : NSObject
+
+// Generate omnibox popup row accessibility identifier at |indexPath|.
++ (NSString*)accessibilityIdentifierForRowAtIndexPath:(NSIndexPath*)indexPath;
+
+@end
+
 #endif  // IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_OMNIBOX_POPUP_ACCESSIBILITY_IDENTIFIER_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_accessibility_identifier_constants.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_accessibility_identifier_constants.mm
index c703511a..474c069 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_accessibility_identifier_constants.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_accessibility_identifier_constants.mm
@@ -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 <UIKit/UIKit.h>
+
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_accessibility_identifier_constants.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -11,5 +13,18 @@
 NSString* const kOmniboxPopupRowSwitchTabAccessibilityIdentifier =
     @"OmniboxPopupRowSwitchTabAccessibilityIdentifier";
 
+NSString* const kOmniboxPopupRowAppendAccessibilityIdentifier =
+    @"OmniboxPopupRowAppendAccessibilityIdentifier";
+
 NSString* const kOmniboxPopupTableViewAccessibilityIdentifier =
     @"OmniboxPopupTableViewAccessibilityIdentifier";
+
+@implementation OmniboxPopupAccessibilityIdentifierHelper
+
++ (NSString*)accessibilityIdentifierForRowAtIndexPath:(NSIndexPath*)indexPath {
+  return
+      [NSString stringWithFormat:@"omnibox suggestion %ld %ld",
+                                 (long)indexPath.section, (long)indexPath.row];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_egtest.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_egtest.mm
index 3eefdd0..207dc24 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_egtest.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_egtest.mm
@@ -9,6 +9,7 @@
 #include "base/strings/sys_string_conversions.h"
 #import "ios/chrome/browser/ui/content_suggestions/ntp_home_constant.h"
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_accessibility_identifier_constants.h"
+#include "ios/chrome/browser/ui/ui_feature_flags.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
@@ -27,7 +28,7 @@
 // Returns the popup row containing the |url| as suggestion.
 id<GREYMatcher> PopupRowWithUrl(GURL url) {
   return grey_allOf(
-      grey_kindOfClassName(@"OmniboxPopupRowCell"),
+      chrome_test_util::OmniboxPopupRow(),
       grey_descendant(chrome_test_util::StaticTextWithAccessibilityLabel(
           base::SysUTF8ToNSString(url.GetContent()))),
       grey_sufficientlyVisible(), nil);
@@ -133,8 +134,7 @@
       selectElementWithMatcher:grey_allOf(SwitchTabElementForUrl(firstPageURL),
                                           grey_sufficientlyVisible(), nil)]
          usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 200)
-      onElementWithMatcher:grey_accessibilityID(
-                               kOmniboxPopupTableViewAccessibilityIdentifier)]
+      onElementWithMatcher:chrome_test_util::OmniboxPopupList()]
       performAction:grey_tap()];
 
   [ChromeEarlGrey waitForWebStateContainingText:kPage1];
@@ -373,8 +373,7 @@
       selectElementWithMatcher:grey_allOf(SwitchTabElementForUrl(URL1),
                                           grey_sufficientlyVisible(), nil)]
          usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 200)
-      onElementWithMatcher:grey_accessibilityID(
-                               kOmniboxPopupTableViewAccessibilityIdentifier)]
+      onElementWithMatcher:chrome_test_util::OmniboxPopupList()]
       assertWithMatcher:grey_sufficientlyVisible()];
 
   // Close the first page.
@@ -447,7 +446,7 @@
 
   // Matcher for a URL-what-you-typed suggestion.
   id<GREYMatcher> row = grey_allOf(
-      grey_kindOfClassName(@"OmniboxPopupRowCell"),
+      chrome_test_util::OmniboxPopupRow(),
       grey_descendant(
           chrome_test_util::StaticTextWithAccessibilityLabel(@"hello")),
       grey_sufficientlyVisible(), nil);
@@ -458,11 +457,13 @@
   GREYAssertTrue([EarlGrey isKeyboardShownWithError:nil],
                  @"Keyboard Should be Shown");
 
-  // Scroll the popup.
-  [[EarlGrey
-      selectElementWithMatcher:
-          grey_accessibilityID(kOmniboxPopupTableViewAccessibilityIdentifier)]
-      performAction:grey_swipeFastInDirection(kGREYDirectionUp)];
+  // Scroll the popup. This swipes from the point located at 50% of the width of
+  // the frame horizontally and most importantly 10% of the height of the frame
+  // vertically. This is necessary if the center of the list's accessibility
+  // frame is not visible, as it is the default start point.
+  [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxPopupList()]
+      performAction:grey_swipeFastInDirectionWithStartPoint(kGREYDirectionUp,
+                                                            0.5, 0.1)];
 
   [[EarlGrey selectElementWithMatcher:row]
       assertWithMatcher:grey_sufficientlyVisible()];
@@ -479,3 +480,22 @@
 }
 
 @end
+
+// Test case for the omnibox popup, except new popup flag is enabled.
+@interface NewOmniboxPopupTestCase : OmniboxPopupTestCase
+
+@end
+
+@implementation NewOmniboxPopupTestCase
+
+- (AppLaunchConfiguration)appConfigurationForTestCase {
+  AppLaunchConfiguration config = [super appConfigurationForTestCase];
+  config.features_enabled.push_back(kIOSOmniboxUpdatedPopupUI);
+  return config;
+}
+
+// This is currently needed to prevent this test case from being ignored.
+- (void)testEmpty {
+}
+
+@end
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm
index c49ea97..32a7018 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm
@@ -268,8 +268,8 @@
     // this method is called).
     rowCell.omniboxSemanticContentAttribute = self.semanticContentAttribute;
 
-    rowCell.accessibilityIdentifier = [NSString
-        stringWithFormat:@"omnibox suggestion %" PRIuNS, indexPath.row];
+    rowCell.accessibilityIdentifier = [OmniboxPopupAccessibilityIdentifierHelper
+        accessibilityIdentifierForRowAtIndexPath:indexPath];
   }
 }
 
diff --git a/ios/chrome/browser/ui/omnibox/popup/popup_swift_bridge.h b/ios/chrome/browser/ui/omnibox/popup/popup_swift_bridge.h
index 9a7b08e2..b38f25d 100644
--- a/ios/chrome/browser/ui/omnibox/popup/popup_swift_bridge.h
+++ b/ios/chrome/browser/ui/omnibox/popup/popup_swift_bridge.h
@@ -12,6 +12,7 @@
 #import "ios/chrome/browser/ui/omnibox/popup/content_providing.h"
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_icon.h"
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_pedal.h"
+#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_accessibility_identifier_constants.h"
 #import "ios/chrome/common/ui/colors/swift_bridge.h"
 
 #endif  // IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_POPUP_SWIFT_BRIDGE_H_
diff --git a/ios/chrome/browser/ui/omnibox/popup/shared/popup_match_trailing_button.swift b/ios/chrome/browser/ui/omnibox/popup/shared/popup_match_trailing_button.swift
index 85238741..88e0836 100644
--- a/ios/chrome/browser/ui/omnibox/popup/shared/popup_match_trailing_button.swift
+++ b/ios/chrome/browser/ui/omnibox/popup/shared/popup_match_trailing_button.swift
@@ -20,7 +20,7 @@
 
   var body: some View {
     Button(action: action) {
-      Image(systemName: match.isAppendable ? "arrow.up.backward" : "arrow.right.square")
+      Image(systemName: match.isTabMatch ? "arrow.right.square" : "arrow.up.backward")
         .foregroundColor(Colors.trailingButtonColor)
         .aspectRatio(contentMode: .fit)
         .frame(
@@ -34,5 +34,9 @@
         )
     }
     .buttonStyle(.plain)
+    .accessibilityIdentifier(
+      match.isTabMatch
+        ? kOmniboxPopupRowSwitchTabAccessibilityIdentifier
+        : kOmniboxPopupRowAppendAccessibilityIdentifier)
   }
 }
diff --git a/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift b/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift
index f71c0b2..8c3fe631 100644
--- a/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift
+++ b/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift
@@ -32,6 +32,14 @@
   }
 }
 
+/// Utility which provides a way to treat the `accessibilityIdentifier` view modifier as a value.
+struct AccessibilityIdentifierModifier: ViewModifier {
+  let identifier: String
+  func body(content: Content) -> some View {
+    content.accessibilityIdentifier(identifier)
+  }
+}
+
 struct PopupView: View {
   enum Dimensions {
     static let matchListRowInsets = EdgeInsets(.zero)
@@ -58,10 +66,11 @@
       let sectionContents =
         ForEach(Array(zip(section.matches.indices, section.matches)), id: \.0) {
           matchIndex, match in
+          let indexPath = IndexPath(row: matchIndex, section: sectionIndex)
+
           PopupMatchRowView(
             match: match,
-            isHighlighted: IndexPath(row: matchIndex, section: sectionIndex)
-              == self.model.highlightedMatchIndexPath,
+            isHighlighted: indexPath == self.model.highlightedMatchIndexPath,
             selectionHandler: {
               model.delegate?.autocompleteResultConsumer(
                 model, didSelectRow: UInt(matchIndex), inSection: UInt(sectionIndex))
@@ -74,6 +83,9 @@
           )
           .deleteDisabled(!match.supportsDeletion)
           .listRowInsets(Dimensions.matchListRowInsets)
+          .accessibilityElement(children: .contain)
+          .accessibilityIdentifier(
+            OmniboxPopupAccessibilityIdentifierHelper.accessibilityIdentifierForRow(at: indexPath))
         }
         .onDelete { indexSet in
           for matchIndex in indexSet {
@@ -97,9 +109,13 @@
 
   @ViewBuilder
   var listView: some View {
-    let listModifier = SimultaneousGestureModifier(DragGesture().onChanged { onDrag($0) })
-      .concat(ScrollOnChangeModifier(value: $model.sections, action: onNewMatches))
-      .concat(BlurredBackground())
+    let listModifier = AccessibilityIdentifierModifier(
+      identifier: kOmniboxPopupTableViewAccessibilityIdentifier
+    )
+    .concat(SimultaneousGestureModifier(DragGesture().onChanged { onDrag($0) }))
+    .concat(ScrollOnChangeModifier(value: $model.sections, action: onNewMatches))
+    .concat(BlurredBackground())
+
     if shouldSelfSize {
       SelfSizingList(
         bottomMargin: Dimensions.selfSizingListBottomMargin,
@@ -129,6 +145,7 @@
       let listAppearance = UITableView.appearance(whenContainedInInstancesOf: [
         appearanceContainerType
       ])
+
       listAppearance.backgroundColor = .clear
 
       if shouldSelfSize {
diff --git a/ios/chrome/browser/ui/settings/settings_app_interface.h b/ios/chrome/browser/ui/settings/settings_app_interface.h
index 76a2404..1490712 100644
--- a/ios/chrome/browser/ui/settings/settings_app_interface.h
+++ b/ios/chrome/browser/ui/settings/settings_app_interface.h
@@ -41,6 +41,9 @@
 // Returns YES if keyboard commands were seen.
 + (BOOL)settingsRegisteredKeyboardCommands;
 
+// Override the default search engine with the given search engine URL.
++ (void)overrideSearchEngineURL:(NSString*)searchEngineURL;
+
 // Resets the default search engine to Google.
 + (void)resetSearchEngine;
 
diff --git a/ios/chrome/browser/ui/settings/settings_app_interface.mm b/ios/chrome/browser/ui/settings/settings_app_interface.mm
index 744ea3b0..785a1f4 100644
--- a/ios/chrome/browser/ui/settings/settings_app_interface.mm
+++ b/ios/chrome/browser/ui/settings/settings_app_interface.mm
@@ -99,6 +99,20 @@
   return viewController.presentedViewController.keyCommands != nil;
 }
 
++ (void)overrideSearchEngineURL:(NSString*)searchEngineURL {
+  TemplateURLData templateURLData;
+  templateURLData.SetURL(base::SysNSStringToUTF8(searchEngineURL));
+
+  auto defaultSearchProvider = std::make_unique<TemplateURL>(templateURLData);
+  TemplateURL* defaultSearchProviderPtr = defaultSearchProvider.get();
+
+  TemplateURLService* service =
+      ios::TemplateURLServiceFactory::GetForBrowserState(
+          chrome_test_util::GetOriginalBrowserState());
+  service->Add(std::move(defaultSearchProvider));
+  service->SetUserSelectedDefaultSearchProvider(defaultSearchProviderPtr);
+}
+
 + (void)resetSearchEngine {
   TemplateURLService* service =
       ios::TemplateURLServiceFactory::GetForBrowserState(
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn
index 3e24331..6df876c 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn
@@ -251,6 +251,7 @@
     "//ios/chrome/browser/ui/fullscreen:feature_flags",
     "//ios/chrome/browser/ui/history:constants",
     "//ios/chrome/browser/ui/recent_tabs:recent_tabs_ui_constants",
+    "//ios/chrome/browser/ui/settings:eg_test_support+eg2",
     "//ios/chrome/browser/ui/start_surface:feature_flags",
     "//ios/chrome/browser/ui/tab_switcher/tab_grid:features",
     "//ios/chrome/browser/ui/tab_switcher/tab_grid/grid:grid_ui_constants",
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_egtest.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_egtest.mm
index 2f1d30c..b730577 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_egtest.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_egtest.mm
@@ -10,6 +10,7 @@
 #import "components/bookmarks/common/bookmark_pref_names.h"
 #import "ios/chrome/browser/ui/history/history_ui_constants.h"
 #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_constants.h"
+#import "ios/chrome/browser/ui/settings/settings_app_interface.h"
 #import "ios/chrome/browser/ui/start_surface/start_surface_features.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/features.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_constants.h"
@@ -23,6 +24,7 @@
 #import "ios/chrome/test/earl_grey/chrome_xcui_actions.h"
 #import "ios/chrome/test/earl_grey/web_http_server_chrome_test_case.h"
 #import "ios/testing/earl_grey/earl_grey_test.h"
+#import "ios/web/public/test/http_server/data_response_provider.h"
 #import "ios/web/public/test/http_server/http_server.h"
 #import "ios/web/public/test/http_server/http_server_util.h"
 #import "net/base/mac/url_conversions.h"
@@ -52,6 +54,9 @@
 using chrome_test_util::RegularTabGrid;
 
 namespace {
+const char kSearchEngineURL[] = "http://searchengine/?q={searchTerms}";
+const char kSearchEngineHost[] = "searchengine";
+
 char kURL1[] = "http://firstURL";
 char kURL2[] = "http://secondURL";
 char kURL3[] = "http://thirdURL";
@@ -249,6 +254,36 @@
       IDS_IOS_CONTENT_CONTEXT_SELECTTABS);
 }
 
+#pragma mark - TestResponseProvider
+
+// A ResponseProvider that provides html responses of the requested URL for
+// requests to |kSearchEngineHost|.
+class EchoURLDefaultSearchEngineResponseProvider
+    : public web::DataResponseProvider {
+ public:
+  bool CanHandleRequest(const Request& request) override;
+  void GetResponseHeadersAndBody(
+      const Request& request,
+      scoped_refptr<net::HttpResponseHeaders>* headers,
+      std::string* response_body) override;
+};
+
+bool EchoURLDefaultSearchEngineResponseProvider::CanHandleRequest(
+    const Request& request) {
+  DLOG(WARNING) << request.url.path();
+  return request.url.spec().find(kSearchEngineHost) != std::string::npos;
+}
+
+void EchoURLDefaultSearchEngineResponseProvider::GetResponseHeadersAndBody(
+    const Request& request,
+    scoped_refptr<net::HttpResponseHeaders>* headers,
+    std::string* response_body) {
+  const GURL& url = request.url;
+  *headers = web::ResponseProvider::GetDefaultResponseHeaders();
+  *response_body =
+      base::StringPrintf("<html><body>%s</body></html>", url.spec().c_str());
+}
+
 }  // namespace
 
 @interface TabGridTestCase : WebHttpServerChromeTestCase {
@@ -287,6 +322,7 @@
       @selector(testSearchSuggestedActionsPageSwitch),
       @selector(testHistorySuggestedActionInRegularTabsSearch),
       @selector(testHistorySuggestedActionInRecentTabsSearch),
+      @selector(testSearchOnWebSuggestedActionInRegularTabsSearch),
       @selector(testEmptyStateAfterNoResultsSearchForIncognitoTabGrid),
       @selector(testSearchResultCloseTab),
       @selector(testSearchResultCloseTabInIncognito),
@@ -319,6 +355,12 @@
 }
 
 - (void)tearDown {
+  // Ensure that the default search engine is reset.
+  if ([self isRunningTest:@selector
+            (testSearchOnWebSuggestedActionInRegularTabsSearch)]) {
+    [SettingsAppInterface resetSearchEngine];
+  }
+
   // Ensure that pref set in testTabGridItemContextMenuAddToBookmarkGreyed is
   // reset even if the test failed.
   if ([self isRunningTest:@selector
@@ -328,6 +370,7 @@
          forUserPref:base::SysUTF8ToNSString(
                          bookmarks::prefs::kEditBookmarksEnabled)];
   }
+
   [super tearDown];
 }
 
@@ -2146,6 +2189,47 @@
       assertWithMatcher:grey_sufficientlyVisible()];
 }
 
+// Tests that tapping the search on web action in the regular tabs search mode
+// opens a new tab on the default search engine with the search term from tab
+// search. Additionally, checks that tab search mode is exited when the user
+// returns to the tab grid.
+- (void)testSearchOnWebSuggestedActionInRegularTabsSearch {
+  // Configure a testing search engine to prevent real external url requests.
+  web::test::AddResponseProvider(
+      std::make_unique<EchoURLDefaultSearchEngineResponseProvider>());
+  GURL searchEngineURL = web::test::HttpServer::MakeUrl(kSearchEngineURL);
+  NSString* searchEngineURLString =
+      base::SysUTF8ToNSString(searchEngineURL.spec());
+  [SettingsAppInterface overrideSearchEngineURL:searchEngineURLString];
+
+  // Enter tab grid search mode & perform a search.
+  [ChromeEarlGrey showTabSwitcher];
+  [[EarlGrey selectElementWithMatcher:TabGridSearchTabsButton()]
+      performAction:grey_tap()];
+  const std::string searchQuery("queryfromtabsearch");
+  NSString* query = [NSString stringWithFormat:@"%s\n", searchQuery.c_str()];
+  [[EarlGrey selectElementWithMatcher:TabGridSearchBar()]
+      performAction:grey_typeText(query)];
+
+  // Scroll to search on web.
+  [[self scrollDownViewMatcher:RegularTabGrid()
+               toSelectMatcher:SearchOnWebSuggestedAction()]
+      performAction:grey_tap()];
+
+  // Ensure that the tab grid was exited.
+  [[EarlGrey selectElementWithMatcher:chrome_test_util::ShowTabsButton()]
+      assertWithMatcher:grey_sufficientlyVisible()];
+
+  // Ensure the loaded page is a default search engine page for |searchQuery|.
+  [ChromeEarlGrey waitForWebStateContainingText:kSearchEngineHost];
+  [ChromeEarlGrey waitForWebStateContainingText:searchQuery];
+
+  // Re-enter the tab grid and ensure search mode was exited.
+  [ChromeEarlGrey showTabSwitcher];
+  [[EarlGrey selectElementWithMatcher:TabGridSearchTabsButton()]
+      assertWithMatcher:grey_sufficientlyVisible()];
+}
+
 // Tests that a search with no results in incognito mode will show the empty
 // state.
 - (void)testEmptyStateAfterNoResultsSearchForIncognitoTabGrid {
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm b/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm
index a0b98e37..4697bbc 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm
+++ b/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm
@@ -31,9 +31,9 @@
 namespace {
 // Waits for omnibox suggestion with index |suggestionID| to contain
 // |suggestion|.
-void WaitForOmniboxSuggestion(NSString* suggestion, int suggestionID) {
+void WaitForOmniboxSuggestion(NSString* suggestion, int section, int row) {
   NSString* accessibilityID =
-      [NSString stringWithFormat:@"omnibox suggestion %d", suggestionID];
+      [NSString stringWithFormat:@"omnibox suggestion %d %d", section, row];
   ConditionBlock condition = ^{
     NSError* error = nil;
     [[EarlGrey
@@ -377,35 +377,35 @@
 
   [[EarlGrey selectElementWithMatcher:chrome_test_util::NewTabPageOmnibox()]
       performAction:grey_typeText(@"a")];
-  WaitForOmniboxSuggestion(@"a", 0);
+  WaitForOmniboxSuggestion(@"a", 0, 0);
 
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
       performAction:grey_typeText(@"b")];
-  WaitForOmniboxSuggestion(@"ab", 0);
+  WaitForOmniboxSuggestion(@"ab", 0, 0);
 
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
       performAction:grey_typeText(@"C")];
-  WaitForOmniboxSuggestion(@"abC", 0);
+  WaitForOmniboxSuggestion(@"abC", 0, 0);
 
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
       performAction:grey_typeText(@"1")];
-  WaitForOmniboxSuggestion(@"abC1", 0);
+  WaitForOmniboxSuggestion(@"abC1", 0, 0);
 
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
       performAction:grey_typeText(@"2")];
-  WaitForOmniboxSuggestion(@"abC12", 0);
+  WaitForOmniboxSuggestion(@"abC12", 0, 0);
 
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
       performAction:grey_typeText(@"@")];
-  WaitForOmniboxSuggestion(@"abC12@", 0);
+  WaitForOmniboxSuggestion(@"abC12@", 0, 0);
 
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
       performAction:grey_typeText(@"{")];
-  WaitForOmniboxSuggestion(@"abC12@{", 0);
+  WaitForOmniboxSuggestion(@"abC12@{", 0, 0);
 
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
       performAction:grey_typeText(@"#")];
-  WaitForOmniboxSuggestion(@"abC12@{#", 0);
+  WaitForOmniboxSuggestion(@"abC12@{#", 0, 0);
 
   id<GREYMatcher> cancelButton =
       grey_accessibilityID(kToolbarCancelOmniboxEditButtonIdentifier);
diff --git a/ios/chrome/browser/web/cache_egtest.mm b/ios/chrome/browser/web/cache_egtest.mm
index 678c3af..bf1e0a1 100644
--- a/ios/chrome/browser/web/cache_egtest.mm
+++ b/ios/chrome/browser/web/cache_egtest.mm
@@ -118,7 +118,7 @@
   // running. This is done because it is inefficient to use
   // ensureAppLaunchedWithConfiguration for each test.
   if ([self isRunningTest:@selector
-            (testCachingBehaviorOnSelectOmniboxSuggestion)]) {
+            (DISABLED_testCachingBehaviorOnSelectOmniboxSuggestion)]) {
     // Explicitly disable feature OnDeviceHeadProviderNonIncognito, whose delay
     // (i.e. http://shortn/_o7kPJvU8ac) will otherwise cause flakiness for this
     // test in build iphone-device (crbug.com/1153136).
@@ -161,13 +161,9 @@
 
 // Tests that cache is not used when selecting omnibox suggested website, even
 // though cache for that website exists.
-- (void)testCachingBehaviorOnSelectOmniboxSuggestion {
-  // TODO(crbug.com/753098): Re-enable this test on iPad once grey_typeText
-  // works.
-  if ([ChromeEarlGrey isIPadIdiom]) {
-    EARL_GREY_TEST_DISABLED(@"Test disabled on iPad.");
-  }
-
+//
+// TODO(crbug.com/753098): Re-enable this test once grey_typeText works.
+- (void)DISABLED_testCachingBehaviorOnSelectOmniboxSuggestion {
   web::test::SetUpHttpServer(std::make_unique<CacheTestResponseProvider>());
 
   // Clear the history to ensure expected omnibox autocomplete results.
@@ -185,7 +181,7 @@
   [ChromeEarlGreyUI focusOmniboxAndType:@"cachetestfirstpage"];
   [[EarlGrey
       selectElementWithMatcher:grey_allOf(grey_accessibilityID(
-                                              @"omnibox suggestion 1"),
+                                              @"omnibox suggestion 0 1"),
                                           grey_sufficientlyVisible(), nil)]
       performAction:grey_tap()];
 
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn
index b18d33d7..a735c04 100644
--- a/ios/chrome/test/earl_grey/BUILD.gn
+++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -122,6 +122,7 @@
     "//ios/chrome/browser/ui/omnibox:eg_app_support+eg2",
     "//ios/chrome/browser/ui/omnibox:omnibox_internal",
     "//ios/chrome/browser/ui/omnibox/keyboard_assist",
+    "//ios/chrome/browser/ui/omnibox/popup:popup_accessibility_identifier_constants",
     "//ios/chrome/browser/ui/passwords:eg_app_support+eg2",
     "//ios/chrome/browser/ui/popup_menu:constants",
     "//ios/chrome/browser/ui/popup_menu/overflow_menu:feature_flags",
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.h b/ios/chrome/test/earl_grey/chrome_earl_grey.h
index 190afed..f3a8ad7 100644
--- a/ios/chrome/test/earl_grey/chrome_earl_grey.h
+++ b/ios/chrome/test/earl_grey/chrome_earl_grey.h
@@ -657,6 +657,9 @@
 // Returns whether the NewOverflowMenu feature is enabled.
 - (BOOL)isNewOverflowMenuEnabled;
 
+// Returns whether the OmniboxUpdatedPopupUI feature is enabled.
+- (BOOL)isNewOmniboxPopupEnabled;
+
 // Returns whether the Thumbstrip feature is enabled for window with given
 // number.
 - (BOOL)isThumbstripEnabledForWindowWithNumber:(int)windowNumber;
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.mm b/ios/chrome/test/earl_grey/chrome_earl_grey.mm
index 79dec42..0006ed1 100644
--- a/ios/chrome/test/earl_grey/chrome_earl_grey.mm
+++ b/ios/chrome/test/earl_grey/chrome_earl_grey.mm
@@ -1245,6 +1245,10 @@
   return [ChromeEarlGreyAppInterface isNewOverflowMenuEnabled];
 }
 
+- (BOOL)isNewOmniboxPopupEnabled {
+  return [ChromeEarlGreyAppInterface isNewOmniboxPopupEnabled];
+}
+
 - (BOOL)isThumbstripEnabledForWindowWithNumber:(int)windowNumber {
   return [ChromeEarlGreyAppInterface
       isThumbstripEnabledForWindowWithNumber:windowNumber];
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h
index 31aa558..87d9a0d5 100644
--- a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h
+++ b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h
@@ -536,6 +536,9 @@
 // Returns whether the NewOverflowMenu feature is enabled.
 + (BOOL)isNewOverflowMenuEnabled;
 
+// Returns whether the OmniboxPopupUpdatedUI feature is enabled.
++ (BOOL)isNewOmniboxPopupEnabled;
+
 // Returns whether the Thumbstrip feature is enabled for window with given
 // number.
 + (BOOL)isThumbstripEnabledForWindowWithNumber:(int)windowNumber;
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm
index acff91f..1d469d7 100644
--- a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm
+++ b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm
@@ -1113,6 +1113,10 @@
   return IsNewOverflowMenuEnabled();
 }
 
++ (BOOL)isNewOmniboxPopupEnabled {
+  return base::FeatureList::IsEnabled(kIOSOmniboxUpdatedPopupUI);
+}
+
 + (BOOL)isThumbstripEnabledForWindowWithNumber:(int)windowNumber {
   return ShowThumbStripInTraitCollection(
       [self windowWithNumber:windowNumber].traitCollection);
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.h b/ios/chrome/test/earl_grey/chrome_matchers.h
index bc2e0810..d0e45b9 100644
--- a/ios/chrome/test/earl_grey/chrome_matchers.h
+++ b/ios/chrome/test/earl_grey/chrome_matchers.h
@@ -111,6 +111,12 @@
 // Returns a matcher for the omnibox.
 id<GREYMatcher> Omnibox();
 
+// Returns matcher for the omnibox popup list row views.
+id<GREYMatcher> OmniboxPopupRow();
+
+// Returns matcher for the omnibox popup list view.
+id<GREYMatcher> OmniboxPopupList();
+
 // Returns a matcher for the location view.
 id<GREYMatcher> DefocusedLocationView();
 
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.mm b/ios/chrome/test/earl_grey/chrome_matchers.mm
index aa7d80ca..d614732e 100644
--- a/ios/chrome/test/earl_grey/chrome_matchers.mm
+++ b/ios/chrome/test/earl_grey/chrome_matchers.mm
@@ -140,6 +140,14 @@
   return [ChromeMatchersAppInterface omnibox];
 }
 
+id<GREYMatcher> OmniboxPopupRow() {
+  return [ChromeMatchersAppInterface omniboxPopupRow];
+}
+
+id<GREYMatcher> OmniboxPopupList() {
+  return [ChromeMatchersAppInterface omniboxPopupList];
+}
+
 id<GREYMatcher> DefocusedLocationView() {
   return [ChromeMatchersAppInterface defocusedLocationView];
 }
diff --git a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.h b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.h
index 008b19d..4c45e04 100644
--- a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.h
+++ b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.h
@@ -238,6 +238,12 @@
 // Returns matcher for the tools menu table view.
 + (id<GREYMatcher>)toolsMenuView;
 
+// Returns matcher for the omnibox popup list row views.
++ (id<GREYMatcher>)omniboxPopupRow;
+
+// Returns matcher for the omnibox popup list view.
++ (id<GREYMatcher>)omniboxPopupList;
+
 // Returns matcher for the OK button.
 + (id<GREYMatcher>)OKButton;
 
diff --git a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm
index 330e3f6..2b9666b7 100644
--- a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm
+++ b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm
@@ -30,6 +30,7 @@
 #import "ios/chrome/browser/ui/ntp/new_tab_page_constants.h"
 #import "ios/chrome/browser/ui/omnibox/keyboard_assist/omnibox_assistive_keyboard_views_utils.h"
 #import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h"
+#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_accessibility_identifier_constants.h"
 #import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h"
 #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_constants.h"
 #import "ios/chrome/browser/ui/settings/autofill/autofill_add_credit_card_view_controller.h"
@@ -54,6 +55,7 @@
 #import "ios/chrome/browser/ui/table_view/cells/table_view_url_item.h"
 #import "ios/chrome/browser/ui/toolbar/primary_toolbar_view.h"
 #import "ios/chrome/browser/ui/toolbar/public/toolbar_constants.h"
+#include "ios/chrome/browser/ui/ui_feature_flags.h"
 #import "ios/chrome/browser/ui/util/ui_util.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 #include "ios/chrome/grit/ios_strings.h"
@@ -553,6 +555,44 @@
   return grey_accessibilityID(kPopupMenuToolsMenuTableViewId);
 }
 
++ (id<GREYMatcher>)omniboxPopupRow {
+  if (!base::FeatureList::IsEnabled(kIOSOmniboxUpdatedPopupUI)) {
+    return grey_kindOfClassName(@"OmniboxPopupRowCell");
+  } else {
+    if (@available(iOS 15, *)) {
+      return grey_allOf(
+          grey_kindOfClassName(@"SwiftUI.ListTableViewCell"),
+          grey_ancestor(grey_kindOfClassName(@"OmniboxPopupContainerView")),
+          nil);
+    } else {
+      return grey_allOf(
+          grey_kindOfClassName(@"SwiftUI.ListCoreCellHost"),
+          grey_ancestor(grey_kindOfClassName(@"OmniboxPopupContainerView")),
+          nil);
+    }
+  }
+}
+
++ (id<GREYMatcher>)omniboxPopupList {
+  if (!base::FeatureList::IsEnabled(kIOSOmniboxUpdatedPopupUI)) {
+    return grey_accessibilityID(kOmniboxPopupTableViewAccessibilityIdentifier);
+  } else {
+    if (@available(iOS 15, *)) {
+      return grey_accessibilityID(
+          kOmniboxPopupTableViewAccessibilityIdentifier);
+    } else {
+      // Implementation detail: the list is the closest ancestor of all popup.
+      // rows. It is the unique element with popup rows as descendants but no
+      // descendant having popup rows as descendants.
+      return grey_allOf(
+          grey_descendant([ChromeMatchersAppInterface omniboxPopupRow]),
+          grey_not(grey_descendant(
+              grey_descendant([ChromeMatchersAppInterface omniboxPopupRow]))),
+          nil);
+    }
+  }
+}
+
 + (id<GREYMatcher>)OKButton {
   return [ChromeMatchersAppInterface buttonWithAccessibilityLabelID:(IDS_OK)];
 }
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 c47c50e..4d470b2 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 @@
-5aa5472ed8bf80fdc197f2d33effdfc98cb0d854
\ No newline at end of file
+65e7aad8093a77fe6b76425a650507d9ef8d70bf
\ 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 5e9abd9..6daa5d29 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 @@
-d506626fb8f5b494484ec7160116f7c25c330b77
\ No newline at end of file
+ad91df0f34c74303797c1a2999ee9289fa874518
\ 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 386ad8a7..5787914 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 @@
-185945b376a7de4ad6d21a77b3cb6aeee79ea285
\ No newline at end of file
+c81afe6ff1db1a0771726300b34eda55e9f3656a
\ 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 74f0c02..64a0a4b0 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 @@
-3d8ebf7bd46a4f78d45e03caa14495164de011bd
\ No newline at end of file
+34420c25a7df6566094d43f71ba4f9948f0cdaf3
\ 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 f4a3917..776c33d6 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 @@
-7acaa6ca0a0fa626c481ed5d3d225229688ad23a
\ No newline at end of file
+7eedddcd4cb53d5af610b51401eeb7805f2c2503
\ 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 8d4db19..d08adda8 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 @@
-c42aedd682eb10a7e63f75d168a24db1f2f5665c
\ No newline at end of file
+2d3506a4a04a82122a05e36fca0b358a46e35e93
\ 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 3632766b..976adcf3 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 @@
-3b9d3a7f719c6adccd34055ec9ebe52a4676ed67
\ No newline at end of file
+d4f0f727fe27e62a7a5b2d8080091eda1bcac9f7
\ 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 3bdc8d9c..a59eecc 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 @@
-c32f83b20b0e26cac6bb2626d1dc535ad0b8f1ee
\ No newline at end of file
+47a45935fb98ef054547706178fa2625fa44fa98
\ 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 cf42cff..8c9fc7f 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 @@
-d6cbb5be8baf71a6531a772a164dc438e5ca4b60
\ No newline at end of file
+9de9c2c5e5da0b78b52b11a5bbb550ce8d9405fe
\ 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 0031f5f..b04162b 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 @@
-cfd811f62c650898d377512589de8a63eb697a97
\ No newline at end of file
+87f79f6975b5d595d9043361a58995328a4bc929
\ No newline at end of file
diff --git a/ios/web/js_messaging/web_frame_impl.mm b/ios/web/js_messaging/web_frame_impl.mm
index 868ee44..faa98533 100644
--- a/ios/web/js_messaging/web_frame_impl.mm
+++ b/ios/web/js_messaging/web_frame_impl.mm
@@ -159,14 +159,10 @@
   int message_id = next_message_id_;
   next_message_id_++;
 
-#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
-  if (@available(iOS 14, *)) {
-    if (content_world && content_world->GetWKContentWorld()) {
-      return ExecuteJavaScriptFunction(content_world, name, parameters,
-                                       message_id, reply_with_result);
-    }
+  if (content_world && content_world->GetWKContentWorld()) {
+    return ExecuteJavaScriptFunction(content_world, name, parameters,
+                                     message_id, reply_with_result);
   }
-#endif  // defined(__IPHONE14_0)
 
   if (!CanCallJavaScriptFunction()) {
     return false;
@@ -277,7 +273,6 @@
 bool WebFrameImpl::ExecuteJavaScript(
     const std::string& script,
     ExecuteJavaScriptCallbackWithError callback) {
-  DCHECK(base::ios::IsRunningOnIOS14OrLater());
   DCHECK(frame_info_);
 
   if (!IsMainFrame()) {
@@ -296,13 +291,9 @@
     }
   };
 
-  if (@available(iOS 14.0, *)) {
-    web::ExecuteJavaScript(frame_info_.webView, WKContentWorld.pageWorld,
-                           frame_info_, ns_script, completion_handler);
-    return true;
-  }
-
-  return false;
+  web::ExecuteJavaScript(frame_info_.webView, WKContentWorld.pageWorld,
+                         frame_info_, ns_script, completion_handler);
+  return true;
 }
 
 WebFrame::ExecuteJavaScriptCallbackWithError
@@ -334,7 +325,6 @@
     int message_id,
     bool reply_with_result) {
   DCHECK(content_world);
-  DCHECK(base::ios::IsRunningOnIOS14OrLater());
   DCHECK(frame_info_);
 
   NSString* script = CreateFunctionCallWithParamaters(name, parameters);
@@ -357,18 +347,12 @@
     };
   }
 
-#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
-  if (@available(iOS 14.0, *)) {
-    WKContentWorld* world = content_world->GetWKContentWorld();
-    DCHECK(world);
+  WKContentWorld* world = content_world->GetWKContentWorld();
+  DCHECK(world);
 
-    web::ExecuteJavaScript(frame_info_.webView, world, frame_info_, script,
-                           completion_handler);
-    return true;
-  }
-#endif  // defined(__IPHONE14_0)
-
-  return false;
+  web::ExecuteJavaScript(frame_info_.webView, world, frame_info_, script,
+                         completion_handler);
+  return true;
 }
 
 bool WebFrameImpl::ExecuteJavaScriptFunction(
diff --git a/ios/web/js_messaging/web_frame_impl_inttest.mm b/ios/web/js_messaging/web_frame_impl_inttest.mm
index 8171b36..5333f033 100644
--- a/ios/web/js_messaging/web_frame_impl_inttest.mm
+++ b/ios/web/js_messaging/web_frame_impl_inttest.mm
@@ -276,9 +276,8 @@
   ASSERT_TRUE(main_frame_impl);
 
   NSTimeInterval js_timeout = kWaitForJSCompletionTimeout;
-  __block bool called = false;
-
   JavaScriptContentWorld world(GetBrowserState(), WKContentWorld.pageWorld);
+  __block bool called = false;
 
   std::vector<base::Value> function_params;
   EXPECT_TRUE(main_frame_impl->CallJavaScriptFunctionInContentWorld(
@@ -301,7 +300,6 @@
 // world.
 TEST_F(WebFrameImplIntTest, CallJavaScriptFunctionMainFrameIsolatedWorld) {
   ASSERT_TRUE(LoadHtml("<p>"));
-
   WKWebView* web_view =
       [web::test::GetWebController(web_state()) ensureWebViewCreated];
   test::ExecuteJavaScript(web_view, WKContentWorld.defaultClientWorld,
@@ -315,11 +313,9 @@
   ASSERT_TRUE(main_frame_impl);
 
   NSTimeInterval js_timeout = kWaitForJSCompletionTimeout;
-  __block bool called = false;
-
   JavaScriptContentWorld world(GetBrowserState(),
                                WKContentWorld.defaultClientWorld);
-
+  __block bool called = false;
   std::vector<base::Value> function_params;
   EXPECT_TRUE(main_frame_impl->CallJavaScriptFunctionInContentWorld(
       "fakeFunction", function_params, &world,
diff --git a/ios/web/js_messaging/web_frame_impl_unittest.mm b/ios/web/js_messaging/web_frame_impl_unittest.mm
index 102c14f..db1a2ff 100644
--- a/ios/web/js_messaging/web_frame_impl_unittest.mm
+++ b/ios/web/js_messaging/web_frame_impl_unittest.mm
@@ -452,10 +452,6 @@
 // Tests that the WebFrame can execute arbitrary JavaScript
 // if and only if it is a main frame.
 TEST_F(WebFrameImplTest, ExecuteJavaScript) {
-  if (!base::ios::IsRunningOnIOS14OrLater()) {
-    return;
-  }
-
   FakeWebState fake_web_state;
   GURL security_origin;
 
@@ -480,10 +476,6 @@
 // Tests that the WebFrame can execute arbitrary JavaScript given
 // a callback if and only if it is a main frame.
 TEST_F(WebFrameImplTest, ExecuteJavaScriptWithCallback) {
-  if (!base::ios::IsRunningOnIOS14OrLater()) {
-    return;
-  }
-
   FakeWebState fake_web_state;
   GURL security_origin;
 
diff --git a/media/base/win/hresult_status_helper.cc b/media/base/win/hresult_status_helper.cc
deleted file mode 100644
index b8218fa..0000000
--- a/media/base/win/hresult_status_helper.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/base/win/hresult_status_helper.h"
-
-#include "base/logging.h"
-#include "base/strings/string_util.h"
-
-namespace media {
-
-D3D11Status HresultToStatus(HRESULT hresult,
-                            D3D11Status::Codes code,
-                            const char* message,
-                            const base::Location& location) {
-  if (SUCCEEDED(hresult))
-    return D3D11Status::Codes::kOk;
-
-  std::string sys_err = logging::SystemErrorCodeToString(hresult);
-  if (!base::IsStringUTF8AllowingNoncharacters(sys_err))
-    sys_err = "System error string is invalid";
-
-  return D3D11Status(code, message == nullptr ? "HRESULT" : message, location)
-      .WithData("value", sys_err);
-}
-
-}  // namespace media
diff --git a/media/base/win/media_foundation_cdm_proxy.h b/media/base/win/media_foundation_cdm_proxy.h
index 8ba852a..36831e9 100644
--- a/media/base/win/media_foundation_cdm_proxy.h
+++ b/media/base/win/media_foundation_cdm_proxy.h
@@ -60,6 +60,12 @@
   // because they are in bad state.
   virtual void OnHardwareContextReset() = 0;
 
+  // Notify the CDM that significant playback (e.g. >1 minutes) has happened.
+  virtual void OnSignificantPlayback() = 0;
+
+  // Notify the CDM that playback error happened.
+  virtual void OnPlaybackError() = 0;
+
  protected:
   friend base::RefCountedThreadSafe<MediaFoundationCdmProxy>;
   virtual ~MediaFoundationCdmProxy() = default;
diff --git a/media/cdm/cdm_auxiliary_helper.cc b/media/cdm/cdm_auxiliary_helper.cc
index 19c8531d..2679b81 100644
--- a/media/cdm/cdm_auxiliary_helper.cc
+++ b/media/cdm/cdm_auxiliary_helper.cc
@@ -64,6 +64,8 @@
 
 void CdmAuxiliaryHelper::SetCdmClientToken(
     const std::vector<uint8_t>& client_token) {}
+
+void CdmAuxiliaryHelper::OnCdmEvent(CdmEvent event) {}
 #endif  // BUILDFLAG(IS_WIN)
 
 }  // namespace media
diff --git a/media/cdm/cdm_auxiliary_helper.h b/media/cdm/cdm_auxiliary_helper.h
index 09f792e..ee35db8 100644
--- a/media/cdm/cdm_auxiliary_helper.h
+++ b/media/cdm/cdm_auxiliary_helper.h
@@ -36,10 +36,8 @@
                                         public CdmDocumentService {
  public:
   CdmAuxiliaryHelper();
-
   CdmAuxiliaryHelper(const CdmAuxiliaryHelper&) = delete;
   CdmAuxiliaryHelper& operator=(const CdmAuxiliaryHelper&) = delete;
-
   ~CdmAuxiliaryHelper() override;
 
   // Callback to report the size of file read by cdm::FileIO created by |this|.
@@ -74,6 +72,7 @@
 #if BUILDFLAG(IS_WIN)
   void GetMediaFoundationCdmData(GetMediaFoundationCdmDataCB callback) override;
   void SetCdmClientToken(const std::vector<uint8_t>& client_token) override;
+  void OnCdmEvent(CdmEvent event) override;
 #endif  // BUILDFLAG(IS_WIN)
 };
 
diff --git a/media/cdm/cdm_document_service.h b/media/cdm/cdm_document_service.h
index 4d7f992..43a290b 100644
--- a/media/cdm/cdm_document_service.h
+++ b/media/cdm/cdm_document_service.h
@@ -18,6 +18,14 @@
 
 namespace media {
 
+// Important events happened to the CDM.
+enum class CdmEvent {
+  kSignificantPlayback,  // Significant (e.g. played >1 minute) successful
+                         // playback happened using the CDM.
+  kPlaybackError,        // Error happened during playback using the CDM.
+  kCdmError,             // Error happened in the CDM.
+};
+
 class MEDIA_EXPORT CdmDocumentService {
  public:
   CdmDocumentService() = default;
@@ -74,6 +82,10 @@
   // Pref Service so that it can be reused next time the CDM request a new
   // license for that origin.
   virtual void SetCdmClientToken(const std::vector<uint8_t>& client_token) = 0;
+
+  // Reports a CDM event. This can be used for metrics reporting or fallback
+  // logic, e.g. disable the CDM in the current robustness level.
+  virtual void OnCdmEvent(CdmEvent event) = 0;
 #endif  // BUILDFLAG(IS_WIN)
 };
 
diff --git a/media/cdm/win/media_foundation_cdm.cc b/media/cdm/win/media_foundation_cdm.cc
index 5374bcd1..46a8f0b 100644
--- a/media/cdm/win/media_foundation_cdm.cc
+++ b/media/cdm/win/media_foundation_cdm.cc
@@ -127,9 +127,11 @@
 class CdmProxyImpl : public MediaFoundationCdmProxy {
  public:
   CdmProxyImpl(ComPtr<IMFContentDecryptionModule> mf_cdm,
-               base::RepeatingClosure hardware_context_reset_cb)
+               base::RepeatingClosure hardware_context_reset_cb,
+               MediaFoundationCdm::CdmEventCB cdm_event_cb)
       : mf_cdm_(mf_cdm),
-        hardware_context_reset_cb_(std::move(hardware_context_reset_cb)) {}
+        hardware_context_reset_cb_(std::move(hardware_context_reset_cb)),
+        cdm_event_cb_(std::move(cdm_event_cb)) {}
 
   // MediaFoundationCdmProxy implementation
 
@@ -229,6 +231,14 @@
     hardware_context_reset_cb_.Run();
   }
 
+  void OnSignificantPlayback() override {
+    cdm_event_cb_.Run(CdmEvent::kSignificantPlayback);
+  }
+
+  void OnPlaybackError() override {
+    cdm_event_cb_.Run(CdmEvent::kPlaybackError);
+  }
+
  private:
   ~CdmProxyImpl() override = default;
 
@@ -251,8 +261,9 @@
 
   ComPtr<IMFContentDecryptionModule> mf_cdm_;
 
-  // A callback to notify hardware context reset.
+  // Callbacks to notify hardware context reset and playback error.
   base::RepeatingClosure hardware_context_reset_cb_;
+  MediaFoundationCdm::CdmEventCB cdm_event_cb_;
 
   // Store IMFTrustedInput to avoid potential performance cost.
   ComPtr<IMFTrustedInput> trusted_input_;
@@ -279,6 +290,7 @@
     const CreateMFCdmCB& create_mf_cdm_cb,
     const IsTypeSupportedCB& is_type_supported_cb,
     const StoreClientTokenCB& store_client_token_cb,
+    const CdmEventCB& cdm_event_cb,
     const SessionMessageCB& session_message_cb,
     const SessionClosedCB& session_closed_cb,
     const SessionKeysChangeCB& session_keys_change_cb,
@@ -287,6 +299,7 @@
       create_mf_cdm_cb_(create_mf_cdm_cb),
       is_type_supported_cb_(is_type_supported_cb),
       store_client_token_cb_(store_client_token_cb),
+      cdm_event_cb_(cdm_event_cb),
       session_message_cb_(session_message_cb),
       session_closed_cb_(session_closed_cb),
       session_keys_change_cb_(session_keys_change_cb),
@@ -311,6 +324,10 @@
   create_mf_cdm_cb_.Run(hresult, mf_cdm);
   if (!mf_cdm) {
     DCHECK(FAILED(hresult));
+    // Only report CdmEvent::kCdmError here as this is where most failures
+    // happen, and other errors can be easily triggered by sites, e.g. a bad
+    // server certificate or a bad license.
+    OnCdmEvent(CdmEvent::kCdmError);
     return hresult;
   }
 
@@ -505,6 +522,8 @@
     cdm_proxy_ = base::MakeRefCounted<CdmProxyImpl>(
         mf_cdm_,
         base::BindRepeating(&MediaFoundationCdm::OnHardwareContextReset,
+                            weak_factory_.GetWeakPtr()),
+        base::BindRepeating(&MediaFoundationCdm::OnCdmEvent,
                             weak_factory_.GetWeakPtr()));
   }
 
@@ -612,6 +631,11 @@
   }
 }
 
+void MediaFoundationCdm::OnCdmEvent(CdmEvent event) {
+  DVLOG_FUNC(1);
+  cdm_event_cb_.Run(event);
+}
+
 void MediaFoundationCdm::OnIsTypeSupportedResult(
     std::unique_ptr<KeyStatusCdmPromise> promise,
     bool is_supported) {
diff --git a/media/cdm/win/media_foundation_cdm.h b/media/cdm/win/media_foundation_cdm.h
index a59fbcb0..0934c38b3 100644
--- a/media/cdm/win/media_foundation_cdm.h
+++ b/media/cdm/win/media_foundation_cdm.h
@@ -18,6 +18,7 @@
 #include "media/base/cdm_context.h"
 #include "media/base/content_decryption_module.h"
 #include "media/base/media_export.h"
+#include "media/cdm/cdm_document_service.h"
 
 namespace media {
 
@@ -65,13 +66,17 @@
   using StoreClientTokenCB =
       base::RepeatingCallback<void(const std::vector<uint8_t>&)>;
 
+  using CdmEventCB = base::RepeatingCallback<void(CdmEvent)>;
+
   // Constructs `MediaFoundationCdm`. Note that `Initialize()` must be called
   // before calling any other methods.
+  // TODO(xhwang): Use a helper to reduce the number of callbacks.
   MediaFoundationCdm(
       const std::string& uma_prefix,
       const CreateMFCdmCB& create_mf_cdm_cb,
       const IsTypeSupportedCB& is_type_supported_cb,
       const StoreClientTokenCB& store_client_token_cb,
+      const CdmEventCB& cdm_event_cb,
       const SessionMessageCB& session_message_cb,
       const SessionClosedCB& session_closed_cb,
       const SessionKeysChangeCB& session_keys_change_cb,
@@ -128,6 +133,9 @@
   // Called when hardware context reset happens.
   void OnHardwareContextReset();
 
+  // Called when CdmEvent happens.
+  void OnCdmEvent(CdmEvent event);
+
   // Called when IsTypeSupported() result is available.
   void OnIsTypeSupportedResult(std::unique_ptr<KeyStatusCdmPromise> promise,
                                bool is_supported);
@@ -146,6 +154,9 @@
   // Callback to MFCdmFactory's StoreClientToken().
   StoreClientTokenCB store_client_token_cb_;
 
+  // Callback to report fatal errors.
+  CdmEventCB cdm_event_cb_;
+
   // Callbacks for firing session events.
   SessionMessageCB session_message_cb_;
   SessionClosedCB session_closed_cb_;
diff --git a/media/cdm/win/media_foundation_cdm_factory.cc b/media/cdm/win/media_foundation_cdm_factory.cc
index ea316bb..60af92a 100644
--- a/media/cdm/win/media_foundation_cdm_factory.cc
+++ b/media/cdm/win/media_foundation_cdm_factory.cc
@@ -258,6 +258,8 @@
                           weak_factory_.GetWeakPtr(), cdm_config.key_system),
       base::BindRepeating(&MediaFoundationCdmFactory::StoreClientToken,
                           weak_factory_.GetWeakPtr()),
+      base::BindRepeating(&MediaFoundationCdmFactory::OnCdmEvent,
+                          weak_factory_.GetWeakPtr()),
       session_message_cb, session_closed_cb, session_keys_change_cb,
       session_expiration_update_cb);
 
@@ -321,6 +323,10 @@
   helper_->SetCdmClientToken(client_token);
 }
 
+void MediaFoundationCdmFactory::OnCdmEvent(CdmEvent event) {
+  helper_->OnCdmEvent(event);
+}
+
 HRESULT MediaFoundationCdmFactory::CreateMfCdmInternal(
     const CdmConfig& cdm_config,
     const base::UnguessableToken& cdm_origin_id,
diff --git a/media/cdm/win/media_foundation_cdm_factory.h b/media/cdm/win/media_foundation_cdm_factory.h
index f87c19ea..7df1df8e 100644
--- a/media/cdm/win/media_foundation_cdm_factory.h
+++ b/media/cdm/win/media_foundation_cdm_factory.h
@@ -70,6 +70,7 @@
                        IsTypeSupportedResultCB is_type_supported_result_cb);
 
   void StoreClientToken(const std::vector<uint8_t>& client_token);
+  void OnCdmEvent(CdmEvent event);
 
   HRESULT CreateMfCdmInternal(
       const CdmConfig& cdm_config,
diff --git a/media/cdm/win/media_foundation_cdm_unittest.cc b/media/cdm/win/media_foundation_cdm_unittest.cc
index 6c5920f..817a353 100644
--- a/media/cdm/win/media_foundation_cdm_unittest.cc
+++ b/media/cdm/win/media_foundation_cdm_unittest.cc
@@ -67,6 +67,7 @@
                                 base::Unretained(this)),
             is_type_supported_cb_.Get(),
             store_client_token_cb_.Get(),
+            cdm_event_cb_.Get(),
             base::BindRepeating(&MockCdmClient::OnSessionMessage,
                                 base::Unretained(&cdm_client_)),
             base::BindRepeating(&MockCdmClient::OnSessionClosed,
@@ -93,6 +94,7 @@
 
   void InitializeAndExpectFailure() {
     can_initialize_ = false;
+    EXPECT_CALL(cdm_event_cb_, Run(CdmEvent::kCdmError));
     ASSERT_FAILED(cdm_->Initialize());
   }
 
@@ -161,6 +163,7 @@
       is_type_supported_cb_;
   base::MockCallback<MediaFoundationCdm::StoreClientTokenCB>
       store_client_token_cb_;
+  StrictMock<base::MockCallback<MediaFoundationCdm::CdmEventCB>> cdm_event_cb_;
   ComPtr<MockMFCdm> mf_cdm_;
   ComPtr<MockMFCdmSession> mf_cdm_session_;
   ComPtr<IMFContentDecryptionModuleSessionCallbacks> mf_cdm_session_callbacks_;
@@ -515,6 +518,7 @@
 
   // Make the next `Initialize()` fail.
   can_initialize_ = false;
+  EXPECT_CALL(cdm_event_cb_, Run(CdmEvent::kCdmError));
 
   COM_EXPECT_CALL(mf_cdm_session_, Close()).WillOnce(Return(S_OK));
   EXPECT_CALL(cdm_client_,
diff --git a/media/mojo/mojom/BUILD.gn b/media/mojo/mojom/BUILD.gn
index 7355c0b4..a22f937 100644
--- a/media/mojo/mojom/BUILD.gn
+++ b/media/mojo/mojom/BUILD.gn
@@ -699,6 +699,15 @@
       {
         types = [
           {
+            mojom = "media.mojom.CdmEvent"
+            cpp = "::media::CdmEvent"
+          },
+        ]
+        traits_headers = [ "media_types_enum_mojom_traits.h" ]
+      },
+      {
+        types = [
+          {
             mojom = "media.mojom.MediaFoundationCdmData"
             cpp = "::std::unique_ptr<::media::MediaFoundationCdmData>"
             move_only = true
diff --git a/media/mojo/mojom/cdm_document_service.mojom b/media/mojo/mojom/cdm_document_service.mojom
index b2d4c953..f20e58de 100644
--- a/media/mojo/mojom/cdm_document_service.mojom
+++ b/media/mojo/mojom/cdm_document_service.mojom
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// TODO(xhwang): Move this out of media if it is needed anywhere else.
 module media.mojom;
 
 import "mojo/public/mojom/base/unguessable_token.mojom";
 import "mojo/public/mojom/base/file_path.mojom";
+import "media/mojo/mojom/media_types.mojom";
 
 // Contains data linked to an origin that the CDM stores in the browser
 // process.
@@ -71,4 +71,9 @@
   // be reused by the CDM for that same origin in the future.
   [EnableIf=is_win]
   SetCdmClientToken(array<uint8> client_token);
+
+  // Reports a CDM event, which can facilitate metrics reporting or fallback
+  // logic.
+  [EnableIf=is_win]
+  OnCdmEvent(CdmEvent event);
 };
diff --git a/media/mojo/mojom/media_types.mojom b/media/mojo/mojom/media_types.mojom
index e5e2125..047c5312 100644
--- a/media/mojo/mojom/media_types.mojom
+++ b/media/mojo/mojom/media_types.mojom
@@ -196,6 +196,15 @@
 [Native]
 struct SubsampleEntry;
 
+// Important events happened to the CDM.
+[EnableIf=is_win]
+enum CdmEvent {
+  kSignificantPlayback,  // Significant (e.g. played >1 minute) successful
+                         // playback happened using the CDM.
+  kPlaybackError,  // Error happened during playback using the CDM.
+  kCdmError,       // Error happened in the CDM.
+};
+
 // See media::CdmSessionClosedReason for descriptions.
 enum CdmSessionClosedReason {
   kInternalError,
diff --git a/media/mojo/mojom/media_types_enum_mojom_traits.h b/media/mojo/mojom/media_types_enum_mojom_traits.h
index 7d9f434c..18924b4 100644
--- a/media/mojo/mojom/media_types_enum_mojom_traits.h
+++ b/media/mojo/mojom/media_types_enum_mojom_traits.h
@@ -6,10 +6,12 @@
 #define MEDIA_MOJO_MOJOM_MEDIA_TYPES_ENUM_MOJOM_TRAITS_H_
 
 #include "base/notreached.h"
+#include "build/build_config.h"
 #include "media/base/renderer_factory_selector.h"
 #include "media/base/svc_scalability_mode.h"
 #include "media/base/video_frame_metadata.h"
 #include "media/base/video_transformation.h"
+#include "media/cdm/cdm_document_service.h"
 #include "media/mojo/mojom/media_types.mojom-shared.h"
 
 // Most enums have automatically generated traits, in media_types.mojom.h, due
@@ -18,6 +20,45 @@
 
 namespace mojo {
 
+#if BUILDFLAG(IS_WIN)
+template <>
+struct EnumTraits<media::mojom::CdmEvent, ::media::CdmEvent> {
+  static media::mojom::CdmEvent ToMojom(::media::CdmEvent input) {
+    switch (input) {
+      case ::media::CdmEvent::kSignificantPlayback:
+        return media::mojom::CdmEvent::kSignificantPlayback;
+      case ::media::CdmEvent::kPlaybackError:
+        return media::mojom::CdmEvent::kPlaybackError;
+      case ::media::CdmEvent::kCdmError:
+        return media::mojom::CdmEvent::kCdmError;
+    }
+
+    NOTREACHED();
+    return media::mojom::CdmEvent::kCdmError;
+  }
+
+  // Returning false results in deserialization failure and causes the
+  // message pipe receiving it to be disconnected.
+  static bool FromMojom(media::mojom::CdmEvent input,
+                        ::media::CdmEvent* output) {
+    switch (input) {
+      case media::mojom::CdmEvent::kSignificantPlayback:
+        *output = ::media::CdmEvent::kSignificantPlayback;
+        return true;
+      case media::mojom::CdmEvent::kPlaybackError:
+        *output = ::media::CdmEvent::kPlaybackError;
+        return true;
+      case media::mojom::CdmEvent::kCdmError:
+        *output = ::media::CdmEvent::kCdmError;
+        return true;
+    }
+
+    NOTREACHED();
+    return false;
+  }
+};
+#endif  // BUILDFLAG(IS_WIN)
+
 template <>
 struct EnumTraits<media::mojom::CdmSessionClosedReason,
                   ::media::CdmSessionClosedReason> {
diff --git a/media/mojo/services/mojo_cdm_helper.cc b/media/mojo/services/mojo_cdm_helper.cc
index 6c27f24..cec5821e 100644
--- a/media/mojo/services/mojo_cdm_helper.cc
+++ b/media/mojo/services/mojo_cdm_helper.cc
@@ -63,6 +63,11 @@
   ConnectToCdmDocumentService();
   cdm_document_service_->SetCdmClientToken(client_token);
 }
+
+void MojoCdmHelper::OnCdmEvent(CdmEvent event) {
+  ConnectToCdmDocumentService();
+  cdm_document_service_->OnCdmEvent(event);
+}
 #endif  // BUILDFLAG(IS_WIN)
 
 cdm::Buffer* MojoCdmHelper::CreateCdmBuffer(size_t capacity) {
diff --git a/media/mojo/services/mojo_cdm_helper.h b/media/mojo/services/mojo_cdm_helper.h
index 321383e..97e3a0a 100644
--- a/media/mojo/services/mojo_cdm_helper.h
+++ b/media/mojo/services/mojo_cdm_helper.h
@@ -51,6 +51,7 @@
 #if BUILDFLAG(IS_WIN)
   void GetMediaFoundationCdmData(GetMediaFoundationCdmDataCB callback) final;
   void SetCdmClientToken(const std::vector<uint8_t>& client_token) final;
+  void OnCdmEvent(CdmEvent event) final;
 #endif  // BUILDFLAG(IS_WIN)
 
   // MojoCdmFileIO::Delegate implementation.
diff --git a/media/renderers/win/media_foundation_renderer.cc b/media/renderers/win/media_foundation_renderer.cc
index c9dc53a1..61860c60 100644
--- a/media/renderers/win/media_foundation_renderer.cc
+++ b/media/renderers/win/media_foundation_renderer.cc
@@ -679,6 +679,13 @@
     return;
   }
 
+  const int kSignificantPlaybackFrames = 1800;  // About 30 fps for 1 minute.
+  if (!has_reported_significant_playback_ && cdm_proxy_ &&
+      new_stats.video_frames_decoded >= kSignificantPlaybackFrames) {
+    has_reported_significant_playback_ = true;
+    cdm_proxy_->OnSignificantPlayback();
+  }
+
   if (statistics_ != new_stats) {
     // OnStatisticsUpdate() expects delta values.
     PipelineStatistics delta;
@@ -878,26 +885,31 @@
       (hresult.has_value() ? (" (" + PrintHr(hresult.value()) + ")") : "");
 
   DLOG(ERROR) << error;
-  MEDIA_LOG(ERROR, media_log_) << error;
-  ReportErrorReason(reason);
 
-  if (!hresult.has_value()) {
-    renderer_client_->OnError(status);
-    return;
-  }
+  // Report to MediaLog so the error will show up in media internals and
+  // MediaError.message.
+  MEDIA_LOG(ERROR, media_log_) << error;
+
+  // Report the error to UMA.
+  ReportErrorReason(reason);
 
   // HRESULT 0x8004CD12 is DRM_E_TEE_INVALID_HWDRM_STATE, which can happen
   // during OS sleep/resume, or moving video to different graphics adapters.
   // This is not an error, so special case it here.
-  PipelineStatus status_to_report = status;
-  if (hresult == static_cast<HRESULT>(0x8004CD12)) {
-    status_to_report = PIPELINE_ERROR_HARDWARE_CONTEXT_RESET;
+  PipelineStatus new_status = status;
+  if (hresult.has_value() && hresult == static_cast<HRESULT>(0x8004CD12)) {
+    new_status = PIPELINE_ERROR_HARDWARE_CONTEXT_RESET;
     if (cdm_proxy_)
       cdm_proxy_->OnHardwareContextReset();
+  } else if (cdm_proxy_) {
+    cdm_proxy_->OnPlaybackError();
   }
 
-  status_to_report.WithData("hresult", static_cast<uint32_t>(hresult.value()));
-  renderer_client_->OnError(status_to_report);
+  // Attach hresult to `new_status` for logging and metrics reporting.
+  if (hresult.has_value())
+    new_status.WithData("hresult", static_cast<uint32_t>(hresult.value()));
+
+  renderer_client_->OnError(new_status);
 }
 
 void MediaFoundationRenderer::RequestNextFrameBetweenTimestamps(
diff --git a/media/renderers/win/media_foundation_renderer.h b/media/renderers/win/media_foundation_renderer.h
index 820284a..87afc1d 100644
--- a/media/renderers/win/media_foundation_renderer.h
+++ b/media/renderers/win/media_foundation_renderer.h
@@ -203,6 +203,8 @@
   // The represents the rendering mode of the Media Engine.
   RenderingMode rendering_mode_ = RenderingMode::DirectComposition;
 
+  bool has_reported_significant_playback_ = false;
+
   // NOTE: Weak pointers must be invalidated before all other member variables.
   base::WeakPtrFactory<MediaFoundationRenderer> weak_factory_{this};
 };
diff --git a/media/renderers/win/media_foundation_renderer_unittest.cc b/media/renderers/win/media_foundation_renderer_unittest.cc
index e6cebaa1..17b1640f 100644
--- a/media/renderers/win/media_foundation_renderer_unittest.cc
+++ b/media/renderers/win/media_foundation_renderer_unittest.cc
@@ -50,6 +50,8 @@
   MOCK_METHOD2(ProcessContentEnabler,
                HRESULT(IUnknown* request, IMFAsyncResult* result));
   MOCK_METHOD0(OnHardwareContextReset, void());
+  MOCK_METHOD0(OnSignificantPlayback, void());
+  MOCK_METHOD0(OnPlaybackError, void());
 
  protected:
   ~MockMediaFoundationCdmProxy() override;
diff --git a/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java b/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java
index 0e366e4c..f53927a 100644
--- a/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java
+++ b/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java
@@ -41,6 +41,8 @@
     private NetworkChangeNotifierAutoDetect mAutoDetector;
     // Last value broadcast via ConnectionTypeChange signal.
     private int mCurrentConnectionType = ConnectionType.CONNECTION_UNKNOWN;
+    // Last value broadcast via ConnectionCostChange signal.
+    private int mCurrentConnectionCost = ConnectionCost.UNKNOWN;
 
     @SuppressLint("StaticFieldLeak")
     private static NetworkChangeNotifier sInstance;
@@ -83,6 +85,11 @@
                 : mAutoDetector.getCurrentNetworkState().getConnectionSubtype();
     }
 
+    @CalledByNative
+    public int getCurrentConnectionCost() {
+        return mCurrentConnectionCost;
+    }
+
     /**
      * Returns NetID of device's current default connected network used for
      * communication. Only available on Lollipop and newer releases and when
@@ -192,6 +199,10 @@
                                 updateCurrentConnectionType(newConnectionType);
                             }
                             @Override
+                            public void onConnectionCostChanged(int newConnectionCost) {
+                                notifyObserversOfConnectionCostChange(newConnectionCost);
+                            }
+                            @Override
                             public void onConnectionSubtypeChanged(int newConnectionSubtype) {
                                 notifyObserversOfConnectionSubtypeChange(newConnectionSubtype);
                             }
@@ -216,6 +227,7 @@
                 final NetworkChangeNotifierAutoDetect.NetworkState networkState =
                         mAutoDetector.getCurrentNetworkState();
                 updateCurrentConnectionType(networkState.getConnectionType());
+                updateCurrentConnectionCost(networkState.getConnectionCost());
                 notifyObserversOfConnectionSubtypeChange(networkState.getConnectionSubtype());
             }
         } else {
@@ -282,6 +294,14 @@
         getInstance().notifyObserversOfConnectionTypeChange(connectionType, netId);
     }
 
+    // For testing, pretend the connection cost has changed.
+    @CalledByNative
+    @VisibleForTesting
+    public static void fakeConnectionCostChanged(int connectionCost) {
+        setAutoDetectConnectivityState(false);
+        getInstance().notifyObserversOfConnectionCostChange(connectionCost);
+    }
+
     // For testing, pretend the connection subtype has changed.
     @CalledByNative
     public static void fakeConnectionSubtypeChanged(int connectionSubtype) {
@@ -311,6 +331,21 @@
         }
     }
 
+    private void updateCurrentConnectionCost(int newConnectionCost) {
+        mCurrentConnectionCost = newConnectionCost;
+        notifyObserversOfConnectionCostChange(newConnectionCost);
+    }
+
+    /**
+     * Alerts all observers of a connection cost change.
+     */
+    void notifyObserversOfConnectionCostChange(int newConnectionCost) {
+        for (Long nativeChangeNotifier : mNativeChangeNotifiers) {
+            NetworkChangeNotifierJni.get().notifyConnectionCostChanged(
+                    nativeChangeNotifier, NetworkChangeNotifier.this, newConnectionCost);
+        }
+    }
+
     /**
      * Alerts all observers of a bandwidth change.
      */
@@ -406,6 +441,10 @@
                 int newConnectionType, long defaultNetId);
 
         @NativeClassQualifiedName("NetworkChangeNotifierDelegateAndroid")
+        void notifyConnectionCostChanged(
+                long nativePtr, NetworkChangeNotifier caller, int newConnectionCost);
+
+        @NativeClassQualifiedName("NetworkChangeNotifierDelegateAndroid")
         void notifyMaxBandwidthChanged(long nativePtr, NetworkChangeNotifier caller, int subType);
 
         @NativeClassQualifiedName("NetworkChangeNotifierDelegateAndroid")
diff --git a/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java b/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
index 921955f..7abfa983 100644
--- a/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
+++ b/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
@@ -63,6 +63,7 @@
         private final boolean mConnected;
         private final int mType;
         private final int mSubtype;
+        private final boolean mIsMetered;
         // WIFI SSID of the connection on pre-Marshmallow, NetID starting with Marshmallow. Always
         // non-null (i.e. instead of null it'll be an empty string) to facilitate .equals().
         private final String mNetworkIdentifier;
@@ -71,11 +72,12 @@
         // Indicates the DNS-over-TLS server in use, if specified.
         private final String mPrivateDnsServerName;
 
-        public NetworkState(boolean connected, int type, int subtype, String networkIdentifier,
-                boolean isPrivateDnsActive, String privateDnsServerName) {
+        public NetworkState(boolean connected, int type, int subtype, boolean isMetered,
+                String networkIdentifier, boolean isPrivateDnsActive, String privateDnsServerName) {
             mConnected = connected;
             mType = type;
             mSubtype = subtype;
+            mIsMetered = isMetered;
             mNetworkIdentifier = networkIdentifier == null ? "" : networkIdentifier;
             mIsPrivateDnsActive = isPrivateDnsActive;
             mPrivateDnsServerName = privateDnsServerName == null ? "" : privateDnsServerName;
@@ -89,6 +91,10 @@
             return mType;
         }
 
+        public boolean isMetered() {
+            return mIsMetered;
+        }
+
         public int getNetworkSubType() {
             return mSubtype;
         }
@@ -110,6 +116,17 @@
         }
 
         /**
+         * Returns the connection cost for the given NetworkState.
+         */
+        @ConnectionCost
+        public int getConnectionCost() {
+            if (isMetered()) {
+                return ConnectionCost.METERED;
+            }
+            return ConnectionCost.UNMETERED;
+        }
+
+        /**
          * Returns the connection subtype for the given NetworkState.
          */
         public int getConnectionSubtype() {
@@ -246,16 +263,21 @@
             }
             networkInfo = processActiveNetworkInfo(networkInfo);
             if (networkInfo == null) {
-                return new NetworkState(false, -1, -1, null, false, "");
+                return new NetworkState(false, -1, -1, false, null, false, "");
             }
+
             if (network != null) {
+                final NetworkCapabilities capabilities = getNetworkCapabilities(network);
+                boolean isMetered = (capabilities != null
+                        && !capabilities.hasCapability(
+                                NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
                 DnsStatus dnsStatus = AndroidNetworkLibrary.getDnsStatus(network);
                 if (dnsStatus == null) {
                     return new NetworkState(true, networkInfo.getType(), networkInfo.getSubtype(),
-                            String.valueOf(networkToNetId(network)), false, "");
+                            isMetered, String.valueOf(networkToNetId(network)), false, "");
                 } else {
                     return new NetworkState(true, networkInfo.getType(), networkInfo.getSubtype(),
-                            String.valueOf(networkToNetId(network)),
+                            isMetered, String.valueOf(networkToNetId(network)),
                             dnsStatus.getPrivateDnsActive(), dnsStatus.getPrivateDnsServerName());
                 }
             }
@@ -265,14 +287,14 @@
                 // Since Android 4.2 the SSID can be retrieved from NetworkInfo.getExtraInfo().
                 if (networkInfo.getExtraInfo() != null && !"".equals(networkInfo.getExtraInfo())) {
                     return new NetworkState(true, networkInfo.getType(), networkInfo.getSubtype(),
-                            networkInfo.getExtraInfo(), false, "");
+                            false, networkInfo.getExtraInfo(), false, "");
                 }
                 // Fetch WiFi SSID directly from WifiManagerDelegate if not in NetworkInfo.
                 return new NetworkState(true, networkInfo.getType(), networkInfo.getSubtype(),
-                        wifiManagerDelegate.getWifiSsid(), false, "");
+                        false, wifiManagerDelegate.getWifiSsid(), false, "");
             }
             return new NetworkState(
-                    true, networkInfo.getType(), networkInfo.getSubtype(), null, false, "");
+                    true, networkInfo.getType(), networkInfo.getSubtype(), false, null, false, "");
         }
 
         /**
@@ -591,7 +613,7 @@
             mLinkProperties = null;
             mNetworkCapabilities = null;
             if (mRegistered) {
-                connectionTypeChangedTo(new NetworkState(false, -1, -1, null, false, ""));
+                connectionTypeChangedTo(new NetworkState(false, -1, -1, false, null, false, ""));
             }
         }
 
@@ -648,7 +670,10 @@
                 NetworkInfo networkInfo = mConnectivityManagerDelegate.getNetworkInfo(network);
                 type = networkInfo != null ? networkInfo.getType() : ConnectivityManager.TYPE_VPN;
             }
-            return new NetworkState(true, type, subtype, String.valueOf(networkToNetId(network)),
+            boolean isMetered = !mNetworkCapabilities.hasCapability(
+                    NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+            return new NetworkState(true, type, subtype, isMetered,
+                    String.valueOf(networkToNetId(network)),
                     ApiHelperForP.isPrivateDnsActive(mLinkProperties),
                     ApiHelperForP.getPrivateDnsServerName(mLinkProperties));
         }
@@ -897,6 +922,10 @@
          */
         public void onConnectionTypeChanged(@ConnectionType int newConnectionType);
         /**
+         * Called when connection cost of default network changes.
+         */
+        public void onConnectionCostChanged(int newConnectionCost);
+        /**
          * Called when connection subtype of default network changes.
          */
         public void onConnectionSubtypeChanged(int newConnectionSubtype);
@@ -1284,6 +1313,9 @@
                 || networkState.getConnectionSubtype() != mNetworkState.getConnectionSubtype()) {
             mObserver.onConnectionSubtypeChanged(networkState.getConnectionSubtype());
         }
+        if (networkState.getConnectionCost() != mNetworkState.getConnectionCost()) {
+            mObserver.onConnectionCostChanged(networkState.getConnectionCost());
+        }
         mNetworkState = networkState;
     }
 
diff --git a/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java b/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java
index 70d8be7..21c8416 100644
--- a/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java
+++ b/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java
@@ -189,6 +189,7 @@
         private boolean mActiveNetworkExists;
         private int mNetworkType;
         private int mNetworkSubtype;
+        private boolean mIsMetered;
         private boolean mIsPrivateDnsActive;
         private String mPrivateDnsServerName;
         private NetworkCallback mLastRegisteredNetworkCallback;
@@ -196,7 +197,7 @@
 
         @Override
         public NetworkState getNetworkState(WifiManagerDelegate wifiManagerDelegate) {
-            return new NetworkState(mActiveNetworkExists, mNetworkType, mNetworkSubtype,
+            return new NetworkState(mActiveNetworkExists, mNetworkType, mNetworkSubtype, mIsMetered,
                     mNetworkType == ConnectivityManager.TYPE_WIFI
                             ? wifiManagerDelegate.getWifiSsid()
                             : null,
@@ -271,6 +272,10 @@
             mNetworkType = networkType;
         }
 
+        public void setIsMetered(boolean isMetered) {
+            mIsMetered = isMetered;
+        }
+
         public void setNetworkSubtype(int networkSubtype) {
             mNetworkSubtype = networkSubtype;
         }
@@ -374,6 +379,8 @@
         @Override
         public void onConnectionTypeChanged(int newConnectionType) {}
         @Override
+        public void onConnectionCostChanged(int newConnectionCost) {}
+        @Override
         public void onConnectionSubtypeChanged(int newConnectionSubtype) {}
 
         @Override
@@ -485,6 +492,10 @@
         return mReceiver.getCurrentNetworkState().getConnectionType();
     }
 
+    private int getCurrentConnectionCost() {
+        return mReceiver.getCurrentNetworkState().getConnectionCost();
+    }
+
     @Before
     public void setUp() throws Throwable {
         LibraryLoader.getInstance().setLibraryProcessType(LibraryProcessType.PROCESS_BROWSER);
@@ -559,6 +570,20 @@
     }
 
     /**
+     * Tests that getCurrentConnectionCost() returns the correct result.
+     */
+    @Test
+    @UiThreadTest
+    @MediumTest
+    @Feature({"Android-AppBase"})
+    public void testNetworkChangeNotifierConnectionCost() {
+        mConnectivityDelegate.setIsMetered(true);
+        Assert.assertEquals(ConnectionCost.METERED, getCurrentConnectionCost());
+        mConnectivityDelegate.setIsMetered(false);
+        Assert.assertEquals(ConnectionCost.UNMETERED, getCurrentConnectionCost());
+    }
+
+    /**
      * Tests that changing the network type changes the connection subtype.
      */
     @Test
diff --git a/net/android/network_change_notifier_android.cc b/net/android/network_change_notifier_android.cc
index cfc82cb..001f2ae2 100644
--- a/net/android/network_change_notifier_android.cc
+++ b/net/android/network_change_notifier_android.cc
@@ -124,6 +124,11 @@
   return delegate_->GetCurrentConnectionType();
 }
 
+NetworkChangeNotifier::ConnectionCost
+NetworkChangeNotifierAndroid::GetCurrentConnectionCost() {
+  return delegate_->GetCurrentConnectionCost();
+}
+
 NetworkChangeNotifier::ConnectionSubtype
 NetworkChangeNotifierAndroid::GetCurrentConnectionSubtype() const {
   return delegate_->GetCurrentConnectionSubtype();
@@ -169,6 +174,10 @@
   BlockingThreadObjects::NotifyNetworkChangeNotifierObservers();
 }
 
+void NetworkChangeNotifierAndroid::OnConnectionCostChanged() {
+  NetworkChangeNotifier::NotifyObserversOfConnectionCostChange();
+}
+
 void NetworkChangeNotifierAndroid::OnMaxBandwidthChanged(
     double max_bandwidth_mbps,
     ConnectionType type) {
diff --git a/net/android/network_change_notifier_android.h b/net/android/network_change_notifier_android.h
index 2b57bb0..8cf8c1e4 100644
--- a/net/android/network_change_notifier_android.h
+++ b/net/android/network_change_notifier_android.h
@@ -63,6 +63,7 @@
 
   // NetworkChangeNotifier:
   ConnectionType GetCurrentConnectionType() const override;
+  ConnectionCost GetCurrentConnectionCost() override;
   // Requires ACCESS_WIFI_STATE permission in order to provide precise WiFi link
   // speed.
   void GetCurrentMaxBandwidthAndConnectionType(
@@ -79,6 +80,7 @@
 
   // NetworkChangeNotifierDelegateAndroid::Observer:
   void OnConnectionTypeChanged() override;
+  void OnConnectionCostChanged() override;
   void OnMaxBandwidthChanged(double max_bandwidth_mbps,
                              ConnectionType type) override;
   void OnNetworkConnected(NetworkHandle network) override;
diff --git a/net/android/network_change_notifier_android_unittest.cc b/net/android/network_change_notifier_android_unittest.cc
index 30b9ee9..087a258b1 100644
--- a/net/android/network_change_notifier_android_unittest.cc
+++ b/net/android/network_change_notifier_android_unittest.cc
@@ -35,18 +35,22 @@
 class NetworkChangeNotifierDelegateAndroidObserver
     : public NetworkChangeNotifierDelegateAndroid::Observer {
  public:
+  typedef NetworkChangeNotifier::ConnectionCost ConnectionCost;
   typedef NetworkChangeNotifier::ConnectionType ConnectionType;
   typedef NetworkChangeNotifier::NetworkHandle NetworkHandle;
   typedef NetworkChangeNotifier::NetworkList NetworkList;
 
   NetworkChangeNotifierDelegateAndroidObserver()
       : type_notifications_count_(0),
+        cost_notifications_count_(0),
         max_bandwidth_notifications_count_(0),
         default_network_active_notifications_count_(0) {}
 
   // NetworkChangeNotifierDelegateAndroid::Observer:
   void OnConnectionTypeChanged() override { type_notifications_count_++; }
 
+  void OnConnectionCostChanged() override { cost_notifications_count_++; }
+
   void OnMaxBandwidthChanged(
       double max_bandwidth_mbps,
       net::NetworkChangeNotifier::ConnectionType type) override {
@@ -66,6 +70,7 @@
   }
 
   int type_notifications_count() const { return type_notifications_count_; }
+  int cost_notifications_count() const { return cost_notifications_count_; }
   int bandwidth_notifications_count() const {
     return max_bandwidth_notifications_count_;
   }
@@ -75,6 +80,7 @@
 
  private:
   int type_notifications_count_;
+  int cost_notifications_count_;
   int max_bandwidth_notifications_count_;
   int default_network_active_notifications_count_;
 };
@@ -98,6 +104,21 @@
   int notifications_count_;
 };
 
+class NetworkChangeNotifierConnectionCostObserver
+    : public NetworkChangeNotifier::ConnectionCostObserver {
+ public:
+  // NetworkChangeNotifier::ConnectionCostObserver:
+  void OnConnectionCostChanged(
+      NetworkChangeNotifier::ConnectionCost cost) override {
+    notifications_count_++;
+  }
+
+  int notifications_count() const { return notifications_count_; }
+
+ private:
+  int notifications_count_ = 0;
+};
+
 class NetworkChangeNotifierMaxBandwidthObserver
     : public NetworkChangeNotifier::MaxBandwidthObserver {
  public:
@@ -168,6 +189,7 @@
 class BaseNetworkChangeNotifierAndroidTest : public TestWithTaskEnvironment {
  protected:
   typedef NetworkChangeNotifier::ConnectionType ConnectionType;
+  typedef NetworkChangeNotifier::ConnectionCost ConnectionCost;
   typedef NetworkChangeNotifier::ConnectionSubtype ConnectionSubtype;
 
   ~BaseNetworkChangeNotifierAndroidTest() override {}
@@ -217,6 +239,11 @@
     }
   }
 
+  void FakeConnectionCostChange(ConnectionCost cost) {
+    delegate_.FakeConnectionCostChanged(cost);
+    base::RunLoop().RunUntilIdle();
+  }
+
   void FakeConnectionSubtypeChange(ConnectionSubtype subtype) {
     delegate_.FakeConnectionSubtypeChanged(subtype);
     base::RunLoop().RunUntilIdle();
@@ -301,6 +328,8 @@
         &connection_type_observer_);
     NetworkChangeNotifier::AddConnectionTypeObserver(
         &other_connection_type_observer_);
+    NetworkChangeNotifier::AddConnectionCostObserver(
+        &connection_cost_observer_);
     NetworkChangeNotifier::AddMaxBandwidthObserver(&max_bandwidth_observer_);
   }
 
@@ -309,6 +338,7 @@
   }
 
   NetworkChangeNotifierObserver connection_type_observer_;
+  NetworkChangeNotifierConnectionCostObserver connection_cost_observer_;
   NetworkChangeNotifierMaxBandwidthObserver max_bandwidth_observer_;
   NetworkChangeNotifierObserver other_connection_type_observer_;
   NetworkChangeNotifier::DisableForTest disable_for_test_;
@@ -368,6 +398,34 @@
             other_connection_type_observer_.notifications_count());
 }
 
+TEST_F(NetworkChangeNotifierAndroidTest, ConnectionCost) {
+  FakeConnectionCostChange(ConnectionCost::CONNECTION_COST_UNMETERED);
+  EXPECT_EQ(NetworkChangeNotifier::CONNECTION_COST_UNMETERED,
+            notifier_.GetConnectionCost());
+  FakeConnectionCostChange(ConnectionCost::CONNECTION_COST_METERED);
+  EXPECT_EQ(NetworkChangeNotifier::CONNECTION_COST_METERED,
+            notifier_.GetConnectionCost());
+}
+
+TEST_F(NetworkChangeNotifierAndroidTest, ConnectionCostCallbackNotifier) {
+  FakeConnectionCostChange(ConnectionCost::CONNECTION_COST_UNMETERED);
+  EXPECT_EQ(1, connection_cost_observer_.notifications_count());
+
+  FakeConnectionCostChange(ConnectionCost::CONNECTION_COST_METERED);
+  EXPECT_EQ(2, connection_cost_observer_.notifications_count());
+}
+
+TEST_F(NetworkChangeNotifierDelegateAndroidTest,
+       ConnectionCostCallbackNotifier) {
+  EXPECT_EQ(0, delegate_observer_.cost_notifications_count());
+
+  FakeConnectionCostChange(ConnectionCost::CONNECTION_COST_UNMETERED);
+  EXPECT_EQ(1, delegate_observer_.cost_notifications_count());
+
+  FakeConnectionCostChange(ConnectionCost::CONNECTION_COST_METERED);
+  EXPECT_EQ(2, delegate_observer_.cost_notifications_count());
+}
+
 TEST_F(NetworkChangeNotifierAndroidTest, MaxBandwidth) {
   SetOnline();
   double max_bandwidth_mbps = 0.0;
diff --git a/net/android/network_change_notifier_delegate_android.cc b/net/android/network_change_notifier_delegate_android.cc
index 6c31087..3d37738 100644
--- a/net/android/network_change_notifier_delegate_android.cc
+++ b/net/android/network_change_notifier_delegate_android.cc
@@ -42,6 +42,22 @@
   return static_cast<NetworkChangeNotifier::ConnectionType>(connection_type);
 }
 
+// Converts a Java side connection cost (integer) to
+// the native side NetworkChangeNotifier::ConnectionCost.
+NetworkChangeNotifier::ConnectionCost ConvertConnectionCost(
+    jint connection_cost) {
+  switch (connection_cost) {
+    case NetworkChangeNotifier::CONNECTION_COST_UNKNOWN:
+    case NetworkChangeNotifier::CONNECTION_COST_UNMETERED:
+    case NetworkChangeNotifier::CONNECTION_COST_METERED:
+      break;
+    default:
+      NOTREACHED() << "Unknown connection cost received: " << connection_cost;
+      return NetworkChangeNotifier::CONNECTION_COST_UNKNOWN;
+  }
+  return static_cast<NetworkChangeNotifier::ConnectionCost>(connection_cost);
+}
+
 // Converts a Java side connection type (integer) to
 // the native side NetworkChangeNotifier::ConnectionType.
 NetworkChangeNotifier::ConnectionSubtype ConvertConnectionSubtype(
@@ -86,6 +102,9 @@
   SetCurrentConnectionType(
       ConvertConnectionType(Java_NetworkChangeNotifier_getCurrentConnectionType(
           env, java_network_change_notifier_)));
+  SetCurrentConnectionCost(
+      ConvertConnectionCost(Java_NetworkChangeNotifier_getCurrentConnectionCost(
+          env, java_network_change_notifier_)));
   SetCurrentMaxBandwidth(
       NetworkChangeNotifierAndroid::GetMaxBandwidthMbpsForConnectionSubtype(
           GetCurrentConnectionSubtype()));
@@ -120,6 +139,12 @@
   return connection_type_;
 }
 
+NetworkChangeNotifier::ConnectionCost
+NetworkChangeNotifierDelegateAndroid::GetCurrentConnectionCost() {
+  base::AutoLock auto_lock(connection_lock_);
+  return connection_cost_;
+}
+
 NetworkChangeNotifier::ConnectionSubtype
 NetworkChangeNotifierDelegateAndroid::GetCurrentConnectionSubtype() const {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -171,6 +196,19 @@
       env, java_network_active_notifier_);
 }
 
+void NetworkChangeNotifierDelegateAndroid::NotifyConnectionCostChanged(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint new_connection_cost) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  const ConnectionCost actual_connection_cost =
+      ConvertConnectionCost(new_connection_cost);
+  SetCurrentConnectionCost(actual_connection_cost);
+  base::AutoLock auto_lock(observer_lock_);
+  if (observer_)
+    observer_->OnConnectionCostChanged();
+}
+
 void NetworkChangeNotifierDelegateAndroid::NotifyConnectionTypeChanged(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
@@ -214,6 +252,11 @@
   return GetCurrentConnectionType();
 }
 
+jint NetworkChangeNotifierDelegateAndroid::GetConnectionCost(JNIEnv*, jobject) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  return GetCurrentConnectionCost();
+}
+
 void NetworkChangeNotifierDelegateAndroid::NotifyMaxBandwidthChanged(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
@@ -380,6 +423,12 @@
   connection_type_ = new_connection_type;
 }
 
+void NetworkChangeNotifierDelegateAndroid::SetCurrentConnectionCost(
+    ConnectionCost new_connection_cost) {
+  base::AutoLock auto_lock(connection_lock_);
+  connection_cost_ = new_connection_cost;
+}
+
 void NetworkChangeNotifierDelegateAndroid::SetCurrentMaxBandwidth(
     double max_bandwidth) {
   base::AutoLock auto_lock(connection_lock_);
@@ -441,6 +490,12 @@
   Java_NetworkChangeNotifier_fakeDefaultNetwork(env, network, type);
 }
 
+void NetworkChangeNotifierDelegateAndroid::FakeConnectionCostChanged(
+    ConnectionCost cost) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_NetworkChangeNotifier_fakeConnectionCostChanged(env, cost);
+}
+
 void NetworkChangeNotifierDelegateAndroid::FakeConnectionSubtypeChanged(
     ConnectionSubtype subtype) {
   JNIEnv* env = base::android::AttachCurrentThread();
diff --git a/net/android/network_change_notifier_delegate_android.h b/net/android/network_change_notifier_delegate_android.h
index 78488d8..71685e4 100644
--- a/net/android/network_change_notifier_delegate_android.h
+++ b/net/android/network_change_notifier_delegate_android.h
@@ -26,6 +26,7 @@
 // unless otherwise stated (e.g. RegisterObserver()/UnregisterObserver()).
 class NET_EXPORT_PRIVATE NetworkChangeNotifierDelegateAndroid {
  public:
+  typedef NetworkChangeNotifier::ConnectionCost ConnectionCost;
   typedef NetworkChangeNotifier::ConnectionType ConnectionType;
   typedef NetworkChangeNotifier::ConnectionSubtype ConnectionSubtype;
   typedef NetworkChangeNotifier::NetworkHandle NetworkHandle;
@@ -41,6 +42,9 @@
     // Updates the current connection type.
     virtual void OnConnectionTypeChanged() = 0;
 
+    // Updates the current connection cost.
+    virtual void OnConnectionCostChanged() = 0;
+
     // Updates the current max bandwidth.
     virtual void OnMaxBandwidthChanged(double max_bandwidth_mbps,
                                        ConnectionType connection_type) = 0;
@@ -76,6 +80,16 @@
   jint GetConnectionType(JNIEnv* env, jobject obj) const;
 
   // Called from NetworkChangeNotifier.java on the JNI thread whenever
+  // the connection cost changes. This updates the current connection cost seen
+  // by this class and forwards the notification to the observers that
+  // subscribed through RegisterObserver().
+  void NotifyConnectionCostChanged(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jint new_connection_cost);
+  jint GetConnectionCost(JNIEnv* env, jobject obj);
+
+  // Called from NetworkChangeNotifier.java on the JNI thread whenever
   // the maximum bandwidth of the connection changes. This updates the current
   // max bandwidth seen by this class and forwards the notification to the
   // observers that subscribed through RegisterObserver().
@@ -132,6 +146,7 @@
 
   // These methods are simply implementations of NetworkChangeNotifier APIs of
   // the same name. They can be called from any thread.
+  ConnectionCost GetCurrentConnectionCost();
   ConnectionType GetCurrentConnectionType() const;
   void GetCurrentMaxBandwidthAndConnectionType(
       double* max_bandwidth_mbps,
@@ -169,6 +184,7 @@
   void DisableDefaultNetworkActiveNotifications();
 
   // Setters that grab appropriate lock.
+  void SetCurrentConnectionCost(ConnectionCost connection_cost);
   void SetCurrentConnectionType(ConnectionType connection_type);
   void SetCurrentMaxBandwidth(double max_bandwidth);
   void SetCurrentDefaultNetwork(NetworkHandle default_network);
@@ -182,6 +198,7 @@
   void FakeNetworkDisconnected(NetworkHandle network);
   void FakePurgeActiveNetworkList(NetworkList networks);
   void FakeDefaultNetwork(NetworkHandle network, ConnectionType type);
+  void FakeConnectionCostChanged(ConnectionCost cost);
   void FakeConnectionSubtypeChanged(ConnectionSubtype subtype);
   void FakeDefaultNetworkActive();
 
@@ -202,6 +219,7 @@
 
   mutable base::Lock connection_lock_;  // Protects the state below.
   ConnectionType connection_type_;
+  ConnectionCost connection_cost_;
   double connection_max_bandwidth_;
   NetworkHandle default_network_;
   NetworkMap network_map_;
diff --git a/net/base/network_change_notifier.h b/net/base/network_change_notifier.h
index 739a13c0..7f5ee34 100644
--- a/net/base/network_change_notifier.h
+++ b/net/base/network_change_notifier.h
@@ -107,6 +107,9 @@
     SUBTYPE_LAST = SUBTYPE_WIFI_AD
   };
 
+  // A Java counterpart will be generated for this enum.
+  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.net
+  //
   // These values are persisted to logs. Entries should not be renumbered and
   // numeric values should never be reused.
   enum ConnectionCost {
diff --git a/net/base/network_change_notifier_mac.mm b/net/base/network_change_notifier_mac.mm
index 30ca4fb8..949c81a 100644
--- a/net/base/network_change_notifier_mac.mm
+++ b/net/base/network_change_notifier_mac.mm
@@ -81,9 +81,6 @@
   if (connection_type_initialized_)
     return connection_type_;
 
-  SCOPED_UMA_HISTOGRAM_TIMER(
-      "Net.NetworkChangeNotifierMac.GetCurrentConnectionTypeWaitTime");
-
   // Wait up to a limited amount of time for the connection type to be
   // determined, to avoid blocking the main thread indefinitely. Since
   // ConditionVariables are susceptible to spurious wake-ups, each call to
diff --git a/net/cert_net/cert_net_fetcher_url_request_unittest.cc b/net/cert_net/cert_net_fetcher_url_request_unittest.cc
index 4455d3d..3def9a1 100644
--- a/net/cert_net/cert_net_fetcher_url_request_unittest.cc
+++ b/net/cert_net/cert_net_fetcher_url_request_unittest.cc
@@ -28,6 +28,7 @@
 #include "net/test/test_with_task_environment.h"
 #include "net/test/url_request/url_request_hanging_read_job.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "net/url_request/url_request_context_builder.h"
 #include "net/url_request/url_request_filter.h"
 #include "net/url_request/url_request_interceptor.h"
 #include "net/url_request/url_request_job_factory.h"
@@ -49,50 +50,6 @@
 
 const char kMockSecureDnsHostname[] = "mock.secure.dns.check";
 
-// A non-mock URLRequestContext which can access http:// urls.
-class RequestContext : public URLRequestContext {
- public:
-  RequestContext() : storage_(this) {
-    ProxyConfig no_proxy;
-    storage_.set_host_resolver(std::make_unique<MockHostResolver>(
-        MockHostResolverBase::RuleResolver::GetLocalhostResult()));
-    storage_.set_cert_verifier(std::make_unique<MockCertVerifier>());
-    storage_.set_transport_security_state(
-        std::make_unique<TransportSecurityState>());
-    storage_.set_ct_policy_enforcer(
-        std::make_unique<DefaultCTPolicyEnforcer>());
-    storage_.set_proxy_resolution_service(
-        ConfiguredProxyResolutionService::CreateFixed(
-            ProxyConfigWithAnnotation(no_proxy, TRAFFIC_ANNOTATION_FOR_TESTS)));
-    storage_.set_ssl_config_service(
-        std::make_unique<SSLConfigServiceDefaults>());
-    storage_.set_http_server_properties(
-        std::make_unique<HttpServerProperties>());
-    storage_.set_quic_context(std::make_unique<QuicContext>());
-
-    HttpNetworkSessionContext session_context;
-    session_context.host_resolver = host_resolver();
-    session_context.cert_verifier = cert_verifier();
-    session_context.transport_security_state = transport_security_state();
-    session_context.ct_policy_enforcer = ct_policy_enforcer();
-    session_context.proxy_resolution_service = proxy_resolution_service();
-    session_context.ssl_config_service = ssl_config_service();
-    session_context.http_server_properties = http_server_properties();
-    session_context.quic_context = quic_context();
-    storage_.set_http_network_session(std::make_unique<HttpNetworkSession>(
-        HttpNetworkSessionParams(), session_context));
-    storage_.set_http_transaction_factory(std::make_unique<HttpCache>(
-        storage_.http_network_session(), HttpCache::DefaultBackend::InMemory(0),
-        false /* is_main_cache */));
-    storage_.set_job_factory(std::make_unique<URLRequestJobFactory>());
-  }
-
-  ~RequestContext() override { AssertNoURLRequests(); }
-
- private:
-  URLRequestContextStorage storage_;
-};
-
 // Wait for the request to complete, and verify that it completed successfully
 // with the indicated bytes.
 void VerifySuccess(const std::string& expected_body,
@@ -117,8 +74,9 @@
 }
 
 struct NetworkThreadState {
-  TestNetworkDelegate network_delegate;
-  RequestContext context;
+  std::unique_ptr<URLRequestContext> context;
+  // Owned by `context`.
+  raw_ptr<TestNetworkDelegate> network_delegate;
 };
 
 class CertNetFetcherURLRequestTest : public PlatformTest {
@@ -143,7 +101,7 @@
 
   void CreateFetcherOnNetworkThread(base::WaitableEvent* done) {
     fetcher_ = base::MakeRefCounted<CertNetFetcherURLRequest>();
-    fetcher_->SetURLRequestContext(&state_->context);
+    fetcher_->SetURLRequestContext(state_->context.get());
     done->Signal();
   }
 
@@ -204,7 +162,10 @@
 
   void InitOnNetworkThread(base::WaitableEvent* done) {
     state_ = std::make_unique<NetworkThreadState>();
-    state_->context.set_network_delegate(&state_->network_delegate);
+    auto builder = CreateTestURLRequestContextBuilder();
+    state_->network_delegate =
+        builder->set_network_delegate(std::make_unique<TestNetworkDelegate>());
+    state_->context = builder->Build();
     done->Signal();
   }
 
@@ -230,7 +191,7 @@
   }
 
   void CountCreatedRequests(int* count, base::WaitableEvent* done) {
-    *count = state_->network_delegate.created_requests();
+    *count = state_->network_delegate->created_requests();
     done->Signal();
   }
 
diff --git a/net/cookies/canonical_cookie.cc b/net/cookies/canonical_cookie.cc
index 5a44d46..29d32a30c2 100644
--- a/net/cookies/canonical_cookie.cc
+++ b/net/cookies/canonical_cookie.cc
@@ -333,6 +333,18 @@
   return static_cast<CookieSameSiteForMetrics>((static_cast<int>(enum_in) + 1));
 }
 
+// Checks if `port` is within [0,65535] or url::PORT_UNSPECIFIED. Returns `port`
+// if so and url::PORT_INVALID otherwise.
+int ValidateAndAdjustSourcePort(int port) {
+  if ((port >= 0 && port <= 65535) || port == url::PORT_UNSPECIFIED) {
+    // 0 would be really weird as it has a special meaning, but it's still
+    // technically a valid tcp/ip port so we're going to accept it here.
+    return port;
+  }
+
+  return url::PORT_INVALID;
+}
+
 }  // namespace
 
 CookieAccessParams::CookieAccessParams(CookieAccessSemantics access_semantics,
@@ -382,9 +394,8 @@
       priority_(priority),
       same_party_(same_party),
       partition_key_(std::move(partition_key)),
-      source_scheme_(source_scheme) {
-  SetSourcePort(source_port);
-}
+      source_scheme_(source_scheme),
+      source_port_(source_port) {}
 
 CanonicalCookie::~CanonicalCookie() = default;
 
@@ -555,7 +566,7 @@
                                          ? CookieSourceScheme::kSecure
                                          : CookieSourceScheme::kNonSecure;
   // Get the port, this will get a default value if a port isn't provided.
-  int source_port = url.EffectiveIntPort();
+  int source_port = ValidateAndAdjustSourcePort(url.EffectiveIntPort());
 
   std::unique_ptr<CanonicalCookie> cc = base::WrapUnique(new CanonicalCookie(
       parsed_cookie.Name(), parsed_cookie.Value(), cookie_domain, cookie_path,
@@ -686,7 +697,7 @@
   }
 
   // Get the port, this will get a default value if a port isn't provided.
-  int source_port = url.EffectiveIntPort();
+  int source_port = ValidateAndAdjustSourcePort(url.EffectiveIntPort());
 
   std::string cookie_path = CanonicalCookie::CanonPathWithString(url, path);
   // Canonicalize path again to make sure it escapes characters as needed.
@@ -766,10 +777,18 @@
     absl::optional<CookiePartitionKey> partition_key,
     CookieSourceScheme source_scheme,
     int source_port) {
+  // We check source_port here because it could have concievably been
+  // corrupted and changed to out of range. Eventually this would be caught by
+  // IsCanonical*() but since the source_port is only used by metrics so far
+  // nothing else checks it. So let's normalize it here and then update this
+  // method when origin-bound cookies is implemented.
+  // TODO(crbug.com/1170548)
+  int validated_port = ValidateAndAdjustSourcePort(source_port);
+
   std::unique_ptr<CanonicalCookie> cc = base::WrapUnique(new CanonicalCookie(
       std::move(name), std::move(value), std::move(domain), std::move(path),
       creation, expiration, last_access, secure, httponly, same_site, priority,
-      same_party, partition_key, source_scheme, source_port));
+      same_party, partition_key, source_scheme, validated_port));
 
   if (cc->IsCanonicalForFromStorage()) {
     // This will help capture the number of times a cookie is canonical but does
@@ -812,13 +831,7 @@
 }
 
 void CanonicalCookie::SetSourcePort(int port) {
-  if ((port >= 0 && port <= 65535) || port == url::PORT_UNSPECIFIED) {
-    // 0 would be really weird as it has a special meaning, but it's still
-    // technically a valid tcp/ip port so we're going to accept it here.
-    source_port_ = port;
-  } else {
-    source_port_ = url::PORT_INVALID;
-  }
+  source_port_ = ValidateAndAdjustSourcePort(port);
 }
 
 bool CanonicalCookie::IsEquivalentForSecureCookieMatching(
diff --git a/net/cookies/canonical_cookie_unittest.cc b/net/cookies/canonical_cookie_unittest.cc
index 66088dd1..76b948c0 100644
--- a/net/cookies/canonical_cookie_unittest.cc
+++ b/net/cookies/canonical_cookie_unittest.cc
@@ -89,9 +89,9 @@
   EXPECT_TRUE(cookie2->IsPartitioned());
   EXPECT_EQ(cookie2->SourceScheme(), CookieSourceScheme::kNonSecure);
   // Because the port can be set explicitly in the constructor its value can be
-  // independent of the other parameters. In this case, test that an invalid
-  // port value is interpreted as such.
-  EXPECT_EQ(cookie2->SourcePort(), url::PORT_INVALID);
+  // independent of the other parameters. In this case, test that an out of
+  // range port is kept out of range.
+  EXPECT_EQ(cookie2->SourcePort(), 65536);
 
   // Set Secure to true but don't specify source_scheme or port.
   auto cookie3 = CanonicalCookie::CreateUnsafeCookieForTesting(
diff --git a/net/cookies/cookie_monster_change_dispatcher.cc b/net/cookies/cookie_monster_change_dispatcher.cc
index 10384e3..d9e41f2 100644
--- a/net/cookies/cookie_monster_change_dispatcher.cc
+++ b/net/cookies/cookie_monster_change_dispatcher.cc
@@ -86,6 +86,11 @@
     }
   }
 
+  if (!change.cookie.IsPartitioned() &&
+      net::CookiePartitionKey::HasNonce(cookie_partition_key_)) {
+    return;
+  }
+
   if (change.cookie.IsPartitioned() &&
       change.cookie.PartitionKey() != cookie_partition_key_) {
     return;
diff --git a/net/cookies/cookie_partition_key_unittest.cc b/net/cookies/cookie_partition_key_unittest.cc
index f3c41a8..b500019 100644
--- a/net/cookies/cookie_partition_key_unittest.cc
+++ b/net/cookies/cookie_partition_key_unittest.cc
@@ -247,6 +247,10 @@
   auto key3 = CookiePartitionKey::FromNetworkIsolationKey(
       NetworkIsolationKey(top_level_site, frame_site, &nonce1));
   EXPECT_EQ(key1, key3);
+
+  auto unnonced_key = CookiePartitionKey::FromNetworkIsolationKey(
+      NetworkIsolationKey(top_level_site, frame_site));
+  EXPECT_NE(key1, unnonced_key);
 }
 
 }  // namespace net
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 4875abb..4d1aa39 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -171,9 +171,7 @@
       quic_stream_factory_(context.net_log,
                            context.host_resolver,
                            context.ssl_config_service,
-                           context.client_socket_factory
-                               ? context.client_socket_factory.get()
-                               : ClientSocketFactory::GetDefaultFactory(),
+                           context.client_socket_factory,
                            context.http_server_properties,
                            context.cert_verifier,
                            context.ct_policy_enforcer,
@@ -208,6 +206,7 @@
   DCHECK(proxy_resolution_service_);
   DCHECK(ssl_config_service_);
   CHECK(http_server_properties_);
+  DCHECK(context_.client_socket_factory);
 
   normal_socket_pool_manager_ = std::make_unique<ClientSocketPoolManagerImpl>(
       CreateCommonConnectJobParams(false /* for_websockets */),
@@ -402,9 +401,7 @@
   // Use null websocket_endpoint_lock_manager, which is only set for WebSockets,
   // and only when not using a proxy.
   return CommonConnectJobParams(
-      context_.client_socket_factory ? context_.client_socket_factory.get()
-                                     : ClientSocketFactory::GetDefaultFactory(),
-      context_.host_resolver, &http_auth_cache_,
+      context_.client_socket_factory, context_.host_resolver, &http_auth_cache_,
       context_.http_auth_handler_factory, &spdy_session_pool_,
       &context_.quic_context->params()->supported_versions,
       &quic_stream_factory_, context_.proxy_delegate,
diff --git a/net/http/http_response_body_drainer_unittest.cc b/net/http/http_response_body_drainer_unittest.cc
index d2f92e4..3e65035 100644
--- a/net/http/http_response_body_drainer_unittest.cc
+++ b/net/http/http_response_body_drainer_unittest.cc
@@ -32,6 +32,7 @@
 #include "net/http/transport_security_state.h"
 #include "net/proxy_resolution/configured_proxy_resolution_service.h"
 #include "net/quic/quic_context.h"
+#include "net/socket/socket_test_util.h"
 #include "net/ssl/ssl_config_service_defaults.h"
 #include "net/test/test_with_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -256,6 +257,7 @@
 
   HttpNetworkSession* CreateNetworkSession() {
     HttpNetworkSessionContext context;
+    context.client_socket_factory = &socket_factory_;
     context.proxy_resolution_service = proxy_resolution_service_.get();
     context.ssl_config_service = ssl_config_service_.get();
     context.http_server_properties = http_server_properties_.get();
@@ -273,6 +275,7 @@
   TransportSecurityState transport_security_state_;
   DefaultCTPolicyEnforcer ct_policy_enforcer_;
   QuicContext quic_context_;
+  MockClientSocketFactory socket_factory_;
   const std::unique_ptr<HttpNetworkSession> session_;
   CloseResultWaiter result_waiter_;
   const raw_ptr<MockHttpStream> mock_stream_;       // Owned by |drainer_|.
diff --git a/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc b/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
index c34711de..39601b8 100644
--- a/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
+++ b/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
@@ -45,7 +45,7 @@
 #include "net/test/gtest_util.h"
 #include "net/test/test_with_task_environment.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "net/url_request/url_request_context_storage.h"
+#include "net/url_request/url_request_context_builder.h"
 #include "net/url_request/url_request_job_factory.h"
 #include "net/url_request/url_request_test_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -74,51 +74,6 @@
   std::u16string text;
 };
 
-// A non-mock URL request which can access http:// urls.
-class RequestContext : public URLRequestContext {
- public:
-  RequestContext() : storage_(this) {
-    ProxyConfig no_proxy;
-    storage_.set_host_resolver(std::make_unique<MockCachingHostResolver>(
-        /*cache_invalidation_num=*/0, /*default_result=*/
-        MockHostResolverBase::RuleResolver::GetLocalhostResult()));
-    storage_.set_cert_verifier(std::make_unique<MockCertVerifier>());
-    storage_.set_transport_security_state(
-        std::make_unique<TransportSecurityState>());
-    storage_.set_ct_policy_enforcer(
-        std::make_unique<DefaultCTPolicyEnforcer>());
-    storage_.set_proxy_resolution_service(
-        ConfiguredProxyResolutionService::CreateFixed(
-            ProxyConfigWithAnnotation(no_proxy, TRAFFIC_ANNOTATION_FOR_TESTS)));
-    storage_.set_ssl_config_service(
-        std::make_unique<SSLConfigServiceDefaults>());
-    storage_.set_http_server_properties(
-        std::make_unique<HttpServerProperties>());
-    storage_.set_quic_context(std::make_unique<QuicContext>());
-
-    HttpNetworkSessionContext session_context;
-    session_context.host_resolver = host_resolver();
-    session_context.cert_verifier = cert_verifier();
-    session_context.transport_security_state = transport_security_state();
-    session_context.ct_policy_enforcer = ct_policy_enforcer();
-    session_context.proxy_resolution_service = proxy_resolution_service();
-    session_context.ssl_config_service = ssl_config_service();
-    session_context.http_server_properties = http_server_properties();
-    session_context.quic_context = quic_context();
-    storage_.set_http_network_session(std::make_unique<HttpNetworkSession>(
-        HttpNetworkSessionParams(), session_context));
-    storage_.set_http_transaction_factory(std::make_unique<HttpCache>(
-        storage_.http_network_session(), HttpCache::DefaultBackend::InMemory(0),
-        false));
-    storage_.set_job_factory(std::make_unique<URLRequestJobFactory>());
-  }
-
-  ~RequestContext() override { AssertNoURLRequests(); }
-
- private:
-  URLRequestContextStorage storage_;
-};
-
 // Get a file:// url relative to net/data/proxy/pac_file_fetcher_unittest.
 GURL GetTestFileUrl(const std::string& relpath) {
   base::FilePath path;
@@ -156,17 +111,21 @@
  public:
   PacFileFetcherImplTest() {
     test_server_.AddDefaultHandlers(base::FilePath(kDocRoot));
-    context_.set_network_delegate(&network_delegate_);
+    auto builder = CreateTestURLRequestContextBuilder();
+    network_delegate_ =
+        builder->set_network_delegate(std::make_unique<BasicNetworkDelegate>());
+    context_ = builder->Build();
   }
 
  protected:
   EmbeddedTestServer test_server_;
-  BasicNetworkDelegate network_delegate_;
-  RequestContext context_;
+  std::unique_ptr<URLRequestContext> context_;
+  // Owned by `context_`.
+  raw_ptr<BasicNetworkDelegate> network_delegate_;
 };
 
 TEST_F(PacFileFetcherImplTest, FileUrlNotAllowed) {
-  auto pac_fetcher = PacFileFetcherImpl::Create(&context_);
+  auto pac_fetcher = PacFileFetcherImpl::Create(context_.get());
 
   // Fetch a file that exists, however the PacFileFetcherImpl does not allow use
   // of file://.
@@ -182,7 +141,7 @@
 TEST_F(PacFileFetcherImplTest, RedirectToFileUrl) {
   ASSERT_TRUE(test_server_.Start());
 
-  auto pac_fetcher = PacFileFetcherImpl::Create(&context_);
+  auto pac_fetcher = PacFileFetcherImpl::Create(context_.get());
 
   GURL url(test_server_.GetURL("/redirect-to-file"));
 
@@ -199,7 +158,7 @@
 TEST_F(PacFileFetcherImplTest, HttpMimeType) {
   ASSERT_TRUE(test_server_.Start());
 
-  auto pac_fetcher = PacFileFetcherImpl::Create(&context_);
+  auto pac_fetcher = PacFileFetcherImpl::Create(context_.get());
 
   {  // Fetch a PAC with mime type "text/plain"
     GURL url(test_server_.GetURL("/pac.txt"));
@@ -236,7 +195,7 @@
 TEST_F(PacFileFetcherImplTest, HttpStatusCode) {
   ASSERT_TRUE(test_server_.Start());
 
-  auto pac_fetcher = PacFileFetcherImpl::Create(&context_);
+  auto pac_fetcher = PacFileFetcherImpl::Create(context_.get());
 
   {  // Fetch a PAC which gives a 500 -- FAIL
     GURL url(test_server_.GetURL("/500.pac"));
@@ -265,7 +224,7 @@
 TEST_F(PacFileFetcherImplTest, ContentDisposition) {
   ASSERT_TRUE(test_server_.Start());
 
-  auto pac_fetcher = PacFileFetcherImpl::Create(&context_);
+  auto pac_fetcher = PacFileFetcherImpl::Create(context_.get());
 
   // Fetch PAC scripts via HTTP with a Content-Disposition header -- should
   // have no effect.
@@ -293,7 +252,7 @@
 
   ASSERT_TRUE(test_server_.Start());
 
-  auto pac_fetcher = PacFileFetcherImpl::Create(&context_);
+  auto pac_fetcher = PacFileFetcherImpl::Create(context_.get());
 
   GURL url(test_server_.GetURL(kHost, "/downloadable.pac"));
   std::u16string text;
@@ -308,7 +267,7 @@
   net::HostResolver::ResolveHostParameters params;
   params.source = net::HostResolverSource::LOCAL_ONLY;
   std::unique_ptr<net::HostResolver::ResolveHostRequest> host_request =
-      context_.host_resolver()->CreateRequest(
+      context_->host_resolver()->CreateRequest(
           url::SchemeHostPort(url),
           pac_fetcher->isolation_info().network_isolation_key(),
           net::NetLogWithSource(), params);
@@ -318,11 +277,11 @@
 
   // Make sure there are no other entries in the HostCache (which would
   // potentially be associated with other NetworkIsolationKeys).
-  EXPECT_EQ(1u, context_.host_resolver()->GetHostCache()->size());
+  EXPECT_EQ(1u, context_->host_resolver()->GetHostCache()->size());
 
   // Make sure the cache is actually returning different results based on
   // NetworkIsolationKey.
-  host_request = context_.host_resolver()->CreateRequest(
+  host_request = context_->host_resolver()->CreateRequest(
       url::SchemeHostPort(url), NetworkIsolationKey(), net::NetLogWithSource(),
       params);
   net::TestCompletionCallback callback3;
@@ -334,7 +293,7 @@
 TEST_F(PacFileFetcherImplTest, NoCache) {
   ASSERT_TRUE(test_server_.Start());
 
-  auto pac_fetcher = PacFileFetcherImpl::Create(&context_);
+  auto pac_fetcher = PacFileFetcherImpl::Create(context_.get());
 
   // Fetch a PAC script whose HTTP headers make it cacheable for 1 hour.
   GURL url(test_server_.GetURL("/cacheable_1hr.pac"));
@@ -369,7 +328,7 @@
 TEST_F(PacFileFetcherImplTest, TooLarge) {
   ASSERT_TRUE(test_server_.Start());
 
-  auto pac_fetcher = PacFileFetcherImpl::Create(&context_);
+  auto pac_fetcher = PacFileFetcherImpl::Create(context_.get());
 
   {
     // Set the maximum response size to 50 bytes.
@@ -407,7 +366,7 @@
 TEST_F(PacFileFetcherImplTest, Empty) {
   ASSERT_TRUE(test_server_.Start());
 
-  auto pac_fetcher = PacFileFetcherImpl::Create(&context_);
+  auto pac_fetcher = PacFileFetcherImpl::Create(context_.get());
 
   GURL url(test_server_.GetURL("/empty"));
   std::u16string text;
@@ -422,7 +381,7 @@
 TEST_F(PacFileFetcherImplTest, Hang) {
   ASSERT_TRUE(test_server_.Start());
 
-  auto pac_fetcher = PacFileFetcherImpl::Create(&context_);
+  auto pac_fetcher = PacFileFetcherImpl::Create(context_.get());
 
   // Set the timeout period to 0.5 seconds.
   base::TimeDelta prev_timeout =
@@ -462,7 +421,7 @@
 TEST_F(PacFileFetcherImplTest, Encodings) {
   ASSERT_TRUE(test_server_.Start());
 
-  auto pac_fetcher = PacFileFetcherImpl::Create(&context_);
+  auto pac_fetcher = PacFileFetcherImpl::Create(context_.get());
 
   // Test a response that is gzip-encoded -- should get inflated.
   {
@@ -503,7 +462,7 @@
 }
 
 TEST_F(PacFileFetcherImplTest, DataURLs) {
-  auto pac_fetcher = PacFileFetcherImpl::Create(&context_);
+  auto pac_fetcher = PacFileFetcherImpl::Create(context_.get());
 
   const char kEncodedUrl[] =
       "data:application/x-ns-proxy-autoconfig;base64,ZnVuY3Rpb24gRmluZFByb3h5R"
@@ -560,7 +519,7 @@
   TestCompletionCallback callback;
   std::u16string text;
   for (int i = 0; i < num_requests; i++) {
-    auto pac_fetcher = PacFileFetcherImpl::Create(&context_);
+    auto pac_fetcher = PacFileFetcherImpl::Create(context_.get());
     GURL url(test_server_.GetURL("/hung"));
     // Fine to use the same string and callback for all of these, as they should
     // all hang.
@@ -582,22 +541,22 @@
 TEST_F(PacFileFetcherImplTest, OnShutdown) {
   ASSERT_TRUE(test_server_.Start());
 
-  auto pac_fetcher = PacFileFetcherImpl::Create(&context_);
+  auto pac_fetcher = PacFileFetcherImpl::Create(context_.get());
   std::u16string text;
   TestCompletionCallback callback;
   int result =
       pac_fetcher->Fetch(test_server_.GetURL("/hung"), &text,
                          callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS);
   EXPECT_THAT(result, IsError(ERR_IO_PENDING));
-  EXPECT_EQ(1u, context_.url_requests()->size());
+  EXPECT_EQ(1u, context_->url_requests()->size());
 
   pac_fetcher->OnShutdown();
-  EXPECT_EQ(0u, context_.url_requests()->size());
+  EXPECT_EQ(0u, context_->url_requests()->size());
   EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONTEXT_SHUT_DOWN));
 
   // Make sure there's no asynchronous completion notification.
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0u, context_.url_requests()->size());
+  EXPECT_EQ(0u, context_->url_requests()->size());
   EXPECT_FALSE(callback.have_result());
 
   result =
@@ -609,7 +568,7 @@
 TEST_F(PacFileFetcherImplTest, OnShutdownWithNoLiveRequest) {
   ASSERT_TRUE(test_server_.Start());
 
-  auto pac_fetcher = PacFileFetcherImpl::Create(&context_);
+  auto pac_fetcher = PacFileFetcherImpl::Create(context_.get());
   pac_fetcher->OnShutdown();
 
   std::u16string text;
@@ -618,7 +577,7 @@
       pac_fetcher->Fetch(test_server_.GetURL("/hung"), &text,
                          callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS);
   EXPECT_THAT(result, IsError(ERR_CONTEXT_SHUT_DOWN));
-  EXPECT_EQ(0u, context_.url_requests()->size());
+  EXPECT_EQ(0u, context_->url_requests()->size());
 }
 
 }  // namespace
diff --git a/net/quic/quic_end_to_end_unittest.cc b/net/quic/quic_end_to_end_unittest.cc
index c0906c06..a5420340 100644
--- a/net/quic/quic_end_to_end_unittest.cc
+++ b/net/quic/quic_end_to_end_unittest.cc
@@ -31,6 +31,7 @@
 #include "net/log/net_log_with_source.h"
 #include "net/proxy_resolution/configured_proxy_resolution_service.h"
 #include "net/quic/quic_context.h"
+#include "net/socket/client_socket_factory.h"
 #include "net/ssl/ssl_config_service_defaults.h"
 #include "net/test/cert_test_util.h"
 #include "net/test/gtest_util.h"
@@ -101,6 +102,8 @@
 
     session_params_.enable_quic = true;
 
+    session_context_.client_socket_factory =
+        ClientSocketFactory::GetDefaultFactory();
     session_context_.quic_context = &quic_context_;
     session_context_.host_resolver = &host_resolver_;
     session_context_.cert_verifier = &cert_verifier_;
diff --git a/net/test/cert_builder.cc b/net/test/cert_builder.cc
index eb598fe..b0ffef3 100644
--- a/net/test/cert_builder.cc
+++ b/net/test/cert_builder.cc
@@ -337,6 +337,11 @@
   Invalidate();
 }
 
+void CertBuilder::SetSubject(base::span<const uint8_t> subject_tlv) {
+  subject_tlv_.assign(subject_tlv.begin(), subject_tlv.end());
+  Invalidate();
+}
+
 void CertBuilder::SetSubjectAltName(const std::string& dns_name) {
   SetSubjectAltNames({dns_name}, {});
 }
diff --git a/net/test/cert_builder.h b/net/test/cert_builder.h
index 25bd6b9..56fe5fe 100644
--- a/net/test/cert_builder.h
+++ b/net/test/cert_builder.h
@@ -120,6 +120,9 @@
   // the value |common_name| tagged as a UTF8String.
   void SetSubjectCommonName(base::StringPiece common_name);
 
+  // Sets the subject to |subject_tlv|.
+  void SetSubject(base::span<const uint8_t> subject_tlv);
+
   // Sets the SAN for the certificate to a single dNSName.
   void SetSubjectAltName(const std::string& dns_name);
 
diff --git a/net/third_party/quiche/BUILD.gn b/net/third_party/quiche/BUILD.gn
index 5ec92f4..2c6bf8c 100644
--- a/net/third_party/quiche/BUILD.gn
+++ b/net/third_party/quiche/BUILD.gn
@@ -734,11 +734,11 @@
   source_set("epoll_quic_tools_core") {
     testonly = true
     sources = [
-      "overrides/quiche_platform_impl/quiche_stream_buffer_allocator_impl.h",
       "overrides/quiche_platform_impl/quiche_udp_socket_platform_impl.h",
       "src/common/platform/api/quiche_epoll.h",
       "src/common/platform/api/quiche_stream_buffer_allocator.h",
       "src/common/platform/api/quiche_udp_socket_platform_api.h",
+      "src/common/platform/default/quiche_platform_impl/quiche_stream_buffer_allocator_impl.h",
       "src/quic/core/quic_default_packet_writer.cc",
       "src/quic/core/quic_default_packet_writer.h",
       "src/quic/core/quic_epoll_alarm_factory.cc",
@@ -943,7 +943,6 @@
     "src/quic/core/quic_trace_visitor.h",
     "src/quic/platform/api/quic_expect_bug.h",
     "src/quic/platform/api/quic_mock_log.h",
-    "src/quic/platform/api/quic_port_utils.h",
     "src/quic/platform/api/quic_test.h",
     "src/quic/platform/api/quic_test_loopback.h",
     "src/quic/platform/api/quic_test_output.h",
diff --git a/net/third_party/quiche/overrides/quiche_platform_impl/quiche_stream_buffer_allocator_impl.h b/net/third_party/quiche/overrides/quiche_platform_impl/quiche_stream_buffer_allocator_impl.h
deleted file mode 100644
index c3ea706..0000000
--- a/net/third_party/quiche/overrides/quiche_platform_impl/quiche_stream_buffer_allocator_impl.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_STREAM_BUFFER_ALLOCATOR_IMPL_H_
-#define NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_STREAM_BUFFER_ALLOCATOR_IMPL_H_
-
-#include "net/third_party/quiche/src/common/simple_buffer_allocator.h"
-
-namespace quiche {
-
-using QuicheStreamBufferAllocatorImpl = quiche::SimpleBufferAllocator;
-
-}  // namespace quiche
-
-#endif  // NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_STREAM_BUFFER_ALLOCATOR_IMPL_H_
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index 34bec81..2152c9d 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -135,7 +135,11 @@
 void URLRequestContextBuilder::SetHttpNetworkSessionComponents(
     const URLRequestContext* request_context,
     HttpNetworkSessionContext* session_context,
-    bool suppress_setting_socket_performance_watcher_factory) {
+    bool suppress_setting_socket_performance_watcher_factory,
+    ClientSocketFactory* client_socket_factory) {
+  session_context->client_socket_factory =
+      client_socket_factory ? client_socket_factory
+                            : ClientSocketFactory::GetDefaultFactory();
   session_context->host_resolver = request_context->host_resolver();
   session_context->cert_verifier = request_context->cert_verifier();
   session_context->transport_security_state =
@@ -553,12 +557,12 @@
   }
 
   HttpNetworkSessionContext network_session_context;
-  SetHttpNetworkSessionComponents(
-      context.get(), &network_session_context,
-      suppress_setting_socket_performance_watcher_factory_for_testing_);
   // Unlike the other fields of HttpNetworkSession::Context,
   // |client_socket_factory| is not mirrored in URLRequestContext.
-  network_session_context.client_socket_factory = client_socket_factory_;
+  SetHttpNetworkSessionComponents(
+      context.get(), &network_session_context,
+      suppress_setting_socket_performance_watcher_factory_for_testing_,
+      client_socket_factory_);
 
   storage->set_http_network_session(std::make_unique<HttpNetworkSession>(
       http_network_session_params_, network_session_context));
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h
index 4b002f96..7b8a4b9 100644
--- a/net/url_request/url_request_context_builder.h
+++ b/net/url_request/url_request_context_builder.h
@@ -153,7 +153,8 @@
   static void SetHttpNetworkSessionComponents(
       const URLRequestContext* request_context,
       HttpNetworkSessionContext* session_context,
-      bool suppress_setting_socket_performance_watcher_factory = false);
+      bool suppress_setting_socket_performance_watcher_factory = false,
+      ClientSocketFactory* client_socket_factory = nullptr);
 
   // These functions are mutually exclusive.  The ProxyConfigService, if
   // set, will be used to construct a ConfiguredProxyResolutionService.
diff --git a/net/url_request/url_request_quic_perftest.cc b/net/url_request/url_request_quic_perftest.cc
index 7ea9e6c..1f0dc15 100644
--- a/net/url_request/url_request_quic_perftest.cc
+++ b/net/url_request/url_request_quic_perftest.cc
@@ -120,7 +120,6 @@
                                               kOriginHost, tcp_server_->port());
     EXPECT_TRUE(host_resolver->AddRuleFromString(map_rule));
 
-    net::HttpNetworkSessionContext network_session_context;
     HttpNetworkSessionParams params;
     params.enable_quic = true;
     params.enable_user_alternate_protocol_ports = true;
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 36dcb4c..f256da8 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -10352,7 +10352,7 @@
   }
 }
 
-// Test that sessions aren't resumed across HttpNetworkSessions.
+// Test that sessions aren't resumed across URLRequestContexts.
 TEST_F(HTTPSRequestTest, SSLSessionCacheShardTest) {
   // Start a server.
   EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
@@ -10360,10 +10360,27 @@
   ASSERT_TRUE(test_server.Start());
   const auto url = test_server.GetURL("/");
 
+  // Connect to the server once. This will add an entry to the session cache.
+  {
+    TestDelegate d;
+    std::unique_ptr<URLRequest> r(default_context().CreateRequest(
+        url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
+
+    r->Start();
+    EXPECT_TRUE(r->is_pending());
+
+    d.RunUntilComplete();
+
+    EXPECT_EQ(1, d.response_started_count());
+    EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, r->ssl_info().handshake_type);
+  }
+
+  // Clear the socket pools and connect again. This should resume the previous
+  // session.
   default_context()
       .http_transaction_factory()
       ->GetSession()
-      ->ClearSSLSessionCache();
+      ->CloseAllConnections(ERR_FAILED, /*net_log_reason_utf8=*/"");
 
   {
     TestDelegate d;
@@ -10376,35 +10393,16 @@
     d.RunUntilComplete();
 
     EXPECT_EQ(1, d.response_started_count());
+    EXPECT_EQ(SSLInfo::HANDSHAKE_RESUME, r->ssl_info().handshake_type);
   }
 
-  // Now create a new HttpNetworkSession.
-  HttpNetworkSessionContext session_context;
-  session_context.host_resolver = default_context().host_resolver();
-  session_context.cert_verifier = default_context().cert_verifier();
-  session_context.transport_security_state =
-      default_context().transport_security_state();
-  session_context.ct_policy_enforcer = default_context().ct_policy_enforcer();
-  session_context.proxy_resolution_service =
-      default_context().proxy_resolution_service();
-  session_context.ssl_config_service = default_context().ssl_config_service();
-  session_context.http_auth_handler_factory =
-      default_context().http_auth_handler_factory();
-  session_context.http_server_properties =
-      default_context().http_server_properties();
-  session_context.quic_context = default_context().quic_context();
-
-  HttpNetworkSession network_session(HttpNetworkSessionParams(),
-                                     session_context);
-  std::unique_ptr<HttpCache> cache(
-      new HttpCache(&network_session, HttpCache::DefaultBackend::InMemory(0),
-                    false /* is_main_cache */));
-
-  default_context().set_http_transaction_factory(cache.get());
+  // Now fetch on a new URLRequestContext. This should not resume the session.
+  auto context_builder = CreateTestURLRequestContextBuilder();
+  auto other_context = context_builder->Build();
 
   {
     TestDelegate d;
-    std::unique_ptr<URLRequest> r(default_context().CreateRequest(
+    std::unique_ptr<URLRequest> r(other_context->CreateRequest(
         url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
 
     r->Start();
diff --git a/printing/OWNERS b/printing/OWNERS
index 97f12041..f5fff104 100644
--- a/printing/OWNERS
+++ b/printing/OWNERS
@@ -3,4 +3,3 @@
 rbpotter@chromium.org
 thestig@chromium.org
 
-per-file printing_context_android*=ctzsm@chromium.org
diff --git a/printing/android/OWNERS b/printing/android/OWNERS
deleted file mode 100644
index 395fd997..0000000
--- a/printing/android/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-ctzsm@chromium.org
diff --git a/printing/printing_context_win.cc b/printing/printing_context_win.cc
index 4f1fb12..d87ba259 100644
--- a/printing/printing_context_win.cc
+++ b/printing/printing_context_win.cc
@@ -80,14 +80,7 @@
     Delegate* delegate,
     bool skip_system_calls) {
   std::unique_ptr<PrintingContext> context;
-#if BUILDFLAG(ENABLE_PRINTING)
   context = std::make_unique<PrintingContextSystemDialogWin>(delegate);
-#else
-  // The code in printing/ is still built when the GN `enable_basic_printing`
-  // variable is set to false. Just return PrintingContextWin as a dummy
-  // context.
-  context = std::make_unique<PrintingContextWin>(delegate);
-#endif
 #if BUILDFLAG(ENABLE_OOP_PRINTING)
   if (skip_system_calls)
     context->set_skip_system_calls();
diff --git a/services/network/restricted_cookie_manager_unittest.cc b/services/network/restricted_cookie_manager_unittest.cc
index 9c94d92..6d37c6a 100644
--- a/services/network/restricted_cookie_manager_unittest.cc
+++ b/services/network/restricted_cookie_manager_unittest.cc
@@ -2140,11 +2140,19 @@
   const base::UnguessableToken kNonce = base::UnguessableToken::Create();
   const absl::optional<std::set<net::SchemefulSite>> kPartyContextEmpty =
       std::set<net::SchemefulSite>();
-  const net::IsolationInfo kIsolationInfo = net::IsolationInfo::Create(
+  const net::IsolationInfo kNoncedIsolationInfo = net::IsolationInfo::Create(
       net::IsolationInfo::RequestType::kMainFrame, kTopFrameOrigin,
       kTopFrameOrigin, kSiteForCookies, kPartyContextEmpty, &kNonce);
 
-  service_->OverrideIsolationInfoForTesting(kIsolationInfo);
+  const absl::optional<net::CookiePartitionKey> kNoncedPartitionKey =
+      net::CookiePartitionKey::FromNetworkIsolationKey(
+          net::NetworkIsolationKey(net::SchemefulSite(kTopFrameURL),
+                                   net::SchemefulSite(kTopFrameURL), &kNonce));
+
+  const net::IsolationInfo kUnnoncedIsolationInfo =
+      net::IsolationInfo::CreateForInternalRequest(kTopFrameOrigin);
+
+  service_->OverrideIsolationInfoForTesting(kNoncedIsolationInfo);
   EXPECT_TRUE(sync_service_->SetCanonicalCookie(
       *net::CanonicalCookie::Create(
           kCookieURL, "__Host-foo=bar; Secure; SameSite=None; Path=/;",
@@ -2161,12 +2169,107 @@
       /*partitioned_cookies_runtime_feature_enabled=*/true);
   ASSERT_EQ(1u, cookies.size());
   EXPECT_TRUE(cookies[0].IsPartitioned());
-  EXPECT_EQ(
-      cookies[0].PartitionKey().value(),
-      net::CookiePartitionKey::FromNetworkIsolationKey(
-          net::NetworkIsolationKey(net::SchemefulSite(kTopFrameURL),
-                                   net::SchemefulSite(kTopFrameURL), &kNonce)));
+  EXPECT_EQ(cookies[0].PartitionKey().value(), kNoncedPartitionKey);
   EXPECT_EQ("__Host-foo", cookies[0].Name());
+
+  {  // Test that an unnonced partition cannot see the cookies or observe
+     // changes to them.
+    service_->OverrideIsolationInfoForTesting(kUnnoncedIsolationInfo);
+
+    auto options = mojom::CookieManagerGetOptions::New();
+    options->name = "";
+    options->match_type = mojom::CookieMatchType::STARTS_WITH;
+
+    net::CookieList cookies = sync_service_->GetAllForUrl(
+        kCookieURL, kSiteForCookies, kTopFrameOrigin, std::move(options),
+        /*partitioned_cookies_runtime_feature_enabled=*/true);
+    ASSERT_EQ(0u, cookies.size());
+
+    auto listener = CreateCookieChangeListener(kCookieURL, kSiteForCookies,
+                                               kTopFrameOrigin);
+
+    service_->OverrideIsolationInfoForTesting(kNoncedIsolationInfo);
+    auto second_listener = CreateCookieChangeListener(
+        kCookieURL, kSiteForCookies, kTopFrameOrigin);
+
+    // Update partitioned cookie Max-Age: None -> 7200.
+    EXPECT_TRUE(SetCanonicalCookie(
+        *net::CanonicalCookie::Create(
+            kCookieURL,
+            "__Host-foo=bar; Secure; SameSite=None; Path=/; Max-Age=7200",
+            base::Time::Now(), absl::nullopt /* server_time */,
+            kNoncedPartitionKey),
+        "https", false /* can_modify_httponly */));
+
+    second_listener->WaitForChange();
+    ASSERT_THAT(listener->observed_changes(), testing::SizeIs(0));
+  }
+
+  {  // Test that the nonced partition cannot observe changes to the unnonced
+     // partition and unpartitioned cookies.
+    // Set an unpartitioned cookie.
+    service_->OverrideIsolationInfoForTesting(kUnnoncedIsolationInfo);
+    EXPECT_TRUE(SetCanonicalCookie(
+        *net::CanonicalCookie::Create(
+            kCookieURL,
+            "__Host-unpartitioned=123; Secure; SameSite=None; Path=/;",
+            base::Time::Now(), absl::nullopt /* server_time */, absl::nullopt),
+        "https", false /* can_modify_httponly */));
+    // Set a partitioned cookie in the unnonced partition.
+    EXPECT_TRUE(sync_service_->SetCanonicalCookie(
+        *net::CanonicalCookie::Create(
+            kCookieURL,
+            "__Host-bar=baz; Secure; SameSite=None; Path=/; Partitioned;",
+            base::Time::Now(), absl::nullopt /* server_time */,
+            net::CookiePartitionKey::FromScript()),
+        kCookieURL, kSiteForCookies, kTopFrameOrigin));
+
+    service_->OverrideIsolationInfoForTesting(kNoncedIsolationInfo);
+
+    auto options = mojom::CookieManagerGetOptions::New();
+    options->name = "";
+    options->match_type = mojom::CookieMatchType::STARTS_WITH;
+
+    // Should only be able to see the nonced partitioned cookie only.
+    net::CookieList cookies = sync_service_->GetAllForUrl(
+        kCookieURL, kSiteForCookies, kTopFrameOrigin, std::move(options),
+        /*partitioned_cookies_runtime_feature_enabled=*/true);
+    ASSERT_EQ(1u, cookies.size());
+    ASSERT_EQ("__Host-foo", cookies[0].Name());
+
+    // Create a listener in the nonced partition.
+    auto listener = CreateCookieChangeListener(kCookieURL, kSiteForCookies,
+                                               kTopFrameOrigin);
+
+    // Create a second listener in an unnonced partition.
+    service_->OverrideIsolationInfoForTesting(kUnnoncedIsolationInfo);
+    auto second_listener = CreateCookieChangeListener(
+        kCookieURL, kSiteForCookies, kTopFrameOrigin);
+
+    // Update unpartitioned cookie Max-Age: None -> 7200.
+    EXPECT_TRUE(SetCanonicalCookie(
+        *net::CanonicalCookie::Create(
+            kCookieURL,
+            "__Host-unpartitioned=123; Secure; SameSite=None; Path=/; "
+            "Max-Age=7200",
+            base::Time::Now(), absl::nullopt /* server_time */, absl::nullopt),
+        "https", false /* can_modify_httponly */));
+    // Test that the nonced partition cannot observe the change.
+    second_listener->WaitForChange();
+    ASSERT_THAT(listener->observed_changes(), testing::SizeIs(0));
+
+    // Update unnonced partitioned cookie Max-Age: None -> 7200.
+    EXPECT_TRUE(SetCanonicalCookie(
+        *net::CanonicalCookie::Create(
+            kCookieURL,
+            "__Host-bar=baz; Secure; SameSite=None; Path=/; Partitioned; "
+            "Max-Age=7200",
+            base::Time::Now(), absl::nullopt /* server_time */, absl::nullopt),
+        "https", false /* can_modify_httponly */));
+    // Test that the nonced partition cannot observe the change.
+    second_listener->WaitForChange();
+    ASSERT_THAT(listener->observed_changes(), testing::SizeIs(0));
+  }
 }
 
 TEST_P(PartitionedCookiesRestrictedCookieManagerTest, RuntimeEnabledFeature) {
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index c5a3dc66..5bf6966 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -9581,7 +9581,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M100",
-              "revision": "version:100.0.4896.56"
+              "revision": "version:100.0.4896.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -9719,90 +9719,6 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
-          "../../weblayer_instrumentation_test_M95/out/Release",
-          "--implementation-outdir",
-          ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--client-version=95",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android30.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "weblayer_skew_tests_with_client_from_95"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "weblayer_skew_tests_with_client_from_95",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.78"
-            },
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "generic_android30",
-              "path": ".android_emulator/generic_android30"
-            }
-          ],
-          "optional_dimensions": {
-            "60": [
-              {
-                "caches": "generic_android30"
-              }
-            ]
-          },
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
-        },
-        "test": "weblayer_skew_tests",
-        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests/"
-      },
-      {
-        "args": [
-          "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--test-runner-outdir",
-          ".",
-          "--client-outdir",
           "../../weblayer_instrumentation_test_M96/out/Release",
           "--implementation-outdir",
           ".",
@@ -9971,6 +9887,90 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
+          "../../weblayer_instrumentation_test_M98/out/Release",
+          "--implementation-outdir",
+          ".",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--client-version=98",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android30.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "weblayer_skew_tests_with_client_from_98"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "weblayer_skew_tests_with_client_from_98",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/testing/weblayer-x86",
+              "location": "weblayer_instrumentation_test_M98",
+              "revision": "version:98.0.4758.109"
+            },
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "machine_type": "n1-standard-4|e2-standard-4",
+              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "pool": "chromium.tests.avd"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "generic_android30",
+              "path": ".android_emulator/generic_android30"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "generic_android30"
+              }
+            ]
+          },
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "weblayer_skew_tests",
+        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests/"
+      },
+      {
+        "args": [
+          "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--test-runner-outdir",
+          ".",
+          "--client-outdir",
           "../../weblayer_instrumentation_test_M99/out/Release",
           "--implementation-outdir",
           ".",
@@ -10085,7 +10085,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M100",
-              "revision": "version:100.0.4896.56"
+              "revision": "version:100.0.4896.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -10225,90 +10225,6 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M95/out/Release",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--impl-version=95",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android30.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "weblayer_skew_tests_with_impl_from_95"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "weblayer_skew_tests_with_impl_from_95",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.78"
-            },
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "generic_android30",
-              "path": ".android_emulator/generic_android30"
-            }
-          ],
-          "optional_dimensions": {
-            "60": [
-              {
-                "caches": "generic_android30"
-              }
-            ]
-          },
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
-        },
-        "test": "weblayer_skew_tests",
-        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests/"
-      },
-      {
-        "args": [
-          "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
-          "--test-runner-outdir",
-          ".",
-          "--client-outdir",
-          ".",
-          "--implementation-outdir",
           "../../weblayer_instrumentation_test_M96/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
@@ -10477,6 +10393,90 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M98/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--impl-version=98",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android30.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "weblayer_skew_tests_with_impl_from_98"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "weblayer_skew_tests_with_impl_from_98",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/testing/weblayer-x86",
+              "location": "weblayer_instrumentation_test_M98",
+              "revision": "version:98.0.4758.109"
+            },
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "machine_type": "n1-standard-4|e2-standard-4",
+              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "pool": "chromium.tests.avd"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "generic_android30",
+              "path": ".android_emulator/generic_android30"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "generic_android30"
+              }
+            ]
+          },
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "weblayer_skew_tests",
+        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests/"
+      },
+      {
+        "args": [
+          "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--test-runner-outdir",
+          ".",
+          "--client-outdir",
+          ".",
+          "--implementation-outdir",
           "../../weblayer_instrumentation_test_M99/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 0c485fc8..ee310f3 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -44881,7 +44881,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M100",
-              "revision": "version:100.0.4896.56"
+              "revision": "version:100.0.4896.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -45019,90 +45019,6 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
-          "../../weblayer_instrumentation_test_M95/out/Release",
-          "--implementation-outdir",
-          ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--client-version=95",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android29.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "weblayer_skew_tests_with_client_from_95"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "weblayer_skew_tests_with_client_from_95",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.78"
-            },
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "generic_android29",
-              "path": ".android_emulator/generic_android29"
-            }
-          ],
-          "optional_dimensions": {
-            "60": [
-              {
-                "caches": "generic_android29"
-              }
-            ]
-          },
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
-        },
-        "test": "weblayer_skew_tests",
-        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests/"
-      },
-      {
-        "args": [
-          "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--test-runner-outdir",
-          ".",
-          "--client-outdir",
           "../../weblayer_instrumentation_test_M96/out/Release",
           "--implementation-outdir",
           ".",
@@ -45271,6 +45187,90 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
+          "../../weblayer_instrumentation_test_M98/out/Release",
+          "--implementation-outdir",
+          ".",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--client-version=98",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android29.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "weblayer_skew_tests_with_client_from_98"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "weblayer_skew_tests_with_client_from_98",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/testing/weblayer-x86",
+              "location": "weblayer_instrumentation_test_M98",
+              "revision": "version:98.0.4758.109"
+            },
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "machine_type": "n1-standard-4|e2-standard-4",
+              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "pool": "chromium.tests.avd"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "generic_android29",
+              "path": ".android_emulator/generic_android29"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "generic_android29"
+              }
+            ]
+          },
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "weblayer_skew_tests",
+        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests/"
+      },
+      {
+        "args": [
+          "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--test-runner-outdir",
+          ".",
+          "--client-outdir",
           "../../weblayer_instrumentation_test_M99/out/Release",
           "--implementation-outdir",
           ".",
@@ -45385,7 +45385,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M100",
-              "revision": "version:100.0.4896.56"
+              "revision": "version:100.0.4896.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -45525,90 +45525,6 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M95/out/Release",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--impl-version=95",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android29.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "weblayer_skew_tests_with_impl_from_95"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "weblayer_skew_tests_with_impl_from_95",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.78"
-            },
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "generic_android29",
-              "path": ".android_emulator/generic_android29"
-            }
-          ],
-          "optional_dimensions": {
-            "60": [
-              {
-                "caches": "generic_android29"
-              }
-            ]
-          },
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
-        },
-        "test": "weblayer_skew_tests",
-        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests/"
-      },
-      {
-        "args": [
-          "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
-          "--test-runner-outdir",
-          ".",
-          "--client-outdir",
-          ".",
-          "--implementation-outdir",
           "../../weblayer_instrumentation_test_M96/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
@@ -45777,6 +45693,90 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M98/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--impl-version=98",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android29.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "weblayer_skew_tests_with_impl_from_98"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "weblayer_skew_tests_with_impl_from_98",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/testing/weblayer-x86",
+              "location": "weblayer_instrumentation_test_M98",
+              "revision": "version:98.0.4758.109"
+            },
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "machine_type": "n1-standard-4|e2-standard-4",
+              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "pool": "chromium.tests.avd"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "generic_android29",
+              "path": ".android_emulator/generic_android29"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "generic_android29"
+              }
+            ]
+          },
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "weblayer_skew_tests",
+        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests/"
+      },
+      {
+        "args": [
+          "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--test-runner-outdir",
+          ".",
+          "--client-outdir",
+          ".",
+          "--implementation-outdir",
           "../../weblayer_instrumentation_test_M99/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
@@ -45893,7 +45893,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M100",
-              "revision": "version:100.0.4896.56"
+              "revision": "version:100.0.4896.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46031,90 +46031,6 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
-          "../../weblayer_instrumentation_test_M95/out/Release",
-          "--implementation-outdir",
-          ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--client-version=95",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "weblayer_skew_tests_with_chrome_with_client_from_95"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "weblayer_skew_tests_with_chrome_with_client_from_95",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.78"
-            },
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "generic_android23",
-              "path": ".android_emulator/generic_android23"
-            }
-          ],
-          "optional_dimensions": {
-            "60": [
-              {
-                "caches": "generic_android23"
-              }
-            ]
-          },
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
-        },
-        "test": "weblayer_skew_tests_with_chrome",
-        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests_with_chrome/"
-      },
-      {
-        "args": [
-          "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--test-runner-outdir",
-          ".",
-          "--client-outdir",
           "../../weblayer_instrumentation_test_M96/out/Release",
           "--implementation-outdir",
           ".",
@@ -46283,6 +46199,90 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
+          "../../weblayer_instrumentation_test_M98/out/Release",
+          "--implementation-outdir",
+          ".",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--client-version=98",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "weblayer_skew_tests_with_chrome_with_client_from_98"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "weblayer_skew_tests_with_chrome_with_client_from_98",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/testing/weblayer-x86",
+              "location": "weblayer_instrumentation_test_M98",
+              "revision": "version:98.0.4758.109"
+            },
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "machine_type": "n1-standard-4|e2-standard-4",
+              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "pool": "chromium.tests.avd"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "generic_android23",
+              "path": ".android_emulator/generic_android23"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "generic_android23"
+              }
+            ]
+          },
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "weblayer_skew_tests_with_chrome",
+        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests_with_chrome/"
+      },
+      {
+        "args": [
+          "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--test-runner-outdir",
+          ".",
+          "--client-outdir",
           "../../weblayer_instrumentation_test_M99/out/Release",
           "--implementation-outdir",
           ".",
@@ -46397,7 +46397,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M100",
-              "revision": "version:100.0.4896.56"
+              "revision": "version:100.0.4896.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46537,90 +46537,6 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M95/out/Release",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--impl-version=95",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "weblayer_skew_tests_with_chrome_with_impl_from_95"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "weblayer_skew_tests_with_chrome_with_impl_from_95",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.78"
-            },
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "generic_android23",
-              "path": ".android_emulator/generic_android23"
-            }
-          ],
-          "optional_dimensions": {
-            "60": [
-              {
-                "caches": "generic_android23"
-              }
-            ]
-          },
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
-        },
-        "test": "weblayer_skew_tests_with_chrome",
-        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests_with_chrome/"
-      },
-      {
-        "args": [
-          "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
-          "--test-runner-outdir",
-          ".",
-          "--client-outdir",
-          ".",
-          "--implementation-outdir",
           "../../weblayer_instrumentation_test_M96/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
@@ -46789,6 +46705,90 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M98/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--impl-version=98",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "weblayer_skew_tests_with_chrome_with_impl_from_98"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "weblayer_skew_tests_with_chrome_with_impl_from_98",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/testing/weblayer-x86",
+              "location": "weblayer_instrumentation_test_M98",
+              "revision": "version:98.0.4758.109"
+            },
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "machine_type": "n1-standard-4|e2-standard-4",
+              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "pool": "chromium.tests.avd"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "generic_android23",
+              "path": ".android_emulator/generic_android23"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "generic_android23"
+              }
+            ]
+          },
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "weblayer_skew_tests_with_chrome",
+        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests_with_chrome/"
+      },
+      {
+        "args": [
+          "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--test-runner-outdir",
+          ".",
+          "--client-outdir",
+          ".",
+          "--implementation-outdir",
           "../../weblayer_instrumentation_test_M99/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
@@ -46972,7 +46972,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M100",
-              "revision": "version:100.0.4896.56"
+              "revision": "version:100.0.4896.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47110,90 +47110,6 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
-          "../../weblayer_instrumentation_test_M95/out/Release",
-          "--implementation-outdir",
-          ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--client-version=95",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android27.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "weblayer_skew_tests_with_client_from_95"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "weblayer_skew_tests_with_client_from_95",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.78"
-            },
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "generic_android27",
-              "path": ".android_emulator/generic_android27"
-            }
-          ],
-          "optional_dimensions": {
-            "60": [
-              {
-                "caches": "generic_android27"
-              }
-            ]
-          },
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
-        },
-        "test": "weblayer_skew_tests",
-        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests/"
-      },
-      {
-        "args": [
-          "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--test-runner-outdir",
-          ".",
-          "--client-outdir",
           "../../weblayer_instrumentation_test_M96/out/Release",
           "--implementation-outdir",
           ".",
@@ -47362,6 +47278,90 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
+          "../../weblayer_instrumentation_test_M98/out/Release",
+          "--implementation-outdir",
+          ".",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--client-version=98",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android27.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "weblayer_skew_tests_with_client_from_98"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "weblayer_skew_tests_with_client_from_98",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/testing/weblayer-x86",
+              "location": "weblayer_instrumentation_test_M98",
+              "revision": "version:98.0.4758.109"
+            },
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "machine_type": "n1-standard-4|e2-standard-4",
+              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "pool": "chromium.tests.avd"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "generic_android27",
+              "path": ".android_emulator/generic_android27"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "generic_android27"
+              }
+            ]
+          },
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "weblayer_skew_tests",
+        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests/"
+      },
+      {
+        "args": [
+          "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--test-runner-outdir",
+          ".",
+          "--client-outdir",
           "../../weblayer_instrumentation_test_M99/out/Release",
           "--implementation-outdir",
           ".",
@@ -47476,7 +47476,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M100",
-              "revision": "version:100.0.4896.56"
+              "revision": "version:100.0.4896.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47616,90 +47616,6 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M95/out/Release",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--impl-version=95",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android27.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "weblayer_skew_tests_with_impl_from_95"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "weblayer_skew_tests_with_impl_from_95",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.78"
-            },
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "generic_android27",
-              "path": ".android_emulator/generic_android27"
-            }
-          ],
-          "optional_dimensions": {
-            "60": [
-              {
-                "caches": "generic_android27"
-              }
-            ]
-          },
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
-        },
-        "test": "weblayer_skew_tests",
-        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests/"
-      },
-      {
-        "args": [
-          "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--test-runner-outdir",
-          ".",
-          "--client-outdir",
-          ".",
-          "--implementation-outdir",
           "../../weblayer_instrumentation_test_M96/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
@@ -47868,6 +47784,90 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M98/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--impl-version=98",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android27.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "weblayer_skew_tests_with_impl_from_98"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "weblayer_skew_tests_with_impl_from_98",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/testing/weblayer-x86",
+              "location": "weblayer_instrumentation_test_M98",
+              "revision": "version:98.0.4758.109"
+            },
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "machine_type": "n1-standard-4|e2-standard-4",
+              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "pool": "chromium.tests.avd"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "generic_android27",
+              "path": ".android_emulator/generic_android27"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "generic_android27"
+              }
+            ]
+          },
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "weblayer_skew_tests",
+        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests/"
+      },
+      {
+        "args": [
+          "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--test-runner-outdir",
+          ".",
+          "--client-outdir",
+          ".",
+          "--implementation-outdir",
           "../../weblayer_instrumentation_test_M99/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
@@ -48051,7 +48051,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M100",
-              "revision": "version:100.0.4896.56"
+              "revision": "version:100.0.4896.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48189,90 +48189,6 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
-          "../../weblayer_instrumentation_test_M95/out/Release",
-          "--implementation-outdir",
-          ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--client-version=95",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android28.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "weblayer_skew_tests_with_client_from_95"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "weblayer_skew_tests_with_client_from_95",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.78"
-            },
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "generic_android28",
-              "path": ".android_emulator/generic_android28"
-            }
-          ],
-          "optional_dimensions": {
-            "60": [
-              {
-                "caches": "generic_android28"
-              }
-            ]
-          },
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
-        },
-        "test": "weblayer_skew_tests",
-        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests/"
-      },
-      {
-        "args": [
-          "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--test-runner-outdir",
-          ".",
-          "--client-outdir",
           "../../weblayer_instrumentation_test_M96/out/Release",
           "--implementation-outdir",
           ".",
@@ -48441,6 +48357,90 @@
           "--test-runner-outdir",
           ".",
           "--client-outdir",
+          "../../weblayer_instrumentation_test_M98/out/Release",
+          "--implementation-outdir",
+          ".",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--client-version=98",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android28.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "weblayer_skew_tests_with_client_from_98"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "weblayer_skew_tests_with_client_from_98",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/testing/weblayer-x86",
+              "location": "weblayer_instrumentation_test_M98",
+              "revision": "version:98.0.4758.109"
+            },
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "machine_type": "n1-standard-4|e2-standard-4",
+              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "pool": "chromium.tests.avd"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "generic_android28",
+              "path": ".android_emulator/generic_android28"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "generic_android28"
+              }
+            ]
+          },
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "weblayer_skew_tests",
+        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests/"
+      },
+      {
+        "args": [
+          "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--test-runner-outdir",
+          ".",
+          "--client-outdir",
           "../../weblayer_instrumentation_test_M99/out/Release",
           "--implementation-outdir",
           ".",
@@ -48555,7 +48555,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M100",
-              "revision": "version:100.0.4896.56"
+              "revision": "version:100.0.4896.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48695,90 +48695,6 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M95/out/Release",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--impl-version=95",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android28.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "weblayer_skew_tests_with_impl_from_95"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "weblayer_skew_tests_with_impl_from_95",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M95",
-              "revision": "version:95.0.4638.78"
-            },
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "generic_android28",
-              "path": ".android_emulator/generic_android28"
-            }
-          ],
-          "optional_dimensions": {
-            "60": [
-              {
-                "caches": "generic_android28"
-              }
-            ]
-          },
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
-        },
-        "test": "weblayer_skew_tests",
-        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests/"
-      },
-      {
-        "args": [
-          "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--test-runner-outdir",
-          ".",
-          "--client-outdir",
-          ".",
-          "--implementation-outdir",
           "../../weblayer_instrumentation_test_M96/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
@@ -48947,6 +48863,90 @@
           "--client-outdir",
           ".",
           "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M98/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--impl-version=98",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android28.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "weblayer_skew_tests_with_impl_from_98"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "weblayer_skew_tests_with_impl_from_98",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/testing/weblayer-x86",
+              "location": "weblayer_instrumentation_test_M98",
+              "revision": "version:98.0.4758.109"
+            },
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "machine_type": "n1-standard-4|e2-standard-4",
+              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "pool": "chromium.tests.avd"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "generic_android28",
+              "path": ".android_emulator/generic_android28"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "generic_android28"
+              }
+            ]
+          },
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "weblayer_skew_tests",
+        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_skew_tests/"
+      },
+      {
+        "args": [
+          "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--test-runner-outdir",
+          ".",
+          "--client-outdir",
+          ".",
+          "--implementation-outdir",
           "../../weblayer_instrumentation_test_M99/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 148c72e9..4e742f0 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -5795,7 +5795,7 @@
       },
       {
         "args": [
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4963.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4964.0/test_ash_chrome",
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter"
         ],
         "isolate_profile_data": true,
@@ -5803,14 +5803,14 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_Lacros version skew testing ash 102.0.4963.0",
+        "name": "lacros_chrome_browsertests_Lacros version skew testing ash 102.0.4964.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_v102.0.4963.0",
-              "revision": "version:102.0.4963.0"
+              "location": "lacros_version_skew_tests_v102.0.4964.0",
+              "revision": "version:102.0.4964.0"
             }
           ],
           "dimension_sets": [
@@ -5937,7 +5937,7 @@
       },
       {
         "args": [
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4963.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4964.0/test_ash_chrome",
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter"
         ],
         "isolate_profile_data": true,
@@ -5945,14 +5945,14 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 102.0.4963.0",
+        "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 102.0.4964.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_v102.0.4963.0",
-              "revision": "version:102.0.4963.0"
+              "location": "lacros_version_skew_tests_v102.0.4964.0",
+              "revision": "version:102.0.4964.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 006d68a..56ce16df6 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -85114,7 +85114,7 @@
       },
       {
         "args": [
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4963.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4964.0/test_ash_chrome",
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter"
         ],
         "isolate_profile_data": true,
@@ -85122,14 +85122,14 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_Lacros version skew testing ash 102.0.4963.0",
+        "name": "lacros_chrome_browsertests_Lacros version skew testing ash 102.0.4964.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_v102.0.4963.0",
-              "revision": "version:102.0.4963.0"
+              "location": "lacros_version_skew_tests_v102.0.4964.0",
+              "revision": "version:102.0.4964.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -85231,7 +85231,7 @@
       },
       {
         "args": [
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4963.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4964.0/test_ash_chrome",
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter"
         ],
         "isolate_profile_data": true,
@@ -85239,14 +85239,14 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 102.0.4963.0",
+        "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 102.0.4964.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_v102.0.4963.0",
-              "revision": "version:102.0.4963.0"
+              "location": "lacros_version_skew_tests_v102.0.4964.0",
+              "revision": "version:102.0.4964.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -86613,21 +86613,21 @@
       },
       {
         "args": [
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4963.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4964.0/test_ash_chrome",
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_Lacros version skew testing ash 102.0.4963.0",
+        "name": "lacros_chrome_browsertests_Lacros version skew testing ash 102.0.4964.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_v102.0.4963.0",
-              "revision": "version:102.0.4963.0"
+              "location": "lacros_version_skew_tests_v102.0.4964.0",
+              "revision": "version:102.0.4964.0"
             }
           ],
           "dimension_sets": [
@@ -86755,21 +86755,21 @@
       },
       {
         "args": [
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4963.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4964.0/test_ash_chrome",
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 102.0.4963.0",
+        "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 102.0.4964.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_v102.0.4963.0",
-              "revision": "version:102.0.4963.0"
+              "location": "lacros_version_skew_tests_v102.0.4964.0",
+              "revision": "version:102.0.4964.0"
             }
           ],
           "dimension_sets": [
@@ -88310,21 +88310,21 @@
       },
       {
         "args": [
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4963.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4964.0/test_ash_chrome",
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_Lacros version skew testing ash 102.0.4963.0",
+        "name": "lacros_chrome_browsertests_Lacros version skew testing ash 102.0.4964.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_v102.0.4963.0",
-              "revision": "version:102.0.4963.0"
+              "location": "lacros_version_skew_tests_v102.0.4964.0",
+              "revision": "version:102.0.4964.0"
             }
           ],
           "dimension_sets": [
@@ -88452,21 +88452,21 @@
       },
       {
         "args": [
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4963.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4964.0/test_ash_chrome",
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 102.0.4963.0",
+        "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 102.0.4964.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_v102.0.4963.0",
-              "revision": "version:102.0.4963.0"
+              "location": "lacros_version_skew_tests_v102.0.4964.0",
+              "revision": "version:102.0.4964.0"
             }
           ],
           "dimension_sets": [
@@ -89203,21 +89203,21 @@
       },
       {
         "args": [
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4963.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4964.0/test_ash_chrome",
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_Lacros version skew testing ash 102.0.4963.0",
+        "name": "lacros_chrome_browsertests_Lacros version skew testing ash 102.0.4964.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_v102.0.4963.0",
-              "revision": "version:102.0.4963.0"
+              "location": "lacros_version_skew_tests_v102.0.4964.0",
+              "revision": "version:102.0.4964.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -89299,21 +89299,21 @@
       },
       {
         "args": [
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4963.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4964.0/test_ash_chrome",
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 102.0.4963.0",
+        "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 102.0.4964.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_v102.0.4963.0",
-              "revision": "version:102.0.4963.0"
+              "location": "lacros_version_skew_tests_v102.0.4964.0",
+              "revision": "version:102.0.4964.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index 8e3e24c..865717c 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -34,7 +34,7 @@
           "dimension_sets": [
             {
               "cpu": "x86",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
@@ -63,7 +63,7 @@
           "dimension_sets": [
             {
               "cpu": "x86",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
@@ -92,7 +92,7 @@
           "dimension_sets": [
             {
               "cpu": "x86",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
@@ -121,7 +121,7 @@
           "dimension_sets": [
             {
               "cpu": "x86",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
@@ -150,7 +150,7 @@
           "dimension_sets": [
             {
               "cpu": "x86",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
@@ -179,7 +179,7 @@
           "dimension_sets": [
             {
               "cpu": "x86",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
@@ -208,7 +208,7 @@
           "dimension_sets": [
             {
               "cpu": "x86",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
@@ -733,7 +733,7 @@
           "dimension_sets": [
             {
               "cpu": "x86",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
@@ -762,7 +762,7 @@
           "dimension_sets": [
             {
               "cpu": "x86",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
@@ -791,7 +791,7 @@
           "dimension_sets": [
             {
               "cpu": "x86",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
@@ -820,7 +820,7 @@
           "dimension_sets": [
             {
               "cpu": "x86",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
@@ -849,7 +849,7 @@
           "dimension_sets": [
             {
               "cpu": "x86",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
@@ -878,7 +878,7 @@
           "dimension_sets": [
             {
               "cpu": "x86",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
@@ -907,7 +907,7 @@
           "dimension_sets": [
             {
               "cpu": "x86",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
@@ -936,7 +936,7 @@
           "dimension_sets": [
             {
               "cpu": "x86",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
@@ -972,7 +972,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
@@ -1009,7 +1009,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
@@ -1096,7 +1096,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Ubuntu-16.04",
+              "os": "Ubuntu-18.04",
               "pool": "chrome.tests"
             }
           ],
diff --git a/testing/buildbot/filters/pixel_browser_tests.filter b/testing/buildbot/filters/pixel_browser_tests.filter
index bcb89d1..3a5f54c 100644
--- a/testing/buildbot/filters/pixel_browser_tests.filter
+++ b/testing/buildbot/filters/pixel_browser_tests.filter
@@ -35,7 +35,6 @@
 PasswordReuseModalWarningTest.*

 PermissionRequestChipDialogBrowserTest.*

 *PermissionPromptBubbleViewBrowserTest.*

-PrivacySandboxDialogViewBrowserTest.*

 PromptForScanningModalDialogTest.*

 QRCodeGeneratorBubbleBrowserTest.*

 RelaunchRecommendedBubbleViewDialogTest.*

diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 3f6590a..4a39a8d2 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -28,16 +28,16 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4963.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v102.0.4964.0/test_ash_chrome',
       '--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter',
     ],
-    'identifier': 'Lacros version skew testing ash 102.0.4963.0',
+    'identifier': 'Lacros version skew testing ash 102.0.4964.0',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v102.0.4963.0',
-          'revision': 'version:102.0.4963.0',
+          'location': 'lacros_version_skew_tests_v102.0.4964.0',
+          'revision': 'version:102.0.4964.0',
         },
       ],
     },
@@ -483,7 +483,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M100',
-          'revision': 'version:100.0.4896.56',
+          'revision': 'version:100.0.4896.58',
         }
       ],
     },
@@ -520,6 +520,30 @@
       '--client-outdir',
       '.',
       '--implementation-outdir',
+      '../../weblayer_instrumentation_test_M98/out/Release',
+      '--test-expectations',
+      '../../weblayer/browser/android/javatests/skew/expectations.txt',
+      '--impl-version=98',
+    ],
+    'identifier': 'with_impl_from_98',
+    'swarming': {
+      'cipd_packages': [
+        {
+          'cipd_package': 'chromium/testing/weblayer-x86',
+          'location': 'weblayer_instrumentation_test_M98',
+          'revision': 'version:98.0.4758.109',
+        }
+      ],
+    },
+  },
+  'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_FOUR_MILESTONE': {
+    'args': [
+      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
+      '--test-runner-outdir',
+      '.',
+      '--client-outdir',
+      '.',
+      '--implementation-outdir',
       '../../weblayer_instrumentation_test_M97/out/Release',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
@@ -536,7 +560,7 @@
       ],
     },
   },
-  'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_FOUR_MILESTONE': {
+  'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_FIVE_MILESTONE': {
     'args': [
       '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--test-runner-outdir',
@@ -560,30 +584,6 @@
       ],
     },
   },
-  'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_FIVE_MILESTONE': {
-    'args': [
-      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
-      '--test-runner-outdir',
-      '.',
-      '--client-outdir',
-      '.',
-      '--implementation-outdir',
-      '../../weblayer_instrumentation_test_M95/out/Release',
-      '--test-expectations',
-      '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--impl-version=95',
-    ],
-    'identifier': 'with_impl_from_95',
-    'swarming': {
-      'cipd_packages': [
-        {
-          'cipd_package': 'chromium/testing/weblayer-x86',
-          'location': 'weblayer_instrumentation_test_M95',
-          'revision': 'version:95.0.4638.78',
-        }
-      ],
-    },
-  },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
       '--webview-apk-path=apks/SystemWebView.apk',
@@ -627,7 +627,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M100',
-          'revision': 'version:100.0.4896.56',
+          'revision': 'version:100.0.4896.58',
         }
       ],
     },
@@ -664,6 +664,30 @@
       '--client-outdir',
       '.',
       '--implementation-outdir',
+      '../../weblayer_instrumentation_test_M98/out/Release',
+      '--test-expectations',
+      '../../weblayer/browser/android/javatests/skew/expectations.txt',
+      '--impl-version=98',
+    ],
+    'identifier': 'with_impl_from_98',
+    'swarming': {
+      'cipd_packages': [
+        {
+          'cipd_package': 'chromium/testing/weblayer-x86',
+          'location': 'weblayer_instrumentation_test_M98',
+          'revision': 'version:98.0.4758.109',
+        }
+      ],
+    },
+  },
+  'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_FOUR_MILESTONE': {
+    'args': [
+      '--webview-apk-path=apks/SystemWebView.apk',
+      '--test-runner-outdir',
+      '.',
+      '--client-outdir',
+      '.',
+      '--implementation-outdir',
       '../../weblayer_instrumentation_test_M97/out/Release',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
@@ -680,7 +704,7 @@
       ],
     },
   },
-  'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_FOUR_MILESTONE': {
+  'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_FIVE_MILESTONE': {
     'args': [
       '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
@@ -704,30 +728,6 @@
       ],
     },
   },
-  'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_FIVE_MILESTONE': {
-    'args': [
-      '--webview-apk-path=apks/SystemWebView.apk',
-      '--test-runner-outdir',
-      '.',
-      '--client-outdir',
-      '.',
-      '--implementation-outdir',
-      '../../weblayer_instrumentation_test_M95/out/Release',
-      '--test-expectations',
-      '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--impl-version=95',
-    ],
-    'identifier': 'with_impl_from_95',
-    'swarming': {
-      'cipd_packages': [
-        {
-          'cipd_package': 'chromium/testing/weblayer-x86',
-          'location': 'weblayer_instrumentation_test_M95',
-          'revision': 'version:95.0.4638.78',
-        }
-      ],
-    },
-  },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
       '--webview-apk-path=apks/SystemWebView.apk',
@@ -771,7 +771,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M100',
-          'revision': 'version:100.0.4896.56',
+          'revision': 'version:100.0.4896.58',
         }
       ],
     },
@@ -806,6 +806,30 @@
       '--test-runner-outdir',
       '.',
       '--client-outdir',
+      '../../weblayer_instrumentation_test_M98/out/Release',
+      '--implementation-outdir',
+      '.',
+      '--test-expectations',
+      '../../weblayer/browser/android/javatests/skew/expectations.txt',
+      '--client-version=98',
+    ],
+    'identifier': 'with_client_from_98',
+    'swarming': {
+      'cipd_packages': [
+        {
+          'cipd_package': 'chromium/testing/weblayer-x86',
+          'location': 'weblayer_instrumentation_test_M98',
+          'revision': 'version:98.0.4758.109',
+        }
+      ],
+    },
+  },
+  'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_FOUR_MILESTONE': {
+    'args': [
+      '--webview-apk-path=apks/SystemWebView.apk',
+      '--test-runner-outdir',
+      '.',
+      '--client-outdir',
       '../../weblayer_instrumentation_test_M97/out/Release',
       '--implementation-outdir',
       '.',
@@ -824,7 +848,7 @@
       ],
     },
   },
-  'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_FOUR_MILESTONE': {
+  'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_FIVE_MILESTONE': {
     'args': [
       '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
@@ -848,30 +872,6 @@
       ],
     },
   },
-  'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_FIVE_MILESTONE': {
-    'args': [
-      '--webview-apk-path=apks/SystemWebView.apk',
-      '--test-runner-outdir',
-      '.',
-      '--client-outdir',
-      '../../weblayer_instrumentation_test_M95/out/Release',
-      '--implementation-outdir',
-      '.',
-      '--test-expectations',
-      '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--client-version=95',
-    ],
-    'identifier': 'with_client_from_95',
-    'swarming': {
-      'cipd_packages': [
-        {
-          'cipd_package': 'chromium/testing/weblayer-x86',
-          'location': 'weblayer_instrumentation_test_M95',
-          'revision': 'version:95.0.4638.78',
-        }
-      ],
-    },
-  },
   'CROS_ATLAS_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'atlas',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 7f65f9a..2f87d1b 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -6245,25 +6245,6 @@
             ]
         }
     ],
-    "ServiceWorkerClientForegroundPriority": [
-        {
-            "platforms": [
-                "windows",
-                "mac",
-                "linux",
-                "chromeos",
-                "chromeos_lacros"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "ServiceWorkerClientForegroundPriority"
-                    ]
-                }
-            ]
-        }
-    ],
     "ServiceWorkerStorageControl": [
         {
             "platforms": [
@@ -7819,10 +7800,7 @@
             ],
             "experiments": [
                 {
-                    "name": "Enabled-20_20220325",
-                    "enable_features": [
-                        "WebRTC-Audio-AgcMinMicLevelExperiment"
-                    ]
+                    "name": "Enabled-20_20220325"
                 }
             ]
         }
@@ -7933,6 +7911,25 @@
             ]
         }
     ],
+    "WebRTC-TaskQueuePacer": [
+        {
+            "platforms": [
+                "windows",
+                "mac",
+                "chromeos",
+                "chromeos_lacros",
+                "linux",
+                "ios",
+                "android",
+                "android_weblayer"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled,holdback_window:5ms,holdback_packets:3,_1"
+                }
+            ]
+        }
+    ],
     "WebRTC-VP8ConferenceTemporalLayers": [
         {
             "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index fb2c40ed..4eb12ca2 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -1069,6 +1069,12 @@
     kBrowsingTopicsMaxNumberOfApiUsageContextEntriesToLoadPerEpoch{
         &kBrowsingTopics,
         "max_number_of_api_usage_context_entries_to_load_per_epoch", 100000};
+// The max number of API usage context domains allowed to be stored per page
+// load.
+const base::FeatureParam<int>
+    kBrowsingTopicsMaxNumberOfApiUsageContextDomainsToStorePerPageLoad{
+        &kBrowsingTopics,
+        "max_number_of_api_usage_context_domains_to_store_per_page_load", 30};
 // Encodes the configuration parameters above. Each version number should only
 // be mapped to one configuration set. In practice, this can be guaranteed by
 // always bumping up the version number whenever parameters are updated.
@@ -1079,6 +1085,13 @@
 const base::FeatureParam<int> kBrowsingTopicsTaxonomyVersion{
     &kBrowsingTopics, "taxonomy_version", 1};
 
+// If enabled, the check for whether the IP address is publicly routable will be
+// bypassed when determining the eligibility for a page to be included in topics
+// calculation. This is useful for developers to test in local environment.
+const base::Feature kBrowsingTopicsBypassIPIsPubliclyRoutableCheck{
+    "BrowsingTopicsBypassIPIsPubliclyRoutableCheck",
+    base::FEATURE_DISABLED_BY_DEFAULT};
+
 // When <dialog>s are closed, this focuses the "previously focused" element
 // which had focus when the <dialog> was first opened.
 // TODO(crbug.com/649162): Remove DialogFocusNewSpecBehavior after
@@ -1361,10 +1374,20 @@
     "FreeNonRequiredTileResourcesForInactiveWindows",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Enables the WindowPlacement RuntimeEnabledFeature.
+// Enables basic Multi-Screen Window Placement functionality.
 const base::Feature kWindowPlacement{"WindowPlacement",
                                      base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Allows sites to request fullscreen and open a popup from a single gesture.
+const base::Feature kWindowPlacementFullscreenCompanionWindow{
+    "WindowPlacementFullscreenCompanionWindow",
+    base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Allows sites to request fullscreen when the set of screens change.
+const base::Feature kWindowPlacementFullscreenOnScreensChange{
+    "WindowPlacementFullscreenOnScreensChange",
+    base::FEATURE_DISABLED_BY_DEFAULT};
+
 // TODO(crbug.com/1277431): This flag should be eventually disabled.
 const base::Feature kEventPath{"EventPath", base::FEATURE_ENABLED_BY_DEFAULT};
 
@@ -1386,5 +1409,10 @@
 const base::Feature kWebSQLAccess{"kWebSQLAccess",
                                   base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Changes behavior of User-Agent Client Hints to send blank headers when the
+// User-Agent string is overridden, instead of disabling the headers altogether.
+const base::Feature kUACHOverrideBlank{"UACHOverrideBlank",
+                                       base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace features
 }  // namespace blink
diff --git a/third_party/blink/common/frame/transient_allow_fullscreen.cc b/third_party/blink/common/frame/transient_allow_fullscreen.cc
index 57f67d5..164c6407 100644
--- a/third_party/blink/common/frame/transient_allow_fullscreen.cc
+++ b/third_party/blink/common/frame/transient_allow_fullscreen.cc
@@ -6,9 +6,6 @@
 
 namespace blink {
 
-// static
-constexpr base::TimeDelta TransientAllowFullscreen::kActivationLifespan;
-
 TransientAllowFullscreen::TransientAllowFullscreen() = default;
 
 void TransientAllowFullscreen::Activate() {
diff --git a/third_party/blink/common/user_agent/user_agent_metadata.cc b/third_party/blink/common/user_agent/user_agent_metadata.cc
index e16a250..8d79e93 100644
--- a/third_party/blink/common/user_agent/user_agent_metadata.cc
+++ b/third_party/blink/common/user_agent/user_agent_metadata.cc
@@ -6,6 +6,7 @@
 
 #include "base/pickle.h"
 #include "net/http/structured_headers.h"
+#include "third_party/blink/public/common/features.h"
 
 namespace blink {
 
@@ -150,6 +151,20 @@
          a.mobile == b.mobile && a.bitness == b.bitness && a.wow64 == b.wow64;
 }
 
+// static
+UserAgentOverride UserAgentOverride::UserAgentOnly(const std::string& ua) {
+  UserAgentOverride result;
+  result.ua_string_override = ua;
+
+  // If ua is empty, it's assumed the system default should be used
+  if (!ua.empty() &&
+      base::FeatureList::IsEnabled(features::kUACHOverrideBlank)) {
+    result.ua_metadata_override = UserAgentMetadata();
+  }
+
+  return result;
+}
+
 bool operator==(const UserAgentOverride& a, const UserAgentOverride& b) {
   return a.ua_string_override == b.ua_string_override &&
          a.ua_metadata_override == b.ua_metadata_override;
diff --git a/third_party/blink/perf_tests/accessibility/build-table.html b/third_party/blink/perf_tests/accessibility/build-table.html
index aec805b..ee8ab5f 100644
--- a/third_party/blink/perf_tests/accessibility/build-table.html
+++ b/third_party/blink/perf_tests/accessibility/build-table.html
@@ -59,6 +59,7 @@
     iterationCount: 6,
     tracingCategories: 'accessibility',
     traceEventsToMeasure: [
+        'AXObjectCacheImpl::ChildrenChanged(LayoutObject)',
         'ProcessDeferredAccessibilityEvents'
     ]
 });
diff --git a/third_party/blink/perf_tests/accessibility/insert-block-child-after-many-inline-children.html b/third_party/blink/perf_tests/accessibility/insert-block-child-after-many-inline-children.html
index cb13a1d..80c0924 100644
--- a/third_party/blink/perf_tests/accessibility/insert-block-child-after-many-inline-children.html
+++ b/third_party/blink/perf_tests/accessibility/insert-block-child-after-many-inline-children.html
@@ -68,6 +68,7 @@
     iterationCount: 6,
     tracingCategories: 'accessibility',
     traceEventsToMeasure: [
+      'AXObjectCacheImpl::ChildrenChanged(LayoutObject)',
       'ProcessDeferredAccessibilityEvents',
       'RenderAccessibilityImpl::SendPendingAccessibilityEvents'
     ]
diff --git a/third_party/blink/perf_tests/accessibility/many-nodes-toggle-content-visibility-auto.html b/third_party/blink/perf_tests/accessibility/many-nodes-toggle-content-visibility-auto.html
index c64e0d0..4e83ffd 100644
--- a/third_party/blink/perf_tests/accessibility/many-nodes-toggle-content-visibility-auto.html
+++ b/third_party/blink/perf_tests/accessibility/many-nodes-toggle-content-visibility-auto.html
@@ -114,6 +114,7 @@
   iterationCount: 6,
   tracingCategories: 'accessibility',
   traceEventsToMeasure: [
+    'AXObjectCacheImpl::ChildrenChanged(LayoutObject)',
     'ProcessDeferredAccessibilityEvents',
     'RenderAccessibilityImpl::SendPendingAccessibilityEvents'
   ]
diff --git a/third_party/blink/perf_tests/accessibility/many-nodes-toggle-content-visibility-hidden.html b/third_party/blink/perf_tests/accessibility/many-nodes-toggle-content-visibility-hidden.html
index 4a98e820..0bd078f 100644
--- a/third_party/blink/perf_tests/accessibility/many-nodes-toggle-content-visibility-hidden.html
+++ b/third_party/blink/perf_tests/accessibility/many-nodes-toggle-content-visibility-hidden.html
@@ -104,6 +104,7 @@
   iterationCount: 6,
   tracingCategories: 'accessibility',
   traceEventsToMeasure: [
+    'AXObjectCacheImpl::ChildrenChanged(LayoutObject)',
     'ProcessDeferredAccessibilityEvents',
     'RenderAccessibilityImpl::SendPendingAccessibilityEvents'
   ]
diff --git a/third_party/blink/perf_tests/accessibility/many-nodes-toggle-display-none-in-focusable.html b/third_party/blink/perf_tests/accessibility/many-nodes-toggle-display-none-in-focusable.html
index f729580f..9a14e7aa 100644
--- a/third_party/blink/perf_tests/accessibility/many-nodes-toggle-display-none-in-focusable.html
+++ b/third_party/blink/perf_tests/accessibility/many-nodes-toggle-display-none-in-focusable.html
@@ -105,6 +105,7 @@
   iterationCount: 6,
   tracingCategories: 'accessibility',
   traceEventsToMeasure: [
+    'AXObjectCacheImpl::ChildrenChanged(LayoutObject)',
     'ProcessDeferredAccessibilityEvents',
     'RenderAccessibilityImpl::SendPendingAccessibilityEvents'
   ]
diff --git a/third_party/blink/perf_tests/accessibility/many-nodes-toggle-display-none.html b/third_party/blink/perf_tests/accessibility/many-nodes-toggle-display-none.html
index d774f25b8..a2103ad 100644
--- a/third_party/blink/perf_tests/accessibility/many-nodes-toggle-display-none.html
+++ b/third_party/blink/perf_tests/accessibility/many-nodes-toggle-display-none.html
@@ -103,6 +103,7 @@
   iterationCount: 6,
   tracingCategories: 'accessibility',
   traceEventsToMeasure: [
+    'AXObjectCacheImpl::ChildrenChanged(LayoutObject)',
     'ProcessDeferredAccessibilityEvents',
     'RenderAccessibilityImpl::SendPendingAccessibilityEvents'
   ]
diff --git a/third_party/blink/perf_tests/accessibility/many-text-changes-deep-block-subtree.html b/third_party/blink/perf_tests/accessibility/many-text-changes-deep-block-subtree.html
index 008664e..1543158 100644
--- a/third_party/blink/perf_tests/accessibility/many-text-changes-deep-block-subtree.html
+++ b/third_party/blink/perf_tests/accessibility/many-text-changes-deep-block-subtree.html
@@ -68,6 +68,8 @@
     iterationCount: 6,
     tracingCategories: 'accessibility',
     traceEventsToMeasure: [
+      // Measuring 'AXObjectCacheImpl::ChildrenChanged(LayoutObject)'
+      // can lead to this test timing out.
       'ProcessDeferredAccessibilityEvents',
       'RenderAccessibilityImpl::SendPendingAccessibilityEvents'
     ]
diff --git a/third_party/blink/perf_tests/accessibility/many-text-changes-deep-hidden-subtree.html b/third_party/blink/perf_tests/accessibility/many-text-changes-deep-hidden-subtree.html
index e101c10..403252b 100644
--- a/third_party/blink/perf_tests/accessibility/many-text-changes-deep-hidden-subtree.html
+++ b/third_party/blink/perf_tests/accessibility/many-text-changes-deep-hidden-subtree.html
@@ -68,6 +68,8 @@
     iterationCount: 6,
     tracingCategories: 'accessibility',
     traceEventsToMeasure: [
+      // Measuring 'AXObjectCacheImpl::ChildrenChanged(LayoutObject)'
+      // can lead to this test timing out.
       'ProcessDeferredAccessibilityEvents',
       'RenderAccessibilityImpl::SendPendingAccessibilityEvents'
     ]
diff --git a/third_party/blink/perf_tests/accessibility/many-text-changes-deep-inline-subtree.html b/third_party/blink/perf_tests/accessibility/many-text-changes-deep-inline-subtree.html
index 5158ec9..8c4b790 100644
--- a/third_party/blink/perf_tests/accessibility/many-text-changes-deep-inline-subtree.html
+++ b/third_party/blink/perf_tests/accessibility/many-text-changes-deep-inline-subtree.html
@@ -68,6 +68,8 @@
     iterationCount: 6,
     tracingCategories: 'accessibility',
     traceEventsToMeasure: [
+      // Measuring 'AXObjectCacheImpl::ChildrenChanged(LayoutObject)'
+      // can lead to this test timing out.
       'ProcessDeferredAccessibilityEvents',
       'RenderAccessibilityImpl::SendPendingAccessibilityEvents'
     ]
diff --git a/third_party/blink/perf_tests/accessibility/many-text-changes-small-wait-between.html b/third_party/blink/perf_tests/accessibility/many-text-changes-small-wait-between.html
index 99bb7916..bdaed4c 100644
--- a/third_party/blink/perf_tests/accessibility/many-text-changes-small-wait-between.html
+++ b/third_party/blink/perf_tests/accessibility/many-text-changes-small-wait-between.html
@@ -75,6 +75,8 @@
     iterationCount: 6,
     tracingCategories: 'accessibility',
     traceEventsToMeasure: [
+      // Measuring 'AXObjectCacheImpl::ChildrenChanged(LayoutObject)'
+      // can lead to this test timing out.
       'ProcessDeferredAccessibilityEvents',
       'RenderAccessibilityImpl::SendPendingAccessibilityEvents'
     ]
diff --git a/third_party/blink/perf_tests/accessibility/slot-updates.html b/third_party/blink/perf_tests/accessibility/slot-updates.html
index 99b2e10..a5f040c 100644
--- a/third_party/blink/perf_tests/accessibility/slot-updates.html
+++ b/third_party/blink/perf_tests/accessibility/slot-updates.html
@@ -136,6 +136,7 @@
       iterationCount: 6,
       tracingCategories: 'accessibility',
       traceEventsToMeasure: [
+        'AXObjectCacheImpl::ChildrenChanged(LayoutObject)',
         'ProcessDeferredAccessibilityEvents',
         'RenderAccessibilityImpl::SendPendingAccessibilityEvents'
       ]
diff --git a/third_party/blink/perf_tests/accessibility/unassignable-slots-deep-tree.html b/third_party/blink/perf_tests/accessibility/unassignable-slots-deep-tree.html
index cd15c3e..5825f23d 100644
--- a/third_party/blink/perf_tests/accessibility/unassignable-slots-deep-tree.html
+++ b/third_party/blink/perf_tests/accessibility/unassignable-slots-deep-tree.html
@@ -103,6 +103,7 @@
   iterationCount: 6,
   tracingCategories: 'accessibility',
   traceEventsToMeasure: [
+    'AXObjectCacheImpl::ChildrenChanged(LayoutObject)',
     'ProcessDeferredAccessibilityEvents',
     'RenderAccessibilityImpl::SendPendingAccessibilityEvents'
   ]
diff --git a/third_party/blink/perf_tests/accessibility/unassignable-slots-focusable-containers.html b/third_party/blink/perf_tests/accessibility/unassignable-slots-focusable-containers.html
index cbcff551..925e13ad 100644
--- a/third_party/blink/perf_tests/accessibility/unassignable-slots-focusable-containers.html
+++ b/third_party/blink/perf_tests/accessibility/unassignable-slots-focusable-containers.html
@@ -105,6 +105,7 @@
   iterationCount: 6,
   tracingCategories: 'accessibility',
   traceEventsToMeasure: [
+    'AXObjectCacheImpl::ChildrenChanged(LayoutObject)',
     'ProcessDeferredAccessibilityEvents',
     'RenderAccessibilityImpl::SendPendingAccessibilityEvents'
   ]
diff --git a/third_party/blink/perf_tests/accessibility/unassignable-slots-wide-tree.html b/third_party/blink/perf_tests/accessibility/unassignable-slots-wide-tree.html
index 780af1a2..cc758b3 100644
--- a/third_party/blink/perf_tests/accessibility/unassignable-slots-wide-tree.html
+++ b/third_party/blink/perf_tests/accessibility/unassignable-slots-wide-tree.html
@@ -109,6 +109,7 @@
   iterationCount: 6,
   tracingCategories: 'accessibility',
   traceEventsToMeasure: [
+    'AXObjectCacheImpl::ChildrenChanged(LayoutObject)',
     'ProcessDeferredAccessibilityEvents',
     'RenderAccessibilityImpl::SendPendingAccessibilityEvents'
   ]
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 8093cad..f0f8a9c2 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -478,9 +478,13 @@
 BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
     kBrowsingTopicsMaxNumberOfApiUsageContextEntriesToLoadPerEpoch;
 BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
+    kBrowsingTopicsMaxNumberOfApiUsageContextDomainsToStorePerPageLoad;
+BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
     kBrowsingTopicsConfigVersion;
 BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
     kBrowsingTopicsTaxonomyVersion;
+BLINK_COMMON_EXPORT extern const base::Feature
+    kBrowsingTopicsBypassIPIsPubliclyRoutableCheck;
 
 // When <dialog>s are closed, this focuses the "previously focused" element
 // which had focus when the <dialog> was first opened.
@@ -667,8 +671,12 @@
 BLINK_COMMON_EXPORT extern const base::Feature
     kFreeNonRequiredTileResourcesForInactiveWindows;
 
-// Enables the WindowPlacement RuntimeEnabledFeature.
+// Gates Multi-Screen Window Placement features and additional enhancements.
 BLINK_COMMON_EXPORT extern const base::Feature kWindowPlacement;
+BLINK_COMMON_EXPORT extern const base::Feature
+    kWindowPlacementFullscreenCompanionWindow;
+BLINK_COMMON_EXPORT extern const base::Feature
+    kWindowPlacementFullscreenOnScreensChange;
 
 // Gates the non-standard API Event.path to help its deprecation and removal.
 BLINK_COMMON_EXPORT extern const base::Feature kEventPath;
@@ -688,6 +696,8 @@
 
 BLINK_COMMON_EXPORT extern const base::Feature kWebSQLAccess;
 
+BLINK_COMMON_EXPORT extern const base::Feature kUACHOverrideBlank;
+
 }  // namespace features
 }  // namespace blink
 
diff --git a/third_party/blink/public/common/user_agent/user_agent_metadata.h b/third_party/blink/public/common/user_agent/user_agent_metadata.h
index 8b034dd..a5830a9 100644
--- a/third_party/blink/public/common/user_agent/user_agent_metadata.h
+++ b/third_party/blink/public/common/user_agent/user_agent_metadata.h
@@ -75,16 +75,7 @@
 // content/public/common/common_param_traits_macros.h
 struct BLINK_COMMON_EXPORT UserAgentOverride {
   // Helper which sets only UA with blank client hints.
-  static UserAgentOverride UserAgentOnly(const std::string& ua) {
-    UserAgentOverride result;
-    result.ua_string_override = ua;
-
-    // If ua is empty, it's assumed the system default should be used
-    if (!ua.empty())
-      result.ua_metadata_override = UserAgentMetadata();
-
-    return result;
-  }
+  static UserAgentOverride UserAgentOnly(const std::string& ua);
 
   // Empty |ua_string_override| means no override;
   // |ua_metadata_override| must also be null in that case.
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index 4152fe8..83d68e1 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -31,6 +31,7 @@
     "background_sync/background_sync.mojom",
     "badging/badging.mojom",
     "browser_interface_broker.mojom",
+    "browsing_topics/browsing_topics.mojom",
     "buckets/bucket_manager_host.mojom",
     "cache_storage/cache_storage.mojom",
     "choosers/color_chooser.mojom",
diff --git a/third_party/blink/public/mojom/browsing_topics/OWNERS b/third_party/blink/public/mojom/browsing_topics/OWNERS
new file mode 100644
index 0000000..08850f4
--- /dev/null
+++ b/third_party/blink/public/mojom/browsing_topics/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/mojom/browsing_topics/browsing_topics.mojom b/third_party/blink/public/mojom/browsing_topics/browsing_topics.mojom
new file mode 100644
index 0000000..b99c1fd
--- /dev/null
+++ b/third_party/blink/public/mojom/browsing_topics/browsing_topics.mojom
@@ -0,0 +1,40 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module blink.mojom;
+
+struct EpochTopic {
+  // A browsing topic from an epoch, calculated when requested from a context.
+  // It's always valid, as when there's no topic to give to a context, the
+  // `EpochTopic` won't be constructed.
+  int32 topic;
+
+  // The version that identifies the taxonomy and the algorithm used to
+  // calculate `topic`. This consists of `config_version`, `model_version`, and
+  // `taxonomy_version`.
+  string version;
+
+  // Version that identifies the configuration FeatureParams for the Topics API.
+  string config_version;
+
+  // Version of the model.
+  string model_version;
+
+  // Version of the taxonomy.
+  string taxonomy_version;
+};
+
+// The `BrowsingTopicsDocumentService` provides a method to request the
+// browsing topics. It is a per-document interface hosted in the browser
+// process.
+interface BrowsingTopicsDocumentService {
+
+  // Asynchronously get the browsing topics. Each topic is calculated for a
+  // particular epoch in the past. Epochs without a valid topic to give to the
+  // requesting context won't be returned - this could happen if the topics
+  // calculation for that epoch failed, or if the topics were later cleared, or
+  // if the candidate topic was filtered for the requesting context and epoch.
+  // Duplicate `EpochTopic`s are removed and their ordering is random.
+  GetBrowsingTopics() => (array<EpochTopic> browsing_topics);
+};
diff --git a/third_party/blink/public/mojom/use_counter/css_property_id.mojom b/third_party/blink/public/mojom/use_counter/css_property_id.mojom
index e79558d..ed1d1479 100644
--- a/third_party/blink/public/mojom/use_counter/css_property_id.mojom
+++ b/third_party/blink/public/mojom/use_counter/css_property_id.mojom
@@ -764,6 +764,7 @@
     kOverrideColors = 711,
     kPageTransitionTag = 712,
     kObjectViewBox = 713,
+    kObjectOverflow = 714,
     // 1. Add new features above this line (don't change the assigned numbers of
     //    the existing items).
     // 2. Run the src/tools/metrics/histograms/update_use_counter_css.py script
diff --git a/third_party/blink/renderer/core/css/css.dict b/third_party/blink/renderer/core/css/css.dict
index b222b51e..9e1e919 100644
--- a/third_party/blink/renderer/core/css/css.dict
+++ b/third_party/blink/renderer/core/css/css.dict
@@ -1228,6 +1228,7 @@
 "nav-up"
 "negative"
 "object-fit"
+"object-overflow"
 "object-view-box"
 "offset"
 "offset-after"
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5
index 479d10fe..05604b8 100644
--- a/third_party/blink/renderer/core/css/css_properties.json5
+++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -3131,6 +3131,17 @@
       getter: "GetObjectFit",
     },
     {
+      name: "object-overflow",
+      property_methods: ["CSSValueFromComputedStyleInternal"],
+      field_group: "*",
+      field_template: "keyword",
+      keywords: ["clip", "visible"],
+      typedom_types: ["Keyword"],
+      default_value: "clip",
+      getter: "GetObjectOverflow",
+      runtime_flag: "CSSObjectViewBoxAndOverflow",
+    },
+    {
       name: "object-position",
       property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
       interpolable: true,
diff --git a/third_party/blink/renderer/core/css/css_property_equality.cc b/third_party/blink/renderer/core/css/css_property_equality.cc
index 92c7563..d44380b4 100644
--- a/third_party/blink/renderer/core/css/css_property_equality.cc
+++ b/third_party/blink/renderer/core/css/css_property_equality.cc
@@ -203,6 +203,8 @@
       return a.MinHeight() == b.MinHeight();
     case CSSPropertyID::kMinWidth:
       return a.MinWidth() == b.MinWidth();
+    case CSSPropertyID::kObjectOverflow:
+      return a.GetObjectOverflow() == b.GetObjectOverflow();
     case CSSPropertyID::kObjectPosition:
       return a.ObjectPosition() == b.ObjectPosition();
     case CSSPropertyID::kObjectViewBox:
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
index a9c90f8..603f615 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
@@ -932,6 +932,8 @@
              value_id == CSSValueID::kContain ||
              value_id == CSSValueID::kCover || value_id == CSSValueID::kNone ||
              value_id == CSSValueID::kScaleDown;
+    case CSSPropertyID::kObjectOverflow:
+      return value_id == CSSValueID::kClip || value_id == CSSValueID::kVisible;
     case CSSPropertyID::kOutlineStyle:
       return value_id == CSSValueID::kAuto || value_id == CSSValueID::kNone ||
              (value_id >= CSSValueID::kInset &&
@@ -1311,6 +1313,7 @@
     case CSSPropertyID::kMathShift:
     case CSSPropertyID::kMathStyle:
     case CSSPropertyID::kObjectFit:
+    case CSSPropertyID::kObjectOverflow:
     case CSSPropertyID::kOutlineStyle:
     case CSSPropertyID::kOverflowAnchor:
     case CSSPropertyID::kOverflowBlock:
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
index 96d2774c..911f83e3 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -4919,6 +4919,13 @@
   return CSSIdentifierValue::Create(style.GetObjectFit());
 }
 
+const CSSValue* ObjectOverflow::CSSValueFromComputedStyleInternal(
+    const ComputedStyle& style,
+    const LayoutObject*,
+    bool allow_visited_style) const {
+  return CSSIdentifierValue::Create(style.GetObjectOverflow());
+}
+
 const CSSValue* ObjectPosition::ParseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
diff --git a/third_party/blink/renderer/core/dom/text.cc b/third_party/blink/renderer/core/dom/text.cc
index 4da5f8bf..89cf48e4 100644
--- a/third_party/blink/renderer/core/dom/text.cc
+++ b/third_party/blink/renderer/core/dom/text.cc
@@ -125,7 +125,7 @@
 
   if (GetLayoutObject()) {
     GetLayoutObject()->SetTextWithOffset(DataImpl(), 0, old_str.length());
-    if (data().IsEmpty()) {
+    if (ContainsOnlyWhitespaceOrEmpty()) {
       // To avoid |LayoutText| has empty text, we rebuild layout tree.
       SetForceReattachLayoutTree();
     }
diff --git a/third_party/blink/renderer/core/dom/tree_scope.cc b/third_party/blink/renderer/core/dom/tree_scope.cc
index 05d7aa2..81ffa04 100644
--- a/third_party/blink/renderer/core/dom/tree_scope.cc
+++ b/third_party/blink/renderer/core/dom/tree_scope.cc
@@ -54,6 +54,7 @@
 #include "third_party/blink/renderer/core/svg/svg_tree_scope_resources.h"
 #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "ui/gfx/geometry/point_conversions.h"
 
 namespace blink {
 
@@ -213,7 +214,7 @@
 // If the point is not in the viewport, returns false. Otherwise, adjusts the
 // point to account for the frame's zoom and scroll.
 static bool PointInFrameContentIfVisible(Document& document,
-                                         DoublePoint& point_in_frame) {
+                                         gfx::PointF& point_in_frame) {
   LocalFrame* frame = document.GetFrame();
   if (!frame)
     return false;
@@ -228,10 +229,10 @@
   gfx::Rect visible_frame_rect(scrollable_area->VisibleContentRect().size());
   visible_frame_rect =
       gfx::ScaleToRoundedRect(visible_frame_rect, 1 / frame->PageZoomFactor());
-  if (!visible_frame_rect.Contains(ToRoundedPoint(point_in_frame)))
+  if (!visible_frame_rect.Contains(gfx::ToRoundedPoint(point_in_frame)))
     return false;
 
-  point_in_frame.Scale(frame->PageZoomFactor(), frame->PageZoomFactor());
+  point_in_frame.Scale(frame->PageZoomFactor());
   return true;
 }
 
@@ -242,7 +243,7 @@
   if (!document->IsActive())
     return HitTestResult();
 
-  DoublePoint hit_point(x, y);
+  gfx::PointF hit_point(x, y);
   if (!PointInFrameContentIfVisible(*document, hit_point))
     return HitTestResult();
 
@@ -329,7 +330,7 @@
 HeapVector<Member<Element>> TreeScope::ElementsFromPoint(double x,
                                                          double y) const {
   Document& document = RootNode().GetDocument();
-  DoublePoint hit_point(x, y);
+  gfx::PointF hit_point(x, y);
   if (!PointInFrameContentIfVisible(document, hit_point))
     return HeapVector<Member<Element>>();
 
diff --git a/third_party/blink/renderer/core/frame/history.cc b/third_party/blink/renderer/core/frame/history.cc
index 313ec0dd..2964a26 100644
--- a/third_party/blink/renderer/core/frame/history.cc
+++ b/third_party/blink/renderer/core/frame/history.cc
@@ -184,27 +184,23 @@
     return;
   }
 
-  // TODO(crbug.com/1262022): Remove this condition when Fenced Frames
-  // transition to MPArch completely.
-  if (DomWindow()->GetFrame()->IsInFencedFrameTree()) {
+  LocalDOMWindow* active_window = LocalDOMWindow::From(script_state);
+  // TODO(crbug.com/1309481): Remove this CHECK, and the `script_state`
+  // parameter altogether.
+  CHECK_EQ(DomWindow(), active_window);
+  if (!DomWindow()->GetFrame()->IsNavigationAllowed())
     return;
-  }
 
   DCHECK(IsMainThread());
-  auto* active_window = LocalDOMWindow::From(script_state);
-  if (!active_window)
-    return;
-
-  if (!active_window->GetFrame() ||
-      !active_window->GetFrame()->CanNavigate(*DomWindow()->GetFrame()) ||
-      !active_window->GetFrame()->IsNavigationAllowed() ||
-      !DomWindow()->GetFrame()->IsNavigationAllowed()) {
-    return;
-  }
 
   if (!DomWindow()->GetFrame()->navigation_rate_limiter().CanProceed())
     return;
 
+  // TODO(crbug.com/1262022): Remove this condition when Fenced Frames
+  // transition to MPArch completely.
+  if (DomWindow()->GetFrame()->IsInFencedFrameTree())
+    return;
+
   if (delta) {
     if (DomWindow()->GetFrame()->Client()->NavigateBackForward(delta)) {
       if (Page* page = DomWindow()->GetFrame()->GetPage())
diff --git a/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.cc b/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.cc
index beb9ca2c..2399e4ca 100644
--- a/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.cc
+++ b/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.cc
@@ -111,7 +111,7 @@
   if (main_frame->View()->HasDominantVideoElement())
     return;
 
-  HitTestLocation location(DoublePoint(main_frame_size.width() / 2.0,
+  HitTestLocation location(gfx::PointF(main_frame_size.width() / 2.0,
                                        main_frame_size.height() / 2.0));
   HitTestResult result;
   main_frame->ContentLayoutObject()->HitTestNoLifecycleUpdate(location, result);
diff --git a/third_party/blink/renderer/core/frame/sticky_ad_detector.cc b/third_party/blink/renderer/core/frame/sticky_ad_detector.cc
index 3669616..8a3a071 100644
--- a/third_party/blink/renderer/core/frame/sticky_ad_detector.cc
+++ b/third_party/blink/renderer/core/frame/sticky_ad_detector.cc
@@ -80,7 +80,7 @@
   gfx::Size main_frame_size = main_frame->GetMainFrameViewportSize();
 
   // Hit test the bottom center of the viewport.
-  HitTestLocation location(DoublePoint(main_frame_size.width() / 2.0,
+  HitTestLocation location(gfx::PointF(main_frame_size.width() / 2.0,
                                        main_frame_size.height() * 9.0 / 10));
 
   HitTestResult result;
diff --git a/third_party/blink/renderer/core/fullscreen/fullscreen.cc b/third_party/blink/renderer/core/fullscreen/fullscreen.cc
index c1f2623..290ca746 100644
--- a/third_party/blink/renderer/core/fullscreen/fullscreen.cc
+++ b/third_party/blink/renderer/core/fullscreen/fullscreen.cc
@@ -328,7 +328,7 @@
 
   // The algorithm is triggered by another event with transient affordances,
   // e.g. permission-gated events for user-generated screens changes.
-  if (RuntimeEnabledFeatures::WindowPlacementV2Enabled(
+  if (RuntimeEnabledFeatures::WindowPlacementFullscreenOnScreensChangeEnabled(
           document.GetExecutionContext()) &&
       document.GetFrame()->IsTransientAllowFullscreenActive()) {
     UseCounter::Count(document, WebFeature::kFullscreenAllowedByScreensChange);
diff --git a/third_party/blink/renderer/core/layout/hit_test_location.cc b/third_party/blink/renderer/core/layout/hit_test_location.cc
index d80bf50..97d3e34 100644
--- a/third_party/blink/renderer/core/layout/hit_test_location.cc
+++ b/third_party/blink/renderer/core/layout/hit_test_location.cc
@@ -56,9 +56,6 @@
       is_rect_based_(false),
       is_rectilinear_(true) {}
 
-HitTestLocation::HitTestLocation(const DoublePoint& point)
-    : HitTestLocation(gfx::PointF(point)) {}
-
 HitTestLocation::HitTestLocation(const gfx::PointF& point,
                                  const gfx::QuadF& quad)
     : transformed_point_(point), transformed_rect_(quad), is_rect_based_(true) {
diff --git a/third_party/blink/renderer/core/layout/hit_test_location.h b/third_party/blink/renderer/core/layout/hit_test_location.h
index 8e8c217..1a2d108 100644
--- a/third_party/blink/renderer/core/layout/hit_test_location.h
+++ b/third_party/blink/renderer/core/layout/hit_test_location.h
@@ -49,7 +49,6 @@
   explicit HitTestLocation(const PhysicalOffset&);
   explicit HitTestLocation(const gfx::Point&);
   explicit HitTestLocation(const gfx::PointF&);
-  explicit HitTestLocation(const DoublePoint&);
   explicit HitTestLocation(const gfx::PointF&, const gfx::QuadF&);
   explicit HitTestLocation(const PhysicalRect&);
 
diff --git a/third_party/blink/renderer/core/script/dynamic_module_resolver.cc b/third_party/blink/renderer/core/script/dynamic_module_resolver.cc
index 1aada66..e7464084 100644
--- a/third_party/blink/renderer/core/script/dynamic_module_resolver.cc
+++ b/third_party/blink/renderer/core/script/dynamic_module_resolver.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_function.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
 #include "third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h"
 #include "third_party/blink/renderer/core/script/modulator.h"
 #include "third_party/blink/renderer/core/script/module_script.h"
diff --git a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5 b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
index beaac9c3..c194866 100644
--- a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
+++ b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
@@ -249,7 +249,7 @@
         fields_to_diff: ["-webkit-user-modify", "user-select", "image-rendering",
                 "column-rule-style", "column-rule-width", "column-rule-color",
                 "-internal-visited-column-rule-color",
-                "-webkit-user-drag", "object-fit", "object-position",
+                "-webkit-user-drag", "object-fit", "object-fit", "object-position", "object-view-box",
                 "mix-blend-mode", "isolation", "Mask", "MaskBoxImage", "mask", "mask-type",
                 "stop-color", "stop-opacity", "flood-color", "flood-opacity",
                 "lighting-color", "shape-rendering", "clip-rule", "fill-rule",
diff --git a/third_party/blink/renderer/core/workers/global_scope_creation_params.h b/third_party/blink/renderer/core/workers/global_scope_creation_params.h
index a311f49..6834e1f 100644
--- a/third_party/blink/renderer/core/workers/global_scope_creation_params.h
+++ b/third_party/blink/renderer/core/workers/global_scope_creation_params.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_GLOBAL_SCOPE_CREATION_PARAMS_H_
 
 #include <memory>
+
 #include "base/unguessable_token.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
@@ -26,7 +27,7 @@
 #include "third_party/blink/renderer/core/workers/worker_clients.h"
 #include "third_party/blink/renderer/core/workers/worker_settings.h"
 #include "third_party/blink/renderer/core/workers/worklet_module_responses_map.h"
-#include "third_party/blink/renderer/platform/graphics/begin_frame_provider.h"
+#include "third_party/blink/renderer/platform/graphics/begin_frame_provider_params.h"
 #include "third_party/blink/renderer/platform/loader/fetch/https_state.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.h b/third_party/blink/renderer/core/workers/worker_global_scope.h
index cba0945b8..9f6f46e 100644
--- a/third_party/blink/renderer/core/workers/worker_global_scope.h
+++ b/third_party/blink/renderer/core/workers/worker_global_scope.h
@@ -42,7 +42,6 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
 #include "third_party/blink/renderer/core/script/script.h"
-#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
 #include "third_party/blink/renderer/core/workers/worker_classic_script_loader.h"
 #include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
 #include "third_party/blink/renderer/core/workers/worker_settings.h"
@@ -59,6 +58,7 @@
 class FetchClientSettingsObjectSnapshot;
 class FontFaceSet;
 class FontMatchingMetrics;
+struct GlobalScopeCreationParams;
 class InstalledScriptsManager;
 class OffscreenFontSelector;
 class WorkerResourceTimingNotifier;
diff --git a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
index 0ef2156..ce37cda 100644
--- a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
+++ b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
@@ -26,6 +26,7 @@
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/core/inspector/inspector_audits_issue.h"
 #include "third_party/blink/renderer/core/loader/loader_factory_for_worker.h"
+#include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
 #include "third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h"
 #include "third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h"
 #include "third_party/blink/renderer/core/loader/subresource_filter.h"
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
index f2192581..ff57dece 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -4498,19 +4498,6 @@
     return true;
   }
 
-  // If this node is already the currently focused node, then calling
-  // focus() won't do anything.  That is a problem when focus is removed
-  // from the webpage to chrome, and then returns.  In these cases, we need
-  // to do what keyboard and mouse focus do, which is reset focus first.
-  if (document->FocusedElement() == element) {
-    document->ClearFocusedElement();
-
-    // Calling ClearFocusedElement could result in changes to the document,
-    // like this AXObject becoming detached.
-    if (IsDetached())
-      return false;
-  }
-
   // If the object is not natively focusable but can be focused using an ARIA
   // active descendant, perform a native click instead. This will enable Web
   // apps that set accessibility focus using an active descendant to capture and
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
index 0a44c5b..11a1a50 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -2166,6 +2166,8 @@
 }
 
 void AXObjectCacheImpl::ChildrenChanged(const LayoutObject* layout_object) {
+  TRACE_EVENT0("accessibility",
+               "AXObjectCacheImpl::ChildrenChanged(LayoutObject)");
   if (!layout_object)
     return;
 
diff --git a/third_party/blink/renderer/modules/browsing_topics/browsing_topics_document_supplement.cc b/third_party/blink/renderer/modules/browsing_topics/browsing_topics_document_supplement.cc
index 9d938d2..80f742e 100644
--- a/third_party/blink/renderer/modules/browsing_topics/browsing_topics_document_supplement.cc
+++ b/third_party/blink/renderer/modules/browsing_topics/browsing_topics_document_supplement.cc
@@ -14,6 +14,8 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_browsing_topic.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/page/page.h"
 
 namespace blink {
 
@@ -45,7 +47,8 @@
 
 BrowsingTopicsDocumentSupplement::BrowsingTopicsDocumentSupplement(
     Document& document)
-    : Supplement<Document>(document) {}
+    : Supplement<Document>(document),
+      document_host_(document.GetExecutionContext()) {}
 
 ScriptPromise BrowsingTopicsDocumentSupplement::GetBrowsingTopics(
     ScriptState* script_state,
@@ -68,6 +71,28 @@
       MakeGarbageCollected<ScriptPromiseResolver>(script_state);
   ScriptPromise promise = resolver->Promise();
 
+  // See https://github.com/jkarlin/topics#specific-details for the restrictions
+  // on the context.
+
+  if (document.GetExecutionContext()->GetSecurityOrigin()->IsOpaque()) {
+    resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
+        script_state->GetIsolate(), DOMExceptionCode::kInvalidAccessError,
+        "document.browsingTopics() is not allowed in an opaque origin "
+        "context."));
+
+    return promise;
+  }
+
+  if (!document.GetFrame()->GetPage()->MainFrame()->IsOutermostMainFrame() ||
+      document.GetFrame()->GetPage()->IsPrerendering()) {
+    resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
+        script_state->GetIsolate(), DOMExceptionCode::kInvalidAccessError,
+        "document.browsingTopics() is only allowed in the primary main frame "
+        "or in its child iframes."));
+
+    return promise;
+  }
+
   if (!document.GetExecutionContext()->IsFeatureEnabled(
           mojom::blink::PermissionsPolicyFeature::kBrowsingTopics)) {
     resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
@@ -89,11 +114,41 @@
     return promise;
   }
 
-  resolver->Resolve(HeapVector<Member<BrowsingTopic>>());
+  ExecutionContext* execution_context = ExecutionContext::From(script_state);
+  if (!document_host_.is_bound()) {
+    execution_context->GetBrowserInterfaceBroker().GetInterface(
+        document_host_.BindNewPipeAndPassReceiver(
+            execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
+  }
+
+  document_host_->GetBrowsingTopics(WTF::Bind(
+      [](ScriptPromiseResolver* resolver,
+         BrowsingTopicsDocumentSupplement* supplement,
+         Vector<mojom::blink::EpochTopicPtr> browsing_topics) {
+        DCHECK(resolver);
+        DCHECK(supplement);
+
+        HeapVector<Member<BrowsingTopic>> result;
+        for (const auto& topic : browsing_topics) {
+          BrowsingTopic* result_topic = BrowsingTopic::Create();
+          result_topic->setTopic(topic->topic);
+          result_topic->setVersion(topic->version);
+          result_topic->setConfigVersion(topic->config_version);
+          result_topic->setModelVersion(topic->model_version);
+          result_topic->setTaxonomyVersion(topic->taxonomy_version);
+          result.push_back(result_topic);
+        }
+
+        resolver->Resolve(result);
+      },
+      WrapPersistent(resolver), WrapPersistent(this)));
+
   return promise;
 }
 
 void BrowsingTopicsDocumentSupplement::Trace(Visitor* visitor) const {
+  visitor->Trace(document_host_);
+
   Supplement<Document>::Trace(visitor);
 }
 
diff --git a/third_party/blink/renderer/modules/browsing_topics/browsing_topics_document_supplement.h b/third_party/blink/renderer/modules/browsing_topics/browsing_topics_document_supplement.h
index 52317a16..e739736 100644
--- a/third_party/blink/renderer/modules/browsing_topics/browsing_topics_document_supplement.h
+++ b/third_party/blink/renderer/modules/browsing_topics/browsing_topics_document_supplement.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BROWSING_TOPICS_BROWSING_TOPICS_DOCUMENT_SUPPLEMENT_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_BROWSING_TOPICS_BROWSING_TOPICS_DOCUMENT_SUPPLEMENT_H_
 
+#include "third_party/blink/public/mojom/browsing_topics/browsing_topics.mojom-blink.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
@@ -36,6 +37,10 @@
 
   // GC functionality.
   void Trace(Visitor* visitor) const override;
+
+ private:
+  // Mojo remote used to query the browsing topics.
+  HeapMojoRemote<mojom::blink::BrowsingTopicsDocumentService> document_host_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 54c1f0b..c066b068 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -751,6 +751,7 @@
     "graphics/apply_viewport_changes.h",
     "graphics/begin_frame_provider.cc",
     "graphics/begin_frame_provider.h",
+    "graphics/begin_frame_provider_params.h",
     "graphics/bitmap_image.cc",
     "graphics/bitmap_image.h",
     "graphics/bitmap_image_metrics.cc",
diff --git a/third_party/blink/renderer/platform/audio/dynamics_compressor.cc b/third_party/blink/renderer/platform/audio/dynamics_compressor.cc
index 5f1ec1a1..e5838ba 100644
--- a/third_party/blink/renderer/platform/audio/dynamics_compressor.cc
+++ b/third_party/blink/renderer/platform/audio/dynamics_compressor.cc
@@ -54,6 +54,27 @@
 constexpr float kReleaseZone3 = 0.42f;
 constexpr float kReleaseZone4 = 0.98f;
 
+constexpr float kABase = 0.9999999999999998f * kReleaseZone1 +
+                         1.8432219684323923e-16f * kReleaseZone2 -
+                         1.9373394351676423e-16f * kReleaseZone3 +
+                         8.824516011816245e-18f * kReleaseZone4;
+constexpr float kBBase =
+    -1.5788320352845888f * kReleaseZone1 + 2.3305837032074286f * kReleaseZone2 -
+    0.9141194204840429f * kReleaseZone3 + 0.1623677525612032f * kReleaseZone4;
+constexpr float kCBase =
+    0.5334142869106424f * kReleaseZone1 - 1.272736789213631f * kReleaseZone2 +
+    0.9258856042207512f * kReleaseZone3 - 0.18656310191776226f * kReleaseZone4;
+constexpr float kDBase =
+    0.08783463138207234f * kReleaseZone1 - 0.1694162967925622f * kReleaseZone2 +
+    0.08588057951595272f * kReleaseZone3 - 0.00429891410546283f * kReleaseZone4;
+constexpr float kEBase = -0.042416883008123074f * kReleaseZone1 +
+                         0.1115693827987602f * kReleaseZone2 -
+                         0.09764676325265872f * kReleaseZone3 +
+                         0.028494263462021576f * kReleaseZone4;
+
+// Detector release time.
+constexpr float kSatReleaseTime = 0.0025f;
+
 // Returns x if x is finite (not NaN or infinite), otherwise returns
 // default_value
 float EnsureFinite(float x, float default_value) {
@@ -128,7 +149,7 @@
   const float db_threshold = ParameterValue(kParamThreshold);
   const float db_knee = ParameterValue(kParamKnee);
   const float ratio = ParameterValue(kParamRatio);
-  float attack_time = ParameterValue(kParamAttack);
+  const float attack_time = ParameterValue(kParamAttack);
   const float release_time = ParameterValue(kParamRelease);
 
   // Apply compression to the source signal.
@@ -141,49 +162,29 @@
 
   const float k = UpdateStaticCurveParameters(db_threshold, db_knee, ratio);
 
-  // Makeup gain.
-  const float full_range_gain = Saturate(1, k);
-  float full_range_makeup_gain = 1 / full_range_gain;
-
-  // Empirical/perceptual tuning.
-  full_range_makeup_gain = fdlibm::powf(full_range_makeup_gain, 0.6f);
-
-  const float linear_post_gain = full_range_makeup_gain;
+  // Makeup gain with empirical/perceptual tuning.
+  const float linear_post_gain = fdlibm::powf(1 / Saturate(1, k), 0.6f);
 
   // Attack parameters.
-  attack_time = std::max(0.001f, attack_time);
-  const float attack_frames = attack_time * sample_rate;
+  const float attack_frames = std::max(0.001f, attack_time) * sample_rate;
 
   // Release parameters.
   const float release_frames = sample_rate * release_time;
 
-  // Detector release time.
-  constexpr float sat_release_time = 0.0025f;
-  const float sat_release_frames = sat_release_time * sample_rate;
+  const float sat_release_frames = kSatReleaseTime * sample_rate;
 
   // Create a smooth function which passes through four points.
 
   // Polynomial of the form
   // y = a + b*x + c*x^2 + d*x^3 + e*x^4;
-
-  const float y1 = release_frames * kReleaseZone1;
-  const float y2 = release_frames * kReleaseZone2;
-  const float y3 = release_frames * kReleaseZone3;
-  const float y4 = release_frames * kReleaseZone4;
-
   // All of these coefficients were derived for 4th order polynomial curve
   // fitting where the y values match the evenly spaced x values as follows:
   // (y1 : x == 0, y2 : x == 1, y3 : x == 2, y4 : x == 3)
-  const float a = 0.9999999999999998f * y1 + 1.8432219684323923e-16f * y2 -
-                  1.9373394351676423e-16f * y3 + 8.824516011816245e-18f * y4;
-  const float b = -1.5788320352845888f * y1 + 2.3305837032074286f * y2 -
-                  0.9141194204840429f * y3 + 0.1623677525612032f * y4;
-  const float c = 0.5334142869106424f * y1 - 1.272736789213631f * y2 +
-                  0.9258856042207512f * y3 - 0.18656310191776226f * y4;
-  const float d = 0.08783463138207234f * y1 - 0.1694162967925622f * y2 +
-                  0.08588057951595272f * y3 - 0.00429891410546283f * y4;
-  const float e = -0.042416883008123074f * y1 + 0.1115693827987602f * y2 -
-                  0.09764676325265872f * y3 + 0.028494263462021576f * y4;
+  const float a = release_frames * kABase;
+  const float b = release_frames * kBBase;
+  const float c = release_frames * kCBase;
+  const float d = release_frames * kDBase;
+  const float e = release_frames * kEBase;
 
   // x ranges from 0 -> 3       0    1    2   3
   //                           -15  -10  -5   0db
@@ -193,9 +194,9 @@
 
   SetPreDelayTime(kPreDelay);
 
-  constexpr int number_of_division_frames = 32;
+  constexpr int kNumberOfDivisionFrames = 32;
 
-  const int number_of_divisions = frames_to_process / number_of_division_frames;
+  const int number_of_divisions = frames_to_process / kNumberOfDivisionFrames;
 
   unsigned frame_index = 0;
   for (int i = 0; i < number_of_divisions; ++i) {
@@ -251,8 +252,8 @@
       const float x4 = x2 * x2;
       const float calc_release_frames = a + b * x + c * x2 + d * x3 + e * x4;
 
-      constexpr float spacing_db = 5;
-      const float db_per_frame = spacing_db / calc_release_frames;
+      constexpr float kSpacingDb = 5;
+      const float db_per_frame = kSpacingDb / calc_release_frames;
 
       envelope_rate = audio_utilities::DecibelsToLinear(db_per_frame);
     } else {
@@ -280,14 +281,14 @@
     float detector_average = detector_average_;
     float compressor_gain = compressor_gain_;
 
-    int loop_frames = number_of_division_frames;
+    int loop_frames = kNumberOfDivisionFrames;
     while (loop_frames--) {
       float compressor_input = 0;
 
       // Predelay signal, computing compression amount from un-delayed
       // version.
       for (unsigned j = 0; j < number_of_channels; ++j) {
-        float* delay_buffer = pre_delay_buffers_[j]->Data();
+        float* const delay_buffer = pre_delay_buffers_[j]->Data();
         const float undelayed_source = source_channels[j][frame_index];
         delay_buffer[pre_delay_write_index] = undelayed_source;
 
@@ -306,15 +307,16 @@
       // Put through shaping curve.
       // This is linear up to the threshold, then enters a "knee" portion
       // followed by the "ratio" portion.  The transition from the threshold
-      // to the knee is smooth (1st derivative matched).  The transition from
-      // the knee to the ratio portion is smooth (1st derivative matched).
+      // to the knee is smooth (1st derivative matched).  The transition
+      // from the knee to the ratio portion is smooth (1st derivative
+      // matched).
       const float shaped_input = Saturate(abs_input, k);
 
       const float attenuation =
           abs_input <= 0.0001f ? 1 : shaped_input / abs_input;
 
-      float attenuation_db = -audio_utilities::LinearToDecibels(attenuation);
-      attenuation_db = std::max(2.0f, attenuation_db);
+      const float attenuation_db =
+          std::max(2.0f, -audio_utilities::LinearToDecibels(attenuation));
 
       const float db_per_frame = attenuation_db / sat_release_frames;
 
@@ -359,7 +361,7 @@
 
       // Apply final gain.
       for (unsigned j = 0; j < number_of_channels; ++j) {
-        const float* delay_buffer = pre_delay_buffers_[j]->Data();
+        const float* const delay_buffer = pre_delay_buffers_[j]->Data();
         destination_channels[j][frame_index] =
             delay_buffer[pre_delay_read_index] * total_gain;
       }
@@ -458,12 +460,12 @@
 
 void DynamicsCompressor::InitializeParameters() {
   // Initializes compressor to default values.
-  parameters_[kParamThreshold] = -24;    // dB
-  parameters_[kParamKnee] = 30;          // dB
-  parameters_[kParamRatio] = 12;         // unit-less
-  parameters_[kParamAttack] = 0.003f;    // seconds
-  parameters_[kParamRelease] = 0.250f;   // seconds
-  parameters_[kParamReduction] = 0;      // dB
+  parameters_[kParamThreshold] = -24;   // dB
+  parameters_[kParamKnee] = 30;         // dB
+  parameters_[kParamRatio] = 12;        // unit-less
+  parameters_[kParamAttack] = 0.003f;   // seconds
+  parameters_[kParamRelease] = 0.250f;  // seconds
+  parameters_[kParamReduction] = 0;     // dB
 }
 
 void DynamicsCompressor::SetPreDelayTime(float pre_delay_time) {
@@ -500,56 +502,44 @@
 
 // Full compression curve with constant ratio after knee.
 float DynamicsCompressor::Saturate(float x, float k) const {
-  float y;
-
   if (x < knee_threshold_) {
-    y = KneeCurve(x, k);
-  } else {
-    // Constant ratio after knee.
-    const float x_db = audio_utilities::LinearToDecibels(x);
-    const float y_db =
-        yknee_threshold_db_ + slope_ * (x_db - knee_threshold_db_);
-
-    y = audio_utilities::DecibelsToLinear(y_db);
+    return KneeCurve(x, k);
   }
-
-  return y;
-}
-
-// Approximate 1st derivative with input and output expressed in dB.
-// This slope is equal to the inverse of the compression "ratio".
-// In other words, a compression ratio of 20 would be a slope of 1/20.
-float DynamicsCompressor::SlopeAt(float x, float k) const {
-  if (x < linear_threshold_) {
-    return 1;
-  }
-
-  const float x2 = x * 1.001;
-
+  // Constant ratio after knee.
   const float x_db = audio_utilities::LinearToDecibels(x);
-  const float x2_db = audio_utilities::LinearToDecibels(x2);
-
-  const float y_db = audio_utilities::LinearToDecibels(KneeCurve(x, k));
-  const float y2_db = audio_utilities::LinearToDecibels(KneeCurve(x2, k));
-
-  const float m = (y2_db - y_db) / (x2_db - x_db);
-
-  return m;
+  const float y_db = yknee_threshold_db_ + slope_ * (x_db - knee_threshold_db_);
+  return audio_utilities::DecibelsToLinear(y_db);
 }
 
 float DynamicsCompressor::KAtSlope(float desired_slope) const {
   const float x_db = db_threshold_ + db_knee_;
   const float x = audio_utilities::DecibelsToLinear(x_db);
+  float x2 = 1;
+  float x2_db = 0;
+
+  if (!(x < linear_threshold_)) {
+    x2 = x * 1.001;
+    x2_db = audio_utilities::LinearToDecibels(x2);
+  }
 
   // Approximate k given initial values.
   float min_k = 0.1;
   float max_k = 10000;
   float k = 5;
 
+  float slope = 1;
   for (int i = 0; i < 15; ++i) {
     // A high value for k will more quickly asymptotically approach a slope of
     // 0.
-    float slope = SlopeAt(x, k);
+
+    // Approximate 1st derivative with input and output expressed in dB.
+    // This slope is equal to the inverse of the compression "ratio".
+    // In other words, a compression ratio of 20 would be a slope of 1/20.
+    if (!(x < linear_threshold_)) {
+      const float y_db = audio_utilities::LinearToDecibels(KneeCurve(x, k));
+      const float y2_db = audio_utilities::LinearToDecibels(KneeCurve(x2, k));
+      slope = (y2_db - y_db) / (x2_db - x_db);
+    }
 
     if (slope < desired_slope) {
       // k is too high.
diff --git a/third_party/blink/renderer/platform/audio/dynamics_compressor.h b/third_party/blink/renderer/platform/audio/dynamics_compressor.h
index 253761e..fd885c4 100644
--- a/third_party/blink/renderer/platform/audio/dynamics_compressor.h
+++ b/third_party/blink/renderer/platform/audio/dynamics_compressor.h
@@ -88,7 +88,6 @@
   // Static compression curve.
   float KneeCurve(float x, float k) const;
   float Saturate(float x, float k) const;
-  float SlopeAt(float x, float k) const;
   float KAtSlope(float desired_slope) const;
 
   float UpdateStaticCurveParameters(float db_threshold,
diff --git a/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc b/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc
index 0654f215..53315db 100644
--- a/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc
@@ -16,6 +16,7 @@
 #include "services/viz/public/mojom/compositing/frame_timing_details.mojom-blink.h"
 #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
 #include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/graphics/begin_frame_provider_params.h"
 #include "third_party/blink/renderer/platform/mojo/mojo_binding_context.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 #include "ui/gfx/mojom/presentation_feedback.mojom-blink.h"
diff --git a/third_party/blink/renderer/platform/graphics/begin_frame_provider.h b/third_party/blink/renderer/platform/graphics/begin_frame_provider.h
index 6182420..649355e5 100644
--- a/third_party/blink/renderer/platform/graphics/begin_frame_provider.h
+++ b/third_party/blink/renderer/platform/graphics/begin_frame_provider.h
@@ -21,10 +21,7 @@
 
 namespace blink {
 
-struct PLATFORM_EXPORT BeginFrameProviderParams final {
-  viz::FrameSinkId parent_frame_sink_id;
-  viz::FrameSinkId frame_sink_id;
-};
+struct BeginFrameProviderParams;
 
 class PLATFORM_EXPORT BeginFrameProviderClient : public GarbageCollectedMixin {
  public:
@@ -37,10 +34,10 @@
       public viz::mojom::blink::CompositorFrameSinkClient,
       public mojom::blink::EmbeddedFrameSinkClient {
  public:
-  explicit BeginFrameProvider(
+  BeginFrameProvider(
       const BeginFrameProviderParams& begin_frame_provider_params,
-      BeginFrameProviderClient*,
-      ContextLifecycleNotifier*);
+      BeginFrameProviderClient* client,
+      ContextLifecycleNotifier* context);
 
   void CreateCompositorFrameSinkIfNeeded();
 
diff --git a/third_party/blink/renderer/platform/graphics/begin_frame_provider_params.h b/third_party/blink/renderer/platform/graphics/begin_frame_provider_params.h
new file mode 100644
index 0000000..8bdb9d9
--- /dev/null
+++ b/third_party/blink/renderer/platform/graphics/begin_frame_provider_params.h
@@ -0,0 +1,20 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_BEGIN_FRAME_PROVIDER_PARAMS_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_BEGIN_FRAME_PROVIDER_PARAMS_H_
+
+#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+
+struct PLATFORM_EXPORT BeginFrameProviderParams final {
+  viz::FrameSinkId parent_frame_sink_id;
+  viz::FrameSinkId frame_sink_id;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_BEGIN_FRAME_PROVIDER_PARAMS_H_
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 411e6528..28458b75 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -2802,13 +2802,12 @@
     // exposes requisite information about displays connected to the device.
     {
       name: "WindowPlacement",
-      origin_trial_feature_name: "WindowPlacementOT2",
-      implied_by: ["WindowPlacementV2"],
       status: "stable",
     },
-    // Further extends window placement functionality for multi-screen devices.
+    // Allows sites to request fullscreen when the set of screens change.
     {
-      name: "WindowPlacementV2",
+      name: "WindowPlacementFullscreenOnScreensChange",
+      depends_on: ["WindowPlacement"],
       status: "experimental",
     },
     {
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/linux.py b/third_party/blink/tools/blinkpy/web_tests/port/linux.py
index 8c3a2977..c51ac10 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/linux.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/linux.py
@@ -241,10 +241,7 @@
         flags = ['-screen', '0', '1280x800x24', '-ac', '-dpi', '96']
         # Raise the Xvfb connection limit if the default limit (256 connections)
         # is in danger of being exceeded by 4 connections per test.
-        # This is conditional since the linux-trusty-rel build bot uses a very
-        # old version of Xvfb which does not recognise the flag.
-        if self.default_child_processes() > 60:
-            flags += ['-maxclients', '512']
+        flags += ['-maxclients', '512']
         return flags
 
     def _find_display(self):
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/linux_unittest.py b/third_party/blink/tools/blinkpy/web_tests/port/linux_unittest.py
index ae1e28e..cfee9fe00 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/linux_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/linux_unittest.py
@@ -139,10 +139,6 @@
 
     def test_xvfb_flags(self):
         port = self.make_port()
-        port.default_child_processes = lambda: 60
-        self.assertEqual(port.xvfb_flags(),
-                         ['-screen', '0', '1280x800x24', '-ac', '-dpi', '96'])
-        port.default_child_processes = lambda: 61
         self.assertEqual(port.xvfb_flags(), [
             '-screen', '0', '1280x800x24', '-ac', '-dpi', '96', '-maxclients',
             '512'
diff --git a/third_party/blink/web_tests/WebGPUExpectations b/third_party/blink/web_tests/WebGPUExpectations
index 1cb8a4f..be09d79 100644
--- a/third_party/blink/web_tests/WebGPUExpectations
+++ b/third_party/blink/web_tests/WebGPUExpectations
@@ -85,6 +85,12 @@
 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,image_copy,layout_related:bound_on_bytes_per_row:* [ Timeout ]
 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,image_copy,buffer_related:bytes_per_row_alignment:* [ Timeout ]
 
+crbug.com/dawn/1330 wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:createView,2d,uncompressed_format:* [ Failure Timeout ]
+crbug.com/dawn/1330 wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:createTexture,2d,uncompressed_format:* [ Failure Timeout ]
+
+[ Win ] wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,expression,call,builtin,clamp:f32:* [ Timeout ]
+
+
 ###
 ### Test bugs
 ###
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/whitespace-reattach.html b/third_party/blink/web_tests/external/wpt/css/css-grid/whitespace-reattach.html
new file mode 100644
index 0000000..f97934e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/whitespace-reattach.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1308400">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div id="target" style="display: grid; grid-template: 100px / 100px 100px; background: red; width: 100px;">
+text
+</div>
+<script>
+document.body.offsetTop;
+const el = document.createElement('div');
+el.style.background = 'green';
+const target = document.getElementById('target');
+const content = target.childNodes[0].splitText(1);
+target.replaceChild(el, content);
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/getComputedStyle-detached-subtree-expected.txt b/third_party/blink/web_tests/external/wpt/css/cssom/getComputedStyle-detached-subtree-expected.txt
index bc03eaa..13902b46 100644
--- a/third_party/blink/web_tests/external/wpt/css/cssom/getComputedStyle-detached-subtree-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/cssom/getComputedStyle-detached-subtree-expected.txt
@@ -1,9 +1,9 @@
 This is a testharness.js-based test.
 PASS getComputedStyle returns no style for detached element
-FAIL getComputedStyle returns no style for element in non-rendered iframe (display: none) assert_equals: expected 0 but got 354
-FAIL getComputedStyle returns no style for element in non-rendered iframe (display: none) from iframe's window assert_equals: expected 0 but got 354
-FAIL getComputedStyle returns no style for element outside the flat tree assert_equals: expected 0 but got 354
-FAIL getComputedStyle returns no style for descendant outside the flat tree assert_equals: expected 0 but got 354
+FAIL getComputedStyle returns no style for element in non-rendered iframe (display: none) assert_equals: expected 0 but got 355
+FAIL getComputedStyle returns no style for element in non-rendered iframe (display: none) from iframe's window assert_equals: expected 0 but got 355
+FAIL getComputedStyle returns no style for element outside the flat tree assert_equals: expected 0 but got 355
+FAIL getComputedStyle returns no style for descendant outside the flat tree assert_equals: expected 0 but got 355
 PASS getComputedStyle returns no style for shadow tree outside of flattened tree
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/getComputedStyle-pseudo-expected.txt b/third_party/blink/web_tests/external/wpt/css/cssom/getComputedStyle-pseudo-expected.txt
index 705b6204..d703703 100644
--- a/third_party/blink/web_tests/external/wpt/css/cssom/getComputedStyle-pseudo-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/cssom/getComputedStyle-pseudo-expected.txt
@@ -7,6 +7,6 @@
 PASS Item-based blockification of nonexistent pseudo-elements
 PASS display: contents on pseudo-elements
 PASS Dynamically change to display: contents on pseudo-elements
-FAIL Unknown pseudo-elements assert_equals: Should return an empty style for unknown pseudo-elements starting with double-colon expected 0 but got 354
+FAIL Unknown pseudo-elements assert_equals: Should return an empty style for unknown pseudo-elements starting with double-colon expected 0 but got 355
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt
index 99549d9..b2afe981 100644
--- a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt
+++ b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt
@@ -241,6 +241,7 @@
 min-width: 0px
 mix-blend-mode: normal
 object-fit: fill
+object-overflow: clip
 object-position: 50% 50%
 object-view-box: none
 offset-anchor: auto
diff --git a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
index 7535adb..ebc179c 100644
--- a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
+++ b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
@@ -241,6 +241,7 @@
 min-width: 0px
 mix-blend-mode: normal
 object-fit: fill
+object-overflow: clip
 object-position: 50% 50%
 object-view-box: none
 offset-anchor: auto
diff --git a/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt b/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt
index 4e248c9..50d9679 100644
--- a/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt
+++ b/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt
@@ -241,6 +241,7 @@
 min-width: 0px
 mix-blend-mode: normal
 object-fit: fill
+object-overflow: clip
 object-position: 50% 50%
 object-view-box: none
 offset-anchor: auto
diff --git a/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt b/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt
index 87480220..d96431e 100644
--- a/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt
+++ b/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt
@@ -279,6 +279,7 @@
 mixBlendMode
 negative
 objectFit
+objectOverflow
 objectPosition
 objectViewBox
 offset
diff --git a/third_party/blink/web_tests/webexposed/css-property-listing-expected.txt b/third_party/blink/web_tests/webexposed/css-property-listing-expected.txt
index 6fdf36d9..fe6f27b 100644
--- a/third_party/blink/web_tests/webexposed/css-property-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/css-property-listing-expected.txt
@@ -258,6 +258,7 @@
     min-width
     mix-blend-mode
     object-fit
+    object-overflow
     object-position
     object-view-box
     offset-anchor
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-images/object-overflow-parsing.html b/third_party/blink/web_tests/wpt_internal/css/css-images/object-overflow-parsing.html
new file mode 100644
index 0000000..1ebf12e
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/css/css-images/object-overflow-parsing.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS object-overflow: computed values</title>
+<link rel="author" title="Khushal Sagar" href="mailto:khushalsagar@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<div id=target></div>
+<script>
+test_valid_value('object-overflow', 'clip');
+test_valid_value('object-overflow', 'visible');
+test_invalid_value('object-view-box', 'blah');
+
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/cts.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/cts.https.html
index 06f85c9a..62c44aab 100644
--- a/third_party/blink/web_tests/wpt_internal/webgpu/cts.https.html
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/cts.https.html
@@ -2060,6 +2060,7 @@
 <meta name=variant content='?q=webgpu:api,validation,encoding,cmds,buffer_texture_copies:depth_stencil_format,copy_buffer_size:*'>
 <meta name=variant content='?q=webgpu:api,validation,encoding,cmds,buffer_texture_copies:depth_stencil_format,copy_buffer_offset:*'>
 <meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:invalid_buffer:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:buffer,device_mismatch:*'>
 <meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:default_args:*'>
 <meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:buffer_usage:*'>
 <meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:size_alignment:*'>
@@ -2225,6 +2226,7 @@
 <meta name=variant content='?q=webgpu:api,validation,error_scope:push,popping_sibling_error_scopes_must_be_balanced:*'>
 <meta name=variant content='?q=webgpu:api,validation,error_scope:push,popping_nested_error_scopes_must_be_balanced:*'>
 <meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_related:valid:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_related:buffer,device_mismatch:*'>
 <meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_related:usage:*'>
 <meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_related:bytes_per_row_alignment:*'>
 <meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:bound_on_rows_per_image:*'>
@@ -2506,7 +2508,6 @@
 <meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:bound_on_offset:*'>
 <meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:valid:*'>
 <meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:texture,device_mismatch:*'>
-<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:buffer,device_mismatch:*'>
 <meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:usage:*'>
 <meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:sample_count:*'>
 <meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:mip_level:*'>
@@ -2586,6 +2587,35 @@
 <meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:validation_scope,different_passes:*'>
 <meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources_from_same_texture_as_color_attachments:*'>
 <meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources_from_same_texture_as_color_attachment_and_in_bind_group:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources_from_same_texture_as_depth_stencil_attachment_and_in_bind_group:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createBuffer:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createTexture,2d,uncompressed_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createTexture,2d,compressed_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createView,2d,uncompressed_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createView,2d,compressed_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createSampler:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createBindGroupLayout:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createBindGroup:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createPipelineLayout:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createShaderModule:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createComputePipeline:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createRenderPipeline:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createCommandEncoder:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createRenderBundleEncoder:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createQuerySet:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,copyBufferToBuffer:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,copyBufferToTexture:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,copyTextureToBuffer:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,copyTextureToTexture:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,clearBuffer:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,writeTimestamp:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,resolveQuerySet:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,computePass,dispatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,renderPass,draw:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,renderPass,renderBundle:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:queue,writeBuffer:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:queue,writeTexture:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:queue,copyExternalImageToTexture:*'>
 <meta name=variant content='?q=webgpu:api,validation,texture,destroy:base:*'>
 <meta name=variant content='?q=webgpu:api,validation,texture,destroy:twice:*'>
 <meta name=variant content='?q=webgpu:api,validation,texture,destroy:submit_a_destroyed_texture_as_attachment:*'>
@@ -2712,6 +2742,14 @@
 <meta name=variant content='?q=webgpu:idl,constants,flags:ColorWrite,values:*'>
 <meta name=variant content='?q=webgpu:idl,constants,flags:ShaderStage,count:*'>
 <meta name=variant content='?q=webgpu:idl,constants,flags:ShaderStage,values:*'>
+<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:binary_arith:*'>
+<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:binary_logical:*'>
+<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:binary_mixed:*'>
+<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:call:*'>
+<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:index_accessor:*'>
+<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:assignment:*'>
+<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:type_constructor:*'>
+<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:member_accessor:*'>
 <meta name=variant content='?q=webgpu:shader,execution,expression,binary,bitwise:bitwise_or:*'>
 <meta name=variant content='?q=webgpu:shader,execution,expression,binary,bitwise:bitwise_and:*'>
 <meta name=variant content='?q=webgpu:shader,execution,expression,binary,bitwise:bitwise_exclusive_or:*'>
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html
index a0a83bd..1a8f292 100644
--- a/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html
@@ -1,6 +1,6 @@
 <html class="reftest-wait">
   <base href="/gen/third_party/webgpu-cts/src/webgpu/web_platform/reftests/" />
-  <title>WebGPU canvas_complex_bgra8unorm_copy_buffer_to_texture</title>
+  <title>WebGPU canvas_complex_bgra8unorm_copy</title>
   <meta charset="utf-8" />
   <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
   <meta
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html
index 72144f3..dae1b02 100644
--- a/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html
@@ -1,6 +1,6 @@
 <html class="reftest-wait">
   <base href="/gen/third_party/webgpu-cts/src/webgpu/web_platform/reftests/" />
-  <title>WebGPU canvas_complex_bgra8unorm_copy_buffer_to_texture</title>
+  <title>WebGPU canvas_complex_bgra8unorm_draw</title>
   <meta charset="utf-8" />
   <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
   <meta
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba16float_copy.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba16float_copy.https.html
new file mode 100644
index 0000000..36bba1ad
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba16float_copy.https.html
@@ -0,0 +1,25 @@
+<html class="reftest-wait">
+  <base href="/gen/third_party/webgpu-cts/src/webgpu/web_platform/reftests/" />
+  <title>WebGPU canvas_complex_rgba16float_copy</title>
+  <meta charset="utf-8" />
+  <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+  <meta
+    name="assert"
+    content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+  />
+  <link rel="match" href="./ref/canvas_complex-ref.html" />
+
+  <canvas id="cvs_copy_buffer_to_texture" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+  <canvas id="cvs_copy_texture_to_texture" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+  <canvas id="cvs_copy_external_image_to_texture" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+
+  <script src="/common/reftest-wait.js"></script>
+  <script type="module">
+    import { run } from './canvas_complex.html.js';
+    run('rgba16float', [
+      { cvs: cvs_copy_buffer_to_texture, writeCanvasMethod: 'copyBufferToTexture' },
+      { cvs: cvs_copy_texture_to_texture, writeCanvasMethod: 'copyTextureToTexture' },
+      { cvs: cvs_copy_external_image_to_texture, writeCanvasMethod: 'copyExternalImageToTexture' },
+    ]);
+  </script>
+</html>
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba16float_draw.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba16float_draw.https.html
new file mode 100644
index 0000000..1b04f2af
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba16float_draw.https.html
@@ -0,0 +1,25 @@
+<html class="reftest-wait">
+  <base href="/gen/third_party/webgpu-cts/src/webgpu/web_platform/reftests/" />
+  <title>WebGPU canvas_complex_rgba16float_draw</title>
+  <meta charset="utf-8" />
+  <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+  <meta
+    name="assert"
+    content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+  />
+  <link rel="match" href="./ref/canvas_complex-ref.html" />
+
+  <canvas id="cvs_draw_texture_sample" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+  <canvas id="cvs_draw_vertex_color" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+  <canvas id="cvs_draw_fragcoord" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+
+  <script src="/common/reftest-wait.js"></script>
+  <script type="module">
+    import { run } from './canvas_complex.html.js';
+    run('rgba16float', [
+      { cvs: cvs_draw_texture_sample, writeCanvasMethod: 'DrawTextureSample' },
+      { cvs: cvs_draw_vertex_color, writeCanvasMethod: 'DrawVertexColor' },
+      { cvs: cvs_draw_fragcoord, writeCanvasMethod: 'DrawFragcoord' },
+    ]);
+  </script>
+</html>
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba16float_store.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba16float_store.https.html
new file mode 100644
index 0000000..e2a9984
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba16float_store.https.html
@@ -0,0 +1,25 @@
+<html class="reftest-wait">
+  <base href="/gen/third_party/webgpu-cts/src/webgpu/web_platform/reftests/" />
+  <title>WebGPU canvas_complex_rgba16float_store</title>
+  <meta charset="utf-8" />
+  <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+  <meta
+    name="assert"
+    content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+  />
+  <link rel="match" href="./ref/canvas_complex-ref.html" />
+
+  <canvas id="cvs_fragment_texture_store" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+  <canvas id="cvs_compute_texture_store_1" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+  <canvas id="cvs_compute_texture_store_2" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+
+  <script src="/common/reftest-wait.js"></script>
+  <script type="module">
+    import { run } from './canvas_complex.html.js';
+    run('rgba16float', [
+      { cvs: cvs_fragment_texture_store, writeCanvasMethod: 'FragmentTextureStore' },
+      { cvs: cvs_compute_texture_store_1, writeCanvasMethod: 'ComputeWorkgroup1x1TextureStore' },
+      { cvs: cvs_compute_texture_store_2, writeCanvasMethod: 'ComputeWorkgroup2x2TextureStore' },
+    ]);
+  </script>
+</html>
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html
new file mode 100644
index 0000000..44aff0a
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html
@@ -0,0 +1,25 @@
+<html class="reftest-wait">
+  <base href="/gen/third_party/webgpu-cts/src/webgpu/web_platform/reftests/" />
+  <title>WebGPU canvas_complex_rgba8unorm_copy</title>
+  <meta charset="utf-8" />
+  <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+  <meta
+    name="assert"
+    content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+  />
+  <link rel="match" href="./ref/canvas_complex-ref.html" />
+
+  <canvas id="cvs_copy_buffer_to_texture" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+  <canvas id="cvs_copy_texture_to_texture" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+  <canvas id="cvs_copy_external_image_to_texture" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+
+  <script src="/common/reftest-wait.js"></script>
+  <script type="module">
+    import { run } from './canvas_complex.html.js';
+    run('rgba8unorm', [
+      { cvs: cvs_copy_buffer_to_texture, writeCanvasMethod: 'copyBufferToTexture' },
+      { cvs: cvs_copy_texture_to_texture, writeCanvasMethod: 'copyTextureToTexture' },
+      { cvs: cvs_copy_external_image_to_texture, writeCanvasMethod: 'copyExternalImageToTexture' },
+    ]);
+  </script>
+</html>
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html
new file mode 100644
index 0000000..464236f
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html
@@ -0,0 +1,25 @@
+<html class="reftest-wait">
+  <base href="/gen/third_party/webgpu-cts/src/webgpu/web_platform/reftests/" />
+  <title>WebGPU canvas_complex_rgba8unorm_draw</title>
+  <meta charset="utf-8" />
+  <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+  <meta
+    name="assert"
+    content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+  />
+  <link rel="match" href="./ref/canvas_complex-ref.html" />
+
+  <canvas id="cvs_draw_texture_sample" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+  <canvas id="cvs_draw_vertex_color" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+  <canvas id="cvs_draw_fragcoord" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+
+  <script src="/common/reftest-wait.js"></script>
+  <script type="module">
+    import { run } from './canvas_complex.html.js';
+    run('rgba8unorm', [
+      { cvs: cvs_draw_texture_sample, writeCanvasMethod: 'DrawTextureSample' },
+      { cvs: cvs_draw_vertex_color, writeCanvasMethod: 'DrawVertexColor' },
+      { cvs: cvs_draw_fragcoord, writeCanvasMethod: 'DrawFragcoord' },
+    ]);
+  </script>
+</html>
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html
new file mode 100644
index 0000000..b3e77dcd
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html
@@ -0,0 +1,25 @@
+<html class="reftest-wait">
+  <base href="/gen/third_party/webgpu-cts/src/webgpu/web_platform/reftests/" />
+  <title>WebGPU canvas_complex_rgba8unorm_store</title>
+  <meta charset="utf-8" />
+  <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+  <meta
+    name="assert"
+    content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+  />
+  <link rel="match" href="./ref/canvas_complex-ref.html" />
+
+  <canvas id="cvs_fragment_texture_store" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+  <canvas id="cvs_compute_texture_store_1" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+  <canvas id="cvs_compute_texture_store_2" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+
+  <script src="/common/reftest-wait.js"></script>
+  <script type="module">
+    import { run } from './canvas_complex.html.js';
+    run('rgba8unorm', [
+      { cvs: cvs_fragment_texture_store, writeCanvasMethod: 'FragmentTextureStore' },
+      { cvs: cvs_compute_texture_store_1, writeCanvasMethod: 'ComputeWorkgroup1x1TextureStore' },
+      { cvs: cvs_compute_texture_store_2, writeCanvasMethod: 'ComputeWorkgroup2x2TextureStore' },
+    ]);
+  </script>
+</html>
diff --git a/third_party/rust/autocxx/v0_17/README.chromium b/third_party/rust/autocxx/v0_17/README.chromium
index 13be0a55..eceaa0c 100644
--- a/third_party/rust/autocxx/v0_17/README.chromium
+++ b/third_party/rust/autocxx/v0_17/README.chromium
@@ -1,6 +1,6 @@
 Name: autocxx
 URL: https://crates.io/crates/autocxx
 Description: Safe autogenerated interop between Rust and C++
-Version: 0.17.2
+Version: 0.17.4
 Security Critical: yes
 License: Apache 2.0
diff --git a/third_party/rust/autocxx/v0_17/crate/.cargo_vcs_info.json b/third_party/rust/autocxx/v0_17/crate/.cargo_vcs_info.json
index 0e2733c..67ce758 100644
--- a/third_party/rust/autocxx/v0_17/crate/.cargo_vcs_info.json
+++ b/third_party/rust/autocxx/v0_17/crate/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "5bb748878f97f854bffa61e5a7cd8ebf970f3dcd"
+    "sha1": "616796cc31322ff782c938dfccc330961fda72a2"
   },
   "path_in_vcs": ""
 }
\ No newline at end of file
diff --git a/third_party/rust/autocxx/v0_17/crate/.github/workflows/ci.yml b/third_party/rust/autocxx/v0_17/crate/.github/workflows/ci.yml
index 45c8723..e3535d9 100644
--- a/third_party/rust/autocxx/v0_17/crate/.github/workflows/ci.yml
+++ b/third_party/rust/autocxx/v0_17/crate/.github/workflows/ci.yml
@@ -139,6 +139,8 @@
       - name: Build non-trivial-type-on-stack example
         working-directory: ./examples/non-trivial-type-on-stack
         run: cargo build
+        # We do not build the LLVM example because even 'apt-get install llvm-13-dev'
+        # does not work to install the LLVM 13 headers.
 
   sanitizer:
     name: Address Sanitizer
diff --git a/third_party/rust/autocxx/v0_17/crate/Cargo.toml b/third_party/rust/autocxx/v0_17/crate/Cargo.toml
index a10da5a2..4c2f68b 100644
--- a/third_party/rust/autocxx/v0_17/crate/Cargo.toml
+++ b/third_party/rust/autocxx/v0_17/crate/Cargo.toml
@@ -12,7 +12,7 @@
 [package]
 edition = "2021"
 name = "autocxx"
-version = "0.17.2"
+version = "0.17.4"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 description = "Safe autogenerated interop between Rust and C++"
 homepage = "https://autocxx.rs"
@@ -29,7 +29,7 @@
 version = "0.1"
 
 [dependencies.autocxx-macro]
-version = "0.17.2"
+version = "0.17.4"
 
 [dependencies.cxx]
 version = "1.0.54"
diff --git a/third_party/rust/autocxx/v0_17/crate/Cargo.toml.orig b/third_party/rust/autocxx/v0_17/crate/Cargo.toml.orig
index 8ea82ad5..80cdb5b 100644
--- a/third_party/rust/autocxx/v0_17/crate/Cargo.toml.orig
+++ b/third_party/rust/autocxx/v0_17/crate/Cargo.toml.orig
@@ -8,7 +8,7 @@
 
 [package]
 name = "autocxx"
-version = "0.17.2"
+version = "0.17.4"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 license = "MIT OR Apache-2.0"
 description = "Safe autogenerated interop between Rust and C++"
@@ -24,14 +24,14 @@
 resolver = "2"
 
 [dependencies]
-autocxx-macro = { path="macro", version="0.17.2" }
+autocxx-macro = { path="macro", version="0.17.4" }
 cxx = "1.0.54" # ... also needed because expansion of type_id refers to ::cxx
 aquamarine = "0.1" # docs
 moveit = { version = "0.4", features = [ "cxx" ] }
 
 [workspace]
 members = ["parser", "engine", "gen/cmd", "gen/build", "macro", "demo", "tools/reduce", "tools/mdbook-preprocessor", "integration-tests"]
-exclude = ["examples/s2", "examples/steam-mini", "examples/subclass", "examples/chromium-fake-render-frame-host", "examples/pod", "examples/non-trivial-type-on-stack"]
+exclude = ["examples/s2", "examples/steam-mini", "examples/subclass", "examples/chromium-fake-render-frame-host", "examples/pod", "examples/non-trivial-type-on-stack", "examples/llvm"]
 
 #[patch.crates-io]
 #cxx = { path="../cxx" }
diff --git a/third_party/rust/autocxx/v0_17/crate/book/src/cpp_types.md b/third_party/rust/autocxx/v0_17/crate/book/src/cpp_types.md
index 3a6f3ea..dc70edb 100644
--- a/third_party/rust/autocxx/v0_17/crate/book/src/cpp_types.md
+++ b/third_party/rust/autocxx/v0_17/crate/book/src/cpp_types.md
@@ -108,6 +108,53 @@
 To make them more useful, you might have to add extra C++ functions to extract
 data or otherwise deal with them.
 
+Usually, such concrete types are synthesized automatically because they're
+parameters or return values from functions. Very rarely, you may
+want to synthesize them yourself - you can do this using the
+[`concrete!`](https://docs.rs/autocxx/latest/autocxx/macro.concrete.html)
+directive. As noted, though, these types are currently opaque and fairly
+useless without passing them back and forth to C++, so this is not a commonly
+used facility. It does, however, allow you to give a more descriptive name
+to the type in Rust:
+
+```rust,ignore,autocxx,hidecpp
+autocxx_integration_tests::doctest(
+"",
+"#include <string>
+struct Tapioca {
+  std::string yuck;
+};
+template<typename Floaters>
+struct Tea {
+  Tea() : floaters(nullptr) {}
+  Floaters* floaters;
+};
+inline Tea<Tapioca> prepare() {
+  Tea<Tapioca> mixture;
+  // prepare...
+  return mixture;
+}
+inline void drink(const Tea<Tapioca>&) {}
+",
+{
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate!("prepare")
+    generate!("drink")
+    concrete!("Tea<Tapioca>", Boba)
+}
+
+fn main() {
+    let nicer_than_it_sounds: cxx::UniquePtr<ffi::Boba> = ffi::prepare();
+    ffi::drink(&nicer_than_it_sounds);
+}
+}
+)
+```
+
 ## Implicit member functions
 
 Most of the API of a C++ type is contained within the type, so `autocxx` can
diff --git a/third_party/rust/autocxx/v0_17/crate/book/src/naming.md b/third_party/rust/autocxx/v0_17/crate/book/src/naming.md
index dee6aaa..ab2240e 100644
--- a/third_party/rust/autocxx/v0_17/crate/book/src/naming.md
+++ b/third_party/rust/autocxx/v0_17/crate/book/src/naming.md
@@ -66,7 +66,7 @@
 }
 
 fn main() {
-    let turducken = ffi::Turkey_Duck_Hen::make_unique();
+    let _turducken = ffi::Turkey_Duck_Hen::make_unique();
 }
 }
 )
diff --git a/third_party/rust/autocxx/v0_17/crate/book/src/tutorial.md b/third_party/rust/autocxx/v0_17/crate/book/src/tutorial.md
index 96b3786b..5cdd864e 100644
--- a/third_party/rust/autocxx/v0_17/crate/book/src/tutorial.md
+++ b/third_party/rust/autocxx/v0_17/crate/book/src/tutorial.md
@@ -19,11 +19,11 @@
 
 ```toml
 [dependencies]
-autocxx = "0.17.2"
+autocxx = "0.17.4"
 cxx = "1.0"
 
 [build-dependencies]
-autocxx-build = "0.17.2"
+autocxx-build = "0.17.4"
 ```
 
 Now, add a `build.rs` next to your `Cargo.toml` (this is a standard `cargo` [build script](https://doc.rust-lang.org/cargo/reference/build-scripts.html)). This is where you need your include path:
diff --git a/third_party/rust/autocxx/v0_17/crate/src/lib.rs b/third_party/rust/autocxx/v0_17/crate/src/lib.rs
index fad1b16f..1edab4cb 100644
--- a/third_party/rust/autocxx/v0_17/crate/src/lib.rs
+++ b/third_party/rust/autocxx/v0_17/crate/src/lib.rs
@@ -210,6 +210,18 @@
     ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
 }
 
+/// A concrete type to make, for example
+/// `concrete!("Container<Contents>")`.
+/// All types msut already be on the allowlist by having used
+/// `generate!` or similar.
+///
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! concrete {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
 /// Specifies a global safety policy for functions generated
 /// from these headers. By default (without such a `safety!`
 /// directive) all such functions are marked as `unsafe` and
@@ -446,6 +458,7 @@
     pub use crate::include_cpp;
     pub use crate::PinMut;
     pub use crate::ValueParam;
+    pub use cxx::UniquePtr;
     pub use moveit::moveit;
     pub use moveit::new::New;
 }
diff --git a/third_party/rust/autocxx_bindgen/v0_59/README.chromium b/third_party/rust/autocxx_bindgen/v0_59/README.chromium
index 499c3af5..3b0ce39 100644
--- a/third_party/rust/autocxx_bindgen/v0_59/README.chromium
+++ b/third_party/rust/autocxx_bindgen/v0_59/README.chromium
@@ -1,6 +1,6 @@
 Name: autocxx-bindgen
 URL: https://crates.io/crates/autocxx-bindgen
 Description: Automatically generates Rust FFI bindings to C and C++ libraries. Version adjusted for cxx.
-Version: 0.59.13
-Security Critical: no
+Version: 0.59.14
+Security Critical: yes
 License: BSD 3-Clause
diff --git a/third_party/rust/autocxx_bindgen/v0_59/crate/.cargo_vcs_info.json b/third_party/rust/autocxx_bindgen/v0_59/crate/.cargo_vcs_info.json
index 147934a7a..63b5739 100644
--- a/third_party/rust/autocxx_bindgen/v0_59/crate/.cargo_vcs_info.json
+++ b/third_party/rust/autocxx_bindgen/v0_59/crate/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "6f77d7d7dc6f48ca4463e4800a5bd2caced9c83d"
+    "sha1": "b53fe6548a15b70c1ca3f8245f2c630b33496ac8"
   },
   "path_in_vcs": ""
 }
\ No newline at end of file
diff --git a/third_party/rust/autocxx_bindgen/v0_59/crate/Cargo.lock b/third_party/rust/autocxx_bindgen/v0_59/crate/Cargo.lock
index 6008f74f..559bf1f 100644
--- a/third_party/rust/autocxx_bindgen/v0_59/crate/Cargo.lock
+++ b/third_party/rust/autocxx_bindgen/v0_59/crate/Cargo.lock
@@ -33,7 +33,7 @@
 
 [[package]]
 name = "autocxx-bindgen"
-version = "0.59.13"
+version = "0.59.14"
 dependencies = [
  "bitflags",
  "cexpr",
diff --git a/third_party/rust/autocxx_bindgen/v0_59/crate/Cargo.toml b/third_party/rust/autocxx_bindgen/v0_59/crate/Cargo.toml
index 91da262..968c0ca 100644
--- a/third_party/rust/autocxx_bindgen/v0_59/crate/Cargo.toml
+++ b/third_party/rust/autocxx_bindgen/v0_59/crate/Cargo.toml
@@ -12,16 +12,36 @@
 [package]
 edition = "2018"
 name = "autocxx-bindgen"
-version = "0.59.13"
-authors = ["Jyun-Yan You <jyyou.tw@gmail.com>", "Emilio Cobos Álvarez <emilio@crisal.io>", "Nick Fitzgerald <fitzgen@gmail.com>", "The Servo project developers", "Adrian Taylor <ade@hohum.me.uk>"]
+version = "0.59.14"
+authors = [
+    "Jyun-Yan You <jyyou.tw@gmail.com>",
+    "Emilio Cobos Álvarez <emilio@crisal.io>",
+    "Nick Fitzgerald <fitzgen@gmail.com>",
+    "The Servo project developers",
+    "Adrian Taylor <ade@hohum.me.uk>",
+]
 build = "build.rs"
-include = ["LICENSE", "README.md", "Cargo.toml", "build.rs", "src/*.rs", "src/**/*.rs"]
+include = [
+    "LICENSE",
+    "README.md",
+    "Cargo.toml",
+    "build.rs",
+    "src/*.rs",
+    "src/**/*.rs",
+]
 description = "Automatically generates Rust FFI bindings to C and C++ libraries. Version adjusted for cxx."
 homepage = "https://rust-lang.github.io/rust-bindgen/"
 documentation = "https://docs.rs/bindgen"
 readme = "README.md"
-keywords = ["bindings", "ffi", "code-generation"]
-categories = ["external-ffi-bindings", "development-tools::ffi"]
+keywords = [
+    "bindings",
+    "ffi",
+    "code-generation",
+]
+categories = [
+    "external-ffi-bindings",
+    "development-tools::ffi",
+]
 license = "BSD-3-Clause"
 repository = "https://github.com/adetaylor/rust-bindgen"
 
@@ -33,6 +53,7 @@
 path = "src/main.rs"
 doc = false
 required-features = ["clap"]
+
 [dependencies.bitflags]
 version = "1.0.3"
 
@@ -77,7 +98,10 @@
 
 [dependencies.regex]
 version = "1.0"
-features = ["std", "unicode"]
+features = [
+    "std",
+    "unicode",
+]
 default-features = false
 
 [dependencies.rustc-hash]
@@ -90,6 +114,7 @@
 version = "4.2.1"
 optional = true
 default-features = false
+
 [dev-dependencies.clap]
 version = "2"
 
@@ -103,8 +128,16 @@
 version = "3"
 
 [features]
-default = ["logging", "clap", "runtime", "which-rustfmt"]
-logging = ["env_logger", "log"]
+default = [
+    "logging",
+    "clap",
+    "runtime",
+    "which-rustfmt",
+]
+logging = [
+    "env_logger",
+    "log",
+]
 runtime = ["clang-sys/runtime"]
 static = ["clang-sys/static"]
 testing_only_docs = []
diff --git a/third_party/rust/autocxx_bindgen/v0_59/crate/Cargo.toml.orig b/third_party/rust/autocxx_bindgen/v0_59/crate/Cargo.toml.orig
index 8014d883..956169a 100644
--- a/third_party/rust/autocxx_bindgen/v0_59/crate/Cargo.toml.orig
+++ b/third_party/rust/autocxx_bindgen/v0_59/crate/Cargo.toml.orig
@@ -15,7 +15,7 @@
 repository = "https://github.com/adetaylor/rust-bindgen"
 documentation = "https://docs.rs/bindgen"
 homepage = "https://rust-lang.github.io/rust-bindgen/"
-version = "0.59.13"
+version = "0.59.14"
 edition = "2018"
 build = "build.rs"
 
diff --git a/third_party/rust/autocxx_bindgen/v0_59/crate/src/codegen/helpers.rs b/third_party/rust/autocxx_bindgen/v0_59/crate/src/codegen/helpers.rs
index c3382861..b7f91c2 100644
--- a/third_party/rust/autocxx_bindgen/v0_59/crate/src/codegen/helpers.rs
+++ b/third_party/rust/autocxx_bindgen/v0_59/crate/src/codegen/helpers.rs
@@ -157,8 +157,8 @@
         }
     }
 
-    fn unused_template_param_in_arg_or_return(&mut self) {
-        self.add_ident("unused_template_param_in_arg_or_return")
+    fn incomprehensible_param_in_arg_or_return(&mut self) {
+        self.add_ident("incomprehensible_param_in_arg_or_return")
     }
 
     fn discards_template_param(&mut self) {
diff --git a/third_party/rust/autocxx_bindgen/v0_59/crate/src/codegen/mod.rs b/third_party/rust/autocxx_bindgen/v0_59/crate/src/codegen/mod.rs
index e2f3e4a..95b84861f 100644
--- a/third_party/rust/autocxx_bindgen/v0_59/crate/src/codegen/mod.rs
+++ b/third_party/rust/autocxx_bindgen/v0_59/crate/src/codegen/mod.rs
@@ -898,6 +898,7 @@
                         semantic_annotations.discards_template_param();
                     }
                     RustTyAnnotation::None |
+                    RustTyAnnotation::Opaque |
                     RustTyAnnotation::Reference |
                     RustTyAnnotation::RValueReference => {}
                     RustTyAnnotation::HasUnusedTemplateArgs => {
@@ -3537,7 +3538,7 @@
 
     fn to_rust_ty_or_opaque(&self, ctx: &BindgenContext, extra: &E) -> RustTy {
         self.try_to_rust_ty(ctx, extra)
-            .unwrap_or_else(|_| self.to_opaque(ctx, extra).into())
+            .unwrap_or_else(|_| RustTy::new_opaque(self.to_opaque(ctx, extra)))
     }
 }
 
@@ -3612,6 +3613,7 @@
     Reference,
     RValueReference,
     HasUnusedTemplateArgs,
+    Opaque,
 }
 
 struct RustTy {
@@ -3633,14 +3635,19 @@
         }
     }
 
+    fn new_opaque(ts: proc_macro2::TokenStream) -> Self {
+        Self {
+            ts,
+            annotation: RustTyAnnotation::Opaque,
+        }
+    }
+
     fn new_reference(
         ts: proc_macro2::TokenStream,
         inner: RustTyAnnotation,
     ) -> Self {
         let annotation = match inner {
-            RustTyAnnotation::HasUnusedTemplateArgs => {
-                RustTyAnnotation::HasUnusedTemplateArgs
-            }
+            RustTyAnnotation::HasUnusedTemplateArgs | RustTyAnnotation::Opaque => inner,
             _ => RustTyAnnotation::Reference,
         };
         Self { ts, annotation }
@@ -3651,9 +3658,7 @@
         inner: RustTyAnnotation,
     ) -> Self {
         let annotation = match inner {
-            RustTyAnnotation::HasUnusedTemplateArgs => {
-                RustTyAnnotation::HasUnusedTemplateArgs
-            }
+            RustTyAnnotation::HasUnusedTemplateArgs | RustTyAnnotation::Opaque => inner,
             _ => RustTyAnnotation::RValueReference,
         };
         Self { ts, annotation }
@@ -4886,8 +4891,8 @@
                 super::RustTyAnnotation::RValueReference => {
                     semantic_annotation.ret_type_rvalue_reference()
                 }
-                super::RustTyAnnotation::HasUnusedTemplateArgs => {
-                    semantic_annotation.unused_template_param_in_arg_or_return()
+                super::RustTyAnnotation::HasUnusedTemplateArgs | super::RustTyAnnotation::Opaque => {
+                    semantic_annotation.incomprehensible_param_in_arg_or_return()
                 }
             };
             (
@@ -4970,8 +4975,8 @@
                     RustTyAnnotation::RValueReference => {
                         semantic_annotation.arg_type_rvalue_reference(&arg_name)
                     }
-                    RustTyAnnotation::HasUnusedTemplateArgs => {
-                        semantic_annotation.unused_template_param_in_arg_or_return()
+                    RustTyAnnotation::HasUnusedTemplateArgs | RustTyAnnotation::Opaque => {
+                        semantic_annotation.incomprehensible_param_in_arg_or_return()
                     }
                 };
 
diff --git a/third_party/rust/autocxx_bindgen/v0_59/crate/src/options.rs b/third_party/rust/autocxx_bindgen/v0_59/crate/src/options.rs
index b10937a..144f9ac1 100644
--- a/third_party/rust/autocxx_bindgen/v0_59/crate/src/options.rs
+++ b/third_party/rust/autocxx_bindgen/v0_59/crate/src/options.rs
@@ -535,6 +535,15 @@
             Arg::with_name("explicit-padding")
                 .long("explicit-padding")
                 .help("Always output explicit padding fields."),
+            Arg::with_name("use-specific-virtual-function-receiver")
+                .long("use-specific-virtual-function-receiver")
+                .help("Always be specific about the 'receiver' of a virtual function."),
+            Arg::with_name("represent-cxx-operators")
+                .long("represent-cxx-operators")
+                .help("Output C++ overloaded operators"),
+            Arg::with_name("cpp-semantic-attributes")
+                .long("cpp-semantic-attributes")
+                .help("Output additional attributes denoting the intended semantics of each C++ function and type. Useful for downstream code generators."),
         ]) // .args()
         .get_matches_from(args);
 
@@ -995,6 +1004,14 @@
         builder = builder.explicit_padding(true);
     }
 
+    if matches.is_present("use-specific-virtual-function-receiver") {
+        builder = builder.use_specific_virtual_function_receiver(true);
+    }
+
+    if matches.is_present("represent-cxx-operators") {
+        builder = builder.represent_cxx_operators(true);
+    }
+
     if matches.is_present("cpp-semantic-attributes") {
         builder = builder.cpp_semantic_attributes(true);
     }
diff --git a/third_party/rust/autocxx_engine/v0_17/README.chromium b/third_party/rust/autocxx_engine/v0_17/README.chromium
index cad75921..7b1bb46 100644
--- a/third_party/rust/autocxx_engine/v0_17/README.chromium
+++ b/third_party/rust/autocxx_engine/v0_17/README.chromium
@@ -1,6 +1,6 @@
 Name: autocxx-engine
 URL: https://crates.io/crates/autocxx-engine
 Description: Safe autogenerated interop between Rust and C++
-Version: 0.17.2
+Version: 0.17.4
 Security Critical: yes
 License: Apache 2.0
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/.cargo_vcs_info.json b/third_party/rust/autocxx_engine/v0_17/crate/.cargo_vcs_info.json
index a34c1ec6..7266eda 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/.cargo_vcs_info.json
+++ b/third_party/rust/autocxx_engine/v0_17/crate/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "5bb748878f97f854bffa61e5a7cd8ebf970f3dcd"
+    "sha1": "616796cc31322ff782c938dfccc330961fda72a2"
   },
   "path_in_vcs": "engine"
 }
\ No newline at end of file
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/Cargo.toml b/third_party/rust/autocxx_engine/v0_17/crate/Cargo.toml
index 1d0bc25..9aca964b 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/Cargo.toml
+++ b/third_party/rust/autocxx_engine/v0_17/crate/Cargo.toml
@@ -12,7 +12,7 @@
 [package]
 edition = "2021"
 name = "autocxx-engine"
-version = "0.17.2"
+version = "0.17.4"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 description = "Safe autogenerated interop between Rust and C++"
 keywords = ["ffi"]
@@ -34,10 +34,10 @@
 version = "0.1"
 
 [dependencies.autocxx-bindgen]
-version = "=0.59.13"
+version = "=0.59.14"
 
 [dependencies.autocxx-parser]
-version = "=0.17.2"
+version = "=0.17.4"
 
 [dependencies.cc]
 version = "1.0"
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/Cargo.toml.orig b/third_party/rust/autocxx_engine/v0_17/crate/Cargo.toml.orig
index 311214a..dfe12e0b 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/Cargo.toml.orig
+++ b/third_party/rust/autocxx_engine/v0_17/crate/Cargo.toml.orig
@@ -8,7 +8,7 @@
 
 [package]
 name = "autocxx-engine"
-version = "0.17.2"
+version = "0.17.4"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 license = "MIT OR Apache-2.0"
 description = "Safe autogenerated interop between Rust and C++"
@@ -30,7 +30,7 @@
 proc-macro2 = "1.0.11"
 quote = "1.0"
 indoc = "1.0"
-autocxx-bindgen = "=0.59.13"
+autocxx-bindgen = "=0.59.14"
 #autocxx-bindgen = { git = "https://github.com/adetaylor/rust-bindgen", branch = "denote-deleted-move-constructors" }
 itertools = "0.10.3"
 cc = { version = "1.0", optional = true }
@@ -38,7 +38,7 @@
 # There can be interdependencies between the code generated by cxx-gen and
 # what cxx expects to be there.
 cxx-gen = "0.7.54"
-autocxx-parser = { version = "=0.17.2", path="../parser" }
+autocxx-parser = { version = "=0.17.4", path="../parser" }
 version_check = "0.9"
 aquamarine = "0.1" # docs
 tempfile = "3.1"
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/src/ast_discoverer.rs b/third_party/rust/autocxx_engine/v0_17/crate/src/ast_discoverer.rs
index 7374a51..87324dbb 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/src/ast_discoverer.rs
+++ b/third_party/rust/autocxx_engine/v0_17/crate/src/ast_discoverer.rs
@@ -516,7 +516,7 @@
     fn test_extern_rust_fun() {
         let mut discoveries = Discoveries::default();
         let itm = parse_quote! {
-            #[autocxx::extern_rust::extern_rust_fun]
+            #[autocxx::extern_rust::extern_rust_function]
             fn bar(a: cxx::UniquePtr<ffi::xxx>) {
             }
         };
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/allocators.rs b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/allocators.rs
index f796de7..c0bfe27a 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/allocators.rs
+++ b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/allocators.rs
@@ -72,7 +72,7 @@
                 name: api_name,
                 fun: Box::new(FuncToConvert {
                     ident,
-                    doc_attr: None,
+                    doc_attrs: Vec::new(),
                     inputs,
                     output,
                     vis: parse_quote! { pub },
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/casts.rs b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/casts.rs
index 330430f..7325abb 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/casts.rs
+++ b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/casts.rs
@@ -93,7 +93,7 @@
         name: ApiName::new_from_qualified_name(name),
         fun: Box::new(crate::conversion::api::FuncToConvert {
             ident,
-            doc_attr: None,
+            doc_attrs: Vec::new(),
             inputs: [fnarg].into_iter().collect(),
             output: parse_quote! {
                 -> * #return_mutability #to_typ
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/doc_label.rs b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/doc_label.rs
new file mode 100644
index 0000000..767da87
--- /dev/null
+++ b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/doc_label.rs
@@ -0,0 +1,17 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use proc_macro2::Span;
+use syn::{parse_quote, Attribute};
+
+pub(crate) fn make_doc_attrs(label: String) -> Vec<Attribute> {
+    let hexathorpe = syn::token::Pound(Span::call_site());
+    vec![parse_quote! {
+        #hexathorpe [doc = #label]
+    }]
+}
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/fun/implicit_constructors.rs b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/fun/implicit_constructors.rs
index a0356ca..975afbc 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/fun/implicit_constructors.rs
+++ b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/fun/implicit_constructors.rs
@@ -6,7 +6,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::collections::{hash_map, HashMap};
+use std::collections::{hash_map, HashMap, HashSet};
 
 use syn::Type;
 
@@ -15,6 +15,8 @@
         analysis::{depth_first::depth_first, pod::PodAnalysis, type_converter::TypeKind},
         api::{Api, ApiName, CppVisibility, FuncToConvert, SpecialMemberKind},
         apivec::ApiVec,
+        convert_error::ConvertErrorWithContext,
+        ConvertError,
     },
     known_types::{known_types, KnownTypeConstructorDetails},
     types::QualifiedName,
@@ -173,7 +175,7 @@
 pub(super) fn find_constructors_present(
     apis: &ApiVec<FnPrePhase1>,
 ) -> HashMap<QualifiedName, ItemsFound> {
-    let explicits = find_explicit_items(apis);
+    let (explicits, unknown_types) = find_explicit_items(apis);
 
     // These contain all the classes we've seen so far with the relevant properties on their
     // constructors of each kind. We iterate via [`depth_first`], so analyzing later classes
@@ -248,6 +250,7 @@
             // unique_ptrs etc.
             let items_found = if bases_items_found.len() != bases.len()
                 || fields_items_found.len() != field_info.len()
+                || unknown_types.contains(&name.name)
             {
                 let is_explicit = |kind: ExplicitKind| -> SpecialMemberFound {
                     // TODO: For https://github.com/google/autocxx/issues/815, map
@@ -532,7 +535,9 @@
     all_items_found
 }
 
-fn find_explicit_items(apis: &ApiVec<FnPrePhase1>) -> HashMap<ExplicitType, ExplicitFound> {
+fn find_explicit_items(
+    apis: &ApiVec<FnPrePhase1>,
+) -> (HashMap<ExplicitType, ExplicitFound>, HashSet<QualifiedName>) {
     let mut result = HashMap::new();
     let mut merge_fun = |ty: QualifiedName, kind: ExplicitKind, fun: &FuncToConvert| match result
         .entry(ExplicitType { ty, kind })
@@ -548,6 +553,7 @@
             entry.insert(ExplicitFound::Multiple);
         }
     };
+    let mut unknown_types = HashSet::new();
     for api in apis.iter() {
         match api {
             Api::Function {
@@ -555,6 +561,8 @@
                     FnAnalysis {
                         kind: FnKind::Method { impl_for, .. },
                         param_details,
+                        ignore_reason:
+                            Ok(()) | Err(ConvertErrorWithContext(ConvertError::AssignmentOperator, _)),
                         ..
                     },
                 fun,
@@ -591,6 +599,21 @@
             Api::Function {
                 analysis:
                     FnAnalysis {
+                        kind: FnKind::Method { impl_for, .. },
+                        ..
+                    },
+                fun,
+                ..
+            } if matches!(
+                fun.special_member,
+                Some(SpecialMemberKind::AssignmentOperator)
+            ) =>
+            {
+                unknown_types.insert(impl_for.clone());
+            }
+            Api::Function {
+                analysis:
+                    FnAnalysis {
                         kind:
                             FnKind::Method {
                                 impl_for,
@@ -635,7 +658,7 @@
             _ => (),
         }
     }
-    result
+    (result, unknown_types)
 }
 
 /// Returns the information for a given known type.
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/fun/mod.rs b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/fun/mod.rs
index f22f749..5b256cf 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/fun/mod.rs
+++ b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/fun/mod.rs
@@ -63,6 +63,7 @@
 };
 
 use super::{
+    doc_label::make_doc_attrs,
     pod::{PodAnalysis, PodPhase},
     tdef::TypedefAnalysis,
     type_converter::Annotated,
@@ -1083,10 +1084,22 @@
             CppVisibility::Protected => false,
             CppVisibility::Public => true,
         };
-        if matches!(
+        if let Some(problem) = bads.into_iter().next() {
+            match problem {
+                Ok(_) => panic!("No error in the error"),
+                Err(problem) => set_ignore_reason(problem),
+            }
+        } else if fun.unused_template_param {
+            // This indicates that bindgen essentially flaked out because templates
+            // were too complex.
+            set_ignore_reason(ConvertError::UnusedTemplateParam)
+        } else if matches!(
             fun.special_member,
             Some(SpecialMemberKind::AssignmentOperator)
         ) {
+            // Be careful with the order of this if-else tree. Anything above here means we won't
+            // treat it as an assignment operator, but anything below we still consider when
+            // deciding which other C++ special member functions are implicitly defined.
             set_ignore_reason(ConvertError::AssignmentOperator)
         } else if fun.references.rvalue_ref_return {
             set_ignore_reason(ConvertError::RValueReturn)
@@ -1102,15 +1115,6 @@
             )
         {
             set_ignore_reason(ConvertError::RValueParam)
-        } else if let Some(problem) = bads.into_iter().next() {
-            match problem {
-                Ok(_) => panic!("No error in the error"),
-                Err(problem) => set_ignore_reason(problem),
-            }
-        } else if fun.unused_template_param {
-            // This indicates that bindgen essentially flaked out because templates
-            // were too complex.
-            set_ignore_reason(ConvertError::UnusedTemplateParam)
         } else {
             match kind {
                 FnKind::Method {
@@ -1930,7 +1934,7 @@
                     Box::new(FuncToConvert {
                         self_ty: Some(self_ty.clone()),
                         ident,
-                        doc_attr: None,
+                        doc_attrs: make_doc_attrs(format!("Synthesized {}.", special_member)),
                         inputs,
                         output: ReturnType::Default,
                         vis: parse_quote! { pub },
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/fun/subclass.rs b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/fun/subclass.rs
index 3bde56a..8d5bddd 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/fun/subclass.rs
+++ b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/fun/subclass.rs
@@ -55,7 +55,7 @@
         synthesized_this_type: self_ty.clone(),
         self_ty,
         ident: super_fn_name.get_final_ident(),
-        doc_attr: fun.doc_attr.clone(),
+        doc_attrs: fun.doc_attrs.clone(),
         inputs: fun.inputs.clone(),
         output: fun.output.clone(),
         vis: fun.vis.clone(),
@@ -221,7 +221,7 @@
         .collect();
     let maybe_wrap = Box::new(FuncToConvert {
         ident: subclass_constructor_name.clone(),
-        doc_attr: fun.doc_attr.clone(),
+        doc_attrs: fun.doc_attrs.clone(),
         inputs,
         output: fun.output.clone(),
         vis: fun.vis.clone(),
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/mod.rs b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/mod.rs
index a4abe099..bb1fb1ac 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/mod.rs
+++ b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/mod.rs
@@ -13,6 +13,7 @@
 pub(crate) mod ctypes;
 pub(crate) mod deps;
 mod depth_first;
+mod doc_label;
 pub(crate) mod fun;
 pub(crate) mod gc;
 mod name_check;
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/type_converter.rs b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/type_converter.rs
index 1112a51..3f8aac47 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/type_converter.rs
+++ b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/analysis/type_converter.rs
@@ -445,8 +445,8 @@
                 };
                 let api = UnanalyzedApi::ConcreteType {
                     name: ApiName::new_in_root_namespace(make_ident(&synthetic_ident)),
-                    rs_definition: Box::new(rs_definition.clone()),
                     cpp_definition: cpp_definition.clone(),
+                    rs_definition: Some(Box::new(rs_definition.clone())),
                 };
                 self.concrete_templates
                     .insert(cpp_definition, api.name().clone());
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/api.rs b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/api.rs
index 7eb8ac67..c333f22 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/api.rs
+++ b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/api.rs
@@ -6,7 +6,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::collections::HashSet;
+use std::{collections::HashSet, fmt::Display};
 
 use crate::types::{make_ident, Namespace, QualifiedName};
 use autocxx_parser::RustPath;
@@ -202,6 +202,22 @@
     AssignmentOperator,
 }
 
+impl Display for SpecialMemberKind {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(
+            f,
+            "{}",
+            match self {
+                SpecialMemberKind::DefaultConstructor => "default constructor",
+                SpecialMemberKind::CopyConstructor => "copy constructor",
+                SpecialMemberKind::MoveConstructor => "move constructor",
+                SpecialMemberKind::Destructor => "destructor",
+                SpecialMemberKind::AssignmentOperator => "assignment operator",
+            }
+        )
+    }
+}
+
 #[derive(Clone)]
 pub(crate) enum Provenance {
     Bindgen,
@@ -224,7 +240,7 @@
 pub(crate) struct FuncToConvert {
     pub(crate) provenance: Provenance,
     pub(crate) ident: Ident,
-    pub(crate) doc_attr: Option<Attribute>,
+    pub(crate) doc_attrs: Vec<Attribute>,
     pub(crate) inputs: Punctuated<FnArg, Comma>,
     pub(crate) output: ReturnType,
     pub(crate) vis: Visibility,
@@ -420,7 +436,7 @@
     /// concretize some templated C++ type.
     ConcreteType {
         name: ApiName,
-        rs_definition: Box<Type>,
+        rs_definition: Option<Box<Type>>,
         cpp_definition: String,
     },
     /// A simple note that we want to make a constructor for
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/codegen_cpp/mod.rs b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/codegen_cpp/mod.rs
index a60adc7..278aa5d 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/codegen_cpp/mod.rs
+++ b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/codegen_cpp/mod.rs
@@ -17,7 +17,10 @@
 };
 use autocxx_parser::IncludeCppConfig;
 use itertools::Itertools;
-use std::collections::{HashMap, HashSet};
+use std::{
+    borrow::Cow,
+    collections::{HashMap, HashSet},
+};
 use type_to_cpp::{original_name_map_from_apis, type_to_cpp, CppNameMap};
 
 use self::type_to_cpp::{
@@ -167,10 +170,20 @@
                     }
                     self.generate_cpp_function(cpp_wrapper)?
                 }
-                Api::ConcreteType { rs_definition, .. } => self.generate_typedef(
-                    api.name(),
-                    type_to_cpp(rs_definition, &self.original_name_map)?,
-                ),
+                Api::ConcreteType {
+                    rs_definition,
+                    cpp_definition,
+                    ..
+                } => {
+                    let effective_cpp_definition = match rs_definition {
+                        Some(rs_definition) => {
+                            Cow::Owned(type_to_cpp(rs_definition, &self.original_name_map)?)
+                        }
+                        None => Cow::Borrowed(cpp_definition),
+                    };
+
+                    self.generate_typedef(api.name(), &effective_cpp_definition)
+                }
                 Api::CType { typename, .. } => self.generate_ctype_typedef(typename),
                 Api::Subclass { .. } => deferred_apis.push(api),
                 Api::RustSubclassFn {
@@ -582,10 +595,10 @@
 
     fn generate_ctype_typedef(&mut self, tn: &QualifiedName) {
         let cpp_name = tn.to_cpp_name();
-        self.generate_typedef(tn, cpp_name)
+        self.generate_typedef(tn, &cpp_name)
     }
 
-    fn generate_typedef(&mut self, tn: &QualifiedName, definition: String) {
+    fn generate_typedef(&mut self, tn: &QualifiedName, definition: &str) {
         let our_name = tn.get_final_item();
         self.additional_functions.push(AdditionalFunction {
             type_definition: Some(format!("typedef {} {};", definition, our_name)),
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/codegen_rs/fun_codegen.rs b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/codegen_rs/fun_codegen.rs
index 8ce6166..b2538b75 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/codegen_rs/fun_codegen.rs
+++ b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/codegen_rs/fun_codegen.rs
@@ -29,7 +29,7 @@
             TraitMethodDetails,
         },
         api::UnsafetyNeeded,
-        codegen_rs::lifetime::add_lifetime_to_all_params,
+        codegen_rs::lifetime::add_lifetime_to_all_reference_params,
     },
     types::{Namespace, QualifiedName},
 };
@@ -97,7 +97,7 @@
     let params = analysis.params;
     let vis = analysis.vis;
     let kind = analysis.kind;
-    let doc_attr = fun.doc_attr;
+    let doc_attrs = fun.doc_attrs;
 
     let mut cpp_name_attr = Vec::new();
     let mut impl_entry = None;
@@ -113,7 +113,7 @@
         rust_name,
         unsafety: &analysis.requires_unsafe,
         always_unsafe_due_to_trait_definition,
-        doc_attr: &doc_attr,
+        doc_attrs: &doc_attrs,
         non_pod_types,
     };
     // In rare occasions, we might need to give an explicit lifetime.
@@ -202,7 +202,7 @@
     let extern_c_mod_item = ForeignItem::Fn(parse_quote!(
         #(#namespace_attr)*
         #(#cpp_name_attr)*
-        #doc_attr
+        #(#doc_attrs)*
         #vis #bridge_unsafety fn #cxxbridge_name #lifetime_tokens ( #params ) #ret_type;
     ));
     RsCodegenResult {
@@ -223,7 +223,7 @@
     rust_name: &'a str,
     unsafety: &'a UnsafetyNeeded,
     always_unsafe_due_to_trait_definition: bool,
-    doc_attr: &'a Option<Attribute>,
+    doc_attrs: &'a Vec<Attribute>,
     non_pod_types: &'a HashSet<QualifiedName>,
 }
 
@@ -231,7 +231,7 @@
     fn generate_arg_lists(
         &self,
         avoid_self: bool,
-    ) -> (Punctuated<FnArg, Comma>, Vec<TokenStream>, Vec<TokenStream>) {
+    ) -> (Punctuated<FnArg, Comma>, TokenStream, Vec<TokenStream>) {
         let mut wrapper_params: Punctuated<FnArg, Comma> = Punctuated::new();
         let mut local_variables = Vec::new();
         let mut arg_list = Vec::new();
@@ -253,6 +253,7 @@
             arg_list.push(actual_arg);
             local_variables.extend(local_variable.into_iter());
         }
+        let local_variables = quote! { #(#local_variables);* };
         (wrapper_params, local_variables, arg_list)
     }
 
@@ -272,16 +273,16 @@
         );
         let rust_name = make_ident(self.rust_name);
         let unsafety = self.unsafety.wrapper_token();
-        let doc_attr = self.doc_attr;
+        let doc_attrs = self.doc_attrs;
         let cxxbridge_name = self.cxxbridge_name;
         let call_body = self.wrap_call_with_unsafe(quote! {
             cxxbridge::#cxxbridge_name ( #(#arg_list),* )
         });
         Box::new(ImplBlockDetails {
             item: ImplItem::Method(parse_quote! {
-                #doc_attr
+                #(#doc_attrs)*
                 pub #unsafety fn #rust_name #lifetime_tokens ( #wrapper_params ) #ret_type {
-                    #(#local_variables),*
+                    #local_variables
                     #call_body
                 }
             }),
@@ -306,7 +307,7 @@
             ret_type,
             self.non_pod_types,
         );
-        let doc_attr = self.doc_attr;
+        let doc_attrs = self.doc_attrs;
         let unsafety = self.unsafety.wrapper_token();
         let cxxbridge_name = self.cxxbridge_name;
         let key = details.trt.clone();
@@ -315,9 +316,9 @@
             cxxbridge::#cxxbridge_name ( #(#arg_list),* )
         });
         let item = parse_quote! {
-            #doc_attr
+            #(#doc_attrs)*
             #unsafety fn #method_name #lifetime_tokens ( #wrapper_params ) #ret_type {
-                #(#local_variables),*
+                #local_variables
                 #call_body
             }
         };
@@ -354,25 +355,25 @@
         let rust_name = make_ident(&self.rust_name);
         let any_references = self.param_details.iter().any(|pd| pd.was_reference);
         let (lifetime_param, lifetime_addition) = if any_references {
-            add_lifetime_to_all_params(&mut wrapper_params);
+            add_lifetime_to_all_reference_params(&mut wrapper_params);
             (quote! { <'a> }, quote! { + 'a })
         } else {
             (quote! {}, quote! {})
         };
         let cxxbridge_name = self.cxxbridge_name;
         let body = quote! {
-            #(#local_variables),*
+            #local_variables
             autocxx::moveit::new::by_raw(move |#ptr_arg_name| {
                 let #ptr_arg_name = #ptr_arg_name.get_unchecked_mut().as_mut_ptr();
                 cxxbridge::#cxxbridge_name(#(#arg_list),* )
             })
         };
         let body = self.wrap_call_with_unsafe(body);
-        let doc_attr = self.doc_attr;
+        let doc_attrs = self.doc_attrs;
         let unsafety = self.unsafety.wrapper_token();
         Box::new(ImplBlockDetails {
             item: ImplItem::Method(parse_quote! {
-                #doc_attr
+                #(#doc_attrs)*
                 pub #unsafety fn #rust_name #lifetime_param ( #wrapper_params ) -> impl autocxx::moveit::new::New<Output=Self> #lifetime_addition {
                     #body
                 }
@@ -385,16 +386,16 @@
     fn generate_function_impl(&self, ret_type: &ReturnType) -> Item {
         let (wrapper_params, local_variables, arg_list) = self.generate_arg_lists(false);
         let rust_name = make_ident(self.rust_name);
-        let doc_attr = self.doc_attr;
+        let doc_attrs = self.doc_attrs;
         let unsafety = self.unsafety.wrapper_token();
         let cxxbridge_name = self.cxxbridge_name;
         let body = self.wrap_call_with_unsafe(quote! {
             cxxbridge::#cxxbridge_name ( #(#arg_list),* )
         });
         Item::Fn(parse_quote! {
-            #doc_attr
+            #(#doc_attrs)*
             pub #unsafety fn #rust_name ( #wrapper_params ) #ret_type {
-                #(#local_variables),*
+                #local_variables
                 #body
             }
         })
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/codegen_rs/lifetime.rs b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/codegen_rs/lifetime.rs
index 1693d04..742f51e0 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/codegen_rs/lifetime.rs
+++ b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/codegen_rs/lifetime.rs
@@ -164,14 +164,19 @@
     tyr.lifetime = Some(parse_quote! { 'a })
 }
 
-pub(crate) fn add_lifetime_to_all_params(params: &mut Punctuated<FnArg, Comma>) {
+pub(crate) fn add_lifetime_to_all_reference_params(params: &mut Punctuated<FnArg, Comma>) {
     for mut param in params.iter_mut() {
         match &mut param {
             FnArg::Typed(PatType { ty, .. }) => match ty.as_mut() {
                 Type::Path(TypePath {
                     path: Path { segments, .. },
                     ..
-                }) => add_lifetime_to_pinned_reference(segments).unwrap(),
+                }) => {
+                    // This function will check whether this path is a pinned reference and if
+                    // so, add a lifetime to it. Otherwise, it will return an error - which
+                    // we ignore.
+                    add_lifetime_to_pinned_reference(segments).unwrap_or_default()
+                }
                 Type::Reference(tyr) => add_lifetime_to_reference(tyr),
                 _ => {}
             },
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/codegen_rs/mod.rs b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/codegen_rs/mod.rs
index 78c48cf..eda1e37e 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/codegen_rs/mod.rs
+++ b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/codegen_rs/mod.rs
@@ -31,7 +31,7 @@
             non_pod_struct::{make_non_pod, new_non_pod_struct},
             unqualify::{unqualify_params, unqualify_ret_type},
         },
-        doc_attr::get_doc_attr,
+        doc_attr::get_doc_attrs,
     },
     types::{make_ident, Namespace, QualifiedName},
 };
@@ -58,7 +58,7 @@
     },
 };
 use super::{convert_error::ErrorContext, ConvertError};
-use quote::{quote, ToTokens};
+use quote::quote;
 
 /// An entry which needs to go into an `impl` block for a given type.
 struct ImplBlockDetails {
@@ -503,7 +503,7 @@
             Api::Struct {
                 details, analysis, ..
             } => {
-                let doc_attr = get_doc_attr(&details.item.attrs);
+                let doc_attrs = get_doc_attrs(&details.item.attrs);
                 let layout = details.layout.clone();
                 self.generate_type(
                     &name,
@@ -511,20 +511,20 @@
                     analysis.pod.kind,
                     analysis.constructors.move_constructor,
                     analysis.constructors.destructor,
-                    || Some((Item::Struct(details.item), doc_attr)),
+                    || Some((Item::Struct(details.item), doc_attrs)),
                     associated_methods,
                     layout,
                 )
             }
             Api::Enum { item, .. } => {
-                let doc_attr = get_doc_attr(&item.attrs);
+                let doc_attrs = get_doc_attrs(&item.attrs);
                 self.generate_type(
                     &name,
                     id,
                     TypeKind::Pod,
                     true,
                     true,
-                    || Some((Item::Enum(item), doc_attr)),
+                    || Some((Item::Enum(item), doc_attrs)),
                     associated_methods,
                     None,
                 )
@@ -619,7 +619,7 @@
             },
         ];
         let mut extern_c_mod_items = vec![
-            self.generate_cxxbridge_type(&full_cpp, false, None),
+            self.generate_cxxbridge_type(&full_cpp, false, Vec::new()),
             parse_quote! {
                 fn #relinquish_ownership_call(self: &#cpp_id);
             },
@@ -803,10 +803,10 @@
         layout: Option<Layout>,
     ) -> RsCodegenResult
     where
-        F: FnOnce() -> Option<(Item, Option<Attribute>)>,
+        F: FnOnce() -> Option<(Item, Vec<Attribute>)>,
     {
         let mut bindgen_mod_items = Vec::new();
-        let mut materializations = vec![Use::UsedFromCxxBridge];
+        let mut materializations = vec![Use::UsedFromBindgen];
         Self::add_superclass_stuff_to_type(
             name,
             &mut bindgen_mod_items,
@@ -814,6 +814,10 @@
             associated_methods.get(name),
         );
         let orig_item = item_creator();
+        let doc_attrs = orig_item
+            .as_ref()
+            .map(|maybe_item| maybe_item.1.clone())
+            .unwrap_or_default();
         // We have a choice here to either:
         // a) tell cxx to generate an opaque type using 'type A;'
         // b) generate a concrete type definition, e.g. by using bindgen's
@@ -842,10 +846,11 @@
                     }
                 }
                 bindgen_mod_items.push(item);
+
                 RsCodegenResult {
                     global_items: self.generate_extern_type_impl(type_kind, name),
                     bridge_items: create_impl_items(&id, movable, destroyable, self.config),
-                    extern_c_mod_items: vec![self.generate_cxxbridge_type(name, true, None)],
+                    extern_c_mod_items: vec![self.generate_cxxbridge_type(name, true, doc_attrs)],
                     bindgen_mod_items,
                     materializations,
                     ..Default::default()
@@ -856,9 +861,8 @@
                 // We MUST do this because otherwise cxx assumes this can be
                 // instantiated using UniquePtr etc.
                 bindgen_mod_items.push(Item::Use(parse_quote! { pub use cxxbridge::#id; }));
-                let doc_attr = orig_item.and_then(|maybe_item| maybe_item.1);
                 RsCodegenResult {
-                    extern_c_mod_items: vec![self.generate_cxxbridge_type(name, false, doc_attr)],
+                    extern_c_mod_items: vec![self.generate_cxxbridge_type(name, false, doc_attrs)],
                     bindgen_mod_items,
                     materializations,
                     ..Default::default()
@@ -1026,7 +1030,7 @@
         &self,
         name: &QualifiedName,
         references_bindgen: bool,
-        doc_attr: Option<Attribute>,
+        doc_attrs: Vec<Attribute>,
     ) -> ForeignItem {
         let ns = name.get_namespace();
         let id = name.get_final_ident();
@@ -1057,9 +1061,9 @@
             });
         }
 
-        if let Some(doc_attr) = doc_attr {
-            doc_attr.to_tokens(&mut for_extern_c_ts);
-        }
+        for_extern_c_ts.extend(quote! {
+            #(#doc_attrs)*
+        });
 
         if references_bindgen {
             for_extern_c_ts.extend(quote! {
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/doc_attr.rs b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/doc_attr.rs
index 685207e7..8fe9d0ba 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/doc_attr.rs
+++ b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/doc_attr.rs
@@ -9,9 +9,10 @@
 use syn::Attribute;
 
 /// Returns the attribute (if any) which contains a doc comment.
-pub(super) fn get_doc_attr(attrs: &[Attribute]) -> Option<Attribute> {
+pub(super) fn get_doc_attrs(attrs: &[Attribute]) -> Vec<Attribute> {
     attrs
         .iter()
-        .find(|a| a.path.get_ident().iter().any(|p| *p == "doc"))
+        .filter(|a| a.path.get_ident().iter().any(|p| *p == "doc"))
         .cloned()
+        .collect()
 }
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/parse/parse_bindgen.rs b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/parse/parse_bindgen.rs
index c56e4ae..90101d6 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/parse/parse_bindgen.rs
+++ b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/parse/parse_bindgen.rs
@@ -106,6 +106,19 @@
                 path: path.clone(),
             }
         }));
+        self.apis.extend(
+            self.config
+                .concretes
+                .iter()
+                .map(|(cpp_definition, rust_id)| {
+                    let name = ApiName::new_in_root_namespace(rust_id.clone());
+                    Api::ConcreteType {
+                        name,
+                        cpp_definition: cpp_definition.clone(),
+                        rs_definition: None,
+                    }
+                }),
+        );
     }
 
     fn find_items_in_root(items: Vec<Item>) -> Result<Vec<Item>, ConvertError> {
diff --git a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/parse/parse_foreign_mod.rs b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/parse/parse_foreign_mod.rs
index 3f7855f..97b4f01 100644
--- a/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/parse/parse_foreign_mod.rs
+++ b/third_party/rust/autocxx_engine/v0_17/crate/src/conversion/parse/parse_foreign_mod.rs
@@ -8,7 +8,7 @@
 
 use crate::conversion::api::{ApiName, NullPhase, Provenance};
 use crate::conversion::apivec::ApiVec;
-use crate::conversion::doc_attr::get_doc_attr;
+use crate::conversion::doc_attr::get_doc_attrs;
 use crate::conversion::error_reporter::report_any_error;
 use crate::conversion::{
     api::{FuncToConvert, UnanalyzedApi},
@@ -68,12 +68,12 @@
         match i {
             ForeignItem::Fn(item) => {
                 let annotations = BindgenSemanticAttributes::new(&item.attrs);
-                let doc_attr = get_doc_attr(&item.attrs);
+                let doc_attrs = get_doc_attrs(&item.attrs);
                 self.funcs_to_convert.push(FuncToConvert {
                     provenance: Provenance::Bindgen,
                     self_ty: None,
                     ident: item.sig.ident,
-                    doc_attr,
+                    doc_attrs,
                     inputs: item.sig.inputs,
                     output: item.sig.output,
                     vis: item.vis,
@@ -81,7 +81,7 @@
                     cpp_vis: annotations.get_cpp_visibility(),
                     special_member: annotations.special_member_kind(),
                     unused_template_param: annotations
-                        .has_attr("unused_template_param_in_arg_or_return"),
+                        .has_attr("incomprehensible_param_in_arg_or_return"),
                     references: annotations.get_reference_parameters_and_return(),
                     original_name: annotations.get_original_name(),
                     synthesized_this_type: None,
diff --git a/third_party/rust/autocxx_gen/v0_17/README.chromium b/third_party/rust/autocxx_gen/v0_17/README.chromium
index 063d33e9..f17262a 100644
--- a/third_party/rust/autocxx_gen/v0_17/README.chromium
+++ b/third_party/rust/autocxx_gen/v0_17/README.chromium
@@ -1,6 +1,6 @@
 Name: autocxx-gen
 URL: https://crates.io/crates/autocxx-gen
 Description: Safe autogenerated interop between Rust and C++
-Version: 0.17.2
+Version: 0.17.4
 Security Critical: yes
 License: Apache 2.0
diff --git a/third_party/rust/autocxx_gen/v0_17/crate/.cargo_vcs_info.json b/third_party/rust/autocxx_gen/v0_17/crate/.cargo_vcs_info.json
index 3c793de0..148e5ca 100644
--- a/third_party/rust/autocxx_gen/v0_17/crate/.cargo_vcs_info.json
+++ b/third_party/rust/autocxx_gen/v0_17/crate/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "5bb748878f97f854bffa61e5a7cd8ebf970f3dcd"
+    "sha1": "616796cc31322ff782c938dfccc330961fda72a2"
   },
   "path_in_vcs": "gen/cmd"
 }
\ No newline at end of file
diff --git a/third_party/rust/autocxx_gen/v0_17/crate/Cargo.lock b/third_party/rust/autocxx_gen/v0_17/crate/Cargo.lock
index e5785f6..5d48236 100644
--- a/third_party/rust/autocxx_gen/v0_17/crate/Cargo.lock
+++ b/third_party/rust/autocxx_gen/v0_17/crate/Cargo.lock
@@ -60,9 +60,9 @@
 
 [[package]]
 name = "autocxx-bindgen"
-version = "0.59.13"
+version = "0.59.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e603c1eb79e21068072ef990e5463f613e0cedddd6712ff11afeae2a90b2510"
+checksum = "f4b4fda7f511ff4d9e685464d622da8b76661d719869fdfa5f64d0c6f8657416"
 dependencies = [
  "bitflags",
  "cexpr",
@@ -84,9 +84,9 @@
 
 [[package]]
 name = "autocxx-engine"
-version = "0.17.2"
+version = "0.17.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66906a5d5167cb933a8faf70a9dd27ebb7f8f68d77054766bc9cf05582d3ac51"
+checksum = "4ee192e5ac1f0c3363759c3229b8f2abe39470e4301ff7c52d3385a79c42c67d"
 dependencies = [
  "aquamarine",
  "autocxx-bindgen",
@@ -107,7 +107,7 @@
 
 [[package]]
 name = "autocxx-gen"
-version = "0.17.2"
+version = "0.17.4"
 dependencies = [
  "assert_cmd",
  "autocxx-engine",
@@ -120,9 +120,9 @@
 
 [[package]]
 name = "autocxx-parser"
-version = "0.17.2"
+version = "0.17.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "688d5eadba022940ccca017a3aa83edd5d1d7acc8ba23c322d0cec1e4ed4afc0"
+checksum = "bd6b77385199cb2bbd19a37bcb2ea94cdd3670964575788046ea767016b80da6"
 dependencies = [
  "log",
  "proc-macro2",
@@ -341,9 +341,9 @@
 
 [[package]]
 name = "libc"
-version = "0.2.120"
+version = "0.2.121"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad5c14e80759d0939d013e6ca49930e59fc53dd8e5009132f76240c179380c09"
+checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
 
 [[package]]
 name = "libloading"
@@ -357,9 +357,9 @@
 
 [[package]]
 name = "log"
-version = "0.4.14"
+version = "0.4.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8"
 dependencies = [
  "cfg-if",
 ]
@@ -460,9 +460,9 @@
 
 [[package]]
 name = "quote"
-version = "1.0.15"
+version = "1.0.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
+checksum = "b4af2ec4714533fcdf07e886f17025ace8b997b9ce51204ee69b6da831c3da57"
 dependencies = [
  "proc-macro2",
 ]
@@ -618,9 +618,9 @@
 
 [[package]]
 name = "syn"
-version = "1.0.88"
+version = "1.0.89"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebd69e719f31e88618baa1eaa6ee2de5c9a1c004f1e9ecdb58e8352a13f20a01"
+checksum = "ea297be220d52398dcc07ce15a209fce436d361735ac1db700cab3b6cdfb9f54"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -716,9 +716,9 @@
 
 [[package]]
 name = "which"
-version = "4.2.4"
+version = "4.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a5a7e487e921cf220206864a94a89b6c6905bfc19f1057fa26a4cb360e5c1d2"
+checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae"
 dependencies = [
  "either",
  "lazy_static",
diff --git a/third_party/rust/autocxx_gen/v0_17/crate/Cargo.toml b/third_party/rust/autocxx_gen/v0_17/crate/Cargo.toml
index bee6b0a..f653c59 100644
--- a/third_party/rust/autocxx_gen/v0_17/crate/Cargo.toml
+++ b/third_party/rust/autocxx_gen/v0_17/crate/Cargo.toml
@@ -12,7 +12,7 @@
 [package]
 edition = "2021"
 name = "autocxx-gen"
-version = "0.17.2"
+version = "0.17.4"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 description = "Safe autogenerated interop between Rust and C++"
 keywords = ["ffi"]
@@ -25,7 +25,7 @@
 resolver = "2"
 
 [dependencies.autocxx-engine]
-version = "=0.17.2"
+version = "=0.17.4"
 
 [dependencies.clap]
 version = "~2.33"
diff --git a/third_party/rust/autocxx_gen/v0_17/crate/Cargo.toml.orig b/third_party/rust/autocxx_gen/v0_17/crate/Cargo.toml.orig
index b299d79..d3bdd0d4 100644
--- a/third_party/rust/autocxx_gen/v0_17/crate/Cargo.toml.orig
+++ b/third_party/rust/autocxx_gen/v0_17/crate/Cargo.toml.orig
@@ -8,7 +8,7 @@
 
 [package]
 name = "autocxx-gen"
-version = "0.17.2"
+version = "0.17.4"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2021"
 license = "MIT OR Apache-2.0"
@@ -22,7 +22,7 @@
 static = [ "autocxx-engine/static" ]
 
 [dependencies]
-autocxx-engine = { version="=0.17.2", path="../../engine" }
+autocxx-engine = { version="=0.17.4", path="../../engine" }
 clap = "~2.33"
 quote = "1.0.7"
 proc-macro2 = "1.0"
diff --git a/third_party/rust/autocxx_macro/v0_17/README.chromium b/third_party/rust/autocxx_macro/v0_17/README.chromium
index e4b2e74..622a613 100644
--- a/third_party/rust/autocxx_macro/v0_17/README.chromium
+++ b/third_party/rust/autocxx_macro/v0_17/README.chromium
@@ -1,6 +1,6 @@
 Name: autocxx-macro
 URL: https://crates.io/crates/autocxx-macro
 Description: Safe autogenerated interop between Rust and C++
-Version: 0.17.2
+Version: 0.17.4
 Security Critical: yes
 License: Apache 2.0
diff --git a/third_party/rust/autocxx_macro/v0_17/crate/.cargo_vcs_info.json b/third_party/rust/autocxx_macro/v0_17/crate/.cargo_vcs_info.json
index ca758e7..db4443b7 100644
--- a/third_party/rust/autocxx_macro/v0_17/crate/.cargo_vcs_info.json
+++ b/third_party/rust/autocxx_macro/v0_17/crate/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "5bb748878f97f854bffa61e5a7cd8ebf970f3dcd"
+    "sha1": "616796cc31322ff782c938dfccc330961fda72a2"
   },
   "path_in_vcs": "macro"
 }
\ No newline at end of file
diff --git a/third_party/rust/autocxx_macro/v0_17/crate/Cargo.toml b/third_party/rust/autocxx_macro/v0_17/crate/Cargo.toml
index ea4aed9..438adf4 100644
--- a/third_party/rust/autocxx_macro/v0_17/crate/Cargo.toml
+++ b/third_party/rust/autocxx_macro/v0_17/crate/Cargo.toml
@@ -12,7 +12,7 @@
 [package]
 edition = "2021"
 name = "autocxx-macro"
-version = "0.17.2"
+version = "0.17.4"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 description = "Safe autogenerated interop between Rust and C++"
 keywords = ["ffi"]
@@ -28,7 +28,7 @@
 proc-macro = true
 
 [dependencies.autocxx-parser]
-version = "=0.17.2"
+version = "=0.17.4"
 
 [dependencies.proc-macro-error]
 version = "1.0"
diff --git a/third_party/rust/autocxx_macro/v0_17/crate/Cargo.toml.orig b/third_party/rust/autocxx_macro/v0_17/crate/Cargo.toml.orig
index b4c21ee..00275550 100644
--- a/third_party/rust/autocxx_macro/v0_17/crate/Cargo.toml.orig
+++ b/third_party/rust/autocxx_macro/v0_17/crate/Cargo.toml.orig
@@ -8,7 +8,7 @@
 
 [package]
 name = "autocxx-macro"
-version = "0.17.2"
+version = "0.17.4"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 license = "MIT OR Apache-2.0"
 description = "Safe autogenerated interop between Rust and C++"
@@ -21,7 +21,7 @@
 proc-macro = true
 
 [dependencies]
-autocxx-parser = { path="../parser", version="=0.17.2" }
+autocxx-parser = { path="../parser", version="=0.17.4" }
 proc-macro-error = "1.0"
 proc-macro2 = "1.0.11"
 quote = "1.0"
diff --git a/third_party/rust/autocxx_parser/v0_17/README.chromium b/third_party/rust/autocxx_parser/v0_17/README.chromium
index 7bf312a..748098e 100644
--- a/third_party/rust/autocxx_parser/v0_17/README.chromium
+++ b/third_party/rust/autocxx_parser/v0_17/README.chromium
@@ -1,6 +1,6 @@
 Name: autocxx-parser
 URL: https://crates.io/crates/autocxx-parser
 Description: Safe autogenerated interop between Rust and C++
-Version: 0.17.2
+Version: 0.17.4
 Security Critical: yes
 License: Apache 2.0
diff --git a/third_party/rust/autocxx_parser/v0_17/crate/.cargo_vcs_info.json b/third_party/rust/autocxx_parser/v0_17/crate/.cargo_vcs_info.json
index f7c92a32..d500615 100644
--- a/third_party/rust/autocxx_parser/v0_17/crate/.cargo_vcs_info.json
+++ b/third_party/rust/autocxx_parser/v0_17/crate/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "5bb748878f97f854bffa61e5a7cd8ebf970f3dcd"
+    "sha1": "616796cc31322ff782c938dfccc330961fda72a2"
   },
   "path_in_vcs": "parser"
 }
\ No newline at end of file
diff --git a/third_party/rust/autocxx_parser/v0_17/crate/Cargo.toml b/third_party/rust/autocxx_parser/v0_17/crate/Cargo.toml
index 0932198..126644e8 100644
--- a/third_party/rust/autocxx_parser/v0_17/crate/Cargo.toml
+++ b/third_party/rust/autocxx_parser/v0_17/crate/Cargo.toml
@@ -12,7 +12,7 @@
 [package]
 edition = "2021"
 name = "autocxx-parser"
-version = "0.17.2"
+version = "0.17.4"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 description = "Safe autogenerated interop between Rust and C++"
 keywords = ["ffi"]
diff --git a/third_party/rust/autocxx_parser/v0_17/crate/Cargo.toml.orig b/third_party/rust/autocxx_parser/v0_17/crate/Cargo.toml.orig
index 15ea808..daf778e 100644
--- a/third_party/rust/autocxx_parser/v0_17/crate/Cargo.toml.orig
+++ b/third_party/rust/autocxx_parser/v0_17/crate/Cargo.toml.orig
@@ -8,7 +8,7 @@
 
 [package]
 name = "autocxx-parser"
-version = "0.17.2"
+version = "0.17.4"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 license = "MIT OR Apache-2.0"
 description = "Safe autogenerated interop between Rust and C++"
diff --git a/third_party/rust/autocxx_parser/v0_17/crate/src/config.rs b/third_party/rust/autocxx_parser/v0_17/crate/src/config.rs
index 4a9a181..7e65a7d 100644
--- a/third_party/rust/autocxx_parser/v0_17/crate/src/config.rs
+++ b/third_party/rust/autocxx_parser/v0_17/crate/src/config.rs
@@ -6,7 +6,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::{borrow::Cow, collections::HashSet};
+use std::{
+    borrow::Cow,
+    collections::{HashMap, HashSet},
+};
 
 use proc_macro2::Span;
 use quote::ToTokens;
@@ -163,6 +166,7 @@
     pub rust_types: Vec<RustPath>,
     pub subclasses: Vec<Subclass>,
     pub extern_rust_funs: Vec<RustFun>,
+    pub concretes: HashMap<String, Ident>,
 }
 
 impl Parse for IncludeCppConfig {
@@ -185,6 +189,7 @@
         let mut mod_name = None;
         let mut subclasses = Vec::new();
         let mut extern_rust_funs = Vec::new();
+        let mut concretes = HashMap::new();
 
         while !input.is_empty() {
             let has_hexathorpe = input.parse::<Option<syn::token::Pound>>()?.is_some();
@@ -229,6 +234,13 @@
                     syn::parenthesized!(args in input);
                     let generate: syn::LitStr = args.parse()?;
                     blocklist.push(generate.value());
+                } else if ident == "concrete" {
+                    let args;
+                    syn::parenthesized!(args in input);
+                    let definition: syn::LitStr = args.parse()?;
+                    args.parse::<syn::token::Comma>()?;
+                    let rust_id: syn::Ident = args.parse()?;
+                    concretes.insert(definition.value(), rust_id);
                 } else if ident == "block_constructors" {
                     let args;
                     syn::parenthesized!(args in input);
@@ -303,6 +315,7 @@
             mod_name,
             subclasses,
             extern_rust_funs,
+            concretes,
         })
     }
 }
@@ -413,6 +426,7 @@
             || self.is_subclass_holder(cpp_name)
             || self.is_subclass_cpp(cpp_name)
             || self.is_rust_fun(cpp_name)
+            || self.is_concrete_type(cpp_name)
             || match &self.allowlist {
                 Allowlist::Unspecified(_) => panic!("Eek no allowlist yet"),
                 Allowlist::All => true,
@@ -435,6 +449,10 @@
         self.blocklist.iter()
     }
 
+    fn is_concrete_type(&self, cpp_name: &str) -> bool {
+        self.concretes.values().any(|val| *val == cpp_name)
+    }
+
     /// In case there are multiple sets of ffi mods in a single binary,
     /// endeavor to return a name which can be used to make symbols
     /// unique.
diff --git a/third_party/rust/autocxx_parser/v0_17/crate/src/lib.rs b/third_party/rust/autocxx_parser/v0_17/crate/src/lib.rs
index f0d988df..e1edb4e 100644
--- a/third_party/rust/autocxx_parser/v0_17/crate/src/lib.rs
+++ b/third_party/rust/autocxx_parser/v0_17/crate/src/lib.rs
@@ -29,7 +29,7 @@
 /// and the standalone macro discoverer
 pub mod directives {
     pub static EXTERN_RUST_TYPE: &str = "extern_rust_type";
-    pub static EXTERN_RUST_FUN: &str = "extern_rust_fun";
+    pub static EXTERN_RUST_FUN: &str = "extern_rust_function";
     pub static SUBCLASS: &str = "subclass";
 }
 
diff --git a/third_party/webgpu-cts/ts_sources.txt b/third_party/webgpu-cts/ts_sources.txt
index 9149b51..14dc8d6 100644
--- a/third_party/webgpu-cts/ts_sources.txt
+++ b/third_party/webgpu-cts/ts_sources.txt
@@ -245,12 +245,14 @@
 src/webgpu/api/validation/resource_usages/texture/in_pass_encoder.spec.ts
 src/webgpu/api/validation/resource_usages/texture/in_render_common.spec.ts
 src/webgpu/api/validation/resource_usages/texture/in_render_misc.spec.ts
+src/webgpu/api/validation/state/device_lost/destroy.spec.ts
 src/webgpu/api/validation/texture/destroy.spec.ts
 src/webgpu/idl/exposed.html.ts
 src/webgpu/idl/idl_test.ts
 src/webgpu/idl/constants/flags.spec.ts
 src/webgpu/shader/types.ts
 src/webgpu/shader/values.ts
+src/webgpu/shader/execution/evaluation_order.spec.ts
 src/webgpu/shader/execution/robust_access.spec.ts
 src/webgpu/shader/execution/robust_access_vertex.spec.ts
 src/webgpu/shader/execution/zero_init.spec.ts
diff --git a/tools/android/checkxmlstyle/checkxmlstyle.py b/tools/android/checkxmlstyle/checkxmlstyle.py
index 3d3fb35..be19dbb7 100644
--- a/tools/android/checkxmlstyle/checkxmlstyle.py
+++ b/tools/android/checkxmlstyle/checkxmlstyle.py
@@ -39,6 +39,30 @@
   return input_api.AffectedFiles(include_deletes=False, file_filter=files)
 
 
+"""
+This class has two jobs. It allows us to delay searching directories for color
+state list files unless we actually find a color reference to check against. And
+additionally it's a convenient mock point for tests to specify files in a
+slightly more robust way than relying on real color state list file names.
+"""
+
+
+class LazyColorStateListSet:
+  _color_set_or_none = None
+
+  def get(self):
+    if self._color_set_or_none != None:
+      return self._color_set_or_none
+
+    self._color_set_or_none = set()
+    for color_dir in helpers.COLOR_STATE_LIST_DIRS:
+      for color_file in os.listdir(color_dir):
+        if '.' in color_file:
+          print(color_file)
+          self._color_set_or_none.add(color_file[:color_file.index('.')])
+    return self._color_set_or_none
+
+
 def _CommonChecks(input_api, output_api):
   """Checks common to both upload and commit."""
   result = []
@@ -47,6 +71,7 @@
   result.extend(_CheckDuplicateColors(input_api, output_api))
   result.extend(_CheckSemanticColorsReferences(input_api, output_api))
   result.extend(_CheckColorPaletteReferences(input_api, output_api))
+  result.extend(_CheckNonDynamicColorReference(input_api, output_api))
   result.extend(_CheckXmlNamespacePrefixes(input_api, output_api))
   result.extend(_CheckTextAppearance(input_api, output_api))
   result.extend(_CheckLineSpacingAttribute(input_api, output_api))
@@ -150,7 +175,6 @@
     ]
   return result
 
-
 def _CheckDuplicateColors(input_api, output_api):
   """
   Checks colors defined by (A)RGB values in color_palette.xml and
@@ -275,6 +299,43 @@
   return []
 
 
+def _CheckNonDynamicColorReference(
+    input_api, output_api, lazy_color_state_list_set=LazyColorStateListSet()):
+  """
+  Checks for @color references that will not work with dynamic colors.
+  """
+
+  warnings = []
+  for f in IncludedFiles(input_api,
+                         allow_list=helpers.DYNAMIC_COLOR_INCLUDED_PATHS):
+    for line_number, line in f.ChangedContents():
+      r = helpers.COLOR_REFERENCE_PATTERN.search(line)
+      if not r:
+        continue
+
+      color_name = r.group(1)
+      if color_name not in lazy_color_state_list_set.get():
+        issue = '  %s:%d\n    \t%s' % (f.LocalPath(), line_number, line.strip())
+        warnings.append(issue)
+
+  if warnings:
+    # TODO(https://crbug.com/1224883): Replace bug with a upstream doc link.
+    return [
+        output_api.PresubmitPromptWarning(
+            '''
+Dynamic Color Reference Check warning:
+  Your new code is using @color references. These will not correctly support
+  dynamic colors. Instead you should use a @macro that routes into an ?attr.
+  Note using color references is currently okay for incognito code, as it should
+  not be dynamically colored.
+
+  See https://crbug.com/1302056 for more information.
+          ''', warnings)
+    ]
+
+  return []
+
+
 def _CheckXmlNamespacePrefixes(input_api, output_api):
   """Checks consistency of prefixes used for XML namespace names."""
   errors = []
diff --git a/tools/android/checkxmlstyle/checkxmlstyle_test.py b/tools/android/checkxmlstyle/checkxmlstyle_test.py
index 91afd71..b0b307d 100755
--- a/tools/android/checkxmlstyle/checkxmlstyle_test.py
+++ b/tools/android/checkxmlstyle/checkxmlstyle_test.py
@@ -197,6 +197,43 @@
     self.assertEqual(0, len(errors))
 
 
+class NonDynamicColorsTest(unittest.TestCase):
+  class MockColorStateListSet:
+    def get(self):
+      return {'color_state_list'}
+
+  def testFailure(self):
+    lines = [
+        'app:tint="@color/tint_color" />',
+        'android:background="@color/bg_color"',
+        '<color name="fake_semantic_color">@color/palettele_color</color>',
+    ]
+    mock_input_api = MockInputApi()
+    mock_input_api.files = [MockFile('chrome/java/res_test/colors.xml', lines)]
+    errors = checkxmlstyle._CheckNonDynamicColorReference(
+        mock_input_api,
+        MockOutputApi(),
+        lazy_color_state_list_set=self.MockColorStateListSet())
+    self.assertEqual(1, len(errors))
+    self.assertEqual(len(lines), len(errors[0].items))
+
+  def testSuccess(self):
+    lines = [
+        'app:tint="@color/color_state_list" />',
+        'android:background="@color/color_state_list"',
+        '<color name="fake_semantic_color">@color/color_state_list</color>',
+    ]
+    mock_input_api = MockInputApi()
+    mock_input_api.files = [
+        MockFile('chrome/java/res_test/colors.xml', lines),
+    ]
+    errors = checkxmlstyle._CheckNonDynamicColorReference(
+        mock_input_api,
+        MockOutputApi(),
+        lazy_color_state_list_set=self.MockColorStateListSet())
+    self.assertEqual(0, len(errors))
+
+
 class XmlNamespacePrefixesTest(unittest.TestCase):
 
   def testFailure(self):
diff --git a/tools/android/checkxmlstyle/helpers.py b/tools/android/checkxmlstyle/helpers.py
index 9617fd25..fef8fb3 100644
--- a/tools/android/checkxmlstyle/helpers.py
+++ b/tools/android/checkxmlstyle/helpers.py
@@ -23,11 +23,29 @@
 INCLUDED_PATHS = [
     r'^(chrome|ui|components|content)[\\/](.*[\\/])?java[\\/]res.+\.xml$'
 ]
+DYNAMIC_COLOR_INCLUDED_PATHS = [
+    r'^(chrome|components)[\\/](.*[\\/])?java[\\/]res.+\.xml$'
+]
 INCLUDED_GRD_PATHS = [
     r'^(chrome|ui|components|content)[\\/](.*[\\/])?android[\\/](.*)\.grd$'
 ]
-# TODO(lazzzis): check color references in java source files
-COLOR_REFERENCE_PATTERN = re.compile('''
+# TODO(lazzzis): Check color references in java source files.
+COLOR_REFERENCE_PATTERN = re.compile(
+    '''
     @color/   # starts with '@color'
-    [\w|_]+   # color name is only composed of numbers, letters and underscore
+    ([\w|_]+)   # color name is only composed of numbers, letters and underscore
 ''', re.VERBOSE)
+
+DYNAMIC_COLOR_SUPPORTING_DIRS = {'components', 'chrome'}
+COLOR_STATE_LIST_DIRS = {
+    # Generated with the command below. When color state lists in new folders
+    # are added, re-run this command and update.
+    # find chrome/ components/ -name *\.xml | grep "/res/color" | xargs grep "<selector" | cut -d: -f1 | xargs dirname | sort | uniq | sed "s/^/'/" | sed "s/$/\/',/"
+    'chrome/android/features/tab_ui/java/res/color/',
+    'chrome/android/java/res/color/',
+    'chrome/browser/feed/android/java/res/color/',
+    'components/browser_ui/styles/android/java/res/color/',
+    'components/browser_ui/styles/android/java/res/color-night/',
+    'components/browser_ui/widget/android/java/res/color/',
+    'components/permissions/android/res/color/',
+}
diff --git a/tools/clang/scripts/build.py b/tools/clang/scripts/build.py
index fea7a1fd..11e5926 100755
--- a/tools/clang/scripts/build.py
+++ b/tools/clang/scripts/build.py
@@ -443,6 +443,22 @@
     sys.exit(1)
 
 
+# TODO(https://crbug.com/1286289): remove once Chrome targets don't rely on
+# libstdc++.so existing in the clang package.
+def CopyLibstdcpp(args, build_dir):
+  if not args.gcc_toolchain:
+    return
+  # Find libstdc++.so.6
+  libstdcpp = subprocess.check_output([
+      os.path.join(args.gcc_toolchain, 'bin', 'g++'),
+      '-print-file-name=libstdc++.so.6'
+  ],
+                                      universal_newlines=True).rstrip()
+
+  EnsureDirExists(os.path.join(build_dir, 'lib'))
+  CopyFile(libstdcpp, os.path.join(build_dir, 'lib'))
+
+
 def gn_arg(v):
   if v == 'True':
     return True
@@ -980,6 +996,7 @@
   os.chdir(LLVM_BUILD_DIR)
   RunCommand(['cmake'] + cmake_args + [os.path.join(LLVM_DIR, 'llvm')],
              msvc_arch='x64', env=deployment_env)
+  CopyLibstdcpp(args, LLVM_BUILD_DIR)
   RunCommand(['ninja'], msvc_arch='x64')
 
   if chrome_tools:
diff --git a/tools/clang/scripts/package.py b/tools/clang/scripts/package.py
index a389e0a..53e32c3 100755
--- a/tools/clang/scripts/package.py
+++ b/tools/clang/scripts/package.py
@@ -306,6 +306,9 @@
     want.extend([
         # pylint: disable=line-too-long
 
+        # Copy the stdlibc++.so.6 we linked the binaries against.
+        'lib/libstdc++.so.6',
+
         # Add llvm-objcopy for partition extraction on Android.
         'bin/llvm-objcopy',
 
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index 8cf820d7d..ceeeedc 100755
--- a/tools/clang/scripts/update.py
+++ b/tools/clang/scripts/update.py
@@ -36,7 +36,7 @@
 # Reverting problematic clang rolls is safe, though.
 # This is the output of `git describe` and is usable as a commit-ish.
 CLANG_REVISION = 'llvmorg-15-init-3677-g8133778d'
-CLANG_SUB_REVISION = 5
+CLANG_SUB_REVISION = 4
 
 PACKAGE_VERSION = '%s-%s' % (CLANG_REVISION, CLANG_SUB_REVISION)
 RELEASE_VERSION = '15.0.0'
diff --git a/tools/mac/power/driver.py b/tools/mac/power/driver.py
index 290857aa..c8a4287 100644
--- a/tools/mac/power/driver.py
+++ b/tools/mac/power/driver.py
@@ -249,54 +249,44 @@
     dtrace_env = os.environ.copy()
     dtrace_env["DYLD_SHARED_REGION"] = "avoid"
 
-    pid_to_subprocess: typing.Dict[str, subprocess.Popen] = {}
-
     try:
       with open(
           os.path.join(self._output_dir, scenario_driver.name,
                        f'dtrace_{profile_mode}_log.txt'), "w") as dtrace_log:
-        # Keep looking for child processes as long as the scenario is running.
-        while scenario_driver.IsRunning():
 
-          # Let some time pass to limit the overhead of this script.
-          time.sleep(0.100)
-          logging.debug("Looking for child processes")
+        # Comments regarding the DTrace probes below.
+        # pid == {pid} to capture the browser process.
+        # ppid == {pid} to capture all child processes.
+        # ustack(64) to capture stacks user space.
 
-          # Watch for new processes and follow those too.
-          for process in browser_process.children(
-              recursive=True) + [browser_process]:
-            pid = process.pid
-            if profile_mode == "wakeups":
-              probe_def = \
-                f"mach_kernel::wakeup/pid == {pid}/ " \
-                "{{ @[ustack(64)] = count(); }}"
-            else:
-              probe_def = \
-                f"profile-1001/pid == {pid}/ {{ @[ustack(64)] = count(); }}"
-            output_filename = os.path.join(dtraces_output_dir, f"{pid}.txt")
-            dtrace_args = [
-                'sudo', 'dtrace', '-p', f"{pid}", "-o", output_filename, '-n',
-                probe_def
-            ]
+        if profile_mode == "wakeups":
+          probe = "mach_kernel::wakeup"
+        else:
+          probe = "profile-1001"
 
-            if pid not in pid_to_subprocess:
-              logging.debug(f"Found new child!:{pid}")
-              # No need to add |process| to |self._started_processeds| as it's
-              # explicitly waited on later.
-              process = subprocess.Popen(dtrace_args,
-                                         env=dtrace_env,
-                                         stdout=dtrace_log,
-                                         stderr=dtrace_log)
-              pid_to_subprocess[pid] = process
+        pid = browser_process.pid
+        probe_def = \
+          f"{probe}/pid=={pid} || ppid=={pid}/ {{@[ustack(128)] = count();}}"
 
+        output_filename = os.path.join(dtraces_output_dir, f"{pid}.txt")
+        dtrace_args = [
+            'sudo', 'dtrace', '-p', f"{pid}", "-o", output_filename, '-n',
+            probe_def
+        ]
+
+        # No need to add |dtrace_process| to |self._started_processeds| as it's
+        # explicitly waited on later.
+        dtrace_process = subprocess.Popen(dtrace_args,
+                                          env=dtrace_env,
+                                          stdout=dtrace_log,
+                                          stderr=dtrace_log)
       scenario_driver.Wait()
 
     finally:
       scenario_driver.TearDown()
 
-      for pid, dtrace_process in pid_to_subprocess.items():
-        logging.debug(f"Waiting for dtrace hooked on {pid} to exit")
-        dtrace_process.wait(30)
+    logging.debug(f"Waiting for dtrace to exit")
+    dtrace_process.wait(30)
 
   def WriteScenarioSummary(
       self, scenario_driver: scenarios.ScenarioWithBrowserOSADriver):
diff --git a/tools/metrics/actions/extract_actions.py b/tools/metrics/actions/extract_actions.py
index cba37db..b7d0baca 100755
--- a/tools/metrics/actions/extract_actions.py
+++ b/tools/metrics/actions/extract_actions.py
@@ -103,7 +103,7 @@
     'render_process_host_impl.cc',  # browser side impl for
     # RenderThread::RecordComputedAction()
     'mock_render_thread.cc',  # mock of RenderThread::RecordComputedAction()
-    'pepper_pdf_host.cc',  # see AddClosedSourceActions()
+    'pdf_view_plugin_base.cc',  # see AddPDFPluginActions()
     'blink_platform_impl.cc',  # see WebKit/public/platform/Platform.h
     'devtools_ui_bindings.cc',  # see AddDevToolsActions()
     'sharing_hub_bubble_controller.cc',  # share targets
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index e868747..d061bcb 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -8639,6 +8639,7 @@
   <int value="270"
       label="RFH_BEFOREUNLOAD_HANDLER_NOT_ALLOWED_IN_FENCED_FRAME"/>
   <int value="271" label="MSDH_GET_OPEN_DEVICE_USE_WITHOUT_FEATURE"/>
+  <int value="272" label="RFHI_SUBFRAME_NAV_WOULD_CHANGE_MAINFRAME_ORIGIN"/>
 </enum>
 
 <enum name="BadMessageReasonExtensions">
@@ -25925,13 +25926,6 @@
   <int value="5" label="Bad gamma value"/>
 </enum>
 
-<enum name="EditableContentType">
-  <int value="0" label="Not editable"/>
-  <int value="1" label="Content editable"/>
-  <int value="2" label="Text area"/>
-  <int value="3" label="Input"/>
-</enum>
-
 <enum name="EduCoexistenceFlowResult">
   <obsolete>
     Deprecated in M91 after v2 EduCoexistence.
@@ -37758,6 +37752,7 @@
   <int value="19" label="ClientMetadataMissingPrivacyPolicyUrl"/>
   <int value="20" label="ThirdPartyCookiesBlocked"/>
   <int value="21" label="DisabledInSettings"/>
+  <int value="22" label="DisabledInFlags"/>
 </enum>
 
 <enum name="FedCmRevokeStatus">
@@ -37772,6 +37767,7 @@
   <int value="8" label="ManifestNoResponse"/>
   <int value="9" label="ManifestInvalidResponse"/>
   <int value="10" label="DisabledInSettings"/>
+  <int value="11" label="DisabledInFlags"/>
 </enum>
 
 <enum name="FeedAutoplayEvent">
@@ -51938,6 +51934,7 @@
   <int value="-1972383451" label="disable-pinch"/>
   <int value="-1972312724" label="OfflinePagesLoadSignalCollecting:enabled"/>
   <int value="-1972219399" label="NTPSaveToOffline:enabled"/>
+  <int value="-1971490389" label="UachOverrideBlank:disabled"/>
   <int value="-1971086581" label="print-scaling"/>
   <int value="-1970672551" label="CanvasContextLostInBackground:disabled"/>
   <int value="-1969636234" label="OmniboxRefinedFocusState:disabled"/>
@@ -54192,6 +54189,7 @@
   <int value="-460486807" label="ConsolidatedSiteStorageControls:enabled"/>
   <int value="-460313418" label="ProgressBarThrottle:enabled"/>
   <int value="-460081932" label="CustomFeedbackUi:disabled"/>
+  <int value="-459469509" label="SidePanelImprovedClobbering:enabled"/>
   <int value="-459318667" label="AccessiblePDFForm:enabled"/>
   <int value="-458308082" label="ContextualTriggersSelectionMenu:disabled"/>
   <int value="-457584339" label="TemporaryHoldingSpace:enabled"/>
@@ -55338,6 +55336,7 @@
   <int value="352191859" label="disabled-new-style-notification"/>
   <int value="352937987" label="OverflowIconsForMediaControls:disabled"/>
   <int value="353898777" label="ClipboardHistoryScreenshotNudge:disabled"/>
+  <int value="354466842" label="UachOverrideBlank:enabled"/>
   <int value="354631905" label="RecoverFromNeverSaveAndroid:disabled"/>
   <int value="355367368" label="SharesheetCopyToClipboard:disabled"/>
   <int value="357138275" label="enable-floating-virtual-keyboard:disabled"/>
@@ -56416,6 +56415,7 @@
   <int value="1093859961" label="RelatedSearchesSimplifiedUx:disabled"/>
   <int value="1094095931" label="enable-vulkan"/>
   <int value="1094506652" label="UseGoogleLocalNtp:enabled"/>
+  <int value="1094889977" label="SidePanelImprovedClobbering:disabled"/>
   <int value="1095061640" label="enable-prominent-url-app-flow"/>
   <int value="1095706700" label="NavigationPredictor:enabled"/>
   <int value="1096477444" label="AssistantVoiceMatch:enabled"/>
@@ -59554,6 +59554,7 @@
   <int value="711" label="override-colors"/>
   <int value="712" label="page-transition-tag"/>
   <int value="713" label="object-view-box"/>
+  <int value="714" label="object-overflow"/>
 </enum>
 
 <enum name="MappedEditingCommands">
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml
index 2732674d..996c364b 100644
--- a/tools/metrics/histograms/metadata/android/histograms.xml
+++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -1427,20 +1427,6 @@
   </summary>
 </histogram>
 
-<histogram name="Android.Input.EditableContentTypes" enum="EditableContentType"
-    expires_after="2022-04-09">
-  <owner>alexmitra@chromium.org</owner>
-  <owner>ctzsm@chromium.org</owner>
-  <owner>nator@chromium.org</owner>
-  <owner>src/android_webview/OWNERS</owner>
-  <summary>
-    Tracks whether a WebView is being used to get user input and how the input
-    is being collected (through an input tag, textarea tag or through an element
-    with the contenteditable attribute). We will log this each time the user
-    focuses on an element.
-  </summary>
-</histogram>
-
 <histogram name="Android.InstantApps.ApiCallDurationWithApp" units="ms"
     expires_after="M81">
   <owner>sbirch@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml
index 13bc63de..098348b5 100644
--- a/tools/metrics/histograms/metadata/ash/histograms.xml
+++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -150,7 +150,7 @@
 </histogram>
 
 <histogram name="Ash.AmbientMode.Activation.{TabletOrClamshell}"
-    enum="AmbientUiMode" expires_after="2022-05-01">
+    enum="AmbientUiMode" expires_after="2022-12-01">
   <owner>cowmoo@google.com</owner>
   <owner>xiaohuic@chromium.org</owner>
   <summary>
@@ -162,7 +162,7 @@
 </histogram>
 
 <histogram name="Ash.AmbientMode.AnimationSmoothness.PhotoTransition" units="%"
-    expires_after="2022-05-01">
+    expires_after="2022-12-01">
   <owner>wutao@chromium.org</owner>
   <owner>xiaohuic@chromium.org</owner>
   <summary>
@@ -173,7 +173,7 @@
 </histogram>
 
 <histogram name="Ash.AmbientMode.Enabled" enum="BooleanEnabled"
-    expires_after="2022-05-01">
+    expires_after="2022-12-01">
   <owner>cowmoo@google.com</owner>
   <owner>xiaohuic@chromium.org</owner>
   <summary>
@@ -186,7 +186,7 @@
 </histogram>
 
 <histogram name="Ash.AmbientMode.EngagementTime.{TabletOrClamshell}" units="ms"
-    expires_after="2022-05-01">
+    expires_after="2022-12-01">
   <owner>cowmoo@google.com</owner>
   <owner>xiaohuic@chromium.org</owner>
   <summary>
@@ -197,7 +197,7 @@
 </histogram>
 
 <histogram name="Ash.AmbientMode.PhotoSource" enum="AmbientModePhotoSource"
-    expires_after="2022-05-01">
+    expires_after="2022-12-01">
   <owner>cowmoo@google.com</owner>
   <owner>xiaohuic@chromium.org</owner>
   <summary>
@@ -207,7 +207,7 @@
 </histogram>
 
 <histogram name="Ash.AmbientMode.SelectedNumberOfAlbums" units="int"
-    expires_after="2022-05-01">
+    expires_after="2022-12-01">
   <owner>cowmoo@google.com</owner>
   <owner>xiaohuic@chromium.org</owner>
   <summary>
@@ -218,7 +218,7 @@
 </histogram>
 
 <histogram name="Ash.AmbientMode.TotalNumberOfAlbums" units="int"
-    expires_after="2022-05-01">
+    expires_after="2022-12-01">
   <owner>cowmoo@google.com</owner>
   <owner>xiaohuic@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml
index bd153d3..209d01e 100644
--- a/tools/metrics/histograms/metadata/net/histograms.xml
+++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -1907,19 +1907,6 @@
   </summary>
 </histogram>
 
-<histogram name="Net.NetworkChangeNotifierMac.GetCurrentConnectionTypeWaitTime"
-    units="ms" expires_after="2022-05-01">
-  <owner>ajuma@chromium.org</owner>
-  <owner>pauljensen@chromium.org</owner>
-  <summary>
-    The amount of time (ms) spent waiting for the connection type to be
-    determined in NetworkChangeNotifierMac::GetCurrentConnectionType. This is
-    recorded the first time GetCurrentConnectionType is called, before the
-    connection type has been determined; it is not recorded again on subsequent
-    calls to this function.
-  </summary>
-</histogram>
-
 <histogram name="Net.NetworkConfigWatcherMac.SCDynamicStore.Create"
     enum="SCStatusCode" expires_after="M85">
   <owner>mef@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml
index a397925..fcb20b0 100644
--- a/tools/metrics/histograms/metadata/others/histograms.xml
+++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -5877,7 +5877,7 @@
   <summary>The time it takes to open a hyphenation dictionary.</summary>
 </histogram>
 
-<histogram name="Hyphenation.Open.File" units="ms" expires_after="2022-04-24">
+<histogram name="Hyphenation.Open.File" units="ms" expires_after="2022-06-26">
   <owner>kojii@chromium.org</owner>
   <owner>layout-dev@chromium.org</owner>
   <summary>The time it takes to open a hyphenation dictionary file.</summary>
diff --git a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
index a096068..64623d1 100644
--- a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
+++ b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
@@ -2505,8 +2505,8 @@
 </histogram>
 
 <histogram name="SafeBrowsingBinaryUploadRequest.DlpResult"
-    enum="BooleanSuccess" expires_after="2022-05-01">
-  <owner>drubery@chromium.org</owner>
+    enum="BooleanSuccess" expires_after="2023-05-01">
+  <owner>domfc@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
     This records whether DLP scanning succeeded or not. It is logged once for
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index 4c2ac37..5e37d4e 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -433,7 +433,7 @@
         ],
         'dimension': {
             'cpu': 'x86',
-            'os': 'Ubuntu-16.04',
+            'os': 'Ubuntu-18.04',
             'pool': 'chrome.tests',
         },
         'perf_trigger':
@@ -521,7 +521,7 @@
         ],
         'dimension': {
             'cpu': 'x86',
-            'os': 'Ubuntu-16.04',
+            'os': 'Ubuntu-18.04',
             'pool': 'chrome.tests',
         },
         'perf_trigger':
@@ -539,7 +539,7 @@
         }],
         'dimension': {
             'cpu': 'x86-64',
-            'os': 'Ubuntu-16.04',
+            'os': 'Ubuntu-18.04',
             'pool': 'chrome.tests',
         },
         'perf_trigger':
@@ -969,7 +969,7 @@
         ],
         'dimension': {
             'cpu': 'x86-64',
-            'os': 'Ubuntu-16.04',
+            'os': 'Ubuntu-18.04',
             'pool': 'chrome.tests',
         },
         'perf_trigger':
@@ -989,7 +989,7 @@
         ],
         'dimension': {
             'cpu': 'x86-64',
-            'os': 'Ubuntu-16.04',
+            'os': 'Ubuntu-18.04',
             'pool': 'chrome.tests',
         },
         'perf_trigger':
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index ecf14a7..83d7b63d 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,24 +5,24 @@
             "remote_path": "perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "win": {
-            "hash": "7e9e772b9003b767bbd1150314132bbcbcba048a",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/32214834f51712d2a9b80cd643aee86374270a73/trace_processor_shell.exe"
+            "hash": "8123ff1123b68a6c08c4f49be05c727c68eee99d",
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/3a5b2ad60d85cf76cc94677544bc08c6a0f42ac6/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893",
             "remote_path": "perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "mac": {
-            "hash": "647302801554811912ab7fedb81e5455625a9303",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/d89b25832b668dcf2d55bccbfb57f9a24723b869/trace_processor_shell"
+            "hash": "32d9d37b055e4ac243193f6492b513fcfa386a31",
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/32214834f51712d2a9b80cd643aee86374270a73/trace_processor_shell"
         },
         "mac_arm64": {
             "hash": "c0397e87456ad6c6a7aa0133e5b81c97adbab4ab",
             "remote_path": "perfetto_binaries/trace_processor_shell/mac_arm64/cefb3e0ec3a0580c996f801e854fe02963c03d5c/trace_processor_shell"
         },
         "linux": {
-            "hash": "9ec43c7ef90ba38a07be800722b7b05cba5deb79",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/32214834f51712d2a9b80cd643aee86374270a73/trace_processor_shell"
+            "hash": "a1bde677e9ff393c05e0ca9a93f33856a6968748",
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/3a5b2ad60d85cf76cc94677544bc08c6a0f42ac6/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/ui/gfx/color_utils.cc b/ui/gfx/color_utils.cc
index 0eaaeb7..e0d4875 100644
--- a/ui/gfx/color_utils.cc
+++ b/ui/gfx/color_utils.cc
@@ -101,6 +101,13 @@
     gfx::kGoogleGreen900,
 };
 
+constexpr SkColor kCyan[kNumGoogleColors] = {
+    gfx::kGoogleCyan050, gfx::kGoogleCyan100, gfx::kGoogleCyan200,
+    gfx::kGoogleCyan300, gfx::kGoogleCyan400, gfx::kGoogleCyan500,
+    gfx::kGoogleCyan600, gfx::kGoogleCyan700, gfx::kGoogleCyan800,
+    gfx::kGoogleCyan900,
+};
+
 constexpr SkColor kBlue[kNumGoogleColors] = {
     gfx::kGoogleBlue050, gfx::kGoogleBlue100, gfx::kGoogleBlue200,
     gfx::kGoogleBlue300, gfx::kGoogleBlue400, gfx::kGoogleBlue500,
@@ -115,6 +122,13 @@
     gfx::kGooglePurple900,
 };
 
+constexpr SkColor kMagenta[kNumGoogleColors] = {
+    gfx::kGoogleMagenta050, gfx::kGoogleMagenta100, gfx::kGoogleMagenta200,
+    gfx::kGoogleMagenta300, gfx::kGoogleMagenta400, gfx::kGoogleMagenta500,
+    gfx::kGoogleMagenta600, gfx::kGoogleMagenta700, gfx::kGoogleMagenta800,
+    gfx::kGoogleMagenta900,
+};
+
 constexpr SkColor kPink[kNumGoogleColors] = {
     gfx::kGooglePink050, gfx::kGooglePink100, gfx::kGooglePink200,
     gfx::kGooglePink300, gfx::kGooglePink400, gfx::kGooglePink500,
@@ -200,30 +214,32 @@
   // Map hue to angles for readability.
   const float color_angle = hsl.h * 360;
 
-  // Hues in comments below are accent colors from MacOS 11.3.1 light mode as
-  // point of reference.
-  // TODO(pbos): Complement this with more Google colors and verify the hue
-  // ranges, this currently knows about enough colors to pick a corresponding
-  // color correctly from MacOS accent colors.
-  // RED: 357.654
-  if (color_angle < 20)
+  // Hues in comments below are of the corresponding kGoogleXXX500 color.
+  // RED: 4
+  if (color_angle < 15)
     return pick_color(kRed);
-  // ORANGE: 28.0687
-  if (color_angle < 40)
+  // ORANGE: 26
+  if (color_angle < 35)
     return pick_color(kOrange);
-  // YELLOW: 44.4156
-  if (color_angle < 70)
+  // YELLOW: 44
+  if (color_angle < 90)
     return pick_color(kYellow);
-  // GREEN: 105.484
-  if (color_angle < 160)
+  // GREEN: 136
+  if (color_angle < 163)
     return pick_color(kGreen);
-  // BLUE: 214.672
-  if (color_angle < 250)
+  // CYAN: 189
+  if (color_angle < 203)
+    return pick_color(kCyan);
+  // BLUE: 217
+  if (color_angle < 245)
     return pick_color(kBlue);
-  // PURPLE: 299.362
-  if (color_angle < 310)
+  // PURPLE: 272
+  if (color_angle < 284)
     return pick_color(kPurple);
-  // PINK: 331.685
+  // MAGENTA: 295
+  if (color_angle < 311)
+    return pick_color(kMagenta);
+  // PINK: 326
   if (color_angle < 345)
     return pick_color(kPink);
 
diff --git a/ui/views/controls/button/image_button.cc b/ui/views/controls/button/image_button.cc
index 326e2416..65c542e 100644
--- a/ui/views/controls/button/image_button.cc
+++ b/ui/views/controls/button/image_button.cc
@@ -171,14 +171,16 @@
 // ImageButton, protected:
 
 gfx::ImageSkia ImageButton::GetImageToPaint() {
+  const auto* const color_provider = GetColorProvider();
   if (!images_[STATE_HOVERED].IsEmpty() && hover_animation().is_animating()) {
     return gfx::ImageSkiaOperations::CreateBlendedImage(
-        GetImage(STATE_NORMAL), GetImage(STATE_HOVERED),
+        images_[STATE_NORMAL].Rasterize(color_provider),
+        images_[STATE_HOVERED].Rasterize(color_provider),
         hover_animation().GetCurrentValue());
   }
 
-  const auto img = GetImage(GetState());
-  return !img.isNull() ? img : GetImage(STATE_NORMAL);
+  const auto img = images_[GetState()].Rasterize(color_provider);
+  return !img.isNull() ? img : images_[STATE_NORMAL].Rasterize(color_provider);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/ContentViewWithAutofill.java b/weblayer/browser/java/org/chromium/weblayer_private/ContentViewWithAutofill.java
index 73f9056..acf44bb4 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/ContentViewWithAutofill.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/ContentViewWithAutofill.java
@@ -18,7 +18,7 @@
 /**
  * API level 26 implementation that includes autofill.
  */
-public class ContentViewWithAutofill extends ContentView.ContentViewApi23 {
+public class ContentViewWithAutofill extends ContentView {
     public static ContentView createContentView(
             Context context, EventOffsetHandler eventOffsetHandler) {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
diff --git a/weblayer/browser/navigation_browsertest.cc b/weblayer/browser/navigation_browsertest.cc
index 5bb663c1..b0c9fdc 100644
--- a/weblayer/browser/navigation_browsertest.cc
+++ b/weblayer/browser/navigation_browsertest.cc
@@ -568,8 +568,10 @@
     : public NavigationBrowserTest {
  public:
   void SetUp() override {
-    scoped_feature_list_.InitAndEnableFeature(
-        blink::features::kUserAgentOverrideExperiment);
+    scoped_feature_list_.InitWithFeatures(
+        {blink::features::kUserAgentOverrideExperiment,
+         blink::features::kUACHOverrideBlank},
+        {});
     NavigationBrowserTest::SetUp();
   }