diff --git a/DEPS b/DEPS
index 0040618..6e0815f 100644
--- a/DEPS
+++ b/DEPS
@@ -253,7 +253,7 @@
   # 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': '5bec818c1f4e4e5ff609fce1422b231d5a9f77ee',
+  'skia_revision': '5fb37db69f1163a45603412a2584a1d1357e09ef',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # 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': '4a800603ab8a7e9e2569ec63fe618501d5f8145e',
+  'catapult_revision': '74f773b8a535b0a4dd401229ae4caef2c972c417',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -328,7 +328,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '2af14943bbfe0a3d67ae357cf664a374e44486de',
+  'devtools_frontend_revision': '92c0e96770b1cf48c7d18b33d89b3774c5c5a6b8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -1514,7 +1514,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'b6557e37c41e01d2cb0508b4c6583e23e2838a17',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '9d1b2dd68697e0b5d912c18674cadd1c16ef5790',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1611,7 +1611,7 @@
   },
 
   'src/third_party/re2/src':
-    Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '055e1241fcfde4f19f072b4dd909a824de54ceb8',
+    Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '74c521bfeb086cda4486584c4feabe03da6fdf63',
 
   'src/third_party/r8': {
       'packages': [
@@ -1805,7 +1805,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@46bd179342dba423088582e543f56b195de2349e',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@28af56c886f33848eab3b5bf9756f9dc5e454e64',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/app_list/model/app_list_model.cc b/ash/app_list/model/app_list_model.cc
index 23241c9..38234f2 100644
--- a/ash/app_list/model/app_list_model.cc
+++ b/ash/app_list/model/app_list_model.cc
@@ -301,8 +301,12 @@
     std::unique_ptr<AppListItem> item_ptr,
     ReparentItemReason reason) {
   CHECK_NE(folder->id(), item_ptr->folder_id());
+
+  // Calling `AppListItemList::AddItem()` could trigger
+  // `AppListModel::SetItemMetadata()` so set the folder id before addition.
+  item_ptr->set_folder_id(folder->id());
+
   AppListItem* item = folder->item_list()->AddItem(std::move(item_ptr));
-  item->set_folder_id(folder->id());
   NotifyItemParentChange(item, reason);
   return item;
 }
diff --git a/ash/app_list/views/apps_grid_view.cc b/ash/app_list/views/apps_grid_view.cc
index e138763..c8804208 100644
--- a/ash/app_list/views/apps_grid_view.cc
+++ b/ash/app_list/views/apps_grid_view.cc
@@ -2843,6 +2843,10 @@
   current_ghost_view_ =
       items_container_->AddChildView(std::move(current_ghost_view));
   current_ghost_view_->FadeIn();
+
+  // Adding the ghost view can reorder the child layers of the
+  // |items_container_| so make sure the background cards remain at the bottom.
+  StackCardsAtBottom();
 }
 
 void AppsGridView::BeginHideCurrentGhostImageView() {
diff --git a/ash/app_list/views/apps_grid_view.h b/ash/app_list/views/apps_grid_view.h
index be1a2b8..74368757 100644
--- a/ash/app_list/views/apps_grid_view.h
+++ b/ash/app_list/views/apps_grid_view.h
@@ -452,6 +452,10 @@
   // that carries a closure to re-enable opacity updates.
   [[nodiscard]] virtual base::ScopedClosureRunner LockAppsGridOpacity() = 0;
 
+  // Makes sure that the background cards render behind everything
+  // else in the items container.
+  virtual void StackCardsAtBottom() {}
+
   // Sets the max number of columns that the grid can have.
   // For root apps grid view, the grid size depends on the space available to
   // apps grid view only, and `cols()` will match `max_columns`. I.e. if the
diff --git a/ash/app_list/views/apps_grid_view_unittest.cc b/ash/app_list/views/apps_grid_view_unittest.cc
index 95b7e5e..6e83664 100644
--- a/ash/app_list/views/apps_grid_view_unittest.cc
+++ b/ash/app_list/views/apps_grid_view_unittest.cc
@@ -33,6 +33,7 @@
 #include "ash/app_list/views/apps_grid_view_test_api.h"
 #include "ash/app_list/views/contents_view.h"
 #include "ash/app_list/views/expand_arrow_view.h"
+#include "ash/app_list/views/ghost_image_view.h"
 #include "ash/app_list/views/paged_apps_grid_view.h"
 #include "ash/app_list/views/scrollable_apps_grid_view.h"
 #include "ash/app_list/views/search_box_view.h"
@@ -506,6 +507,14 @@
     }
   }
 
+  views::View* GetItemsContainer() {
+    return apps_grid_view_->items_container();
+  }
+
+  views::View* GetCurrentGhostImageView() {
+    return apps_grid_view_->current_ghost_view_;
+  }
+
   // Calls the private method.
   static void DeleteItemAt(AppListItemList* item_list, size_t index) {
     item_list->DeleteItemAt(index);
@@ -4664,6 +4673,41 @@
                                      1);
 }
 
+// Test that the background cards remain stacked as the bottom layer during
+// an item drag. The adding of views to the apps grid during a drag (e.g. ghost
+// image view) can cause a reorder of layers.
+TEST_P(AppsGridViewCardifiedStateTest, BackgroundCardLayerOrderedAtBottom) {
+  ASSERT_TRUE(paged_apps_grid_view_);
+
+  // Create only one page with two apps.
+  model_->PopulateApps(2);
+
+  // Start cardified apps grid.
+  InitiateDragForItemAtCurrentPageAt(AppsGridView::TOUCH, 0, 0,
+                                     paged_apps_grid_view_);
+  ASSERT_TRUE(paged_apps_grid_view_->cardified_state_for_testing());
+  EXPECT_EQ(nullptr, GetCurrentGhostImageView());
+
+  if (features::IsProductivityLauncherEnabled()) {
+    test_api_->FireReorderTimerAndWaitForAnimationDone();
+    // Check that the ghost image view was created.
+    EXPECT_NE(nullptr, GetCurrentGhostImageView());
+  } else {
+    test_api_->LayoutToIdealBounds();
+  }
+
+  const int kExpectedBackgroundCardCount =
+      features::IsProductivityLauncherEnabled() ? 1 : 2;
+  ASSERT_EQ(kExpectedBackgroundCardCount,
+            paged_apps_grid_view_->BackgroundCardCountForTesting());
+
+  // Check that the first background card layer is stacked at the bottom.
+  EXPECT_EQ(paged_apps_grid_view_->GetBackgroundCardLayerForTesting(0),
+            GetItemsContainer()
+                ->layer()
+                ->children()[kExpectedBackgroundCardCount - 1]);
+}
+
 TEST_P(AppsGridViewCardifiedStateTest, PeekingCardOnLastPage) {
   ASSERT_TRUE(paged_apps_grid_view_);
 
diff --git a/ash/app_list/views/paged_apps_grid_view.cc b/ash/app_list/views/paged_apps_grid_view.cc
index 1ee6834..21004f2 100644
--- a/ash/app_list/views/paged_apps_grid_view.cc
+++ b/ash/app_list/views/paged_apps_grid_view.cc
@@ -903,6 +903,12 @@
   return gfx::Rect(origin_in_apps_grid, bounds_in_items_container.size());
 }
 
+ui::Layer* PagedAppsGridView::GetBackgroundCardLayerForTesting(
+    size_t card_index) const {
+  DCHECK_LT(card_index, background_cards_.size());
+  return background_cards_[card_index].get();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // private:
 
@@ -1450,4 +1456,10 @@
          (shown_under_recent_apps_ ? 2 * first_page_vertical_tile_padding_ : 0);
 }
 
+void PagedAppsGridView::StackCardsAtBottom() {
+  for (size_t i = 0; i < background_cards_.size(); ++i) {
+    items_container()->layer()->StackAtBottom(background_cards_[i].get());
+  }
+}
+
 }  // namespace ash
diff --git a/ash/app_list/views/paged_apps_grid_view.h b/ash/app_list/views/paged_apps_grid_view.h
index 7962f6d..af922838 100644
--- a/ash/app_list/views/paged_apps_grid_view.h
+++ b/ash/app_list/views/paged_apps_grid_view.h
@@ -159,6 +159,7 @@
   // Returns bounds within the apps grid view for the background card layer
   // with provided card index.
   gfx::Rect GetBackgroundCardBoundsForTesting(size_t card_index);
+  ui::Layer* GetBackgroundCardLayerForTesting(size_t card_index) const;
   void set_page_flip_delay_for_testing(base::TimeDelta page_flip_delay) {
     page_flip_delay_ = page_flip_delay;
   }
@@ -343,6 +344,8 @@
   // cardified state's background cards.
   int margin_for_gradient_mask_ = 0;
 
+  void StackCardsAtBottom() override;
+
   // If true, ignore the calls on `UpdateOpacity()`.
   bool lock_opacity_ = false;
 
diff --git a/ash/webui/personalization_app/BUILD.gn b/ash/webui/personalization_app/BUILD.gn
index 069e21f..87f04aa 100644
--- a/ash/webui/personalization_app/BUILD.gn
+++ b/ash/webui/personalization_app/BUILD.gn
@@ -17,8 +17,6 @@
     "personalization_app_url_constants.h",
     "personalization_app_user_provider.h",
     "personalization_app_wallpaper_provider.h",
-    "untrusted_personalization_app_ui_config.cc",
-    "untrusted_personalization_app_ui_config.h",
   ]
 
   deps = [
diff --git a/ash/webui/personalization_app/personalization_app_ui.cc b/ash/webui/personalization_app/personalization_app_ui.cc
index dd5b985..5e32086 100644
--- a/ash/webui/personalization_app/personalization_app_ui.cc
+++ b/ash/webui/personalization_app/personalization_app_ui.cc
@@ -33,22 +33,10 @@
   return GURL(kGooglePhotosURL);
 }
 
-bool ShouldIncludeResource(const webui::ResourcePath& resource) {
-  return base::StartsWith(resource.path, "trusted") ||
-         base::StartsWith(resource.path, "common") ||
-         resource.id == IDR_ASH_PERSONALIZATION_APP_ICON_192_PNG;
-}
-
 void AddResources(content::WebUIDataSource* source) {
   source->AddResourcePath("", IDR_ASH_PERSONALIZATION_APP_TRUSTED_INDEX_HTML);
-
-  const auto resources = base::make_span(kAshPersonalizationAppResources,
-                                         kAshPersonalizationAppResourcesSize);
-
-  for (const auto& resource : resources) {
-    if (ShouldIncludeResource(resource))
-      source->AddResourcePath(resource.path, resource.id);
-  }
+  source->AddResourcePaths(base::make_span(
+      kAshPersonalizationAppResources, kAshPersonalizationAppResourcesSize));
   source->AddResourcePath("test_loader.html", IDR_WEBUI_HTML_TEST_LOADER_HTML);
   source->AddResourcePath("test_loader.js", IDR_WEBUI_JS_TEST_LOADER_JS);
   source->AddResourcePath("test_loader_util.js",
@@ -210,13 +198,6 @@
       "script-src chrome://resources chrome://test chrome://webui-test "
       "'self';");
 
-  // Allow requesting a chrome-untrusted://personalization/ iframe.
-  web_ui->AddRequestableScheme(content::kChromeUIUntrustedScheme);
-  source->OverrideContentSecurityPolicy(
-      network::mojom::CSPDirectiveName::FrameSrc,
-      base::StrCat(
-          {"frame-src ", kChromeUIUntrustedPersonalizationAppURL, ";"}));
-
   // TODO(crbug.com/1098690): Trusted Type Polymer
   source->DisableTrustedTypesCSP();
 
diff --git a/ash/webui/personalization_app/personalization_app_url_constants.cc b/ash/webui/personalization_app/personalization_app_url_constants.cc
index 5eb030e..5663567 100644
--- a/ash/webui/personalization_app/personalization_app_url_constants.cc
+++ b/ash/webui/personalization_app/personalization_app_url_constants.cc
@@ -14,7 +14,5 @@
     "chrome://personalization/user";
 const char kChromeUIPersonalizationAppWallpaperSubpageURL[] =
     "chrome://personalization/wallpaper";
-const char kChromeUIUntrustedPersonalizationAppURL[] =
-    "chrome-untrusted://personalization/";
 
 }  // namespace ash
diff --git a/ash/webui/personalization_app/personalization_app_url_constants.h b/ash/webui/personalization_app/personalization_app_url_constants.h
index b5ee39e..f209803 100644
--- a/ash/webui/personalization_app/personalization_app_url_constants.h
+++ b/ash/webui/personalization_app/personalization_app_url_constants.h
@@ -12,7 +12,6 @@
 extern const char kChromeUIPersonalizationAppAmbientModeSubpageURL[];
 extern const char kChromeUIPersonalizationAppUserSubpageURL[];
 extern const char kChromeUIPersonalizationAppWallpaperSubpageURL[];
-extern const char kChromeUIUntrustedPersonalizationAppURL[];
 
 }  // namespace ash
 
diff --git a/ash/webui/personalization_app/resources/BUILD.gn b/ash/webui/personalization_app/resources/BUILD.gn
index 8ff05ed..08d823d 100644
--- a/ash/webui/personalization_app/resources/BUILD.gn
+++ b/ash/webui/personalization_app/resources/BUILD.gn
@@ -101,7 +101,6 @@
 
   "untrusted/collections_grid.ts",
   "untrusted/images_grid.ts",
-  "untrusted/styles.ts",
 ]
 
 static_resource_files = [
@@ -112,9 +111,6 @@
   "common/no_images.svg",
 
   "trusted/index.html",
-
-  "untrusted/collections.html",
-  "untrusted/images.html",
 ]
 
 html_to_js("web_components") {
diff --git a/ash/webui/personalization_app/resources/common/constants.ts b/ash/webui/personalization_app/resources/common/constants.ts
index 29cb6e9..cef19ab8 100644
--- a/ash/webui/personalization_app/resources/common/constants.ts
+++ b/ash/webui/personalization_app/resources/common/constants.ts
@@ -2,19 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-/**
- * @fileoverview TODO(cowmoo)
- */
-
-
 import {FilePath} from 'chrome://resources/mojo/mojo/public/mojom/base/file_path.mojom-webui.js';
-
 import {Url} from 'chrome://resources/mojo/url/mojom/url.mojom-webui.js';
 
 import {WallpaperCollection} from '../trusted/personalization_app.mojom-webui.js';
 
-export const untrustedOrigin = 'chrome-untrusted://personalization';
-
 export const trustedOrigin = 'chrome://personalization';
 
 export const kMaximumGooglePhotosPreviews = 4;
diff --git a/ash/webui/personalization_app/resources/trusted/iframe_api.ts b/ash/webui/personalization_app/resources/trusted/iframe_api.ts
index 60c1fda..2b4c333 100644
--- a/ash/webui/personalization_app/resources/trusted/iframe_api.ts
+++ b/ash/webui/personalization_app/resources/trusted/iframe_api.ts
@@ -14,41 +14,48 @@
 
 import * as constants from '../common/constants.js';
 import {isNonEmptyArray} from '../common/utils.js';
+import {CollectionsGrid} from '../untrusted/collections_grid.js';
+import {ImagesGrid} from '../untrusted/images_grid.js';
 
 import {WallpaperCollection, WallpaperImage} from './personalization_app.mojom-webui.js';
 
+/**
+ * TODO(b:197023872) this class is deprecated and should be removed by more
+ * post-iframe cleanup.
+ */
 export class IFrameApi {
   /**
    * Send an array of wallpaper collections to untrusted.
    */
-  sendCollections(target: Window, collections: Array<WallpaperCollection>) {
+  sendCollections(
+      target: CollectionsGrid, collections: Array<WallpaperCollection>) {
     const event: constants.SendCollectionsEvent = {
       type: constants.EventType.SEND_COLLECTIONS,
       collections
     };
-    target.postMessage(event, constants.untrustedOrigin);
+    target.onMessageReceived(event);
   }
 
   /**
    * Sends the count of Google Photos photos to untrusted.
    */
-  sendGooglePhotosCount(target: Window, count: number|null) {
+  sendGooglePhotosCount(target: CollectionsGrid, count: number|null) {
     const event: constants.SendGooglePhotosCountEvent = {
       type: constants.EventType.SEND_GOOGLE_PHOTOS_COUNT,
       count
     };
-    target.postMessage(event, constants.untrustedOrigin);
+    target.onMessageReceived(event);
   }
 
   /**
    * Sends the list of Google Photos photos to untrusted.
    */
-  sendGooglePhotosPhotos(target: Window, photos: Array<Url>|null) {
+  sendGooglePhotosPhotos(target: CollectionsGrid, photos: Array<Url>|null) {
     const event: constants.SendGooglePhotosPhotosEvent = {
       type: constants.EventType.SEND_GOOGLE_PHOTOS_PHOTOS,
       photos
     };
-    target.postMessage(event, constants.untrustedOrigin);
+    target.onMessageReceived(event);
   }
 
   /**
@@ -56,12 +63,13 @@
    * A value of null for a given collection id represents that the collection
    * failed to load.
    */
-  sendImageCounts(target: Window, counts: {[key: string]: number|null}) {
+  sendImageCounts(
+      target: CollectionsGrid, counts: {[key: string]: number|null}) {
     const event: constants.SendImageCountsEvent = {
       type: constants.EventType.SEND_IMAGE_COUNTS,
       counts
     };
-    target.postMessage(event, constants.untrustedOrigin);
+    target.onMessageReceived(event);
   }
 
   /**
@@ -69,89 +77,88 @@
    * resize event on iron-list when an iframe becomes visible again so that
    * iron-list will run layout with the current size.
    */
-  sendVisible(target: Window, visible: boolean) {
+  sendVisible(target: CollectionsGrid|ImagesGrid, visible: boolean) {
     const event: constants.SendVisibleEvent = {
       type: constants.EventType.SEND_VISIBLE,
       visible
     };
-    target.postMessage(event, constants.untrustedOrigin);
+    target.onMessageReceived(event);
   }
 
   /**
    * Send an array of wallpaper images to chrome-untrusted://.
    * Will clear the page if images is empty array.
    */
-  sendImageTiles(target: Window, tiles: constants.ImageTile[]) {
+  sendImageTiles(target: ImagesGrid, tiles: constants.ImageTile[]) {
     const event: constants.SendImageTilesEvent = {
       type: constants.EventType.SEND_IMAGE_TILES,
       tiles
     };
-    target.postMessage(event, constants.untrustedOrigin);
+    target.onMessageReceived(event);
   }
 
   /**
    * Send an array of local images to chrome-untrusted://.
    */
-  sendLocalImages(target: Window, images: FilePath[]) {
+  sendLocalImages(target: CollectionsGrid, images: FilePath[]) {
     const event: constants.SendLocalImagesEvent = {
       type: constants.EventType.SEND_LOCAL_IMAGES,
       images
     };
-    target.postMessage(event, constants.untrustedOrigin);
+    target.onMessageReceived(event);
   }
 
   /**
    * Sends image data keyed by stringified image id.
    */
-  sendLocalImageData(target: Window, data: Record<string, string>) {
+  sendLocalImageData(target: CollectionsGrid, data: Record<string, string>) {
     const event: constants.SendLocalImageDataEvent = {
       type: constants.EventType.SEND_LOCAL_IMAGE_DATA,
       data
     };
-    target.postMessage(event, constants.untrustedOrigin);
+    target.onMessageReceived(event);
   }
 
   /**
-   * Send the |assetId| of the currently selected wallpaper to |target| iframe
-   * window. Sending null indicates that no image is selected.
+   * Send the |assetId| of the currently selected wallpaper to |target|.
+   * Sending null indicates that no image is selected.
    */
-  sendCurrentWallpaperAssetId(target: Window, assetId: bigint|undefined) {
+  sendCurrentWallpaperAssetId(target: ImagesGrid, assetId: bigint|undefined) {
     const event: constants.SendCurrentWallpaperAssetIdEvent = {
       type: constants.EventType.SEND_CURRENT_WALLPAPER_ASSET_ID,
       assetId
     };
-    target.postMessage(event, constants.untrustedOrigin);
+    target.onMessageReceived(event);
   }
 
   /**
-   * Send the |assetId| to the |target| iframe when the user clicks on online
-   * wallpaper image.
+   * Send the |assetId| to the |target| when the user clicks on online wallpaper
+   * image.
    */
-  sendPendingWallpaperAssetId(target: Window, assetId: bigint|undefined) {
+  sendPendingWallpaperAssetId(target: ImagesGrid, assetId: bigint|undefined) {
     const event: constants.SendPendingWallpaperAssetIdEvent = {
       type: constants.EventType.SEND_PENDING_WALLPAPER_ASSET_ID,
       assetId
     };
-    target.postMessage(event, constants.untrustedOrigin);
+    target.onMessageReceived(event);
   }
 
 
   /**
-   * Called from trusted code to validate that a received postMessage event
-   * contains valid data. Ignores messages that are not of the expected type.
+   * Called from trusted code to validate that a received event contains valid
+   * data. Ignores messages that are not of the expected type.
    */
   validateReceivedSelection(
-      event: MessageEvent,
+      data: constants.Events,
       choices: WallpaperCollection[]|null): WallpaperCollection;
   validateReceivedSelection(
-      event: MessageEvent, choices: WallpaperImage[]|null): WallpaperImage;
+      data: constants.Events, choices: WallpaperImage[]|null): WallpaperImage;
   validateReceivedSelection(
-      event: MessageEvent,
+      data: constants.Events,
       choices: (WallpaperCollection|WallpaperImage)[]|null): WallpaperCollection
       |WallpaperImage {
     assert(isNonEmptyArray(choices), 'choices must be a non-empty array');
 
-    const data: constants.Events = event.data;
     let selected: WallpaperCollection|WallpaperImage|undefined = undefined;
     switch (data.type) {
       case constants.EventType.SELECT_COLLECTION: {
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/index.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/index.ts
index 2c679cf..451abd7 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper/index.ts
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/index.ts
@@ -16,15 +16,14 @@
 import './wallpaper_preview_element.js';
 import './wallpaper_selected_element.js';
 import './wallpaper_subpage_element.js';
+import '../../untrusted/collections_grid.js';
+import '../../untrusted/images_grid.js';
 import './styles.js';
 
-import {onMessageReceived} from './untrusted_message_handler.js';
 import {WallpaperObserver} from './wallpaper_observer.js';
 
 WallpaperObserver.initWallpaperObserverIfNeeded();
 
-window.addEventListener('message', onMessageReceived);
-
 function reload(): void {
   window.location.reload();
 }
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/styles.html b/ash/webui/personalization_app/resources/trusted/wallpaper/styles.html
index 782b9ddf..a29c0ad 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper/styles.html
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/styles.html
@@ -1,8 +1,6 @@
 <template>
   <style>
-    /* There is a corresponding media query for iframe grids because media
-     * queries inside iframes reference width of the frame, not the entire
-     * window. Use !important to make sure there are no css ordering issues.
+    /* Use !important to make sure there are no css ordering issues.
      * Subtract 0.25px to fix subpixel rounding issues with iron-list. This
      * makes sure all photo containers on a row add up to at least 1px smaller
      * than the parent width.*/
@@ -12,17 +10,13 @@
         width: calc(25% - 0.25px) !important;
       }
     }
-    main,
-    iframe {
+    main {
       height: 100%;
       width: 100%;
     }
     main:focus,
     main:focus-visible,
-    main:focus-within,
-    iframe:focus,
-    iframe:focus-visible,
-    iframe:focus-within {
+    main:focus-within {
       outline: none;
     }
   </style>
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/untrusted_message_handler.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/untrusted_message_handler.ts
index 95b97e6..2f3bb222 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper/untrusted_message_handler.ts
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/untrusted_message_handler.ts
@@ -2,9 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {assert} from 'chrome://resources/js/assert.m.js';
-
-import {Events, EventType, untrustedOrigin} from '../../common/constants.js';
+import {Events, EventType} from '../../common/constants.js';
 import {IFrameApi} from '../iframe_api.js';
 import {Paths, PersonalizationRouter} from '../personalization_router_element.js';
 import {PersonalizationStore} from '../personalization_store.js';
@@ -16,19 +14,15 @@
  * @fileoverview message handler that receives data from untrusted.
  */
 
-export function onMessageReceived(event: MessageEvent) {
-  assert(
-      event.origin === untrustedOrigin, 'Message not from the correct origin');
-
+export function onMessageReceived(data: Events) {
   const store = PersonalizationStore.getInstance();
 
-  const data = event.data as Events;
   switch (data.type) {
     case EventType.SELECT_COLLECTION:
       const collections = store.data.wallpaper.backdrop.collections;
 
       const selectedCollection =
-          IFrameApi.getInstance().validateReceivedSelection(event, collections);
+          IFrameApi.getInstance().validateReceivedSelection(data, collections);
       PersonalizationRouter.instance().selectCollection(selectedCollection);
       break;
     case EventType.SELECT_GOOGLE_PHOTOS_COLLECTION:
@@ -45,7 +39,7 @@
       }
       const images = store.data.wallpaper.backdrop.images[collectionId];
       const selectedImage =
-          IFrameApi.getInstance().validateReceivedSelection(event, images);
+          IFrameApi.getInstance().validateReceivedSelection(data, images);
       selectWallpaper(selectedImage, getWallpaperProvider(), store);
       break;
   }
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_collections_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_collections_element.html
index 09f2ce1..4ab5bc83 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_collections_element.html
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_collections_element.html
@@ -2,7 +2,6 @@
 <template is="dom-if" if="[[hasError_]]">
   <wallpaper-error></wallpaper-error>
 </template>
-<iframe id="collections-iframe" frameBorder="0" hidden$="[[hasError_]]"
-    src="chrome-untrusted://personalization/untrusted/collections.html"
-    role="main" aria-label="$i18n{wallpaperCollections}">
-</iframe>
+<main aria-label="$i18n{wallpaperCollections}" hidden$="[[hasError_]]">
+  <collections-grid id="collectionsGrid"></collections-grid>
+</main>
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_collections_element.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_collections_element.ts
index d16f231..c14faba 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_collections_element.ts
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_collections_element.ts
@@ -11,10 +11,11 @@
 import './styles.js';
 
 import {FilePath} from 'chrome://resources/mojo/mojo/public/mojom/base/file_path.mojom-webui.js';
-import {afterNextRender, html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {kMaximumGooglePhotosPreviews, kMaximumLocalImagePreviews} from '../../common/constants.js';
-import {isNonEmptyArray, isNullOrArray, isNullOrNumber, promisifyOnload} from '../../common/utils.js';
+import {isNonEmptyArray, isNullOrArray, isNullOrNumber} from '../../common/utils.js';
+import {CollectionsGrid} from '../../untrusted/collections_grid.js';
 import {IFrameApi} from '../iframe_api.js';
 import {GooglePhotosPhoto, WallpaperCollection, WallpaperImage, WallpaperProviderInterface} from '../personalization_app.mojom-webui.js';
 import {WithPersonalizationStore} from '../personalization_store.js';
@@ -22,6 +23,10 @@
 import {initializeBackdropData} from './wallpaper_controller.js';
 import {getWallpaperProvider} from './wallpaper_interface_provider.js';
 
+export interface WallpaperCollections {
+  $: {collectionsGrid: CollectionsGrid;}
+}
+
 export class WallpaperCollections extends WithPersonalizationStore {
   static get is() {
     return 'wallpaper-collections';
@@ -33,10 +38,7 @@
 
   static get properties() {
     return {
-      /**
-       * Hidden state of this element. Used to notify iframe of visibility
-       * changes.
-       */
+      /** Hidden state of this element. Used to notify of visibility changes. */
       hidden: {
         type: Boolean,
         reflectToAttribute: true,
@@ -120,7 +122,6 @@
   private hasError_: boolean;
 
   private wallpaperProvider_: WallpaperProviderInterface;
-  private iframePromise_: Promise<HTMLIFrameElement>;
   private didSendLocalImageData_: boolean;
 
 
@@ -138,9 +139,6 @@
   constructor() {
     super();
     this.wallpaperProvider_ = getWallpaperProvider();
-    this.iframePromise_ =
-        promisifyOnload(this, 'collections-iframe', afterNextRender) as
-        Promise<HTMLIFrameElement>;
     this.didSendLocalImageData_ = false;
   }
 
@@ -171,14 +169,13 @@
   }
 
   /**
-   * Notify iframe that this element visibility has changed.
+   * Notify that this element visibility has changed.
    */
   private async onHiddenChanged_(hidden: boolean) {
     if (!hidden) {
       document.title = this.i18n('wallpaperLabel');
     }
-    const iframe = await this.iframePromise_;
-    IFrameApi.getInstance().sendVisible(iframe.contentWindow!, !hidden);
+    IFrameApi.getInstance().sendVisible(this.$.collectionsGrid, !hidden);
   }
 
   private computeHasError_(
@@ -199,14 +196,13 @@
     return !localImagesLoading && !isNonEmptyArray(localImages);
   }
 
-  private async onCollectionsChanged_(
+  private onCollectionsChanged_(
       collections: WallpaperCollection[], collectionsLoading: boolean) {
-    // Check whether collections are loaded before sending to
-    // the iframe. Collections could be null/empty array.
+    // Check whether collections are loaded before sending. Collections could be
+    // null/empty array.
     if (!collectionsLoading) {
-      const iframe = await this.iframePromise_;
       IFrameApi.getInstance().sendCollections(
-          iframe.contentWindow!, collections);
+          this.$.collectionsGrid, collections);
     }
   }
 
@@ -214,7 +210,7 @@
    * Send count of image units in each collection when a new collection is
    * fetched. D/L variants of the same image represent a count of 1.
    */
-  private async onCollectionImagesChanged_(
+  private onCollectionImagesChanged_(
       images: Record<string, WallpaperImage[]>,
       imagesLoading: Record<string, boolean>) {
     if (!images || !imagesLoading) {
@@ -242,52 +238,48 @@
                          result[key!] = value;
                          return result;
                        }, {} as Record<string, number|null>);
-    const iframe = await this.iframePromise_;
-    IFrameApi.getInstance().sendImageCounts(iframe.contentWindow!, counts);
+    IFrameApi.getInstance().sendImageCounts(this.$.collectionsGrid, counts);
   }
 
   /** Invoked on changes to the list of Google Photos photos. */
-  private async onGooglePhotosChanged_(
+  private onGooglePhotosChanged_(
       googlePhotos: GooglePhotosPhoto[]|null, googlePhotosLoading: boolean) {
     if (googlePhotosLoading || !isNullOrArray(googlePhotos)) {
       return;
     }
-    const iframe = await this.iframePromise_;
     IFrameApi.getInstance().sendGooglePhotosPhotos(
-        iframe.contentWindow!,
+        this.$.collectionsGrid,
         googlePhotos?.slice(0, kMaximumGooglePhotosPreviews)
                 ?.map(googlePhoto => googlePhoto.url) ??
             null);
   }
 
   /** Invoked on changes to the count of Google Photos photos. */
-  private async onGooglePhotosCountChanged_(
+  private onGooglePhotosCountChanged_(
       googlePhotosCount: number|null, googlePhotosCountLoading: boolean) {
     if (googlePhotosCountLoading || !isNullOrNumber(googlePhotosCount)) {
       return;
     }
-    const iframe = await this.iframePromise_;
     IFrameApi.getInstance().sendGooglePhotosCount(
-        iframe.contentWindow!, googlePhotosCount);
+        this.$.collectionsGrid, googlePhotosCount);
   }
 
   /**
-   * Send updated local images list to the iframe.
+   * Send updated local images list.
    */
-  private async onLocalImagesChanged_(
+  private onLocalImagesChanged_(
       localImages: FilePath[]|null, localImagesLoading: boolean) {
     this.didSendLocalImageData_ = false;
     if (!localImagesLoading && Array.isArray(localImages)) {
-      const iframe = await this.iframePromise_;
       IFrameApi.getInstance().sendLocalImages(
-          iframe.contentWindow!, localImages);
+          this.$.collectionsGrid, localImages);
     }
   }
 
   /**
-   * Send up to |maximumImageThumbnailsCount| image thumbnails to untrusted.
+   * Send up to |maximumImageThumbnailsCount| image thumbnails.
    */
-  private async onLocalImageDataChanged_(
+  private onLocalImageDataChanged_(
       images: FilePath[]|null, imageData: Record<string, string>,
       imageDataLoading: Record<string, boolean>) {
     if (!Array.isArray(images) || !imageData || !imageDataLoading ||
@@ -344,8 +336,7 @@
 
       this.didSendLocalImageData_ = true;
 
-      const iframe = await this.iframePromise_;
-      IFrameApi.getInstance().sendLocalImageData(iframe.contentWindow!, data);
+      IFrameApi.getInstance().sendLocalImageData(this.$.collectionsGrid, data);
     }
   }
 }
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_images_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_images_element.html
index ab7bb20b..0394843 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_images_element.html
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_images_element.html
@@ -1,10 +1,8 @@
-<style include="trusted-style">
-</style>
+<style include="trusted-style"></style>
 <main id="main" tabindex="-1"
     aria-label$="[[getMainAriaLabel_(collectionId, collections_)]]">
   <iron-media-query query="(prefers-color-scheme: dark)"
     query-matches="{{isDarkModeActive_}}">
   </iron-media-query>
-  <iframe frameBorder="0" id="images-iframe"
-      src="chrome-untrusted://personalization/untrusted/images.html"></iframe>
+  <images-grid id="imagesGrid"></images-grid>
 </main>
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_images_element.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_images_element.ts
index ccf4a675..87153e7 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_images_element.ts
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_images_element.ts
@@ -13,10 +13,11 @@
 import './styles.js';
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {afterNextRender, html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {ImageTile} from '../../common/constants.js';
-import {isNonEmptyArray, promisifyOnload} from '../../common/utils.js';
+import {isNonEmptyArray} from '../../common/utils.js';
+import {ImagesGrid} from '../../untrusted/images_grid.js';
 import {IFrameApi} from '../iframe_api.js';
 import {CurrentWallpaper, OnlineImageType, WallpaperCollection, WallpaperImage, WallpaperType} from '../personalization_app.mojom-webui.js';
 import {DisplayableImage} from '../personalization_reducers.js';
@@ -89,6 +90,10 @@
   return [...tileMap.values()];
 }
 
+export interface WallpaperImages {
+  $: {imagesGrid: ImagesGrid;}
+}
+
 export class WallpaperImages extends WithPersonalizationStore {
   static get is() {
     return 'wallpaper-images';
@@ -181,21 +186,12 @@
   private hasImages_: boolean;
   private isDarkModeActive_: boolean;
 
-  private iframePromise_: Promise<HTMLIFrameElement>;
-
   static get observers() {
     return [
       'onImagesUpdated_(hasImages_, hasError_, collectionId, isDarkModeActive_)',
     ];
   }
 
-  constructor() {
-    super();
-    this.iframePromise_ =
-        promisifyOnload(this, 'images-iframe', afterNextRender) as
-        Promise<HTMLIFrameElement>;
-  }
-
   connectedCallback() {
     super.connectedCallback();
     this.watch<WallpaperImages['images_']>(
@@ -216,26 +212,22 @@
   /**
    * Notify iframe that this element visibility has changed.
    */
-  private async onHiddenChanged_(hidden: boolean) {
+  private onHiddenChanged_(hidden: boolean) {
     if (!hidden) {
       this.shadowRoot!.getElementById('main')!.focus();
     }
-    const iframe = await this.iframePromise_;
-    IFrameApi.getInstance().sendVisible(iframe.contentWindow!, !hidden);
+    IFrameApi.getInstance().sendVisible(this.$.imagesGrid, !hidden);
   }
 
-  private async onCurrentSelectedChanged_(selected: CurrentWallpaper|null) {
+  private onCurrentSelectedChanged_(selected: CurrentWallpaper|null) {
     const assetId = getAssetId(selected);
-    const iframe = await this.iframePromise_;
     IFrameApi.getInstance().sendCurrentWallpaperAssetId(
-        iframe.contentWindow!, assetId);
+        this.$.imagesGrid, assetId);
   }
 
-  private async onPendingSelectedChanged_(pendingSelected: DisplayableImage|
-                                          null) {
-    const iframe = await this.iframePromise_;
+  private onPendingSelectedChanged_(pendingSelected: DisplayableImage|null) {
     IFrameApi.getInstance().sendPendingWallpaperAssetId(
-        iframe.contentWindow!,
+        this.$.imagesGrid,
         isWallpaperImage(pendingSelected) ? pendingSelected.assetId :
                                             undefined);
   }
@@ -280,7 +272,7 @@
    * Send images if loading is ready and we have some images. Punt back to
    * main page if there is an error viewing this collection.
    */
-  private async onImagesUpdated_(
+  private onImagesUpdated_(
       hasImages: boolean, hasError: boolean, collectionId: string,
       isDarkModeActive: boolean) {
     if (hasError) {
@@ -291,17 +283,16 @@
     }
 
     if (hasImages && collectionId) {
-      const iframe = await this.iframePromise_;
       const imageArr = this.images_[collectionId];
       const isDarkLightModeEnabled =
           loadTimeData.getBoolean('isDarkLightModeEnabled');
       if (isDarkLightModeEnabled) {
         IFrameApi.getInstance().sendImageTiles(
-            iframe.contentWindow!,
+            this.$.imagesGrid,
             getDarkLightImageTiles(isDarkModeActive, imageArr!));
       } else {
         IFrameApi.getInstance().sendImageTiles(
-            iframe.contentWindow!, getRegularImageTiles(imageArr!));
+            this.$.imagesGrid, getRegularImageTiles(imageArr!));
       }
     }
   }
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.html
index b94a8d0..01e88c0 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.html
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.html
@@ -7,7 +7,7 @@
       '. leftspacer imagegrid  rightspacer .'
       '. leftspacer .          rightspacer .';
     grid-template-columns: 1fr 16px minmax(568px, 920px) 16px 1fr;
-    grid-template-rows: 172px 12px 1fr 12px;
+    grid-template-rows: 172px 12px minmax(0, 1fr) 12px;
     height: 100%;
     position: relative;
     width: 100%;
diff --git a/ash/webui/personalization_app/resources/untrusted/collections.html b/ash/webui/personalization_app/resources/untrusted/collections.html
deleted file mode 100644
index 02d6463..0000000
--- a/ash/webui/personalization_app/resources/untrusted/collections.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!doctype html>
-<html dir="$i18n{textdirection}" lang="$i18n{language}">
-<head>
-  <meta charset="utf-8">
-  <link rel="stylesheet" href="/common/base.css">
-  <link rel="stylesheet" href="//resources/chromeos/colors/cros_styles.css">
-  <script type="module" src="collections_grid.js" defer></script>
-</head>
-<body>
-  <collections-grid></collections-grid>
-</body>
-</html>
diff --git a/ash/webui/personalization_app/resources/untrusted/collections_grid.html b/ash/webui/personalization_app/resources/untrusted/collections_grid.html
index 52fed048..cf297fa 100644
--- a/ash/webui/personalization_app/resources/untrusted/collections_grid.html
+++ b/ash/webui/personalization_app/resources/untrusted/collections_grid.html
@@ -1,9 +1,9 @@
-<style include="common-style untrusted-style">
+<style include="common-style trusted-style">
   :host {
     margin: 12px 0;
   }
 </style>
-<iron-list items="[[tiles_]]" grid scroll-target="document">
+<iron-list items="[[tiles_]]" grid>
   <template>
     <div class="photo-container">
       <template is="dom-if" if="[[isLoadingTile_(item)]]">
@@ -18,7 +18,8 @@
             class="photo-inner-container photo-loading-failure">
           <div class$="[[getClassForImagesContainer_(item)]]">
             <template is="dom-repeat" items="[[item.preview]]" as="preview">
-              <img src$="[[preview.url]]" aria-hidden="true">
+              <img is="cr-auto-img" auto-src="[[preview.url]]"
+                  aria-hidden="true">
             </template>
           </div>
           <div class="photo-text-container">
@@ -35,7 +36,8 @@
             class$="[[getClassForEmptyTile_(item)]]" selectable$="[[isSelectableTile_(item)]]"
             on-click="onCollectionSelected_" on-keypress="onCollectionSelected_">
           <div class$="[[getClassForImagesContainer_(item)]]">
-            <img src$="[[getImageUrlForEmptyTile_(item)]]" aria-hidden="true">
+            <img is="cr-auto-img" auto-src="[[getImageUrlForEmptyTile_(item)]]"
+                aria-hidden="true">
           </div>
           <div class="photo-text-container">
             <p title$="[[item.name]]">[[item.name]]</p>
@@ -49,8 +51,8 @@
             on-keypress="onCollectionSelected_" tabindex$="[[tabIndex]]" role="button">
           <div class$="[[getClassForImagesContainer_(item)]]">
             <template is="dom-repeat" items="[[item.preview]]" as="preview">
-              <img src="[[preview.url]]" aria-hidden="true"
-                  on-load="onImgLoad_" on-error="onImgLoad_">
+              <img is="cr-auto-img" auto-src="[[preview.url]]"
+                  aria-hidden="true" on-load="onImgLoad_" on-error="onImgLoad_">
             </template>
           </div>
           <div class="photo-text-container" hidden>
diff --git a/ash/webui/personalization_app/resources/untrusted/collections_grid.ts b/ash/webui/personalization_app/resources/untrusted/collections_grid.ts
index 9574ec4..d637089 100644
--- a/ash/webui/personalization_app/resources/untrusted/collections_grid.ts
+++ b/ash/webui/personalization_app/resources/untrusted/collections_grid.ts
@@ -4,13 +4,16 @@
 
 import '//resources/polymer/v3_0/iron-list/iron-list.js';
 import './setup.js';
-import './styles.js';
+import '../trusted/wallpaper/styles.js';
 
 import {loadTimeData} from '//resources/js/load_time_data.m.js';
 import {afterNextRender, html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {FilePath} from 'chrome://resources/mojo/mojo/public/mojom/base/file_path.mojom-webui.js';
+import {Url} from 'chrome://resources/mojo/url/mojom/url.mojom-webui.js';
 
 import {Events, EventType, kMaximumGooglePhotosPreviews, kMaximumLocalImagePreviews} from '../common/constants.js';
 import {getCountText, getLoadingPlaceholderAnimationDelay, getNumberOfGridItemsPerRow, isNullOrArray, isNullOrNumber, isSelectionEvent} from '../common/utils.js';
+import {WallpaperCollection} from '../trusted/personalization_app.mojom-webui.js';
 import {selectCollection, selectGooglePhotosCollection, selectLocalCollection, validateReceivedData} from '../untrusted/iframe_api.js';
 
 /**
@@ -30,23 +33,6 @@
   FAILURE = 'failure',
 }
 
-/** mirror from mojom type, cannot use mojom type directly from untrusted. */
-type Url = {
-  url: string
-};
-
-/** mirror from mojom type, cannot use mojom type directly from untrusted. */
-type FilePath = {
-  path: string
-};
-
-/** mirror from mojom type, cannot use mojom type directly from untrusted. */
-type WallpaperCollection = {
-  id: string,
-  name: string,
-  preview?: Url,
-};
-
 type LoadingTile = {
   type: TileType.LOADING
 };
@@ -215,20 +201,6 @@
     ];
   }
 
-  constructor() {
-    super();
-    this.onMessageReceived_ = this.onMessageReceived_.bind(this);
-  }
-
-  connectedCallback() {
-    super.connectedCallback();
-    window.addEventListener('message', this.onMessageReceived_);
-  }
-
-  disconnectedCallback() {
-    super.disconnectedCallback();
-    window.removeEventListener('message', this.onMessageReceived_);
-  }
 
   getLoadingPlaceholderAnimationDelay(index: number): string {
     return getLoadingPlaceholderAnimationDelay(index);
@@ -313,12 +285,11 @@
   }
 
   /**
-   * Handler for messages from trusted code. Expects only SendImagesEvent and
-   * will error on any other event.
+   * Handler for messages from trusted code.
+   * TODO(cowmoo) move this up beneath static properties because it is public.
    */
-  private onMessageReceived_(message: MessageEvent) {
-    const event = message.data as Events;
-    const isValid = validateReceivedData(event, message.origin);
+  onMessageReceived(event: Events) {
+    const isValid = validateReceivedData(event);
     if (!isValid) {
       console.warn('Invalid event message received, event type: ' + event.type);
     }
@@ -380,7 +351,7 @@
         }
         return;
       default:
-        console.error(`Unexpected event type ${message.data.type}`);
+        console.error(`Unexpected event type ${event.type}`);
         break;
     }
   }
@@ -413,13 +384,13 @@
     }
     switch (tile.id) {
       case kGooglePhotosCollectionId:
-        selectGooglePhotosCollection(window.parent);
+        selectGooglePhotosCollection();
         return;
       case kLocalCollectionId:
-        selectLocalCollection(window.parent);
+        selectLocalCollection();
         return;
       default:
-        selectCollection(window.parent, tile.id);
+        selectCollection(tile.id);
         return;
     }
   }
diff --git a/ash/webui/personalization_app/resources/untrusted/iframe_api.ts b/ash/webui/personalization_app/resources/untrusted/iframe_api.ts
index ddbdef5..98ff28c 100644
--- a/ash/webui/personalization_app/resources/untrusted/iframe_api.ts
+++ b/ash/webui/personalization_app/resources/untrusted/iframe_api.ts
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {assert} from '//resources/js/assert.m.js';
 import * as constants from '../common/constants.js';
 import {isNullOrArray, isNullOrNumber} from '../common/utils.js';
+import {onMessageReceived} from '../trusted/wallpaper/untrusted_message_handler.js';
 
 /**
  * @fileoverview Helper functions for communicating between trusted and
@@ -15,55 +15,50 @@
 /**
  * Select a collection. Sent from untrusted to trusted.
  */
-export function selectCollection(target: Window, collectionId: string) {
+export function selectCollection(collectionId: string) {
   const event: constants.SelectCollectionEvent = {
     type: constants.EventType.SELECT_COLLECTION,
     collectionId
   };
-  target.postMessage(event, constants.trustedOrigin);
+  onMessageReceived(event);
 }
 
 /**
  * Select the Google Photos collection. Sent from untrusted to trusted.
  */
-export function selectGooglePhotosCollection(target: Window) {
+export function selectGooglePhotosCollection() {
   const event: constants.SelectGooglePhotosCollectionEvent = {
     type: constants.EventType.SELECT_GOOGLE_PHOTOS_COLLECTION
   };
-  target.postMessage(event, constants.trustedOrigin);
+  onMessageReceived(event);
 }
 
 /**
  * Select the local collection. Sent from untrusted to trusted.
  */
-export function selectLocalCollection(target: Window) {
+export function selectLocalCollection() {
   const event: constants.SelectLocalCollectionEvent = {
     type: constants.EventType.SELECT_LOCAL_COLLECTION
   };
-  target.postMessage(event, constants.trustedOrigin);
+  onMessageReceived(event);
 }
 
 /**
  * Select an image. Sent from untrusted to trusted.
  */
-export function selectImage(target: Window, assetId: bigint) {
+export function selectImage(assetId: bigint) {
   const event: constants.SelectImageEvent = {
     type: constants.EventType.SELECT_IMAGE,
     assetId
   };
-  target.postMessage(event, constants.trustedOrigin);
+  onMessageReceived(event);
 }
 
 /**
  * Called from untrusted code to validate that a received event is of an
  * expected type and contains the expected data.
  */
-export function validateReceivedData(
-    event: constants.Events, origin: string): boolean {
-  assert(
-      origin === constants.trustedOrigin,
-      'Message is not from the correct origin');
-
+export function validateReceivedData(event: constants.Events): boolean {
   switch (event.type) {
     case constants.EventType.SEND_COLLECTIONS: {
       return isNullOrArray(event.collections);
diff --git a/ash/webui/personalization_app/resources/untrusted/images.html b/ash/webui/personalization_app/resources/untrusted/images.html
deleted file mode 100644
index 2a3368f3..0000000
--- a/ash/webui/personalization_app/resources/untrusted/images.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!doctype html>
-<html dir="$i18n{textdirection}" lang="$i18n{language}">
-<head>
-  <meta charset="utf-8">
-  <link rel="stylesheet" href="/common/base.css">
-  <link rel="stylesheet" href="//resources/chromeos/colors/cros_styles.css">
-  <script type="module" src="images_grid.js" defer></script>
-</head>
-<body>
-  <images-grid></images-grid>
-</body>
-</html>
diff --git a/ash/webui/personalization_app/resources/untrusted/images_grid.html b/ash/webui/personalization_app/resources/untrusted/images_grid.html
index 678f9a9..0f0080a5 100644
--- a/ash/webui/personalization_app/resources/untrusted/images_grid.html
+++ b/ash/webui/personalization_app/resources/untrusted/images_grid.html
@@ -1,4 +1,4 @@
-<style include="common-style untrusted-style">
+<style include="common-style trusted-style">
   :host {
     margin: 12px 0;
   }
@@ -11,7 +11,7 @@
     position: absolute;
   }
 </style>
-<iron-list scroll-target="document" grid items="[[tiles_]]" role="listbox"
+<iron-list grid items="[[tiles_]]" role="listbox"
     aria-setsize$="[[tiles_.length]]">
   <template>
     <div class="photo-container">
@@ -24,7 +24,8 @@
           aria-label$="[[getAriaLabel_(item)]]">
         <div class="photo-images-container">
           <template is="dom-repeat" items="[[item.preview]]" as="preview">
-            <img class$="[[getClassForImg_(index, item)]]" src$="[[preview.url]]" aria-hidden="true">
+            <img is="cr-auto-img" class$="[[getClassForImg_(index, item)]]"
+                auto-src="[[preview.url]]" aria-hidden="true">
           </template>
           <iron-icon icon="personalization:checkmark"></iron-icon>
         </div>
diff --git a/ash/webui/personalization_app/resources/untrusted/images_grid.ts b/ash/webui/personalization_app/resources/untrusted/images_grid.ts
index c916934..a2ffdcd6 100644
--- a/ash/webui/personalization_app/resources/untrusted/images_grid.ts
+++ b/ash/webui/personalization_app/resources/untrusted/images_grid.ts
@@ -4,10 +4,10 @@
 
 import '//resources/polymer/v3_0/iron-list/iron-list.js';
 import './setup.js';
-import './styles.js';
+import '../trusted/wallpaper/styles.js';
 
 import {assertNotReached} from '//resources/js/assert.m.js';
-import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {afterNextRender, html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {Events, EventType, ImageTile} from '../common/constants.js';
 import {isSelectionEvent} from '../common/utils.js';
@@ -18,7 +18,7 @@
  * input and responds with |SelectImageEvent| when an image is selected.
  */
 
-class ImagesGrid extends PolymerElement {
+export class ImagesGrid extends PolymerElement {
   static get is() {
     return 'images-grid';
   }
@@ -50,49 +50,31 @@
   private selectedAssetId_: bigint|undefined;
   private pendingSelectedAssetId_: bigint|undefined;
 
-  constructor() {
-    super();
-    this.onMessageReceived_ = this.onMessageReceived_.bind(this);
-  }
-
-  connectedCallback() {
-    super.connectedCallback();
-    window.addEventListener('message', this.onMessageReceived_);
-  }
-
-  disconnectedCallback() {
-    super.disconnectedCallback();
-    window.removeEventListener('message', this.onMessageReceived_);
-  }
-
   /**
    * Handler for messages from trusted code. Expects only SendImagesEvent and
    * will error on any other event.
    */
-  private onMessageReceived_(message: MessageEvent) {
-    const event: Events = message.data;
+  onMessageReceived(event: Events) {
     switch (event.type) {
       case EventType.SEND_IMAGE_TILES:
-        this.tiles_ =
-            validateReceivedData(event, message.origin) ? event.tiles : [];
+        this.tiles_ = validateReceivedData(event) ? event.tiles : [];
         return;
       case EventType.SEND_CURRENT_WALLPAPER_ASSET_ID:
-        this.selectedAssetId_ = validateReceivedData(event, message.origin) ?
-            event.assetId :
-            undefined;
+        this.selectedAssetId_ =
+            validateReceivedData(event) ? event.assetId : undefined;
         return;
       case EventType.SEND_PENDING_WALLPAPER_ASSET_ID:
         this.pendingSelectedAssetId_ =
-            validateReceivedData(event, message.origin) ? event.assetId :
-                                                          undefined;
+            validateReceivedData(event) ? event.assetId : undefined;
         return;
       case EventType.SEND_VISIBLE:
         let visible = false;
-        if (validateReceivedData(event, message.origin)) {
+        if (validateReceivedData(event)) {
           visible = event.visible;
         }
         if (!visible) {
-          // When the iframe is hidden, do some dom magic to hide old image
+          // TODO(b/219799872) revisit if this is necessary.
+          // When the grid is hidden, do some dom magic to hide old image
           // content. This is in preparation for a user switching to a new
           // wallpaper collection and loading a new set of images.
           const ironList = this.shadowRoot!.querySelector('iron-list');
@@ -103,6 +85,16 @@
           }
           this.tiles_ = [];
         }
+        if (visible) {
+          // If iron-list items were updated while this iron-list was hidden,
+          // the layout will be incorrect. Trigger another layout when iron-list
+          // becomes visible again. Wait until |afterNextRender| completes
+          // otherwise iron-list width may still be 0.
+          afterNextRender(this, () => {
+            // Trigger a layout now that iron-list has the correct width.
+            this.shadowRoot!.querySelector('iron-list')!.fire('iron-resize');
+          });
+        }
         return;
       default:
         throw new Error('unexpected event type');
@@ -147,7 +139,7 @@
       assertNotReached('assetId not found');
       return;
     }
-    selectImage(window.parent, BigInt(assetId));
+    selectImage(BigInt(assetId));
   }
 
   private getAriaLabel_(tile: ImageTile): string {
diff --git a/ash/webui/personalization_app/resources/untrusted/styles.html b/ash/webui/personalization_app/resources/untrusted/styles.html
deleted file mode 100644
index 56f8cc0..0000000
--- a/ash/webui/personalization_app/resources/untrusted/styles.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<template>
-  <style>
-    /* Different breakpoint for inside the iframe. Use !important to make sure
-     * there are no css ordering issues. Subtract 0.25px to fix subpixel
-     * rounding issues with iron-list. This makes sure all photo containers on
-     * a row add up to at least 1px smaller than the parent width.*/
-    @media (min-width: 688px) {
-      .photo-container {
-        width: calc(25% - 0.25px) !important;
-      }
-    }
-  </style>
-</template>
diff --git a/ash/webui/personalization_app/resources/untrusted/styles.ts b/ash/webui/personalization_app/resources/untrusted/styles.ts
deleted file mode 100644
index 2943681..0000000
--- a/ash/webui/personalization_app/resources/untrusted/styles.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview styles for polymer components in untrusted code.
- */
-
-import '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
-const template = document.createElement('dom-module');
-template.innerHTML = `{__html_template__}`;
-template.register('untrusted-style');
diff --git a/ash/webui/personalization_app/test/personalization_app_browsertest.js b/ash/webui/personalization_app/test/personalization_app_browsertest.js
index 4f05375..caef8d9 100644
--- a/ash/webui/personalization_app/test/personalization_app_browsertest.js
+++ b/ash/webui/personalization_app/test/personalization_app_browsertest.js
@@ -167,7 +167,7 @@
   testDone();
 });
 
-TEST_F('WallpaperSubpageBrowserTest', 'LoadsCollectionsUntrustedIframe', () => {
+TEST_F('WallpaperSubpageBrowserTest', 'LoadsCollectionsGrid', () => {
   const router = document.querySelector('personalization-router');
   assertTrue(!!router, 'personalization-router should be top level element');
 
@@ -183,11 +183,17 @@
       'wallpaper-collections should be found under wallpaper-subpage');
 
 
-  const iframe = collections.shadowRoot.getElementById('collections-iframe');
-  assertTrue(!!iframe, 'iframe with id collections-iframe should be visible');
+  const collectionsGrid =
+      collections.shadowRoot.getElementById('collectionsGrid');
+  assertTrue(!!collectionsGrid, 'collections-grid should be visible');
 
-  assertEquals(
-      'chrome-untrusted://personalization/untrusted/collections.html',
-      iframe.src);
+  assertFalse(
+      collectionsGrid.parentElement.hidden, 'parent element should be visible');
+  assertGT(
+      collectionsGrid.offsetWidth, 0,
+      'collections grid should have visible width');
+  assertGT(
+      collectionsGrid.offsetHeight, 0,
+      'collections grid should have visible height');
   testDone();
 });
diff --git a/ash/webui/personalization_app/untrusted_personalization_app_ui_config.cc b/ash/webui/personalization_app/untrusted_personalization_app_ui_config.cc
deleted file mode 100644
index a57da58..0000000
--- a/ash/webui/personalization_app/untrusted_personalization_app_ui_config.cc
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/webui/personalization_app/untrusted_personalization_app_ui_config.h"
-
-#include "ash/constants/ash_features.h"
-#include "ash/webui/grit/ash_personalization_app_resources.h"
-#include "ash/webui/grit/ash_personalization_app_resources_map.h"
-#include "ash/webui/personalization_app/personalization_app_url_constants.h"
-#include "base/strings/string_util.h"
-#include "chromeos/strings/grit/chromeos_strings.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_ui.h"
-#include "content/public/browser/web_ui_data_source.h"
-#include "content/public/common/url_constants.h"
-#include "services/network/public/mojom/content_security_policy.mojom-shared.h"
-#include "url/gurl.h"
-
-namespace ash {
-
-namespace {
-
-void AddStrings(content::WebUIDataSource* source) {
-  static constexpr webui::LocalizedString kLocalizedStrings[] = {
-      {"myImagesLabel", IDS_PERSONALIZATION_APP_MY_IMAGES},
-      {"zeroImages", IDS_PERSONALIZATION_APP_NO_IMAGES},
-      {"oneImage", IDS_PERSONALIZATION_APP_ONE_IMAGE},
-      {"multipleImages", IDS_PERSONALIZATION_APP_MULTIPLE_IMAGES},
-      {"ariaLabelLoading", IDS_PERSONALIZATION_APP_ARIA_LABEL_LOADING}};
-  source->AddLocalizedStrings(kLocalizedStrings);
-
-  if (features::IsWallpaperGooglePhotosIntegrationEnabled()) {
-    source->AddLocalizedString("googlePhotosLabel",
-                               IDS_PERSONALIZATION_APP_GOOGLE_PHOTOS);
-  }
-
-  source->UseStringsJs();
-}
-
-void AddBooleans(content::WebUIDataSource* source) {
-  source->AddBoolean("isGooglePhotosIntegrationEnabled",
-                     features::IsWallpaperGooglePhotosIntegrationEnabled());
-}
-
-class UntrustedPersonalizationAppUI : public ui::UntrustedWebUIController {
- public:
-  explicit UntrustedPersonalizationAppUI(content::WebUI* web_ui)
-      : ui::UntrustedWebUIController(web_ui) {
-    content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
-        web_ui->GetWebContents()->GetBrowserContext(),
-        kChromeUIUntrustedPersonalizationAppURL);
-
-    AddStrings(source);
-    AddBooleans(source);
-
-    const auto resources = base::make_span(kAshPersonalizationAppResources,
-                                           kAshPersonalizationAppResourcesSize);
-
-    for (const auto& resource : resources) {
-      if (base::StartsWith(resource.path, "untrusted") ||
-          base::StartsWith(resource.path, "common"))
-        source->AddResourcePath(resource.path, resource.id);
-    }
-
-    source->AddFrameAncestor(GURL(kChromeUIPersonalizationAppURL));
-
-    // Allow images only from this url.
-    source->OverrideContentSecurityPolicy(
-        network::mojom::CSPDirectiveName::ImgSrc,
-        "img-src 'self' data: https://*.googleusercontent.com;");
-
-    source->OverrideContentSecurityPolicy(
-        network::mojom::CSPDirectiveName::ScriptSrc,
-        "script-src 'self' chrome-untrusted://resources;");
-
-    source->OverrideContentSecurityPolicy(
-        network::mojom::CSPDirectiveName::StyleSrc,
-        "style-src 'self' 'unsafe-inline' chrome-untrusted://resources;");
-
-#if !DCHECK_IS_ON()
-    // When DCHECKs are off and a user goes to an invalid url serve a default
-    // page to avoid crashing. We crash when DCHECKs are on to make it clearer
-    // that a resource path was not property specified.
-    source->SetDefaultResource(
-        IDR_ASH_PERSONALIZATION_APP_UNTRUSTED_COLLECTIONS_HTML);
-#endif  // !DCHECK_IS_ON()
-
-    // TODO(crbug/1169829) set up trusted types properly to allow Polymer to
-    // write html.
-    source->DisableTrustedTypesCSP();
-  }
-
-  UntrustedPersonalizationAppUI(const UntrustedPersonalizationAppUI&) = delete;
-  UntrustedPersonalizationAppUI& operator=(
-      const UntrustedPersonalizationAppUI&) = delete;
-  ~UntrustedPersonalizationAppUI() override = default;
-};
-
-}  // namespace
-
-UntrustedPersonalizationAppUIConfig::UntrustedPersonalizationAppUIConfig()
-    : WebUIConfig(content::kChromeUIUntrustedScheme,
-                  kChromeUIPersonalizationAppHost) {}
-
-UntrustedPersonalizationAppUIConfig::~UntrustedPersonalizationAppUIConfig() =
-    default;
-
-bool UntrustedPersonalizationAppUIConfig::IsWebUIEnabled(
-    content::BrowserContext* browser_context) {
-  return features::IsWallpaperWebUIEnabled() &&
-         !browser_context->IsOffTheRecord();
-}
-
-std::unique_ptr<content::WebUIController>
-UntrustedPersonalizationAppUIConfig::CreateWebUIController(
-    content::WebUI* web_ui) {
-  return std::make_unique<UntrustedPersonalizationAppUI>(web_ui);
-}
-
-}  // namespace ash
diff --git a/ash/webui/personalization_app/untrusted_personalization_app_ui_config.h b/ash/webui/personalization_app/untrusted_personalization_app_ui_config.h
deleted file mode 100644
index 5d600219..0000000
--- a/ash/webui/personalization_app/untrusted_personalization_app_ui_config.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_WEBUI_PERSONALIZATION_APP_UNTRUSTED_PERSONALIZATION_APP_UI_CONFIG_H_
-#define ASH_WEBUI_PERSONALIZATION_APP_UNTRUSTED_PERSONALIZATION_APP_UI_CONFIG_H_
-
-#include "ui/webui/untrusted_web_ui_controller.h"
-#include "ui/webui/webui_config.h"
-
-namespace content {
-class WebUI;
-}  // namespace content
-
-namespace ash {
-
-class UntrustedPersonalizationAppUIConfig : public ui::WebUIConfig {
- public:
-  UntrustedPersonalizationAppUIConfig();
-  ~UntrustedPersonalizationAppUIConfig() override;
-
-  bool IsWebUIEnabled(content::BrowserContext* browser_context) override;
-
-  std::unique_ptr<content::WebUIController> CreateWebUIController(
-      content::WebUI* web_ui) override;
-};
-
-}  // namespace ash
-
-#endif  // ASH_WEBUI_PERSONALIZATION_APP_UNTRUSTED_PERSONALIZATION_APP_UI_CONFIG_H_
diff --git a/ash/webui/telemetry_extension_ui/OWNERS b/ash/webui/telemetry_extension_ui/OWNERS
index 67df9ab..cb53585 100644
--- a/ash/webui/telemetry_extension_ui/OWNERS
+++ b/ash/webui/telemetry_extension_ui/OWNERS
@@ -1,3 +1,2 @@
 lamzin@google.com
 mgawad@google.com
-ortuno@chromium.org
diff --git a/base/third_party/nspr/OWNERS b/base/third_party/nspr/OWNERS
index 20ba660..2f04b3a 100644
--- a/base/third_party/nspr/OWNERS
+++ b/base/third_party/nspr/OWNERS
@@ -1,2 +1 @@
-rsleevi@chromium.org
 wtc@chromium.org
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 6cd8a19..4aef923 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-7.20220228.2.3
+7.20220303.1.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index c329a3c4..4aef923 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-7.20220228.2.2
+7.20220303.1.1
diff --git a/cc/base/features.cc b/cc/base/features.cc
index 3a52f7b..0caa7b1 100644
--- a/cc/base/features.cc
+++ b/cc/base/features.cc
@@ -29,6 +29,10 @@
     "ImpulseScrollAnimations",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
+bool IsImpulseScrollAnimationEnabled() {
+  return base::FeatureList::IsEnabled(features::kImpulseScrollAnimations);
+}
+
 // Whether the compositor should attempt to sync with the scroll handlers before
 // submitting a frame.
 const base::Feature kSynchronizedScrolling = {
diff --git a/cc/base/features.h b/cc/base/features.h
index fa165f2..aab0e40 100644
--- a/cc/base/features.h
+++ b/cc/base/features.h
@@ -13,6 +13,7 @@
 
 CC_BASE_EXPORT extern const base::Feature kAnimatedImageResume;
 CC_BASE_EXPORT extern const base::Feature kImpulseScrollAnimations;
+CC_BASE_EXPORT extern bool IsImpulseScrollAnimationEnabled();
 CC_BASE_EXPORT extern const base::Feature kSynchronizedScrolling;
 
 // When enabled, the double tap to zoom will be disabled when the viewport
diff --git a/cc/input/input_handler.h b/cc/input/input_handler.h
index ca2b41d2..a242013 100644
--- a/cc/input/input_handler.h
+++ b/cc/input/input_handler.h
@@ -94,9 +94,6 @@
   // scrolling node is the viewport, this would be the sum of the scroll offsets
   // of the inner and outer node, representing the visual scroll offset.
   gfx::PointF current_visual_offset;
-  // Indicates whether the currently scrolling node is lost, in that case the
-  // delta is not used for this ScrollUpdate call and we return immediately
-  bool currently_scrolling_node_lost = false;
 };
 
 class CC_EXPORT InputHandlerClient {
diff --git a/cc/input/threaded_input_handler.cc b/cc/input/threaded_input_handler.cc
index dc1932fd..448d8f9 100644
--- a/cc/input/threaded_input_handler.cc
+++ b/cc/input/threaded_input_handler.cc
@@ -371,11 +371,8 @@
   TRACE_EVENT2("cc", "ThreadedInputHandler::ScrollUpdate", "dx",
                scroll_state->delta_x(), "dy", scroll_state->delta_y());
 
-  if (!CurrentlyScrollingNode()) {
-    InputHandlerScrollResult result;
-    result.currently_scrolling_node_lost = true;
-    return result;
-  }
+  if (!CurrentlyScrollingNode())
+    return InputHandlerScrollResult();
 
   last_scroll_update_state_ = *scroll_state;
 
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc
index 129218d9..409995de 100644
--- a/cc/layers/heads_up_display_layer_impl.cc
+++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -372,9 +372,10 @@
     constexpr GLuint background_color = SkColorSetARGB(0, 0, 0, 0);
     constexpr GLuint msaa_sample_count = -1;
     constexpr bool can_use_lcd_text = true;
-    ri->BeginRasterCHROMIUM(
-        background_color, needs_clear, msaa_sample_count, gpu::raster::kNoMSAA,
-        can_use_lcd_text, gfx::ColorSpace::CreateSRGB(), backing->mailbox.name);
+    ri->BeginRasterCHROMIUM(background_color, needs_clear, msaa_sample_count,
+                            gpu::raster::kNoMSAA, can_use_lcd_text,
+                            /*visible=*/true, gfx::ColorSpace::CreateSRGB(),
+                            backing->mailbox.name);
     constexpr gfx::Vector2dF post_translate(0.f, 0.f);
     constexpr gfx::Vector2dF post_scale(1.f, 1.f);
     DummyImageProvider image_provider;
diff --git a/cc/paint/oop_pixeltest.cc b/cc/paint/oop_pixeltest.cc
index 17ad8596..ef935c0b 100644
--- a/cc/paint/oop_pixeltest.cc
+++ b/cc/paint/oop_pixeltest.cc
@@ -218,7 +218,8 @@
       raster_implementation->BeginRasterCHROMIUM(
           options.preclear_color, /*needs_clear=*/options.preclear,
           options.msaa_sample_count, msaa_mode, options.use_lcd_text,
-          options.target_color_params.color_space, mailbox.name);
+          /*visible=*/true, options.target_color_params.color_space,
+          mailbox.name);
       raster_implementation->EndRasterCHROMIUM();
     }
 
@@ -229,7 +230,8 @@
     raster_implementation->BeginRasterCHROMIUM(
         options.background_color, /*needs_clear=*/!options.preclear,
         options.msaa_sample_count, msaa_mode, options.use_lcd_text,
-        options.target_color_params.color_space, mailbox.name);
+        /*visible=*/true, options.target_color_params.color_space,
+        mailbox.name);
     size_t max_op_size_limit =
         gpu::raster::RasterInterface::kDefaultMaxOpSizeHint;
     raster_implementation->RasterCHROMIUM(
diff --git a/cc/raster/gpu_raster_buffer_provider.cc b/cc/raster/gpu_raster_buffer_provider.cc
index 931db23..9ed8d388 100644
--- a/cc/raster/gpu_raster_buffer_provider.cc
+++ b/cc/raster/gpu_raster_buffer_provider.cc
@@ -385,10 +385,10 @@
   bool is_raw_draw_backing =
       client_->is_using_raw_draw_ && !backing_->overlay_candidate;
   bool use_lcd_text = playback_settings.use_lcd_text && !is_raw_draw_backing;
-  ri->BeginRasterCHROMIUM(raster_source->background_color(),
-                          mailbox_needs_clear,
-                          playback_settings.msaa_sample_count, msaa_mode,
-                          use_lcd_text, color_space_, backing_->mailbox.name);
+  ri->BeginRasterCHROMIUM(
+      raster_source->background_color(), mailbox_needs_clear,
+      playback_settings.msaa_sample_count, msaa_mode, use_lcd_text,
+      playback_settings.visible, color_space_, backing_->mailbox.name);
   gfx::Vector2dF recording_to_raster_scale = transform.scale();
   recording_to_raster_scale.Scale(1 / raster_source->recording_scale_factor());
   gfx::Size content_size = raster_source->GetContentSize(transform.scale());
diff --git a/cc/raster/raster_source.h b/cc/raster/raster_source.h
index f3411fe..f8ab19f 100644
--- a/cc/raster/raster_source.h
+++ b/cc/raster/raster_source.h
@@ -52,6 +52,9 @@
     // Specifies the sample count if MSAA is enabled for this tile.
     int msaa_sample_count = 0;
 
+    // Visible hint, GPU may use it as a hint to schedule raster tasks.
+    bool visible = false;
+
     raw_ptr<ImageProvider> image_provider = nullptr;
   };
 
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc
index a2b8e66..d1fa969 100644
--- a/cc/tiles/tile_manager.cc
+++ b/cc/tiles/tile_manager.cc
@@ -1173,7 +1173,7 @@
   image_controller_.ReduceMemoryUsage();
 
   // Insert nodes for our task completion tasks. We enqueue these using
-  // NONCONCURRENT_FOREGROUND category this is the highest prioirty category and
+  // NONCONCURRENT_FOREGROUND category this is the highest priority category and
   // we'd like to run these tasks as soon as possible.
   InsertNodeForTask(&graph_, required_for_activation_done_task.get(),
                     TASK_CATEGORY_NONCONCURRENT_FOREGROUND,
@@ -1260,6 +1260,8 @@
       prioritized_tile.priority().resolution == LOW_RESOLUTION;
   playback_settings.use_lcd_text = tile->can_use_lcd_text();
   playback_settings.msaa_sample_count = msaa_sample_count;
+  playback_settings.visible =
+      tile->required_for_activation() || tile->required_for_draw();
 
   // Create and queue all image decode tasks that this tile depends on. Note
   // that we need to store the images for decode tasks in
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index d6422192..feb04c6 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -2740,8 +2740,7 @@
   EXPECT_FALSE(GetInputHandler().animating_for_snap_for_testing());
   // Finish the smooth scroll animation for wheel.
   const int scroll_animation_duration_ms =
-      base::FeatureList::IsEnabled(features::kImpulseScrollAnimations) ? 300
-                                                                       : 150;
+      features::IsImpulseScrollAnimationEnabled() ? 300 : 150;
   BeginImplFrameAndAnimate(
       begin_frame_args,
       start_time + base::Milliseconds(scroll_animation_duration_ms));
@@ -14841,10 +14840,8 @@
   begin_frame_args.frame_id.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->UpdateAnimationState(true);
-  EXPECT_NEAR(
-      (base::FeatureList::IsEnabled(features::kImpulseScrollAnimations) ? 87
-                                                                        : 50),
-      CurrentScrollOffset(scrolling_layer).y(), 1);
+  EXPECT_NEAR((features::IsImpulseScrollAnimationEnabled() ? 87 : 50),
+              CurrentScrollOffset(scrolling_layer).y(), 1);
   host_impl_->DidFinishImplFrame(begin_frame_args);
 
   // Update target.
diff --git a/chrome/OWNERS b/chrome/OWNERS
index ecb896f..34869c5 100644
--- a/chrome/OWNERS
+++ b/chrome/OWNERS
@@ -37,7 +37,6 @@
 per-file MAJOR_BRANCH_DATE=chrome-official-brancher@chops-service-accounts.iam.gserviceaccount.com
 per-file VERSION=chrome-official-brancher@chops-service-accounts.iam.gserviceaccount.com
 per-file VERSION=govind@chromium.org
-per-file VERSION=mmoss@chromium.org
 
 # For Fuchsia-specific changes:
 per-file ...fuchsia*=file://build/fuchsia/OWNERS
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceCardViewTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceCardViewTest.java
new file mode 100644
index 0000000..7252d33
--- /dev/null
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceCardViewTest.java
@@ -0,0 +1,99 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.tasks.tab_management;
+
+import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE;
+
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import androidx.test.filters.MediumTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.params.ParameterAnnotations;
+import org.chromium.base.test.params.ParameterAnnotations.ClassParameter;
+import org.chromium.base.test.params.ParameterSet;
+import org.chromium.base.test.params.ParameterizedRunner;
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.CriteriaHelper;
+import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.Restriction;
+import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.tab_ui.R;
+import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
+import org.chromium.chrome.test.util.ChromeRenderTestRule;
+import org.chromium.content_public.browser.test.util.TestThreadUtils;
+import org.chromium.ui.test.util.BlankUiTestActivityTestCase;
+import org.chromium.ui.test.util.NightModeTestUtils;
+import org.chromium.ui.test.util.UiRestriction;
+
+import java.io.IOException;
+import java.util.List;
+
+/** Render tests for PriceCardView. */
+@RunWith(ParameterizedRunner.class)
+@ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+@Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
+public class PriceCardViewTest extends BlankUiTestActivityTestCase {
+    @ClassParameter
+    private static List<ParameterSet> sClassParams =
+            new NightModeTestUtils.NightModeParams().getParameters();
+
+    @Rule
+    public ChromeRenderTestRule mRenderTestRule =
+            ChromeRenderTestRule.Builder.withPublicCorpus().build();
+
+    public PriceCardViewTest(boolean nightModeEnabled) {
+        NightModeTestUtils.setUpNightModeForBlankUiTestActivity(nightModeEnabled);
+        mRenderTestRule.setNightModeEnabled(nightModeEnabled);
+    }
+
+    private PriceCardView mPriceCardView;
+
+    @Override
+    public void setUpTest() throws Exception {
+        super.setUpTest();
+
+        TabUiTestHelper.applyThemeOverlays(getActivity());
+        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            ViewGroup view = new FrameLayout(getActivity());
+            getActivity().setContentView(view, params);
+
+            ViewGroup tabView = (ViewGroup) getActivity().getLayoutInflater().inflate(
+                    R.layout.closable_tab_grid_card_item, view, false);
+            tabView.setVisibility(View.VISIBLE);
+
+            view.addView(tabView);
+
+            mPriceCardView = tabView.findViewById(R.id.price_info_box_outer);
+        });
+    }
+
+    @Override
+    public void tearDownTest() throws Exception {
+        NightModeTestUtils.tearDownNightModeForBlankUiTestActivity();
+        super.tearDownTest();
+    }
+
+    @Test
+    @MediumTest
+    @Feature({"RenderTest"})
+    public void testRenderPriceCardView() throws IOException {
+        mPriceCardView.setPriceStrings("$50", "$100");
+        mPriceCardView.setVisibility(View.VISIBLE);
+
+        CriteriaHelper.pollUiThread(() -> mPriceCardView.getVisibility() == View.VISIBLE);
+
+        mRenderTestRule.render(mPriceCardView, "price_card_view");
+    }
+}
diff --git a/chrome/android/features/tab_ui/tab_management_java_sources.gni b/chrome/android/features/tab_ui/tab_management_java_sources.gni
index ddd44d8..d8b5e2f3 100644
--- a/chrome/android/features/tab_ui/tab_management_java_sources.gni
+++ b/chrome/android/features/tab_ui/tab_management_java_sources.gni
@@ -38,6 +38,7 @@
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewBinderTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceAlertsMessageCardTest.java",
+  "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceCardViewTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingUtilitiesTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/RecyclerViewMatcherUtils.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutofillVirtualCardEnrollmentInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutofillVirtualCardEnrollmentInfoBar.java
index a3ae494..b4b40f9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutofillVirtualCardEnrollmentInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutofillVirtualCardEnrollmentInfoBar.java
@@ -197,8 +197,14 @@
                 layout.getContext().getString(
                         R.string.autofill_virtual_card_enrollment_infobar_card_prefix),
                 mCardLabel);
-        control.addIcon(
-                mIssuerIcon, 0, formattedCardLabel, null, R.dimen.infobar_descriptive_text_size);
+        Bitmap scaledIssuerIcon = Bitmap.createScaledBitmap(mIssuerIcon,
+                layout.getResources().getDimensionPixelSize(
+                        R.dimen.virtual_card_enrollment_dialog_card_art_width),
+                layout.getResources().getDimensionPixelSize(
+                        R.dimen.virtual_card_enrollment_dialog_card_art_height),
+                true);
+        control.addIcon(scaledIssuerIcon, 0, formattedCardLabel, null,
+                R.dimen.infobar_descriptive_text_size);
 
         addLegalMessageLines(mGoogleLegalMessageLines, control);
         addLegalMessageLines(mIssuerLegalMessageLines, control);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java
index 88df6cb..93b3f7d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java
@@ -7,7 +7,6 @@
 import static org.chromium.base.test.util.CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL;
 import static org.chromium.base.test.util.CriteriaHelper.DEFAULT_POLLING_INTERVAL;
 
-import android.app.Activity;
 import android.support.test.InstrumentationRegistry;
 import android.view.KeyEvent;
 
@@ -15,9 +14,11 @@
 import androidx.test.filters.MediumTest;
 
 import org.hamcrest.Matchers;
+import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -27,6 +28,7 @@
 import org.chromium.base.test.params.ParameterAnnotations;
 import org.chromium.base.test.params.ParameterSet;
 import org.chromium.base.test.params.ParameterizedRunner;
+import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Criteria;
 import org.chromium.base.test.util.CriteriaHelper;
@@ -38,7 +40,6 @@
 import org.chromium.chrome.browser.history.HistoryActivity;
 import org.chromium.chrome.browser.omnibox.LocationBarLayout;
 import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
-import org.chromium.chrome.browser.omnibox.UrlBar;
 import org.chromium.chrome.browser.omnibox.action.OmniboxPedalType;
 import org.chromium.chrome.browser.omnibox.suggestions.pedal.PedalSuggestionView;
 import org.chromium.chrome.browser.password_manager.settings.PasswordSettings;
@@ -46,13 +47,12 @@
 import org.chromium.chrome.browser.settings.MainSettings;
 import org.chromium.chrome.browser.settings.SettingsActivity;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tabmodel.IncognitoTabHostUtils;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ActivityTestUtils;
 import org.chromium.chrome.test.util.OmniboxTestUtils;
 import org.chromium.chrome.test.util.OmniboxTestUtils.SuggestionInfo;
-import org.chromium.chrome.test.util.WaitForFocusHelper;
-import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.components.browser_ui.accessibility.AccessibilitySettings;
 import org.chromium.components.browser_ui.site_settings.SiteSettings;
 import org.chromium.components.embedder_support.util.UrlConstants;
@@ -60,7 +60,7 @@
 import org.chromium.components.omnibox.AutocompleteMatchBuilder;
 import org.chromium.components.omnibox.AutocompleteResult;
 import org.chromium.components.omnibox.action.OmniboxPedal;
-import org.chromium.content_public.browser.test.NativeLibraryTestUtils;
+import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.content_public.browser.test.util.TestTouchUtils;
 import org.chromium.ui.test.util.UiDisableIf;
 import org.chromium.url.GURL;
@@ -73,7 +73,9 @@
  * Tests of the Omnibox Pedals feature.
  */
 @RunWith(ParameterizedRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+@CommandLineFlags.
+Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-features=OmniboxPedalsAndroidBatch1"})
+@Batch(Batch.PER_CLASS)
 @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
 public class OmniboxPedalsTest {
     @ParameterAnnotations.ClassParameter
@@ -81,14 +83,16 @@
             Arrays.asList(new ParameterSet().value(false).name("RegularTab"),
                     new ParameterSet().value(true).name("IncognitoTab"));
 
-    @Rule
-    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
+    @ClassRule
+    public static ChromeTabbedActivityTestRule sActivityTestRule =
+            new ChromeTabbedActivityTestRule();
 
     @Rule
     public HistogramTestRule mHistogramTester = new HistogramTestRule();
 
     private OmniboxTestUtils mOmniboxUtils;
     private boolean mIncognito;
+    private LocationBarLayout mLocationBarLayout;
 
     public OmniboxPedalsTest(boolean incognito) {
         mIncognito = incognito;
@@ -96,17 +100,26 @@
 
     @BeforeClass
     public static void beforeClass() {
-        // Only needs to be loaded once and needs to be loaded before HistogramTestRule.
-        NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess();
+        sActivityTestRule.startMainActivityOnBlankPage();
+        sActivityTestRule.waitForActivityNativeInitializationComplete();
+        sActivityTestRule.waitForDeferredStartup();
     }
 
     @Before
     public void setUp() throws InterruptedException {
-        mActivityTestRule.startMainActivityOnBlankPage();
         if (mIncognito) {
-            mActivityTestRule.newIncognitoTabFromMenu();
+            sActivityTestRule.newIncognitoTabFromMenu();
         }
-        mOmniboxUtils = new OmniboxTestUtils(mActivityTestRule.getActivity());
+        sActivityTestRule.loadUrl("about:blank");
+        mOmniboxUtils = new OmniboxTestUtils(sActivityTestRule.getActivity());
+        mLocationBarLayout =
+                (LocationBarLayout) sActivityTestRule.getActivity().findViewById(R.id.location_bar);
+    }
+
+    @After
+    public void tearDown() {
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { IncognitoTabHostUtils.closeAllIncognitoTabs(); });
     }
 
     /**
@@ -115,14 +128,10 @@
      * @param activity The Activity which url_bar is in.
      * @param text The text will be typed into url_bar.
      */
-    private void typeInOmnibox(Activity activity, String text) throws InterruptedException {
-        final UrlBar urlBar = activity.findViewById(R.id.url_bar);
-        Assert.assertNotNull(urlBar);
-
-        WaitForFocusHelper.acquireFocusForView(urlBar);
+    private void typeInOmnibox(String text) throws InterruptedException {
         mOmniboxUtils.requestFocus();
-
         mOmniboxUtils.typeText(text, false);
+        mOmniboxUtils.waitForAutocomplete();
         mOmniboxUtils.checkSuggestionsShown();
     }
 
@@ -130,14 +139,12 @@
      * Find the Omnibox Pedal suggestion which suggests the |pedalType|, and return the
      * suggestion. This method needs to run on the UI thread.
      *
-     * @param locationBarLayout The layout which omnibox suggestions will show in.
      * @param pedalType The Omnibox pedal type to be found.
      * @return The suggesstion which suggests the matching OmniboxPedalType.
      */
-    private AutocompleteMatch findOmniboxPedalSuggestion(
-            LocationBarLayout locationBarLayout, @OmniboxPedalType int pedalType) {
+    private AutocompleteMatch findOmniboxPedalSuggestion(@OmniboxPedalType int pedalType) {
         ThreadUtils.assertOnUiThread();
-        AutocompleteCoordinator coordinator = locationBarLayout.getAutocompleteCoordinator();
+        AutocompleteCoordinator coordinator = mLocationBarLayout.getAutocompleteCoordinator();
         // Find the first matching suggestion.
         for (int i = 0; i < coordinator.getSuggestionCount(); ++i) {
             AutocompleteMatch suggestion = coordinator.getSuggestionAt(i);
@@ -149,8 +156,7 @@
         return null;
     }
 
-    private void clickOnPedal(
-            LocationBarLayout locationBarLayout, @OmniboxPedalType int omniboxPedalType) {
+    private void clickOnPedal(@OmniboxPedalType int omniboxPedalType) {
         SuggestionInfo<PedalSuggestionView> info =
                 mOmniboxUtils.getSuggestionByType(OmniboxSuggestionUiType.PEDAL_SUGGESTION);
         CriteriaHelper.pollUiThread(() -> {
@@ -162,15 +168,12 @@
     /**
      * Check whether the |pedalType| pedal suggestion was shown.
      *
-     * @param locationBarLayout The layout which omnibox suggestions will show in.
      * @param pedalType The Omnibox pedal type to be found.
      * @param expectShown expect pedal is shown or not.
      */
-    private void checkPedalWasShown(LocationBarLayout locationBarLayout,
-            @OmniboxPedalType int pedalType, boolean expectShown) {
+    private void checkPedalWasShown(@OmniboxPedalType int pedalType, boolean expectShown) {
         CriteriaHelper.pollUiThread(() -> {
-            AutocompleteMatch matchSuggestion =
-                    findOmniboxPedalSuggestion(locationBarLayout, pedalType);
+            AutocompleteMatch matchSuggestion = findOmniboxPedalSuggestion(pedalType);
             Criteria.checkThat(
                     matchSuggestion, expectShown ? Matchers.notNullValue() : Matchers.nullValue());
         });
@@ -180,14 +183,13 @@
      * click on the pedal to open the SettingsActivity, and return the SettingsActivity.
      *
      * @param activityType The class type of the activity.
-     * @param locationBarLayout The layout which omnibox suggestions will show in.
      * @param pedalType The Omnibox pedal type to be found.
      * @return The opened SettingsActivity.
      */
-    private <T> T clickOnPedalToSettings(final Class<T> activityType,
-            LocationBarLayout locationBarLayout, @OmniboxPedalType int pedalType) {
+    private <T> T clickOnPedalToSettings(
+            final Class<T> activityType, @OmniboxPedalType int pedalType) {
         return ActivityTestUtils.waitForActivity(InstrumentationRegistry.getInstrumentation(),
-                activityType, () -> { clickOnPedal(locationBarLayout, pedalType); });
+                activityType, () -> { clickOnPedal(pedalType); });
     }
 
     /**
@@ -253,15 +255,11 @@
 
     @Test
     @MediumTest
-    @EnableFeatures("OmniboxPedalsAndroidBatch1")
     public void testClearBrowsingDataOmniboxPedalSuggestion() throws InterruptedException {
         // Generate the clear browsing data pedal.
-        LocationBarLayout locationBarLayout =
-                (LocationBarLayout) mActivityTestRule.getActivity().findViewById(R.id.location_bar);
-        typeInOmnibox(mActivityTestRule.getActivity(), "Clear data");
+        typeInOmnibox("Clear data");
 
-        checkPedalWasShown(locationBarLayout, OmniboxPedalType.CLEAR_BROWSING_DATA,
-                /*expectShown=*/!mIncognito);
+        checkPedalWasShown(OmniboxPedalType.CLEAR_BROWSING_DATA, /*expectShown=*/!mIncognito);
 
         if (mIncognito) {
             // In incognito mode, no pedal shows, so the test can stop here.
@@ -269,7 +267,7 @@
         }
 
         SettingsActivity settingsActivity = clickOnPedalToSettings(
-                SettingsActivity.class, locationBarLayout, OmniboxPedalType.CLEAR_BROWSING_DATA);
+                SettingsActivity.class, OmniboxPedalType.CLEAR_BROWSING_DATA);
         Assert.assertNotNull("Could not find the Settings activity", settingsActivity);
 
         checkSettingsWasShownAndOmniboxNoFocus(
@@ -282,18 +280,14 @@
 
     @Test
     @MediumTest
-    @EnableFeatures("OmniboxPedalsAndroidBatch1")
     public void testManagePasswordsOmniboxPedalSuggestion() throws InterruptedException {
         // Generate the manage passwords pedal.
-        LocationBarLayout locationBarLayout =
-                (LocationBarLayout) mActivityTestRule.getActivity().findViewById(R.id.location_bar);
-        typeInOmnibox(mActivityTestRule.getActivity(), "Manage passwords");
+        typeInOmnibox("Manage passwords");
 
-        checkPedalWasShown(
-                locationBarLayout, OmniboxPedalType.MANAGE_PASSWORDS, /*expectShown=*/true);
+        checkPedalWasShown(OmniboxPedalType.MANAGE_PASSWORDS, /*expectShown=*/true);
 
-        SettingsActivity settingsActivity = clickOnPedalToSettings(
-                SettingsActivity.class, locationBarLayout, OmniboxPedalType.MANAGE_PASSWORDS);
+        SettingsActivity settingsActivity =
+                clickOnPedalToSettings(SettingsActivity.class, OmniboxPedalType.MANAGE_PASSWORDS);
         Assert.assertNotNull("Could not find the Settings activity", settingsActivity);
 
         checkSettingsWasShownAndOmniboxNoFocus(settingsActivity, PasswordSettings.class);
@@ -305,18 +299,14 @@
 
     @Test
     @MediumTest
-    @EnableFeatures("OmniboxPedalsAndroidBatch1")
     public void testManagePaymentMethodsOmniboxPedalSuggestion() throws InterruptedException {
         // Generate the manage payment methods pedal.
-        LocationBarLayout locationBarLayout =
-                (LocationBarLayout) mActivityTestRule.getActivity().findViewById(R.id.location_bar);
-        typeInOmnibox(mActivityTestRule.getActivity(), "Manage payment methods");
+        typeInOmnibox("Manage payment methods");
 
-        checkPedalWasShown(
-                locationBarLayout, OmniboxPedalType.UPDATE_CREDIT_CARD, /*expectShown=*/true);
+        checkPedalWasShown(OmniboxPedalType.UPDATE_CREDIT_CARD, /*expectShown=*/true);
 
-        SettingsActivity settingsActivity = clickOnPedalToSettings(
-                SettingsActivity.class, locationBarLayout, OmniboxPedalType.UPDATE_CREDIT_CARD);
+        SettingsActivity settingsActivity =
+                clickOnPedalToSettings(SettingsActivity.class, OmniboxPedalType.UPDATE_CREDIT_CARD);
         Assert.assertNotNull("Could not find the Settings activity", settingsActivity);
 
         checkSettingsWasShownAndOmniboxNoFocus(
@@ -329,20 +319,16 @@
 
     @Test
     @MediumTest
-    @EnableFeatures("OmniboxPedalsAndroidBatch1")
     public void testOpenIncognitoTabOmniboxPedalSuggestion() throws InterruptedException {
         // Generate the open incognito pedal.
-        LocationBarLayout locationBarLayout =
-                (LocationBarLayout) mActivityTestRule.getActivity().findViewById(R.id.location_bar);
-        typeInOmnibox(mActivityTestRule.getActivity(), "Open Incognito");
+        typeInOmnibox("Open Incognito");
 
-        checkPedalWasShown(
-                locationBarLayout, OmniboxPedalType.LAUNCH_INCOGNITO, /*expectShown=*/true);
+        checkPedalWasShown(OmniboxPedalType.LAUNCH_INCOGNITO, /*expectShown=*/true);
 
-        clickOnPedal(locationBarLayout, OmniboxPedalType.LAUNCH_INCOGNITO);
+        clickOnPedal(OmniboxPedalType.LAUNCH_INCOGNITO);
 
         CriteriaHelper.pollUiThread(() -> {
-            Tab tab = mActivityTestRule.getActivity().getActivityTab();
+            Tab tab = sActivityTestRule.getActivity().getActivityTab();
             Criteria.checkThat(tab, Matchers.notNullValue());
             Criteria.checkThat(tab.isIncognito(), Matchers.is(true));
         });
@@ -352,18 +338,14 @@
 
     @Test
     @MediumTest
-    @EnableFeatures("OmniboxPedalsAndroidBatch1")
     public void testRunChromeSafetyCheckOmniboxPedalSuggestion() throws InterruptedException {
         // Generate the run chrome safety check pedal.
-        LocationBarLayout locationBarLayout =
-                (LocationBarLayout) mActivityTestRule.getActivity().findViewById(R.id.location_bar);
-        typeInOmnibox(mActivityTestRule.getActivity(), "Run safety check");
+        typeInOmnibox("Run safety check");
 
-        checkPedalWasShown(
-                locationBarLayout, OmniboxPedalType.RUN_CHROME_SAFETY_CHECK, /*expectShown=*/true);
+        checkPedalWasShown(OmniboxPedalType.RUN_CHROME_SAFETY_CHECK, /*expectShown=*/true);
 
-        SettingsActivity settingsActivity = clickOnPedalToSettings(SettingsActivity.class,
-                locationBarLayout, OmniboxPedalType.RUN_CHROME_SAFETY_CHECK);
+        SettingsActivity settingsActivity = clickOnPedalToSettings(
+                SettingsActivity.class, OmniboxPedalType.RUN_CHROME_SAFETY_CHECK);
         Assert.assertNotNull("Could not find the Settings activity", settingsActivity);
 
         checkSettingsWasShownAndOmniboxNoFocus(settingsActivity, SafetyCheckSettingsFragment.class);
@@ -382,18 +364,14 @@
 
     @Test
     @MediumTest
-    @EnableFeatures("OmniboxPedalsAndroidBatch1")
     public void testManageSiteSettingsOmniboxPedalSuggestion() throws InterruptedException {
         // Generate the manage site setting pedal.
-        LocationBarLayout locationBarLayout =
-                (LocationBarLayout) mActivityTestRule.getActivity().findViewById(R.id.location_bar);
-        typeInOmnibox(mActivityTestRule.getActivity(), "Change site permissions");
+        typeInOmnibox("Change site permissions");
 
-        checkPedalWasShown(
-                locationBarLayout, OmniboxPedalType.MANAGE_SITE_SETTINGS, /*expectShown=*/true);
+        checkPedalWasShown(OmniboxPedalType.MANAGE_SITE_SETTINGS, /*expectShown=*/true);
 
         SettingsActivity settingsActivity = clickOnPedalToSettings(
-                SettingsActivity.class, locationBarLayout, OmniboxPedalType.MANAGE_SITE_SETTINGS);
+                SettingsActivity.class, OmniboxPedalType.MANAGE_SITE_SETTINGS);
         Assert.assertNotNull("Could not find the Settings activity", settingsActivity);
 
         checkSettingsWasShownAndOmniboxNoFocus(settingsActivity, SiteSettings.class);
@@ -405,18 +383,14 @@
 
     @Test
     @MediumTest
-    @EnableFeatures("OmniboxPedalsAndroidBatch1")
     public void testManageChromeSettingsOmniboxPedalSuggestion() throws InterruptedException {
         // Generate the manage chrome settings pedal.
-        LocationBarLayout locationBarLayout =
-                (LocationBarLayout) mActivityTestRule.getActivity().findViewById(R.id.location_bar);
-        typeInOmnibox(mActivityTestRule.getActivity(), "manage settings");
+        typeInOmnibox("manage settings");
 
-        checkPedalWasShown(
-                locationBarLayout, OmniboxPedalType.MANAGE_CHROME_SETTINGS, /*expectShown=*/true);
+        checkPedalWasShown(OmniboxPedalType.MANAGE_CHROME_SETTINGS, /*expectShown=*/true);
 
         SettingsActivity settingsActivity = clickOnPedalToSettings(
-                SettingsActivity.class, locationBarLayout, OmniboxPedalType.MANAGE_CHROME_SETTINGS);
+                SettingsActivity.class, OmniboxPedalType.MANAGE_CHROME_SETTINGS);
         Assert.assertNotNull("Could not find the Settings activity", settingsActivity);
 
         checkSettingsWasShownAndOmniboxNoFocus(settingsActivity, MainSettings.class);
@@ -428,19 +402,15 @@
 
     @Test
     @MediumTest
-    @EnableFeatures("OmniboxPedalsAndroidBatch1")
     @DisableIf.Device(type = {UiDisableIf.TABLET}) // https://crbug.com/1291207
     public void testViewYourChromeHistoryOmniboxPedalSuggestion() throws InterruptedException {
         // Generate the view chrome history pedal.
-        LocationBarLayout locationBarLayout =
-                (LocationBarLayout) mActivityTestRule.getActivity().findViewById(R.id.location_bar);
-        typeInOmnibox(mActivityTestRule.getActivity(), "view chrome history");
+        typeInOmnibox("view chrome history");
 
-        checkPedalWasShown(
-                locationBarLayout, OmniboxPedalType.VIEW_CHROME_HISTORY, /*expectShown=*/true);
+        checkPedalWasShown(OmniboxPedalType.VIEW_CHROME_HISTORY, /*expectShown=*/true);
 
-        HistoryActivity historyActivity = clickOnPedalToSettings(
-                HistoryActivity.class, locationBarLayout, OmniboxPedalType.VIEW_CHROME_HISTORY);
+        HistoryActivity historyActivity =
+                clickOnPedalToSettings(HistoryActivity.class, OmniboxPedalType.VIEW_CHROME_HISTORY);
 
         // Make sure the history setting page was opened.
         Assert.assertNotNull("Could not find the history activity", historyActivity);
@@ -452,19 +422,16 @@
 
     @Test
     @MediumTest
-    @EnableFeatures("OmniboxPedalsAndroidBatch1")
     public void testManageAccessibilitySettingsOmniboxPedalSuggestion()
             throws InterruptedException {
         // Generate the manage accessibility setting pedal.
-        LocationBarLayout locationBarLayout =
-                (LocationBarLayout) mActivityTestRule.getActivity().findViewById(R.id.location_bar);
-        typeInOmnibox(mActivityTestRule.getActivity(), "Chrome accessibility");
+        typeInOmnibox("Chrome accessibility");
 
-        checkPedalWasShown(locationBarLayout, OmniboxPedalType.MANAGE_CHROME_ACCESSIBILITY,
+        checkPedalWasShown(OmniboxPedalType.MANAGE_CHROME_ACCESSIBILITY,
                 /*expectShown=*/true);
 
-        SettingsActivity settingsActivity = clickOnPedalToSettings(SettingsActivity.class,
-                locationBarLayout, OmniboxPedalType.MANAGE_CHROME_ACCESSIBILITY);
+        SettingsActivity settingsActivity = clickOnPedalToSettings(
+                SettingsActivity.class, OmniboxPedalType.MANAGE_CHROME_ACCESSIBILITY);
         Assert.assertNotNull("Could not find the Settings activity", settingsActivity);
 
         checkSettingsWasShownAndOmniboxNoFocus(settingsActivity, AccessibilitySettings.class);
@@ -476,11 +443,8 @@
 
     @Test
     @MediumTest
-    @EnableFeatures("OmniboxPedalsAndroidBatch1")
     public void testPedalsStartedOnCtrlEnterKeyStroke() throws InterruptedException {
-        mOmniboxUtils.requestFocus();
-        mOmniboxUtils.typeText("Chrome accessibility", false);
-        mOmniboxUtils.checkSuggestionsShown();
+        typeInOmnibox("Chrome accessibility");
         SuggestionInfo<PedalSuggestionView> pedal =
                 mOmniboxUtils.getSuggestionByType(OmniboxSuggestionUiType.PEDAL_SUGGESTION);
         Assert.assertNotNull(pedal.view);
@@ -491,7 +455,7 @@
 
         SettingsActivity settingsActivity = ActivityTestUtils.waitForActivity(
                 InstrumentationRegistry.getInstrumentation(), SettingsActivity.class,
-                () -> { mOmniboxUtils.sendKey(KeyEvent.KEYCODE_ENTER); });
+                () -> mOmniboxUtils.sendKey(KeyEvent.KEYCODE_ENTER));
         Assert.assertNotNull("Could not find the Settings activity", settingsActivity);
 
         checkSettingsWasShownAndOmniboxNoFocus(settingsActivity, AccessibilitySettings.class);
@@ -503,21 +467,17 @@
 
     @Test
     @MediumTest
-    @EnableFeatures("OmniboxPedalsAndroidBatch1")
     public void testPlayChromeDinoGameOmniboxPedalSuggestion() throws InterruptedException {
         // Generate the play chrome dino game pedal.
-        LocationBarLayout locationBarLayout =
-                (LocationBarLayout) mActivityTestRule.getActivity().findViewById(R.id.location_bar);
-        typeInOmnibox(mActivityTestRule.getActivity(), "Dino game");
+        typeInOmnibox("Dino game");
 
-        checkPedalWasShown(
-                locationBarLayout, OmniboxPedalType.PLAY_CHROME_DINO_GAME, /*expectShown=*/true);
+        checkPedalWasShown(OmniboxPedalType.PLAY_CHROME_DINO_GAME, /*expectShown=*/true);
 
         // Click the pedal.
-        clickOnPedal(locationBarLayout, OmniboxPedalType.PLAY_CHROME_DINO_GAME);
+        clickOnPedal(OmniboxPedalType.PLAY_CHROME_DINO_GAME);
 
         CriteriaHelper.pollUiThread(() -> {
-            Tab tab = mActivityTestRule.getActivity().getActivityTab();
+            Tab tab = sActivityTestRule.getActivity().getActivityTab();
             Criteria.checkThat(tab, Matchers.notNullValue());
             Criteria.checkThat(
                     tab.getUrl().getSpec(), Matchers.startsWith(UrlConstants.CHROME_DINO_URL));
@@ -528,7 +488,6 @@
 
     @Test(expected = AssertionError.class)
     @MediumTest
-    @EnableFeatures("OmniboxPedalsAndroidBatch1")
     public void testNoPedalSuggestionAfterTop3() {
         mOmniboxUtils.requestFocus();
         List<AutocompleteMatch> suggestionsList = buildDummySuggestionsList(3, "Suggestion");
@@ -547,7 +506,6 @@
 
     @Test
     @MediumTest
-    @EnableFeatures("OmniboxPedalsAndroidBatch1")
     public void testShownPedalSuggestionInTop3() {
         mOmniboxUtils.requestFocus();
         List<AutocompleteMatch> suggestionsList = buildDummySuggestionsList(2, "Suggestion");
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index a9db4013..a7ccbf0 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -100,6 +100,7 @@
 #include "components/flags_ui/flags_ui_switches.h"
 #include "components/heavy_ad_intervention/heavy_ad_features.h"
 #include "components/history_clusters/core/features.h"
+#include "components/history_clusters/core/on_device_clustering_features.h"
 #include "components/invalidation/impl/invalidation_switches.h"
 #include "components/language/core/common/language_experiments.h"
 #include "components/lens/lens_features.h"
@@ -990,6 +991,41 @@
      kPageContentAnnotationsTitleParams,
      std::size(kPageContentAnnotationsTitleParams), nullptr},
 };
+const FeatureEntry::FeatureParam
+    kJourneysOnDeviceClusteringLabelingNoContentClusteringParams[] = {
+        {"should_label_clusters", "true"},
+        {"content_clustering_enabled", "false"},
+};
+const FeatureEntry::FeatureParam
+    kJourneysOnDeviceClusteringNoContentClusteringParams[] = {
+        {"should_label_clusters", "false"},
+        {"content_clustering_enabled", "false"},
+};
+const FeatureEntry::FeatureParam
+    kJourneysOnDeviceClusteringLabelingWithContentClusteringParams[] = {
+        {"should_label_clusters", "true"},
+        {"content_clustering_enabled", "true"},
+};
+const FeatureEntry::FeatureParam
+    kJourneysOnDeviceClusteringContentClusteringParams[] = {
+        {"should_label_clusters", "false"},
+        {"content_clustering_enabled", "true"},
+};
+const FeatureEntry::FeatureVariation kJourneysOnDeviceClusteringVariations[] = {
+    {"Label Clusters and No Content Clustering",
+     kJourneysOnDeviceClusteringLabelingNoContentClusteringParams,
+     std::size(kJourneysOnDeviceClusteringLabelingNoContentClusteringParams),
+     nullptr},
+    {"No Content Clustering",
+     kJourneysOnDeviceClusteringNoContentClusteringParams,
+     std::size(kJourneysOnDeviceClusteringNoContentClusteringParams), nullptr},
+    {"Label Clusters and Content Clustering",
+     kJourneysOnDeviceClusteringLabelingWithContentClusteringParams,
+     std::size(kJourneysOnDeviceClusteringLabelingWithContentClusteringParams),
+     nullptr},
+    {"Content Clustering", kJourneysOnDeviceClusteringContentClusteringParams,
+     std::size(kJourneysOnDeviceClusteringContentClusteringParams), nullptr},
+};
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC) || \
     BUILDFLAG(IS_WIN) || BUILDFLAG(IS_FUCHSIA)
@@ -5003,6 +5039,15 @@
      flag_descriptions::kJourneysOmniboxActionDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(history_clusters::internal::kOmniboxAction)},
 
+    {"history-journeys-on-device-clustering",
+     flag_descriptions::kJourneysOnDeviceClusteringBackendName,
+     flag_descriptions::kJourneysOnDeviceClusteringBackendDescription,
+     kOsDesktop,
+     FEATURE_WITH_PARAMS_VALUE_TYPE(
+         history_clusters::features::kOnDeviceClustering,
+         kJourneysOnDeviceClusteringVariations,
+         "HistoryJourneysOnDeviceClusteringBackend")},
+
     {"page-content-annotations", flag_descriptions::kPageContentAnnotationsName,
      flag_descriptions::kPageContentAnnotationsDescription, kOsDesktop,
      FEATURE_WITH_PARAMS_VALUE_TYPE(
diff --git a/chrome/browser/android/vr/gvr_graphics_delegate.cc b/chrome/browser/android/vr/gvr_graphics_delegate.cc
index 256fc88..2c6f08c8 100644
--- a/chrome/browser/android/vr/gvr_graphics_delegate.cc
+++ b/chrome/browser/android/vr/gvr_graphics_delegate.cc
@@ -168,7 +168,7 @@
   gl::init::DisableANGLE();
 
   if (gl::GetGLImplementation() == gl::kGLImplementationNone &&
-      !gl::init::InitializeGLOneOff()) {
+      !gl::init::InitializeGLOneOff(/*system_device_id=*/0)) {
     LOG(ERROR) << "gl::init::InitializeGLOneOff failed";
     browser_->ForceExitVr();
     return;
diff --git a/chrome/browser/apps/platform_apps/api/sync_file_system/OWNERS b/chrome/browser/apps/platform_apps/api/sync_file_system/OWNERS
index f09417b0..fb1695c 100644
--- a/chrome/browser/apps/platform_apps/api/sync_file_system/OWNERS
+++ b/chrome/browser/apps/platform_apps/api/sync_file_system/OWNERS
@@ -1,3 +1,2 @@
-kinuko@chromium.org
 mek@chromium.org
 pwnall@chromium.org
diff --git a/chrome/browser/ash/policy/status_collector/managed_session_service.cc b/chrome/browser/ash/policy/status_collector/managed_session_service.cc
index 48543d6..40e628f 100644
--- a/chrome/browser/ash/policy/status_collector/managed_session_service.cc
+++ b/chrome/browser/ash/policy/status_collector/managed_session_service.cc
@@ -49,13 +49,9 @@
     ManagedSessionService::Observer* observer) {
   observers_.AddObserver(observer);
   if (is_logged_in_observed_) {
-    if (user_manager::UserManager::Get()->IsLoggedInAsGuest()) {
-      observer->OnGuestLogin();
-    } else {
-      auto* const profile = ash::ProfileHelper::Get()->GetProfileByUser(
-          user_manager::UserManager::Get()->GetPrimaryUser());
-      observer->OnLogin(profile);
-    }
+    auto* const profile = ash::ProfileHelper::Get()->GetProfileByUser(
+        user_manager::UserManager::Get()->GetPrimaryUser());
+    observer->OnLogin(profile);
   }
 }
 
@@ -177,9 +173,7 @@
 
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   is_logged_in_observed_ = true;
-  if (!user_manager::UserManager::Get()->IsLoggedInAsGuest()) {
-    profile_observations_.AddObservation(profile);
-  }
+  profile_observations_.AddObservation(profile);
   if (ash::SessionTerminationManager::Get()) {
     ash::SessionTerminationManager::Get()->AddObserver(this);
   }
diff --git a/chrome/browser/ash/policy/status_collector/managed_session_service.h b/chrome/browser/ash/policy/status_collector/managed_session_service.h
index bdb3319..a0953e9c 100644
--- a/chrome/browser/ash/policy/status_collector/managed_session_service.h
+++ b/chrome/browser/ash/policy/status_collector/managed_session_service.h
@@ -41,9 +41,6 @@
     // Occurs when a user has logged in.
     virtual void OnLogin(Profile* profile) {}
 
-    // Occurs when a user login as guest.
-    virtual void OnGuestLogin() {}
-
     // Occurs when a user has logged out.
     // TODO(b/194215634):: Check if this function can be replaced by
     // `OnSessionTerminationStarted`
diff --git a/chrome/browser/ash/policy/status_collector/managed_session_service_unittest.cc b/chrome/browser/ash/policy/status_collector/managed_session_service_unittest.cc
index 9af3f5a..a719a37 100644
--- a/chrome/browser/ash/policy/status_collector/managed_session_service_unittest.cc
+++ b/chrome/browser/ash/policy/status_collector/managed_session_service_unittest.cc
@@ -14,6 +14,7 @@
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/session_manager/core/session_manager.h"
 #include "components/user_manager/scoped_user_manager.h"
+#include "components/user_manager/user_names.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/login_manager/dbus-constants.h"
@@ -61,7 +62,7 @@
     return profile;
   }
 
-  void GuestLogin() {
+  std::unique_ptr<TestingProfile> GuestLogin() {
     user_manager::User* const user = user_manager_->AddGuestUser();
     TestingProfile::Builder profile_builder;
     profile_builder.SetProfileName(user->GetAccountId().GetUserEmail());
@@ -70,6 +71,7 @@
     ash::ProfileHelper::Get()->SetUserToProfileMappingForTesting(user,
                                                                  profile.get());
     user_manager_->LoginUser(user->GetAccountId(), true);
+    return profile;
   }
 
   ManagedSessionService* managed_session_service() {
@@ -90,8 +92,6 @@
 
   int ObservedLoginCount() { return observed_login_count_; }
 
-  int ObservedGuestLoginCount() { return observed_guest_login_count_; }
-
   int ObservedSessionTerminationCount() {
     return observed_session_termination_count_;
   }
@@ -103,7 +103,6 @@
     logged_in_ = profile;
     ++observed_login_count_;
   }
-  void OnGuestLogin() override { ++observed_guest_login_count_; }
   void OnLogout(Profile* profile) override { logged_out_ = profile; }
   void OnSessionTerminationStarted(const user_manager::User*) override {
     ++observed_session_termination_count_;
@@ -138,8 +137,6 @@
 
   int observed_login_count_ = 0;
 
-  int observed_guest_login_count_ = 0;
-
   int observed_session_termination_count_ = 0;
 };
 
@@ -213,6 +210,15 @@
   EXPECT_TRUE(unaffiliated_profile->IsSameOrParent(logged_in_));
 }
 
+TEST_F(ManagedSessionServiceTest, OnUserProfileLoadedGuest) {
+  const auto guest_profile = GuestLogin();
+  managed_session_service()->AddObserver(this);
+
+  session_manager()->NotifyUserProfileLoaded(user_manager::GuestAccountId());
+
+  EXPECT_TRUE(guest_profile->IsSameOrParent(logged_in_));
+}
+
 TEST_F(ManagedSessionServiceTest,
        OnProfileWillBeDestroyedAffiliatedAndPrimary) {
   AccountId affiliated_account_id =
@@ -253,6 +259,16 @@
   EXPECT_TRUE(unaffiliated_profile->IsSameOrParent(logged_in_));
 }
 
+TEST_F(ManagedSessionServiceTest, OnProfileWillBeDestroyedGuest) {
+  const auto guest_profile = GuestLogin();
+  managed_session_service()->AddObserver(this);
+
+  session_manager()->NotifyUserProfileLoaded(user_manager::GuestAccountId());
+  guest_profile->MaybeSendDestroyedNotification();
+
+  EXPECT_TRUE(guest_profile->IsSameOrParent(logged_out_));
+}
+
 TEST_F(ManagedSessionServiceTest, SuspendDone) {
   managed_session_service()->AddObserver(this);
   test_clock()->SetNow(base::Time::Now());
@@ -321,19 +337,23 @@
   EXPECT_EQ(ObservedSessionTerminationCount(), 1);
 }
 
-TEST_F(ManagedSessionServiceTest, GuestLogin) {
-  GuestLogin();
+TEST_F(ManagedSessionServiceTest, GuestLoginBeforeCreate) {
+  const auto guest_profile = GuestLogin();
 
   ManagedSessionService managed_session_service;
   managed_session_service.AddObserver(this);
 
-  EXPECT_EQ(ObservedLoginCount(), 0);
-  ASSERT_EQ(ObservedGuestLoginCount(), 1);
+  EXPECT_EQ(ObservedLoginCount(), 1);
+  EXPECT_TRUE(guest_profile->IsSameOrParent(logged_in_));
 
   ::ash::SessionTerminationManager::Get()->StopSession(
       login_manager::SessionStopReason::REQUEST_FROM_SESSION_MANAGER);
 
   EXPECT_EQ(ObservedSessionTerminationCount(), 1);
+
+  guest_profile->MaybeSendDestroyedNotification();
+
+  EXPECT_TRUE(guest_profile->IsSameOrParent(logged_out_));
 }
 
 TEST_F(ManagedSessionServiceTest, LoggedInProfileNotCreated) {
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
index ad38fe10..d3aaff8 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -827,6 +827,9 @@
           delete_begin_, delete_end_,
           CreateTaskCompletionClosure(TracingDataType::kWebAuthnCredentials));
     }
+
+    browsing_data::RemoveFederatedSiteSettingsData(delete_begin_, delete_end_,
+                                                   host_content_settings_map_);
   }
 
   if (remove_mask & constants::DATA_TYPE_ACCOUNT_PASSWORDS) {
diff --git a/chrome/browser/chromeos/extensions/speech/speech_recognition_private_recognizer.cc b/chrome/browser/chromeos/extensions/speech/speech_recognition_private_recognizer.cc
index 61dca200..42924d8 100644
--- a/chrome/browser/chromeos/extensions/speech/speech_recognition_private_recognizer.cc
+++ b/chrome/browser/chromeos/extensions/speech/speech_recognition_private_recognizer.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/chromeos/extensions/speech/speech_recognition_private_recognizer.h"
 
+#include "base/debug/crash_logging.h"
 #include "chrome/browser/chromeos/extensions/speech/speech_recognition_private_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/speech/network_speech_recognizer.h"
@@ -49,6 +50,9 @@
 
 void SpeechRecognitionPrivateRecognizer::OnSpeechRecognitionStateChanged(
     SpeechRecognizerStatus new_state) {
+  // Crash keys for https://crbug.com/1296304.
+  SCOPED_CRASH_KEY_NUMBER("Accessibility", "Speech recognition state",
+                          new_state);
   SpeechRecognizerStatus next_state = new_state;
   if (new_state == SPEECH_RECOGNIZER_READY) {
     if (current_state_ == SPEECH_RECOGNIZER_OFF && speech_recognizer_) {
@@ -62,9 +66,15 @@
       delegate_->HandleSpeechRecognitionStopped(id_);
     }
   } else if (new_state == SPEECH_RECOGNIZER_RECOGNIZING) {
-    DCHECK(!on_start_callback_.is_null());
-    std::move(on_start_callback_)
-        .Run(/*type=*/type_, /*error=*/absl::optional<std::string>());
+    if (!on_start_callback_.is_null()) {
+      std::move(on_start_callback_)
+          .Run(/*type=*/type_, /*error=*/absl::optional<std::string>());
+    } else {
+      // If we get here, we are unintentionally recognizing speech. Turn off
+      // the recognizer.
+      next_state = SPEECH_RECOGNIZER_OFF;
+      RecognizerOff();
+    }
   } else if (new_state == SPEECH_RECOGNIZER_ERROR) {
     // When a speech recognition error occurs, ask the delegate to handle both
     // error and stop events.
@@ -118,9 +128,7 @@
   }
 
   RecognizerOff();
-
   delegate_->HandleSpeechRecognitionStopped(id_);
-
   DCHECK(!callback.is_null());
   std::move(callback).Run(/*error=*/absl::optional<std::string>());
 }
diff --git a/chrome/browser/chromeos/extensions/speech/speech_recognition_private_recognizer_browsertest.cc b/chrome/browser/chromeos/extensions/speech/speech_recognition_private_recognizer_browsertest.cc
index 579a5fa..abe88b11 100644
--- a/chrome/browser/chromeos/extensions/speech/speech_recognition_private_recognizer_browsertest.cc
+++ b/chrome/browser/chromeos/extensions/speech/speech_recognition_private_recognizer_browsertest.cc
@@ -349,4 +349,17 @@
   ASSERT_TRUE(last_is_final());
 }
 
+// Verifies that the speech recognizer can handle transitions between states.
+// Some of the below states are intentionally erroneous to ensure the recognizer
+// can handle unexpected input.
+IN_PROC_BROWSER_TEST_P(SpeechRecognitionPrivateRecognizerTest, SetState) {
+  FakeSpeechRecognitionStateChanged(SPEECH_RECOGNIZER_READY);
+  FakeSpeechRecognitionStateChanged(SPEECH_RECOGNIZER_RECOGNIZING);
+  FakeSpeechRecognitionStateChanged(SPEECH_RECOGNIZER_ERROR);
+  // Erroneously change the state to 'recognizing'. The recognizer should
+  // intelligently handle this case.
+  FakeSpeechRecognitionStateChanged(SPEECH_RECOGNIZER_RECOGNIZING);
+  ASSERT_EQ(SPEECH_RECOGNIZER_OFF, recognizer()->current_state());
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 915c681..344f5fd1e 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -3624,12 +3624,17 @@
   },
   {
     "name": "history-journeys",
-    "owners": [ "tommycli", "chrome-memories@google.com", "chrome-omnibox-team@google.com" ],
+    "owners": [ "tommycli", "chrome-journeys@google.com", "chrome-omnibox-team@google.com" ],
     "expiry_milestone": 105
   },
   {
     "name": "history-journeys-omnibox-action",
-    "owners": [ "tommycli", "chrome-memories@google.com", "chrome-omnibox-team@google.com" ],
+    "owners": [ "tommycli", "chrome-journeys@google.com", "chrome-omnibox-team@google.com" ],
+    "expiry_milestone": 105
+  },
+  {
+    "name": "history-journeys-on-device-clustering",
+    "owners": [ "sophiechang", "chrome-journeys@google.com", "chrome-intelligence-core@google.com" ],
     "expiry_milestone": 105
   },
   {
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 910d662..be2deff 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1609,6 +1609,11 @@
 const char kJourneysOmniboxActionDescription[] =
     "Enables the History Journeys Omnibox Action.";
 
+const char kJourneysOnDeviceClusteringBackendName[] =
+    "History Journeys On-Device Clustering Backend";
+const char kJourneysOnDeviceClusteringBackendDescription[] =
+    "Enables variations for the on-device clustering backend";
+
 const char kLargeFaviconFromGoogleName[] = "Large favicons from Google";
 const char kLargeFaviconFromGoogleDescription[] =
     "Request large favicons from Google's favicon service";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 08f5a6ad..c87cced 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -919,6 +919,9 @@
 extern const char kJourneysOmniboxActionName[];
 extern const char kJourneysOmniboxActionDescription[];
 
+extern const char kJourneysOnDeviceClusteringBackendName[];
+extern const char kJourneysOnDeviceClusteringBackendDescription[];
+
 extern const char kLargeFaviconFromGoogleName[];
 extern const char kLargeFaviconFromGoogleDescription[];
 
diff --git a/chrome/browser/interstitials/OWNERS b/chrome/browser/interstitials/OWNERS
index a669713..5d5aa262 100644
--- a/chrome/browser/interstitials/OWNERS
+++ b/chrome/browser/interstitials/OWNERS
@@ -3,4 +3,3 @@
 felt@chromium.org
 mattm@chromium.org
 meacer@chromium.org
-rsleevi@chromium.org
diff --git a/chrome/browser/login_detection/OWNERS b/chrome/browser/login_detection/OWNERS
index 2783dea..5ff4c36 100644
--- a/chrome/browser/login_detection/OWNERS
+++ b/chrome/browser/login_detection/OWNERS
@@ -1 +1,3 @@
-file://components/data_reduction_proxy/OWNERS
+alexmos@chromium.org
+rajendrant@chromium.org
+tbansal@chromium.org
\ No newline at end of file
diff --git a/chrome/browser/metrics/per_user_state_manager_chromeos.cc b/chrome/browser/metrics/per_user_state_manager_chromeos.cc
index b008353..91132f4 100644
--- a/chrome/browser/metrics/per_user_state_manager_chromeos.cc
+++ b/chrome/browser/metrics/per_user_state_manager_chromeos.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/metrics/per_user_state_manager_chromeos.h"
 
 #include "base/callback_list.h"
+#include "base/files/file_util.h"
 #include "base/guid.h"
 #include "base/metrics/histogram_functions.h"
 #include "chrome/browser/ash/login/login_pref_names.h"
@@ -27,14 +28,24 @@
 
 namespace {
 
+constexpr char kDaemonStorePath[] = "/run/daemon-store/uma-consent/";
+constexpr char kDaemonStoreFileName[] = "consent-enabled";
+
 absl::optional<bool> g_is_managed_for_testing;
 
 std::string GenerateUserId() {
   return base::GenerateGUID();
 }
 
+// Keep in sync with PerUserDaemonStoreFail enum.
+enum class DaemonStoreFailType {
+  kFailedDisabling = 0,
+  kFailedEnabling = 1,
+  kMaxValue = kFailedEnabling,
+};
+
 // Keep in sync with PerUserIdType enum.
-enum IdResetType {
+enum class IdResetType {
   kClientId = 0,
   kUserId = 1,
   kMaxValue = kUserId,
@@ -45,6 +56,18 @@
   base::UmaHistogramEnumeration("UMA.CrosPerUser.IdReset", id_type);
 }
 
+void WriteDaemonStore(base::FilePath path, bool metrics_consent) {
+  const std::string file_contents = metrics_consent ? "1" : "0";
+  if (!base::WriteFile(path, file_contents)) {
+    LOG(ERROR) << "Failed to persist consent change " << file_contents
+               << " to daemon-store. State on disk will be inaccurate!";
+    base::UmaHistogramEnumeration("UMA.CrosPerUser.DaemonStoreWriteFailed",
+                                  metrics_consent
+                                      ? DaemonStoreFailType::kFailedEnabling
+                                      : DaemonStoreFailType::kFailedDisabling);
+  }
+}
+
 }  // namespace
 
 PerUserStateManagerChromeOS::PerUserStateManagerChromeOS(
@@ -60,6 +83,9 @@
       signing_key_(signing_key) {
   user_manager_->AddSessionStateObserver(this);
   user_manager_->AddObserver(this);
+
+  task_runner_ =
+      base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()});
 }
 
 PerUserStateManagerChromeOS::PerUserStateManagerChromeOS(
@@ -236,6 +262,16 @@
 
   GetCurrentUserPrefs()->SetBoolean(prefs::kMetricsUserConsent,
                                     metrics_consent);
+
+  std::string hash = user_manager_->GetActiveUser()->username_hash();
+  base::FilePath daemon_store_consent = base::FilePath(kDaemonStorePath)
+                                            .Append(hash)
+                                            .Append(kDaemonStoreFileName);
+  // Do this asynchronously so we don't block in a potentially non-blocking
+  // context.
+  task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(WriteDaemonStore, daemon_store_consent, metrics_consent));
   NotifyObservers(metrics_consent);
 }
 
@@ -325,7 +361,7 @@
   if (user_id.has_value()) {
     local_state_->SetString(prefs::kMetricsCurrentUserId, user_id.value());
   } else {
-    RecordIdReset(kUserId);
+    RecordIdReset(IdResetType::kUserId);
     local_state_->ClearPref(prefs::kMetricsCurrentUserId);
   }
 
@@ -416,7 +452,7 @@
   // to on, this will cause the client ID to be reset each time, which is not
   // necessary. Look for a way to allow resetting client id less eager.
   if (user_prefs->GetBoolean(prefs::kMetricsRequiresClientIdResetOnConsent)) {
-    RecordIdReset(kClientId);
+    RecordIdReset(IdResetType::kClientId);
     ForceClientIdReset();
   } else {
     user_prefs->SetBoolean(prefs::kMetricsRequiresClientIdResetOnConsent, true);
diff --git a/chrome/browser/metrics/per_user_state_manager_chromeos.h b/chrome/browser/metrics/per_user_state_manager_chromeos.h
index 8367194..c3f1cbc 100644
--- a/chrome/browser/metrics/per_user_state_manager_chromeos.h
+++ b/chrome/browser/metrics/per_user_state_manager_chromeos.h
@@ -8,8 +8,10 @@
 #include <string>
 
 #include "base/callback_list.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
+#include "base/task/thread_pool.h"
 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
 #include "chrome/browser/metrics/profile_pref_names.h"
 #include "chrome/browser/profiles/profile.h"
@@ -250,6 +252,9 @@
   // Current state for |this|.
   State state_ = State::CONSTRUCTED;
 
+  // Task runner. Used to persist state to daemon-store.
+  scoped_refptr<base::SequencedTaskRunner> task_runner_ = nullptr;
+
   base::WeakPtrFactory<PerUserStateManagerChromeOS> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index 4b9e1c1..1db57b1 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -134,6 +134,8 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "components/browsing_data/core/pref_names.h"
+#include "components/keep_alive_registry/keep_alive_types.h"
+#include "components/keep_alive_registry/scoped_keep_alive.h"
 #include "components/live_caption/live_caption_controller.h"
 #endif
 
@@ -1973,8 +1975,8 @@
     base::FilePath cur_path = profile->GetPath();
     if (cur_path != profile_dir && cur_path != guest_profile_path &&
         !IsProfileDirectoryMarkedForDeletion(cur_path)) {
-      OnNewActiveProfileLoaded(profile_dir, cur_path, &callback, profile,
-                               Profile::CREATE_STATUS_INITIALIZED);
+      OnNewActiveProfileLoaded(profile_dir, cur_path, &callback, nullptr,
+                               profile, Profile::CREATE_STATUS_INITIALIZED);
       return;
     }
   }
@@ -2004,6 +2006,12 @@
         ProfileMetrics::ADD_NEW_USER_LAST_DELETED);
   }
 
+  // When this is called all browser windows may be about to be destroyed
+  // (but still exist in BrowserList), which means shutdown may be about to
+  // start. Use a KeepAlive to ensure shutdown doesn't start.
+  std::unique_ptr<ScopedKeepAlive> keep_alive =
+      std::make_unique<ScopedKeepAlive>(KeepAliveOrigin::PROFILE_MANAGER,
+                                        KeepAliveRestartOption::DISABLED);
   // Create and/or load fallback profile.
   CreateProfileAsync(
       fallback_profile_path,
@@ -2013,7 +2021,8 @@
           // OnNewActiveProfileLoaded may be called several times, but
           // only once with CREATE_STATUS_INITIALIZED.
           base::Owned(
-              std::make_unique<ProfileLoadedCallback>(std::move(callback)))));
+              std::make_unique<ProfileLoadedCallback>(std::move(callback))),
+          base::Owned(std::move(keep_alive))));
 }
 
 void ProfileManager::OnLoadProfileForProfileDeletion(
@@ -2462,6 +2471,7 @@
     const base::FilePath& profile_to_delete_path,
     const base::FilePath& new_active_profile_path,
     ProfileLoadedCallback* callback,
+    ScopedKeepAlive* keep_alive,
     Profile* loaded_profile,
     Profile::CreateStatus status) {
   DCHECK_NE(status, Profile::CREATE_STATUS_LOCAL_FAIL);
diff --git a/chrome/browser/profiles/profile_manager.h b/chrome/browser/profiles/profile_manager.h
index 18c384d..cc3c0df 100644
--- a/chrome/browser/profiles/profile_manager.h
+++ b/chrome/browser/profiles/profile_manager.h
@@ -41,6 +41,7 @@
 class ProfileAttributesStorage;
 enum class ProfileKeepAliveOrigin;
 class ProfileManagerObserver;
+class ScopedKeepAlive;
 class ScopedProfileKeepAlive;
 
 // Manages the lifecycle of Profile objects.
@@ -545,15 +546,17 @@
     raw_ptr<ProfileManager> profile_manager_;
   };
 
-  // If the |loaded_profile| has been loaded successfully (according to
-  // |status|) and isn't already scheduled for deletion, then finishes adding
-  // |profile_to_delete_dir| to the queue of profiles to be deleted, and updates
+  // If the `loaded_profile` has been loaded successfully (according to
+  // `status`) and isn't already scheduled for deletion, then finishes adding
+  // `profile_to_delete_dir` to the queue of profiles to be deleted, and updates
   // the kProfileLastUsed preference based on
-  // |last_non_supervised_profile_path|.
+  // `last_non_supervised_profile_path`. `keep_alive` may be null and is used
+  // to ensure shutdown does not start.
   void OnNewActiveProfileLoaded(
       const base::FilePath& profile_to_delete_path,
       const base::FilePath& last_non_supervised_profile_path,
       ProfileLoadedCallback* callback,
+      ScopedKeepAlive* keep_alive,
       Profile* loaded_profile,
       Profile::CreateStatus status);
 
diff --git a/chrome/browser/profiles/profile_manager_browsertest.cc b/chrome/browser/profiles/profile_manager_browsertest.cc
index 5064b3bf..917f5ca2 100644
--- a/chrome/browser/profiles/profile_manager_browsertest.cc
+++ b/chrome/browser/profiles/profile_manager_browsertest.cc
@@ -116,7 +116,7 @@
 
   void Wait() {
     keep_alive_ = std::make_unique<ScopedKeepAlive>(
-        KeepAliveOrigin::PROFILE_HELPER, KeepAliveRestartOption::DISABLED);
+        KeepAliveOrigin::PROFILE_MANAGER, KeepAliveRestartOption::DISABLED);
     loop_.Run();
   }
 
@@ -723,25 +723,8 @@
   verify_add.Wait();
   EXPECT_EQ(1u, verify_add.GetPasswords().size());
 
-  ProfileManager* profile_manager = g_browser_process->profile_manager();
-
-  // Create an additional profile. ScheduleProfileForDeletion() ensures another
-  // profile exists. If one does not exist, it will create one (async). As
-  // creation is async, and ScheduleProfileForDeletion() will close all
-  // browsers, triggering shutdown, creation will fail (DCHECK). By creating
-  // another profile first, we ensure this doesn't happen.
-  base::FilePath path_profile2 =
-      profile_manager->GenerateNextProfileDirectoryPath();
-  base::RunLoop create_run_loop;
-  profile_manager->CreateProfileAsync(
-      path_profile2,
-      base::BindRepeating(&OnUnblockOnProfileCreation, &create_run_loop));
-  // Run the message loop to allow profile creation to take place; the loop is
-  // terminated by OnUnblockOnProfileCreation when the profile is created.
-  create_run_loop.Run();
-
   base::RunLoop run_loop;
-  profile_manager->ScheduleProfileForDeletion(
+  g_browser_process->profile_manager()->ScheduleProfileForDeletion(
       profile->GetPath(),
       base::BindLambdaForTesting([&run_loop](Profile*) { run_loop.Quit(); }));
   run_loop.Run();
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
index 2481b83a..d3462bb 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
@@ -35,7 +35,6 @@
   "background/braille_background.js",
   "background/braille_captions_background.js",
   "background/braille_command_data.js",
-  "background/braille_command_handler.js",
   "background/chromevox_state.js",
   "background/classic_background.js",
   "background/color.js",
@@ -119,6 +118,7 @@
 chromevox_es6_modules = [
   "../common/instance_checker.js",
   "background/background.js",
+  "background/braille_command_handler.js",
   "background/command_handler.js",
   "background/download_handler.js",
   "background/earcon_engine.js",
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
index e758a17b..1696d16 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
@@ -4,6 +4,7 @@
 
 import {InstanceChecker} from '../../common/instance_checker.js';
 
+import {BrailleCommandHandler} from './braille_command_handler.js';
 import {CommandHandler} from './command_handler.js';
 import {DownloadHandler} from './download_handler.js';
 import {Earcons} from './earcons.js';
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
index 1bd994a2..5c4fe10 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
@@ -22,6 +22,9 @@
     this.forceContextualLastOutput();
 
     await importModule(
+        'BrailleCommandHandler',
+        '/chromevox/background/braille_command_handler.js');
+    await importModule(
         'GestureCommandHandler',
         '/chromevox/background/gesture_command_handler.js');
     await importModule(
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille_command_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille_command_handler.js
index d48a779..22d700ff 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille_command_handler.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille_command_handler.js
@@ -6,17 +6,11 @@
  * @fileoverview ChromeVox braille commands.
  */
 
-goog.provide('BrailleCommandHandler');
-
-goog.require('EventGenerator');
-goog.require('EventSourceState');
-goog.require('DesktopAutomationHandler');
-goog.require('KeyCode');
-
-goog.scope(function() {
 const RoleType = chrome.automation.RoleType;
 const StateType = chrome.automation.StateType;
 
+export const BrailleCommandHandler = {};
+
 /**
  * Global setting for the enabled state of this handler.
  * @param {boolean} state
@@ -25,6 +19,13 @@
   BrailleCommandHandler.enabled_ = state;
 };
 
+chrome.runtime.onMessage.addListener(message => {
+  if (message.target === 'BrailleCommandHandler' &&
+      message.action === 'setEnabled') {
+    BrailleCommandHandler.setEnabled(message.value);
+  }
+});
+
 /**
  * Handles a braille command.
  * @param {!BrailleKeyEvent} evt
@@ -222,4 +223,3 @@
 
 /** @private {boolean} */
 BrailleCommandHandler.enabled_ = true;
-});  // goog.scope
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/loader.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/loader.js
index cdf17ff..0ab33ad 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/loader.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/loader.js
@@ -11,7 +11,6 @@
 goog.require('AutoScrollHandler');
 goog.require('BackgroundKeyboardHandler');
 goog.require('BrailleCommandData');
-goog.require('BrailleCommandHandler');
 goog.require('BrailleKeyCommand');
 goog.require('ChromeVoxBackground');
 goog.require('ChromeVoxEditableTextBase');
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/kbexplorer.js b/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/kbexplorer.js
index ec59fe3..f41088f 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/kbexplorer.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/kbexplorer.js
@@ -45,7 +45,8 @@
     chrome.accessibilityPrivate.onAccessibilityGesture.addListener(
         KbExplorer.onAccessibilityGesture);
     chrome.accessibilityPrivate.setKeyboardListener(true, true);
-    window.backgroundWindow['BrailleCommandHandler']['setEnabled'](false);
+    chrome.runtime.sendMessage(
+        {target: 'BrailleCommandHandler', action: 'setEnabled', value: false});
     chrome.runtime.sendMessage(
         {target: 'GestureCommandHandler', action: 'setEnabled', value: false});
 
@@ -296,7 +297,8 @@
     chrome.accessibilityPrivate.onAccessibilityGesture.removeListener(
         KbExplorer.onAccessibilityGesture);
     chrome.accessibilityPrivate.setKeyboardListener(true, false);
-    window.backgroundWindow['BrailleCommandHandler']['setEnabled'](true);
+    chrome.runtime.sendMessage(
+        {target: 'BrailleCommandHandler', action: 'setEnabled', value: true});
     chrome.runtime.sendMessage(
         {target: 'GestureCommandHandler', action: 'setEnabled', value: true});
   }
diff --git a/chrome/browser/resources/new_tab_page/modules/cart/module.ts b/chrome/browser/resources/new_tab_page/modules/cart/module.ts
index 61be33f..379d1c7 100644
--- a/chrome/browser/resources/new_tab_page/modules/cart/module.ts
+++ b/chrome/browser/resources/new_tab_page/modules/cart/module.ts
@@ -137,7 +137,7 @@
 
     this.eventTracker_.add(
         this, 'discount-consent-accepted',
-        () => this.onDiscountConsentAccepted_);
+        () => this.onDiscountConsentAccepted_());
     this.eventTracker_.add(
         this, 'discount-consent-rejected',
         () => this.onDiscountConsentRejected_());
diff --git a/chrome/browser/resources/sync_file_system_internals/OWNERS b/chrome/browser/resources/sync_file_system_internals/OWNERS
index 86da7f4..156078c 100644
--- a/chrome/browser/resources/sync_file_system_internals/OWNERS
+++ b/chrome/browser/resources/sync_file_system_internals/OWNERS
@@ -1,5 +1,4 @@
 calvinlo@chromium.org
-kinuko@chromium.org
 mek@chromium.org
 nhiroki@chromium.org
 pwnall@chromium.org
diff --git a/chrome/browser/ssl/OWNERS b/chrome/browser/ssl/OWNERS
index 96820043..65db9c0 100644
--- a/chrome/browser/ssl/OWNERS
+++ b/chrome/browser/ssl/OWNERS
@@ -2,4 +2,3 @@
 carlosil@chromium.org
 estark@chromium.org
 meacer@chromium.org
-rsleevi@chromium.org
diff --git a/chrome/browser/storage/OWNERS b/chrome/browser/storage/OWNERS
index ebe5c80..869c9a1 100644
--- a/chrome/browser/storage/OWNERS
+++ b/chrome/browser/storage/OWNERS
@@ -1,5 +1,4 @@
 jsbell@chromium.org
-kinuko@chromium.org
 mek@chromium.org
 pwnall@chromium.org
 
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 1c841cc..1845804 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
@@ -872,56 +872,5 @@
   helper_.CheckAppInListNotLocallyInstalled("SiteA");
 }
 
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    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();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    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();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    TwoClientWebAppsIntegrationTestMacWinLinux,
-    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();
-}
-
 }  // namespace
 }  // namespace web_app
diff --git a/chrome/browser/sync_file_system/OWNERS b/chrome/browser/sync_file_system/OWNERS
index 3350117b7..8535c4f 100644
--- a/chrome/browser/sync_file_system/OWNERS
+++ b/chrome/browser/sync_file_system/OWNERS
@@ -1,4 +1,3 @@
-kinuko@chromium.org
 nhiroki@chromium.org
 mek@chromium.org
 pwnall@chromium.org
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
index 4c3c73a..8820efb 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
@@ -424,4 +424,9 @@
         assert mModalDialogManagerSupplier.hasValue();
         return mModalDialogManagerSupplier.get();
     }
+
+    @VisibleForTesting
+    public void stopAutocompleteForTest(boolean clearResults) {
+        mMediator.stopAutocomplete(clearResults);
+    }
 }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
index 5f8c03c1..7a1bfaf 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
@@ -888,7 +888,8 @@
      *
      * @param clear Whether to clear the most recent autocomplete results.
      */
-    private void stopAutocomplete(boolean clear) {
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    void stopAutocomplete(boolean clear) {
         if (mNativeInitialized && mAutocomplete != null) mAutocomplete.stop(clear);
         cancelAutocompleteRequests();
     }
diff --git a/chrome/browser/ui/android/toolbar/java/res/layout/start_top_toolbar.xml b/chrome/browser/ui/android/toolbar/java/res/layout/start_top_toolbar.xml
index c5dffac..ff887069 100644
--- a/chrome/browser/ui/android/toolbar/java/res/layout/start_top_toolbar.xml
+++ b/chrome/browser/ui/android/toolbar/java/res/layout/start_top_toolbar.xml
@@ -35,9 +35,9 @@
         android:id="@+id/logo"
         android:visibility="gone"
         android:layout_width="match_parent"
-        android:layout_height="32dp"
+        android:layout_height="40dp"
         android:layout_centerHorizontal="true"
-        android:layout_centerVertical="true"/>
+        android:layout_alignParentBottom="true"/>
 
     <LinearLayout
         android:layout_width="wrap_content"
diff --git a/chrome/browser/ui/android/toolbar/java/res/values/dimens.xml b/chrome/browser/ui/android/toolbar/java/res/values/dimens.xml
index cb868ba0..c463c7a 100644
--- a/chrome/browser/ui/android/toolbar/java/res/values/dimens.xml
+++ b/chrome/browser/ui/android/toolbar/java/res/values/dimens.xml
@@ -37,7 +37,7 @@
     <!-- Start surface toolbar dimensions -->
     <dimen name="start_surface_toolbar_button_padding_to_button">8dp</dimen>
     <dimen name="start_surface_toolbar_button_padding_to_edge">16dp</dimen>
-    <dimen name="start_surface_fake_search_box_top_margin">0dp</dimen>
+    <dimen name="start_surface_fake_search_box_top_margin">24dp</dimen>
     <dimen name="identity_disc_button_margin_start">16dp</dimen>
 
     <!-- Navigation history popup dimensions -->
diff --git a/chrome/browser/ui/messages/OWNERS b/chrome/browser/ui/messages/OWNERS
index 5521cea..e2f466a 100644
--- a/chrome/browser/ui/messages/OWNERS
+++ b/chrome/browser/ui/messages/OWNERS
@@ -1,5 +1,4 @@
 # Primary:
-pavely@chromium.org
 
 # Secondary:
 dtrainor@chromium.org
diff --git a/chrome/browser/ui/quick_answers/quick_answers_ui_controller.cc b/chrome/browser/ui/quick_answers/quick_answers_ui_controller.cc
index f8fcba5e..5a117a8 100644
--- a/chrome/browser/ui/quick_answers/quick_answers_ui_controller.cc
+++ b/chrome/browser/ui/quick_answers/quick_answers_ui_controller.cc
@@ -53,7 +53,8 @@
 
   DCHECK(!user_consent_view_);
   SetActiveQuery(query);
-  quick_answers_view_ = new QuickAnswersView(bounds, title, is_internal, this);
+  quick_answers_view_ = new QuickAnswersView(bounds, title, is_internal,
+                                             weak_factory_.GetWeakPtr());
   quick_answers_view_->GetWidget()->ShowInactive();
 }
 
@@ -119,7 +120,7 @@
   DCHECK(!quick_answers_view_);
   DCHECK(!user_consent_view_);
   user_consent_view_ = new quick_answers::UserConsentView(
-      anchor_bounds, intent_type, intent_text, this);
+      anchor_bounds, intent_type, intent_text, weak_factory_.GetWeakPtr());
   user_consent_view_->GetWidget()->ShowInactive();
 }
 
diff --git a/chrome/browser/ui/quick_answers/quick_answers_ui_controller.h b/chrome/browser/ui/quick_answers/quick_answers_ui_controller.h
index 6e71d5ed2..26907dda 100644
--- a/chrome/browser/ui/quick_answers/quick_answers_ui_controller.h
+++ b/chrome/browser/ui/quick_answers/quick_answers_ui_controller.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "base/memory/weak_ptr.h"
 #include "ui/gfx/geometry/rect.h"
 
 class QuickAnswersView;
@@ -100,6 +101,8 @@
   QuickAnswersView* quick_answers_view_ = nullptr;
   quick_answers::UserConsentView* user_consent_view_ = nullptr;
   std::string query_;
+
+  base::WeakPtrFactory<QuickAnswersUiController> weak_factory_{this};
 };
 
 #endif  // CHROME_BROWSER_UI_QUICK_ANSWERS_QUICK_ANSWERS_UI_CONTROLLER_H_
diff --git a/chrome/browser/ui/quick_answers/ui/quick_answers_view.cc b/chrome/browser/ui/quick_answers/ui/quick_answers_view.cc
index 591aa8f..3acaad9d 100644
--- a/chrome/browser/ui/quick_answers/ui/quick_answers_view.cc
+++ b/chrome/browser/ui/quick_answers/ui/quick_answers_view.cc
@@ -289,12 +289,13 @@
 
 // QuickAnswersView -----------------------------------------------------------
 
-QuickAnswersView::QuickAnswersView(const gfx::Rect& anchor_view_bounds,
-                                   const std::string& title,
-                                   bool is_internal,
-                                   QuickAnswersUiController* controller)
+QuickAnswersView::QuickAnswersView(
+    const gfx::Rect& anchor_view_bounds,
+    const std::string& title,
+    bool is_internal,
+    base::WeakPtr<QuickAnswersUiController> controller)
     : anchor_view_bounds_(anchor_view_bounds),
-      controller_(controller),
+      controller_(std::move(controller)),
       title_(title),
       is_internal_(is_internal),
       quick_answers_view_handler_(
@@ -367,7 +368,8 @@
 }
 
 void QuickAnswersView::SendQuickAnswersQuery() {
-  controller_->OnQuickAnswersViewPressed();
+  if (controller_)
+    controller_->OnQuickAnswersViewPressed();
 }
 
 void QuickAnswersView::UpdateAnchorViewBounds(
@@ -408,7 +410,7 @@
   retry_label_ =
       description_container->AddChildView(std::make_unique<views::LabelButton>(
           base::BindRepeating(&QuickAnswersUiController::OnRetryLabelPressed,
-                              base::Unretained(controller_)),
+                              controller_),
           l10n_util::GetStringUTF16(IDS_ASH_QUICK_ANSWERS_VIEW_RETRY)));
   retry_label_->SetEnabledTextColors(
       GetColorProvider()->GetColor(ui::kColorProgressBar));
@@ -496,8 +498,7 @@
       .SetCrossAxisAlignment(views::LayoutAlignment::kEnd);
   settings_button_ = settings_view->AddChildView(
       std::make_unique<views::ImageButton>(base::BindRepeating(
-          &QuickAnswersUiController::OnSettingsButtonPressed,
-          base::Unretained(controller_))));
+          &QuickAnswersUiController::OnSettingsButtonPressed, controller_)));
   settings_button_->SetTooltipText(l10n_util::GetStringUTF16(
       IDS_ASH_QUICK_ANSWERS_SETTINGS_BUTTON_TOOLTIP_TEXT));
   settings_button_->SetBorder(
@@ -648,7 +649,7 @@
     report_query_view_ = base_view_->AddChildView(
         std::make_unique<ReportQueryView>(base::BindRepeating(
             &QuickAnswersUiController::OnReportQueryButtonPressed,
-            base::Unretained(controller_))));
+            controller_)));
   }
 }
 
diff --git a/chrome/browser/ui/quick_answers/ui/quick_answers_view.h b/chrome/browser/ui/quick_answers/ui/quick_answers_view.h
index 5ce8e573..fbfc1dda 100644
--- a/chrome/browser/ui/quick_answers/ui/quick_answers_view.h
+++ b/chrome/browser/ui/quick_answers/ui/quick_answers_view.h
@@ -7,6 +7,7 @@
 
 #include <vector>
 
+#include "base/memory/weak_ptr.h"
 #include "chrome/browser/ui/quick_answers/ui/quick_answers_focus_search.h"
 #include "ui/events/event_handler.h"
 #include "ui/views/focus/focus_manager.h"
@@ -31,7 +32,7 @@
   QuickAnswersView(const gfx::Rect& anchor_view_bounds,
                    const std::string& title,
                    bool is_internal,
-                   QuickAnswersUiController* controller);
+                   base::WeakPtr<QuickAnswersUiController> controller);
 
   QuickAnswersView(const QuickAnswersView&) = delete;
   QuickAnswersView& operator=(const QuickAnswersView&) = delete;
@@ -76,7 +77,7 @@
   void OnPhoneticsAudioButtonPressed(const GURL& phonetics_audio);
 
   gfx::Rect anchor_view_bounds_;
-  QuickAnswersUiController* const controller_;
+  base::WeakPtr<QuickAnswersUiController> controller_;
   bool has_second_row_answer_ = false;
   std::string title_;
   bool is_internal_ = false;
diff --git a/chrome/browser/ui/quick_answers/ui/quick_answers_view_unittest.cc b/chrome/browser/ui/quick_answers/ui/quick_answers_view_unittest.cc
index 69be7f28..7fdacf7 100644
--- a/chrome/browser/ui/quick_answers/ui/quick_answers_view_unittest.cc
+++ b/chrome/browser/ui/quick_answers/ui/quick_answers_view_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/ui/quick_answers/ui/quick_answers_view.h"
 
-#include "chrome/browser/ui/quick_answers/quick_answers_controller_impl.h"
 #include "chrome/browser/ui/quick_answers/test/chrome_quick_answers_test_base.h"
 #include "ui/views/controls/menu/menu_controller.h"
 
@@ -54,11 +53,10 @@
     CreateAndShowBasicMenu();
 
     anchor_bounds_ = anchor_bounds;
-    auto* ui_controller =
-        static_cast<QuickAnswersControllerImpl*>(QuickAnswersController::Get())
-            ->quick_answers_ui_controller();
+
+    // TODO(b/222422130): Rewrite QuickAnswersViewsTest to expand coverage.
     quick_answers_view_ = std::make_unique<QuickAnswersView>(
-        anchor_bounds_, title, /*is_internal=*/false, ui_controller);
+        anchor_bounds_, title, /*is_internal=*/false, /*controller=*/nullptr);
   }
 
  private:
diff --git a/chrome/browser/ui/quick_answers/ui/user_consent_view.cc b/chrome/browser/ui/quick_answers/ui/user_consent_view.cc
index df094117..05d9a02 100644
--- a/chrome/browser/ui/quick_answers/ui/user_consent_view.cc
+++ b/chrome/browser/ui/quick_answers/ui/user_consent_view.cc
@@ -118,13 +118,14 @@
 // UserConsentView
 // -------------------------------------------------------------
 
-UserConsentView::UserConsentView(const gfx::Rect& anchor_view_bounds,
-                                 const std::u16string& intent_type,
-                                 const std::u16string& intent_text,
-                                 QuickAnswersUiController* ui_controller)
+UserConsentView::UserConsentView(
+    const gfx::Rect& anchor_view_bounds,
+    const std::u16string& intent_type,
+    const std::u16string& intent_text,
+    base::WeakPtr<QuickAnswersUiController> controller)
     : anchor_view_bounds_(anchor_view_bounds),
       event_handler_(this),
-      ui_controller_(ui_controller),
+      controller_(std::move(controller)),
       focus_search_(this,
                     base::BindRepeating(&UserConsentView::GetFocusableViews,
                                         base::Unretained(this))) {
@@ -294,7 +295,7 @@
   // No thanks button.
   auto no_thanks_button = std::make_unique<CustomizedLabelButton>(
       base::BindRepeating(&QuickAnswersUiController::OnUserConsentResult,
-                          base::Unretained(ui_controller_), false),
+                          controller_, false),
       l10n_util::GetStringUTF16(
           IDS_ASH_QUICK_ANSWERS_USER_CONSENT_VIEW_NO_THANKS_BUTTON),
       ShouldUseCompactButtonLayout(anchor_view_bounds_.width()));
@@ -304,13 +305,14 @@
   auto allow_button = std::make_unique<CustomizedLabelButton>(
       base::BindRepeating(
           [](QuickAnswersPreTargetHandler* handler,
-             QuickAnswersUiController* controller) {
+             base::WeakPtr<QuickAnswersUiController> controller) {
             // When user consent is accepted, QuickAnswersView will be
             // displayed instead of dismissing the menu.
             handler->set_dismiss_anchor_menu_on_view_closed(false);
-            controller->OnUserConsentResult(true);
+            if (controller)
+              controller->OnUserConsentResult(true);
           },
-          &event_handler_, ui_controller_),
+          &event_handler_, controller_),
       l10n_util::GetStringUTF16(
           IDS_ASH_QUICK_ANSWERS_USER_CONSENT_VIEW_ALLOW_BUTTON),
       ShouldUseCompactButtonLayout(anchor_view_bounds_.width()));
diff --git a/chrome/browser/ui/quick_answers/ui/user_consent_view.h b/chrome/browser/ui/quick_answers/ui/user_consent_view.h
index a23cc22..ac7fa08 100644
--- a/chrome/browser/ui/quick_answers/ui/user_consent_view.h
+++ b/chrome/browser/ui/quick_answers/ui/user_consent_view.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/memory/weak_ptr.h"
 #include "chrome/browser/ui/quick_answers/ui/quick_answers_focus_search.h"
 #include "chrome/browser/ui/quick_answers/ui/quick_answers_pre_target_handler.h"
 #include "ui/views/view.h"
@@ -28,7 +29,7 @@
   UserConsentView(const gfx::Rect& anchor_view_bounds,
                   const std::u16string& intent_type,
                   const std::u16string& intent_text,
-                  QuickAnswersUiController* ui_controller);
+                  base::WeakPtr<QuickAnswersUiController> controller);
 
   // Disallow copy and assign.
   UserConsentView(const UserConsentView&) = delete;
@@ -63,7 +64,7 @@
   std::u16string title_text_;
 
   QuickAnswersPreTargetHandler event_handler_;
-  QuickAnswersUiController* const ui_controller_;
+  base::WeakPtr<QuickAnswersUiController> controller_;
   QuickAnswersFocusSearch focus_search_;
 
   // Owned by view hierarchy.
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
index 01ab3b18..dade33c 100644
--- a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
+++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
@@ -109,8 +109,10 @@
     Profile* profile,
     content::WebContents* contents,
     global_media_controls::GlobalMediaControlsEntryPoint entry_point) {
-  DCHECK(!instance_);
   DCHECK(service);
+  // Hide the previous instance if it exists, since there can only be one dialog
+  // instance at a time.
+  HideDialog();
   instance_ = new MediaDialogView(anchor_view, anchor_position, service,
                                   profile, contents, entry_point);
   if (!anchor_view) {
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_view.cc b/chrome/browser/ui/views/media_router/cast_dialog_view.cc
index df06d1a..789059e 100644
--- a/chrome/browser/ui/views/media_router/cast_dialog_view.cc
+++ b/chrome/browser/ui/views/media_router/cast_dialog_view.cc
@@ -201,8 +201,10 @@
     Profile* profile,
     const base::Time& start_time,
     MediaRouterDialogOpenOrigin activation_location) {
-  DCHECK(!instance_);
   DCHECK(!start_time.is_null());
+  // Hide the previous dialog instance if it exists, since there can only be one
+  // instance at a time.
+  HideDialog();
   instance_ = new CastDialogView(anchor_view, anchor_position, controller,
                                  profile, start_time, activation_location);
   views::Widget* widget =
@@ -292,8 +294,7 @@
   auto callback = base::BindRepeating(&CastDialogView::ShowAccessCodeCastDialog,
                                       base::Unretained(this));
 
-  access_code_cast_button_ =
-      new CastDialogAccessCodeCastButton(callback);
+  access_code_cast_button_ = new CastDialogAccessCodeCastButton(callback);
   AddChildView(access_code_cast_button_.get());
 }
 
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 1081608..6cd4df2 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
@@ -2151,374 +2151,4 @@
   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/webui/chrome_untrusted_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_untrusted_web_ui_controller_factory.cc
index 1dec19bc..845d1204 100644
--- a/chrome/browser/ui/webui/chrome_untrusted_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_untrusted_web_ui_controller_factory.cc
@@ -34,7 +34,6 @@
 #include "ash/webui/file_manager/file_manager_untrusted_ui.h"
 #include "ash/webui/help_app_ui/help_app_kids_magazine_untrusted_ui.h"
 #include "ash/webui/os_feedback_ui/os_feedback_untrusted_ui.h"
-#include "ash/webui/personalization_app/untrusted_personalization_app_ui_config.h"
 #include "chrome/browser/ash/web_applications/camera_app/camera_app_untrusted_ui_config.h"
 #include "chrome/browser/ash/web_applications/crosh_ui.h"
 #include "chrome/browser/ash/web_applications/help_app/help_app_untrusted_ui_config.h"
@@ -84,7 +83,6 @@
   register_config(std::make_unique<TerminalUIConfig>());
   register_config(std::make_unique<ash::eche_app::UntrustedEcheAppUIConfig>());
   register_config(std::make_unique<MediaAppGuestUIConfig>());
-  register_config(std::make_unique<ash::UntrustedPersonalizationAppUIConfig>());
   register_config(std::make_unique<ash::HelpAppUntrustedUIConfig>());
   register_config(std::make_unique<ash::CameraAppUntrustedUIConfig>());
   register_config(
diff --git a/chrome/browser/ui/webui/nearby_share/nearby_share_mojom_traits.cc b/chrome/browser/ui/webui/nearby_share/nearby_share_mojom_traits.cc
index b97937c..0e4c4fcf 100644
--- a/chrome/browser/ui/webui/nearby_share/nearby_share_mojom_traits.cc
+++ b/chrome/browser/ui/webui/nearby_share/nearby_share_mojom_traits.cc
@@ -8,19 +8,21 @@
 #include "chrome/browser/nearby_sharing/attachment.h"
 #include "chrome/browser/nearby_sharing/file_attachment.h"
 #include "chrome/browser/nearby_sharing/text_attachment.h"
+#include "mojo/public/cpp/bindings/optional_as_pointer.h"
 
 namespace mojo {
 
 // static
-base::UnguessableToken
+const base::UnguessableToken&
 StructTraits<nearby_share::mojom::ShareTargetDataView, ShareTarget>::id(
     const ShareTarget& share_target) {
   return share_target.id;
 }
 
 // static
-std::string StructTraits<nearby_share::mojom::ShareTargetDataView,
-                         ShareTarget>::name(const ShareTarget& share_target) {
+const std::string&
+StructTraits<nearby_share::mojom::ShareTargetDataView, ShareTarget>::name(
+    const ShareTarget& share_target) {
   return share_target.device_name;
 }
 
@@ -32,12 +34,13 @@
 }
 
 // static
-absl::optional<GURL>
+mojo::OptionalAsPointer<const GURL>
 StructTraits<nearby_share::mojom::ShareTargetDataView, ShareTarget>::image_url(
     const ShareTarget& share_target) {
-  return share_target.image_url && share_target.image_url->is_valid()
-             ? share_target.image_url
-             : absl::nullopt;
+  return mojo::MakeOptionalAsPointer(share_target.image_url &&
+                                             share_target.image_url->is_valid()
+                                         ? &share_target.image_url.value()
+                                         : nullptr);
 }
 
 // static
diff --git a/chrome/browser/ui/webui/nearby_share/nearby_share_mojom_traits.h b/chrome/browser/ui/webui/nearby_share/nearby_share_mojom_traits.h
index b42ded2..ffc0cac 100644
--- a/chrome/browser/ui/webui/nearby_share/nearby_share_mojom_traits.h
+++ b/chrome/browser/ui/webui/nearby_share/nearby_share_mojom_traits.h
@@ -9,6 +9,7 @@
 
 #include "chrome/browser/nearby_sharing/share_target.h"
 #include "chrome/browser/ui/webui/nearby_share/nearby_share.mojom.h"
+#include "mojo/public/cpp/bindings/optional_as_pointer.h"
 #include "mojo/public/cpp/bindings/struct_traits.h"
 #include "url/gurl.h"
 
@@ -16,11 +17,12 @@
 
 template <>
 struct StructTraits<nearby_share::mojom::ShareTargetDataView, ShareTarget> {
-  static base::UnguessableToken id(const ShareTarget& share_target);
-  static std::string name(const ShareTarget& share_target);
+  static const base::UnguessableToken& id(const ShareTarget& share_target);
+  static const std::string& name(const ShareTarget& share_target);
   static nearby_share::mojom::ShareTargetType type(
       const ShareTarget& share_target);
-  static absl::optional<GURL> image_url(const ShareTarget& share_target);
+  static mojo::OptionalAsPointer<const GURL> image_url(
+      const ShareTarget& share_target);
   static nearby_share::mojom::PayloadPreviewPtr payload_preview(
       const ShareTarget& share_target);
   static bool Read(nearby_share::mojom::ShareTargetDataView data,
diff --git a/chrome/browser/ui/webui/profile_helper.cc b/chrome/browser/ui/webui/profile_helper.cc
index 11f3426..d95e532 100644
--- a/chrome/browser/ui/webui/profile_helper.cc
+++ b/chrome/browser/ui/webui/profile_helper.cc
@@ -17,20 +17,10 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/profile_picker.h"
 #include "chrome/browser/ui/webui/signin/signin_utils.h"
-#include "components/keep_alive_registry/keep_alive_types.h"
-#include "components/keep_alive_registry/scoped_keep_alive.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 
 namespace webui {
-namespace {
-
-void DeleteProfileCallback(std::unique_ptr<ScopedKeepAlive> keep_alive,
-                           Profile* profile) {
-  OpenNewWindowForProfile(profile);
-}
-
-}  // namespace
 
 void OpenNewWindowForProfile(Profile* profile) {
   if (profiles::IsProfileLocked(profile->GetPath())) {
@@ -64,12 +54,7 @@
   if (!profiles::IsMultipleProfilesEnabled())
     return;
   g_browser_process->profile_manager()->MaybeScheduleProfileForDeletion(
-      file_path,
-      base::BindOnce(
-          &DeleteProfileCallback,
-          std::make_unique<ScopedKeepAlive>(KeepAliveOrigin::PROFILE_HELPER,
-                                            KeepAliveRestartOption::DISABLED)),
-      deletion_source);
+      file_path, base::BindOnce(&OpenNewWindowForProfile), deletion_source);
 }
 
 }  // namespace webui
diff --git a/chrome/browser/ui/webui/sync_file_system_internals/OWNERS b/chrome/browser/ui/webui/sync_file_system_internals/OWNERS
index 86da7f4..156078c 100644
--- a/chrome/browser/ui/webui/sync_file_system_internals/OWNERS
+++ b/chrome/browser/ui/webui/sync_file_system_internals/OWNERS
@@ -1,5 +1,4 @@
 calvinlo@chromium.org
-kinuko@chromium.org
 mek@chromium.org
 nhiroki@chromium.org
 pwnall@chromium.org
diff --git a/chrome/installer/mac/BUILD.gn b/chrome/installer/mac/BUILD.gn
index 77e9fc6..4d5e867 100644
--- a/chrome/installer/mac/BUILD.gn
+++ b/chrome/installer/mac/BUILD.gn
@@ -153,7 +153,6 @@
            "signing/pipeline_test.py",
            "signing/run_mac_signing_tests.py",
            "signing/signing_test.py",
-           "signing/test_common.py",
            "signing/test_config.py",
            "//third_party/catapult/third_party/typ/",
          ]
diff --git a/chrome/installer/mac/signing/model.py b/chrome/installer/mac/signing/model.py
index b6ce9557..2431ab9d 100644
--- a/chrome/installer/mac/signing/model.py
+++ b/chrome/installer/mac/signing/model.py
@@ -6,7 +6,7 @@
 This module contains classes that encapsulate data about the signing process.
 """
 
-from enum import Enum
+import enum
 import os.path
 import re
 import string
@@ -60,8 +60,7 @@
             identifier: The unique identifier set when code signing. This is
                 only explicitly passed with the `--identifier` flag if
                 |sign_with_identifier| is True.
-            options: Options flags to pass to `codesign --options`, from
-                |CodeSignOptions|.
+            options: |CodeSignOptions| flags to pass to `codesign --options`.
             requirements: String for additional `--requirements` to pass to the
                 `codesign` command. These are joined with a space to the
                 |config.CodeSignConfig.codesign_requirements_basic| string. See
@@ -75,20 +74,20 @@
                 infer the identifier itself.
             entitlements: File name of the entitlements file to sign the product
                 with. The file should reside in the |Paths.packaging_dir|.
-            verify_options: Flags to pass to `codesign --verify`, from
-                |VerifyOptions|.
+            verify_options: |VerifyOptions| flags to pass to `codesign
+                --verify`.
         """
         self.path = path
         self.identifier = identifier
-        if not CodeSignOptions.valid(options):
-            raise ValueError('Invalid CodeSignOptions: {}'.format(options))
+        if options and not isinstance(options, CodeSignOptions):
+            raise ValueError('Must be a CodeSignOptions')
         self.options = options
         self.requirements = requirements
         self.identifier_requirement = identifier_requirement
         self.sign_with_identifier = sign_with_identifier
         self.entitlements = entitlements
-        if not VerifyOptions.valid(verify_options):
-            raise ValueError('Invalid VerifyOptions: {}'.format(verify_options))
+        if verify_options and not isinstance(verify_options, VerifyOptions):
+            raise ValueError('Must be a VerifyOptions')
         self.verify_options = verify_options
 
     def requirements_string(self, config):
@@ -124,75 +123,65 @@
                 'options={0.options}, path={0.path})'.format(self)
 
 
-def make_enum(class_name, options):
-    """Makes a new class type for an enum.
+class VerifyOptions(enum.Flag):
+    """Enum for the options that can be specified when validating the results of
+    code signing.
 
-    Args:
-        class_name: Name of the new type to make.
-        options: A dictionary of enum options to use. The keys will become
-            attributes on the class, and the values will be wrapped in a tuple
-            so that the options can be joined together.
-
-    Returns:
-        A new class for the enum.
+    These options are passed to `codesign --verify` after the
+    |CodeSignedProduct| has been signed.
     """
-    attrs = {}
+    DEEP = enum.auto()
+    STRICT = enum.auto()
+    NO_STRICT = enum.auto()
+    IGNORE_RESOURCES = enum.auto()
 
-    @classmethod
-    def valid(cls, opts_to_check):
-        """Tests if the specified |opts_to_check| are valid.
+    def to_list(self):
+        result = []
+        values = {
+            self.DEEP: '--deep',
+            self.STRICT: '--strict',
+            self.NO_STRICT: '--no-strict',
+            self.IGNORE_RESOURCES: '--ignore-resources',
+        }
 
-        Args:
-            options: Iterable of option strings.
+        for key, value in values.items():
+            if key & self:
+                result.append(value)
 
-        Returns:
-            True if all the options are valid, False if otherwise.
-        """
-        if opts_to_check is None:
-            return True
-        valid_values = options.values()
-        return all([option in valid_values for option in opts_to_check])
-
-    attrs['valid'] = valid
-
-    for name, value in options.items():
-        assert type(name) is str
-        assert type(value) is str
-        attrs[name] = (value,)
-
-    return type(class_name, (object,), attrs)
+        return sorted(result)
 
 
-"""Enum for the options that can be specified when validating the results of
-code signing.
+class CodeSignOptions(enum.Flag):
+    """Enum for the options that can be specified when signing the code.
 
-These options are passed to `codesign --verify` after the
-|CodeSignedProduct| has been signed.
-"""
-VerifyOptions = make_enum(
-    'signing.model.VerifyOptions', {
-        'DEEP': '--deep',
-        'STRICT': '--strict',
-        'NO_STRICT': '--no-strict',
-        'IGNORE_RESOURCES': '--ignore-resources',
-    })
+    These options are passed to `codesign --sign --options`.
+    """
+    RESTRICT = enum.auto()
+    LIBRARY_VALIDATION = enum.auto()
+    HARDENED_RUNTIME = enum.auto()
+    KILL = enum.auto()
+    # Specify the components of HARDENED_RUNTIME that are also available on
+    # older macOS versions.
+    FULL_HARDENED_RUNTIME_OPTIONS = (
+        RESTRICT | LIBRARY_VALIDATION | HARDENED_RUNTIME | KILL)
 
-CodeSignOptions = make_enum(
-    'signing.model.CodeSignOptions', {
-        'RESTRICT': 'restrict',
-        'LIBRARY_VALIDATION': 'library',
-        'HARDENED_RUNTIME': 'runtime',
-        'KILL': 'kill',
-    })
+    def to_comma_delimited_string(self):
+        result = []
+        values = {
+            self.RESTRICT: 'restrict',
+            self.LIBRARY_VALIDATION: 'library',
+            self.HARDENED_RUNTIME: 'runtime',
+            self.KILL: 'kill',
+        }
 
-# Specify the components of HARDENED_RUNTIME that are also available on
-# older macOS versions.
-CodeSignOptions.FULL_HARDENED_RUNTIME_OPTIONS = (
-    CodeSignOptions.HARDENED_RUNTIME + CodeSignOptions.RESTRICT +
-    CodeSignOptions.LIBRARY_VALIDATION + CodeSignOptions.KILL)
+        for key, value in values.items():
+            if key & self:
+                result.append(value)
+
+        return ','.join(sorted(result))
 
 
-class NotarizeAndStapleLevel(Enum):
+class NotarizeAndStapleLevel(enum.Enum):
     """An enum specifying the level of notarization and stapling to do.
 
     `NONE` means no notarization tasks should be performed.
diff --git a/chrome/installer/mac/signing/model_test.py b/chrome/installer/mac/signing/model_test.py
index 647846d4..457a68d 100644
--- a/chrome/installer/mac/signing/model_test.py
+++ b/chrome/installer/mac/signing/model_test.py
@@ -4,12 +4,11 @@
 
 import os.path
 import unittest
+from unittest import mock
 
-from . import model, test_common
+from . import model
 from .test_config import TestConfig
 
-mock = test_common.import_mock()
-
 
 def _get_identity_hash(i):
     if i == '[IDENTITY]':
@@ -64,18 +63,6 @@
             '', product.requirements_string(RequirementConfig(identity='-')))
 
 
-class TestVerifyOptions(unittest.TestCase):
-
-    def test_valid_all(self):
-        opts = (
-            model.VerifyOptions.DEEP + model.VerifyOptions.NO_STRICT +
-            model.VerifyOptions.IGNORE_RESOURCES)
-        self.assertTrue(model.VerifyOptions.valid(opts))
-
-    def test_invalid(self):
-        self.assertFalse(model.VerifyOptions.valid(['--whatever']))
-
-
 @mock.patch('signing.model._get_identity_hash', _get_identity_hash)
 class TestDistribution(unittest.TestCase):
 
diff --git a/chrome/installer/mac/signing/modification_test.py b/chrome/installer/mac/signing/modification_test.py
index 8ef6c53..50054ce 100644
--- a/chrome/installer/mac/signing/modification_test.py
+++ b/chrome/installer/mac/signing/modification_test.py
@@ -3,10 +3,9 @@
 # found in the LICENSE file.
 
 import unittest
+from unittest import mock
 
-from . import model, modification, test_common, test_config
-
-mock = test_common.import_mock()
+from . import model, modification, test_config
 
 
 def plist_read(*args):
diff --git a/chrome/installer/mac/signing/notarize.py b/chrome/installer/mac/signing/notarize.py
index aaefc27d..fb39a53e 100644
--- a/chrome/installer/mac/signing/notarize.py
+++ b/chrome/installer/mac/signing/notarize.py
@@ -13,10 +13,6 @@
 
 from . import commands, logger
 
-# python2 support.
-if not hasattr(plistlib, 'loads'):
-    plistlib.loads = lambda s: plistlib.readPlistFromString(str(s))
-
 _LOG_FILE_URL = 'LogFileURL'
 
 _NOTARY_SERVICE_MAX_RETRIES = 3
diff --git a/chrome/installer/mac/signing/notarize_test.py b/chrome/installer/mac/signing/notarize_test.py
index 34577d2..ee1b109 100644
--- a/chrome/installer/mac/signing/notarize_test.py
+++ b/chrome/installer/mac/signing/notarize_test.py
@@ -5,27 +5,17 @@
 import plistlib
 import subprocess
 import unittest
+from unittest import mock
 
-from . import notarize, test_common, test_config
+from . import notarize, test_config
 from .model import CodeSignedProduct, Paths
 
-mock = test_common.import_mock()
-
-
-# python2 support.
-def _make_plist(d):
-    if hasattr(plistlib, 'dumps'):
-        return plistlib.dumps(d)
-    else:
-        as_str = plistlib.writePlistToString(d)
-        return bytes(as_str)
-
 
 class TestSubmit(unittest.TestCase):
 
     @mock.patch('signing.commands.run_command_output')
     def test_valid_upload(self, run_command_output):
-        run_command_output.return_value = _make_plist({
+        run_command_output.return_value = plistlib.dumps({
             'notarization-upload': {
                 'RequestUUID': '0c652bb4-7d44-4904-8c59-1ee86a376ece'
             },
@@ -43,7 +33,7 @@
 
     @mock.patch('signing.commands.run_command_output')
     def test_valid_upload_with_asc_provider(self, run_command_output):
-        run_command_output.return_value = _make_plist({
+        run_command_output.return_value = plistlib.dumps({
             'notarization-upload': {
                 'RequestUUID': '746f1537-0613-4e49-a9a0-869f2c9dc8e5'
             },
@@ -66,7 +56,7 @@
             subprocess.CalledProcessError(
                 176, 'altool',
                 'Unable to find requested file(s): metadata.xml (1057)'),
-            _make_plist({
+            plistlib.dumps({
                 'notarization-upload': {
                     'RequestUUID': '600b24b7-8fa2-4fdb-adf9-dff1f8b7858e'
                 }
@@ -146,7 +136,7 @@
 
     @mock.patch('signing.commands.run_command_output')
     def test_success(self, run_command_output):
-        run_command_output.return_value = _make_plist({
+        run_command_output.return_value = plistlib.dumps({
             'notarization-info': {
                 'Date': '2019-05-20T13:18:35Z',
                 'LogFileURL': 'https://example.com/log.json',
@@ -168,7 +158,7 @@
 
     @mock.patch('signing.commands.run_command_output')
     def test_success_with_asc_provider(self, run_command_output):
-        run_command_output.return_value = _make_plist({
+        run_command_output.return_value = plistlib.dumps({
             'notarization-info': {
                 'Date': '2019-07-08T20:11:24Z',
                 'LogFileURL': 'https://example.com/log.json',
@@ -194,7 +184,7 @@
 
     @mock.patch('signing.commands.run_command_output')
     def test_failure(self, run_command_output):
-        run_command_output.return_value = _make_plist({
+        run_command_output.return_value = plistlib.dumps({
             'notarization-info': {
                 'Date': '2019-05-20T13:18:35Z',
                 'LogFileURL': 'https://example.com/log.json',
@@ -220,7 +210,7 @@
         run_command_output.side_effect = [
             subprocess.CalledProcessError(
                 239, 'altool',
-                _make_plist({
+                plistlib.dumps({
                     'product-errors': [{
                         'code': 1519,
                         'message': 'Could not find the RequestUUID.',
@@ -234,7 +224,7 @@
                         }
                     }]
                 })),
-            _make_plist({
+            plistlib.dumps({
                 'notarization-info': {
                     'Date': '2019-05-20T13:18:35Z',
                     'LogFileURL': 'https://example.com/log.json',
@@ -260,7 +250,7 @@
     @mock.patch('signing.commands.run_command_output')
     def test_bad_notarization_info(self, run_command_output, **kwargs):
         run_command_output.side_effect = subprocess.CalledProcessError(
-            239, 'altool', _make_plist({'product-errors': [{
+            239, 'altool', plistlib.dumps({'product-errors': [{
                 'code': 9595
             }]}))
 
@@ -276,7 +266,7 @@
             subprocess.CalledProcessError(
                 13, 'altool', '*** Error: Connection failed! Error Message'
                 '- The network connection was lost.'),
-            _make_plist({
+            plistlib.dumps({
                 'notarization-info': {
                     'Date': '2019-05-20T13:18:35Z',
                     'LogFileURL': 'https://example.com/log.json',
@@ -304,7 +294,7 @@
     def test_notarization_info_exit_1(self, run_command_output, **kwargs):
         run_command_output.side_effect = [
             subprocess.CalledProcessError(1, 'altool', ''),
-            _make_plist({
+            plistlib.dumps({
                 'notarization-info': {
                     'Date': '2021-08-24T19:28:21Z',
                     'LogFileURL': 'https://example.com/log.json',
@@ -331,7 +321,7 @@
     @mock.patch.multiple('signing.commands',
                          **{'run_command_output': mock.DEFAULT})
     def test_timeout(self, **kwargs):
-        kwargs['run_command_output'].return_value = _make_plist(
+        kwargs['run_command_output'].return_value = plistlib.dumps(
             {'notarization-info': {
                 'Status': 'in progress'
             }})
diff --git a/chrome/installer/mac/signing/parts.py b/chrome/installer/mac/signing/parts.py
index cc8dd04..d4247ed 100644
--- a/chrome/installer/mac/signing/parts.py
+++ b/chrome/installer/mac/signing/parts.py
@@ -33,7 +33,7 @@
     else:
         uncustomized_bundle_id = config.base_bundle_id
 
-    verify_options = VerifyOptions.DEEP + VerifyOptions.STRICT
+    verify_options = VerifyOptions.DEEP | VerifyOptions.STRICT
 
     parts = {
         'app':
@@ -73,8 +73,8 @@
                 # Do not use |CodeSignOptions.FULL_HARDENED_RUNTIME_OPTIONS|
                 # because library validation is incompatible with the JIT
                 # entitlement.
-                options=CodeSignOptions.RESTRICT + CodeSignOptions.KILL +
-                CodeSignOptions.HARDENED_RUNTIME,
+                options=CodeSignOptions.RESTRICT | CodeSignOptions.KILL
+                | CodeSignOptions.HARDENED_RUNTIME,
                 entitlements='helper-renderer-entitlements.plist',
                 verify_options=verify_options),
         'helper-gpu-app':
@@ -85,8 +85,8 @@
                 # Do not use |CodeSignOptions.FULL_HARDENED_RUNTIME_OPTIONS|
                 # because library validation is incompatible with more
                 # permissive code signing entitlements.
-                options=CodeSignOptions.RESTRICT + CodeSignOptions.KILL +
-                CodeSignOptions.HARDENED_RUNTIME,
+                options=CodeSignOptions.RESTRICT | CodeSignOptions.KILL
+                | CodeSignOptions.HARDENED_RUNTIME,
                 entitlements='helper-gpu-entitlements.plist',
                 verify_options=verify_options),
         'helper-plugin-app':
@@ -97,8 +97,8 @@
                 # Do not use |CodeSignOptions.FULL_HARDENED_RUNTIME_OPTIONS|
                 # because library validation is incompatible with the
                 # disable-library-validation entitlement.
-                options=CodeSignOptions.RESTRICT + CodeSignOptions.KILL +
-                CodeSignOptions.HARDENED_RUNTIME,
+                options=CodeSignOptions.RESTRICT | CodeSignOptions.KILL
+                | CodeSignOptions.HARDENED_RUNTIME,
                 entitlements='helper-plugin-entitlements.plist',
                 verify_options=verify_options),
         'helper-alerts':
@@ -158,13 +158,13 @@
     )
     for binary in binaries:
         options = (
-            CodeSignOptions.HARDENED_RUNTIME + CodeSignOptions.RESTRICT +
-            CodeSignOptions.LIBRARY_VALIDATION + CodeSignOptions.KILL)
+            CodeSignOptions.HARDENED_RUNTIME | CodeSignOptions.RESTRICT
+            | CodeSignOptions.LIBRARY_VALIDATION | CodeSignOptions.KILL)
         tools[binary] = CodeSignedProduct(
             '{.packaging_dir}/{binary}'.format(config, binary=binary),
             binary.replace('.dylib', ''),
             options=options if not binary.endswith('dylib') else None,
-            verify_options=VerifyOptions.DEEP + VerifyOptions.STRICT)
+            verify_options=VerifyOptions.DEEP | VerifyOptions.STRICT)
 
     return tools
 
diff --git a/chrome/installer/mac/signing/parts_test.py b/chrome/installer/mac/signing/parts_test.py
index 94f1e98..ddd00b7 100644
--- a/chrome/installer/mac/signing/parts_test.py
+++ b/chrome/installer/mac/signing/parts_test.py
@@ -3,10 +3,9 @@
 # found in the LICENSE file.
 
 import unittest
+from unittest import mock
 
-from . import model, parts, signing, test_common, test_config
-
-mock = test_common.import_mock()
+from . import model, parts, signing, test_config
 
 
 def _get_identity_hash(i):
@@ -64,47 +63,46 @@
     def test_part_options(self):
         all_parts = parts.get_parts(test_config.TestConfig())
         self.assertEqual(
-            set(model.CodeSignOptions.RESTRICT +
-                model.CodeSignOptions.LIBRARY_VALIDATION +
-                model.CodeSignOptions.KILL +
-                model.CodeSignOptions.HARDENED_RUNTIME),
-            set(all_parts['app'].options))
+            model.CodeSignOptions.RESTRICT
+            | model.CodeSignOptions.LIBRARY_VALIDATION
+            | model.CodeSignOptions.KILL
+            | model.CodeSignOptions.HARDENED_RUNTIME, all_parts['app'].options)
         self.assertEqual(
-            set(model.CodeSignOptions.RESTRICT +
-                model.CodeSignOptions.LIBRARY_VALIDATION +
-                model.CodeSignOptions.KILL +
-                model.CodeSignOptions.HARDENED_RUNTIME),
-            set(all_parts['helper-app'].options))
+            model.CodeSignOptions.RESTRICT
+            | model.CodeSignOptions.LIBRARY_VALIDATION
+            | model.CodeSignOptions.KILL
+            | model.CodeSignOptions.HARDENED_RUNTIME,
+            all_parts['helper-app'].options)
         self.assertEqual(
-            set(model.CodeSignOptions.RESTRICT + model.CodeSignOptions.KILL +
-                model.CodeSignOptions.HARDENED_RUNTIME),
-            set(all_parts['helper-renderer-app'].options))
+            model.CodeSignOptions.RESTRICT | model.CodeSignOptions.KILL
+            | model.CodeSignOptions.HARDENED_RUNTIME,
+            all_parts['helper-renderer-app'].options)
         self.assertEqual(
-            set(model.CodeSignOptions.RESTRICT + model.CodeSignOptions.KILL +
-                model.CodeSignOptions.HARDENED_RUNTIME),
-            set(all_parts['helper-gpu-app'].options))
+            model.CodeSignOptions.RESTRICT | model.CodeSignOptions.KILL
+            | model.CodeSignOptions.HARDENED_RUNTIME,
+            all_parts['helper-gpu-app'].options)
         self.assertEqual(
-            set(model.CodeSignOptions.RESTRICT + model.CodeSignOptions.KILL +
-                model.CodeSignOptions.HARDENED_RUNTIME),
-            set(all_parts['helper-plugin-app'].options))
+            model.CodeSignOptions.RESTRICT | model.CodeSignOptions.KILL
+            | model.CodeSignOptions.HARDENED_RUNTIME,
+            all_parts['helper-plugin-app'].options)
         self.assertEqual(
-            set(model.CodeSignOptions.RESTRICT +
-                model.CodeSignOptions.LIBRARY_VALIDATION +
-                model.CodeSignOptions.KILL +
-                model.CodeSignOptions.HARDENED_RUNTIME),
-            set(all_parts['crashpad'].options))
+            model.CodeSignOptions.RESTRICT
+            | model.CodeSignOptions.LIBRARY_VALIDATION
+            | model.CodeSignOptions.KILL
+            | model.CodeSignOptions.HARDENED_RUNTIME,
+            all_parts['crashpad'].options)
         self.assertEqual(
-            set(model.CodeSignOptions.RESTRICT +
-                model.CodeSignOptions.LIBRARY_VALIDATION +
-                model.CodeSignOptions.KILL +
-                model.CodeSignOptions.HARDENED_RUNTIME),
-            set(all_parts['helper-alerts'].options))
+            model.CodeSignOptions.RESTRICT
+            | model.CodeSignOptions.LIBRARY_VALIDATION
+            | model.CodeSignOptions.KILL
+            | model.CodeSignOptions.HARDENED_RUNTIME,
+            all_parts['helper-alerts'].options)
         self.assertEqual(
-            set(model.CodeSignOptions.RESTRICT +
-                model.CodeSignOptions.LIBRARY_VALIDATION +
-                model.CodeSignOptions.KILL +
-                model.CodeSignOptions.HARDENED_RUNTIME),
-            set(all_parts['app-mode-app'].options))
+            model.CodeSignOptions.RESTRICT
+            | model.CodeSignOptions.LIBRARY_VALIDATION
+            | model.CodeSignOptions.KILL
+            | model.CodeSignOptions.HARDENED_RUNTIME,
+            all_parts['app-mode-app'].options)
 
 
 def _get_plist_read(other_version):
diff --git a/chrome/installer/mac/signing/pipeline_test.py b/chrome/installer/mac/signing/pipeline_test.py
index c505988..b5756ce1 100644
--- a/chrome/installer/mac/signing/pipeline_test.py
+++ b/chrome/installer/mac/signing/pipeline_test.py
@@ -4,11 +4,10 @@
 
 import os.path
 import unittest
+from unittest import mock
 from xml.etree import ElementTree
 
-from . import model, pipeline, test_common, test_config
-
-mock = test_common.import_mock()
+from . import model, pipeline, test_config
 
 
 def _get_work_dir(*args, **kwargs):
diff --git a/chrome/installer/mac/signing/signing.py b/chrome/installer/mac/signing/signing.py
index a710b52..2cbc10b 100644
--- a/chrome/installer/mac/signing/signing.py
+++ b/chrome/installer/mac/signing/signing.py
@@ -83,7 +83,7 @@
     if reqs:
         command.extend(['--requirements', '=' + reqs])
     if part.options:
-        command.extend(['--options', ','.join(part.options)])
+        command.extend(['--options', part.options.to_comma_delimited_string()])
     if part.entitlements:
         command.extend(
             ['--entitlements',
@@ -100,7 +100,8 @@
         part: The |model.CodeSignedProduct| to verify. The product's |path|
             must be in |paths.work|.
     """
-    verify_options = list(part.verify_options) if part.verify_options else []
+    verify_options = part.verify_options.to_list(
+    ) if part.verify_options else []
     part_path = os.path.join(paths.work, part.path)
     commands.run_command([
         'codesign', '--display', '--verbose=5', '--requirements', '-', part_path
diff --git a/chrome/installer/mac/signing/signing_test.py b/chrome/installer/mac/signing/signing_test.py
index f5ba5a85..de38c0f 100644
--- a/chrome/installer/mac/signing/signing_test.py
+++ b/chrome/installer/mac/signing/signing_test.py
@@ -3,16 +3,9 @@
 # found in the LICENSE file.
 
 import unittest
+from unittest import mock
 
-from . import model, signing, test_common, test_config
-
-mock = test_common.import_mock()
-
-# python2 support.
-try:
-    FileNotFoundError
-except NameError:
-    FileNotFoundError = IOError
+from . import model, signing, test_config
 
 
 @mock.patch('signing.commands.lenient_run_command_output')
@@ -168,13 +161,13 @@
         part = model.CodeSignedProduct(
             'Test.app',
             'test.signing.app',
-            options=model.CodeSignOptions.RESTRICT +
-            model.CodeSignOptions.LIBRARY_VALIDATION)
+            options=model.CodeSignOptions.RESTRICT
+            | model.CodeSignOptions.LIBRARY_VALIDATION)
         signing.sign_part(self.paths, self.config, part)
         run_command.assert_called_once_with([
             'codesign', '--sign', '[IDENTITY]', '--timestamp', '--requirements',
             '=designated => identifier "test.signing.app"', '--options',
-            'restrict,library', '/$W/Test.app'
+            'library,restrict', '/$W/Test.app'
         ])
 
     def test_sign_part_with_entitlements(self, run_command,
@@ -206,8 +199,8 @@
         part = model.CodeSignedProduct(
             'Test.app',
             'test.signing.app',
-            verify_options=model.VerifyOptions.DEEP +
-            model.VerifyOptions.IGNORE_RESOURCES)
+            verify_options=model.VerifyOptions.DEEP
+            | model.VerifyOptions.IGNORE_RESOURCES)
         signing.verify_part(self.paths, part)
         self.assertEqual(run_command.mock_calls, [
             mock.call([
diff --git a/chrome/installer/mac/signing/test_common.py b/chrome/installer/mac/signing/test_common.py
deleted file mode 100644
index cdf40cf9..0000000
--- a/chrome/installer/mac/signing/test_common.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-def import_mock():
-    # python2 support.
-    try:
-        from unittest import mock
-        return mock
-    except:
-        import mock
-        return mock
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/OmniboxTestUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/OmniboxTestUtils.java
index 65d8efa..f7c51c0 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/OmniboxTestUtils.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/OmniboxTestUtils.java
@@ -42,6 +42,7 @@
 import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
 import org.chromium.ui.modelutil.PropertyModel;
 
+import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
 
 /**
@@ -210,6 +211,33 @@
     }
 
     /**
+     * Stops any subsequent AutocompleteResults from being generated.
+     * Ensures that no subsequent asynchronous AutocompleteResults could tamper with test execution.
+     */
+    public void waitForAutocomplete() {
+        AtomicLong previousId = new AtomicLong(-1);
+        AtomicLong count = new AtomicLong();
+
+        CriteriaHelper.pollUiThread(() -> {
+            long currentId = mAutocomplete.getCurrentNativeAutocompleteResult();
+            // Suggestions have changed as a result of a recent push.
+            // Reset the counter and monitor for possible updates.
+            if (currentId != previousId.get()) {
+                previousId.set(currentId);
+                count.set(0);
+                return false;
+            }
+
+            // Check that nothing has changed 3 times in a row, rejecting everything that
+            // arrives late. This guarantees that the suggestions will not change and the list
+            // can be used for testing purposes.
+            if (count.incrementAndGet() < 3) return false;
+            mAutocomplete.stopAutocompleteForTest(false);
+            return true;
+        });
+    }
+
+    /**
      * Check whether suggestion of supplied type has been shown in the Suggestions Dropdown.
      *
      * @param type The type of suggestion to check.
diff --git a/chrome/test/data/webui/chromeos/personalization_app/personalization_app_test_utils.ts b/chrome/test/data/webui/chromeos/personalization_app/personalization_app_test_utils.ts
index 742f4601..46d4a917 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/personalization_app_test_utils.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/personalization_app_test_utils.ts
@@ -14,7 +14,6 @@
 import {setUserProviderForTesting} from 'chrome://personalization/trusted/user/user_interface_provider.js';
 import {setWallpaperProviderForTesting} from 'chrome://personalization/trusted/wallpaper/wallpaper_interface_provider.js';
 import {flush, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
 import {flushTasks} from 'chrome://webui-test/test_util.js';
 
@@ -39,19 +38,13 @@
 }
 
 /**
- * Tear down an element. Make sure the iframe load callback
- * has completed to avoid weird race condition with loading.
- * @see {b/185905694, crbug/466089}
+ * Tear down an element. Remove from dom and call |flushTasks| to finish any
+ * async cleanup in polymer and execute pending promises.
  */
 export async function teardownElement(element: HTMLElement|null) {
   if (!element) {
     return;
   }
-  const iframe = await (element as any).iframePromise_;
-  if (iframe) {
-    iframe.remove();
-    await flushTasks();
-  }
   element.remove();
   await flushTasks();
 }
@@ -81,25 +74,6 @@
   };
 }
 
-function getDebugString(w: any) {
-  if (w === window) {
-    return w.location.href;
-  }
-  return 'iframe';
-}
-
-/**
- * Helper function to test if two window objects are the same.
- * Plain |assertEquals| fails when it attempts to get a debug string
- * representation of cross-origin iframe window.
- */
-export function assertWindowObjectsEqual(x: object|null, y: object|null) {
-  assertTrue(
-      x === y,
-      `Window objects are not identical: ${getDebugString(x)}, ${
-          getDebugString(y)}`);
-}
-
 /**
  * Helper function to setup a mock `IFrameApi` singleton.
  */
diff --git a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_collections_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_collections_element_test.ts
index 2f07fe1..833aee4 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_collections_element_test.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_collections_element_test.ts
@@ -6,12 +6,13 @@
 import {IFrameApi} from 'chrome://personalization/trusted/iframe_api.js';
 import {GooglePhotosPhoto} from 'chrome://personalization/trusted/personalization_app.mojom-webui.js';
 import {emptyState} from 'chrome://personalization/trusted/personalization_state.js';
+import {WallpaperActionName} from 'chrome://personalization/trusted/wallpaper/wallpaper_actions.js';
 import {WallpaperCollections} from 'chrome://personalization/trusted/wallpaper/wallpaper_collections_element.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {waitAfterNextRender} from 'chrome://webui-test/test_util.js';
 
-import {assertWindowObjectsEqual, baseSetup, initElement, setupTestIFrameApi, teardownElement} from './personalization_app_test_utils.js';
+import {baseSetup, initElement, setupTestIFrameApi, teardownElement} from './personalization_app_test_utils.js';
 import {TestPersonalizationStore} from './test_personalization_store.js';
 import {TestWallpaperProvider} from './test_wallpaper_interface_provider.js';
 
@@ -50,11 +51,12 @@
         Parameters<IFrameApi['sendCollections']>;
     await waitAfterNextRender(wallpaperCollectionsElement);
 
-    const iframe =
-        wallpaperCollectionsElement.shadowRoot!.querySelector('iframe');
-    assertFalse(iframe!.hidden);
+    const main = wallpaperCollectionsElement.shadowRoot!.querySelector('main');
+    assertFalse(main!.hidden);
 
-    assertWindowObjectsEqual(iframe!.contentWindow, target);
+    assertEquals(
+        wallpaperCollectionsElement.$.collectionsGrid, target,
+        'collections data is sent to collections-grid');
     assertDeepEquals(wallpaperProvider!.collections, data);
   });
 
@@ -73,11 +75,12 @@
         Parameters<IFrameApi['sendGooglePhotosCount']>;
     await waitAfterNextRender(wallpaperCollectionsElement);
 
-    const iframe =
-        wallpaperCollectionsElement.shadowRoot!.querySelector('iframe');
-    assertFalse(iframe!.hidden);
+    const main = wallpaperCollectionsElement.shadowRoot!.querySelector('main');
+    assertFalse(main!.hidden);
 
-    assertWindowObjectsEqual(iframe!.contentWindow, target);
+    assertEquals(
+        wallpaperCollectionsElement.$.collectionsGrid, target,
+        'google photos count is sent to collections-grid');
     assertDeepEquals(
         personalizationStore.data.wallpaper.googlePhotos.count, data);
   });
@@ -99,11 +102,12 @@
         Parameters<IFrameApi['sendGooglePhotosPhotos']>;
     await waitAfterNextRender(wallpaperCollectionsElement);
 
-    const iframe =
-        wallpaperCollectionsElement.shadowRoot!.querySelector('iframe');
-    assertFalse(iframe!.hidden);
+    const main = wallpaperCollectionsElement.shadowRoot!.querySelector('main');
+    assertFalse(main!.hidden);
 
-    assertWindowObjectsEqual(iframe!.contentWindow, target);
+    assertEquals(
+        wallpaperCollectionsElement.$.collectionsGrid, target,
+        'google photos urls are sent to collections-grid');
     assertDeepEquals(
         personalizationStore.data.wallpaper.googlePhotos.photos
             .slice(0, kMaximumGooglePhotosPreviews)
@@ -122,9 +126,8 @@
       images: {},
     };
 
-    wallpaperCollectionsElement = initElement(WallpaperCollections);
-    // Wait for initial load to complete.
     const testProxy = setupTestIFrameApi();
+    wallpaperCollectionsElement = initElement(WallpaperCollections);
     await testProxy.whenCalled('sendImageCounts');
 
     testProxy.resetResolver('sendImageCounts');
@@ -186,11 +189,12 @@
         Parameters<IFrameApi['sendLocalImages']>;
     await waitAfterNextRender(wallpaperCollectionsElement);
 
-    const iframe =
-        wallpaperCollectionsElement.shadowRoot!.querySelector('iframe');
-    assertFalse(iframe!.hidden);
+    const main = wallpaperCollectionsElement.shadowRoot!.querySelector('main');
+    assertFalse(main!.hidden);
 
-    assertWindowObjectsEqual(iframe!.contentWindow, target);
+    assertEquals(
+        wallpaperCollectionsElement.$.collectionsGrid, target,
+        'local image urls are sent to collections-grid');
     assertDeepEquals(wallpaperProvider.localImages, data);
   });
 
@@ -215,11 +219,12 @@
         Parameters<IFrameApi['sendCollections']>;
     await waitAfterNextRender(wallpaperCollectionsElement);
 
-    const iframe =
-        wallpaperCollectionsElement.shadowRoot!.querySelector('iframe');
-    assertFalse(iframe!.hidden);
+    const main = wallpaperCollectionsElement.shadowRoot!.querySelector('main');
+    assertFalse(main!.hidden);
 
-    assertWindowObjectsEqual(iframe!.contentWindow, target);
+    assertEquals(
+        wallpaperCollectionsElement.$.collectionsGrid, target,
+        'null sent to collections-grid when failed to fetch data');
     assertEquals(null, data);
 
     // Wait for |sendLocalImages| to be called.
@@ -228,9 +233,11 @@
         Parameters<IFrameApi['sendLocalImages']>;
     await waitAfterNextRender(wallpaperCollectionsElement);
 
-    assertFalse(iframe!.hidden);
+    assertFalse(main!.hidden);
 
-    assertWindowObjectsEqual(iframe!.contentWindow, imageTarget);
+    assertEquals(
+        wallpaperCollectionsElement.$.collectionsGrid, imageTarget,
+        'local images still sent to collections-grid when offline');
     assertDeepEquals(wallpaperProvider.localImages, imageData);
   });
 
@@ -256,9 +263,9 @@
         'wallpaper-error');
     assertTrue(!!error);
 
-    // Iframe should be hidden if there is an error.
-    assertTrue(wallpaperCollectionsElement.shadowRoot!.querySelector(
-                                                          'iframe')!.hidden);
+    assertTrue(
+        wallpaperCollectionsElement.shadowRoot!.querySelector('main')!.hidden,
+        'main should be hidden if there is an error');
   });
 
   test('loads backdrop data and saves to store', async () => {
@@ -266,14 +273,15 @@
     assertDeepEquals(emptyState(), personalizationStore.data);
     // Actually run the reducers.
     personalizationStore.setReducersEnabled(true);
-
-    const testProxy = setupTestIFrameApi();
+    personalizationStore.expectAction(
+        WallpaperActionName.SET_IMAGES_FOR_COLLECTION);
+    setupTestIFrameApi();
 
     wallpaperCollectionsElement = initElement(WallpaperCollections);
 
-    const [_, collections] = await testProxy.whenCalled('sendCollections') as
-        Parameters<IFrameApi['sendCollections']>;
-    assertDeepEquals(wallpaperProvider.collections, collections);
+    await personalizationStore.waitForAction(
+        WallpaperActionName.SET_IMAGES_FOR_COLLECTION);
+
 
     assertDeepEquals(
         {
@@ -284,6 +292,7 @@
           },
         },
         personalizationStore.data.wallpaper.backdrop,
+        'expected backdrop data is set',
     );
     assertDeepEquals(
         {
@@ -295,6 +304,7 @@
           },
         },
         personalizationStore.data.wallpaper.loading,
+        'expected loading state is set',
     );
   });
 
@@ -333,7 +343,6 @@
         };
         personalizationStore.notifyObservers();
 
-        await wallpaperCollectionsElement['iframePromise_'];
         await waitAfterNextRender(wallpaperCollectionsElement);
 
         // Should not have sent any image data since more thumbnails are still
@@ -369,14 +378,13 @@
             sentData);
       });
 
-  test('sets aria label on collections-iframe', async () => {
+  test('sets aria label on main', async () => {
     wallpaperCollectionsElement = initElement(WallpaperCollections);
     await waitAfterNextRender(wallpaperCollectionsElement);
 
     assertEquals(
         loadTimeData.getString('wallpaperCollections'),
-        wallpaperCollectionsElement.shadowRoot
-            ?.getElementById('collections-iframe')
+        wallpaperCollectionsElement.shadowRoot?.querySelector('main')
             ?.getAttribute('aria-label'),
         'aria label equals expected value');
   });
diff --git a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_images_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_images_element_test.ts
index 60f799e..c8cbe5f 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_images_element_test.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_images_element_test.ts
@@ -7,10 +7,10 @@
 import {PersonalizationRouter} from 'chrome://personalization/trusted/personalization_router_element.js';
 import {getDarkLightImageTiles, getRegularImageTiles, WallpaperImages} from 'chrome://personalization/trusted/wallpaper/wallpaper_images_element.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {assertDeepEquals, assertEquals, assertFalse} from 'chrome://webui-test/chai_assert.js';
+import {assertDeepEquals, assertEquals} from 'chrome://webui-test/chai_assert.js';
 import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/test_util.js';
 
-import {assertWindowObjectsEqual, baseSetup, initElement, setupTestIFrameApi, teardownElement} from './personalization_app_test_utils.js';
+import {baseSetup, initElement, setupTestIFrameApi, teardownElement} from './personalization_app_test_utils.js';
 import {TestPersonalizationStore} from './test_personalization_store.js';
 import {TestWallpaperProvider} from './test_wallpaper_interface_provider.js';
 
@@ -42,15 +42,14 @@
     wallpaperImagesElement =
         initElement(WallpaperImages, {collectionId: 'id_0'});
 
-    const iframe = wallpaperImagesElement.shadowRoot!.getElementById(
-                       'images-iframe') as HTMLIFrameElement;
+    const imagesGrid = wallpaperImagesElement.$.imagesGrid;
 
     // Wait for iframe to receive data.
-    let [targetWindow, data] =
+    let [target, data] =
         await testProxy.whenCalled('sendCurrentWallpaperAssetId') as
         Parameters<IFrameApi['sendCurrentWallpaperAssetId']>;
 
-    assertEquals(iframe.contentWindow, targetWindow);
+    assertEquals(imagesGrid, target);
     assertDeepEquals(
         BigInt(personalizationStore.data.wallpaper.currentSelected.key), data);
 
@@ -68,10 +67,10 @@
     personalizationStore.notifyObservers();
 
     // Wait for iframe to receive data.
-    [targetWindow, data] =
+    [target, data] =
         await testProxy.whenCalled('sendCurrentWallpaperAssetId') as
         Parameters<IFrameApi['sendCurrentWallpaperAssetId']>;
-    assertEquals(iframe.contentWindow, targetWindow);
+    assertEquals(imagesGrid, target);
     assertDeepEquals(
         BigInt(personalizationStore.data.wallpaper.currentSelected.key), data);
 
@@ -89,10 +88,10 @@
     personalizationStore.notifyObservers();
 
     // Wait for iframe to receive data.
-    [targetWindow, data] =
+    [target, data] =
         await testProxy.whenCalled('sendCurrentWallpaperAssetId') as
         Parameters<IFrameApi['sendCurrentWallpaperAssetId']>;
-    assertEquals(iframe.contentWindow, targetWindow);
+    assertEquals(imagesGrid, target);
     assertEquals(undefined, data);
   });
 
@@ -116,33 +115,29 @@
     wallpaperImagesElement =
         initElement(WallpaperImages, {collectionId: 'id_0'});
 
-    const iframe = wallpaperImagesElement.shadowRoot!.getElementById(
-                       'images-iframe') as HTMLIFrameElement;
+    const imagesGrid = wallpaperImagesElement.$.imagesGrid;
 
     // Wait for iframe to receive data.
-    let [targetWindow, data] = await testProxy.whenCalled('sendImageTiles') as
+    let [target, data] = await testProxy.whenCalled('sendImageTiles') as
         Parameters<IFrameApi['sendImageTiles']>;
-    assertEquals(iframe.contentWindow, targetWindow);
+    assertEquals(imagesGrid, target);
     assertDeepEquals(
         getRegularImageTiles(
             personalizationStore.data.wallpaper.backdrop.images['id_0']),
         data);
     // Wait for a render to happen.
     await waitAfterNextRender(wallpaperImagesElement);
-    assertFalse(iframe.hidden);
 
     testProxy.resetResolver('sendImageTiles');
     wallpaperImagesElement.collectionId = 'id_1';
 
     // Wait for iframe to receive new data.
-    [targetWindow, data] = await testProxy.whenCalled('sendImageTiles') as
+    [target, data] = await testProxy.whenCalled('sendImageTiles') as
         Parameters<IFrameApi['sendImageTiles']>;
 
     await waitAfterNextRender(wallpaperImagesElement);
 
-    assertFalse(iframe.hidden);
-
-    assertWindowObjectsEqual(iframe.contentWindow, targetWindow);
+    assertEquals(imagesGrid, target);
     assertDeepEquals(
         getRegularImageTiles(
             personalizationStore.data.wallpaper.backdrop.images['id_1']),
@@ -170,13 +165,12 @@
     wallpaperImagesElement =
         initElement(WallpaperImages, {collectionId: 'id_0'});
 
-    const iframe = wallpaperImagesElement.shadowRoot!.getElementById(
-                       'images-iframe') as HTMLIFrameElement;
+    const imagesGrid = wallpaperImagesElement.$.imagesGrid;
 
-    // Wait for iframe to receive data.
-    let [targetWindow, data] = await testProxy.whenCalled('sendImageTiles') as
+    // Wait for images-grid to receive data.
+    let [target, data] = await testProxy.whenCalled('sendImageTiles') as
         Parameters<IFrameApi['sendImageTiles']>;
-    assertEquals(iframe.contentWindow, targetWindow);
+    assertEquals(imagesGrid, target);
     const tiles = getDarkLightImageTiles(
         false, personalizationStore.data.wallpaper.backdrop.images['id_0']);
     assertDeepEquals(tiles, data);
@@ -188,20 +182,17 @@
         data[0]!.preview[1]!.url, 'https://images.googleusercontent.com/0');
     // Wait for a render to happen.
     await waitAfterNextRender(wallpaperImagesElement);
-    assertFalse(iframe.hidden);
 
     testProxy.resetResolver('sendImageTiles');
     wallpaperImagesElement.collectionId = 'id_1';
 
     // Wait for iframe to receive new data.
-    [targetWindow, data] = await testProxy.whenCalled('sendImageTiles') as
+    [target, data] = await testProxy.whenCalled('sendImageTiles') as
         Parameters<IFrameApi['sendImageTiles']>;
 
     await waitAfterNextRender(wallpaperImagesElement);
 
-    assertFalse(iframe.hidden);
-
-    assertWindowObjectsEqual(iframe.contentWindow, targetWindow);
+    assertEquals(imagesGrid, target);
     assertDeepEquals(
         getDarkLightImageTiles(
             false, personalizationStore.data.wallpaper.backdrop.images['id_1']),
diff --git a/chrome/test/data/webui/new_tab_page/modules/cart/module_test.ts b/chrome/test/data/webui/new_tab_page/modules/cart/module_test.ts
index 42091f8..5104b80 100644
--- a/chrome/test/data/webui/new_tab_page/modules/cart/module_test.ts
+++ b/chrome/test/data/webui/new_tab_page/modules/cart/module_test.ts
@@ -804,7 +804,8 @@
 
     test('scroll with consent card', async () => testScrollWithConsent());
 
-    test('click on cart item', async () => {
+    // https://crbug.com/1287294: Flaky
+    test.skip('click on cart item', async () => {
       const carts = [
         {
           merchant: 'Amazon',
@@ -988,7 +989,8 @@
       loadTimeData.overrideValues({ruleBasedDiscountEnabled: true});
     });
 
-    test('click on cart item with rule-based discount', async () => {
+    // https://crbug.com/1287294: Flaky
+    test.skip('click on cart item with rule-based discount', async () => {
       const carts = [
         {
           merchant: 'Amazon',
@@ -1177,8 +1179,9 @@
       await flushTasks();
 
       // Assert.
-      assertEquals(false, isVisible(consentCard));
-      assertEquals(true, consentToast.open);
+      assertEquals(
+          false, isVisible(consentCard), 'consent cart should not be visible');
+      assertEquals(true, consentToast.open, 'consentToast should open');
       assertEquals(
           'Accept confirmation!',
           moduleElement.$.confirmDiscountConsentMessage.innerText);
diff --git a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js
index 107e27b..8a8932d3 100644
--- a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js
+++ b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js
@@ -321,8 +321,7 @@
   }
 };
 
-// https://crbug.com/1287294: Flaky
-TEST_F('NewTabPageModulesChromeCartModuleTest', 'DISABLED_All', function() {
+TEST_F('NewTabPageModulesChromeCartModuleTest', 'All', function() {
   mocha.run();
 });
 
diff --git a/chrome/test/webapps/coverage/coverage_cros.tsv b/chrome/test/webapps/coverage/coverage_cros.tsv
index 9b3d75d5..530b8b4 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: 48%, 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🌑
@@ -164,27 +164,27 @@
 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_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_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🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
@@ -200,103 +200,103 @@
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_colors_SiteA🌑	launch_from_launch_icon_SiteA🌑	check_window_color_correct🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_colors_SiteA🌑	launch_from_chrome_apps_SiteA🌑	check_window_color_correct🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_colors_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_color_correct🌑
-install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_tab_not_created🌕
+install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_tab_not_created🌑
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_tab_not_created🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_tab_not_created🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_tab_not_created🌑
-install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_tab_not_created🌕
+install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_tab_not_created🌑
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_tab_not_created🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_tab_not_created🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_tab_not_created🌑
-install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_tab_not_created🌕
+install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_tab_not_created🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_tab_not_created🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_tab_not_created🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_tab_not_created🌑
-install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 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_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_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🌕
 install_create_shortcut_tabbed_SiteA🌕	set_open_in_window_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_create_shortcut_windowed_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_create_shortcut_windowed_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_omnibox_icon_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_omnibox_icon_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_omnibox_icon_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_menu_option_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_menu_option_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_create_shortcut_windowed_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_create_shortcut_windowed_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_create_shortcut_windowed_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_create_shortcut_windowed_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
-install_omnibox_icon_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_omnibox_icon_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_omnibox_icon_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_omnibox_icon_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_omnibox_icon_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
-install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
-install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
-install_menu_option_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_menu_option_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_menu_option_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_menu_option_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_menu_option_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
@@ -308,57 +308,68 @@
 install_policy_app_windowed_no_shortcut_SiteA🌓	delete_platform_shortcut_SiteA🌑	create_shortcuts_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
 install_policy_app_windowed_shortcut_SiteA🌓	delete_platform_shortcut_SiteA🌑	create_shortcuts_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	delete_platform_shortcut_SiteA🌑	create_shortcuts_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 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_menu_option_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_windowed_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_menu_option_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_menu_option_SiteA🌑	check_tab_created🌑
 install_omnibox_icon_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_omnibox_icon_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_policy_app_windowed_no_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 install_policy_app_windowed_no_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_policy_app_windowed_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 install_policy_app_windowed_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_policy_app_windowed_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_menu_option_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 install_menu_option_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_menu_option_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_create_shortcut_tabbed_SiteC🌕	launch_from_menu_option_SiteC🌑	check_tab_created🌑
 install_create_shortcut_tabbed_SiteC🌕	launch_from_chrome_apps_SiteC🌓	check_tab_created🌕
 install_create_shortcut_tabbed_SiteC🌕	launch_from_platform_shortcut_SiteC🌑	check_tab_created🌑
+install_policy_app_tabbed_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌑	check_tab_created🌑
 install_policy_app_tabbed_shortcut_SiteC🌓	launch_from_chrome_apps_SiteC🌓	check_tab_created🌕
 install_policy_app_tabbed_shortcut_SiteC🌓	launch_from_platform_shortcut_SiteC🌑	check_tab_created🌑
+install_policy_app_tabbed_no_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌑	check_tab_created🌑
 install_policy_app_tabbed_no_shortcut_SiteC🌓	launch_from_chrome_apps_SiteC🌓	check_tab_created🌕
 install_policy_app_tabbed_no_shortcut_SiteC🌓	launch_from_platform_shortcut_SiteC🌑	check_tab_created🌑
-install_create_shortcut_windowed_SiteB🌕	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_create_shortcut_windowed_SiteB🌕	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_create_shortcut_windowed_SiteB🌕	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteB🌕	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteB🌕	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_omnibox_icon_SiteB🌕	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_omnibox_icon_SiteB🌕	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_omnibox_icon_SiteB🌕	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_omnibox_icon_SiteB🌕	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_omnibox_icon_SiteB🌕	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_policy_app_windowed_shortcut_SiteB🌓	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_policy_app_windowed_shortcut_SiteB🌓	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_policy_app_windowed_shortcut_SiteB🌓	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_policy_app_windowed_shortcut_SiteB🌓	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_policy_app_windowed_shortcut_SiteB🌓	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_menu_option_SiteB🌕	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_menu_option_SiteB🌕	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_menu_option_SiteB🌕	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_menu_option_SiteB🌕	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_menu_option_SiteB🌕	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_create_shortcut_windowed_SiteC🌕	launch_from_menu_option_SiteC🌕	check_window_created🌕
+install_create_shortcut_windowed_SiteC🌕	launch_from_menu_option_SiteC🌑	check_window_created🌑
 install_create_shortcut_windowed_SiteC🌕	launch_from_launch_icon_SiteC🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteC🌕	launch_from_chrome_apps_SiteC🌓	check_window_created🌕
 install_create_shortcut_windowed_SiteC🌕	launch_from_platform_shortcut_SiteC🌑	check_window_created🌑
-install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌕	check_window_created🌕
+install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌑	check_window_created🌑
 install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_launch_icon_SiteC🌕	check_window_created🌕
 install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_chrome_apps_SiteC🌓	check_window_created🌕
 install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_platform_shortcut_SiteC🌑	check_window_created🌑
-install_policy_app_windowed_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌕	check_window_created🌕
+install_policy_app_windowed_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌑	check_window_created🌑
 install_policy_app_windowed_shortcut_SiteC🌓	launch_from_launch_icon_SiteC🌕	check_window_created🌕
 install_policy_app_windowed_shortcut_SiteC🌓	launch_from_chrome_apps_SiteC🌓	check_window_created🌕
 install_policy_app_windowed_shortcut_SiteC🌓	launch_from_platform_shortcut_SiteC🌑	check_window_created🌑
diff --git a/chrome/test/webapps/coverage/coverage_linux.tsv b/chrome/test/webapps/coverage/coverage_linux.tsv
index 8259d32..03969429 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: 53%, with partial coverage: 70%
+# Full coverage: 49%, 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🌑
@@ -187,27 +187,27 @@
 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_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_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🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
@@ -223,115 +223,115 @@
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_colors_SiteA🌑	launch_from_launch_icon_SiteA🌑	check_window_color_correct🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_colors_SiteA🌑	launch_from_chrome_apps_SiteA🌑	check_window_color_correct🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_colors_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_color_correct🌑
-install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_tab_not_created🌕
+install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_tab_not_created🌑
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_tab_not_created🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_tab_not_created🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_tab_not_created🌑
-install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_tab_not_created🌕
+install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_tab_not_created🌑
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_tab_not_created🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_tab_not_created🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_tab_not_created🌑
-install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_tab_not_created🌕
+install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_tab_not_created🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_tab_not_created🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_tab_not_created🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_tab_not_created🌑
-install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 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_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_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_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_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🌕
 install_create_shortcut_tabbed_SiteA🌕	set_open_in_window_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_create_shortcut_windowed_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_create_shortcut_windowed_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_omnibox_icon_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_omnibox_icon_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_omnibox_icon_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_menu_option_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_menu_option_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_create_shortcut_windowed_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_create_shortcut_windowed_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_create_shortcut_windowed_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_create_shortcut_windowed_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
-install_omnibox_icon_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_omnibox_icon_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_omnibox_icon_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_omnibox_icon_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_omnibox_icon_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
-install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
-install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
-install_menu_option_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_menu_option_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_menu_option_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_menu_option_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_menu_option_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
@@ -343,65 +343,80 @@
 install_policy_app_windowed_no_shortcut_SiteA🌓	delete_platform_shortcut_SiteA🌑	create_shortcuts_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
 install_policy_app_windowed_shortcut_SiteA🌓	delete_platform_shortcut_SiteA🌑	create_shortcuts_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	delete_platform_shortcut_SiteA🌑	create_shortcuts_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 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_menu_option_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🌕	install_locally_SiteA🌓	launch_from_menu_option_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_menu_option_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_menu_option_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_menu_option_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_menu_option_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_menu_option_SiteA🌑	check_tab_created🌑
 install_omnibox_icon_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_omnibox_icon_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_policy_app_windowed_no_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 install_policy_app_windowed_no_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_policy_app_windowed_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 install_policy_app_windowed_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_policy_app_windowed_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_menu_option_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 install_menu_option_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_menu_option_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_create_shortcut_tabbed_SiteC🌕	launch_from_menu_option_SiteC🌑	check_tab_created🌑
 install_create_shortcut_tabbed_SiteC🌕	launch_from_chrome_apps_SiteC🌓	check_tab_created🌕
 install_create_shortcut_tabbed_SiteC🌕	launch_from_platform_shortcut_SiteC🌑	check_tab_created🌑
+install_policy_app_tabbed_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌑	check_tab_created🌑
 install_policy_app_tabbed_shortcut_SiteC🌓	launch_from_chrome_apps_SiteC🌓	check_tab_created🌕
 install_policy_app_tabbed_shortcut_SiteC🌓	launch_from_platform_shortcut_SiteC🌑	check_tab_created🌑
+install_policy_app_tabbed_no_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌑	check_tab_created🌑
 install_policy_app_tabbed_no_shortcut_SiteC🌓	launch_from_chrome_apps_SiteC🌓	check_tab_created🌕
 install_policy_app_tabbed_no_shortcut_SiteC🌓	launch_from_platform_shortcut_SiteC🌑	check_tab_created🌑
-install_create_shortcut_windowed_SiteB🌕	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_create_shortcut_windowed_SiteB🌕	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_create_shortcut_windowed_SiteB🌕	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteB🌕	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteB🌕	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_omnibox_icon_SiteB🌕	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_omnibox_icon_SiteB🌕	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_omnibox_icon_SiteB🌕	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_omnibox_icon_SiteB🌕	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_omnibox_icon_SiteB🌕	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_policy_app_windowed_shortcut_SiteB🌓	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_policy_app_windowed_shortcut_SiteB🌓	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_policy_app_windowed_shortcut_SiteB🌓	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_policy_app_windowed_shortcut_SiteB🌓	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_policy_app_windowed_shortcut_SiteB🌓	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_menu_option_SiteB🌕	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_menu_option_SiteB🌕	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_menu_option_SiteB🌕	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_menu_option_SiteB🌕	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_menu_option_SiteB🌕	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_create_shortcut_windowed_SiteC🌕	launch_from_menu_option_SiteC🌕	check_window_created🌕
+install_create_shortcut_windowed_SiteC🌕	launch_from_menu_option_SiteC🌑	check_window_created🌑
 install_create_shortcut_windowed_SiteC🌕	launch_from_launch_icon_SiteC🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteC🌕	launch_from_chrome_apps_SiteC🌓	check_window_created🌕
 install_create_shortcut_windowed_SiteC🌕	launch_from_platform_shortcut_SiteC🌑	check_window_created🌑
-install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌕	check_window_created🌕
+install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌑	check_window_created🌑
 install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_launch_icon_SiteC🌕	check_window_created🌕
 install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_chrome_apps_SiteC🌓	check_window_created🌕
 install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_platform_shortcut_SiteC🌑	check_window_created🌑
-install_policy_app_windowed_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌕	check_window_created🌕
+install_policy_app_windowed_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌑	check_window_created🌑
 install_policy_app_windowed_shortcut_SiteC🌓	launch_from_launch_icon_SiteC🌕	check_window_created🌕
 install_policy_app_windowed_shortcut_SiteC🌓	launch_from_chrome_apps_SiteC🌓	check_window_created🌕
 install_policy_app_windowed_shortcut_SiteC🌓	launch_from_platform_shortcut_SiteC🌑	check_window_created🌑
diff --git a/chrome/test/webapps/coverage/coverage_mac.tsv b/chrome/test/webapps/coverage/coverage_mac.tsv
index 170ccf0..d416809 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: 49%, with partial coverage: 65%
+# Full coverage: 43%, with partial coverage: 58%
 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🌑
@@ -73,22 +73,22 @@
 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_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🌑
@@ -187,27 +187,27 @@
 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_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_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🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
@@ -223,115 +223,115 @@
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_colors_SiteA🌑	launch_from_launch_icon_SiteA🌑	check_window_color_correct🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_colors_SiteA🌑	launch_from_chrome_apps_SiteA🌑	check_window_color_correct🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_colors_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_color_correct🌑
-install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_tab_not_created🌕
+install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_tab_not_created🌑
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_tab_not_created🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_tab_not_created🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_tab_not_created🌑
-install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_tab_not_created🌕
+install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_tab_not_created🌑
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_tab_not_created🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_tab_not_created🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_tab_not_created🌑
-install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_tab_not_created🌕
+install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_tab_not_created🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_tab_not_created🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_tab_not_created🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_tab_not_created🌑
-install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 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_tabbed_SiteA🌕	set_open_in_window_SiteA🌓	launch_from_menu_option_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🌕
 install_create_shortcut_tabbed_SiteA🌕	set_open_in_window_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_create_shortcut_windowed_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_create_shortcut_windowed_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_omnibox_icon_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_omnibox_icon_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_omnibox_icon_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_menu_option_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_menu_option_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_create_shortcut_windowed_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_create_shortcut_windowed_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_create_shortcut_windowed_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_create_shortcut_windowed_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
-install_omnibox_icon_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_omnibox_icon_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_omnibox_icon_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_omnibox_icon_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_omnibox_icon_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
-install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
-install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
-install_menu_option_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_menu_option_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_menu_option_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_menu_option_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_menu_option_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
@@ -343,65 +343,80 @@
 install_policy_app_windowed_no_shortcut_SiteA🌓	delete_platform_shortcut_SiteA🌑	create_shortcuts_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
 install_policy_app_windowed_shortcut_SiteA🌓	delete_platform_shortcut_SiteA🌑	create_shortcuts_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	delete_platform_shortcut_SiteA🌑	create_shortcuts_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 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_menu_option_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🌕	install_locally_SiteA🌓	launch_from_menu_option_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_windowed_SiteA🌕	switch_profile_clients_Client2🌑	launch_from_menu_option_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_menu_option_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_menu_option_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_menu_option_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_menu_option_SiteA🌑	check_tab_created🌑
 install_omnibox_icon_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_omnibox_icon_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_policy_app_windowed_no_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 install_policy_app_windowed_no_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_policy_app_windowed_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 install_policy_app_windowed_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_policy_app_windowed_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_menu_option_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 install_menu_option_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_menu_option_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_create_shortcut_tabbed_SiteC🌕	launch_from_menu_option_SiteC🌑	check_tab_created🌑
 install_create_shortcut_tabbed_SiteC🌕	launch_from_chrome_apps_SiteC🌓	check_tab_created🌕
 install_create_shortcut_tabbed_SiteC🌕	launch_from_platform_shortcut_SiteC🌑	check_tab_created🌑
+install_policy_app_tabbed_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌑	check_tab_created🌑
 install_policy_app_tabbed_shortcut_SiteC🌓	launch_from_chrome_apps_SiteC🌓	check_tab_created🌕
 install_policy_app_tabbed_shortcut_SiteC🌓	launch_from_platform_shortcut_SiteC🌑	check_tab_created🌑
+install_policy_app_tabbed_no_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌑	check_tab_created🌑
 install_policy_app_tabbed_no_shortcut_SiteC🌓	launch_from_chrome_apps_SiteC🌓	check_tab_created🌕
 install_policy_app_tabbed_no_shortcut_SiteC🌓	launch_from_platform_shortcut_SiteC🌑	check_tab_created🌑
-install_create_shortcut_windowed_SiteB🌕	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_create_shortcut_windowed_SiteB🌕	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_create_shortcut_windowed_SiteB🌕	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteB🌕	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteB🌕	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_omnibox_icon_SiteB🌕	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_omnibox_icon_SiteB🌕	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_omnibox_icon_SiteB🌕	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_omnibox_icon_SiteB🌕	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_omnibox_icon_SiteB🌕	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_policy_app_windowed_shortcut_SiteB🌓	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_policy_app_windowed_shortcut_SiteB🌓	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_policy_app_windowed_shortcut_SiteB🌓	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_policy_app_windowed_shortcut_SiteB🌓	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_policy_app_windowed_shortcut_SiteB🌓	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_menu_option_SiteB🌕	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_menu_option_SiteB🌕	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_menu_option_SiteB🌕	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_menu_option_SiteB🌕	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_menu_option_SiteB🌕	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_create_shortcut_windowed_SiteC🌕	launch_from_menu_option_SiteC🌕	check_window_created🌕
+install_create_shortcut_windowed_SiteC🌕	launch_from_menu_option_SiteC🌑	check_window_created🌑
 install_create_shortcut_windowed_SiteC🌕	launch_from_launch_icon_SiteC🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteC🌕	launch_from_chrome_apps_SiteC🌓	check_window_created🌕
 install_create_shortcut_windowed_SiteC🌕	launch_from_platform_shortcut_SiteC🌑	check_window_created🌑
-install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌕	check_window_created🌕
+install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌑	check_window_created🌑
 install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_launch_icon_SiteC🌕	check_window_created🌕
 install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_chrome_apps_SiteC🌓	check_window_created🌕
 install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_platform_shortcut_SiteC🌑	check_window_created🌑
-install_policy_app_windowed_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌕	check_window_created🌕
+install_policy_app_windowed_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌑	check_window_created🌑
 install_policy_app_windowed_shortcut_SiteC🌓	launch_from_launch_icon_SiteC🌕	check_window_created🌕
 install_policy_app_windowed_shortcut_SiteC🌓	launch_from_chrome_apps_SiteC🌓	check_window_created🌕
 install_policy_app_windowed_shortcut_SiteC🌓	launch_from_platform_shortcut_SiteC🌑	check_window_created🌑
@@ -526,20 +541,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 +565,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 +645,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🌕
diff --git a/chrome/test/webapps/coverage/coverage_win.tsv b/chrome/test/webapps/coverage/coverage_win.tsv
index 15dc3d4..749c586 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: 54%, with partial coverage: 71%
+# Full coverage: 51%, with partial coverage: 68%
 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🌑
@@ -187,27 +187,27 @@
 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_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_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🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_omnibox_icon_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_menu_option_SiteA🌕	install_policy_app_tabbed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_menu_option_SiteA🌕	install_policy_app_tabbed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
@@ -223,115 +223,115 @@
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_colors_SiteA🌑	launch_from_launch_icon_SiteA🌑	check_window_color_correct🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_colors_SiteA🌑	launch_from_chrome_apps_SiteA🌑	check_window_color_correct🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_colors_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_color_correct🌑
-install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_tab_not_created🌕
+install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_tab_not_created🌑
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_tab_not_created🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_tab_not_created🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_tab_not_created🌑
-install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_tab_not_created🌕
+install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_tab_not_created🌑
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_tab_not_created🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_tab_not_created🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_tab_not_created🌑
-install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_tab_not_created🌕
+install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_tab_not_created🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_tab_not_created🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_tab_not_created🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_tab_not_created🌑
-install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_browser_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_minimal🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_minimal🌕
 install_omnibox_icon_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_minimal🌑
-install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_minimal🌕
+install_menu_option_SiteA🌕	close_pwa🌕	manifest_update_display_minimal_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_minimal🌑
 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_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_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_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_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🌕
 install_create_shortcut_tabbed_SiteA🌕	set_open_in_window_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_policy_app_tabbed_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_policy_app_tabbed_no_shortcut_SiteA🌓	set_open_in_window_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_create_shortcut_windowed_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_create_shortcut_windowed_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_create_shortcut_windowed_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_omnibox_icon_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_omnibox_icon_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_omnibox_icon_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_omnibox_icon_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_omnibox_icon_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_menu_option_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_created🌕
+install_menu_option_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_created🌕
 install_menu_option_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_created🌕
 install_menu_option_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
-install_create_shortcut_windowed_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_create_shortcut_windowed_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_create_shortcut_windowed_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_create_shortcut_windowed_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_create_shortcut_windowed_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
-install_omnibox_icon_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_omnibox_icon_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_omnibox_icon_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_omnibox_icon_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_omnibox_icon_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
-install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
-install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_policy_app_windowed_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
-install_menu_option_SiteA🌕	launch_from_menu_option_SiteA🌕	check_window_display_standalone🌕
+install_menu_option_SiteA🌕	launch_from_menu_option_SiteA🌑	check_window_display_standalone🌑
 install_menu_option_SiteA🌕	launch_from_launch_icon_SiteA🌕	check_window_display_standalone🌕
 install_menu_option_SiteA🌕	launch_from_chrome_apps_SiteA🌓	check_window_display_standalone🌕
 install_menu_option_SiteA🌕	launch_from_platform_shortcut_SiteA🌑	check_window_display_standalone🌑
@@ -343,65 +343,80 @@
 install_policy_app_windowed_no_shortcut_SiteA🌓	delete_platform_shortcut_SiteA🌑	create_shortcuts_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
 install_policy_app_windowed_shortcut_SiteA🌓	delete_platform_shortcut_SiteA🌑	create_shortcuts_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
 install_menu_option_SiteA🌕	delete_platform_shortcut_SiteA🌑	create_shortcuts_SiteA🌑	launch_from_platform_shortcut_SiteA🌑	check_window_created🌑
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_no_shortcut_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_create_shortcut_tabbed_SiteA🌕	install_policy_app_windowed_shortcut_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 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_menu_option_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🌕	install_locally_SiteA🌓	launch_from_menu_option_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_menu_option_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_menu_option_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_menu_option_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_menu_option_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_menu_option_SiteA🌑	check_tab_created🌑
 install_omnibox_icon_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_omnibox_icon_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_policy_app_windowed_no_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 install_policy_app_windowed_no_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_policy_app_windowed_no_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_policy_app_windowed_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 install_policy_app_windowed_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_policy_app_windowed_shortcut_SiteA🌓	set_open_in_tab_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_menu_option_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_menu_option_SiteA🌑	check_tab_created🌑
 install_menu_option_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_chrome_apps_SiteA🌓	check_tab_created🌕
 install_menu_option_SiteA🌕	set_open_in_tab_SiteA🌓	launch_from_platform_shortcut_SiteA🌑	check_tab_created🌑
+install_create_shortcut_tabbed_SiteC🌕	launch_from_menu_option_SiteC🌑	check_tab_created🌑
 install_create_shortcut_tabbed_SiteC🌕	launch_from_chrome_apps_SiteC🌓	check_tab_created🌕
 install_create_shortcut_tabbed_SiteC🌕	launch_from_platform_shortcut_SiteC🌑	check_tab_created🌑
+install_policy_app_tabbed_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌑	check_tab_created🌑
 install_policy_app_tabbed_shortcut_SiteC🌓	launch_from_chrome_apps_SiteC🌓	check_tab_created🌕
 install_policy_app_tabbed_shortcut_SiteC🌓	launch_from_platform_shortcut_SiteC🌑	check_tab_created🌑
+install_policy_app_tabbed_no_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌑	check_tab_created🌑
 install_policy_app_tabbed_no_shortcut_SiteC🌓	launch_from_chrome_apps_SiteC🌓	check_tab_created🌕
 install_policy_app_tabbed_no_shortcut_SiteC🌓	launch_from_platform_shortcut_SiteC🌑	check_tab_created🌑
-install_create_shortcut_windowed_SiteB🌕	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_create_shortcut_windowed_SiteB🌕	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_create_shortcut_windowed_SiteB🌕	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteB🌕	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_create_shortcut_windowed_SiteB🌕	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_omnibox_icon_SiteB🌕	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_omnibox_icon_SiteB🌕	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_omnibox_icon_SiteB🌕	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_omnibox_icon_SiteB🌕	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_omnibox_icon_SiteB🌕	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_policy_app_windowed_no_shortcut_SiteB🌓	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_policy_app_windowed_shortcut_SiteB🌓	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_policy_app_windowed_shortcut_SiteB🌓	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_policy_app_windowed_shortcut_SiteB🌓	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_policy_app_windowed_shortcut_SiteB🌓	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_policy_app_windowed_shortcut_SiteB🌓	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_menu_option_SiteB🌕	launch_from_menu_option_SiteB🌕	check_window_display_minimal🌕
+install_menu_option_SiteB🌕	launch_from_menu_option_SiteB🌑	check_window_display_minimal🌑
 install_menu_option_SiteB🌕	launch_from_launch_icon_SiteB🌕	check_window_display_minimal🌕
 install_menu_option_SiteB🌕	launch_from_chrome_apps_SiteB🌓	check_window_display_minimal🌕
 install_menu_option_SiteB🌕	launch_from_platform_shortcut_SiteB🌑	check_window_display_minimal🌑
-install_create_shortcut_windowed_SiteC🌕	launch_from_menu_option_SiteC🌕	check_window_created🌕
+install_create_shortcut_windowed_SiteC🌕	launch_from_menu_option_SiteC🌑	check_window_created🌑
 install_create_shortcut_windowed_SiteC🌕	launch_from_launch_icon_SiteC🌕	check_window_created🌕
 install_create_shortcut_windowed_SiteC🌕	launch_from_chrome_apps_SiteC🌓	check_window_created🌕
 install_create_shortcut_windowed_SiteC🌕	launch_from_platform_shortcut_SiteC🌑	check_window_created🌑
-install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌕	check_window_created🌕
+install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌑	check_window_created🌑
 install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_launch_icon_SiteC🌕	check_window_created🌕
 install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_chrome_apps_SiteC🌓	check_window_created🌕
 install_policy_app_windowed_no_shortcut_SiteC🌓	launch_from_platform_shortcut_SiteC🌑	check_window_created🌑
-install_policy_app_windowed_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌕	check_window_created🌕
+install_policy_app_windowed_shortcut_SiteC🌓	launch_from_menu_option_SiteC🌑	check_window_created🌑
 install_policy_app_windowed_shortcut_SiteC🌓	launch_from_launch_icon_SiteC🌕	check_window_created🌕
 install_policy_app_windowed_shortcut_SiteC🌓	launch_from_chrome_apps_SiteC🌓	check_window_created🌕
 install_policy_app_windowed_shortcut_SiteC🌓	launch_from_platform_shortcut_SiteC🌑	check_window_created🌑
diff --git a/chrome/test/webapps/data/actions.csv b/chrome/test/webapps/data/actions.csv
index cc3eb28..9ada38e 100644
--- a/chrome/test/webapps/data/actions.csv
+++ b/chrome/test/webapps/data/actions.csv
@@ -64,10 +64,10 @@
 install_with_shortcut,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,install_policy_app_windowed_shortcut & install_policy_app_tabbed_shortcut & install_create_shortcut_windowed & install_omnibox_icon & install_menu_option & install_create_shortcut_tabbed,63,,,,,N/A (Parameterized Action),,
 launch,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,launch_from_menu_option & launch_from_launch_icon & launch_from_chrome_apps & launch_from_platform_shortcut,64,,,,,N/A (Parameterized Action),,
 launch_from_browser,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,launch_from_menu_option & launch_from_launch_icon & launch_from_chrome_apps,65,,,,,N/A (Parameterized Action),,
-launch_from_shortcut_or_list,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,launch_from_chrome_apps & launch_from_platform_shortcut,66,,,,,N/A (Parameterized Action),All ways to launch an app that are still available for 'browser' apps.,
+launch_no_launch_icon,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,launch_from_menu_option & launch_from_chrome_apps & launch_from_platform_shortcut,66,,,,,N/A (Parameterized Action),All ways to launch an app except by using the launch icon - which isn't available for 'browser' apps.,
 uninstall_by_user,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,uninstall_from_list & uninstall_from_menu & uninstall_from_os & uninstall_from_app_settings,67,,,,,N/A (Parameterized Action),,
 manifest_update_icons,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,,68,,,,,Not Yet Implemented,Updates the icon field in the manifest of the website.,finnur@ is working on this
-launch_from_menu_option,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,,69,,,,,Implemented,"Launch the web app by navigating the browser to the web app, and selecting the ""Launch _"" menu option in the 3-dot menu.","cliffordcheng@, P1"
+launch_from_menu_option,SiteA* | SiteAFoo | SiteABar | SiteB | SiteC,,69,,,,,Not Yet Implemented,"Launch the web app by navigating the browser to the web app, and selecting the ""Launch _"" menu option in the 3-dot menu.",P1
 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"
diff --git a/chrome/test/webapps/data/coverage_required.csv b/chrome/test/webapps/data/coverage_required.csv
index 09fb430e..5811bbd 100644
--- a/chrome/test/webapps/data/coverage_required.csv
+++ b/chrome/test/webapps/data/coverage_required.csv
@@ -63,12 +63,12 @@
 WMLC,install_windowed,launch,check_window_display_standalone,install_windowed,launch,check_window_display_standalone,,,,,
 WMLC,install_tabbed & delete_platform_shortcut & create_shortcuts,launch_from_platform_shortcut,check_tab_created,install_tabbed,delete_platform_shortcut,create_shortcuts,launch_from_platform_shortcut,check_tab_created,,,
 WMLC,install_windowed & delete_platform_shortcut & create_shortcuts,launch_from_platform_shortcut,check_window_created,install_windowed,delete_platform_shortcut,create_shortcuts,launch_from_platform_shortcut,check_window_created,,,
-WMLC,install_by_user_tabbed & install_policy_app_windowed,launch_from_shortcut_or_list,check_tab_created,install_by_user_tabbed,install_policy_app_windowed,launch_from_shortcut_or_list,check_tab_created,,,,
-WMLC,install_by_user_tabbed & switch_profile_clients,launch_from_shortcut_or_list,check_tab_created,install_by_user_tabbed,switch_profile_clients,launch_from_shortcut_or_list,check_tab_created,,,,
-WML,install_by_user_tabbed & switch_profile_clients & install_locally,launch_from_shortcut_or_list,check_tab_created,install_by_user_tabbed,switch_profile_clients,install_locally,launch_from_shortcut_or_list,check_tab_created,,,
-WML,install_by_user_windowed & switch_profile_clients,launch_from_shortcut_or_list,check_tab_created,install_by_user_windowed,switch_profile_clients,launch_from_shortcut_or_list,check_tab_created,,,,
-WMLC,install_windowed & set_open_in_tab,launch_from_shortcut_or_list,check_tab_created,install_windowed,set_open_in_tab,launch_from_shortcut_or_list,check_tab_created,,,,
-WMLC,install_tabbed(SiteC),launch_from_shortcut_or_list(SiteC),check_tab_created,install_tabbed(SiteC),launch_from_shortcut_or_list(SiteC),check_tab_created,,,,,
+WMLC,install_by_user_tabbed & install_policy_app_windowed,launch_no_launch_icon,check_tab_created,install_by_user_tabbed,install_policy_app_windowed,launch_no_launch_icon,check_tab_created,,,,
+WMLC,install_by_user_tabbed & switch_profile_clients,launch_no_launch_icon,check_tab_created,install_by_user_tabbed,switch_profile_clients,launch_no_launch_icon,check_tab_created,,,,
+WML,install_by_user_tabbed & switch_profile_clients & install_locally,launch_no_launch_icon,check_tab_created,install_by_user_tabbed,switch_profile_clients,install_locally,launch_no_launch_icon,check_tab_created,,,
+WML,install_by_user_windowed & switch_profile_clients,launch_no_launch_icon,check_tab_created,install_by_user_windowed,switch_profile_clients,launch_no_launch_icon,check_tab_created,,,,
+WMLC,install_windowed & set_open_in_tab,launch_no_launch_icon,check_tab_created,install_windowed,set_open_in_tab,launch_no_launch_icon,check_tab_created,,,,
+WMLC,install_tabbed(SiteC),launch_no_launch_icon(SiteC),check_tab_created,install_tabbed(SiteC),launch_no_launch_icon(SiteC),check_tab_created,,,,,
 WMLC,install_windowed(SiteB),launch(SiteB),check_window_display_minimal,install_windowed(SiteB),launch(SiteB),check_window_display_minimal,,,,,
 WMLC,install_windowed(SiteC),launch(SiteC),check_window_created,install_windowed(SiteC),launch(SiteC),check_window_created,,,,,
 WMLC,install_by_user_windowed,manifest_update_icons,check_app_in_list_icon_correct,install_by_user_windowed,close_pwa,manifest_update_icons,check_app_in_list_icon_correct,,,,
diff --git a/chrome/test/webapps/data/framework_supported_actions.csv b/chrome/test/webapps/data/framework_supported_actions.csv
index b840ddf..5aca8cfd 100644
--- a/chrome/test/webapps/data/framework_supported_actions.csv
+++ b/chrome/test/webapps/data/framework_supported_actions.csv
@@ -30,7 +30,6 @@
 install_policy_app_windowed_shortcut,                  🌓, 🌓,  🌓,   🌓,
 launch_from_chrome_apps,                               🌓, 🌓,  🌓,   🌓,
 launch_from_launch_icon,                               🌕, 🌕,  🌕,   🌕,
-launch_from_menu_option,                               🌕, 🌕,  🌕,   🌕,
 manifest_update_display_browser,                       🌕, 🌕,  🌕,   🌕,
 manifest_update_display_minimal,                       🌕, 🌕,  🌕,   🌕,
 navigate_browser,                                      🌕, 🌕,  🌕,   🌕,
diff --git a/chrome/third_party/mozilla_security_manager/OWNERS b/chrome/third_party/mozilla_security_manager/OWNERS
index 79dbd13..04405ed2 100644
--- a/chrome/third_party/mozilla_security_manager/OWNERS
+++ b/chrome/third_party/mozilla_security_manager/OWNERS
@@ -1,3 +1,2 @@
 mattm@chromium.org
-rsleevi@chromium.org
 wtc@chromium.org
diff --git a/chromecast/cast_core/runtime/browser/BUILD.gn b/chromecast/cast_core/runtime/browser/BUILD.gn
index 9a65005..d414fb33 100644
--- a/chromecast/cast_core/runtime/browser/BUILD.gn
+++ b/chromecast/cast_core/runtime/browser/BUILD.gn
@@ -158,7 +158,18 @@
     "//content/public/browser",
     "//mojo/public/cpp/bindings",
     "//third_party/blink/public/common:headers",
+    "//third_party/openscreen/src/cast/streaming:receiver",
   ]
+
+  # TODO: Move this block up once the parent CL merges in. Without keeping it
+  # separate, rebasing wouldn't work
+  sources += [
+    "streaming_controller_remoting.cc",
+    "streaming_controller_remoting.h",
+  ]
+  if (enable_remoting_for_cwr) {
+    sources += [ "streaming_controller_factory_mirroring.cc" ]
+  }
 }
 
 cast_source_set("runtime_application_watcher") {
diff --git a/chromecast/cast_core/runtime/browser/DEPS b/chromecast/cast_core/runtime/browser/DEPS
index a50d028..159535d9 100644
--- a/chromecast/cast_core/runtime/browser/DEPS
+++ b/chromecast/cast_core/runtime/browser/DEPS
@@ -27,5 +27,5 @@
   "+third_party/grpc",
   "+third_party/metrics_proto",
   "+third_party/openscreen/src/cast/common/public/cast_streaming_app_ids.h",
-  "+third_party/openscreen/src/cast/streaming/constants.h",
+  "+third_party/openscreen/src/cast/streaming",
 ]
diff --git a/chromecast/cast_core/runtime/browser/streaming_controller_factory_remoting.cc b/chromecast/cast_core/runtime/browser/streaming_controller_factory_remoting.cc
new file mode 100644
index 0000000..bf5876c
--- /dev/null
+++ b/chromecast/cast_core/runtime/browser/streaming_controller_factory_remoting.cc
@@ -0,0 +1,21 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+
+#include "chromecast/cast_core/runtime/browser/streaming_controller_base.h"
+#include "chromecast/cast_core/runtime/browser/streaming_controller_remoting.h"
+#include "components/cast/message_port/message_port.h"
+
+namespace chromecast {
+
+// static
+std::unique_ptr<StreamingController> StreamingControllerBase::Create(
+    std::unique_ptr<cast_api_bindings::MessagePort> message_port,
+    CastWebContents* cast_web_contents) {
+  return std::make_unique<StreamingControllerRemoting>(std::move(message_port),
+                                                       cast_web_contents);
+}
+
+}  // namespace chromecast
diff --git a/chromecast/cast_core/runtime/browser/streaming_controller_mirroring.cc b/chromecast/cast_core/runtime/browser/streaming_controller_mirroring.cc
index b64612bd..57f832c9 100644
--- a/chromecast/cast_core/runtime/browser/streaming_controller_mirroring.cc
+++ b/chromecast/cast_core/runtime/browser/streaming_controller_mirroring.cc
@@ -22,8 +22,7 @@
         cast_streaming_receiver,
     mojo::AssociatedRemote<cast_streaming::mojom::RendererController>
         renderer_connection) {
-  receiver_session->SetCastStreamingReceiver(
-      std::move(cast_streaming_receiver));
+  receiver_session->StartStreamingAsync(std::move(cast_streaming_receiver));
 
   renderer_connection_ = std::move(renderer_connection);
   renderer_connection_->SetPlaybackController(
diff --git a/chromecast/cast_core/runtime/browser/streaming_controller_remoting.cc b/chromecast/cast_core/runtime/browser/streaming_controller_remoting.cc
new file mode 100644
index 0000000..c4fc8ed
--- /dev/null
+++ b/chromecast/cast_core/runtime/browser/streaming_controller_remoting.cc
@@ -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.
+
+#include "chromecast/cast_core/runtime/browser/streaming_controller_remoting.h"
+
+#include "components/cast/message_port/message_port.h"
+#include "components/cast_streaming/browser/public/receiver_session.h"
+#include "third_party/openscreen/src/cast/streaming/receiver_session.h"
+
+namespace chromecast {
+
+StreamingControllerRemoting::StreamingControllerRemoting(
+    std::unique_ptr<cast_api_bindings::MessagePort> message_port,
+    CastWebContents* cast_web_contents)
+    : StreamingControllerBase(std::move(message_port), cast_web_contents) {}
+
+StreamingControllerRemoting::~StreamingControllerRemoting() = default;
+
+void StreamingControllerRemoting::StartPlayback(
+    cast_streaming::ReceiverSession* receiver_session,
+    mojo::AssociatedRemote<cast_streaming::mojom::CastStreamingReceiver>
+        cast_streaming_receiver,
+    mojo::AssociatedRemote<cast_streaming::mojom::RendererController>
+        renderer_connection) {
+  receiver_session->StartStreamingAsync(std::move(cast_streaming_receiver),
+                                        std::move(renderer_connection));
+
+  auto* renderer_controller = receiver_session->GetRendererControls();
+  DCHECK(renderer_controller);
+  DCHECK(renderer_controller->IsValid());
+  renderer_controller->StartPlayingFrom(base::Seconds(0));
+  renderer_controller->SetPlaybackRate(1.0);
+}
+
+void StreamingControllerRemoting::ProcessAVConstraints(
+    cast_streaming::ReceiverSession::AVConstraints* constraints) {
+  DCHECK(constraints);
+
+  // Ensure remoting is enabled for this streaming session.
+  if (!constraints->remoting) {
+    DLOG(INFO) << "Remoting configuration added to received AVConstraints";
+    constraints->remoting = std::make_unique<
+        openscreen::cast::ReceiverSession::RemotingPreferences>();
+  }
+}
+
+}  // namespace chromecast
diff --git a/chromecast/cast_core/runtime/browser/streaming_controller_remoting.h b/chromecast/cast_core/runtime/browser/streaming_controller_remoting.h
new file mode 100644
index 0000000..a918162
--- /dev/null
+++ b/chromecast/cast_core/runtime/browser/streaming_controller_remoting.h
@@ -0,0 +1,50 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_CAST_CORE_RUNTIME_BROWSER_STREAMING_CONTROLLER_REMOTING_H_
+#define CHROMECAST_CAST_CORE_RUNTIME_BROWSER_STREAMING_CONTROLLER_REMOTING_H_
+
+#include <memory>
+
+#include "chromecast/cast_core/runtime/browser/streaming_controller_base.h"
+#include "components/cast_streaming/public/mojom/cast_streaming_session.mojom.h"
+#include "components/cast_streaming/public/mojom/renderer_controller.mojom.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+
+namespace cast_api_bindings {
+class MessagePort;
+}  // namespace cast_api_bindings
+
+namespace cast_streaming {
+class ReceiverSession;
+}  // namespace cast_streaming
+
+namespace chromecast {
+
+class CastWebContents;
+
+// This class provides an implementation of StreamingControllerBase using the
+// remoting functionality provided in the cast_streaming component.
+class StreamingControllerRemoting : public StreamingControllerBase {
+ public:
+  StreamingControllerRemoting(
+      std::unique_ptr<cast_api_bindings::MessagePort> message_port,
+      CastWebContents* cast_web_contents);
+  ~StreamingControllerRemoting() override;
+
+ private:
+  // StreamingControllerBase overrides:
+  void StartPlayback(
+      cast_streaming::ReceiverSession* receiver_session,
+      mojo::AssociatedRemote<cast_streaming::mojom::CastStreamingReceiver>
+          cast_streaming_receiver,
+      mojo::AssociatedRemote<cast_streaming::mojom::RendererController>
+          renderer_connection) override;
+  void ProcessAVConstraints(
+      cast_streaming::ReceiverSession::AVConstraints* constraints) override;
+};
+
+}  // namespace chromecast
+
+#endif  // CHROMECAST_CAST_CORE_RUNTIME_BROWSER_STREAMING_CONTROLLER_REMOTING_H_
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 812e92da..dab8f6d5 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -926,6 +926,7 @@
 
     deps = [
       "//base",
+      "//components/bookmarks/test",
       "//components/discardable_memory/common",
       "//components/history/core/test",
       "//components/leveldb_proto",
diff --git a/components/autofill/core/browser/payments/virtual_card_enrollment_manager.cc b/components/autofill/core/browser/payments/virtual_card_enrollment_manager.cc
index 0ba28db..6b801fa 100644
--- a/components/autofill/core/browser/payments/virtual_card_enrollment_manager.cc
+++ b/components/autofill/core/browser/payments/virtual_card_enrollment_manager.cc
@@ -291,6 +291,8 @@
 #if !BUILDFLAG(IS_ANDROID)
   if (base::FeatureList::IsEnabled(
           features::kAutofillEnableToolbarStatusChip) &&
+      base::FeatureList::IsEnabled(
+          features::kAutofillCreditCardUploadFeedback) &&
       state_.virtual_card_enrollment_fields.virtual_card_enrollment_source ==
           VirtualCardEnrollmentSource::kUpstream &&
       !avatar_animation_complete_) {
diff --git a/components/autofill/core/browser/payments/virtual_card_enrollment_manager_unittest.cc b/components/autofill/core/browser/payments/virtual_card_enrollment_manager_unittest.cc
index eb583edc..660fed5 100644
--- a/components/autofill/core/browser/payments/virtual_card_enrollment_manager_unittest.cc
+++ b/components/autofill/core/browser/payments/virtual_card_enrollment_manager_unittest.cc
@@ -468,7 +468,9 @@
 
 TEST_F(VirtualCardEnrollmentManagerTest, UpstreamAnimationSync_ResponseFirst) {
   base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(features::kAutofillEnableToolbarStatusChip);
+  feature_list.InitWithFeatures({features::kAutofillEnableToolbarStatusChip,
+                                 features::kAutofillCreditCardUploadFeedback},
+                                {});
   personal_data_manager_->ClearCreditCardArtImages();
   SetUpCard();
   SetValidCardArtImageForCard(*card_);
diff --git a/components/cast_streaming/browser/BUILD.gn b/components/cast_streaming/browser/BUILD.gn
index f8512cdb..356a6c1b 100644
--- a/components/cast_streaming/browser/BUILD.gn
+++ b/components/cast_streaming/browser/BUILD.gn
@@ -67,9 +67,11 @@
   deps = [
     ":core",
     ":receiver_session_public",
+    ":renderer_controls",
     "//base",
     "//components/cast_streaming/public",
     "//components/cast_streaming/public:config_conversions",
+    "//components/cast_streaming/public/mojom",
     "//components/openscreen_platform",
     "//media",
     "//media/mojo/common",
@@ -84,6 +86,8 @@
   sources = [
     "cast_streaming_session.cc",
     "cast_streaming_session.h",
+    "renderer_controller_config.cc",
+    "renderer_controller_config.h",
     "stream_consumer.cc",
     "stream_consumer.h",
   ]
@@ -115,6 +119,8 @@
     "playback_command_dispatcher.cc",
     "playback_command_dispatcher.h",
     "remoting_session_client.h",
+    "renderer_control_multiplexer.cc",
+    "renderer_control_multiplexer.h",
     "rpc_call_translator.cc",
     "rpc_call_translator.h",
   ]
diff --git a/components/cast_streaming/browser/cast_streaming_session.cc b/components/cast_streaming/browser/cast_streaming_session.cc
index b20573a..68ce668 100644
--- a/components/cast_streaming/browser/cast_streaming_session.cc
+++ b/components/cast_streaming/browser/cast_streaming_session.cc
@@ -38,6 +38,7 @@
 
 CastStreamingSession::ReceiverSessionClient::ReceiverSessionClient(
     CastStreamingSession::Client* client,
+    absl::optional<RendererControllerConfig> renderer_controls,
     std::unique_ptr<ReceiverSession::AVConstraints> av_constraints,
     std::unique_ptr<cast_api_bindings::MessagePort> message_port,
     scoped_refptr<base::SequencedTaskRunner> task_runner)
@@ -56,6 +57,14 @@
       this, &environment_, &cast_message_port_impl_,
       std::move(*av_constraints));
 
+  if (renderer_controls) {
+    playback_command_dispatcher_ = std::make_unique<PlaybackCommandDispatcher>(
+        task_runner,
+        std::move(renderer_controls.value().control_configuration));
+    playback_command_dispatcher_->RegisterCommandSource(
+        std::move(renderer_controls.value().external_renderer_controls));
+  }
+
   init_timeout_timer_.Start(
       FROM_HERE, kInitTimeout,
       base::BindOnce(
@@ -213,12 +222,24 @@
   }
 }
 
+void CastStreamingSession::ReceiverSessionClient::OnRemotingNegotiated(
+    const openscreen::cast::ReceiverSession* session,
+    openscreen::cast::ReceiverSession::RemotingNegotiation negotiation) {
+  DCHECK(playback_command_dispatcher_);
+  OnNegotiated(session, std::move(negotiation.receivers));
+  playback_command_dispatcher_->OnRemotingSessionNegotiated(
+      negotiation.messenger);
+}
+
 void CastStreamingSession::ReceiverSessionClient::OnReceiversDestroying(
     const openscreen::cast::ReceiverSession* session,
     ReceiversDestroyingReason reason) {
   // This can be called when |receiver_session_| is being destroyed, so we
   // do not sanity-check |session| here.
   DVLOG(1) << __func__;
+  if (playback_command_dispatcher_) {
+    playback_command_dispatcher_->OnRemotingSessionEnded();
+  }
 
   switch (reason) {
     case ReceiversDestroyingReason::kEndOfSession:
@@ -258,6 +279,7 @@
 
 void CastStreamingSession::Start(
     Client* client,
+    absl::optional<RendererControllerConfig> renderer_controls,
     std::unique_ptr<ReceiverSession::AVConstraints> av_constraints,
     std::unique_ptr<cast_api_bindings::MessagePort> message_port,
     scoped_refptr<base::SequencedTaskRunner> task_runner) {
@@ -265,7 +287,8 @@
   DCHECK(client);
   DCHECK(!receiver_session_);
   receiver_session_ = std::make_unique<ReceiverSessionClient>(
-      client, std::move(av_constraints), std::move(message_port), task_runner);
+      client, std::move(renderer_controls), std::move(av_constraints),
+      std::move(message_port), task_runner);
 }
 
 void CastStreamingSession::Stop() {
diff --git a/components/cast_streaming/browser/cast_streaming_session.h b/components/cast_streaming/browser/cast_streaming_session.h
index c8ca811e..7190f35 100644
--- a/components/cast_streaming/browser/cast_streaming_session.h
+++ b/components/cast_streaming/browser/cast_streaming_session.h
@@ -13,7 +13,9 @@
 #include "base/timer/timer.h"
 #include "components/cast/message_port/message_port.h"
 #include "components/cast_streaming/browser/cast_message_port_impl.h"
+#include "components/cast_streaming/browser/playback_command_dispatcher.h"
 #include "components/cast_streaming/browser/public/receiver_session.h"
+#include "components/cast_streaming/browser/renderer_controller_config.h"
 #include "components/openscreen_platform/network_util.h"
 #include "components/openscreen_platform/task_runner.h"
 #include "media/base/audio_decoder_config.h"
@@ -91,6 +93,7 @@
   // |av_constraints| specifies the supported media codecs and limitations
   // surrounding this support.
   void Start(Client* client,
+             absl::optional<RendererControllerConfig> renderer_controls,
              std::unique_ptr<ReceiverSession::AVConstraints> av_constraints,
              std::unique_ptr<cast_api_bindings::MessagePort> message_port,
              scoped_refptr<base::SequencedTaskRunner> task_runner);
@@ -107,6 +110,7 @@
    public:
     ReceiverSessionClient(
         CastStreamingSession::Client* client,
+        absl::optional<RendererControllerConfig> renderer_controls,
         std::unique_ptr<ReceiverSession::AVConstraints> av_constraints,
         std::unique_ptr<cast_api_bindings::MessagePort> message_port,
         scoped_refptr<base::SequencedTaskRunner> task_runner);
@@ -134,6 +138,10 @@
     void OnNegotiated(const openscreen::cast::ReceiverSession* session,
                       openscreen::cast::ReceiverSession::ConfiguredReceivers
                           receivers) override;
+    void OnRemotingNegotiated(
+        const openscreen::cast::ReceiverSession* session,
+        openscreen::cast::ReceiverSession::RemotingNegotiation negotiation)
+        override;
     void OnReceiversDestroying(const openscreen::cast::ReceiverSession* session,
                                ReceiversDestroyingReason reason) override;
     void OnError(const openscreen::cast::ReceiverSession* session,
@@ -148,6 +156,9 @@
     std::unique_ptr<openscreen::cast::ReceiverSession> receiver_session_;
     base::OneShotTimer init_timeout_timer_;
 
+    // Handles remoting messages.
+    std::unique_ptr<PlaybackCommandDispatcher> playback_command_dispatcher_;
+
     // Timer to trigger connection closure if no data is received for 15
     // seconds.
     base::OneShotTimer data_timeout_timer_;
diff --git a/components/cast_streaming/browser/playback_command_dispatcher.cc b/components/cast_streaming/browser/playback_command_dispatcher.cc
index f35c021..3aee33a 100644
--- a/components/cast_streaming/browser/playback_command_dispatcher.cc
+++ b/components/cast_streaming/browser/playback_command_dispatcher.cc
@@ -17,17 +17,30 @@
     scoped_refptr<base::SequencedTaskRunner> task_runner,
     mojo::AssociatedRemote<mojom::RendererController> control_configuration)
     : task_runner_(std::move(task_runner)), weak_factory_(this) {
+  // Create a muxer using the "real" media::mojom::Renderer instance that
+  // connects to the remote media::Renderer.
   mojo::Remote<media::mojom::Renderer> renderer;
   control_configuration->SetPlaybackController(
       renderer.BindNewPipeAndPassReceiver());
-  call_translator_ =
-      std::make_unique<remoting::RpcCallTranslator>(std::move(renderer));
+  muxer_ = std::make_unique<RendererControlMultiplexer>(std::move(renderer));
+
+  // Create a "fake" media::mojom::Renderer so that the RpcCallTranslator can
+  // pass commands to the |muxer_|.
+  mojo::Remote<media::mojom::Renderer> translators_renderer;
+  RegisterCommandSource(translators_renderer.BindNewPipeAndPassReceiver());
+  call_translator_ = std::make_unique<remoting::RpcCallTranslator>(
+      std::move(translators_renderer));
 }
 
 PlaybackCommandDispatcher::~PlaybackCommandDispatcher() {
   OnRemotingSessionEnded();
 }
 
+void PlaybackCommandDispatcher::RegisterCommandSource(
+    mojo::PendingReceiver<media::mojom::Renderer> controls) {
+  muxer_->RegisterController(std::move(controls));
+}
+
 void PlaybackCommandDispatcher::OnRemotingSessionNegotiated(
     openscreen::cast::RpcMessenger* messenger) {
   DCHECK(messenger);
diff --git a/components/cast_streaming/browser/playback_command_dispatcher.h b/components/cast_streaming/browser/playback_command_dispatcher.h
index a7430da..84c7e43c 100644
--- a/components/cast_streaming/browser/playback_command_dispatcher.h
+++ b/components/cast_streaming/browser/playback_command_dispatcher.h
@@ -11,7 +11,9 @@
 #include "base/memory/weak_ptr.h"
 #include "base/task/sequenced_task_runner.h"
 #include "components/cast_streaming/browser/remoting_session_client.h"
+#include "components/cast_streaming/browser/renderer_control_multiplexer.h"
 #include "components/cast_streaming/public/mojom/renderer_controller.mojom.h"
+#include "media/mojo/mojom/renderer.mojom.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
 #include "third_party/openscreen/src/cast/streaming/rpc_messenger.h"
 
@@ -41,12 +43,15 @@
       mojo::AssociatedRemote<mojom::RendererController> control_configuration);
   ~PlaybackCommandDispatcher() override;
 
- private:
+  void RegisterCommandSource(
+      mojo::PendingReceiver<media::mojom::Renderer> controls);
+
   // remoting::RemotingSessionClient overrides.
   void OnRemotingSessionNegotiated(
       openscreen::cast::RpcMessenger* messenger) override;
   void OnRemotingSessionEnded() override;
 
+ private:
   void SendRemotingRpcMessageToRemote(
       openscreen::cast::RpcMessenger::Handle handle,
       std::unique_ptr<openscreen::cast::RpcMessage> message);
@@ -56,7 +61,13 @@
   openscreen::cast::RpcMessenger* messenger_;
   openscreen::cast::RpcMessenger::Handle handle_;
 
+  // Multiplexes Renderer commands from a number of senders.
+  std::unique_ptr<RendererControlMultiplexer> muxer_;
+
+  // Handles translating between Remoting commands (in proto form) and mojo
+  // commands.
   std::unique_ptr<remoting::RpcCallTranslator> call_translator_;
+
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
   base::WeakPtrFactory<PlaybackCommandDispatcher> weak_factory_;
 };
diff --git a/components/cast_streaming/browser/public/receiver_session.h b/components/cast_streaming/browser/public/receiver_session.h
index bda57c97..4b03a3bd7 100644
--- a/components/cast_streaming/browser/public/receiver_session.h
+++ b/components/cast_streaming/browser/public/receiver_session.h
@@ -8,7 +8,9 @@
 #include <memory>
 
 #include "base/callback.h"
+#include "base/time/time.h"
 #include "components/cast_streaming/public/mojom/cast_streaming_session.mojom.h"
+#include "components/cast_streaming/public/mojom/renderer_controller.mojom.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
 #include "third_party/openscreen/src/cast/streaming/receiver_session.h"
 
@@ -43,6 +45,27 @@
         const media::VideoDecoderConfig& video_config) = 0;
   };
 
+  // Provides controls for a media::Renderer instance. Methods are a subset of
+  // those provided by a media::Renderer.
+  class RendererController {
+   public:
+    virtual ~RendererController() = default;
+
+    // Returns true if calls may be made to this object.
+    virtual bool IsValid() const = 0;
+
+    // Starts rendering from |time|. May only be called if this object is valid.
+    virtual void StartPlayingFrom(base::TimeDelta time) = 0;
+
+    // Updates the current playback rate. The default playback rate should be 0.
+    // May only be called if this object is valid.
+    virtual void SetPlaybackRate(double playback_rate) = 0;
+
+    // Sets the output volume. The default volume should be 1. May only be
+    // called if this object is valid.
+    virtual void SetVolume(float volume) = 0;
+  };
+
   using MessagePortProvider =
       base::OnceCallback<std::unique_ptr<cast_api_bindings::MessagePort>()>;
   using AVConstraints = openscreen::cast::ReceiverSession::Preferences;
@@ -61,13 +84,29 @@
       MessagePortProvider message_port_provider,
       Client* client = nullptr);
 
-  // Sets up the CastStreamingReceiver mojo remote. This will immediately call
-  // CastStreamingReceiver::EnableReceiver(). Upon receiving the callback for
-  // this method, the Cast Streaming Receiver Session will be started and audio
+  // Schedules a call to begin streaming, following initial internal
+  // initialization of the component. Following this initialization, audio
   // and/or video frames will be sent over a Mojo channel.
-  virtual void SetCastStreamingReceiver(
+  // NOTE: Depending on the media::Renderer currently being used for media
+  // playback, additional steps may be required to begin playback. If the
+  // |PlaybackCommandForwardingRenderer| is being used, the below overload is
+  // recommended instead.
+  virtual void StartStreamingAsync(
       mojo::AssociatedRemote<mojom::CastStreamingReceiver>
           cast_streaming_receiver) = 0;
+
+  // As above, but also sets the |renderer_controller| to be used to control a
+  // renderer-process |PlaybackCommandForwardingRenderer|. This control may then
+  // be done through the RenderControls returned by GetRendererControls() below.
+  virtual void StartStreamingAsync(
+      mojo::AssociatedRemote<mojom::CastStreamingReceiver>
+          cast_streaming_receiver,
+      mojo::AssociatedRemote<mojom::RendererController>
+          renderer_controller) = 0;
+
+  // Returns a RendererController through which commands may be injected into
+  // the renderer-process PlaybackCommandForwardingRenderer.
+  virtual RendererController* GetRendererControls() = 0;
 };
 
 }  // namespace cast_streaming
diff --git a/components/cast_streaming/browser/receiver_session_impl.cc b/components/cast_streaming/browser/receiver_session_impl.cc
index bc7f61a..837cda47 100644
--- a/components/cast_streaming/browser/receiver_session_impl.cc
+++ b/components/cast_streaming/browser/receiver_session_impl.cc
@@ -8,7 +8,6 @@
 #include "components/cast_streaming/browser/public/network_context_getter.h"
 #include "media/base/audio_decoder_config.h"
 #include "media/base/video_decoder_config.h"
-#include "media/mojo/mojom/media_types.mojom.h"
 
 namespace cast_streaming {
 
@@ -35,7 +34,7 @@
 
 ReceiverSessionImpl::~ReceiverSessionImpl() = default;
 
-void ReceiverSessionImpl::SetCastStreamingReceiver(
+void ReceiverSessionImpl::StartStreamingAsync(
     mojo::AssociatedRemote<mojom::CastStreamingReceiver>
         cast_streaming_receiver) {
   DCHECK(HasNetworkContextGetter());
@@ -52,10 +51,29 @@
       &ReceiverSessionImpl::OnMojoDisconnect, base::Unretained(this)));
 }
 
+void ReceiverSessionImpl::StartStreamingAsync(
+    mojo::AssociatedRemote<mojom::CastStreamingReceiver>
+        cast_streaming_receiver,
+    mojo::AssociatedRemote<mojom::RendererController> renderer_controller) {
+  DCHECK(!renderer_control_config_);
+  external_renderer_controls_ = std::make_unique<RendererControllerImpl>();
+  renderer_control_config_.emplace(std::move(renderer_controller),
+                                   external_renderer_controls_->Bind());
+
+  StartStreamingAsync(std::move(cast_streaming_receiver));
+}
+
+ReceiverSession::RendererController*
+ReceiverSessionImpl::GetRendererControls() {
+  DCHECK(external_renderer_controls_);
+  return external_renderer_controls_.get();
+}
+
 void ReceiverSessionImpl::OnReceiverEnabled() {
   DVLOG(1) << __func__;
   DCHECK(message_port_provider_);
-  cast_streaming_session_.Start(this, std::move(av_constraints_),
+  cast_streaming_session_.Start(this, std::move(renderer_control_config_),
+                                std::move(av_constraints_),
                                 std::move(message_port_provider_).Run(),
                                 base::SequencedTaskRunnerHandle::Get());
 }
@@ -171,4 +189,34 @@
   video_remote_.reset();
 }
 
+ReceiverSessionImpl::RendererControllerImpl::RendererControllerImpl() = default;
+ReceiverSessionImpl::RendererControllerImpl::~RendererControllerImpl() =
+    default;
+
+bool ReceiverSessionImpl::RendererControllerImpl::IsValid() const {
+  return renderer_controls_.is_bound() && renderer_controls_.is_connected();
+}
+
+void ReceiverSessionImpl::RendererControllerImpl::StartPlayingFrom(
+    base::TimeDelta time) {
+  DCHECK(IsValid());
+  renderer_controls_->StartPlayingFrom(time);
+}
+
+void ReceiverSessionImpl::RendererControllerImpl::SetPlaybackRate(
+    double playback_rate) {
+  DCHECK(IsValid());
+  renderer_controls_->SetPlaybackRate(playback_rate);
+}
+
+void ReceiverSessionImpl::RendererControllerImpl::SetVolume(float volume) {
+  DCHECK(IsValid());
+  renderer_controls_->SetVolume(volume);
+}
+
+mojo::PendingReceiver<media::mojom::Renderer>
+ReceiverSessionImpl::RendererControllerImpl::Bind() {
+  return renderer_controls_.BindNewPipeAndPassReceiver();
+}
+
 }  // namespace cast_streaming
diff --git a/components/cast_streaming/browser/receiver_session_impl.h b/components/cast_streaming/browser/receiver_session_impl.h
index 76b5682..dba6d1fc7 100644
--- a/components/cast_streaming/browser/receiver_session_impl.h
+++ b/components/cast_streaming/browser/receiver_session_impl.h
@@ -8,6 +8,8 @@
 #include "components/cast_streaming/browser/cast_streaming_session.h"
 #include "components/cast_streaming/browser/public/receiver_session.h"
 #include "components/cast_streaming/public/mojom/cast_streaming_session.mojom.h"
+#include "components/cast_streaming/public/mojom/renderer_controller.mojom.h"
+#include "media/mojo/mojom/media_types.mojom.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -32,11 +34,32 @@
   ReceiverSessionImpl& operator=(const ReceiverSessionImpl&) = delete;
 
   // ReceiverSession implementation.
-  void SetCastStreamingReceiver(
-      mojo::AssociatedRemote<mojom::CastStreamingReceiver>
-          cast_streaming_receiver) override;
+  void StartStreamingAsync(mojo::AssociatedRemote<mojom::CastStreamingReceiver>
+                               cast_streaming_receiver) override;
+  void StartStreamingAsync(mojo::AssociatedRemote<mojom::CastStreamingReceiver>
+                               cast_streaming_receiver,
+                           mojo::AssociatedRemote<mojom::RendererController>
+                               renderer_controller) override;
+  RendererController* GetRendererControls() override;
 
  private:
+  class RendererControllerImpl : public ReceiverSession::RendererController {
+   public:
+    RendererControllerImpl();
+    ~RendererControllerImpl() override;
+
+    mojo::PendingReceiver<media::mojom::Renderer> Bind();
+
+    // ReceiverSession::RendererController overrides.
+    bool IsValid() const override;
+    void StartPlayingFrom(base::TimeDelta time) override;
+    void SetPlaybackRate(double playback_rate) override;
+    void SetVolume(float volume) override;
+
+   private:
+    mojo::Remote<media::mojom::Renderer> renderer_controls_;
+  };
+
   // Handler for |cast_streaming_receiver_| disconnect.
   void OnMojoDisconnect();
 
@@ -70,6 +93,8 @@
   mojo::Remote<mojom::CastStreamingBufferReceiver> video_remote_;
 
   ReceiverSession::Client* const client_;
+  std::unique_ptr<RendererControllerImpl> external_renderer_controls_;
+  absl::optional<RendererControllerConfig> renderer_control_config_;
 };
 
 }  // namespace cast_streaming
diff --git a/components/cast_streaming/browser/renderer_control_multiplexer.cc b/components/cast_streaming/browser/renderer_control_multiplexer.cc
new file mode 100644
index 0000000..af4d7eb
--- /dev/null
+++ b/components/cast_streaming/browser/renderer_control_multiplexer.cc
@@ -0,0 +1,58 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/cast_streaming/browser/renderer_control_multiplexer.h"
+
+namespace cast_streaming {
+
+RendererControlMultiplexer::RendererControlMultiplexer(
+    mojo::Remote<media::mojom::Renderer> renderer_remote)
+    : renderer_remote_(std::move(renderer_remote)) {}
+
+RendererControlMultiplexer::~RendererControlMultiplexer() = default;
+
+void RendererControlMultiplexer::RegisterController(
+    mojo::PendingReceiver<media::mojom::Renderer> controls) {
+  DCHECK(controls);
+  auto bound_controls =
+      std::make_unique<mojo::Receiver<media::mojom::Renderer>>(
+          this, std::move(controls));
+  receiver_list_.push_back(std::move(bound_controls));
+}
+
+void RendererControlMultiplexer::StartPlayingFrom(::base::TimeDelta time) {
+  renderer_remote_->StartPlayingFrom(time);
+}
+
+void RendererControlMultiplexer::SetPlaybackRate(double playback_rate) {
+  renderer_remote_->SetPlaybackRate(playback_rate);
+}
+
+void RendererControlMultiplexer::SetVolume(float volume) {
+  renderer_remote_->SetVolume(volume);
+}
+
+void RendererControlMultiplexer::SetCdm(
+    const absl::optional<::base::UnguessableToken>& cdm_id,
+    SetCdmCallback callback) {
+  renderer_remote_->SetCdm(cdm_id, std::move(callback));
+}
+
+void RendererControlMultiplexer::Initialize(
+    mojo::PendingAssociatedRemote<media::mojom::RendererClient> client,
+    absl::optional<
+        std::vector<::mojo::PendingRemote<::media::mojom::DemuxerStream>>>
+        streams,
+    media::mojom::MediaUrlParamsPtr media_url_params,
+    InitializeCallback callback) {
+  renderer_remote_->Initialize(std::move(client), std::move(streams),
+                               std::move(media_url_params),
+                               std::move(callback));
+}
+
+void RendererControlMultiplexer::Flush(FlushCallback callback) {
+  renderer_remote_->Flush(std::move(callback));
+}
+
+}  // namespace cast_streaming
diff --git a/components/cast_streaming/browser/renderer_control_multiplexer.h b/components/cast_streaming/browser/renderer_control_multiplexer.h
new file mode 100644
index 0000000..1fc6902
--- /dev/null
+++ b/components/cast_streaming/browser/renderer_control_multiplexer.h
@@ -0,0 +1,59 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CAST_STREAMING_BROWSER_RENDERER_CONTROL_MULTIPLEXER_H_
+#define COMPONENTS_CAST_STREAMING_BROWSER_RENDERER_CONTROL_MULTIPLEXER_H_
+
+#include <memory>
+#include <vector>
+
+#include "media/mojo/mojom/renderer.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+namespace cast_streaming {
+
+// This class is responsible for multiplexing a number of media::mojo::Renderer
+// callers by forwarding all such calls across a single mojo pipe.
+class RendererControlMultiplexer : public media::mojom::Renderer {
+ public:
+  explicit RendererControlMultiplexer(
+      mojo::Remote<media::mojom::Renderer> renderer_remote);
+  ~RendererControlMultiplexer() override;
+
+  // Adds a new mojo pipe for which calls should be forwarded to
+  // |renderer_remote_|.
+  void RegisterController(
+      mojo::PendingReceiver<media::mojom::Renderer> controls);
+
+  // media::mojo::Renderer overrides.
+  //
+  // These calls only function to forward calls to |renderer_remote_|. Note that
+  // mojo::FusePipes() cannot be used instead because we must retain the
+  // |renderer_remote_| instance to make calls from here.
+  void StartPlayingFrom(::base::TimeDelta time) override;
+  void SetPlaybackRate(double playback_rate) override;
+  void SetVolume(float volume) override;
+  void SetCdm(const absl::optional<::base::UnguessableToken>& cdm_id,
+              SetCdmCallback callback) override;
+  void Initialize(
+      mojo::PendingAssociatedRemote<media::mojom::RendererClient> client,
+      absl::optional<
+          std::vector<::mojo::PendingRemote<::media::mojom::DemuxerStream>>>
+          streams,
+      media::mojom::MediaUrlParamsPtr media_url_params,
+      InitializeCallback callback) override;
+  void Flush(FlushCallback callback) override;
+
+ private:
+  mojo::Remote<media::mojom::Renderer> renderer_remote_;
+
+  std::vector<std::unique_ptr<mojo::Receiver<media::mojom::Renderer>>>
+      receiver_list_;
+};
+
+}  // namespace cast_streaming
+
+#endif  // COMPONENTS_CAST_STREAMING_BROWSER_RENDERER_CONTROL_MULTIPLEXER_H_
diff --git a/components/cast_streaming/browser/renderer_controller_config.cc b/components/cast_streaming/browser/renderer_controller_config.cc
new file mode 100644
index 0000000..56f8da3
--- /dev/null
+++ b/components/cast_streaming/browser/renderer_controller_config.cc
@@ -0,0 +1,25 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/cast_streaming/browser/renderer_controller_config.h"
+
+namespace cast_streaming {
+
+RendererControllerConfig::RendererControllerConfig() = default;
+
+RendererControllerConfig::RendererControllerConfig(
+    mojo::AssociatedRemote<mojom::RendererController> control_config,
+    mojo::PendingReceiver<media::mojom::Renderer> external_renderer_control)
+    : control_configuration(std::move(control_config)),
+      external_renderer_controls(std::move(external_renderer_control)) {}
+
+RendererControllerConfig::RendererControllerConfig(
+    RendererControllerConfig&& other) = default;
+
+RendererControllerConfig::~RendererControllerConfig() = default;
+
+RendererControllerConfig& RendererControllerConfig::operator=(
+    RendererControllerConfig&& other) = default;
+
+}  // namespace cast_streaming
diff --git a/components/cast_streaming/browser/renderer_controller_config.h b/components/cast_streaming/browser/renderer_controller_config.h
new file mode 100644
index 0000000..caffda2
--- /dev/null
+++ b/components/cast_streaming/browser/renderer_controller_config.h
@@ -0,0 +1,37 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CAST_STREAMING_BROWSER_RENDERER_CONTROLLER_CONFIG_H_
+#define COMPONENTS_CAST_STREAMING_BROWSER_RENDERER_CONTROLLER_CONFIG_H_
+
+#include "components/cast_streaming/public/mojom/renderer_controller.mojom.h"
+#include "media/mojo/mojom/renderer.mojom.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+
+namespace cast_streaming {
+
+struct RendererControllerConfig {
+  RendererControllerConfig();
+  RendererControllerConfig(
+      mojo::AssociatedRemote<mojom::RendererController> control_config,
+      mojo::PendingReceiver<media::mojom::Renderer> external_renderer_control);
+  RendererControllerConfig(RendererControllerConfig&& other);
+
+  ~RendererControllerConfig();
+
+  RendererControllerConfig& operator=(RendererControllerConfig&& other);
+
+  // Mojo pipe required to set up a connection between the browser process
+  // controls and the renderer-process PlaybackCommandForwardingRenderer.
+  mojo::AssociatedRemote<mojom::RendererController> control_configuration;
+
+  // Provides an external channel by which the underlying Renderer may be
+  // controlled outside of those used during a Remoting session.
+  mojo::PendingReceiver<media::mojom::Renderer> external_renderer_controls;
+};
+
+}  // namespace cast_streaming
+
+#endif  // COMPONENTS_CAST_STREAMING_BROWSER_RENDERER_CONTROLLER_CONFIG_H_
diff --git a/components/cast_streaming/browser/test/cast_streaming_test_receiver.cc b/components/cast_streaming/browser/test/cast_streaming_test_receiver.cc
index 3282e88..0036674 100644
--- a/components/cast_streaming/browser/test/cast_streaming_test_receiver.cc
+++ b/components/cast_streaming/browser/test/cast_streaming_test_receiver.cc
@@ -23,7 +23,7 @@
                                      media::VideoCodec::kVP8),
           ToAudioCaptureConfigCodecs(media::AudioCodec::kAAC,
                                      media::AudioCodec::kOpus));
-  receiver_session_.Start(this, std::move(stream_config),
+  receiver_session_.Start(this, absl::nullopt, std::move(stream_config),
                           std::move(message_port),
                           base::SequencedTaskRunnerHandle::Get());
 }
diff --git a/components/cast_streaming/public/BUILD.gn b/components/cast_streaming/public/BUILD.gn
index 95602d8c..7f87e9a 100644
--- a/components/cast_streaming/public/BUILD.gn
+++ b/components/cast_streaming/public/BUILD.gn
@@ -46,10 +46,7 @@
   public_configs =
       [ "//third_party/openscreen/src/build:openscreen_include_dirs" ]
 
-  deps = [
-    "//components/openscreen_platform:openscreen_platform",
-    "//components/openscreen_platform:openscreen_platform_network_service",
-  ]
+  deps = [ "//components/openscreen_platform:openscreen_platform" ]
 
   public_deps = [
     "//base",
@@ -66,6 +63,7 @@
     ":public",
     ":remoting_utils",
     "//base/test:test_support",
+    "//components/openscreen_platform:openscreen_platform_network_service",
     "//media:test_support",
     "//media/mojo:test_support",
     "//testing/gmock",
diff --git a/components/encrypted_messages/OWNERS b/components/encrypted_messages/OWNERS
index fb3da75..abc6202b 100644
--- a/components/encrypted_messages/OWNERS
+++ b/components/encrypted_messages/OWNERS
@@ -1,2 +1 @@
 estark@chromium.org
-rsleevi@chromium.org
diff --git a/components/error_page/common/localized_error.cc b/components/error_page/common/localized_error.cc
index e62128d..e54f585b 100644
--- a/components/error_page/common/localized_error.cc
+++ b/components/error_page/common/localized_error.cc
@@ -912,7 +912,7 @@
         l10n_util::GetStringUTF16(IDS_ERRORPAGE_DINO_GAME_DESCRIPTION));
 
     if (EnableAltGameMode()) {
-      result.strings.SetBoolean("enableAltGameMode", true);
+      result.strings.SetBoolKey("enableAltGameMode", true);
       // We don't know yet which scale the page will use, so both 1x and 2x
       // should be loaded.
       result.strings.SetStringPath(
diff --git a/components/exo/wayland/clients/client_base.cc b/components/exo/wayland/clients/client_base.cc
index 2653845..ab18a91 100644
--- a/components/exo/wayland/clients/client_base.cc
+++ b/components/exo/wayland/clients/client_base.cc
@@ -553,7 +553,7 @@
     ui::OzonePlatform::InitParams ozone_params;
     ozone_params.single_process = true;
     ui::OzonePlatform::InitializeForGPU(ozone_params);
-    bool gl_initialized = gl::init::InitializeGLOneOff();
+    bool gl_initialized = gl::init::InitializeGLOneOff(/*system_device_id=*/0);
     DCHECK(gl_initialized);
     gl_surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
     gl_context_ =
diff --git a/components/history/core/browser/history_service.h b/components/history/core/browser/history_service.h
index 38e84dd3..e774ac3 100644
--- a/components/history/core/browser/history_service.h
+++ b/components/history/core/browser/history_service.h
@@ -412,7 +412,7 @@
 
   // Delete all the information related to a list of urls.  (Deleting
   // URLs one by one is slow as it has to flush to disk each time.)
-  void DeleteURLs(const std::vector<GURL>& urls);
+  virtual void DeleteURLs(const std::vector<GURL>& urls);
 
   // Removes all visits in the selected time range (including the
   // start time), updating the URLs accordingly. This deletes any
diff --git a/components/history_clusters/core/config.cc b/components/history_clusters/core/config.cc
index a37cfc1..49b48e39 100644
--- a/components/history_clusters/core/config.cc
+++ b/components/history_clusters/core/config.cc
@@ -17,6 +17,15 @@
 
 namespace history_clusters {
 
+namespace {
+
+Config& GetConfigInternal() {
+  static base::NoDestructor<Config> s_config;
+  return *s_config;
+}
+
+}  // namespace
+
 Config::Config() {
   // Override any parameters that may be provided by Finch.
   is_journeys_enabled_no_locale_check =
@@ -201,7 +210,7 @@
 Config::~Config() = default;
 
 void SetConfigForTesting(const Config& config) {
-  const_cast<Config&>(GetConfig()) = config;
+  GetConfigInternal() = config;
 }
 
 bool IsApplicationLocaleSupportedByJourneys(
@@ -230,8 +239,7 @@
 }
 
 const Config& GetConfig() {
-  static base::NoDestructor<Config> s_config;
-  return *s_config;
+  return GetConfigInternal();
 }
 
 }  // namespace history_clusters
diff --git a/components/infobars/android/BUILD.gn b/components/infobars/android/BUILD.gn
index c110cd1..a4871503 100644
--- a/components/infobars/android/BUILD.gn
+++ b/components/infobars/android/BUILD.gn
@@ -18,6 +18,7 @@
     "res/drawable-xxxhdpi/infobar_shadow_top.png",
     "res/drawable/infobar_wrapper_bg.xml",
     "res/layout/infobar_control_icon_with_description.xml",
+    "res/layout/infobar_control_icon_with_title.xml",
     "res/layout/infobar_control_message.xml",
     "res/layout/infobar_control_spinner.xml",
     "res/layout/infobar_control_spinner_drop_down.xml",
diff --git a/components/infobars/android/OWNERS b/components/infobars/android/OWNERS
index 5521cea..e2f466a 100644
--- a/components/infobars/android/OWNERS
+++ b/components/infobars/android/OWNERS
@@ -1,5 +1,4 @@
 # Primary:
-pavely@chromium.org
 
 # Secondary:
 dtrainor@chromium.org
diff --git a/components/infobars/android/java/src/org/chromium/components/infobars/InfoBarControlLayout.java b/components/infobars/android/java/src/org/chromium/components/infobars/InfoBarControlLayout.java
index 109c014d..b9488a91 100644
--- a/components/infobars/android/java/src/org/chromium/components/infobars/InfoBarControlLayout.java
+++ b/components/infobars/android/java/src/org/chromium/components/infobars/InfoBarControlLayout.java
@@ -306,13 +306,13 @@
      */
     public View addIconTitle(int iconResourceId, CharSequence titleMessage) {
         LinearLayout layout = (LinearLayout) inflateLayout(
-                getContext(), R.layout.infobar_control_icon_with_description, this);
+                getContext(), R.layout.infobar_control_icon_with_title, this);
         addView(layout, new ControlLayoutParams());
 
-        ImageView iconView = (ImageView) layout.findViewById(R.id.control_icon);
+        ImageView iconView = (ImageView) layout.findViewById(R.id.control_title_icon);
         iconView.setImageResource(iconResourceId);
 
-        TextView titleView = (TextView) layout.findViewById(R.id.control_message);
+        TextView titleView = (TextView) layout.findViewById(R.id.control_title);
         titleView.setText(titleMessage);
         titleView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
                 getContext().getResources().getDimension(R.dimen.infobar_text_size));
diff --git a/components/infobars/android/res/layout/infobar_control_icon_with_title.xml b/components/infobars/android/res/layout/infobar_control_icon_with_title.xml
new file mode 100644
index 0000000..e32693d
--- /dev/null
+++ b/components/infobars/android/res/layout/infobar_control_icon_with_title.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="36dp"
+    android:gravity="center_vertical">
+
+    <ImageView
+        android:id="@+id/control_title_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="@dimen/dual_control_margin_between_items"
+        android:scaleType="centerInside"
+        tools:ignore="ContentDescription" />
+
+    <TextView
+        android:id="@+id/control_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textAppearance="@style/TextAppearance.TextLarge.Primary" />
+
+</LinearLayout>
diff --git a/components/keep_alive_registry/keep_alive_types.cc b/components/keep_alive_registry/keep_alive_types.cc
index 4b7b71c..5decae15 100644
--- a/components/keep_alive_registry/keep_alive_types.cc
+++ b/components/keep_alive_registry/keep_alive_types.cc
@@ -60,10 +60,8 @@
       return out << "PANEL";
     case KeepAliveOrigin::PANEL_VIEW:
       return out << "PANEL_VIEW";
-    case KeepAliveOrigin::PROFILE_HELPER:
-      return out << "PROFILE_HELPER";
-    case KeepAliveOrigin::PROFILE_LOADER:
-      return out << "PROFILE_LOADER";
+    case KeepAliveOrigin::PROFILE_MANAGER:
+      return out << "PROFILE_MANAGER";
     case KeepAliveOrigin::USER_MANAGER_VIEW:
       return out << "USER_MANAGER_VIEW";
     case KeepAliveOrigin::CREDENTIAL_PROVIDER_SIGNIN_DIALOG:
diff --git a/components/keep_alive_registry/keep_alive_types.h b/components/keep_alive_registry/keep_alive_types.h
index a867de71..88bf5f4 100644
--- a/components/keep_alive_registry/keep_alive_types.h
+++ b/components/keep_alive_registry/keep_alive_types.h
@@ -59,8 +59,7 @@
   CHROME_VIEWS_DELEGATE,
   PANEL,
   PANEL_VIEW,
-  PROFILE_HELPER,
-  PROFILE_LOADER,
+  PROFILE_MANAGER,
   USER_MANAGER_VIEW,
   CREDENTIAL_PROVIDER_SIGNIN_DIALOG,
   WEB_APP_INTENT_PICKER,
diff --git a/components/media_router/common/mojom/media_router_mojom_traits.h b/components/media_router/common/mojom/media_router_mojom_traits.h
index 5d25b436..256b8ac 100644
--- a/components/media_router/common/mojom/media_router_mojom_traits.h
+++ b/components/media_router/common/mojom/media_router_mojom_traits.h
@@ -11,6 +11,7 @@
 #include "components/media_router/common/issue.h"
 #include "components/media_router/common/mojom/media_router.mojom-shared.h"
 #include "components/media_router/common/route_request_result.h"
+#include "mojo/public/cpp/bindings/optional_as_pointer.h"
 #include "net/base/ip_endpoint.h"
 
 namespace mojo {
@@ -344,15 +345,15 @@
     return route.presentation_id();
   }
 
-  static absl::optional<std::string> media_source(
+  static mojo::OptionalAsPointer<const std::string> media_source(
       const media_router::MediaRoute& route) {
     // TODO(imcheng): If we ever convert from C++ to Mojo outside of unit tests,
     // it would be better to make the |media_source_| field on MediaRoute a
     // absl::optional<MediaSource::Id> instead so it can be returned directly
     // here.
-    return route.media_source().id().empty()
-               ? absl::optional<std::string>()
-               : absl::make_optional(route.media_source().id());
+    return mojo::MakeOptionalAsPointer(route.media_source().id().empty()
+                                           ? nullptr
+                                           : &route.media_source().id());
   }
 
   static const std::string& media_sink_id(
diff --git a/components/omnibox/browser/fake_autocomplete_provider_client.cc b/components/omnibox/browser/fake_autocomplete_provider_client.cc
index 2f4b982..245091a 100644
--- a/components/omnibox/browser/fake_autocomplete_provider_client.cc
+++ b/components/omnibox/browser/fake_autocomplete_provider_client.cc
@@ -21,47 +21,21 @@
 #include "components/search_engines/search_terms_data.h"
 #include "components/search_engines/template_url_service.h"
 
-FakeAutocompleteProviderClient::FakeAutocompleteProviderClient(
-    bool create_history_db) {
+FakeAutocompleteProviderClient::FakeAutocompleteProviderClient() {
   set_template_url_service(std::make_unique<TemplateURLService>(nullptr, 0));
 
-  bookmark_model_ = bookmarks::TestBookmarkClient::CreateModel();
-
-  CHECK(history_dir_.CreateUniqueTempDir());
-  history_service_ =
-      history::CreateHistoryService(history_dir_.GetPath(), create_history_db);
-
-  in_memory_url_index_ = std::make_unique<InMemoryURLIndex>(
-      bookmark_model_.get(), history_service_.get(), nullptr,
-      history_dir_.GetPath(), SchemeSet());
-  in_memory_url_index_->Init();
-
   pref_service_ = std::make_unique<TestingPrefServiceSimple>();
   local_state_ = std::make_unique<TestingPrefServiceSimple>();
-
-  shortcuts_backend_ = base::MakeRefCounted<ShortcutsBackend>(
-      GetTemplateURLService(), std::make_unique<SearchTermsData>(),
-      GetHistoryService(), base::FilePath(), true);
-  shortcuts_backend_->Init();
-
   tile_service_ = std::make_unique<query_tiles::FakeTileService>();
 }
 
 FakeAutocompleteProviderClient::~FakeAutocompleteProviderClient() {
   // The InMemoryURLIndex must be explicitly shut down or it will DCHECK() in
   // its destructor.
-  GetInMemoryURLIndex()->Shutdown();
-  set_in_memory_url_index(nullptr);
-  // Allow its final cache write to complete in the thread pool.
-  base::ThreadPoolInstance::Get()->FlushForTesting();
-
-  // Explicitly shut down the history service and wait for its backed to be
-  // destroyed to prevent resource leaks.
-  base::RunLoop run_loop;
-  auto* history_service = GetHistoryService();
-  history_service->SetOnBackendDestroyTask(run_loop.QuitClosure());
-  history_service->Shutdown();
-  run_loop.Run();
+  if (in_memory_url_index_)
+    in_memory_url_index_->Shutdown();
+  if (history_service_)
+    history_service_->Shutdown();
 }
 
 PrefService* FakeAutocompleteProviderClient::GetPrefs() const {
diff --git a/components/omnibox/browser/fake_autocomplete_provider_client.h b/components/omnibox/browser/fake_autocomplete_provider_client.h
index 072273c..68f4208e 100644
--- a/components/omnibox/browser/fake_autocomplete_provider_client.h
+++ b/components/omnibox/browser/fake_autocomplete_provider_client.h
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/files/scoped_temp_dir.h"
+#include "components/bookmarks/browser/bookmark_model.h"
 #include "components/omnibox/browser/fake_tab_matcher.h"
 #include "components/omnibox/browser/in_memory_url_index.h"
 #include "components/omnibox/browser/mock_autocomplete_provider_client.h"
@@ -36,7 +37,7 @@
 // task_environment_.RunUntilIdle().
 class FakeAutocompleteProviderClient : public MockAutocompleteProviderClient {
  public:
-  explicit FakeAutocompleteProviderClient(bool create_history_db = true);
+  FakeAutocompleteProviderClient();
   ~FakeAutocompleteProviderClient() override;
   FakeAutocompleteProviderClient(const FakeAutocompleteProviderClient&) =
       delete;
@@ -61,6 +62,14 @@
   ntp_tiles::MostVisitedSites* GetNtpMostVisitedSites() override;
 
   // Test-only setters
+  void set_bookmark_model(std::unique_ptr<bookmarks::BookmarkModel> model) {
+    bookmark_model_ = std::move(model);
+  }
+
+  void set_history_service(std::unique_ptr<history::HistoryService> service) {
+    history_service_ = std::move(service);
+  }
+
   void set_in_memory_url_index(std::unique_ptr<InMemoryURLIndex> index) {
     in_memory_url_index_ = std::move(index);
   }
@@ -73,6 +82,10 @@
     ntp_most_visited_sites_ = ntp_mv_sites;
   }
 
+  void set_shortcuts_backend(scoped_refptr<ShortcutsBackend> backend) {
+    shortcuts_backend_ = std::move(backend);
+  }
+
  private:
   base::ScopedTempDir history_dir_;
   std::unique_ptr<bookmarks::BookmarkModel> bookmark_model_;
diff --git a/components/omnibox/browser/history_provider_unittest.cc b/components/omnibox/browser/history_provider_unittest.cc
index 139e91f..7258de7 100644
--- a/components/omnibox/browser/history_provider_unittest.cc
+++ b/components/omnibox/browser/history_provider_unittest.cc
@@ -6,6 +6,9 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/task_environment.h"
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/bookmarks/test/test_bookmark_client.h"
+#include "components/history/core/test/history_service_test_util.h"
 #include "components/omnibox/browser/fake_autocomplete_provider_client.h"
 #include "components/omnibox/browser/history_provider.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -44,6 +47,7 @@
   HistoryProvider* provider() { return &(*provider_); }
 
  private:
+  base::ScopedTempDir history_dir_;
   base::test::TaskEnvironment task_environment_;
   std::unique_ptr<FakeAutocompleteProviderClient> client_;
   scoped_refptr<TestHistoryProvider> provider_;
@@ -51,6 +55,16 @@
 
 void HistoryProviderTest::SetUp() {
   client_ = std::make_unique<FakeAutocompleteProviderClient>();
+
+  CHECK(history_dir_.CreateUniqueTempDir());
+  client_->set_history_service(
+      history::CreateHistoryService(history_dir_.GetPath(), true));
+  client_->set_bookmark_model(bookmarks::TestBookmarkClient::CreateModel());
+  client_->set_in_memory_url_index(std::make_unique<InMemoryURLIndex>(
+      client_->GetBookmarkModel(), client_->GetHistoryService(), nullptr,
+      history_dir_.GetPath(), SchemeSet()));
+  client_->GetInMemoryURLIndex()->Init();
+
   provider_ = new TestHistoryProvider(client_.get());
 }
 
diff --git a/components/omnibox/browser/history_quick_provider_performance_unittest.cc b/components/omnibox/browser/history_quick_provider_performance_unittest.cc
index bdab81d..c6b9f5c 100644
--- a/components/omnibox/browser/history_quick_provider_performance_unittest.cc
+++ b/components/omnibox/browser/history_quick_provider_performance_unittest.cc
@@ -9,7 +9,9 @@
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/thread_pool/thread_pool_instance.h"
 #include "base/test/task_environment.h"
+#include "components/bookmarks/test/test_bookmark_client.h"
 #include "components/history/core/browser/history_backend.h"
 #include "components/history/core/browser/history_database.h"
 #include "components/history/core/browser/history_service.h"
@@ -99,9 +101,9 @@
  private:
   base::TimeDelta RunTest(const std::u16string& text);
 
+  base::ScopedTempDir history_dir_;
   base::test::TaskEnvironment task_environment_;
   std::unique_ptr<FakeAutocompleteProviderClient> client_;
-
   scoped_refptr<HistoryQuickProvider> provider_;
 };
 
@@ -109,13 +111,28 @@
   if (base::ThreadTicks::IsSupported())
     base::ThreadTicks::WaitUntilInitialized();
   client_ = std::make_unique<FakeAutocompleteProviderClient>();
+
+  CHECK(history_dir_.CreateUniqueTempDir());
+  client_->set_history_service(
+      history::CreateHistoryService(history_dir_.GetPath(), true));
+  client_->set_bookmark_model(bookmarks::TestBookmarkClient::CreateModel());
+  client_->set_in_memory_url_index(std::make_unique<InMemoryURLIndex>(
+      client_->GetBookmarkModel(), client_->GetHistoryService(), nullptr,
+      history_dir_.GetPath(), SchemeSet()));
+  client_->GetInMemoryURLIndex()->Init();
+
   ASSERT_TRUE(client_->GetHistoryService());
   ASSERT_NO_FATAL_FAILURE(PrepareData());
 }
 
 void HQPPerfTestOnePopularURL::TearDown() {
+  base::RunLoop run_loop;
+  auto* history_service = client_->GetHistoryService();
+  history_service->SetOnBackendDestroyTask(run_loop.QuitClosure());
   provider_ = nullptr;
   client_.reset();
+  run_loop.Run();
+  base::ThreadPoolInstance::Get()->FlushForTesting();
   task_environment_.RunUntilIdle();
 }
 
diff --git a/components/omnibox/browser/history_quick_provider_unittest.cc b/components/omnibox/browser/history_quick_provider_unittest.cc
index 35a6b23f..8a75f32 100644
--- a/components/omnibox/browser/history_quick_provider_unittest.cc
+++ b/components/omnibox/browser/history_quick_provider_unittest.cc
@@ -187,6 +187,7 @@
 
  private:
   base::test::TaskEnvironment task_environment_;
+  base::ScopedTempDir history_dir_;
   std::unique_ptr<FakeAutocompleteProviderClient> client_;
 
   ACMatches ac_matches_;  // The resulting matches after running RunTest.
@@ -196,6 +197,14 @@
 
 void HistoryQuickProviderTest::SetUp() {
   client_ = std::make_unique<FakeAutocompleteProviderClient>();
+  CHECK(history_dir_.CreateUniqueTempDir());
+  client_->set_history_service(
+      history::CreateHistoryService(history_dir_.GetPath(), true));
+  client_->set_bookmark_model(bookmarks::TestBookmarkClient::CreateModel());
+  client_->set_in_memory_url_index(std::make_unique<InMemoryURLIndex>(
+      client_->GetBookmarkModel(), client_->GetHistoryService(), nullptr,
+      history_dir_.GetPath(), SchemeSet()));
+  client_->GetInMemoryURLIndex()->Init();
   ASSERT_TRUE(client_->GetHistoryService());
 
   // First make sure the automatic initialization completes to avoid a race
diff --git a/components/omnibox/browser/history_url_provider_unittest.cc b/components/omnibox/browser/history_url_provider_unittest.cc
index 2789b4c5..fa008a10 100644
--- a/components/omnibox/browser/history_url_provider_unittest.cc
+++ b/components/omnibox/browser/history_url_provider_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "components/bookmarks/test/test_bookmark_client.h"
 #include "components/history/core/browser/history_service.h"
 #include "components/history/core/browser/url_database.h"
 #include "components/history/core/test/history_service_test_util.h"
@@ -241,6 +242,7 @@
                                 size_t expected_match_location,
                                 size_t expected_match_length);
 
+  base::ScopedTempDir history_dir_;
   base::test::TaskEnvironment task_environment_;
   ACMatches matches_;
   std::unique_ptr<FakeAutocompleteProviderClient> client_;
@@ -273,7 +275,15 @@
 }
 
 bool HistoryURLProviderTest::SetUpImpl(bool create_history_db) {
-  client_ = std::make_unique<FakeAutocompleteProviderClient>(create_history_db);
+  client_ = std::make_unique<FakeAutocompleteProviderClient>();
+  CHECK(history_dir_.CreateUniqueTempDir());
+  client_->set_history_service(
+      history::CreateHistoryService(history_dir_.GetPath(), create_history_db));
+  client_->set_bookmark_model(bookmarks::TestBookmarkClient::CreateModel());
+  client_->set_in_memory_url_index(std::make_unique<InMemoryURLIndex>(
+      client_->GetBookmarkModel(), client_->GetHistoryService(), nullptr,
+      history_dir_.GetPath(), SchemeSet()));
+  client_->GetInMemoryURLIndex()->Init();
   if (!client_->GetHistoryService())
     return false;
   autocomplete_ = base::MakeRefCounted<HistoryURLProvider>(client_.get(), this);
diff --git a/components/omnibox/browser/local_history_zero_suggest_provider_unittest.cc b/components/omnibox/browser/local_history_zero_suggest_provider_unittest.cc
index dc9007f..7f10274d 100644
--- a/components/omnibox/browser/local_history_zero_suggest_provider_unittest.cc
+++ b/components/omnibox/browser/local_history_zero_suggest_provider_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "components/bookmarks/test/test_bookmark_client.h"
 #include "components/history/core/browser/history_service.h"
 #include "components/history/core/browser/keyword_search_term.h"
 #include "components/history/core/browser/url_database.h"
@@ -79,6 +80,14 @@
 
     client_ = std::make_unique<FakeAutocompleteProviderClient>();
     client_->set_identity_manager(identity_env_->identity_manager());
+    CHECK(history_dir_.CreateUniqueTempDir());
+    client_->set_history_service(
+        history::CreateHistoryService(history_dir_.GetPath(), true));
+    client_->set_bookmark_model(bookmarks::TestBookmarkClient::CreateModel());
+    client_->set_in_memory_url_index(std::make_unique<InMemoryURLIndex>(
+        client_->GetBookmarkModel(), client_->GetHistoryService(), nullptr,
+        history_dir_.GetPath(), SchemeSet()));
+    client_->GetInMemoryURLIndex()->Init();
 
     provider_ = base::WrapRefCounted(
         LocalHistoryZeroSuggestProvider::Create(client_.get(), this));
@@ -137,6 +146,7 @@
   }
 
   base::test::TaskEnvironment task_environment_;
+  base::ScopedTempDir history_dir_;
   // Used to spin the message loop until |provider_| is done with its async ops.
   std::unique_ptr<base::RunLoop> provider_run_loop_;
   std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
diff --git a/components/omnibox/browser/most_visited_sites_provider_unittest.cc b/components/omnibox/browser/most_visited_sites_provider_unittest.cc
index f4207de..401e2bf 100644
--- a/components/omnibox/browser/most_visited_sites_provider_unittest.cc
+++ b/components/omnibox/browser/most_visited_sites_provider_unittest.cc
@@ -136,7 +136,7 @@
   // AutocompleteProviderListener:
   void OnProviderUpdate(bool updated_matches) override;
 
-  std::unique_ptr<base::test::TaskEnvironment> task_environment_;
+  std::unique_ptr<base::test::SingleThreadTaskEnvironment> task_environment_;
   scoped_refptr<FakeTopSites> top_sites_;
   scoped_refptr<FakeTopSites> top_sites_for_start_surface_;
   scoped_refptr<MostVisitedSitesProvider> provider_;
@@ -216,7 +216,8 @@
 }
 
 void MostVisitedSitesProviderTest::SetUp() {
-  task_environment_ = std::make_unique<base::test::TaskEnvironment>();
+  task_environment_ =
+      std::make_unique<base::test::SingleThreadTaskEnvironment>();
   ntp_tiles::MostVisitedSites::RegisterProfilePrefs(pref_service_.registry());
   top_sites_ = new FakeTopSites();
   top_sites_for_start_surface_ = new FakeTopSites();
diff --git a/components/omnibox/browser/shortcuts_provider_unittest.cc b/components/omnibox/browser/shortcuts_provider_unittest.cc
index 873f6c1..8f52849e 100644
--- a/components/omnibox/browser/shortcuts_provider_unittest.cc
+++ b/components/omnibox/browser/shortcuts_provider_unittest.cc
@@ -248,6 +248,12 @@
 
 }  // namespace
 
+class MockHistoryService : public history::HistoryService {
+ public:
+  MockHistoryService() = default;
+  MOCK_METHOD1(DeleteURLs, void(const std::vector<GURL>&));
+};
+
 // ShortcutsProviderTest ------------------------------------------------------
 
 class ShortcutsProviderTest : public testing::Test {
@@ -283,6 +289,12 @@
 
 void ShortcutsProviderTest::SetUp() {
   client_ = std::make_unique<FakeAutocompleteProviderClient>();
+  client_->set_history_service(std::make_unique<MockHistoryService>());
+  auto shortcuts_backend = base::MakeRefCounted<ShortcutsBackend>(
+      client_->GetTemplateURLService(), std::make_unique<SearchTermsData>(),
+      client_->GetHistoryService(), base::FilePath(), true);
+  shortcuts_backend->Init();
+  client_->set_shortcuts_backend(std::move(shortcuts_backend));
 
   ASSERT_TRUE(client_->GetShortcutsBackend());
   provider_ = base::MakeRefCounted<ShortcutsProvider>(client_.get());
diff --git a/components/reporting/OWNERS b/components/reporting/OWNERS
index 808cfac..537ee2b 100644
--- a/components/reporting/OWNERS
+++ b/components/reporting/OWNERS
@@ -1,8 +1,7 @@
 lbaraz@chromium.org
-zatrudo@google.com
 jrhilke@google.com
 tylergarrett@chromium.org
 anasr@google.com
 albertojuarez@google.com
 scmoreno@google.com
-vshenvi@google.com
\ No newline at end of file
+vshenvi@google.com
diff --git a/components/safe_browsing/content/browser/password_protection/OWNERS b/components/safe_browsing/content/browser/password_protection/OWNERS
index ac5b456..d9b7752e 100644
--- a/components/safe_browsing/content/browser/password_protection/OWNERS
+++ b/components/safe_browsing/content/browser/password_protection/OWNERS
@@ -1 +1,2 @@
-bdea@chromium.org
+vakh@chromium.org
+xinghuilu@chromium.org
\ No newline at end of file
diff --git a/components/safe_browsing/core/browser/verdict_cache_manager.cc b/components/safe_browsing/core/browser/verdict_cache_manager.cc
index 90bbe1d..f430d69 100644
--- a/components/safe_browsing/core/browser/verdict_cache_manager.cc
+++ b/components/safe_browsing/core/browser/verdict_cache_manager.cc
@@ -621,9 +621,10 @@
   }
 
   ChromeUserPopulation::PageLoadToken token = page_load_token_map_[hostname];
-  return HasPageLoadTokenExpired(token.token_time_msec())
-             ? ChromeUserPopulation::PageLoadToken()
-             : token;
+  bool has_expired = HasPageLoadTokenExpired(token.token_time_msec());
+  base::UmaHistogramBoolean("SafeBrowsing.PageLoadToken.HasExpired",
+                            has_expired);
+  return has_expired ? ChromeUserPopulation::PageLoadToken() : token;
 }
 
 void VerdictCacheManager::ScheduleNextCleanUpAfterInterval(
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
index a5ffac47..a53eb88 100644
--- a/components/viz/service/display/skia_renderer.cc
+++ b/components/viz/service/display/skia_renderer.cc
@@ -2064,6 +2064,15 @@
   if (needs_color_conversion_filter)
     override_color_space = CurrentRenderPassColorSpace();
 
+  // TODO(b/221643955): Some Chrome OS tests rely on the old GLRenderer
+  // behavior of skipping color space conversions if the quad's color space is
+  // invalid. Once these tests are migrated, we can remove the override here
+  // and revert to Skia's default behavior of assuming sRGB on invalid.
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  if (!src_color_space.IsValid())
+    override_color_space = CurrentRenderPassColorSpace();
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
   ScopedSkImageBuilder builder(
       this, quad->resource_id(), /*maybe_concurrent_reads=*/true,
       quad->premultiplied_alpha ? kPremul_SkAlphaType : kUnpremul_SkAlphaType,
diff --git a/components/viz/test/test_context_provider.cc b/components/viz/test/test_context_provider.cc
index 8cc2954..495c0106 100644
--- a/components/viz/test/test_context_provider.cc
+++ b/components/viz/test/test_context_provider.cc
@@ -78,6 +78,7 @@
                            GLuint msaa_sample_count,
                            gpu::raster::MsaaMode msaa_mode,
                            GLboolean can_use_lcd_text,
+                           GLboolean visible,
                            const gfx::ColorSpace& color_space,
                            const GLbyte* mailbox) override {}
   void RasterCHROMIUM(const cc::DisplayItemList* list,
diff --git a/components/webcrypto/OWNERS b/components/webcrypto/OWNERS
index 81033345..e69de29 100644
--- a/components/webcrypto/OWNERS
+++ b/components/webcrypto/OWNERS
@@ -1 +0,0 @@
-rsleevi@chromium.org
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 064051cc..bf59b79f 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -2895,6 +2895,8 @@
       "direct_sockets/direct_sockets_service_impl.h",
       "direct_sockets/direct_udp_socket_impl.cc",
       "direct_sockets/direct_udp_socket_impl.h",
+      "direct_sockets/resolve_host_and_open_socket.cc",
+      "direct_sockets/resolve_host_and_open_socket.h",
 
       # The Serial API is not implemented on Android.
       "serial/serial_service.cc",
diff --git a/content/browser/android/dialog_overlay_impl.cc b/content/browser/android/dialog_overlay_impl.cc
index eed4297..cc95bd5 100644
--- a/content/browser/android/dialog_overlay_impl.cc
+++ b/content/browser/android/dialog_overlay_impl.cc
@@ -305,7 +305,7 @@
 
 static void JNI_DialogOverlayImpl_NotifyDestroyedSynchronously(
     JNIEnv* env,
-    jlong message_pipe_handle) {
+    int message_pipe_handle) {
   mojo::MessagePipeHandle handle(message_pipe_handle);
   mojo::ScopedMessagePipeHandle scoped_handle(handle);
   mojo::Remote<media::mojom::AndroidOverlayClient> remote(
diff --git a/content/browser/android/message_port_descriptor.cc b/content/browser/android/message_port_descriptor.cc
index d904d01d..c2875fb0 100644
--- a/content/browser/android/message_port_descriptor.cc
+++ b/content/browser/android/message_port_descriptor.cc
@@ -19,7 +19,7 @@
 
 namespace {
 
-mojo::ScopedMessagePipeHandle WrapNativeHandle(jlong native_handle) {
+mojo::ScopedMessagePipeHandle WrapNativeHandle(jint native_handle) {
   MojoHandle raw_handle = static_cast<MojoHandle>(native_handle);
   DCHECK_NE(MOJO_HANDLE_INVALID, raw_handle);
   return mojo::ScopedMessagePipeHandle(mojo::MessagePipeHandle(raw_handle));
@@ -45,7 +45,7 @@
 }
 
 JNI_EXPORT jlong JNI_AppWebMessagePortDescriptor_Create(JNIEnv* env,
-                                                        jlong native_handle,
+                                                        jint native_handle,
                                                         jlong id_low,
                                                         jlong id_high,
                                                         jlong sequence_number) {
@@ -61,7 +61,7 @@
   return reinterpret_cast<jlong>(port);
 }
 
-JNI_EXPORT jlong JNI_AppWebMessagePortDescriptor_TakeHandleToEntangle(
+JNI_EXPORT jint JNI_AppWebMessagePortDescriptor_TakeHandleToEntangle(
     JNIEnv* env,
     jlong native_message_port_decriptor) {
   blink::MessagePortDescriptor* message_port_descriptor =
@@ -82,7 +82,7 @@
 JNI_EXPORT void JNI_AppWebMessagePortDescriptor_GiveDisentangledHandle(
     JNIEnv* env,
     jlong native_message_port_decriptor,
-    jlong native_handle) {
+    jint native_handle) {
   blink::MessagePortDescriptor* message_port_descriptor =
       reinterpret_cast<blink::MessagePortDescriptor*>(
           native_message_port_decriptor);
diff --git a/content/browser/attribution_reporting/attribution_src_browsertest.cc b/content/browser/attribution_reporting/attribution_src_browsertest.cc
index 6267fdd..d6b55be8 100644
--- a/content/browser/attribution_reporting/attribution_src_browsertest.cc
+++ b/content/browser/attribution_reporting/attribution_src_browsertest.cc
@@ -529,7 +529,7 @@
   http_response->set_code(net::HTTP_MOVED_PERMANENTLY);
   http_response->AddCustomHeader(
       "Attribution-Reporting-Register-Source",
-      R"({"source_event_id":"9", "destination":"https://advertiser.example"})");
+      R"({"source_event_id":"9", "destination":"https://d.test"})");
   http_response->AddCustomHeader(
       "Attribution-Reporting-Register-Aggregatable-Source", "");
   http_response->AddCustomHeader("Location",
@@ -546,7 +546,7 @@
   EXPECT_EQ(source_data.size(), 1u);
   EXPECT_EQ(source_data.back()->source_event_id, 5UL);
   EXPECT_EQ(source_data.back()->destination,
-            url::Origin::Create(GURL("https://advertiser.example")));
+            url::Origin::Create(GURL("https://d.test")));
   EXPECT_THAT(source_data.back()->aggregatable_sources->sources, SizeIs(2));
 }
 
diff --git a/content/browser/direct_sockets/direct_sockets_open_browsertest.cc b/content/browser/direct_sockets/direct_sockets_open_browsertest.cc
index 1fe5f47..34845e69 100644
--- a/content/browser/direct_sockets/direct_sockets_open_browsertest.cc
+++ b/content/browser/direct_sockets/direct_sockets_open_browsertest.cc
@@ -5,7 +5,10 @@
 #include <map>
 #include <vector>
 
+#include "base/bind.h"
+#include "base/command_line.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/metrics/histogram.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
@@ -15,6 +18,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "content/browser/direct_sockets/direct_sockets_service_impl.h"
+#include "content/browser/direct_sockets/resolve_host_and_open_socket.h"
 #include "content/browser/renderer_host/frame_tree_node.h"
 #include "content/browser/renderer_host/render_frame_host_impl.h"
 #include "content/public/browser/browser_context.h"
@@ -32,10 +36,14 @@
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_errors.h"
 #include "net/dns/host_resolver.h"
+#include "net/http/http_request_headers.h"
 #include "net/net_buildflags.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_response.h"
+#include "net/test/embedded_test_server/request_handler_util.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "services/network/public/cpp/cors/cors.h"
 #include "services/network/public/mojom/host_resolver.mojom.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 #include "services/network/public/mojom/tcp_socket.mojom.h"
@@ -407,9 +415,6 @@
     command_line->AppendSwitchASCII(switches::kRestrictedApiOrigins,
                                     origin_list);
   }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
 };
 
 IN_PROC_BROWSER_TEST_F(DirectSocketsOpenBrowserTest, OpenTcp_Success_Hostname) {
@@ -451,25 +456,6 @@
       EvalJs(shell(), script));
 }
 
-IN_PROC_BROWSER_TEST_F(DirectSocketsOpenBrowserTest, OpenTcp_CannotEvadeCors) {
-  EXPECT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL()));
-
-  base::HistogramTester histogram_tester;
-  histogram_tester.ExpectBucketCount(
-      kPermissionDeniedHistogramName,
-      blink::mojom::DirectSocketFailureType::kCORS, 0);
-
-  // HTTPS uses port 443.
-  const std::string script =
-      "openTcp({remoteAddress: '127.0.0.1', remotePort: 443})";
-
-  EXPECT_EQ("openTcp failed: NetworkError: Network error.",
-            EvalJs(shell(), script));
-  histogram_tester.ExpectBucketCount(
-      kPermissionDeniedHistogramName,
-      blink::mojom::DirectSocketFailureType::kCORS, 1);
-}
-
 // Remote address should be provided or TEST will fail with NotAllowedError. In
 // actual use scenario, it can be obtained from the user's input in connection
 // dialog.
@@ -746,25 +732,6 @@
             EvalJs(shell(), script));
 }
 
-IN_PROC_BROWSER_TEST_F(DirectSocketsOpenBrowserTest, OpenUdp_CannotEvadeCors) {
-  EXPECT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL()));
-
-  base::HistogramTester histogram_tester;
-  histogram_tester.ExpectBucketCount(
-      kPermissionDeniedHistogramName,
-      blink::mojom::DirectSocketFailureType::kCORS, 0);
-
-  // QUIC uses port 443.
-  const std::string script =
-      "openUdp({remoteAddress: '127.0.0.1', remotePort: 443})";
-
-  EXPECT_EQ("openUdp failed: NetworkError: Network error.",
-            EvalJs(shell(), script));
-  histogram_tester.ExpectBucketCount(
-      kPermissionDeniedHistogramName,
-      blink::mojom::DirectSocketFailureType::kCORS, 1);
-}
-
 // Remote address should be provided or TEST will fail with NotAllowedError. In
 // actual use scenario, it can be obtained from the user's input in connection
 // dialog.
@@ -906,4 +873,134 @@
   EXPECT_EQ(1234, call.receive_buffer_size);
 }
 
+class DirectSocketsOpenCorsBrowserTest
+    : public DirectSocketsOpenBrowserTest,
+      public testing::WithParamInterface<bool> {
+ public:
+  DirectSocketsOpenCorsBrowserTest()
+      : https_server_(net::test_server::EmbeddedTestServer::TYPE_HTTPS) {}
+
+  void SetUp() override {
+    https_server()->RegisterDefaultHandler(base::BindRepeating(
+        &net::test_server::HandlePrefixedRequest, "/",
+        base::BindRepeating(
+            &DirectSocketsOpenCorsBrowserTest::HandleCORSRequest,
+            base::Unretained(this), GetParam())));
+    ASSERT_TRUE(https_server()->Start(4344));
+    DirectSocketsOpenBrowserTest::SetUp();
+  }
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    ContentBrowserTest::SetUpCommandLine(command_line);
+
+    command_line->AppendSwitchASCII(switches::kRestrictedApiOrigins,
+                                    GetTestOpenPageURL().spec());
+  }
+
+ protected:
+  std::unique_ptr<net::test_server::HttpResponse> HandleCORSRequest(
+      bool cors_success,
+      const net::test_server::HttpRequest& request) {
+    auto response = std::make_unique<net::test_server::BasicHttpResponse>();
+
+    if (request.method == net::test_server::METHOD_OPTIONS) {
+      if (cors_success) {
+        response->AddCustomHeader(
+            network::cors::header_names::kAccessControlAllowOrigin, "*");
+
+        response->AddCustomHeader(
+            network::cors::header_names::kAccessControlAllowHeaders, "*");
+      }
+    } else {
+      response->AddCustomHeader(
+          network::cors::header_names::kAccessControlAllowOrigin, "*");
+      response->set_content("OK");
+    }
+
+    return response;
+  }
+
+  net::test_server::EmbeddedTestServer* https_server() {
+    return &https_server_;
+  }
+
+ private:
+  net::test_server::EmbeddedTestServer https_server_;
+};
+
+IN_PROC_BROWSER_TEST_P(DirectSocketsOpenCorsBrowserTest, OpenTcp) {
+  EXPECT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL()));
+
+  MockNetworkContext mock_network_context(net::OK);
+  DirectSocketsServiceImpl::SetNetworkContextForTesting(&mock_network_context);
+  // HTTPS uses port 443. We cannot really start a server on port 443, therefore
+  // we mock the behavior.
+  ResolveHostAndOpenSocket::SetHttpsPortForTesting(https_server()->port());
+
+  base::HistogramTester histogram_tester;
+  histogram_tester.ExpectBucketCount(
+      kPermissionDeniedHistogramName,
+      blink::mojom::DirectSocketFailureType::kCORS, 0);
+
+  const std::string script =
+      base::StringPrintf("openTcp({remoteAddress: '%s', remotePort: %d})",
+                         "127.0.0.1", https_server()->port());
+
+  bool cors_success = GetParam();
+
+  const std::string expected_verdict =
+      cors_success
+          ? base::StringPrintf(
+                "openTcp succeeded: {remoteAddress: \"127.0.0.1\", remotePort: "
+                "%d}",
+                https_server()->port())
+          : "openTcp failed: NetworkError: Network error.";
+
+  EXPECT_EQ(expected_verdict, EvalJs(shell(), script));
+
+  histogram_tester.ExpectBucketCount(
+      kPermissionDeniedHistogramName,
+      blink::mojom::DirectSocketFailureType::kCORS, cors_success ? 0 : 1);
+}
+
+IN_PROC_BROWSER_TEST_P(DirectSocketsOpenCorsBrowserTest, OpenUdp) {
+  EXPECT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL()));
+
+  MockNetworkContext mock_network_context(net::OK);
+  DirectSocketsServiceImpl::SetNetworkContextForTesting(&mock_network_context);
+
+  // HTTPS uses port 443. We cannot really start a server on port 443, therefore
+  // we mock the behavior.
+  ResolveHostAndOpenSocket::SetHttpsPortForTesting(https_server()->port());
+
+  base::HistogramTester histogram_tester;
+  histogram_tester.ExpectBucketCount(
+      kPermissionDeniedHistogramName,
+      blink::mojom::DirectSocketFailureType::kCORS, 0);
+
+  const std::string script =
+      base::StringPrintf("openUdp({remoteAddress: '%s', remotePort: %d})",
+                         "127.0.0.1", https_server()->port());
+
+  bool cors_success = GetParam();
+
+  const std::string expected_verdict =
+      cors_success
+          ? base::StringPrintf(
+                "openUdp succeeded: {remoteAddress: \"127.0.0.1\", remotePort: "
+                "%d}",
+                https_server()->port())
+          : "openUdp failed: NetworkError: Network error.";
+
+  EXPECT_EQ(expected_verdict, EvalJs(shell(), script));
+
+  histogram_tester.ExpectBucketCount(
+      kPermissionDeniedHistogramName,
+      blink::mojom::DirectSocketFailureType::kCORS, cors_success ? 0 : 1);
+}
+
+INSTANTIATE_TEST_SUITE_P(/*no prefix*/,
+                         DirectSocketsOpenCorsBrowserTest,
+                         testing::Bool());
+
 }  // namespace content
diff --git a/content/browser/direct_sockets/direct_sockets_service_impl.cc b/content/browser/direct_sockets/direct_sockets_service_impl.cc
index 2f47771..97dcf74 100644
--- a/content/browser/direct_sockets/direct_sockets_service_impl.cc
+++ b/content/browser/direct_sockets/direct_sockets_service_impl.cc
@@ -4,18 +4,23 @@
 
 #include "content/browser/direct_sockets/direct_sockets_service_impl.h"
 
-#include <memory>
-
 #include "base/bind.h"
+#include "base/callback_forward.h"
 #include "base/feature_list.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/no_destructor.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "content/browser/direct_sockets/direct_udp_socket_impl.h"
+#include "content/browser/direct_sockets/resolve_host_and_open_socket.h"
 #include "content/browser/renderer_host/frame_tree_node.h"
 #include "content/browser/renderer_host/render_frame_host_impl.h"
+#include "content/browser/url_loader_factory_params_helper.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_client.h"
@@ -23,11 +28,17 @@
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "net/base/address_list.h"
+#include "net/base/ip_address.h"
+#include "net/base/ip_endpoint.h"
+#include "net/http/http_request_headers.h"
 #include "net/net_buildflags.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/cpp/resolve_host_client_base.h"
+#include "services/network/public/cpp/simple_url_loader.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 #include "services/network/public/mojom/tcp_socket.mojom.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/url_constants.h"
 
 using blink::mojom::DirectSocketFailureType;
 
@@ -54,9 +65,6 @@
 
 constexpr int32_t kMaxBufferSize = 32 * 1024 * 1024;
 
-constexpr char kPermissionDeniedHistogramName[] =
-    "DirectSockets.PermissionDeniedFailures";
-
 DirectSocketsServiceImpl::PermissionCallback&
 GetPermissionCallbackForTesting() {
   static base::NoDestructor<DirectSocketsServiceImpl::PermissionCallback>
@@ -69,37 +77,6 @@
   return network_context;
 }
 
-// Get local ip address from options.
-absl::optional<net::IPEndPoint> GetLocalAddr(
-    const blink::mojom::DirectSocketOptions& options) {
-  absl::optional<net::IPEndPoint> local_addr = absl::nullopt;
-  if (!options.local_hostname)
-    return local_addr;
-
-  net::IPAddress local_address;
-  bool success = local_address.AssignFromIPLiteral(*options.local_hostname);
-  if (success)
-    local_addr = net::IPEndPoint(local_address, options.local_port);
-
-  return local_addr;
-}
-
-#if BUILDFLAG(ENABLE_MDNS)
-bool ResemblesMulticastDNSName(const std::string& hostname) {
-  return base::EndsWith(hostname, ".local") ||
-         base::EndsWith(hostname, ".local.");
-}
-#endif  // !BUILDFLAG(ENABLE_MDNS)
-
-bool ContainNonPubliclyRoutableAddress(const net::AddressList& addresses) {
-  DCHECK(!addresses.empty());
-  for (auto ip : addresses) {
-    if (!ip.address().IsPubliclyRoutable())
-      return true;
-  }
-  return false;
-}
-
 }  // namespace
 
 DirectSocketsServiceImpl::DirectSocketsServiceImpl(RenderFrameHost& frame_host)
@@ -118,215 +95,6 @@
       std::move(receiver));
 }
 
-class DirectSocketsServiceImpl::ResolveHostAndOpenSocket final
-    : public network::ResolveHostClientBase {
- public:
-  ResolveHostAndOpenSocket(
-      base::WeakPtr<DirectSocketsServiceImpl> direct_sockets_service_impl,
-      blink::mojom::DirectSocketOptionsPtr options,
-      mojo::PendingReceiver<network::mojom::TCPConnectedSocket> tcp_receiver,
-      mojo::PendingRemote<network::mojom::SocketObserver> observer,
-      OpenTcpSocketCallback tcp_callback)
-      : protocol_(ProtocolType::kTcp),
-        direct_sockets_service_impl_(std::move(direct_sockets_service_impl)),
-        options_(std::move(options)),
-        tcp_receiver_(std::move(tcp_receiver)),
-        observer_(std::move(observer)),
-        tcp_callback_(std::move(tcp_callback)) {}
-
-  ResolveHostAndOpenSocket(
-      base::WeakPtr<DirectSocketsServiceImpl> direct_sockets_service_impl,
-      blink::mojom::DirectSocketOptionsPtr options,
-      mojo::PendingReceiver<blink::mojom::DirectUDPSocket> udp_receiver,
-      mojo::PendingRemote<network::mojom::UDPSocketListener> udp_listener,
-      OpenUdpSocketCallback udp_callback)
-      : protocol_(ProtocolType::kUdp),
-        direct_sockets_service_impl_(std::move(direct_sockets_service_impl)),
-        options_(std::move(options)),
-        udp_receiver_(std::move(udp_receiver)),
-        udp_listener_(std::move(udp_listener)),
-        udp_callback_(std::move(udp_callback)) {}
-
-  ~ResolveHostAndOpenSocket() override = default;
-
-  void Start(network::mojom::NetworkContext* network_context) {
-    DCHECK(network_context);
-    DCHECK(!receiver_.is_bound());
-    DCHECK(!resolver_.is_bound());
-
-    if (net::IPAddress().AssignFromIPLiteral(*options_->remote_hostname)) {
-      is_raw_address_ = true;
-    }
-
-    mojo::PendingRemote<network::mojom::HostResolver> pending_host_resolver;
-    network_context->CreateHostResolver(
-        absl::nullopt, pending_host_resolver.InitWithNewPipeAndPassReceiver());
-    resolver_.Bind(std::move(pending_host_resolver));
-
-    network::mojom::ResolveHostParametersPtr parameters =
-        network::mojom::ResolveHostParameters::New();
-#if BUILDFLAG(ENABLE_MDNS)
-    if (ResemblesMulticastDNSName(*options_->remote_hostname)) {
-      parameters->source = net::HostResolverSource::MULTICAST_DNS;
-      is_mdns_name_ = true;
-    }
-#endif  // !BUILDFLAG(ENABLE_MDNS)
-    resolver_->ResolveHost(
-        net::HostPortPair(*options_->remote_hostname, options_->remote_port),
-        net::NetworkIsolationKey::CreateTransient(), std::move(parameters),
-        receiver_.BindNewPipeAndPassRemote());
-    receiver_.set_disconnect_handler(
-        base::BindOnce(&ResolveHostAndOpenSocket::OnComplete,
-                       base::Unretained(this), net::ERR_NAME_NOT_RESOLVED,
-                       net::ResolveErrorInfo(net::ERR_FAILED), absl::nullopt));
-  }
-
- private:
-  // network::mojom::ResolveHostClient implementation:
-  void OnComplete(
-      int result,
-      const net::ResolveErrorInfo& resolve_error_info,
-      const absl::optional<net::AddressList>& resolved_addresses) override {
-    DCHECK(receiver_.is_bound());
-    receiver_.reset();
-
-    // Reject hostnames that resolve to non-public exception unless a raw IP
-    // address or a *.local hostname is entered by the user.
-    if (!is_raw_address_ && !is_mdns_name_ && resolved_addresses &&
-        ContainNonPubliclyRoutableAddress(*resolved_addresses)) {
-      result = net::Error::ERR_NETWORK_ACCESS_DENIED;
-      base::UmaHistogramEnumeration(
-          kPermissionDeniedHistogramName,
-          DirectSocketFailureType::kResolvingToNonPublic);
-    }
-    protocol_ == ProtocolType::kTcp ? OpenTCPSocket(result, resolved_addresses)
-                                    : OpenUDPSocket(result, resolved_addresses);
-  }
-
-  void OpenTCPSocket(
-      int result,
-      const absl::optional<net::AddressList>& resolved_addresses) {
-    network::mojom::NetworkContext* network_context = nullptr;
-    if (DirectSocketsServiceImpl* const direct_sockets_service_impl =
-            direct_sockets_service_impl_.get()) {
-      network_context = direct_sockets_service_impl->GetNetworkContext();
-    }
-    if (!network_context) {
-      delete this;
-      return;
-    }
-
-    if (result != net::OK) {
-      std::move(tcp_callback_)
-          .Run(result, absl::nullopt, absl::nullopt,
-               mojo::ScopedDataPipeConsumerHandle(),
-               mojo::ScopedDataPipeProducerHandle());
-      delete this;
-      return;
-    }
-
-    DCHECK(resolved_addresses && !resolved_addresses->empty());
-    const absl::optional<net::IPEndPoint> local_addr = GetLocalAddr(*options_);
-
-    network::mojom::TCPConnectedSocketOptionsPtr tcp_connected_socket_options =
-        network::mojom::TCPConnectedSocketOptions::New();
-    if (options_->send_buffer_size > 0) {
-      tcp_connected_socket_options->send_buffer_size =
-          std::min(options_->send_buffer_size, kMaxBufferSize);
-    }
-    if (options_->receive_buffer_size > 0) {
-      tcp_connected_socket_options->receive_buffer_size =
-          std::min(options_->receive_buffer_size, kMaxBufferSize);
-    }
-    tcp_connected_socket_options->no_delay = options_->no_delay;
-    if (options_->keep_alive_options) {
-      // options_->keep_alive_options will be invalidated.
-      tcp_connected_socket_options->keep_alive_options =
-          std::move(options_->keep_alive_options);
-    }
-    // invalidate options_.
-    options_.reset();
-
-    network_context->CreateTCPConnectedSocket(
-        local_addr, *resolved_addresses,
-        std::move(tcp_connected_socket_options), TrafficAnnotation(),
-        std::move(tcp_receiver_), std::move(observer_),
-        std::move(tcp_callback_));
-    delete this;
-  }
-
-  void OpenUDPSocket(
-      int result,
-      const absl::optional<net::AddressList>& resolved_addresses) {
-    network::mojom::NetworkContext* network_context = nullptr;
-    DirectSocketsServiceImpl* const direct_sockets_service_impl =
-        direct_sockets_service_impl_.get();
-    if (direct_sockets_service_impl) {
-      network_context = direct_sockets_service_impl->GetNetworkContext();
-    }
-    if (!network_context) {
-      delete this;
-      return;
-    }
-
-    if (result != net::OK) {
-      std::move(udp_callback_).Run(result, absl::nullopt, absl::nullopt);
-      delete this;
-      return;
-    }
-
-    DCHECK(resolved_addresses && !resolved_addresses->empty());
-    absl::optional<net::IPEndPoint> local_addr = GetLocalAddr(*options_);
-
-    network::mojom::UDPSocketOptionsPtr udp_socket_options =
-        network::mojom::UDPSocketOptions::New();
-    if (options_->send_buffer_size > 0) {
-      udp_socket_options->send_buffer_size =
-          std::min(options_->send_buffer_size, kMaxBufferSize);
-    }
-    if (options_->receive_buffer_size > 0) {
-      udp_socket_options->receive_buffer_size =
-          std::min(options_->receive_buffer_size, kMaxBufferSize);
-    }
-
-    net::IPEndPoint peer_addr = resolved_addresses->front();
-    auto direct_udp_socket = std::make_unique<DirectUDPSocketImpl>(
-        network_context, std::move(udp_listener_));
-    direct_udp_socket->Connect(
-        peer_addr, std::move(udp_socket_options),
-        base::BindOnce(&ResolveHostAndOpenSocket::OnUdpConnectCompleted,
-                       base::Unretained(this), peer_addr));
-    direct_sockets_service_impl->direct_udp_socket_receivers_.Add(
-        std::move(direct_udp_socket), std::move(udp_receiver_));
-  }
-
-  void OnUdpConnectCompleted(
-      net::IPEndPoint peer_addr,
-      int result,
-      const absl::optional<net::IPEndPoint>& local_addr) {
-    std::move(udp_callback_).Run(result, local_addr, peer_addr);
-    delete this;
-  }
-
-  bool is_mdns_name_ = false;
-  bool is_raw_address_ = false;
-
-  const ProtocolType protocol_;
-  const base::WeakPtr<DirectSocketsServiceImpl> direct_sockets_service_impl_;
-  blink::mojom::DirectSocketOptionsPtr options_;
-
-  mojo::PendingReceiver<network::mojom::TCPConnectedSocket> tcp_receiver_;
-  mojo::PendingRemote<network::mojom::SocketObserver> observer_;
-  OpenTcpSocketCallback tcp_callback_;
-
-  mojo::PendingReceiver<blink::mojom::DirectUDPSocket> udp_receiver_;
-  mojo::PendingRemote<network::mojom::UDPSocketListener> udp_listener_;
-  OpenUdpSocketCallback udp_callback_;
-
-  mojo::Receiver<network::mojom::ResolveHostClient> receiver_{this};
-  mojo::Remote<network::mojom::HostResolver> resolver_;
-};
-
 void DirectSocketsServiceImpl::OpenTcpSocket(
     blink::mojom::DirectSocketOptionsPtr options,
     mojo::PendingReceiver<network::mojom::TCPConnectedSocket> receiver,
@@ -346,16 +114,15 @@
     return;
   }
 
-  network::mojom::NetworkContext* const network_context = GetNetworkContext();
-  if (!network_context) {
+  if (!GetNetworkContext()) {
     mojo::ReportBadMessage("Invalid request to open socket");
     return;
   }
 
-  ResolveHostAndOpenSocket* resolver = new ResolveHostAndOpenSocket(
+  ResolveHostAndOpenSocket* resolver = new ResolveHostAndOpenTCPSocket(
       weak_ptr_factory_.GetWeakPtr(), std::move(options), std::move(receiver),
       std::move(observer), std::move(callback));
-  resolver->Start(network_context);
+  resolver->Start();
 }
 
 void DirectSocketsServiceImpl::OpenUdpSocket(
@@ -381,20 +148,30 @@
     return;
   }
 
-  ResolveHostAndOpenSocket* resolver = new ResolveHostAndOpenSocket(
+  ResolveHostAndOpenSocket* resolver = new ResolveHostAndOpenUDPSocket(
       weak_ptr_factory_.GetWeakPtr(), std::move(options), std::move(receiver),
       std::move(listener), std::move(callback));
-  resolver->Start(network_context);
+  resolver->Start();
 }
 
 // static
 net::MutableNetworkTrafficAnnotationTag
-DirectSocketsServiceImpl::TrafficAnnotation() {
+DirectSocketsServiceImpl::MutableTrafficAnnotation() {
   return net::MutableNetworkTrafficAnnotationTag(
       kDirectSocketsTrafficAnnotation);
 }
 
 // static
+net::NetworkTrafficAnnotationTag DirectSocketsServiceImpl::TrafficAnnotation() {
+  return kDirectSocketsTrafficAnnotation;
+}
+
+// static
+int32_t DirectSocketsServiceImpl::GetMaxBufferSize() {
+  return kMaxBufferSize;
+}
+
+// static
 void DirectSocketsServiceImpl::SetPermissionCallbackForTesting(
     PermissionCallback callback) {
   GetPermissionCallbackForTesting() = std::move(callback);
@@ -410,7 +187,14 @@
 absl::optional<net::IPEndPoint>
 DirectSocketsServiceImpl::GetLocalAddrForTesting(
     const blink::mojom::DirectSocketOptions& options) {
-  return GetLocalAddr(options);
+  if (!options.local_hostname) {
+    return {};
+  }
+  if (net::IPAddress address;
+      address.AssignFromIPLiteral(*options.local_hostname)) {
+    return net::IPEndPoint(std::move(address), options.local_port);
+  }
+  return {};
 }
 
 void DirectSocketsServiceImpl::RenderFrameDeleted(
@@ -433,6 +217,10 @@
   return frame_host_->GetStoragePartition()->GetNetworkContext();
 }
 
+RenderFrameHost* DirectSocketsServiceImpl::GetFrameHost() {
+  return frame_host_;
+}
+
 net::Error DirectSocketsServiceImpl::ValidateOptions(
     const blink::mojom::DirectSocketOptions& options) {
   if (!frame_host_)
@@ -444,14 +232,13 @@
   if (options.send_buffer_size < 0 || options.receive_buffer_size < 0)
     return net::ERR_INVALID_ARGUMENT;
 
-  if (options.remote_port == 443) {
-    base::UmaHistogramEnumeration(kPermissionDeniedHistogramName,
-                                  DirectSocketFailureType::kCORS);
-    // TODO(crbug.com/1119601): Issue a CORS preflight request.
-    return net::ERR_UNSAFE_PORT;
-  }
-
   return net::OK;
 }
 
+void DirectSocketsServiceImpl::AddDirectUDPSocketReceiver(
+    std::unique_ptr<DirectUDPSocketImpl> socket,
+    mojo::PendingReceiver<blink::mojom::DirectUDPSocket> receiver) {
+  direct_udp_socket_receivers_.Add(std::move(socket), std::move(receiver));
+}
+
 }  // namespace content
\ No newline at end of file
diff --git a/content/browser/direct_sockets/direct_sockets_service_impl.h b/content/browser/direct_sockets/direct_sockets_service_impl.h
index 24016eb7..26cf967 100644
--- a/content/browser/direct_sockets/direct_sockets_service_impl.h
+++ b/content/browser/direct_sockets/direct_sockets_service_impl.h
@@ -7,7 +7,10 @@
 
 #include "base/callback.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
+#include "base/run_loop.h"
+#include "content/browser/direct_sockets/direct_udp_socket_impl.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -15,7 +18,9 @@
 #include "mojo/public/cpp/bindings/unique_receiver_set.h"
 #include "net/base/ip_address.h"
 #include "net/base/net_errors.h"
+#include "net/http/http_response_headers.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/cpp/simple_url_loader.h"
 #include "services/network/public/mojom/udp_socket.mojom.h"
 #include "third_party/blink/public/mojom/direct_sockets/direct_sockets.mojom.h"
 
@@ -64,13 +69,15 @@
   void WebContentsDestroyed() override;
 
   network::mojom::NetworkContext* GetNetworkContext();
+  RenderFrameHost* GetFrameHost();
 
-  mojo::UniqueReceiverSet<blink::mojom::DirectUDPSocket>&
-  direct_udp_socket_receivers() {
-    return direct_udp_socket_receivers_;
-  }
+  void AddDirectUDPSocketReceiver(
+      std::unique_ptr<DirectUDPSocketImpl> socket,
+      mojo::PendingReceiver<blink::mojom::DirectUDPSocket> receiver);
 
-  static net::MutableNetworkTrafficAnnotationTag TrafficAnnotation();
+  static net::MutableNetworkTrafficAnnotationTag MutableTrafficAnnotation();
+  static net::NetworkTrafficAnnotationTag TrafficAnnotation();
+  static int32_t GetMaxBufferSize();
 
   static void SetEnterpriseManagedForTesting(bool enterprise_managed);
 
@@ -84,8 +91,6 @@
  private:
   friend class DirectSocketsUnitTest;
 
-  class ResolveHostAndOpenSocket;
-
   // Returns net::OK if the options are valid and the connection is permitted.
   net::Error ValidateOptions(const blink::mojom::DirectSocketOptions& options);
 
@@ -93,6 +98,7 @@
   mojo::UniqueReceiverSet<blink::mojom::DirectUDPSocket>
       direct_udp_socket_receivers_;
 
+  std::unique_ptr<network::SimpleURLLoader> loader_;
   base::WeakPtrFactory<DirectSocketsServiceImpl> weak_ptr_factory_{this};
 };
 
diff --git a/content/browser/direct_sockets/direct_udp_socket_impl.cc b/content/browser/direct_sockets/direct_udp_socket_impl.cc
index 5bf3a4e9..52cd02e 100644
--- a/content/browser/direct_sockets/direct_udp_socket_impl.cc
+++ b/content/browser/direct_sockets/direct_udp_socket_impl.cc
@@ -39,7 +39,8 @@
     std::move(callback).Run(net::ERR_FAILED);
     return;
   }
-  remote_->Send(std::move(data), DirectSocketsServiceImpl::TrafficAnnotation(),
+  remote_->Send(std::move(data),
+                DirectSocketsServiceImpl::MutableTrafficAnnotation(),
                 std::move(callback));
 }
 
diff --git a/content/browser/direct_sockets/resolve_host_and_open_socket.cc b/content/browser/direct_sockets/resolve_host_and_open_socket.cc
new file mode 100644
index 0000000..597cf11e
--- /dev/null
+++ b/content/browser/direct_sockets/resolve_host_and_open_socket.cc
@@ -0,0 +1,363 @@
+// 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/direct_sockets/resolve_host_and_open_socket.h"
+
+#include "base/memory/scoped_refptr.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
+#include "content/browser/direct_sockets/direct_sockets_service_impl.h"
+#include "net/base/ip_endpoint.h"
+#include "net/http/http_response_headers.h"
+#include "net/net_buildflags.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/network_context.mojom.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "third_party/blink/public/mojom/direct_sockets/direct_sockets.mojom-shared.h"
+
+namespace {
+
+constexpr char kPermissionDeniedHistogramName[] =
+    "DirectSockets.PermissionDeniedFailures";
+
+constexpr base::TimeDelta kCorsRequestTimeout = base::Seconds(15);
+
+constexpr int kHttpsPort = 443;
+
+#if BUILDFLAG(ENABLE_MDNS)
+bool ResemblesMulticastDNSName(const std::string& hostname) {
+  return base::EndsWith(hostname, ".local") ||
+         base::EndsWith(hostname, ".local.");
+}
+#endif  // !BUILDFLAG(ENABLE_MDNS)
+
+bool ContainNonPubliclyRoutableAddress(const net::AddressList& addresses) {
+  DCHECK(!addresses.empty());
+  for (auto ip : addresses) {
+    if (!ip.address().IsPubliclyRoutable())
+      return true;
+  }
+  return false;
+}
+
+absl::optional<net::IPEndPoint> GetLocalAddr(
+    const blink::mojom::DirectSocketOptions& options) {
+  absl::optional<net::IPEndPoint> local_addr = absl::nullopt;
+  if (!options.local_hostname) {
+    return {};
+  }
+
+  if (net::IPAddress local_address;
+      local_address.AssignFromIPLiteral(*options.local_hostname)) {
+    return net::IPEndPoint(local_address, options.local_port);
+  }
+
+  return {};
+}
+
+absl::optional<int> g_https_port_for_testing = {};
+
+}  // namespace
+
+namespace content {
+
+// ResolveHostAndOpenSocket implementation.
+
+ResolveHostAndOpenSocket::ResolveHostAndOpenSocket(
+    base::WeakPtr<DirectSocketsServiceImpl> service,
+    blink::mojom::DirectSocketOptionsPtr options)
+    : service_(std::move(service)), options_(std::move(options)) {}
+
+ResolveHostAndOpenSocket::~ResolveHostAndOpenSocket() = default;
+
+void ResolveHostAndOpenSocket::Start() {
+  auto* network_context = service_->GetNetworkContext();
+  DCHECK(network_context);
+  DCHECK(!receiver_.is_bound());
+  DCHECK(!resolver_.is_bound());
+
+  if (net::IPAddress().AssignFromIPLiteral(*options_->remote_hostname)) {
+    is_raw_address_ = true;
+  }
+
+  network_context->CreateHostResolver(absl::nullopt,
+                                      resolver_.BindNewPipeAndPassReceiver());
+
+  network::mojom::ResolveHostParametersPtr parameters =
+      network::mojom::ResolveHostParameters::New();
+#if BUILDFLAG(ENABLE_MDNS)
+  if (ResemblesMulticastDNSName(*options_->remote_hostname)) {
+    parameters->source = net::HostResolverSource::MULTICAST_DNS;
+    is_mdns_name_ = true;
+  }
+#endif  // !BUILDFLAG(ENABLE_MDNS)
+  resolver_->ResolveHost(
+      net::HostPortPair(*options_->remote_hostname, options_->remote_port),
+      net::NetworkIsolationKey::CreateTransient(), std::move(parameters),
+      receiver_.BindNewPipeAndPassRemote());
+  receiver_.set_disconnect_handler(
+      base::BindOnce(&ResolveHostAndOpenSocket::OnComplete,
+                     base::Unretained(this), net::ERR_NAME_NOT_RESOLVED,
+                     net::ResolveErrorInfo(net::ERR_FAILED), absl::nullopt));
+}
+
+// static
+int ResolveHostAndOpenSocket::GetHttpsPort() {
+  if (g_https_port_for_testing) {
+    return *g_https_port_for_testing;
+  }
+  return kHttpsPort;
+}
+
+// static
+void ResolveHostAndOpenSocket::SetHttpsPortForTesting(
+    absl::optional<int> https_port) {
+  g_https_port_for_testing = https_port;
+}
+
+void ResolveHostAndOpenSocket::OnComplete(
+    int result,
+    const net::ResolveErrorInfo& resolve_error_info,
+    const absl::optional<net::AddressList>& resolved_addresses) {
+  DCHECK(receiver_.is_bound());
+  receiver_.reset();
+
+  // Reject hostnames that resolve to non-public exception unless a raw IP
+  // address or a *.local hostname is entered by the user.
+  if (!is_raw_address_ && !is_mdns_name_ && resolved_addresses &&
+      ContainNonPubliclyRoutableAddress(*resolved_addresses)) {
+    base::UmaHistogramEnumeration(
+        kPermissionDeniedHistogramName,
+        blink::mojom::DirectSocketFailureType::kResolvingToNonPublic);
+    OpenSocket(net::ERR_NETWORK_ACCESS_DENIED, {});
+    return;
+  }
+
+  if (result == net::OK && resolved_addresses) {
+    if (resolved_addresses->size() > 1) {
+      OpenSocket(net::ERR_NOT_IMPLEMENTED, {});
+      return;
+    }
+    if (const auto& resolved_address = resolved_addresses->front();
+        resolved_address.port() == GetHttpsPort()) {
+      // Delegates to OpenSocket(...) after the check.
+      // We cannot use the resolved address here since it causes problems
+      // with SSL :(
+      PerformCORSCheck(*options_->remote_hostname, resolved_address);
+      return;
+    }
+  }
+
+  OpenSocket(result, resolved_addresses);
+}
+
+void ResolveHostAndOpenSocket::PerformCORSCheck(
+    const std::string& address,
+    const net::IPEndPoint& resolved_address) {
+  if (!service_) {
+    OpenSocket(net::ERR_UNEXPECTED, {});
+    return;
+  }
+
+  auto* frame = service_->GetFrameHost();
+  if (!frame) {
+    OpenSocket(net::ERR_UNEXPECTED, {});
+    return;
+  }
+
+  mojo::Remote<network::mojom::URLLoaderFactory> factory;
+  frame->CreateNetworkServiceDefaultFactory(
+      factory.BindNewPipeAndPassReceiver());
+
+  auto resource_request = std::make_unique<network::ResourceRequest>();
+
+  resource_request->url =
+      url::SchemeHostPort(url::kHttpsScheme, address, GetHttpsPort()).GetURL();
+  if (!resource_request->url.is_valid()) {
+    OpenSocket(net::ERR_INVALID_URL, {});
+    return;
+  }
+
+  resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
+  resource_request->method = net::HttpRequestHeaders::kGetMethod;
+  resource_request->mode =
+      network::mojom::RequestMode::kCorsWithForcedPreflight;
+  resource_request->request_initiator = frame->GetLastCommittedOrigin();
+
+  auto loader = network::SimpleURLLoader::Create(
+      std::move(resource_request),
+      DirectSocketsServiceImpl::TrafficAnnotation());
+  auto* loader_ptr = loader.get();
+
+  loader_ptr->SetTimeoutDuration(kCorsRequestTimeout);
+
+  loader_ptr->DownloadHeadersOnly(
+      factory.get(),
+      base::BindOnce(&ResolveHostAndOpenSocket::OnCORSCheckComplete,
+                     base::Unretained(this), std::move(loader),
+                     resolved_address));
+}
+
+void ResolveHostAndOpenSocket::OnCORSCheckComplete(
+    std::unique_ptr<network::SimpleURLLoader> loader,
+    net::IPEndPoint resolved_address,
+    scoped_refptr<net::HttpResponseHeaders>) {
+  if (const auto& completion_status = loader->CompletionStatus()) {
+    if (auto status = completion_status->cors_error_status) {
+      LOG(ERROR) << "Preflight failed: " << *status;
+      base::UmaHistogramEnumeration(
+          kPermissionDeniedHistogramName,
+          blink::mojom::DirectSocketFailureType::kCORS);
+      OpenSocket(net::ERR_BLOCKED_BY_RESPONSE, {});
+      return;
+    }
+    if (completion_status->error_code != net::OK) {
+      OpenSocket(completion_status->error_code, {});
+      return;
+    }
+    auto resolved_addresses = net::AddressList(std::move(resolved_address));
+    OpenSocket(net::OK, std::move(resolved_addresses));
+    return;
+  }
+
+  OpenSocket(net::ERR_TIMED_OUT, {});
+}
+
+// ResolveHostAndOpenTCPSocket implementation.
+
+ResolveHostAndOpenTCPSocket::ResolveHostAndOpenTCPSocket(
+    base::WeakPtr<DirectSocketsServiceImpl> service,
+    blink::mojom::DirectSocketOptionsPtr options,
+    mojo::PendingReceiver<network::mojom::TCPConnectedSocket> receiver,
+    mojo::PendingRemote<network::mojom::SocketObserver> observer,
+    OpenTcpSocketCallback callback)
+    : ResolveHostAndOpenSocket(std::move(service), std::move(options)),
+      receiver_(std::move(receiver)),
+      observer_(std::move(observer)),
+      callback_(std::move(callback)) {}
+
+ResolveHostAndOpenTCPSocket::~ResolveHostAndOpenTCPSocket() = default;
+
+void ResolveHostAndOpenTCPSocket::OpenSocket(
+    int result,
+    const absl::optional<net::AddressList>& resolved_addresses) {
+  network::mojom::NetworkContext* network_context = nullptr;
+  if (service_) {
+    network_context = service_->GetNetworkContext();
+  }
+  if (!network_context) {
+    delete this;
+    return;
+  }
+
+  if (result != net::OK) {
+    std::move(callback_).Run(result, absl::nullopt, absl::nullopt,
+                             mojo::ScopedDataPipeConsumerHandle(),
+                             mojo::ScopedDataPipeProducerHandle());
+    delete this;
+    return;
+  }
+
+  DCHECK(resolved_addresses && !resolved_addresses->empty());
+  const absl::optional<net::IPEndPoint> local_addr = GetLocalAddr(*options_);
+
+  network::mojom::TCPConnectedSocketOptionsPtr tcp_connected_socket_options =
+      network::mojom::TCPConnectedSocketOptions::New();
+  if (options_->send_buffer_size > 0) {
+    tcp_connected_socket_options->send_buffer_size =
+        std::min(options_->send_buffer_size,
+                 DirectSocketsServiceImpl::GetMaxBufferSize());
+  }
+  if (options_->receive_buffer_size > 0) {
+    tcp_connected_socket_options->receive_buffer_size =
+        std::min(options_->receive_buffer_size,
+                 DirectSocketsServiceImpl::GetMaxBufferSize());
+  }
+  tcp_connected_socket_options->no_delay = options_->no_delay;
+  if (options_->keep_alive_options) {
+    // options_->keep_alive_options will be invalidated.
+    tcp_connected_socket_options->keep_alive_options =
+        std::move(options_->keep_alive_options);
+  }
+  // invalidate options_.
+  options_.reset();
+
+  network_context->CreateTCPConnectedSocket(
+      local_addr, *resolved_addresses, std::move(tcp_connected_socket_options),
+      DirectSocketsServiceImpl::MutableTrafficAnnotation(),
+      std::move(receiver_), std::move(observer_), std::move(callback_));
+  delete this;
+}
+
+// ResolveHostAndOpenUDPSocket implementation.
+
+ResolveHostAndOpenUDPSocket::ResolveHostAndOpenUDPSocket(
+    base::WeakPtr<DirectSocketsServiceImpl> service,
+    blink::mojom::DirectSocketOptionsPtr options,
+    mojo::PendingReceiver<blink::mojom::DirectUDPSocket> receiver,
+    mojo::PendingRemote<network::mojom::UDPSocketListener> listener,
+    OpenUdpSocketCallback callback)
+    : ResolveHostAndOpenSocket(std::move(service), std::move(options)),
+      receiver_(std::move(receiver)),
+      listener_(std::move(listener)),
+      callback_(std::move(callback)) {}
+
+ResolveHostAndOpenUDPSocket::~ResolveHostAndOpenUDPSocket() = default;
+
+void ResolveHostAndOpenUDPSocket::OpenSocket(
+    int result,
+    const absl::optional<net::AddressList>& resolved_addresses) {
+  network::mojom::NetworkContext* network_context = nullptr;
+  if (service_) {
+    network_context = service_->GetNetworkContext();
+  }
+  if (!network_context) {
+    delete this;
+    return;
+  }
+
+  if (result != net::OK) {
+    std::move(callback_).Run(result, absl::nullopt, absl::nullopt);
+    delete this;
+    return;
+  }
+
+  DCHECK(resolved_addresses && !resolved_addresses->empty());
+
+  network::mojom::UDPSocketOptionsPtr udp_socket_options =
+      network::mojom::UDPSocketOptions::New();
+  if (options_->send_buffer_size > 0) {
+    udp_socket_options->send_buffer_size =
+        std::min(options_->send_buffer_size,
+                 DirectSocketsServiceImpl::GetMaxBufferSize());
+  }
+  if (options_->receive_buffer_size > 0) {
+    udp_socket_options->receive_buffer_size =
+        std::min(options_->receive_buffer_size,
+                 DirectSocketsServiceImpl::GetMaxBufferSize());
+  }
+
+  net::IPEndPoint peer_addr = resolved_addresses->front();
+  auto direct_udp_socket = std::make_unique<DirectUDPSocketImpl>(
+      network_context, std::move(listener_));
+  direct_udp_socket->Connect(
+      peer_addr, std::move(udp_socket_options),
+      base::BindOnce(&ResolveHostAndOpenUDPSocket::OnUdpConnectCompleted,
+                     base::Unretained(this), peer_addr));
+  service_->AddDirectUDPSocketReceiver(std::move(direct_udp_socket),
+                                       std::move(receiver_));
+}
+
+void ResolveHostAndOpenUDPSocket::OnUdpConnectCompleted(
+    net::IPEndPoint peer_addr,
+    int result,
+    const absl::optional<net::IPEndPoint>& local_addr) {
+  std::move(callback_).Run(result, local_addr, peer_addr);
+  delete this;
+}
+
+}  // namespace content
\ No newline at end of file
diff --git a/content/browser/direct_sockets/resolve_host_and_open_socket.h b/content/browser/direct_sockets/resolve_host_and_open_socket.h
new file mode 100644
index 0000000..0b36731
--- /dev/null
+++ b/content/browser/direct_sockets/resolve_host_and_open_socket.h
@@ -0,0 +1,121 @@
+// 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_DIRECT_SOCKETS_RESOLVE_HOST_AND_OPEN_SOCKET_H_
+#define CONTENT_BROWSER_DIRECT_SOCKETS_RESOLVE_HOST_AND_OPEN_SOCKET_H_
+
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "net/base/address_list.h"
+#include "services/network/public/cpp/resolve_host_client_base.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+#include "third_party/blink/public/mojom/direct_sockets/direct_sockets.mojom.h"
+
+namespace content {
+
+class DirectSocketsServiceImpl;
+
+// Resolves the host/port pair provided in options and opens the requested
+// socket on success. For calls to https port (443) an additional cors check is
+// performed to ensure compliance. This class is self-owned: inheritors must
+// call "delete this" at some point in OpenSocket(...).
+class CONTENT_EXPORT ResolveHostAndOpenSocket
+    : public network::ResolveHostClientBase {
+ public:
+  ResolveHostAndOpenSocket(base::WeakPtr<DirectSocketsServiceImpl> service,
+                           blink::mojom::DirectSocketOptionsPtr options);
+
+  ~ResolveHostAndOpenSocket() override;
+
+  void Start();
+
+  static int GetHttpsPort();
+  static void SetHttpsPortForTesting(absl::optional<int> port);
+
+ protected:
+  void OnComplete(
+      int result,
+      const net::ResolveErrorInfo& resolve_error_info,
+      const absl::optional<net::AddressList>& resolved_addresses) override;
+
+  void PerformCORSCheck(const std::string& address,
+                        const net::IPEndPoint& resolved_address);
+
+  void OnCORSCheckComplete(std::unique_ptr<network::SimpleURLLoader> loader,
+                           net::IPEndPoint resolved_address,
+                           scoped_refptr<net::HttpResponseHeaders>);
+
+  virtual void OpenSocket(
+      int result,
+      const absl::optional<net::AddressList>& resolved_addresses) = 0;
+
+  base::WeakPtr<DirectSocketsServiceImpl> service_;
+  blink::mojom::DirectSocketOptionsPtr options_;
+
+  bool is_mdns_name_ = false;
+  bool is_raw_address_ = false;
+
+  mojo::Receiver<network::mojom::ResolveHostClient> receiver_{this};
+  mojo::Remote<network::mojom::HostResolver> resolver_;
+};
+
+using OpenTcpSocketCallback =
+    blink::mojom::DirectSocketsService::OpenTcpSocketCallback;
+
+// Overrides OpenSocket(...) to open a TCP connection.
+class ResolveHostAndOpenTCPSocket final : public ResolveHostAndOpenSocket {
+ public:
+  ResolveHostAndOpenTCPSocket(
+      base::WeakPtr<DirectSocketsServiceImpl> service,
+      blink::mojom::DirectSocketOptionsPtr options,
+      mojo::PendingReceiver<network::mojom::TCPConnectedSocket> receiver,
+      mojo::PendingRemote<network::mojom::SocketObserver> observer,
+      OpenTcpSocketCallback callback);
+
+  ~ResolveHostAndOpenTCPSocket() override;
+
+ private:
+  void OpenSocket(
+      int result,
+      const absl::optional<net::AddressList>& resolved_addresses) override;
+
+  mojo::PendingReceiver<network::mojom::TCPConnectedSocket> receiver_;
+  mojo::PendingRemote<network::mojom::SocketObserver> observer_;
+  OpenTcpSocketCallback callback_;
+};
+
+using OpenUdpSocketCallback =
+    blink::mojom::DirectSocketsService::OpenUdpSocketCallback;
+
+// Overrides OpenSocket(...) to open a UDP connection.
+class ResolveHostAndOpenUDPSocket final : public ResolveHostAndOpenSocket {
+ public:
+  ResolveHostAndOpenUDPSocket(
+      base::WeakPtr<DirectSocketsServiceImpl> service,
+      blink::mojom::DirectSocketOptionsPtr options,
+      mojo::PendingReceiver<blink::mojom::DirectUDPSocket> receiver,
+      mojo::PendingRemote<network::mojom::UDPSocketListener> listener,
+      OpenUdpSocketCallback callback);
+
+  ~ResolveHostAndOpenUDPSocket() override;
+
+ private:
+  void OpenSocket(
+      int result,
+      const absl::optional<net::AddressList>& resolved_addresses) override;
+
+  void OnUdpConnectCompleted(net::IPEndPoint peer_addr,
+                             int result,
+                             const absl::optional<net::IPEndPoint>& local_addr);
+
+  mojo::PendingReceiver<blink::mojom::DirectUDPSocket> receiver_;
+  mojo::PendingRemote<network::mojom::UDPSocketListener> listener_;
+  OpenUdpSocketCallback callback_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_DIRECT_SOCKETS_RESOLVE_HOST_AND_OPEN_SOCKET_H_
\ No newline at end of file
diff --git a/content/browser/interest_group/auction_runner_unittest.cc b/content/browser/interest_group/auction_runner_unittest.cc
index 0cdc7b0..8065d2f8 100644
--- a/content/browser/interest_group/auction_runner_unittest.cc
+++ b/content/browser/interest_group/auction_runner_unittest.cc
@@ -360,7 +360,12 @@
       if (debugWinReportUrl)
         forDebuggingOnly.reportAdAuctionWin(debugWinReportUrl + bid);
 
-      return computeScore(bid);
+      return {desirability: computeScore(bid),
+              // Only allow a component auction when the passed in ad is from
+              // one.
+              allowComponentAuction:
+                  browserSignals.topLevelSeller !== undefined ||
+                  browserSignals.componentSeller !== undefined}
     }
 
     function reportResult(auctionConfig, browserSignals) {
@@ -2324,8 +2329,8 @@
   const std::string kSellerScript = R"(
     function scoreAd(adMetadata, bid, auctionConfig, browserSignals) {
       if (auctionConfig.seller == "https://adstuff.publisher1.com")
-        return 20 + bid;
-      return 10 + bid;
+        return {desirability: 20 + bid, allowComponentAuction: true};
+      return {desirability: 10 + bid, allowComponentAuction: true};
     }
 
     function reportResult(auctionConfig, browserSignals) {
@@ -5572,7 +5577,10 @@
       "https://top-seller-loss-reporting.test/" + bid);
   forDebuggingOnly.reportAdAuctionWin(
       "https://top-seller-win-reporting.test/" + bid);
-  return 0;
+  // While not setting `allowComponentAuction` will also reject the ad, it
+  // also prevents loss reports and adds an error message, so need to set
+  // it to true.
+  return {desirability: 0, allowComponentAuction: true};
 }
   )");
 
diff --git a/content/browser/interest_group/interest_group_browsertest.cc b/content/browser/interest_group/interest_group_browsertest.cc
index 2d90343..eed8c283 100644
--- a/content/browser/interest_group/interest_group_browsertest.cc
+++ b/content/browser/interest_group/interest_group_browsertest.cc
@@ -3493,13 +3493,17 @@
       R"({
         seller: $1,
         decisionLogicUrl: $2,
+        // Signal to the top-level seller to allow participation in a component
+        // auction.
+        auctionSignals: "sellerAllowsComponentAuction",
         componentAuctions: [{
           seller: $1,
           decisionLogicUrl: $2,
           interestGroupBuyers: [$1],
-          // Signal to the bidder to allow participation in a component
-          // auction.
-          auctionSignals: "bidderAllowsComponentAuction"
+          // Signal to the bidder and component seller to allow participation in
+          // a component auction.
+          auctionSignals: "bidderAllowsComponentAuction,"+
+                          "sellerAllowsComponentAuction"
         }]
       })",
       test_origin,
@@ -3527,13 +3531,87 @@
       R"({
         seller: $1,
         decisionLogicUrl: $2,
+        // Signal to the top-level seller to allow participation in a component
+        // auction.
+        auctionSignals: "sellerAllowsComponentAuction",
         componentAuctions: [{
           seller: $1,
           decisionLogicUrl: $2,
           interestGroupBuyers: [$1],
-          // Since this does not include "bidderAllowsComponentAuction", the
-          // bidder will refuse to participate in component auctions.
-          auctionSignals: "foo"
+          // Signal to the component seller to allow participation in a
+          // component auction.
+          auctionSignals: "sellerAllowsComponentAuction"
+        }]
+      })",
+      test_origin,
+      https_server_->GetURL("a.test", "/interest_group/decision_logic.js"));
+  EXPECT_EQ(nullptr, RunAuctionAndWait(auction_config));
+}
+
+// Test the case of a component argument in the case the top-level seller
+// refuses to participate in component auctions.
+IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
+                       ComponentAuctionTopLevelSellerRefuses) {
+  GURL test_url = https_server_->GetURL("a.test", "/page_with_iframe.html");
+  ASSERT_TRUE(NavigateToURL(shell(), test_url));
+  url::Origin test_origin = url::Origin::Create(test_url);
+  GURL ad_url = https_server_->GetURL("c.test", "/echo?render_cars");
+
+  EXPECT_TRUE(JoinInterestGroupAndWaitInJs(
+      /*owner=*/test_origin,
+      /*name=*/"cars",
+      /*bidding_url=*/
+      https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
+      /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}}));
+
+  std::string auction_config = JsReplace(
+      R"({
+        seller: $1,
+        decisionLogicUrl: $2,
+        componentAuctions: [{
+          seller: $1,
+          decisionLogicUrl: $2,
+          interestGroupBuyers: [$1],
+          // Signal to the bidder and component seller to allow participation in
+          // a component auction.
+          auctionSignals: "bidderAllowsComponentAuction,"+
+                          "sellerAllowsComponentAuction"
+        }]
+      })",
+      test_origin,
+      https_server_->GetURL("a.test", "/interest_group/decision_logic.js"));
+  EXPECT_EQ(nullptr, RunAuctionAndWait(auction_config));
+}
+
+// Test the case of a component argument in the case a component seller refuses
+// to participate in component auctions.
+IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
+                       ComponentAuctionComponentSellerRefuses) {
+  GURL test_url = https_server_->GetURL("a.test", "/page_with_iframe.html");
+  ASSERT_TRUE(NavigateToURL(shell(), test_url));
+  url::Origin test_origin = url::Origin::Create(test_url);
+  GURL ad_url = https_server_->GetURL("c.test", "/echo?render_cars");
+
+  EXPECT_TRUE(JoinInterestGroupAndWaitInJs(
+      /*owner=*/test_origin,
+      /*name=*/"cars",
+      /*bidding_url=*/
+      https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
+      /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}}));
+
+  std::string auction_config = JsReplace(
+      R"({
+        seller: $1,
+        decisionLogicUrl: $2,
+        // Signal to the top-level seller to allow participation in a component
+        // auction.
+        auctionSignals: "sellerAllowsComponentAuction",
+        componentAuctions: [{
+          seller: $1,
+          decisionLogicUrl: $2,
+          interestGroupBuyers: [$1],
+          // Signal to the bidder to allow participation in a component auction.
+          auctionSignals: "bidderAllowsComponentAuction"
         }]
       })",
       test_origin,
diff --git a/content/browser/renderer_host/render_frame_host_android.cc b/content/browser/renderer_host/render_frame_host_android.cc
index f5830d7f..8d76d04 100644
--- a/content/browser/renderer_host/render_frame_host_android.cc
+++ b/content/browser/renderer_host/render_frame_host_android.cc
@@ -183,7 +183,7 @@
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>&,
     const base::android::JavaParamRef<jstring>& interface_name,
-    jlong message_pipe_raw_handle) const {
+    jint message_pipe_raw_handle) const {
   DCHECK(render_frame_host_->IsRenderFrameCreated());
   render_frame_host_->GetRemoteInterfaces()->GetInterfaceByName(
       ConvertJavaStringToUTF8(env, interface_name),
diff --git a/content/browser/renderer_host/render_frame_host_android.h b/content/browser/renderer_host/render_frame_host_android.h
index 55412020..f4f1525 100644
--- a/content/browser/renderer_host/render_frame_host_android.h
+++ b/content/browser/renderer_host/render_frame_host_android.h
@@ -73,7 +73,7 @@
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>&,
       const base::android::JavaParamRef<jstring>& interface_name,
-      jlong message_pipe_handle) const;
+      jint message_pipe_handle) const;
 
   void TerminateRendererDueToBadMessage(
       JNIEnv* env,
diff --git a/content/browser/resources/quota/quota_internals.css b/content/browser/resources/quota/quota_internals.css
index 14b40aa..332139b 100644
--- a/content/browser/resources/quota/quota_internals.css
+++ b/content/browser/resources/quota/quota_internals.css
@@ -2,62 +2,9 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file. */
 
-* {
-  box-sizing: border-box;
-}
-
-html {
-  height: 100%;
-}
-
-body {
-  color: rgb(48, 57, 66);
-  display: flex;
-  flex-direction: column;
-  font-family: Roboto, sans-serif;
-  font-size: 13px;
-  height: 100%;
-  margin: 15px;
-  overflow: auto;
-}
-
-#listeners-tbody {
-  margin: auto;
-  text-align: center;
-}
-
-#eviction-tbody {
-  margin: auto;
-  text-align: center;
-}
-
-hr {
-  border-top: 1px solid rgb(48, 57, 66);
-  width: 100%;
-}
-
-.content {
-  background-color: #fbfbfb;
-  border: 1px solid #cecece;
-  border-radius: 3px;
-  line-height: 1.5;
-  overflow-x: scroll;
-  padding: 19px;
-}
-
-table {
-  border: 0;
-  border-collapse: collapse;
-}
-
-table tr {
-  border-top-color: rgba(0,0,0,.12);
-  border-top-style: solid;
-  border-top-width: 1px;
-}
-
-table td,
-table th {
-  padding-inline-end: 16px;
-  padding-inline-start: 16px;
-}
\ No newline at end of file
+ th,
+ td {
+   padding-inline-end: 0.5em;
+   padding-inline-start: 0.5em;
+   text-align: center;
+ }
\ No newline at end of file
diff --git a/content/browser/resources/quota/quota_internals.html b/content/browser/resources/quota/quota_internals.html
index 78366ba..115478a 100644
--- a/content/browser/resources/quota/quota_internals.html
+++ b/content/browser/resources/quota/quota_internals.html
@@ -2,62 +2,89 @@
 <html lang="en" dir="ltr">
 <head>
   <meta charset="utf-8">
-  <title>Quota Internals 2</title>
+  <title>Quota Internals</title>
   <meta name="viewport" content="width=device-width">
-  <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
   <link rel="stylesheet" href="chrome://resources/css/roboto.css">
+  <link rel="stylesheet" href="chrome://resources/css/tabs.css">
+  <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
+  <link rel="stylesheet" href="chrome://resources/css/tree.css">
   <link rel="stylesheet" href="quota_internals.css">
   <script type="module" src="quota_internals.js" defer></script>
 </head>
-<body>
-  <h1>Quota Internals 2</h1>
+  <body>
+    <tabbox>
+      <tabs class="new-style-tabs">
+        <tab id="summary-tab">Summary</tab>
+        <tab id="usage-tab">Usage &amp; Quota</tab>
+      </tabs>
+      <tabpanels class="new-style-tabs">
+        <tabpanel id="summary-tabpanel" selected="selected">
+          <!-- Summary -->
+          <h2>Summary</h2>
+          <h3>Disk Availability</h3>
+          <table>
+            <thead>
+              <th>Total Space</th>
+              <th>Available Space</th>
+            </thead>
+            <tbody id="listeners-tbody"></tbody>
+          </table>
 
-  <h2>Disk Availability</h2>
-  <table>
-    <thead>
-      <th>Total Space</th>
-      <th>Available Space</th>
-    </thead>
-    <tbody id="listeners-tbody"></tbody>
-  </table>
+          <h3>Eviction Statistics</h3>
+          <table>
+            <thead>
+              <th>Errors on Getting Usage and Quota</th>
+              <th>Evicted Buckets</th>
+              <th>Eviction Rounds</th>
+              <th>Skipped Eviction Rounds</th>
+            </thead>
+            <tbody id="eviction-tbody"></tbody>
+          </table>
 
-  <h2>Eviction Statistics</h2>
-  <table>
-    <thead>
-      <th>Errors on Getting Usage and Quota</th>
-      <th>Evicted Buckets</th>
-      <th>Eviction Rounds</th>
-      <th>Skipped Eviction Rounds</th>
-    </thead>
-    <tbody id="eviction-tbody"></tbody>
-  </table>
+          <h2>Test Storage Pressure Behavior</h2>
+            <form>
+              <label>Origin to test: </label>
+              <input type="url" name="origin-to-test" id="origin-to-test"
+                  placeholder="https://example.com" pattern="https://.*"
+                  size="30" required>
+              <button name="trigger-notification" id="trigger-notification"
+                  type="submit">
+                Trigger Storage Pressure Notification
+              </button>
+            </form>
+        </tabpanel>
 
-  <template id="listener-row">
-    <tr>
-      <td class="total-space"></td>
-      <td class="available-space"></td>
-    </tr>
-  </template>
-  <template id="eviction-row">
-    <tr>
-      <td class="errors-on-getting-usage-and-quota"></td>
-      <td class="evicted-buckets"></td>
-      <td class="eviction-rounds"></td>
-      <td class="skipped-eviction-rounds"></td>
-    </tr>
-  </template>
+        <tabpanel id="usage-tabpanel">
+          <!-- Usage and Quota -->
+          <h2>Host Usage Data</h2>
+          <div id="tree-view-container">
+            <button id="refresh-button">Refresh</button>
+            <tree id="tree-view"></tree>
+          </div>
+          <table>
+            <thead></thead>
+            <tbody id="tree-item-description"></tbody>
+          </table>
+        </tabpanel>
+      </tabpanels>
+    </tabbox>
 
-  <h2>Test Storage Pressure Behavior</h2>
-  <form>
-    <label>Origin to test: </label>
-    <input type="url" name="origin-to-test" id="origin-to-test"
-        placeholder="https://example.com" pattern="https://.*"
-        size="30"required>
-    <button name="trigger-notification" id="trigger-notification" type="submit">
-      Trigger Storage Pressure Notification
-    </button>
-  </form>
-</body>
+    <template id="listener-row">
+      <tr>
+        <td class="total-space"></td>
+        <td class="available-space"></td>
+      </tr>
+    </template>
+    <template id="eviction-row">
+      <tr>
+        <td class="errors-on-getting-usage-and-quota"></td>
+        <td class="evicted-buckets"></td>
+        <td class="eviction-rounds"></td>
+        <td class="skipped-eviction-rounds"></td>
+      </tr>
+    </template>
+
+  </body>
 </html>
 
 
diff --git a/content/browser/resources/quota/quota_internals.ts b/content/browser/resources/quota/quota_internals.ts
index faa25bf..cc546efc 100644
--- a/content/browser/resources/quota/quota_internals.ts
+++ b/content/browser/resources/quota/quota_internals.ts
@@ -59,4 +59,16 @@
   renderEvictionStats();
   document.body.querySelector('#trigger-notification')!.addEventListener(
       'click', () => getProxy().simulateStoragePressure());
+
+  document.body.querySelector('#summary-tab')!.addEventListener('click', () => {
+    document.body.querySelector('#usage-tabpanel')!.removeAttribute('selected');
+    document.body.querySelector('#summary-tabpanel')!.setAttribute(
+        'selected', 'selected');
+  });
+
+  document.querySelector('#usage-tab')!.addEventListener('click', () => {
+    document.querySelector('#summary-tabpanel')!.removeAttribute('selected');
+    document.querySelector('#usage-tabpanel')!.setAttribute(
+        'selected', 'selected');
+  });
 });
\ No newline at end of file
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc
index 08c725e..8068d06 100644
--- a/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -6166,7 +6166,7 @@
 // On Mac and Android, the reported menu coordinates are relative to the
 // OOPIF, and its screen position is computed later, so this test isn't
 // relevant on those platforms.
-#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_MAC)
+#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_CHROMECAST)
 IN_PROC_BROWSER_TEST_F(SitePerProcessHitTestBrowserTest,
                        ScrolledNestedPopupMenuTest) {
   GURL main_url(embedded_test_server()->GetURL(
diff --git a/content/browser/ssl/OWNERS b/content/browser/ssl/OWNERS
index dda20f8..b601c19 100644
--- a/content/browser/ssl/OWNERS
+++ b/content/browser/ssl/OWNERS
@@ -1,3 +1,2 @@
 agl@chromium.org
 estark@chromium.org
-rsleevi@chromium.org
diff --git a/content/public/android/java/src/org/chromium/content/browser/AppWebMessagePortDescriptor.java b/content/public/android/java/src/org/chromium/content/browser/AppWebMessagePortDescriptor.java
index f6cf3778..a17e872b 100644
--- a/content/public/android/java/src/org/chromium/content/browser/AppWebMessagePortDescriptor.java
+++ b/content/public/android/java/src/org/chromium/content/browser/AppWebMessagePortDescriptor.java
@@ -45,7 +45,7 @@
  */
 public class AppWebMessagePortDescriptor implements ConnectionErrorHandler {
     private static final long NATIVE_NULL = 0;
-    private static final long INVALID_NATIVE_MOJO_HANDLE = 0; // Mirrors CoreImpl.INVALID_HANDLE.
+    private static final int INVALID_NATIVE_MOJO_HANDLE = 0; // Mirrors CoreImpl.INVALID_HANDLE.
     private static final long INVALID_SEQUENCE_NUMBER = 0;
 
     /** Handle to the native blink::MessagePortDescriptor associated with this object. */
@@ -111,7 +111,7 @@
     Connector entangleWithConnector() {
         ensureNativeMessagePortDescriptorExists();
         assert mConnector == null : "handle already taken";
-        long nativeHandle = AppWebMessagePortDescriptorJni.get().takeHandleToEntangle(
+        int nativeHandle = AppWebMessagePortDescriptorJni.get().takeHandleToEntangle(
                 mNativeMessagePortDescriptor);
         assert nativeHandle
                 != INVALID_NATIVE_MOJO_HANDLE : "native object returned an invalid handle";
@@ -177,7 +177,7 @@
                 AppWebMessagePortDescriptorJni.get().passSerialized(mNativeMessagePortDescriptor);
         assert serialized.length == 4 : "native passSerialized returned an invalid value";
 
-        long nativeHandle = serialized[0];
+        int nativeHandle = (int) serialized[0];
         long idLow = serialized[1];
         long idHigh = serialized[2];
         long sequenceNumber = serialized[3];
@@ -254,7 +254,7 @@
     /**
      * Wraps the provided native handle as MessagePipeHandle.
      */
-    MessagePipeHandle wrapNativeHandle(long nativeHandle) {
+    MessagePipeHandle wrapNativeHandle(int nativeHandle) {
         return CoreImpl.getInstance().acquireNativeHandle(nativeHandle).toMessagePipeHandle();
     }
 
@@ -282,7 +282,7 @@
 
     private void disentangleImpl() {
         MessagePipeHandle handle = mConnector.passHandle();
-        long nativeHandle = handle.releaseNativeHandle();
+        int nativeHandle = handle.releaseNativeHandle();
         // An invalid handle should be returned iff the connection errored.
         if (mConnectorErrored) {
             assert nativeHandle
@@ -324,14 +324,14 @@
     @NativeMethods
     interface Native {
         long[] createPair();
-        long create(long mojoHandle, long idLow, long idHigh, long sequenceNumber);
+        long create(int nativeHandle, long idLow, long idHigh, long sequenceNumber);
         // Deliberately do not use nativeObjectType naming to avoid automatic typecasting and
         // member function dispatch; these need to be routed to static functions.
 
         // Takes the handle from the native object for entangling with a mojo.Connector.
-        long takeHandleToEntangle(long blinkMessagePortDescriptor);
+        int takeHandleToEntangle(long blinkMessagePortDescriptor);
         // Returns the handle previously taken via "takeHandleToEntangle".
-        void giveDisentangledHandle(long blinkMessagePortDescriptor, long nativeHandle);
+        void giveDisentangledHandle(long blinkMessagePortDescriptor, int nativeHandle);
         // Indicates that the entangled error experienced a connection error. The descriptor must be
         // entangled at this point.
         void onConnectionError(long blinkMessagePortDescriptor);
diff --git a/content/public/android/java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java b/content/public/android/java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java
index 1c857b8..97330d87 100644
--- a/content/public/android/java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java
@@ -23,7 +23,7 @@
     private static boolean sHasRegisteredRegistrars;
 
     @CalledByNative
-    static void createInterfaceRegistry(long nativeHandle) {
+    static void createInterfaceRegistry(int nativeHandle) {
         ensureSingletonRegistrarsAreRegistered();
 
         InterfaceRegistry registry = InterfaceRegistry.create(
@@ -32,14 +32,14 @@
     }
 
     @CalledByNative
-    static void createInterfaceRegistryOnIOThread(long nativeHandle) {
+    static void createInterfaceRegistryOnIOThread(int nativeHandle) {
         InterfaceRegistry registry = InterfaceRegistry.create(
                 CoreImpl.getInstance().acquireNativeHandle(nativeHandle).toMessagePipeHandle());
         registerInterfacesOnIOThread(registry);
     }
 
     @CalledByNative
-    static void createInterfaceRegistryForWebContents(long nativeHandle, WebContents webContents) {
+    static void createInterfaceRegistryForWebContents(int nativeHandle, WebContents webContents) {
         ensureSingletonRegistrarsAreRegistered();
 
         InterfaceRegistry registry = InterfaceRegistry.create(
@@ -49,7 +49,7 @@
 
     @CalledByNative
     static void createInterfaceRegistryForRenderFrameHost(
-            long nativeHandle, RenderFrameHost renderFrameHost) {
+            int nativeHandle, RenderFrameHost renderFrameHost) {
         ensureSingletonRegistrarsAreRegistered();
 
         InterfaceRegistry registry = InterfaceRegistry.create(
diff --git a/content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogOverlayImpl.java b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogOverlayImpl.java
index 4cc64b1..be596776 100644
--- a/content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogOverlayImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogOverlayImpl.java
@@ -297,7 +297,7 @@
         // removed once Android O is no longer supported.
         final AndroidOverlayClient.Proxy proxy = (AndroidOverlayClient.Proxy) client;
         final MessagePipeHandle handle = proxy.getProxyHandler().passHandle();
-        final long nativeHandle = handle.releaseNativeHandle();
+        final int nativeHandle = handle.releaseNativeHandle();
         DialogOverlayImplJni.get().notifyDestroyedSynchronously(nativeHandle);
     }
 
@@ -360,6 +360,6 @@
          * @param version Mojo interface version.
          * @return none, but the message pipe is closed.
          */
-        void notifyDestroyedSynchronously(long messagePipeHandle);
+        void notifyDestroyedSynchronously(int messagePipeHandle);
     }
 }
diff --git a/content/public/android/java/src/org/chromium/content/browser/framehost/RenderFrameHostImpl.java b/content/public/android/java/src/org/chromium/content/browser/framehost/RenderFrameHostImpl.java
index 869a576..8d2d036 100644
--- a/content/public/android/java/src/org/chromium/content/browser/framehost/RenderFrameHostImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/framehost/RenderFrameHostImpl.java
@@ -246,7 +246,7 @@
                 long nativeRenderFrameHostAndroid, RenderFrameHostImpl caller);
         boolean isRenderFrameCreated(long nativeRenderFrameHostAndroid, RenderFrameHostImpl caller);
         void getInterfaceToRendererFrame(long nativeRenderFrameHostAndroid,
-                RenderFrameHostImpl caller, String interfacename, long messagePipeRawHandle);
+                RenderFrameHostImpl caller, String interfacename, int messagePipeRawHandle);
         void terminateRendererDueToBadMessage(
                 long nativeRenderFrameHostAndroid, RenderFrameHostImpl caller, int reason);
         boolean isProcessBlocked(long nativeRenderFrameHostAndroid, RenderFrameHostImpl caller);
diff --git a/content/services/auction_worklet/seller_worklet.cc b/content/services/auction_worklet/seller_worklet.cc
index e47320dc..3a3eb38 100644
--- a/content/services/auction_worklet/seller_worklet.cc
+++ b/content/services/auction_worklet/seller_worklet.cc
@@ -455,7 +455,6 @@
   args.push_back(browser_signals);
 
   v8::Local<v8::Value> score_ad_result;
-  double score;
   std::vector<std::string> errors_out;
   v8_helper_->MaybeTriggerInstrumentationBreakpoint(
       *debug_id_, "beforeSellerWorkletScoringStart");
@@ -471,6 +470,8 @@
     return;
   }
 
+  double score;
+  bool allow_component_auction = false;
   // Try to parse the result as a number. On success, it's the desirability
   // score.
   if (!gin::ConvertFromV8(isolate, score_ad_result, &score)) {
@@ -500,6 +501,25 @@
           /*debug_win_report_url=*/absl::nullopt, std::move(errors_out));
       return;
     }
+
+    if (!result_dict.Get("allowComponentAuction", &allow_component_auction))
+      allow_component_auction = false;
+  }
+
+  // Fail if `allow_component_auction` is false and this is a component seller
+  // or a top-level seller scoring a bid from a component auction -
+  // `browser_signals_other_seller` is non-null in only those two cases.
+  if (browser_signals_other_seller && !allow_component_auction) {
+    errors_out.push_back(base::StrCat(
+        {decision_logic_url_.spec(),
+         " scoreAd() return value does not have allowComponentAuction set to "
+         "true. Ad dropped from component auction."}));
+    PostScoreAdCallbackToUserThread(
+        std::move(callback), /*score=*/0,
+        /*scoring_signals_data_version=*/absl::nullopt,
+        /*debug_loss_report_url=*/absl::nullopt,
+        /*debug_win_report_url=*/absl::nullopt, std::move(errors_out));
+    return;
   }
 
   // Fail if the score is invalid.
diff --git a/content/services/auction_worklet/seller_worklet_unittest.cc b/content/services/auction_worklet/seller_worklet_unittest.cc
index 565dcfe..d8a6a0f8 100644
--- a/content/services/auction_worklet/seller_worklet_unittest.cc
+++ b/content/services/auction_worklet/seller_worklet_unittest.cc
@@ -395,15 +395,12 @@
   }
 
   // Loads and runs a report_result() script, expecting the supplied result.
-  // Runs ScoreAd() first, expecting a score of 1, since that's required before
-  // calling ReportResult.
   void RunReportResultExpectingResult(
       const absl::optional<std::string>& expected_signals_for_winner,
       const absl::optional<GURL>& expected_report_url,
       const std::vector<std::string>& expected_errors =
           std::vector<std::string>()) {
     auto seller_worklet = CreateWorklet();
-    RunScoreAdExpectingResultOnWorklet(seller_worklet.get(), 1);
     ASSERT_TRUE(seller_worklet);
 
     base::RunLoop run_loop;
@@ -603,6 +600,70 @@
       {"https://url.test/:5 Uncaught ReferenceError: shrimp is not defined."});
 }
 
+TEST_F(SellerWorkletTest, ScoreAdAllowComponentAuction) {
+  // Expected errors vector on failure.
+  const std::vector<std::string> kExpectedErrorsOnFailure{
+      R"(https://url.test/ scoreAd() return value does not have )"
+      R"(allowComponentAuction set to true. Ad dropped from component )"
+      R"(auction.)"};
+
+  // With a null `browser_signals_other_seller_`, returning a raw score is
+  // allowed, and if returning an object, `allowComponentAuction` doesn't
+  // matter.
+  browser_signals_other_seller_.reset();
+  RunScoreAdWithReturnValueExpectingResult("1", 1);
+  RunScoreAdWithReturnValueExpectingResult(
+      "{desirability:1, allowComponentAuction:true}", 1);
+  RunScoreAdWithReturnValueExpectingResult(
+      "{desirability:1, allowComponentAuction:false}", 1);
+  RunScoreAdWithReturnValueExpectingResult("{desirability:1}", 1);
+  RunScoreAdWithReturnValueExpectingResult(
+      "{desirability:1, allowComponentAuction:1}", 1);
+  RunScoreAdWithReturnValueExpectingResult(
+      "{desirability:1, allowComponentAuction:0}", 1);
+  RunScoreAdWithReturnValueExpectingResult(
+      "{desirability:1, allowComponentAuction:[32]}", 1);
+
+  // With a non-null `browser_signals_other_seller_`, an object must be
+  // returned, and `allowComponentAuction` must be true.
+
+  browser_signals_other_seller_ =
+      mojom::ComponentAuctionOtherSeller::NewTopLevelSeller(
+          url::Origin::Create(GURL("https://top.seller.test")));
+  RunScoreAdWithReturnValueExpectingResult("1", 0, kExpectedErrorsOnFailure);
+  RunScoreAdWithReturnValueExpectingResult(
+      "{desirability:1, allowComponentAuction:true}", 1);
+  RunScoreAdWithReturnValueExpectingResult(
+      "{desirability:1, allowComponentAuction:false}", 0,
+      kExpectedErrorsOnFailure);
+  RunScoreAdWithReturnValueExpectingResult("{desirability:1}", 0,
+                                           kExpectedErrorsOnFailure);
+  RunScoreAdWithReturnValueExpectingResult(
+      "{desirability:1, allowComponentAuction:1}", 1);
+  RunScoreAdWithReturnValueExpectingResult(
+      "{desirability:1, allowComponentAuction:0}", 0, kExpectedErrorsOnFailure);
+  RunScoreAdWithReturnValueExpectingResult(
+      "{desirability:1, allowComponentAuction:[32]}", 1);
+
+  browser_signals_other_seller_ =
+      mojom::ComponentAuctionOtherSeller::NewComponentSeller(
+          url::Origin::Create(GURL("https://component.seller.test")));
+  RunScoreAdWithReturnValueExpectingResult("1", 0, kExpectedErrorsOnFailure);
+  RunScoreAdWithReturnValueExpectingResult(
+      "{desirability:1, allowComponentAuction:true}", 1);
+  RunScoreAdWithReturnValueExpectingResult(
+      "{desirability:1, allowComponentAuction:false}", 0,
+      kExpectedErrorsOnFailure);
+  RunScoreAdWithReturnValueExpectingResult("{desirability:1}", 0,
+                                           kExpectedErrorsOnFailure);
+  RunScoreAdWithReturnValueExpectingResult(
+      "{desirability:1, allowComponentAuction:1}", 1);
+  RunScoreAdWithReturnValueExpectingResult(
+      "{desirability:1, allowComponentAuction:0}", 0, kExpectedErrorsOnFailure);
+  RunScoreAdWithReturnValueExpectingResult(
+      "{desirability:1, allowComponentAuction:[32]}", 1);
+}
+
 TEST_F(SellerWorkletTest, ScoreAdDateNotAvailable) {
   RunScoreAdWithReturnValueExpectingResult(
       "Date.parse(Date().toString())", 0,
@@ -633,40 +694,60 @@
 }
 
 TEST_F(SellerWorkletTest, ScoreAdTopLevelSeller) {
+  // `topLevelSeller` should be empty when a top-level seller is scoring a bid
+  // from its own auction.
   browser_signals_other_seller_.reset();
   RunScoreAdWithReturnValueExpectingResult(
       R"("topLevelSeller" in browserSignals ? 0 : 1)", 1);
 
+  // `topLevelSeller` should be set when a top-level seller is scoring a bid
+  // from a component auction. Must set `allowComponentAuction` to true for any
+  // value to be returned.
   browser_signals_other_seller_ =
       mojom::ComponentAuctionOtherSeller::NewTopLevelSeller(
           url::Origin::Create(GURL("https://top.seller.test")));
   RunScoreAdWithReturnValueExpectingResult(
-      R"(browserSignals.topLevelSeller === "https://top.seller.test" ? 2 : 0)",
+      R"(browserSignals.topLevelSeller === "https://top.seller.test" ?
+             {desirability: 2, allowComponentAuction: true} : 0)",
       2);
 
+  // `topLevelSeller` should be empty when a component seller is scoring a bid.
+  // Must set `allowComponentAuction` to true for any value to be returned.
   browser_signals_other_seller_ =
       mojom::ComponentAuctionOtherSeller::NewComponentSeller(
           url::Origin::Create(GURL("https://component.test")));
   RunScoreAdWithReturnValueExpectingResult(
-      R"("topLevelSeller" in browserSignals ? 0 : 3)", 3);
+      R"("topLevelSeller" in browserSignals ?
+             0 : {desirability: 3, allowComponentAuction: true})",
+      3);
 }
 
 TEST_F(SellerWorkletTest, ScoreAdComponentSeller) {
+  // `componentSeller` should be empty when a top-level seller is scoring a bid
+  // from its own auction.
   browser_signals_other_seller_.reset();
   RunScoreAdWithReturnValueExpectingResult(
       R"("componentSeller" in browserSignals ? 0 : 1)", 1);
 
+  // `componentSeller` should be empty when a top-level seller is scoring a bid
+  // from a component auction. Must set `allowComponentAuction` to true for any
+  // value to be returned.
   browser_signals_other_seller_ =
       mojom::ComponentAuctionOtherSeller::NewTopLevelSeller(
           url::Origin::Create(GURL("https://top.seller.test")));
   RunScoreAdWithReturnValueExpectingResult(
-      R"("componentSeller" in browserSignals ? 0 : 2)", 2);
+      R"("componentSeller" in browserSignals ?
+             0 : {desirability: 2, allowComponentAuction: true})",
+      2);
 
+  // `componentSeller` should be set when a component seller is scoring a bid.
+  // Must set `allowComponentAuction` to true for any value to be returned.
   browser_signals_other_seller_ =
       mojom::ComponentAuctionOtherSeller::NewComponentSeller(
           url::Origin::Create(GURL("https://component.test")));
   RunScoreAdWithReturnValueExpectingResult(
-      R"(browserSignals.componentSeller === "https://component.test" ? 3 : 0)",
+      R"(browserSignals.componentSeller === "https://component.test" ?
+             {desirability: 3, allowComponentAuction: true} : 0)",
       3);
 }
 
diff --git a/content/test/data/interest_group/component_auction_component_decision_argument_validator.js b/content/test/data/interest_group/component_auction_component_decision_argument_validator.js
index 476724d..ccaa538 100644
--- a/content/test/data/interest_group/component_auction_component_decision_argument_validator.js
+++ b/content/test/data/interest_group/component_auction_component_decision_argument_validator.js
@@ -9,7 +9,7 @@
   validateAuctionConfig(auctionConfig);
   validateTrustedScoringSignals(trustedScoringSignals);
   validateBrowserSignals(browserSignals, /*isScoreAd=*/true);
-  return 13;
+  return {desirability: 13, allowComponentAuction: true};
 }
 
 function reportResult(auctionConfig, browserSignals) {
diff --git a/content/test/data/interest_group/component_auction_top_level_decision_argument_validator.js b/content/test/data/interest_group/component_auction_top_level_decision_argument_validator.js
index 93dbdc7..3e231559 100644
--- a/content/test/data/interest_group/component_auction_top_level_decision_argument_validator.js
+++ b/content/test/data/interest_group/component_auction_top_level_decision_argument_validator.js
@@ -13,7 +13,7 @@
   if (browserSignals.biddingDurationMsec < 0)
     throw 'Wrong biddingDurationMsec ' + browserSignals.biddingDurationMsec;
 
-  return 37;
+  return {desirability: 37, allowComponentAuction: true};
 }
 
 function reportResult(auctionConfig, browserSignals) {
diff --git a/content/test/data/interest_group/decision_logic.js b/content/test/data/interest_group/decision_logic.js
index 975d5c1..01f743fc 100644
--- a/content/test/data/interest_group/decision_logic.js
+++ b/content/test/data/interest_group/decision_logic.js
@@ -2,13 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-function scoreAd(
-  adMetadata, bid, auctionConfig, trustedScoringSignals, browserSignals) {
-  return bid;
+function scoreAd(adMetadata, bid, auctionConfig, trustedScoringSignals,
+                 browserSignals) {
+  // `auctionSignals` controls whether or not component auctions are allowed.
+  let allowComponentAuction =
+      typeof auctionConfig.auctionSignals === 'string' &&
+      auctionConfig.auctionSignals.includes('sellerAllowsComponentAuction');
+  return {desirability: bid,
+          allowComponentAuction:allowComponentAuction};
 }
 
-function reportResult(
-  auctionConfig, browserSignals) {
+function reportResult(auctionConfig, browserSignals) {
   sendReportTo(auctionConfig.seller + '/echoall?report_seller');
   return {
     'success': true,
diff --git a/crypto/OWNERS b/crypto/OWNERS
index c1da9e3..d9697bd 100644
--- a/crypto/OWNERS
+++ b/crypto/OWNERS
@@ -2,4 +2,3 @@
 agl@chromium.org
 davidben@chromium.org
 mattm@chromium.org
-rsleevi@chromium.org
diff --git a/device/vr/android/arcore/arcore_gl.cc b/device/vr/android/arcore/arcore_gl.cc
index ea32ac3..07016fb 100644
--- a/device/vr/android/arcore/arcore_gl.cc
+++ b/device/vr/android/arcore/arcore_gl.cc
@@ -438,7 +438,7 @@
   gl::init::DisableANGLE();
 
   if (gl::GetGLImplementation() == gl::kGLImplementationNone &&
-      !gl::init::InitializeGLOneOff()) {
+      !gl::init::InitializeGLOneOff(/*system_device_id=*/0)) {
     DLOG(ERROR) << "gl::init::InitializeGLOneOff failed";
     return false;
   }
diff --git a/fuchsia/engine/browser/receiver_session_client.cc b/fuchsia/engine/browser/receiver_session_client.cc
index a5ab0349..00ee109c 100644
--- a/fuchsia/engine/browser/receiver_session_client.cc
+++ b/fuchsia/engine/browser/receiver_session_client.cc
@@ -47,6 +47,5 @@
                 std::move(port));
           },
           std::move(message_port_request_)));
-  receiver_session_->SetCastStreamingReceiver(
-      std::move(cast_streaming_receiver));
+  receiver_session_->StartStreamingAsync(std::move(cast_streaming_receiver));
 }
diff --git a/gpu/command_buffer/client/raster_cmd_helper_autogen.h b/gpu/command_buffer/client/raster_cmd_helper_autogen.h
index 0c20f99c..e445c02 100644
--- a/gpu/command_buffer/client/raster_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/raster_cmd_helper_autogen.h
@@ -93,6 +93,7 @@
                                   GLuint msaa_sample_count,
                                   gpu::raster::MsaaMode msaa_mode,
                                   GLboolean can_use_lcd_text,
+                                  GLboolean visible,
                                   const GLbyte* mailbox) {
   const uint32_t size =
       raster::cmds::BeginRasterCHROMIUMImmediate::ComputeSize();
@@ -101,7 +102,7 @@
           size);
   if (c) {
     c->Init(sk_color, needs_clear, msaa_sample_count, msaa_mode,
-            can_use_lcd_text, mailbox);
+            can_use_lcd_text, visible, mailbox);
   }
 }
 
diff --git a/gpu/command_buffer/client/raster_implementation.cc b/gpu/command_buffer/client/raster_implementation.cc
index 8069aa9..6613f581 100644
--- a/gpu/command_buffer/client/raster_implementation.cc
+++ b/gpu/command_buffer/client/raster_implementation.cc
@@ -1335,13 +1335,14 @@
     GLuint msaa_sample_count,
     MsaaMode msaa_mode,
     GLboolean can_use_lcd_text,
+    GLboolean visible,
     const gfx::ColorSpace& color_space,
     const GLbyte* mailbox) {
   DCHECK(!raster_properties_);
 
   helper_->BeginRasterCHROMIUMImmediate(sk_color, needs_clear,
                                         msaa_sample_count, msaa_mode,
-                                        can_use_lcd_text, mailbox);
+                                        can_use_lcd_text, visible, mailbox);
 
   raster_properties_.emplace(sk_color, can_use_lcd_text,
                              color_space.ToSkColorSpace());
diff --git a/gpu/command_buffer/client/raster_implementation.h b/gpu/command_buffer/client/raster_implementation.h
index 7116673..fdd547e 100644
--- a/gpu/command_buffer/client/raster_implementation.h
+++ b/gpu/command_buffer/client/raster_implementation.h
@@ -152,6 +152,7 @@
                            GLuint msaa_sample_count,
                            MsaaMode msaa_mode,
                            GLboolean can_use_lcd_text,
+                           GLboolean visible,
                            const gfx::ColorSpace& color_space,
                            const GLbyte* mailbox) override;
   void RasterCHROMIUM(const cc::DisplayItemList* list,
diff --git a/gpu/command_buffer/client/raster_implementation_gles.cc b/gpu/command_buffer/client/raster_implementation_gles.cc
index 24dc1efc..0adfbfe 100644
--- a/gpu/command_buffer/client/raster_implementation_gles.cc
+++ b/gpu/command_buffer/client/raster_implementation_gles.cc
@@ -221,6 +221,7 @@
     GLuint msaa_sample_count,
     MsaaMode msaa_mode,
     GLboolean can_use_lcd_text,
+    GLboolean visible,
     const gfx::ColorSpace& color_space,
     const GLbyte* mailbox) {
   NOTREACHED();
diff --git a/gpu/command_buffer/client/raster_implementation_gles.h b/gpu/command_buffer/client/raster_implementation_gles.h
index f750557..1142dbd 100644
--- a/gpu/command_buffer/client/raster_implementation_gles.h
+++ b/gpu/command_buffer/client/raster_implementation_gles.h
@@ -95,6 +95,7 @@
                            GLuint msaa_sample_count,
                            MsaaMode msaa_mode,
                            GLboolean can_use_lcd_text,
+                           GLboolean visible,
                            const gfx::ColorSpace& color_space,
                            const GLbyte* mailbox) override;
   void RasterCHROMIUM(const cc::DisplayItemList* list,
diff --git a/gpu/command_buffer/client/raster_interface.h b/gpu/command_buffer/client/raster_interface.h
index 96f90982..e43b373 100644
--- a/gpu/command_buffer/client/raster_interface.h
+++ b/gpu/command_buffer/client/raster_interface.h
@@ -89,6 +89,7 @@
                                    GLuint msaa_sample_count,
                                    MsaaMode msaa_mode,
                                    GLboolean can_use_lcd_text,
+                                   GLboolean visible,
                                    const gfx::ColorSpace& color_space,
                                    const GLbyte* mailbox) = 0;
 
diff --git a/gpu/command_buffer/common/raster_cmd_format_autogen.h b/gpu/command_buffer/common/raster_cmd_format_autogen.h
index 729feb2..6351f48 100644
--- a/gpu/command_buffer/common/raster_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/raster_cmd_format_autogen.h
@@ -393,6 +393,7 @@
             GLuint _msaa_sample_count,
             gpu::raster::MsaaMode _msaa_mode,
             GLboolean _can_use_lcd_text,
+            GLboolean _visible,
             const GLbyte* _mailbox) {
     SetHeader();
     sk_color = _sk_color;
@@ -400,6 +401,7 @@
     msaa_sample_count = _msaa_sample_count;
     msaa_mode = _msaa_mode;
     can_use_lcd_text = _can_use_lcd_text;
+    visible = _visible;
     memcpy(ImmediateDataAddress(this), _mailbox, ComputeDataSize());
   }
 
@@ -409,10 +411,11 @@
             GLuint _msaa_sample_count,
             gpu::raster::MsaaMode _msaa_mode,
             GLboolean _can_use_lcd_text,
+            GLboolean _visible,
             const GLbyte* _mailbox) {
     static_cast<ValueType*>(cmd)->Init(_sk_color, _needs_clear,
                                        _msaa_sample_count, _msaa_mode,
-                                       _can_use_lcd_text, _mailbox);
+                                       _can_use_lcd_text, _visible, _mailbox);
     const uint32_t size = ComputeSize();
     return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size);
   }
@@ -423,10 +426,11 @@
   uint32_t msaa_sample_count;
   uint32_t msaa_mode;
   uint32_t can_use_lcd_text;
+  uint32_t visible;
 };
 
-static_assert(sizeof(BeginRasterCHROMIUMImmediate) == 24,
-              "size of BeginRasterCHROMIUMImmediate should be 24");
+static_assert(sizeof(BeginRasterCHROMIUMImmediate) == 28,
+              "size of BeginRasterCHROMIUMImmediate should be 28");
 static_assert(offsetof(BeginRasterCHROMIUMImmediate, header) == 0,
               "offset of BeginRasterCHROMIUMImmediate header should be 0");
 static_assert(offsetof(BeginRasterCHROMIUMImmediate, sk_color) == 4,
@@ -441,6 +445,8 @@
 static_assert(
     offsetof(BeginRasterCHROMIUMImmediate, can_use_lcd_text) == 20,
     "offset of BeginRasterCHROMIUMImmediate can_use_lcd_text should be 20");
+static_assert(offsetof(BeginRasterCHROMIUMImmediate, visible) == 24,
+              "offset of BeginRasterCHROMIUMImmediate visible should be 24");
 
 struct RasterCHROMIUM {
   typedef RasterCHROMIUM ValueType;
diff --git a/gpu/command_buffer/common/raster_cmd_format_test_autogen.h b/gpu/command_buffer/common/raster_cmd_format_test_autogen.h
index 02ee0b3..9ba27ca 100644
--- a/gpu/command_buffer/common/raster_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/raster_cmd_format_test_autogen.h
@@ -161,7 +161,7 @@
   void* next_cmd =
       cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLboolean>(12),
               static_cast<GLuint>(13), static_cast<gpu::raster::MsaaMode>(14),
-              static_cast<GLboolean>(15), data);
+              static_cast<GLboolean>(15), static_cast<GLboolean>(16), data);
   EXPECT_EQ(static_cast<uint32_t>(cmds::BeginRasterCHROMIUMImmediate::kCmdId),
             cmd.header.command);
   EXPECT_EQ(sizeof(cmd) + RoundSizeToMultipleOfEntries(sizeof(data)),
@@ -171,6 +171,7 @@
   EXPECT_EQ(static_cast<GLuint>(13), cmd.msaa_sample_count);
   EXPECT_EQ(static_cast<gpu::raster::MsaaMode>(14), cmd.msaa_mode);
   EXPECT_EQ(static_cast<GLboolean>(15), cmd.can_use_lcd_text);
+  EXPECT_EQ(static_cast<GLboolean>(16), cmd.visible);
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd, sizeof(cmd) + RoundSizeToMultipleOfEntries(sizeof(data)));
 }
diff --git a/gpu/command_buffer/raster_cmd_buffer_functions.txt b/gpu/command_buffer/raster_cmd_buffer_functions.txt
index a414976..b174fbc 100644
--- a/gpu/command_buffer/raster_cmd_buffer_functions.txt
+++ b/gpu/command_buffer/raster_cmd_buffer_functions.txt
@@ -23,7 +23,7 @@
 GL_APICALL GLenum	GL_APIENTRY glGetGraphicsResetStatusKHR (void);
 
 // Extension CHROMIUM_raster_transport
-GL_APICALL void         GL_APIENTRY glBeginRasterCHROMIUM (GLuint sk_color, GLboolean needs_clear, GLuint msaa_sample_count, gpu::raster::MsaaMode msaa_mode, GLboolean can_use_lcd_text, const GLbyte* mailbox);
+GL_APICALL void         GL_APIENTRY glBeginRasterCHROMIUM (GLuint sk_color, GLboolean needs_clear, GLuint msaa_sample_count, gpu::raster::MsaaMode msaa_mode, GLboolean can_use_lcd_text, GLboolean visible, const GLbyte* mailbox);
 GL_APICALL void         GL_APIENTRY glRasterCHROMIUM (GLuint raster_shm_id, GLuint raster_shm_offset, GLuint raster_shm_size, GLuint font_shm_id, GLuint font_shm_offset, GLuint font_shm_size);
 GL_APICALL void         GL_APIENTRY glEndRasterCHROMIUM (void);
 GL_APICALL void         GL_APIENTRY glCreateTransferCacheEntryINTERNAL (GLuint entry_type, GLuint entry_id, GLuint handle_shm_id, GLuint handle_shm_offset, GLuint data_shm_id, GLuint data_shm_offset, GLuint data_size);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index b0a2ddd..8aa9a770 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -2444,7 +2444,11 @@
 
   gl::init::InitializeStaticGLBindingsImplementation(
       gl::GLImplementationParts(gl::kGLImplementationEGLANGLE), false);
-  gl::init::InitializeGLOneOffPlatformImplementation(false, false, true);
+  gl::init::InitializeGLOneOffPlatformImplementation(
+      /*fallback_to_software_gl=*/false,
+      /*disable_gl_drawing=*/false,
+      /*init_extensions=*/true,
+      /*system_device_id=*/0);
 
   scoped_refptr<gles2::FeatureInfo> feature_info = new gles2::FeatureInfo();
   group_ = new gles2::ContextGroup(
diff --git a/gpu/command_buffer/service/image_reader_gl_owner_unittest.cc b/gpu/command_buffer/service/image_reader_gl_owner_unittest.cc
index 6f0be3e4..1e17975 100644
--- a/gpu/command_buffer/service/image_reader_gl_owner_unittest.cc
+++ b/gpu/command_buffer/service/image_reader_gl_owner_unittest.cc
@@ -38,7 +38,11 @@
 
     gl::init::InitializeStaticGLBindingsImplementation(
         gl::GLImplementationParts(gl::kGLImplementationEGLGLES2), false);
-    gl::init::InitializeGLOneOffPlatformImplementation(false, false, true);
+    gl::init::InitializeGLOneOffPlatformImplementation(
+        /*fallback_to_software_gl=*/false,
+        /*disable_gl_drawing=*/false,
+        /*init_extensions=*/true,
+        /*system_device_id=*/0);
 
     surface_ = new gl::PbufferGLSurfaceEGL(gfx::Size(320, 240));
     surface_->Initialize();
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 37f4c50..223ca4d 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -782,6 +782,7 @@
                              GLuint msaa_sample_count,
                              MsaaMode msaa_mode,
                              GLboolean can_use_lcd_text,
+                             GLboolean visible,
                              const volatile GLbyte* key);
   void DoRasterCHROMIUM(GLuint raster_shm_id,
                         GLuint raster_shm_offset,
@@ -3505,6 +3506,7 @@
                                               GLuint msaa_sample_count,
                                               MsaaMode msaa_mode,
                                               GLboolean can_use_lcd_text,
+                                              GLboolean visible,
                                               const volatile GLbyte* key) {
   // Workaround for https://crbug.com/906453: Flush before BeginRaster (the
   // commands between BeginRaster and EndRaster will not flush).
@@ -3597,7 +3599,8 @@
       clear_color.emplace(sk_color);
     scoped_shared_image_raster_write_ =
         shared_image_raster_->BeginScopedWriteAccess(
-            final_msaa_count, surface_props, clear_color);
+            shared_context_state_, final_msaa_count, surface_props, clear_color,
+            visible);
     if (!scoped_shared_image_raster_write_) {
       LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginRasterCHROMIUM",
                          "failed to create surface");
diff --git a/gpu/command_buffer/service/raster_decoder_autogen.h b/gpu/command_buffer/service/raster_decoder_autogen.h
index d900eeba..c7a59c1 100644
--- a/gpu/command_buffer/service/raster_decoder_autogen.h
+++ b/gpu/command_buffer/service/raster_decoder_autogen.h
@@ -117,6 +117,7 @@
   gpu::raster::MsaaMode msaa_mode =
       static_cast<gpu::raster::MsaaMode>(c.msaa_mode);
   GLboolean can_use_lcd_text = static_cast<GLboolean>(c.can_use_lcd_text);
+  GLboolean visible = static_cast<GLboolean>(c.visible);
   uint32_t mailbox_size;
   if (!gles2::GLES2Util::ComputeDataSize<GLbyte, 16>(1, &mailbox_size)) {
     return error::kOutOfBounds;
@@ -131,7 +132,7 @@
     return error::kOutOfBounds;
   }
   DoBeginRasterCHROMIUM(sk_color, needs_clear, msaa_sample_count, msaa_mode,
-                        can_use_lcd_text, mailbox);
+                        can_use_lcd_text, visible, mailbox);
   return error::kNoError;
 }
 
diff --git a/gpu/command_buffer/service/shared_context_state.cc b/gpu/command_buffer/service/shared_context_state.cc
index 664e79a..d58e8281 100644
--- a/gpu/command_buffer/service/shared_context_state.cc
+++ b/gpu/command_buffer/service/shared_context_state.cc
@@ -287,7 +287,8 @@
   if (gpu_preferences.force_max_texture_size)
     options.fMaxTextureSizeOverride = gpu_preferences.force_max_texture_size;
 
-  if (base::FeatureList::IsEnabled(features::kReduceOpsTaskSplitting)) {
+  if (base::FeatureList::IsEnabled(features::kReduceOpsTaskSplitting) &&
+      !workarounds.disable_skia_reduce_ops_task_splitting) {
     options.fReduceOpsTaskSplitting = GrContextOptions::Enable::kYes;
   } else {
     options.fReduceOpsTaskSplitting = GrContextOptions::Enable::kNo;
diff --git a/gpu/command_buffer/service/shared_image_backing_raw_draw.cc b/gpu/command_buffer/service/shared_image_backing_raw_draw.cc
index 48b9300e..05e5ddc 100644
--- a/gpu/command_buffer/service/shared_image_backing_raw_draw.cc
+++ b/gpu/command_buffer/service/shared_image_backing_raw_draw.cc
@@ -38,11 +38,14 @@
   ~RepresentationRaster() override = default;
 
   cc::PaintOpBuffer* BeginWriteAccess(
+      scoped_refptr<SharedContextState> context_state,
       int final_msaa_count,
       const SkSurfaceProps& surface_props,
-      const absl::optional<SkColor>& clear_color) override {
+      const absl::optional<SkColor>& clear_color,
+      bool visible) override {
     return raw_draw_backing()->BeginRasterWriteAccess(
-        final_msaa_count, surface_props, clear_color);
+        std::move(context_state), final_msaa_count, surface_props, clear_color,
+        visible);
   }
 
   void EndWriteAccess(base::OnceClosure callback) override {
@@ -198,7 +201,8 @@
     std::move(paint_op_release_callback_).Run();
 }
 
-bool SharedImageBackingRawDraw::CreateBackendTextureAndFlushPaintOps() {
+bool SharedImageBackingRawDraw::CreateBackendTextureAndFlushPaintOps(
+    bool flush) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(!backend_texture_.isValid());
   DCHECK(!promise_texture_);
@@ -230,10 +234,16 @@
     paint_op_buffer_->Playback(surface->getCanvas(), playback_params);
   }
 
-  // Insert resolveMSAA in surface's command stream, so if the surface,
-  // otherwise gr_context->flush() call will not resolve to the wrapped
-  // backend_texture_.
-  surface->resolveMSAA();
+  if (flush) {
+    surface->flush();
+  } else {
+    // For a MSAA SkSurface, if gr_context->flush() is called, all draws on the
+    // SkSurface will be flush into a temp MSAA buffer, but the it will not
+    // resolved the temp MSAA buffer to the wrapped backend texture.
+    // So call resolveMSAA() to insert resolve op in surface's command stream,
+    // and when gr_context->flush() is call, the surface will be resolved.
+    surface->resolveMSAA();
+  }
 
   return true;
 }
@@ -249,9 +259,11 @@
 }
 
 cc::PaintOpBuffer* SharedImageBackingRawDraw::BeginRasterWriteAccess(
+    scoped_refptr<SharedContextState> context_state,
     int final_msaa_count,
     const SkSurfaceProps& surface_props,
-    const absl::optional<SkColor>& clear_color) {
+    const absl::optional<SkColor>& clear_color,
+    bool visible) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   AutoLock auto_lock(this);
   if (read_count_) {
@@ -273,9 +285,13 @@
   if (!paint_op_buffer_)
     paint_op_buffer_ = sk_make_sp<cc::PaintOpBuffer>();
 
+  DCHECK(!context_state_ || context_state_ == context_state);
+  context_state_ = std::move(context_state);
+
   final_msaa_count_ = final_msaa_count;
   surface_props_ = surface_props;
   clear_color_ = clear_color;
+  visible_ = visible;
 
   return paint_op_buffer_.get();
 }
@@ -289,6 +305,21 @@
 
   is_write_ = false;
 
+  // If |paint_op_buffer_| contains SaveLayerOps, it usually means a SVG image
+  // is drawn. For some complex SVG re-rasterizing is expensive, it causes
+  // janky scrolling for some page which SVG images are heavily used.
+  // Workaround the problem by return nullptr here, and then SkiaRenderer will
+  // fallback to using |backing_texture_|.
+  // TODO(crbug.com/1292068): only cache raster results for the SaveLayerOp
+  // covered area.
+  if (visible_ && paint_op_buffer_->has_save_layer_ops()) {
+    // If the raster task priority is high, we will execute paint ops
+    // immediately.
+    CreateBackendTextureAndFlushPaintOps(/*flush=*/true);
+    DCHECK(!paint_op_release_callback_);
+    std::move(callback).Run();
+  }
+
   if (callback) {
     DCHECK(!paint_op_release_callback_);
     paint_op_release_callback_ = std::move(callback);
@@ -335,7 +366,8 @@
 sk_sp<SkPromiseImageTexture> SharedImageBackingRawDraw::BeginSkiaReadAccess() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   AutoLock auto_lock(this);
-  if (!backend_texture_.isValid() && !CreateBackendTextureAndFlushPaintOps())
+  if (!backend_texture_.isValid() &&
+      !CreateBackendTextureAndFlushPaintOps(/*flush=*/false))
     return nullptr;
 
   DCHECK(promise_texture_);
diff --git a/gpu/command_buffer/service/shared_image_backing_raw_draw.h b/gpu/command_buffer/service/shared_image_backing_raw_draw.h
index aa1aac5..b7b4205 100644
--- a/gpu/command_buffer/service/shared_image_backing_raw_draw.h
+++ b/gpu/command_buffer/service/shared_image_backing_raw_draw.h
@@ -54,13 +54,16 @@
   class RepresentationSkia;
 
   void ResetPaintOpBuffer() EXCLUSIVE_LOCKS_REQUIRED(lock_);
-  bool CreateBackendTextureAndFlushPaintOps() EXCLUSIVE_LOCKS_REQUIRED(lock_);
+  bool CreateBackendTextureAndFlushPaintOps(bool flush)
+      EXCLUSIVE_LOCKS_REQUIRED(lock_);
   void DestroyBackendTexture() EXCLUSIVE_LOCKS_REQUIRED(lock_);
 
   cc::PaintOpBuffer* BeginRasterWriteAccess(
+      scoped_refptr<SharedContextState> context_state,
       int final_msaa_count,
       const SkSurfaceProps& surface_props,
-      const absl::optional<SkColor>& clear_color);
+      const absl::optional<SkColor>& clear_color,
+      bool visible);
   void EndRasterWriteAccess(base::OnceClosure callback);
   cc::PaintOpBuffer* BeginRasterReadAccess(
       absl::optional<SkColor>& clear_color);
@@ -70,6 +73,7 @@
   int32_t final_msaa_count_ GUARDED_BY_CONTEXT(thread_checker_) = 0;
   SkSurfaceProps surface_props_ GUARDED_BY_CONTEXT(thread_checker_){};
   absl::optional<SkColor> clear_color_ GUARDED_BY(lock_);
+  bool visible_ GUARDED_BY(lock_) = false;
   sk_sp<cc::PaintOpBuffer> paint_op_buffer_ GUARDED_BY(lock_);
   base::OnceClosure paint_op_release_callback_
       GUARDED_BY_CONTEXT(thread_checker_);
diff --git a/gpu/command_buffer/service/shared_image_representation.cc b/gpu/command_buffer/service/shared_image_representation.cc
index 7a582478..dcb0136 100644
--- a/gpu/command_buffer/service/shared_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image_representation.cc
@@ -7,6 +7,7 @@
 #include "base/strings/stringprintf.h"
 #include "build/build_config.h"
 #include "components/viz/common/resources/resource_format_utils.h"
+#include "gpu/command_buffer/service/shared_context_state.h"
 #include "gpu/command_buffer/service/texture_manager.h"
 #include "third_party/skia/include/core/SkPromiseImageTexture.h"
 #include "third_party/skia/include/gpu/GrBackendSurfaceMutableState.h"
@@ -440,12 +441,15 @@
 
 std::unique_ptr<SharedImageRepresentationRaster::ScopedWriteAccess>
 SharedImageRepresentationRaster::BeginScopedWriteAccess(
+    scoped_refptr<SharedContextState> context_state,
     int final_msaa_count,
     const SkSurfaceProps& surface_props,
-    const absl::optional<SkColor>& clear_color) {
+    const absl::optional<SkColor>& clear_color,
+    bool visible) {
   return std::make_unique<ScopedWriteAccess>(
       base::PassKey<SharedImageRepresentationRaster>(), this,
-      BeginWriteAccess(final_msaa_count, surface_props, clear_color));
+      BeginWriteAccess(std::move(context_state), final_msaa_count,
+                       surface_props, clear_color, visible));
 }
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_representation.h b/gpu/command_buffer/service/shared_image_representation.h
index 12d7872c..19962b28 100644
--- a/gpu/command_buffer/service/shared_image_representation.h
+++ b/gpu/command_buffer/service/shared_image_representation.h
@@ -650,18 +650,22 @@
   std::unique_ptr<ScopedReadAccess> BeginScopedReadAccess();
 
   std::unique_ptr<ScopedWriteAccess> BeginScopedWriteAccess(
+      scoped_refptr<SharedContextState> context_state,
       int final_msaa_count,
       const SkSurfaceProps& surface_props,
-      const absl::optional<SkColor>& clear_color);
+      const absl::optional<SkColor>& clear_color,
+      bool visible);
 
  protected:
   virtual cc::PaintOpBuffer* BeginReadAccess(
       absl::optional<SkColor>& clear_color) = 0;
   virtual void EndReadAccess() = 0;
   virtual cc::PaintOpBuffer* BeginWriteAccess(
+      scoped_refptr<SharedContextState> context_state,
       int final_msaa_count,
       const SkSurfaceProps& surface_props,
-      const absl::optional<SkColor>& clear_color) = 0;
+      const absl::optional<SkColor>& clear_color,
+      bool visible) = 0;
   virtual void EndWriteAccess(base::OnceClosure callback) = 0;
 };
 
diff --git a/gpu/command_buffer/service/surface_texture_gl_owner_unittest.cc b/gpu/command_buffer/service/surface_texture_gl_owner_unittest.cc
index de50e0e5..5ddb2fa5 100644
--- a/gpu/command_buffer/service/surface_texture_gl_owner_unittest.cc
+++ b/gpu/command_buffer/service/surface_texture_gl_owner_unittest.cc
@@ -39,7 +39,11 @@
   void SetUp() override {
     gl::init::InitializeStaticGLBindingsImplementation(
         gl::GLImplementationParts(gl::kGLImplementationEGLGLES2), false);
-    gl::init::InitializeGLOneOffPlatformImplementation(false, false, true);
+    gl::init::InitializeGLOneOffPlatformImplementation(
+        /*fallback_to_software_gl=*/false,
+        /*disable_gl_drawing=*/false,
+        /*init_extensions=*/true,
+        /*system_device_id=*/0);
 
     surface_ = new gl::PbufferGLSurfaceEGL(gfx::Size(320, 240));
     surface_->Initialize();
diff --git a/gpu/command_buffer/service/wrapped_sk_image.cc b/gpu/command_buffer/service/wrapped_sk_image.cc
index 5944ca5c..dea6e897 100644
--- a/gpu/command_buffer/service/wrapped_sk_image.cc
+++ b/gpu/command_buffer/service/wrapped_sk_image.cc
@@ -165,6 +165,7 @@
       SkImageInfo info = MakeSkImageInfo(size(), format());
       SkPixmap pixmap(info, shared_memory_wrapper_.GetMemory(),
                       shared_memory_wrapper_.GetStride());
+
       if (!context_state_->gr_context()->updateBackendTexture(
               backend_texture_, &pixmap, /*numLevels=*/1, nullptr, nullptr)) {
         DLOG(ERROR) << "Failed to update WrappedSkImage texture";
diff --git a/gpu/command_buffer/tests/fuzzer_main.cc b/gpu/command_buffer/tests/fuzzer_main.cc
index bab0876e..c417755 100644
--- a/gpu/command_buffer/tests/fuzzer_main.cc
+++ b/gpu/command_buffer/tests/fuzzer_main.cc
@@ -342,8 +342,11 @@
 
     CHECK(gl::init::InitializeStaticGLBindingsImplementation(
         gl::GLImplementationParts(gl::kGLImplementationEGLANGLE), false));
-    CHECK(
-        gl::init::InitializeGLOneOffPlatformImplementation(false, false, true));
+    CHECK(gl::init::InitializeGLOneOffPlatformImplementation(
+        /*fallback_to_software_gl=*/false,
+        /*disable_gl_drawing=*/false,
+        /*init_extensions=*/true,
+        /*system_device_id=*/0));
 #elif defined(GPU_FUZZER_USE_STUB)
     gl::GLSurfaceTestSupport::InitializeOneOffWithStubBindings();
     // Because the context depends on configuration bits, we want to recreate
diff --git a/gpu/command_buffer/tests/gl_test_utils.cc b/gpu/command_buffer/tests/gl_test_utils.cc
index 233bed6..d1f3235 100644
--- a/gpu/command_buffer/tests/gl_test_utils.cc
+++ b/gpu/command_buffer/tests/gl_test_utils.cc
@@ -37,19 +37,20 @@
 
 bool GLTestHelper::InitializeGL(gl::GLImplementation gl_impl) {
   if (gl_impl == gl::GLImplementation::kGLImplementationNone) {
-    if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ true))
+    if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings=*/true,
+                                                  /*system_device_id=*/0))
       return false;
   } else {
     if (!gl::init::InitializeStaticGLBindingsImplementation(
             gl::GLImplementationParts(gl_impl),
-            /*fallback_to_software_gl*/ false))
+            /*fallback_to_software_gl=*/false))
       return false;
 
     if (!gl::init::InitializeGLOneOffPlatformImplementation(
-            false,  // fallback_to_software_gl
-            false,  // disable_gl_drawing
-            false   // init_extensions
-            )) {
+            /*fallback_to_software_gl=*/false,
+            /*disable_gl_drawing=*/false,
+            /*init_extensions=*/false,
+            /*system_device_id=*/0)) {
       return false;
     }
   }
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json
index ed95f35..322ae0d 100644
--- a/gpu/config/gpu_driver_bug_list.json
+++ b/gpu/config/gpu_driver_bug_list.json
@@ -3940,6 +3940,20 @@
       "features": [
         "disable_dynamic_video_encode_framerate_update"
       ]
+    },
+    {
+      "id": 391,
+      "description": "Skia ReduceOpsTaskSplitting causes artifacts on Intel Skylake",
+      "cr_bugs": [1298809],
+      "os": {
+        "type": "win"
+      },
+      "intel_gpu_series": [
+        "skylake"
+      ],
+      "features": [
+        "disable_skia_reduce_ops_task_splitting"
+      ]
     }
   ]
 }
diff --git a/gpu/config/gpu_info.cc b/gpu/config/gpu_info.cc
index 5e8b28d..68f5ff2 100644
--- a/gpu/config/gpu_info.cc
+++ b/gpu/config/gpu_info.cc
@@ -141,6 +141,20 @@
   }
 }
 
+bool IsIntegratedGpu(const gpu::GPUInfo::GPUDevice& gpu) {
+  // TODO(crbug.com/1291675): handle M1 with eGPU situation.
+  switch (gpu.vendor_id) {
+    case 0x8086:  // Intel
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool IsDiscreteGpu(const gpu::GPUInfo::GPUDevice& gpu) {
+  return !IsSoftwareRenderer(gpu.vendor_id) && !IsIntegratedGpu(gpu);
+}
+
 }  // namespace
 
 namespace gpu {
@@ -268,6 +282,61 @@
   return gpu_count;
 }
 
+bool GPUInfo::GetIntegratedGpu(GPUDevice* output_integrated_gpu) const {
+  unsigned int integrated_gpu_count = 0;
+  unsigned int discrete_gpu_count = 0;
+  GPUDevice integrated_gpu;
+  if (IsIntegratedGpu(gpu)) {
+    ++integrated_gpu_count;
+    integrated_gpu = gpu;
+  } else if (IsDiscreteGpu(gpu)) {
+    ++discrete_gpu_count;
+  }
+  for (const auto& secondary_gpu : secondary_gpus) {
+    if (IsIntegratedGpu(secondary_gpu)) {
+      ++integrated_gpu_count;
+      if (integrated_gpu_count == 1)
+        integrated_gpu = secondary_gpu;
+    } else if (IsDiscreteGpu(secondary_gpu)) {
+      ++discrete_gpu_count;
+    }
+  }
+  if (integrated_gpu_count == 1 && discrete_gpu_count >= 1) {
+    if (output_integrated_gpu)
+      *output_integrated_gpu = integrated_gpu;
+    return true;
+  }
+  return false;
+}
+
+bool GPUInfo::GetDiscreteGpu(GPUDevice* output_discrete_gpu) const {
+  unsigned int integrated_gpu_count = 0;
+  unsigned int discrete_gpu_count = 0;
+  GPUDevice discrete_gpu;
+  if (IsIntegratedGpu(gpu)) {
+    ++integrated_gpu_count;
+  } else if (IsDiscreteGpu(gpu)) {
+    ++discrete_gpu_count;
+    discrete_gpu = gpu;
+  }
+  for (const auto& secondary_gpu : secondary_gpus) {
+    if (IsIntegratedGpu(secondary_gpu)) {
+      ++integrated_gpu_count;
+    } else if (IsDiscreteGpu(secondary_gpu)) {
+      ++discrete_gpu_count;
+      if (discrete_gpu_count == 1)
+        discrete_gpu = secondary_gpu;
+    }
+  }
+  if (integrated_gpu_count + discrete_gpu_count > 1 &&
+      discrete_gpu_count >= 1) {
+    if (output_discrete_gpu)
+      *output_discrete_gpu = discrete_gpu;
+    return true;
+  }
+  return false;
+}
+
 void GPUInfo::EnumerateFields(Enumerator* enumerator) const {
   struct GPUInfoKnownFields {
     base::TimeDelta initialization_time;
diff --git a/gpu/config/gpu_info.h b/gpu/config/gpu_info.h
index 3e76ca1..81bd0c9 100644
--- a/gpu/config/gpu_info.h
+++ b/gpu/config/gpu_info.h
@@ -303,6 +303,13 @@
 
   unsigned int GpuCount() const;
 
+  // Return true if it's a multi-gpu system and there is a single integrated
+  // GPU identified.
+  bool GetIntegratedGpu(GPUDevice* output_integrated_gpu) const;
+  // Return true if it's a multi-gpu system and there is a discrete GPU.
+  // |output_discrete_gpu| is the first non-Intel GPU.
+  bool GetDiscreteGpu(GPUDevice* output_discrete_gpu) const;
+
   // The amount of time taken to get from the process starting to the message
   // loop being pumped.
   base::TimeDelta initialization_time;
diff --git a/gpu/config/gpu_util.cc b/gpu/config/gpu_util.cc
index f5150ef2..f2c7059e 100644
--- a/gpu/config/gpu_util.cc
+++ b/gpu/config/gpu_util.cc
@@ -745,7 +745,8 @@
   }
   if (gl::GetGLImplementation() == gl::kGLImplementationNone) {
     // Some tests initialize bindings by themselves.
-    if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ true)) {
+    if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings=*/true,
+                                                  /*system_device_id=*/0)) {
       VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed";
       return false;
     }
diff --git a/gpu/config/gpu_workaround_list.txt b/gpu/config/gpu_workaround_list.txt
index 6b15985..3f14f7c 100644
--- a/gpu/config/gpu_workaround_list.txt
+++ b/gpu/config/gpu_workaround_list.txt
@@ -54,6 +54,7 @@
 disable_program_cache
 disable_program_caching_for_transform_feedback
 disable_program_disk_cache
+disable_skia_reduce_ops_task_splitting
 disable_software_to_accelerated_canvas_upgrade
 disable_texture_storage
 disable_timestamp_queries
diff --git a/gpu/gles2_conform_support/egl/thread_state.cc b/gpu/gles2_conform_support/egl/thread_state.cc
index 4013ebe0..624b9dc0 100644
--- a/gpu/gles2_conform_support/egl/thread_state.cc
+++ b/gpu/gles2_conform_support/egl/thread_state.cc
@@ -88,7 +88,8 @@
 #if defined(USE_OZONE)
       ui::OzonePlatform::InitializeForGPU(ui::OzonePlatform::InitParams());
 #endif
-      gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ true);
+      gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings=*/true,
+                                               /*system_device_id=*/0);
       gpu::GpuFeatureInfo gpu_feature_info;
       if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) {
         gpu::GPUInfo gpu_info;
diff --git a/gpu/ipc/client/raster_in_process_context_tests.cc b/gpu/ipc/client/raster_in_process_context_tests.cc
index 0750a6a..b77e9f2 100644
--- a/gpu/ipc/client/raster_in_process_context_tests.cc
+++ b/gpu/ipc/client/raster_in_process_context_tests.cc
@@ -106,8 +106,8 @@
   // Call BeginRasterCHROMIUM.
   ri_->BeginRasterCHROMIUM(
       /*sk_color=*/0, /*needs_clear=*/true, /*msaa_sample_count=*/0,
-      gpu::raster::kNoMSAA, /*can_use_lcd_text=*/false, color_space,
-      mailbox.name);
+      gpu::raster::kNoMSAA, /*can_use_lcd_text=*/false, /*visible=*/true,
+      color_space, mailbox.name);
   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), ri_->GetError());
 
   // Should flag an error this command is not allowed between a Begin and
diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc
index 47a5b40..bd06bfe1 100644
--- a/gpu/ipc/service/gpu_init.cc
+++ b/gpu/ipc/service/gpu_init.cc
@@ -185,7 +185,14 @@
   }
   return false;
 }
-#endif  // !BUILDFLAG(ENABLE_VULKAN)
+#endif  // BUILDFLAG(ENABLE_VULKAN)
+
+#if BUILDFLAG(IS_WIN)
+uint64_t CHROME_LUID_to_uint64_t(const CHROME_LUID& luid) {
+  uint64_t id64 = static_cast<uint32_t>(luid.HighPart);
+  return (id64 << 32) | (luid.LowPart & 0xFFFFFFFF);
+}
+#endif  // BUILDFLAG(IS_WIN)
 
 }  // namespace
 
@@ -202,6 +209,7 @@
   // need more context based GPUInfo. In such situations, switching to
   // SwiftShader needs to wait until creating a context.
   bool needs_more_info = true;
+  uint64_t system_device_id = 0;
 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMECAST)
   needs_more_info = false;
   if (!PopGPUInfoCache(&gpu_info_)) {
@@ -238,6 +246,33 @@
     gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
                                               command_line, &needs_more_info);
   }
+
+  // GPU picking is only effective with ANGLE/Metal backend on Mac and
+  // on Windows.
+  GPUInfo::GPUDevice preferred_gpu;
+  bool force_integrated_gpu =
+      gpu_feature_info_.IsWorkaroundEnabled(FORCE_LOW_POWER_GPU);
+  bool force_discrete_gpu =
+      gpu_feature_info_.IsWorkaroundEnabled(FORCE_HIGH_PERFORMANCE_GPU);
+#if BUILDFLAG(IS_MAC)
+  // Default to the integrated gpu on a multi-gpu Mac.
+  if (!force_discrete_gpu)
+    force_integrated_gpu = true;
+#endif  // BUILDFLAG(IS_MAC)
+  if (force_discrete_gpu && gpu_info_.GetDiscreteGpu(&preferred_gpu)) {
+#if BUILDFLAG(IS_MAC)
+    system_device_id = preferred_gpu.register_id;
+#elif BUILDFLAG(IS_WIN)
+    system_device_id = CHROME_LUID_to_uint64_t(preferred_gpu.luid);
+#endif
+  } else if (force_integrated_gpu &&
+             gpu_info_.GetIntegratedGpu(&preferred_gpu)) {
+#if BUILDFLAG(IS_MAC)
+    system_device_id = preferred_gpu.register_id;
+#elif BUILDFLAG(IS_WIN)
+    system_device_id = CHROME_LUID_to_uint64_t(preferred_gpu.luid);
+#endif
+  }
 #endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMECAST)
 
   gpu_info_.in_process_gpu = false;
@@ -401,8 +436,8 @@
     if (watchdog_thread_)
       watchdog_thread_->ResumeWatchdog();
     if (gl::GetGLImplementation() != gl::kGLImplementationDisabled) {
-      gl_initialized =
-          gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ false);
+      gl_initialized = gl::init::InitializeGLNoExtensionsOneOff(
+          /*init_bindings*/ false, system_device_id);
       if (!gl_initialized) {
         VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed";
         return false;
@@ -478,7 +513,8 @@
         gl::init::ShutdownGL(true);
         watchdog_thread_ = nullptr;
         watchdog_init.SetGpuWatchdogPtr(nullptr);
-        if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ true)) {
+        if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ true,
+                                                      system_device_id)) {
           VLOG(1)
               << "gl::init::InitializeGLNoExtensionsOneOff with SwiftShader "
               << "failed";
@@ -766,7 +802,8 @@
   gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
       command_line, gpu_feature_info_,
       gpu_preferences_.disable_software_rasterizer, needs_more_info);
-  if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ true)) {
+  if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings=*/true,
+                                                /*system_device_id=*/0)) {
     VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed";
     return;
   }
@@ -782,7 +819,8 @@
     if (gl_use_swiftshader_) {
       SaveHardwareGpuInfoAndGpuFeatureInfo();
       gl::init::ShutdownGL(true);
-      if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ true)) {
+      if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings=*/true,
+                                                    /*system_device_id=*/0)) {
         VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed "
                 << "with SwiftShader";
         return;
@@ -836,7 +874,8 @@
     if (gl_use_swiftshader_) {
       SaveHardwareGpuInfoAndGpuFeatureInfo();
       gl::init::ShutdownGL(true);
-      if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ true)) {
+      if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings=*/true,
+                                                    /*system_device_id=*/0)) {
         VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed "
                 << "with SwiftShader";
         return;
diff --git a/gpu/perftests/run_all_tests.cc b/gpu/perftests/run_all_tests.cc
index 3c8ac1a..2decc61 100644
--- a/gpu/perftests/run_all_tests.cc
+++ b/gpu/perftests/run_all_tests.cc
@@ -30,7 +30,7 @@
       base::MessagePumpType::IO);
 #endif
 
-  CHECK(gl::init::InitializeGLOneOff());
+  CHECK(gl::init::InitializeGLOneOff(/*system_device_id=*/0));
   return test_suite->Run();
 }
 
diff --git a/gpu/tools/compositor_model_bench/compositor_model_bench.cc b/gpu/tools/compositor_model_bench/compositor_model_bench.cc
index 1e5bc0d..c34ddf3 100644
--- a/gpu/tools/compositor_model_bench/compositor_model_bench.cc
+++ b/gpu/tools/compositor_model_bench/compositor_model_bench.cc
@@ -187,7 +187,7 @@
 
   // Initialize the OpenGL context.
   bool InitGLContext() {
-    if (!gl::init::InitializeGLOneOff()) {
+    if (!gl::init::InitializeGLOneOff(/*system_device_id=*/0)) {
       LOG(FATAL) << "gl::init::InitializeGLOneOff failed";
       return false;
     }
diff --git a/infra/OWNERS b/infra/OWNERS
index 497d48f8..d17af9a 100644
--- a/infra/OWNERS
+++ b/infra/OWNERS
@@ -11,7 +11,6 @@
 hypan@google.com
 kimstephanie@google.com
 martiniss@chromium.org
-mmoss@chromium.org
 
 # Other folks who understand the infrastructure well.
 bsheedy@chromium.org
diff --git a/ios/chrome/browser/discover_feed/OWNERS b/ios/chrome/browser/discover_feed/OWNERS
index 90c007a..e534c90 100644
--- a/ios/chrome/browser/discover_feed/OWNERS
+++ b/ios/chrome/browser/discover_feed/OWNERS
@@ -1,2 +1 @@
 sczs@chromium.org
-gogerald@chromium.org
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
index 8233777..712f76a 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -4007,10 +4007,6 @@
                 oldWebState:(web::WebState*)oldWebState
                     atIndex:(int)atIndex
                      reason:(ActiveWebStateChangeReason)reason {
-  // TODO(crbug.com/1272513): Move this update to NTPCoordinator.
-  if (IsSingleNtpEnabled()) {
-    self.ntpCoordinator.webState = newWebState;
-  }
   if (oldWebState) {
     // TODO(crbug.com/1272514): Move webstate lifecycle updates to a browser
     // agent.
@@ -4024,6 +4020,10 @@
     }
     [self dismissPopups];
   }
+  // TODO(crbug.com/1272513): Move this update to NTPCoordinator.
+  if (IsSingleNtpEnabled()) {
+    self.ntpCoordinator.webState = newWebState;
+  }
   // NOTE: webStateSelected expects to always be called with a
   // non-null WebState.
   if (!newWebState)
@@ -4583,9 +4583,10 @@
       return;
     }
     if (NTPHelper->IsActive()) {
+      [self.ntpCoordinator ntpDidChangeVisibility:YES];
       self.ntpCoordinator.webState = webState;
     } else {
-      // Set to nullptr to save NTP scroll offset before navigation.
+      [self.ntpCoordinator ntpDidChangeVisibility:NO];
       self.ntpCoordinator.webState = nullptr;
       [self stopNTPIfNeeded];
     }
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.h b/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.h
index 82e0d32..2bcdc0e 100644
--- a/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.h
+++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.h
@@ -101,6 +101,10 @@
 // Tell location bar has taken focus.
 - (void)locationBarDidBecomeFirstResponder;
 
+// Save the NTP scroll offset into the last committed navigation item for the
+// before navigating away.
+- (void)saveContentOffsetForWebState:(web::WebState*)webState;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_NTP_HOME_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.mm b/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.mm
index e9c4bb9..222bff7 100644
--- a/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.mm
+++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.mm
@@ -198,13 +198,59 @@
   [self.consumer locationBarResignsFirstResponder];
 }
 
+- (void)saveContentOffsetForWebState:(web::WebState*)webState {
+  if (!IsSingleNtpEnabled() &&
+      webState->GetLastCommittedURL().DeprecatedGetOriginAsURL() !=
+          kChromeUINewTabURL) {
+    return;
+  }
+  if (IsSingleNtpEnabled() &&
+      (webState->GetLastCommittedURL().DeprecatedGetOriginAsURL() !=
+           kChromeUINewTabURL &&
+       webState->GetVisibleURL().DeprecatedGetOriginAsURL() !=
+           kChromeUINewTabURL)) {
+    // Do nothing if the current page is not the NTP.
+    return;
+  }
+
+  web::NavigationManager* manager = webState->GetNavigationManager();
+  web::NavigationItem* item =
+      webState->GetLastCommittedURL() == kChromeUINewTabURL
+          ? manager->GetLastCommittedItem()
+          : manager->GetVisibleItem();
+  web::PageDisplayState displayState;
+
+  // TODO(crbug.com/1114792): Create a protocol to stop having references to
+  // both of these ViewControllers directly.
+  UICollectionView* collectionView =
+      self.ntpViewController.discoverFeedWrapperViewController
+          .contentCollectionView;
+  UIEdgeInsets contentInset = collectionView.contentInset;
+  CGPoint contentOffset = collectionView.contentOffset;
+  if ([self.suggestionsMediator mostRecentTabStartSurfaceTileIsShowing]) {
+    // Return to Recent tab tile is only shown one time, so subtract it's
+    // vertical space to preserve relative scroll position from top.
+    CGFloat tileSectionHeight =
+        [ContentSuggestionsReturnToRecentTabCell defaultSize].height +
+        content_suggestions::kReturnToRecentTabSectionBottomMargin;
+    if (contentOffset.y >
+        tileSectionHeight +
+            [self.headerCollectionInteractionHandler pinnedOffsetY]) {
+      contentOffset.y -= tileSectionHeight;
+    }
+  }
+
+  contentOffset.y -=
+      self.headerCollectionInteractionHandler.collectionShiftingOffset;
+  displayState.scroll_state() =
+      web::PageScrollState(contentOffset, contentInset);
+  item->SetPageDisplayState(displayState);
+}
+
 #pragma mark - Properties.
 
 - (void)setWebState:(web::WebState*)webState {
   if (_webState && _webStateObserver) {
-    if (IsSingleNtpEnabled()) {
-      [self saveContentOffsetForWebState:_webState];
-    }
     _webState->RemoveObserver(_webStateObserver.get());
   }
   _webState = webState;
@@ -540,57 +586,6 @@
   [self.dispatcher showSnackbarMessage:message];
 }
 
-// Save the NTP scroll offset into the last committed navigation item for the
-// before we navigate away.
-- (void)saveContentOffsetForWebState:(web::WebState*)webState {
-  if (!IsSingleNtpEnabled() &&
-      webState->GetLastCommittedURL().DeprecatedGetOriginAsURL() !=
-          kChromeUINewTabURL) {
-    return;
-  }
-  if (IsSingleNtpEnabled() &&
-      (webState->GetLastCommittedURL().DeprecatedGetOriginAsURL() !=
-           kChromeUINewTabURL &&
-       webState->GetVisibleURL().DeprecatedGetOriginAsURL() !=
-           kChromeUINewTabURL)) {
-    // Do nothing if the current page is not the NTP.
-    return;
-  }
-
-  web::NavigationManager* manager = webState->GetNavigationManager();
-  web::NavigationItem* item =
-      webState->GetLastCommittedURL() == kChromeUINewTabURL
-          ? manager->GetLastCommittedItem()
-          : manager->GetVisibleItem();
-  web::PageDisplayState displayState;
-
-  // TODO(crbug.com/1114792): Create a protocol to stop having references to
-  // both of these ViewControllers directly.
-  UICollectionView* collectionView =
-      self.ntpViewController.discoverFeedWrapperViewController
-          .contentCollectionView;
-  UIEdgeInsets contentInset = collectionView.contentInset;
-  CGPoint contentOffset = collectionView.contentOffset;
-  if ([self.suggestionsMediator mostRecentTabStartSurfaceTileIsShowing]) {
-    // Return to Recent tab tile is only shown one time, so subtract it's
-    // vertical space to preserve relative scroll position from top.
-    CGFloat tileSectionHeight =
-        [ContentSuggestionsReturnToRecentTabCell defaultSize].height +
-        content_suggestions::kReturnToRecentTabSectionBottomMargin;
-    if (contentOffset.y >
-        tileSectionHeight +
-            [self.headerCollectionInteractionHandler pinnedOffsetY]) {
-      contentOffset.y -= tileSectionHeight;
-    }
-  }
-
-  contentOffset.y -=
-      self.headerCollectionInteractionHandler.collectionShiftingOffset;
-  displayState.scroll_state() =
-      web::PageScrollState(contentOffset, contentInset);
-  item->SetPageDisplayState(displayState);
-}
-
 // Set the NTP scroll offset for the current navigation item.
 - (void)setContentOffsetForWebState:(web::WebState*)webState {
   if (webState->GetVisibleURL().DeprecatedGetOriginAsURL() !=
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
index b6ac25d8..12c7d42 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
@@ -556,6 +556,8 @@
 - (void)ntpDidChangeVisibility:(BOOL)visible {
   if (visible) {
     [self.contentSuggestionsCoordinator configureStartSurfaceIfNeeded];
+  } else if (IsSingleNtpEnabled()) {
+    [self.ntpMediator saveContentOffsetForWebState:self.webState];
   }
   self.viewPresented = visible;
   [self updateVisible];
diff --git a/ios/chrome/browser/ui/start_surface/OWNERS b/ios/chrome/browser/ui/start_surface/OWNERS
index 0b8a6d31..6777393 100644
--- a/ios/chrome/browser/ui/start_surface/OWNERS
+++ b/ios/chrome/browser/ui/start_surface/OWNERS
@@ -1,2 +1 @@
-gogerald@chromium.org
 thegreenfrog@chromium.org
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm
index 123ce18..35e9d97d 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm
@@ -246,7 +246,8 @@
       web::WebState* webState = self.webStateList->GetWebStateAt(i);
       _scopedWebStateObservation->AddObservation(webState);
     }
-    [self populateConsumerItems];
+    if (self.webStateList->count() > 0)
+      [self populateConsumerItems];
   }
 }
 
@@ -452,9 +453,29 @@
 }
 
 - (void)closeItemWithID:(NSString*)itemID {
-  int index = GetIndexOfTabWithId(self.webStateList, itemID);
-  if (index != WebStateList::kInvalidIndex)
-    self.webStateList->CloseWebStateAt(index, WebStateList::CLOSE_USER_ACTION);
+  WebStateList* itemWebStateList = self.webStateList;
+  int index = GetIndexOfTabWithId(itemWebStateList, itemID);
+  if (index == WebStateList::kInvalidIndex) {
+    if (!IsTabsSearchEnabled())
+      return;
+    // If this is a search result, it may contain items from other windows -
+    // check other windows first before giving up.
+    BrowserList* browserList =
+        BrowserListFactory::GetForBrowserState(self.browserState);
+    Browser* browser = GetBrowserForTabWithId(
+        browserList, itemID, self.browserState->IsOffTheRecord());
+    if (!browser)
+      return;
+    itemWebStateList = browser->GetWebStateList();
+    index = GetIndexOfTabWithId(itemWebStateList, itemID);
+    // This item is not from the current browser therefore no UI updates will be
+    // sent to the current grid. So notify the current grid consumer about the
+    // change.
+    [self.consumer removeItemWithID:itemID selectedItemID:nil];
+    base::RecordAction(base::UserMetricsAction(
+        "MobileTabGridSearchCloseTabFromAnotherWindow"));
+  }
+  itemWebStateList->CloseWebStateAt(index, WebStateList::CLOSE_USER_ACTION);
 }
 
 - (void)closeItemsWithIDs:(NSArray<NSString*>*)itemIDs {
@@ -824,10 +845,8 @@
 
 // Calls |-populateItems:selectedItemID:| on the consumer.
 - (void)populateConsumerItems {
-  if (self.webStateList->count() > 0) {
-    [self.consumer populateItems:CreateItems(self.webStateList)
-                  selectedItemID:GetActiveTabId(self.webStateList)];
-  }
+  [self.consumer populateItems:CreateItems(self.webStateList)
+                selectedItemID:GetActiveTabId(self.webStateList)];
 }
 
 // Removes |self.syncedClosedTabsCount| most recent entries from the
diff --git a/ios/public/provider/chrome/browser/discover_feed/OWNERS b/ios/public/provider/chrome/browser/discover_feed/OWNERS
index 90c007a..e534c90 100644
--- a/ios/public/provider/chrome/browser/discover_feed/OWNERS
+++ b/ios/public/provider/chrome/browser/discover_feed/OWNERS
@@ -1,2 +1 @@
 sczs@chromium.org
-gogerald@chromium.org
diff --git a/media/gpu/android/codec_image_unittest.cc b/media/gpu/android/codec_image_unittest.cc
index ec8a7b10..308d574 100644
--- a/media/gpu/android/codec_image_unittest.cc
+++ b/media/gpu/android/codec_image_unittest.cc
@@ -51,7 +51,11 @@
 
     gl::init::InitializeStaticGLBindingsImplementation(
         gl::GLImplementationParts(gl::kGLImplementationEGLGLES2), false);
-    gl::init::InitializeGLOneOffPlatformImplementation(false, false, false);
+    gl::init::InitializeGLOneOffPlatformImplementation(
+        /*fallback_to_software_gl=*/false,
+        /*disable_gl_drawing=*/false,
+        /*init_extensions=*/false,
+        /*system_device_id=*/0);
 
     surface_ = new gl::PbufferGLSurfaceEGL(gfx::Size(320, 240));
     surface_->Initialize();
diff --git a/media/gpu/test/video_player/frame_renderer_thumbnail.cc b/media/gpu/test/video_player/frame_renderer_thumbnail.cc
index 973f5a85..68be5bc 100644
--- a/media/gpu/test/video_player/frame_renderer_thumbnail.cc
+++ b/media/gpu/test/video_player/frame_renderer_thumbnail.cc
@@ -307,7 +307,7 @@
 
   // Initialize GL rendering and create GL context.
   if (!gl_initialized_) {
-    if (!gl::init::InitializeGLOneOff())
+    if (!gl::init::InitializeGLOneOff(/*system_device_id=*/0))
       LOG(FATAL) << "Could not initialize GL";
     gl_initialized_ = true;
   }
diff --git a/media/mojo/mojom/stable/stable_video_decoder_types_mojom_traits.cc b/media/mojo/mojom/stable/stable_video_decoder_types_mojom_traits.cc
index f68ac29..28ad47c 100644
--- a/media/mojo/mojom/stable/stable_video_decoder_types_mojom_traits.cc
+++ b/media/mojo/mojom/stable/stable_video_decoder_types_mojom_traits.cc
@@ -7,6 +7,7 @@
 #include "gpu/ipc/common/gpu_memory_buffer_support.h"
 #include "media/base/format_utils.h"
 #include "media/gpu/buffer_validation.h"
+#include "mojo/public/cpp/bindings/optional_as_pointer.h"
 
 #if BUILDFLAG(USE_V4L2_CODEC)
 #include "media/gpu/v4l2/v4l2_status.h"
@@ -703,8 +704,8 @@
 }
 
 // static
-base::Value StructTraits<media::stable::mojom::StatusDataDataView,
-                         media::internal::StatusData>::
+const base::Value& StructTraits<media::stable::mojom::StatusDataDataView,
+                                media::internal::StatusData>::
     data(const media::internal::StatusData& input) {
   static_assert(
       std::is_same<decltype(input.data.Clone()),
@@ -713,7 +714,7 @@
       "need to change this assertion, please contact "
       "chromeos-gfx-video@google.com.");
 
-  return input.data.Clone();
+  return input.data;
 }
 
 // static
@@ -778,7 +779,7 @@
 }
 
 // static
-absl::optional<media::internal::StatusData> StructTraits<
+mojo::OptionalAsPointer<const media::internal::StatusData> StructTraits<
     media::stable::mojom::StatusDataView,
     media::DecoderStatus>::internal(const media::DecoderStatus& input) {
   static_assert(
@@ -791,9 +792,7 @@
 
   CHECK(input.data_ || input.is_ok());
 
-  if (input.data_)
-    return *input.data_;
-  return absl::nullopt;
+  return MakeOptionalAsPointer(input.data_.get());
 }
 
 // static
diff --git a/media/mojo/mojom/stable/stable_video_decoder_types_mojom_traits.h b/media/mojo/mojom/stable/stable_video_decoder_types_mojom_traits.h
index 232935757..33c8d7c5 100644
--- a/media/mojo/mojom/stable/stable_video_decoder_types_mojom_traits.h
+++ b/media/mojo/mojom/stable/stable_video_decoder_types_mojom_traits.h
@@ -6,6 +6,7 @@
 #define MEDIA_MOJO_MOJOM_STABLE_STABLE_VIDEO_DECODER_TYPES_MOJOM_TRAITS_H_
 
 #include "media/mojo/mojom/stable/stable_video_decoder_types.mojom.h"
+#include "mojo/public/cpp/bindings/optional_as_pointer.h"
 
 namespace mojo {
 
@@ -600,7 +601,7 @@
   static absl::optional<media::internal::StatusData> cause(
       const media::internal::StatusData& input);
 
-  static base::Value data(const media::internal::StatusData& input);
+  static const base::Value& data(const media::internal::StatusData& input);
 
   static bool Read(media::stable::mojom::StatusDataDataView data,
                    media::internal::StatusData* output);
@@ -609,7 +610,7 @@
 template <>
 struct StructTraits<media::stable::mojom::StatusDataView,
                     media::DecoderStatus> {
-  static absl::optional<media::internal::StatusData> internal(
+  static mojo::OptionalAsPointer<const media::internal::StatusData> internal(
       const media::DecoderStatus& input);
 
   static bool Read(media::stable::mojom::StatusDataView data,
diff --git a/media/mojo/mojom/status_mojom_traits.h b/media/mojo/mojom/status_mojom_traits.h
index 8572740..7180389 100644
--- a/media/mojo/mojom/status_mojom_traits.h
+++ b/media/mojo/mojom/status_mojom_traits.h
@@ -12,6 +12,7 @@
 #include "media/base/ipc/media_param_traits.h"
 #include "media/base/status.h"
 #include "media/mojo/mojom/media_types.mojom.h"
+#include "mojo/public/cpp/bindings/optional_as_pointer.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace mojo {
@@ -28,23 +29,22 @@
     return input.group;
   }
 
-  static std::string message(const media::internal::StatusData& input) {
+  static const std::string& message(const media::internal::StatusData& input) {
     return input.message;
   }
 
-  static base::span<base::Value> frames(media::internal::StatusData& input) {
+  static base::span<const base::Value> frames(
+      const media::internal::StatusData& input) {
     return input.frames;
   }
 
-  static absl::optional<media::internal::StatusData> cause(
+  static mojo::OptionalAsPointer<const media::internal::StatusData> cause(
       const media::internal::StatusData& input) {
-    if (input.cause)
-      return *input.cause;
-    return absl::nullopt;
+    return mojo::MakeOptionalAsPointer(input.cause.get());
   }
 
-  static base::Value data(const media::internal::StatusData& input) {
-    return input.data.Clone();
+  static const base::Value& data(const media::internal::StatusData& input) {
+    return input.data;
   }
 
   static bool Read(media::mojom::StatusDataDataView data,
@@ -53,11 +53,9 @@
 
 template <typename StatusEnum, typename DataView>
 struct StructTraits<DataView, media::TypedStatus<StatusEnum>> {
-  static absl::optional<media::internal::StatusData> internal(
+  static mojo::OptionalAsPointer<const media::internal::StatusData> internal(
       const media::TypedStatus<StatusEnum>& input) {
-    if (input.data_)
-      return *input.data_;
-    return absl::nullopt;
+    return mojo::MakeOptionalAsPointer(input.data_.get());
   }
 
   static bool Read(DataView data, media::TypedStatus<StatusEnum>* output) {
diff --git a/media/remoting/BUILD.gn b/media/remoting/BUILD.gn
index e45a3ea..504a880 100644
--- a/media/remoting/BUILD.gn
+++ b/media/remoting/BUILD.gn
@@ -39,7 +39,10 @@
 
     # Consumers of the CourierRenderer implicitly take a dependency on the
     # generated remoting.pb.h file.
-    public_deps += [ "//components/cast_streaming/public:remoting_utils" ]
+    public_deps += [
+      "//components/cast_streaming/public:remoting_utils",
+      "//components/openscreen_platform:openscreen_platform_network_service",
+    ]
   }
 }
 
@@ -61,7 +64,7 @@
 
   deps = [
     ":remoting_constants",
-    "//components/cast_streaming/public:remoting_utils",
+    "//components/openscreen_platform:openscreen_platform_network_service",
     "//media/mojo/common:common",
     "//media/mojo/mojom:remoting",
   ]
@@ -91,6 +94,7 @@
     "//base",
     "//base/test:test_support",
     "//components/cast_streaming/public:remoting_utils",
+    "//components/openscreen_platform:openscreen_platform_network_service",
     "//media:test_support",
     "//media/mojo/common",
     "//media/mojo/mojom:remoting",
@@ -112,7 +116,6 @@
     ]
 
     deps += [
-      "//components/cast_streaming/public:remoting_utils",
       "//media/test:pipeline_integration_test_base",
       "//services/service_manager/public/cpp:cpp",
       "//ui/gfx:test_support",
diff --git a/mojo/core/handle_table.cc b/mojo/core/handle_table.cc
index 1befb91..a044f1c8 100644
--- a/mojo/core/handle_table.cc
+++ b/mojo/core/handle_table.cc
@@ -73,8 +73,8 @@
   DCHECK_GE(next_available_handle_, 1u);
 
   // If this insertion would cause handle overflow, we're out of handles.
-  const uint64_t num_handles_available =
-      std::numeric_limits<uint64_t>::max() - next_available_handle_ + 1;
+  const uint32_t num_handles_available =
+      std::numeric_limits<uint32_t>::max() - next_available_handle_ + 1;
   if (num_handles_available < dispatchers.size()) {
     return false;
   }
diff --git a/mojo/core/handle_table.h b/mojo/core/handle_table.h
index c79b2a14..6718b6f 100644
--- a/mojo/core/handle_table.h
+++ b/mojo/core/handle_table.h
@@ -82,7 +82,7 @@
   HandleMap handles_;
   base::Lock lock_;
 
-  uint64_t next_available_handle_ = 1;
+  uint32_t next_available_handle_ = 1;
 };
 
 }  // namespace core
diff --git a/mojo/public/c/system/types.h b/mojo/public/c/system/types.h
index 0e1d16ad..56ffd78 100644
--- a/mojo/public/c/system/types.h
+++ b/mojo/public/c/system/types.h
@@ -22,7 +22,7 @@
 // |MojoHandle|: Handles to Mojo objects.
 //   |MOJO_HANDLE_INVALID| - A value that is never a valid handle.
 
-typedef uint64_t MojoHandle;
+typedef uint32_t MojoHandle;
 
 #ifdef __cplusplus
 const MojoHandle MOJO_HANDLE_INVALID = 0;
diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn
index 92e64d4..6436027 100644
--- a/mojo/public/cpp/bindings/BUILD.gn
+++ b/mojo/public/cpp/bindings/BUILD.gn
@@ -99,6 +99,7 @@
     "message.h",
     "message_header_validator.h",
     "message_metadata_helpers.h",
+    "optional_as_pointer.h",
     "scoped_interface_endpoint_handle.h",
     "scoped_message_error_crash_key.cc",
     "scoped_message_error_crash_key.h",
diff --git a/mojo/public/cpp/bindings/lib/serialization_forward.h b/mojo/public/cpp/bindings/lib/serialization_forward.h
index 06f7fa3..cffe7d8 100644
--- a/mojo/public/cpp/bindings/lib/serialization_forward.h
+++ b/mojo/public/cpp/bindings/lib/serialization_forward.h
@@ -5,12 +5,15 @@
 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_FORWARD_H_
 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_FORWARD_H_
 
+#include <type_traits>
+
 #include "mojo/public/cpp/bindings/array_traits.h"
 #include "mojo/public/cpp/bindings/enum_traits.h"
 #include "mojo/public/cpp/bindings/lib/buffer.h"
 #include "mojo/public/cpp/bindings/lib/message_fragment.h"
 #include "mojo/public/cpp/bindings/lib/template_util.h"
 #include "mojo/public/cpp/bindings/map_traits.h"
+#include "mojo/public/cpp/bindings/optional_as_pointer.h"
 #include "mojo/public/cpp/bindings/string_traits.h"
 #include "mojo/public/cpp/bindings/struct_traits.h"
 #include "mojo/public/cpp/bindings/union_traits.h"
@@ -28,62 +31,47 @@
 struct Serializer;
 
 template <typename T>
-struct IsOptionalWrapper {
-  static const bool value = IsSpecializationOf<
-      absl::optional,
-      typename std::remove_const<
-          typename std::remove_reference<T>::type>::type>::value;
-};
+using IsAbslOptional = IsSpecializationOf<absl::optional, std::decay_t<T>>;
 
-template <typename MojomType,
-          typename InputUserType,
-          typename... Args,
-          typename std::enable_if<
-              !IsOptionalWrapper<InputUserType>::value>::type* = nullptr>
+template <typename T>
+using IsOptionalAsPointer =
+    IsSpecializationOf<mojo::OptionalAsPointer, std::decay_t<T>>;
+
+template <typename MojomType, typename InputUserType, typename... Args>
 void Serialize(InputUserType&& input, Args&&... args) {
-  Serializer<MojomType, typename std::remove_reference<InputUserType>::type>::
-      Serialize(std::forward<InputUserType>(input),
-                std::forward<Args>(args)...);
-}
-
-template <typename MojomType,
-          typename DataType,
-          typename InputUserType,
-          typename... Args,
-          typename std::enable_if<
-              !IsOptionalWrapper<InputUserType>::value>::type* = nullptr>
-bool Deserialize(DataType&& input, InputUserType* output, Args&&... args) {
-  return Serializer<MojomType, InputUserType>::Deserialize(
-      std::forward<DataType>(input), output, std::forward<Args>(args)...);
-}
-
-template <typename MojomType,
-          typename InputUserType,
-          typename FragmentType,
-          typename... Args,
-          typename std::enable_if<
-              IsOptionalWrapper<InputUserType>::value>::type* = nullptr>
-void Serialize(InputUserType&& input, FragmentType& fragment, Args&&... args) {
-  if (!input)
-    return;
-  Serialize<MojomType>(*input, fragment, std::forward<Args>(args)...);
-}
-
-template <typename MojomType,
-          typename DataType,
-          typename InputUserType,
-          typename... Args,
-          typename std::enable_if<
-              IsOptionalWrapper<InputUserType>::value>::type* = nullptr>
-bool Deserialize(DataType&& input, InputUserType* output, Args&&... args) {
-  if (!input) {
-    *output = absl::nullopt;
-    return true;
+  if constexpr (IsAbslOptional<InputUserType>::value) {
+    if (!input)
+      return;
+    Serialize<MojomType>(*input, std::forward<Args>(args)...);
+  } else if constexpr (IsOptionalAsPointer<InputUserType>::value) {
+    if (!input.has_value())
+      return;
+    Serialize<MojomType>(*input.value(), std::forward<Args>(args)...);
+  } else {
+    Serializer<MojomType, std::remove_reference_t<InputUserType>>::Serialize(
+        std::forward<InputUserType>(input), std::forward<Args>(args)...);
   }
-  if (!*output)
-    output->emplace();
-  return Deserialize<MojomType>(std::forward<DataType>(input), &output->value(),
-                                std::forward<Args>(args)...);
+}
+
+template <typename MojomType,
+          typename DataType,
+          typename InputUserType,
+          typename... Args>
+bool Deserialize(DataType&& input, InputUserType* output, Args&&... args) {
+  if constexpr (IsAbslOptional<InputUserType>::value) {
+    if (!input) {
+      *output = absl::nullopt;
+      return true;
+    }
+    if (!*output)
+      output->emplace();
+    return Deserialize<MojomType>(std::forward<DataType>(input),
+                                  &output->value(),
+                                  std::forward<Args>(args)...);
+  } else {
+    return Serializer<MojomType, InputUserType>::Deserialize(
+        std::forward<DataType>(input), output, std::forward<Args>(args)...);
+  }
 }
 
 }  // namespace internal
diff --git a/mojo/public/cpp/bindings/lib/serialization_util.h b/mojo/public/cpp/bindings/lib/serialization_util.h
index 4384f4c..5f990d7b 100644
--- a/mojo/public/cpp/bindings/lib/serialization_util.h
+++ b/mojo/public/cpp/bindings/lib/serialization_util.h
@@ -98,7 +98,7 @@
 
 template <typename MojomType, typename UserType>
 constexpr bool IsValidUserTypeForOptionalValue() {
-  if constexpr (IsOptionalWrapper<UserType>::value) {
+  if constexpr (IsAbslOptional<UserType>::value) {
     return true;
   } else {
     using Traits = typename TraitsFinder<MojomType, UserType>::Traits;
diff --git a/mojo/public/cpp/bindings/optional_as_pointer.h b/mojo/public/cpp/bindings/optional_as_pointer.h
new file mode 100644
index 0000000..81617fe
--- /dev/null
+++ b/mojo/public/cpp/bindings/optional_as_pointer.h
@@ -0,0 +1,71 @@
+// 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 MOJO_PUBLIC_CPP_BINDINGS_OPTIONAL_AS_POINTER_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_OPTIONAL_AS_POINTER_H_
+
+#include <cstddef>
+
+namespace mojo {
+
+// Simple wrapper around a pointer to allow zero-copy serialization of a
+// nullable type.
+//
+// Traits for nullable fields typically return `const absl::optional<T>&` or
+// `absl::optional<T>&`. However, if the field is not already an
+// `absl::optional`, this can be inefficient:
+//
+//   static absl::optional<std::string> nullable_field_getter(
+//       const MyType& input) {
+//     // Bad: copies input.data() to populate `absl::optional`.
+//     return absl::make_optional(
+//         input.has_valid_data() ? input.data() : absl::nullopt);
+//   }
+//
+// Using this wrapper allows this to be serialized without additional copies:
+//
+//   static mojo::OptionalAsPointer<std::string> nullable_field_getter(
+//       const MyType& input) {
+//     return mojo::MakeOptionalAsPointer(
+//         input.has_valid_data() ? &input.data() : nullptr);
+//   }
+//
+// N.B. The original prototype for reducing copies in serialization attempted to
+// use C++ pointers directly; unfortunately, some Windows SDK opaque handle
+// types are actually defined as a pointer to a struct, which confused the Mojo
+// serialization traits. While it is possible to block the problematic types,
+// having an actual type makes the intent more explicit.
+template <typename T>
+class OptionalAsPointer {
+ public:
+  explicit OptionalAsPointer(T* ptr) : value_(ptr) {}
+  OptionalAsPointer(std::nullptr_t) {}
+
+  // Allows for conversions between compatible pointer types (e.g. from `T*` to
+  // `const T*`). For simplicity, this does not bother with using SFINAE to
+  // restrict conversions: assignment of the underlying pointer will give a
+  // compile error that is hopefully "good enough".
+  template <typename U>
+  OptionalAsPointer(const OptionalAsPointer<U>& other) : value_(other.value_) {}
+
+  bool has_value() const { return value_ != nullptr; }
+  T* value() const { return value_; }
+
+ private:
+  template <typename U>
+  friend class OptionalAsPointer;
+
+  T* value_ = nullptr;
+};
+
+// Type-deducing helpers for constructing a `OptionalAsPointer`.
+// TODO(dcheng): Remove this when we have C++20.
+template <int&... ExplicitArgumentBarrier, typename T>
+OptionalAsPointer<T> MakeOptionalAsPointer(T* ptr) {
+  return OptionalAsPointer<T>(ptr);
+}
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_BINDINGS_OPTIONAL_AS_POINTER_H_
diff --git a/mojo/public/java/system/core_impl.cc b/mojo/public/java/system/core_impl.cc
index 203323f..0e00fbb 100644
--- a/mojo/public/java/system/core_impl.cc
+++ b/mojo/public/java/system/core_impl.cc
@@ -82,19 +82,19 @@
   }
   MojoHandle handle;
   MojoResult result = MojoCreateSharedBuffer(num_bytes, options, &handle);
-  return Java_CoreImpl_newResultAndLong(env, result, handle);
+  return Java_CoreImpl_newResultAndInteger(env, result, handle);
 }
 
 static jint JNI_CoreImpl_Close(JNIEnv* env,
                                const JavaParamRef<jobject>& jcaller,
-                               jlong mojo_handle) {
+                               jint mojo_handle) {
   return MojoClose(mojo_handle);
 }
 
 static jint JNI_CoreImpl_QueryHandleSignalsState(
     JNIEnv* env,
     const JavaParamRef<jobject>& jcaller,
-    jlong mojo_handle,
+    jint mojo_handle,
     const JavaParamRef<jobject>& buffer) {
   MojoHandleSignalsState* signals_state =
       static_cast<MojoHandleSignalsState*>(env->GetDirectBufferAddress(buffer));
@@ -107,7 +107,7 @@
 static jint JNI_CoreImpl_WriteMessage(
     JNIEnv* env,
     const JavaParamRef<jobject>& jcaller,
-    jlong mojo_handle,
+    jint mojo_handle,
     const JavaParamRef<jobject>& bytes,
     jint num_bytes,
     const JavaParamRef<jobject>& handles_buffer,
@@ -125,8 +125,7 @@
   if (handles_buffer) {
     handles =
         static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer));
-    num_handles =
-        env->GetDirectBufferCapacity(handles_buffer) / sizeof(MojoHandle);
+    num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4;
   }
   // Java code will handle invalidating handles if the write succeeded.
   return WriteMessageRaw(
@@ -137,7 +136,7 @@
 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_ReadMessage(
     JNIEnv* env,
     const JavaParamRef<jobject>& jcaller,
-    jlong mojo_handle,
+    jint mojo_handle,
     jint flags) {
   ScopedMessageHandle message;
   MojoResult result =
@@ -171,14 +170,14 @@
       env, result,
       base::android::ToJavaByteArray(env, static_cast<uint8_t*>(buffer),
                                      num_bytes),
-      base::android::ToJavaLongArray(
-          env, reinterpret_cast<jlong*>(handles.data()), num_handles));
+      base::android::ToJavaIntArray(
+          env, reinterpret_cast<jint*>(handles.data()), num_handles));
 }
 
 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_ReadData(
     JNIEnv* env,
     const JavaParamRef<jobject>& jcaller,
-    jlong mojo_handle,
+    jint mojo_handle,
     const JavaParamRef<jobject>& elements,
     jint elements_capacity,
     jint flags) {
@@ -201,7 +200,7 @@
 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_BeginReadData(
     JNIEnv* env,
     const JavaParamRef<jobject>& jcaller,
-    jlong mojo_handle,
+    jint mojo_handle,
     jint num_bytes,
     jint flags) {
   void const* buffer = 0;
@@ -224,7 +223,7 @@
 
 static jint JNI_CoreImpl_EndReadData(JNIEnv* env,
                                      const JavaParamRef<jobject>& jcaller,
-                                     jlong mojo_handle,
+                                     jint mojo_handle,
                                      jint num_bytes_read) {
   return MojoEndReadData(mojo_handle, num_bytes_read, nullptr);
 }
@@ -232,7 +231,7 @@
 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_WriteData(
     JNIEnv* env,
     const JavaParamRef<jobject>& jcaller,
-    jlong mojo_handle,
+    jint mojo_handle,
     const JavaParamRef<jobject>& elements,
     jint limit,
     jint flags) {
@@ -253,7 +252,7 @@
 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_BeginWriteData(
     JNIEnv* env,
     const JavaParamRef<jobject>& jcaller,
-    jlong mojo_handle,
+    jint mojo_handle,
     jint num_bytes,
     jint flags) {
   void* buffer = 0;
@@ -275,7 +274,7 @@
 
 static jint JNI_CoreImpl_EndWriteData(JNIEnv* env,
                                       const JavaParamRef<jobject>& jcaller,
-                                      jlong mojo_handle,
+                                      jint mojo_handle,
                                       jint num_bytes_written) {
   return MojoEndWriteData(mojo_handle, num_bytes_written, nullptr);
 }
@@ -283,7 +282,7 @@
 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_Duplicate(
     JNIEnv* env,
     const JavaParamRef<jobject>& jcaller,
-    jlong mojo_handle,
+    jint mojo_handle,
     const JavaParamRef<jobject>& options_buffer) {
   const MojoDuplicateBufferHandleOptions* options = 0;
   if (options_buffer) {
@@ -297,13 +296,13 @@
   }
   MojoHandle handle;
   MojoResult result = MojoDuplicateBufferHandle(mojo_handle, options, &handle);
-  return Java_CoreImpl_newResultAndLong(env, result, handle);
+  return Java_CoreImpl_newResultAndInteger(env, result, handle);
 }
 
 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_Map(
     JNIEnv* env,
     const JavaParamRef<jobject>& jcaller,
-    jlong mojo_handle,
+    jint mojo_handle,
     jlong offset,
     jlong num_bytes,
     jint flags) {
@@ -344,7 +343,7 @@
   return alignment - offset;
 }
 
-static jlong JNI_CoreImpl_CreatePlatformHandle(JNIEnv* env, jint fd) {
+static jint JNI_CoreImpl_CreatePlatformHandle(JNIEnv* env, jint fd) {
   mojo::ScopedHandle handle =
       mojo::WrapPlatformHandle(mojo::PlatformHandle(base::ScopedFD(fd)));
   return handle.release().value();
diff --git a/mojo/public/java/system/javatests/src/org/chromium/mojo/HandleMock.java b/mojo/public/java/system/javatests/src/org/chromium/mojo/HandleMock.java
index c0e48abc..715e1e54 100644
--- a/mojo/public/java/system/javatests/src/org/chromium/mojo/HandleMock.java
+++ b/mojo/public/java/system/javatests/src/org/chromium/mojo/HandleMock.java
@@ -77,7 +77,7 @@
      * @see Handle#releaseNativeHandle()
      */
     @Override
-    public long releaseNativeHandle() {
+    public int releaseNativeHandle() {
         return 0;
     }
 
diff --git a/mojo/public/java/system/javatests/src/org/chromium/mojo/bindings/BindingsVersioningTest.java b/mojo/public/java/system/javatests/src/org/chromium/mojo/bindings/BindingsVersioningTest.java
index 6120083..762da41 100644
--- a/mojo/public/java/system/javatests/src/org/chromium/mojo/bindings/BindingsVersioningTest.java
+++ b/mojo/public/java/system/javatests/src/org/chromium/mojo/bindings/BindingsVersioningTest.java
@@ -119,7 +119,7 @@
         }
 
         {
-            long expectedHandle = 42;
+            int expectedHandle = 42;
             MultiVersionStructV7 v7 = new MultiVersionStructV7();
             v7.fInt32 = 123;
             v7.fRect = newRect(5);
@@ -198,7 +198,7 @@
         }
 
         {
-            long expectedHandle = 42;
+            int expectedHandle = 42;
             MultiVersionStructV7 expected = new MultiVersionStructV7();
             expected.fInt32 = 123;
             expected.fRect = newRect(5);
diff --git a/mojo/public/java/system/src/org/chromium/mojo/system/Core.java b/mojo/public/java/system/src/org/chromium/mojo/system/Core.java
index f059ef3..7b5684b 100644
--- a/mojo/public/java/system/src/org/chromium/mojo/system/Core.java
+++ b/mojo/public/java/system/src/org/chromium/mojo/system/Core.java
@@ -166,7 +166,7 @@
      *
      * @return a new {@link UntypedHandle} representing the native handle.
      */
-    public UntypedHandle acquireNativeHandle(long handle);
+    public UntypedHandle acquireNativeHandle(int handle);
 
     /**
      * Creates and acquires a handle from the native side. The handle will be owned by the returned
diff --git a/mojo/public/java/system/src/org/chromium/mojo/system/Handle.java b/mojo/public/java/system/src/org/chromium/mojo/system/Handle.java
index 558ba5c..903f36d 100644
--- a/mojo/public/java/system/src/org/chromium/mojo/system/Handle.java
+++ b/mojo/public/java/system/src/org/chromium/mojo/system/Handle.java
@@ -56,5 +56,6 @@
      * Releases the native handle backed by this {@link Handle}. The caller owns the handle and must
      * close it.
      */
-    public long releaseNativeHandle();
+    public int releaseNativeHandle();
+
 }
diff --git a/mojo/public/java/system/src/org/chromium/mojo/system/InvalidHandle.java b/mojo/public/java/system/src/org/chromium/mojo/system/InvalidHandle.java
index 2ea4397..5292605 100644
--- a/mojo/public/java/system/src/org/chromium/mojo/system/InvalidHandle.java
+++ b/mojo/public/java/system/src/org/chromium/mojo/system/InvalidHandle.java
@@ -80,7 +80,7 @@
      * @see Handle#releaseNativeHandle()
      */
     @Override
-    public long releaseNativeHandle() {
+    public int releaseNativeHandle() {
         return 0;
     }
 
diff --git a/mojo/public/java/system/src/org/chromium/mojo/system/MessagePipeHandle.java b/mojo/public/java/system/src/org/chromium/mojo/system/MessagePipeHandle.java
index f151cf29..baa5a9549 100644
--- a/mojo/public/java/system/src/org/chromium/mojo/system/MessagePipeHandle.java
+++ b/mojo/public/java/system/src/org/chromium/mojo/system/MessagePipeHandle.java
@@ -125,7 +125,7 @@
         /**
          * If a message was read, this contains the raw handle values.
          */
-        public long[] mRawHandles;
+        public int[] mRawHandles;
         /**
          * If a message was read, the handles contained in the message, undefined otherwise.
          */
diff --git a/mojo/public/java/system/src/org/chromium/mojo/system/impl/CoreImpl.java b/mojo/public/java/system/src/org/chromium/mojo/system/impl/CoreImpl.java
index 42f79ac..757636a 100644
--- a/mojo/public/java/system/src/org/chromium/mojo/system/impl/CoreImpl.java
+++ b/mojo/public/java/system/src/org/chromium/mojo/system/impl/CoreImpl.java
@@ -47,7 +47,7 @@
     /**
      * the size of a handle, in bytes.
      */
-    private static final int HANDLE_SIZE = 8;
+    private static final int HANDLE_SIZE = 4;
 
     /**
      * the size of a flag, in bytes.
@@ -57,7 +57,7 @@
     /**
      * The mojo handle for an invalid handle.
      */
-    static final long INVALID_HANDLE = 0;
+    static final int INVALID_HANDLE = 0;
 
     private static class LazyHolder { private static final Core INSTANCE = new CoreImpl(); }
 
@@ -106,7 +106,7 @@
             optionsBuffer.putInt(0, 8);
             optionsBuffer.putInt(4, options.getFlags().getFlags());
         }
-        ResultAnd<RawHandlePair> result =
+        ResultAnd<IntegerPair> result =
                 CoreImplJni.get().createMessagePipe(CoreImpl.this, optionsBuffer);
         if (result.getMojoResult() != MojoResult.OK) {
             throw new MojoException(result.getMojoResult());
@@ -129,7 +129,7 @@
             optionsBuffer.putInt(8, options.getElementNumBytes());
             optionsBuffer.putInt(12, options.getCapacityNumBytes());
         }
-        ResultAnd<RawHandlePair> result =
+        ResultAnd<IntegerPair> result =
                 CoreImplJni.get().createDataPipe(CoreImpl.this, optionsBuffer);
         if (result.getMojoResult() != MojoResult.OK) {
             throw new MojoException(result.getMojoResult());
@@ -151,7 +151,7 @@
             optionsBuffer.putInt(0, 8);
             optionsBuffer.putInt(4, options.getFlags().getFlags());
         }
-        ResultAnd<Long> result =
+        ResultAnd<Integer> result =
                 CoreImplJni.get().createSharedBuffer(CoreImpl.this, optionsBuffer, numBytes);
         if (result.getMojoResult() != MojoResult.OK) {
             throw new MojoException(result.getMojoResult());
@@ -160,10 +160,10 @@
     }
 
     /**
-     * @see org.chromium.mojo.system.Core#acquireNativeHandle(long)
+     * @see org.chromium.mojo.system.Core#acquireNativeHandle(int)
      */
     @Override
-    public UntypedHandle acquireNativeHandle(long handle) {
+    public UntypedHandle acquireNativeHandle(int handle) {
         return new UntypedHandleImpl(this, handle);
     }
 
@@ -172,7 +172,7 @@
      */
     @Override
     public UntypedHandle wrapFileDescriptor(ParcelFileDescriptor fd) {
-        long releasedHandle = CoreImplJni.get().createPlatformHandle(fd.detachFd());
+        int releasedHandle = CoreImplJni.get().createPlatformHandle(fd.detachFd());
         return acquireNativeHandle(releasedHandle);
     }
 
@@ -212,18 +212,18 @@
         mCurrentRunLoop.remove();
     }
 
-    int closeWithResult(long mojoHandle) {
+    int closeWithResult(int mojoHandle) {
         return CoreImplJni.get().close(CoreImpl.this, mojoHandle);
     }
 
-    void close(long mojoHandle) {
+    void close(int mojoHandle) {
         int mojoResult = CoreImplJni.get().close(CoreImpl.this, mojoHandle);
         if (mojoResult != MojoResult.OK) {
             throw new MojoException(mojoResult);
         }
     }
 
-    HandleSignalsState queryHandleSignalsState(long mojoHandle) {
+    HandleSignalsState queryHandleSignalsState(int mojoHandle) {
         ByteBuffer buffer = allocateDirectBuffer(8);
         int result = CoreImplJni.get().queryHandleSignalsState(CoreImpl.this, mojoHandle, buffer);
         if (result != MojoResult.OK) throw new MojoException(result);
@@ -240,7 +240,7 @@
         if (handles != null && !handles.isEmpty()) {
             handlesBuffer = allocateDirectBuffer(handles.size() * HANDLE_SIZE);
             for (Handle handle : handles) {
-                handlesBuffer.putLong(getMojoHandle(handle));
+                handlesBuffer.putInt(getMojoHandle(handle));
             }
             handlesBuffer.position(0);
         }
@@ -272,10 +272,10 @@
         }
 
         MessagePipeHandle.ReadMessageResult readResult = result.getValue();
-        long[] rawHandles = readResult.mRawHandles;
+        int[] rawHandles = readResult.mRawHandles;
         if (rawHandles != null && rawHandles.length != 0) {
             readResult.mHandles = new ArrayList<UntypedHandle>(rawHandles.length);
-            for (long rawHandle : rawHandles) {
+            for (int rawHandle : rawHandles) {
                 readResult.mHandles.add(new UntypedHandleImpl(this, rawHandle));
             }
         } else {
@@ -385,7 +385,7 @@
             optionsBuffer.putInt(0, 8);
             optionsBuffer.putInt(4, options.getFlags().getFlags());
         }
-        ResultAnd<Long> result =
+        ResultAnd<Integer> result =
                 CoreImplJni.get().duplicate(CoreImpl.this, handle.getMojoHandle(), optionsBuffer);
         if (result.getMojoResult() != MojoResult.OK) {
             throw new MojoException(result.getMojoResult());
@@ -418,7 +418,7 @@
     /**
      * @return the mojo handle associated to the given handle, considering invalid handles.
      */
-    private long getMojoHandle(Handle handle) {
+    private int getMojoHandle(Handle handle) {
         if (handle.isValid()) {
             return ((HandleBase) handle).getMojoHandle();
         }
@@ -459,18 +459,18 @@
     }
 
     /**
-     * Trivial alias for Pair<Long, Long>. This is needed because our jni generator is unable
+     * Trivial alias for Pair<Integer, Integer>. This is needed because our jni generator is unable
      * to handle class that contains space.
      */
-    static final class RawHandlePair extends Pair<Long, Long> {
-        public RawHandlePair(Long first, Long second) {
+    static final class IntegerPair extends Pair<Integer, Integer> {
+        public IntegerPair(Integer first, Integer second) {
             super(first, second);
         }
     }
 
     @CalledByNative
     private static ResultAnd<MessagePipeHandle.ReadMessageResult> newReadMessageResult(
-            int mojoResult, byte[] data, long[] rawHandles) {
+            int mojoResult, byte[] data, int[] rawHandles) {
         MessagePipeHandle.ReadMessageResult result = new MessagePipeHandle.ReadMessageResult();
         if (mojoResult == MojoResult.OK) {
             result.mData = data;
@@ -485,45 +485,39 @@
     }
 
     @CalledByNative
-    private static ResultAnd<Long> newResultAndLong(int mojoResult, long value) {
-        return new ResultAnd<>(mojoResult, value);
-    }
-
-    @CalledByNative
-    private static ResultAnd<RawHandlePair> newNativeCreationResult(
-            int mojoResult, long mojoHandle1, long mojoHandle2) {
-        return new ResultAnd<>(mojoResult, new RawHandlePair(mojoHandle1, mojoHandle2));
+    private static ResultAnd<IntegerPair> newNativeCreationResult(
+            int mojoResult, int mojoHandle1, int mojoHandle2) {
+        return new ResultAnd<>(mojoResult, new IntegerPair(mojoHandle1, mojoHandle2));
     }
 
     @NativeMethods
     interface Natives {
         long getTimeTicksNow(CoreImpl caller);
-        ResultAnd<RawHandlePair> createMessagePipe(CoreImpl caller, ByteBuffer optionsBuffer);
-        ResultAnd<RawHandlePair> createDataPipe(CoreImpl caller, ByteBuffer optionsBuffer);
-        ResultAnd<Long> createSharedBuffer(
+        ResultAnd<IntegerPair> createMessagePipe(CoreImpl caller, ByteBuffer optionsBuffer);
+        ResultAnd<IntegerPair> createDataPipe(CoreImpl caller, ByteBuffer optionsBuffer);
+        ResultAnd<Integer> createSharedBuffer(
                 CoreImpl caller, ByteBuffer optionsBuffer, long numBytes);
-        int close(CoreImpl caller, long mojoHandle);
-        int queryHandleSignalsState(
-                CoreImpl caller, long mojoHandle, ByteBuffer signalsStateBuffer);
-        int writeMessage(CoreImpl caller, long mojoHandle, ByteBuffer bytes, int numBytes,
+        int close(CoreImpl caller, int mojoHandle);
+        int queryHandleSignalsState(CoreImpl caller, int mojoHandle, ByteBuffer signalsStateBuffer);
+        int writeMessage(CoreImpl caller, int mojoHandle, ByteBuffer bytes, int numBytes,
                 ByteBuffer handlesBuffer, int flags);
         ResultAnd<MessagePipeHandle.ReadMessageResult> readMessage(
-                CoreImpl caller, long mojoHandle, int flags);
+                CoreImpl caller, int mojoHandle, int flags);
         ResultAnd<Integer> readData(
-                CoreImpl caller, long mojoHandle, ByteBuffer elements, int elementsSize, int flags);
+                CoreImpl caller, int mojoHandle, ByteBuffer elements, int elementsSize, int flags);
         ResultAnd<ByteBuffer> beginReadData(
-                CoreImpl caller, long mojoHandle, int numBytes, int flags);
-        int endReadData(CoreImpl caller, long mojoHandle, int numBytesRead);
+                CoreImpl caller, int mojoHandle, int numBytes, int flags);
+        int endReadData(CoreImpl caller, int mojoHandle, int numBytesRead);
         ResultAnd<Integer> writeData(
-                CoreImpl caller, long mojoHandle, ByteBuffer elements, int limit, int flags);
+                CoreImpl caller, int mojoHandle, ByteBuffer elements, int limit, int flags);
         ResultAnd<ByteBuffer> beginWriteData(
-                CoreImpl caller, long mojoHandle, int numBytes, int flags);
-        int endWriteData(CoreImpl caller, long mojoHandle, int numBytesWritten);
-        ResultAnd<Long> duplicate(CoreImpl caller, long mojoHandle, ByteBuffer optionsBuffer);
+                CoreImpl caller, int mojoHandle, int numBytes, int flags);
+        int endWriteData(CoreImpl caller, int mojoHandle, int numBytesWritten);
+        ResultAnd<Integer> duplicate(CoreImpl caller, int mojoHandle, ByteBuffer optionsBuffer);
         ResultAnd<ByteBuffer> map(
-                CoreImpl caller, long mojoHandle, long offset, long numBytes, int flags);
+                CoreImpl caller, int mojoHandle, long offset, long numBytes, int flags);
         int unmap(CoreImpl caller, ByteBuffer buffer);
         int getNativeBufferOffset(CoreImpl caller, ByteBuffer buffer, int alignment);
-        long createPlatformHandle(int fd);
+        int createPlatformHandle(int fd);
     }
 }
diff --git a/mojo/public/java/system/src/org/chromium/mojo/system/impl/DataPipeConsumerHandleImpl.java b/mojo/public/java/system/src/org/chromium/mojo/system/impl/DataPipeConsumerHandleImpl.java
index 587c14bb..820a6f9 100644
--- a/mojo/public/java/system/src/org/chromium/mojo/system/impl/DataPipeConsumerHandleImpl.java
+++ b/mojo/public/java/system/src/org/chromium/mojo/system/impl/DataPipeConsumerHandleImpl.java
@@ -15,9 +15,9 @@
  */
 class DataPipeConsumerHandleImpl extends HandleBase implements ConsumerHandle {
     /**
-     * @see HandleBase#HandleBase(CoreImpl, long)
+     * @see HandleBase#HandleBase(CoreImpl, int)
      */
-    DataPipeConsumerHandleImpl(CoreImpl core, long mojoHandle) {
+    DataPipeConsumerHandleImpl(CoreImpl core, int mojoHandle) {
         super(core, mojoHandle);
     }
 
diff --git a/mojo/public/java/system/src/org/chromium/mojo/system/impl/DataPipeProducerHandleImpl.java b/mojo/public/java/system/src/org/chromium/mojo/system/impl/DataPipeProducerHandleImpl.java
index 28d7a89..cf4eebe0 100644
--- a/mojo/public/java/system/src/org/chromium/mojo/system/impl/DataPipeProducerHandleImpl.java
+++ b/mojo/public/java/system/src/org/chromium/mojo/system/impl/DataPipeProducerHandleImpl.java
@@ -15,9 +15,9 @@
  */
 class DataPipeProducerHandleImpl extends HandleBase implements ProducerHandle {
     /**
-     * @see HandleBase#HandleBase(CoreImpl, long)
+     * @see HandleBase#HandleBase(CoreImpl, int)
      */
-    DataPipeProducerHandleImpl(CoreImpl core, long mojoHandle) {
+    DataPipeProducerHandleImpl(CoreImpl core, int mojoHandle) {
         super(core, mojoHandle);
     }
 
diff --git a/mojo/public/java/system/src/org/chromium/mojo/system/impl/HandleBase.java b/mojo/public/java/system/src/org/chromium/mojo/system/impl/HandleBase.java
index 5e7f787..9b7f5de 100644
--- a/mojo/public/java/system/src/org/chromium/mojo/system/impl/HandleBase.java
+++ b/mojo/public/java/system/src/org/chromium/mojo/system/impl/HandleBase.java
@@ -19,7 +19,7 @@
     /**
      * The pointer to the scoped handle owned by this object.
      */
-    private long mMojoHandle;
+    private int mMojoHandle;
 
     /**
      * The core implementation. Will be used to delegate all behavior.
@@ -29,7 +29,7 @@
     /**
      * Base constructor. Takes ownership of the passed handle.
      */
-    HandleBase(CoreImpl core, long mojoHandle) {
+    HandleBase(CoreImpl core, int mojoHandle) {
         mCore = core;
         mMojoHandle = mojoHandle;
     }
@@ -41,7 +41,7 @@
     protected HandleBase(HandleBase other) {
         mCore = other.mCore;
         HandleBase otherAsHandleImpl = other;
-        long mojoHandle = otherAsHandleImpl.mMojoHandle;
+        int mojoHandle = otherAsHandleImpl.mMojoHandle;
         otherAsHandleImpl.mMojoHandle = CoreImpl.INVALID_HANDLE;
         mMojoHandle = mojoHandle;
     }
@@ -53,7 +53,7 @@
     public void close() {
         if (mMojoHandle != CoreImpl.INVALID_HANDLE) {
             // After a close, the handle is invalid whether the close succeed or not.
-            long handle = mMojoHandle;
+            int handle = mMojoHandle;
             mMojoHandle = CoreImpl.INVALID_HANDLE;
             mCore.close(handle);
         }
@@ -95,8 +95,8 @@
      * @see Handle#releaseNativeHandle()
      */
     @Override
-    public long releaseNativeHandle() {
-        long result = mMojoHandle;
+    public int releaseNativeHandle() {
+        int result = mMojoHandle;
         mMojoHandle = CoreImpl.INVALID_HANDLE;
         return result;
     }
@@ -106,7 +106,7 @@
      *
      * @return the native scoped handle.
      */
-    long getMojoHandle() {
+    int getMojoHandle() {
         return mMojoHandle;
     }
 
diff --git a/mojo/public/java/system/src/org/chromium/mojo/system/impl/MessagePipeHandleImpl.java b/mojo/public/java/system/src/org/chromium/mojo/system/impl/MessagePipeHandleImpl.java
index db6a5b3b0..a2dd75d0 100644
--- a/mojo/public/java/system/src/org/chromium/mojo/system/impl/MessagePipeHandleImpl.java
+++ b/mojo/public/java/system/src/org/chromium/mojo/system/impl/MessagePipeHandleImpl.java
@@ -16,9 +16,9 @@
  */
 class MessagePipeHandleImpl extends HandleBase implements MessagePipeHandle {
     /**
-     * @see HandleBase#HandleBase(CoreImpl, long)
+     * @see HandleBase#HandleBase(CoreImpl, int)
      */
-    MessagePipeHandleImpl(CoreImpl core, long mojoHandle) {
+    MessagePipeHandleImpl(CoreImpl core, int mojoHandle) {
         super(core, mojoHandle);
     }
 
diff --git a/mojo/public/java/system/src/org/chromium/mojo/system/impl/SharedBufferHandleImpl.java b/mojo/public/java/system/src/org/chromium/mojo/system/impl/SharedBufferHandleImpl.java
index 560ed6ce..cd28a48 100644
--- a/mojo/public/java/system/src/org/chromium/mojo/system/impl/SharedBufferHandleImpl.java
+++ b/mojo/public/java/system/src/org/chromium/mojo/system/impl/SharedBufferHandleImpl.java
@@ -13,9 +13,9 @@
  */
 class SharedBufferHandleImpl extends HandleBase implements SharedBufferHandle {
     /**
-     * @see HandleBase#HandleBase(CoreImpl, long)
+     * @see HandleBase#HandleBase(CoreImpl, int)
      */
-    SharedBufferHandleImpl(CoreImpl core, long mojoHandle) {
+    SharedBufferHandleImpl(CoreImpl core, int mojoHandle) {
         super(core, mojoHandle);
     }
 
diff --git a/mojo/public/java/system/src/org/chromium/mojo/system/impl/UntypedHandleImpl.java b/mojo/public/java/system/src/org/chromium/mojo/system/impl/UntypedHandleImpl.java
index 8ddf784d..e365abf3 100644
--- a/mojo/public/java/system/src/org/chromium/mojo/system/impl/UntypedHandleImpl.java
+++ b/mojo/public/java/system/src/org/chromium/mojo/system/impl/UntypedHandleImpl.java
@@ -15,9 +15,9 @@
  */
 class UntypedHandleImpl extends HandleBase implements UntypedHandle {
     /**
-     * @see HandleBase#HandleBase(CoreImpl, long)
+     * @see HandleBase#HandleBase(CoreImpl, int)
      */
-    UntypedHandleImpl(CoreImpl core, long mojoHandle) {
+    UntypedHandleImpl(CoreImpl core, int mojoHandle) {
         super(core, mojoHandle);
     }
 
diff --git a/mojo/public/java/system/src/org/chromium/mojo/system/impl/WatcherImpl.java b/mojo/public/java/system/src/org/chromium/mojo/system/impl/WatcherImpl.java
index 8aec8844..ed4d7606 100644
--- a/mojo/public/java/system/src/org/chromium/mojo/system/impl/WatcherImpl.java
+++ b/mojo/public/java/system/src/org/chromium/mojo/system/impl/WatcherImpl.java
@@ -59,7 +59,7 @@
     @NativeMethods
     interface Natives {
         long createWatcher(WatcherImpl caller);
-        int start(WatcherImpl caller, long implPtr, long mojoHandle, int flags);
+        int start(WatcherImpl caller, long implPtr, int mojoHandle, int flags);
         void cancel(WatcherImpl caller, long implPtr);
         void delete(WatcherImpl caller, long implPtr);
     }
diff --git a/mojo/public/java/system/watcher_impl.cc b/mojo/public/java/system/watcher_impl.cc
index eb2c9ce0..065677f 100644
--- a/mojo/public/java/system/watcher_impl.cc
+++ b/mojo/public/java/system/watcher_impl.cc
@@ -33,7 +33,7 @@
 
   jint Start(JNIEnv* env,
              const JavaParamRef<jobject>& jcaller,
-             jlong mojo_handle,
+             jint mojo_handle,
              jint signals) {
     java_watcher_.Reset(env, jcaller);
 
@@ -83,7 +83,7 @@
 static jint JNI_WatcherImpl_Start(JNIEnv* env,
                                   const JavaParamRef<jobject>& jcaller,
                                   jlong watcher_ptr,
-                                  jlong mojo_handle,
+                                  jint mojo_handle,
                                   jint signals) {
   auto* watcher = reinterpret_cast<WatcherImpl*>(watcher_ptr);
   return watcher->Start(env, jcaller, mojo_handle, signals);
diff --git a/net/OWNERS b/net/OWNERS
index 95888ca0..7f44448 100644
--- a/net/OWNERS
+++ b/net/OWNERS
@@ -12,7 +12,6 @@
 pauljensen@chromium.org
 rch@chromium.org
 ricea@chromium.org
-rsleevi@chromium.org
 yhirano@chromium.org
 
 file://net/quic/OWNERS # For QUICHE rolls only.
diff --git a/net/base/registry_controlled_domains/OWNERS b/net/base/registry_controlled_domains/OWNERS
index 2ba05a6..9f8b179 100644
--- a/net/base/registry_controlled_domains/OWNERS
+++ b/net/base/registry_controlled_domains/OWNERS
@@ -1,3 +1,2 @@
 pam@chromium.org
 pkasting@chromium.org
-rsleevi@chromium.org
diff --git a/net/cert/OWNERS b/net/cert/OWNERS
index 72ba933e..f8d21715 100644
--- a/net/cert/OWNERS
+++ b/net/cert/OWNERS
@@ -1,4 +1,3 @@
 davidben@chromium.org
 mattm@chromium.org
-rsleevi@chromium.org
 svaldez@chromium.org
diff --git a/net/cert_net/OWNERS b/net/cert_net/OWNERS
index b05c25b..55cc021 100644
--- a/net/cert_net/OWNERS
+++ b/net/cert_net/OWNERS
@@ -1,2 +1 @@
 mattm@chromium.org
-rsleevi@chromium.org
diff --git a/net/ntlm/OWNERS b/net/ntlm/OWNERS
index 57eef363..1bef084 100644
--- a/net/ntlm/OWNERS
+++ b/net/ntlm/OWNERS
@@ -1,2 +1 @@
-rsleevi@chromium.org
 zentaro@chromium.org
diff --git a/net/third_party/mozilla_win/OWNERS b/net/third_party/mozilla_win/OWNERS
index 6949c15..1d084a8 100644
--- a/net/third_party/mozilla_win/OWNERS
+++ b/net/third_party/mozilla_win/OWNERS
@@ -1,3 +1,2 @@
 hchao@chromium.org
 davidben@chromium.org
-rsleevi@chromium.org
diff --git a/net/third_party/nss/OWNERS b/net/third_party/nss/OWNERS
index e6478b3b..679ba5e9 100644
--- a/net/third_party/nss/OWNERS
+++ b/net/third_party/nss/OWNERS
@@ -1,4 +1,3 @@
 agl@chromium.org
 davidben@chromium.org
-rsleevi@chromium.org
 wtc@chromium.org
diff --git a/pdf/paint_manager.cc b/pdf/paint_manager.cc
index 83927dd9..442018b 100644
--- a/pdf/paint_manager.cc
+++ b/pdf/paint_manager.cc
@@ -14,6 +14,7 @@
 #include "base/callback.h"
 #include "base/check.h"
 #include "base/location.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "pdf/paint_ready_rect.h"
 #include "pdf/ppapi_migration/callback.h"
@@ -160,11 +161,9 @@
   if (manual_callback_pending_)
     return;
 
-  client_->ScheduleTaskOnMainThread(
-      FROM_HERE,
-      base::BindOnce(&PaintManager::OnManualCallbackComplete,
-                     weak_factory_.GetWeakPtr()),
-      /*result=*/0, base::TimeDelta());
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(&PaintManager::OnManualCallbackComplete,
+                                weak_factory_.GetWeakPtr()));
   manual_callback_pending_ = true;
 }
 
@@ -290,7 +289,7 @@
   }
 }
 
-void PaintManager::OnManualCallbackComplete(int32_t) {
+void PaintManager::OnManualCallbackComplete() {
   DCHECK(manual_callback_pending_);
   manual_callback_pending_ = false;
 
diff --git a/pdf/paint_manager.h b/pdf/paint_manager.h
index 5854c01..a66cc32e 100644
--- a/pdf/paint_manager.h
+++ b/pdf/paint_manager.h
@@ -14,13 +14,8 @@
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "pdf/paint_aggregator.h"
-#include "pdf/ppapi_migration/callback.h"
 #include "ui/gfx/geometry/size.h"
 
-namespace base {
-class Location;
-}  // namespace base
-
 namespace gfx {
 class Point;
 class Rect;
@@ -73,17 +68,6 @@
                          std::vector<PaintReadyRect>& ready,
                          std::vector<gfx::Rect>& pending) = 0;
 
-    // Schedules work to be executed on a main thread after a specific delay.
-    // The `result` parameter will be passed as the argument to the `callback`.
-    // `result` is needed sometimes to emulate calls of some callbacks, but it's
-    // not always needed. `delay` should be no longer than `INT32_MAX`
-    // milliseconds for the Pepper plugin implementation to prevent integer
-    // overflow.
-    virtual void ScheduleTaskOnMainThread(const base::Location& from_here,
-                                          ResultCallback callback,
-                                          int32_t result,
-                                          base::TimeDelta delay) = 0;
-
    protected:
     // You shouldn't be doing deleting through this interface.
     ~Client() = default;
@@ -164,7 +148,7 @@
 
   // Callback for manual scheduling of paints when there is no flush callback
   // pending.
-  void OnManualCallbackComplete(int32_t);
+  void OnManualCallbackComplete();
 
   // Non-owning pointer. See the constructor.
   const raw_ptr<Client> client_;
diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h
index a74eda6..f1af57f 100644
--- a/pdf/pdf_engine.h
+++ b/pdf/pdf_engine.h
@@ -17,7 +17,6 @@
 #include "base/values.h"
 #include "build/build_config.h"
 #include "pdf/document_layout.h"
-#include "pdf/ppapi_migration/callback.h"
 #include "printing/mojom/print.mojom-forward.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -33,10 +32,6 @@
 
 class SkBitmap;
 
-namespace base {
-class Location;
-}  // namespace base
-
 namespace blink {
 class WebInputEvent;
 struct WebPrintParams;
@@ -289,17 +284,6 @@
     // viewers.
     // See https://crbug.com/312882 for an example.
     virtual bool IsValidLink(const std::string& url) = 0;
-
-    // Schedules work to be executed on a main thread after a specific delay.
-    // The `result` parameter will be passed as the argument to the `callback`.
-    // `result` is needed sometimes to emulate calls of some callbacks, but it's
-    // not always needed. `delay` should be no longer than `INT32_MAX`
-    // milliseconds for the Pepper plugin implementation to prevent integer
-    // overflow.
-    virtual void ScheduleTaskOnMainThread(const base::Location& from_here,
-                                          ResultCallback callback,
-                                          int32_t result,
-                                          base::TimeDelta delay) = 0;
   };
 
   virtual ~PDFEngine() = default;
diff --git a/pdf/pdf_view_plugin_base.cc b/pdf/pdf_view_plugin_base.cc
index 4302684..8fb0686 100644
--- a/pdf/pdf_view_plugin_base.cc
+++ b/pdf/pdf_view_plugin_base.cc
@@ -35,6 +35,7 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "net/base/escape.h"
@@ -324,11 +325,11 @@
     return;
 
   recently_sent_find_update_ = true;
-  ScheduleTaskOnMainThread(
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
       FROM_HERE,
       base::BindOnce(&PdfViewPluginBase::ResetRecentlySentFindUpdate,
                      GetWeakPtr()),
-      /*result=*/0, kFindResultCooldown);
+      kFindResultCooldown);
 }
 
 void PdfViewPluginBase::NotifyTouchSelectionOccurred() {
@@ -816,11 +817,9 @@
   if (deferred_invalidates_.empty())
     return;
 
-  ScheduleTaskOnMainThread(
-      FROM_HERE,
-      base::BindOnce(&PdfViewPluginBase::ClearDeferredInvalidates,
-                     GetWeakPtr()),
-      /*result=*/0, base::TimeDelta());
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(&PdfViewPluginBase::ClearDeferredInvalidates,
+                                GetWeakPtr()));
 }
 
 void PdfViewPluginBase::OnGeometryChanged(double old_zoom,
@@ -1050,11 +1049,11 @@
                            std::move(chars), std::move(page_objects));
 
   // Schedule loading the next page.
-  ScheduleTaskOnMainThread(
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
       FROM_HERE,
       base::BindOnce(&PdfViewPluginBase::PrepareAndSetAccessibilityPageInfo,
-                     GetWeakPtr()),
-      /*result=*/page_index + 1, kAccessibilityPageDelay);
+                     GetWeakPtr(), page_index + 1),
+      kAccessibilityPageDelay);
 }
 
 void PdfViewPluginBase::PrepareAndSetAccessibilityViewportInfo() {
@@ -1539,8 +1538,7 @@
       PaintReadyRect(rect, GetPluginImageData(), /*flush_now=*/true));
 }
 
-void PdfViewPluginBase::ClearDeferredInvalidates(
-    int32_t /*unused_but_required*/) {
+void PdfViewPluginBase::ClearDeferredInvalidates() {
   DCHECK(!in_paint_);
   for (const gfx::Rect& rect : deferred_invalidates_)
     Invalidate(rect);
@@ -1666,15 +1664,14 @@
   PrepareAndSetAccessibilityViewportInfo();
 
   // Schedule loading the first page.
-  ScheduleTaskOnMainThread(
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
       FROM_HERE,
       base::BindOnce(&PdfViewPluginBase::PrepareAndSetAccessibilityPageInfo,
-                     GetWeakPtr()),
-      /*result=*/0, kAccessibilityPageDelay);
+                     GetWeakPtr(), /*page_index=*/0),
+      kAccessibilityPageDelay);
 }
 
-void PdfViewPluginBase::ResetRecentlySentFindUpdate(
-    int32_t /*unused_but_required*/) {
+void PdfViewPluginBase::ResetRecentlySentFindUpdate() {
   recently_sent_find_update_ = false;
 }
 
diff --git a/pdf/pdf_view_plugin_base.h b/pdf/pdf_view_plugin_base.h
index 5d28ea3..085757e8 100644
--- a/pdf/pdf_view_plugin_base.h
+++ b/pdf/pdf_view_plugin_base.h
@@ -62,8 +62,6 @@
                           public PaintManager::Client,
                           public PreviewModeClient::Client {
  public:
-  using PDFEngine::Client::ScheduleTaskOnMainThread;
-
   // Do not save files with over 100 MB. This cap should be kept in sync with
   // and is also enforced in chrome/browser/resources/pdf/pdf_viewer.js.
   static constexpr size_t kMaximumSavedFileSize = 100 * 1000 * 1000;
@@ -480,7 +478,7 @@
   void PrepareForFirstPaint(std::vector<PaintReadyRect>& ready);
 
   // Callback to clear deferred invalidates after painting finishes.
-  void ClearDeferredInvalidates(int32_t /*unused_but_required*/);
+  void ClearDeferredInvalidates();
 
   // Sends the attachments data.
   void SendAttachments();
@@ -497,7 +495,7 @@
   // Starts loading accessibility information.
   void LoadAccessibility();
 
-  void ResetRecentlySentFindUpdate(int32_t /*unused_but_required*/);
+  void ResetRecentlySentFindUpdate();
 
   // Records metrics about the attachment types.
   void RecordAttachmentTypes();
diff --git a/pdf/pdf_view_plugin_base_unittest.cc b/pdf/pdf_view_plugin_base_unittest.cc
index 34e601d6..45662d6 100644
--- a/pdf/pdf_view_plugin_base_unittest.cc
+++ b/pdf/pdf_view_plugin_base_unittest.cc
@@ -201,11 +201,6 @@
 
   MOCK_METHOD(bool, BindPaintGraphics, (Graphics&), (override));
 
-  MOCK_METHOD(void,
-              ScheduleTaskOnMainThread,
-              (const base::Location&, ResultCallback, int32_t, base::TimeDelta),
-              (override));
-
   MOCK_METHOD(std::unique_ptr<PDFiumEngine>,
               CreateEngine,
               (PDFEngine::Client*, PDFiumFormFiller::ScriptOption),
diff --git a/pdf/pdf_view_web_plugin.cc b/pdf/pdf_view_web_plugin.cc
index 7181b1f5..6c8406b4 100644
--- a/pdf/pdf_view_web_plugin.cc
+++ b/pdf/pdf_view_web_plugin.cc
@@ -775,14 +775,6 @@
   return false;
 }
 
-void PdfViewWebPlugin::ScheduleTaskOnMainThread(const base::Location& from_here,
-                                                ResultCallback callback,
-                                                int32_t result,
-                                                base::TimeDelta delay) {
-  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-      from_here, base::BindOnce(std::move(callback), result), delay);
-}
-
 void PdfViewWebPlugin::SetCaretPosition(const gfx::PointF& position) {
   PdfViewPluginBase::SetCaretPosition(position);
 }
@@ -981,11 +973,9 @@
 }
 
 void PdfViewWebPlugin::InvokePrintDialog() {
-  ScheduleTaskOnMainThread(
-      FROM_HERE,
-      base::BindOnce(&PdfViewWebPlugin::OnInvokePrintDialog,
-                     weak_factory_.GetWeakPtr()),
-      /*result=*/0, base::TimeDelta());
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(&PdfViewWebPlugin::OnInvokePrintDialog,
+                                weak_factory_.GetWeakPtr()));
 }
 
 void PdfViewWebPlugin::NotifySelectionChanged(const gfx::PointF& left,
@@ -1096,7 +1086,7 @@
   }
 }
 
-void PdfViewWebPlugin::OnInvokePrintDialog(int32_t /*result*/) {
+void PdfViewWebPlugin::OnInvokePrintDialog() {
   client_->Print(Container()->GetElement());
 }
 
diff --git a/pdf/pdf_view_web_plugin.h b/pdf/pdf_view_web_plugin.h
index 01cc7b7..224a3694 100644
--- a/pdf/pdf_view_web_plugin.h
+++ b/pdf/pdf_view_web_plugin.h
@@ -250,10 +250,6 @@
   bool IsValidLink(const std::string& url) override;
   std::unique_ptr<Graphics> CreatePaintGraphics(const gfx::Size& size) override;
   bool BindPaintGraphics(Graphics& graphics) override;
-  void ScheduleTaskOnMainThread(const base::Location& from_here,
-                                ResultCallback callback,
-                                int32_t result,
-                                base::TimeDelta delay) override;
 
   // pdf::mojom::PdfListener:
   void SetCaretPosition(const gfx::PointF& position) override;
@@ -359,7 +355,7 @@
   // see crbug.com/66334.
   // TODO(crbug.com/1217012): Re-evaluate the need for a callback when parts of
   // the plugin are moved off the main thread.
-  void OnInvokePrintDialog(int32_t /*result*/);
+  void OnInvokePrintDialog();
 
   // Callback to set the document information in the accessibility tree
   // asynchronously.
diff --git a/pdf/pdf_view_web_plugin_unittest.cc b/pdf/pdf_view_web_plugin_unittest.cc
index 07c2c21..8d840cc 100644
--- a/pdf/pdf_view_web_plugin_unittest.cc
+++ b/pdf/pdf_view_web_plugin_unittest.cc
@@ -346,11 +346,8 @@
 
     // Waits for main thread callback scheduled by `PaintManager`.
     base::RunLoop run_loop;
-    plugin_->ScheduleTaskOnMainThread(
-        FROM_HERE, base::BindLambdaForTesting([&run_loop](int32_t /*result*/) {
-          run_loop.Quit();
-        }),
-        /*result=*/0, base::TimeDelta());
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                  run_loop.QuitClosure());
     run_loop.Run();
   }
 
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc
index 1304069..8c3cf63 100644
--- a/pdf/pdfium/pdfium_engine.cc
+++ b/pdf/pdfium/pdfium_engine.cc
@@ -592,11 +592,9 @@
     // asynchronously to avoid observable differences between this path and the
     // normal loading path.
     document_pending_ = false;
-    client_->ScheduleTaskOnMainThread(
-        FROM_HERE,
-        base::BindOnce(&PDFiumEngine::FinishLoadingDocument,
-                       weak_factory_.GetWeakPtr()),
-        /*result=*/0, base::TimeDelta());
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(&PDFiumEngine::FinishLoadingDocument,
+                                  weak_factory_.GetWeakPtr()));
   }
 }
 
@@ -823,7 +821,7 @@
 
 void PDFiumEngine::OnDocumentComplete() {
   if (doc())
-    return FinishLoadingDocument(0);
+    return FinishLoadingDocument();
 
   document_->file_access().m_FileLen = doc_loader_->GetDocumentSize();
   if (!fpdf_availability()) {
@@ -840,7 +838,7 @@
     OnDocumentComplete();
 }
 
-void PDFiumEngine::FinishLoadingDocument(int32_t /*unused_but_required*/) {
+void PDFiumEngine::FinishLoadingDocument() {
   // Note that doc_loader_->IsDocumentComplete() may not be true here if
   // called via `OnDocumentCanceled()`.
   DCHECK(doc());
@@ -1819,11 +1817,10 @@
   if (doc_loader_set_for_testing_) {
     ContinueFind(case_sensitive ? 1 : 0);
   } else {
-    client_->ScheduleTaskOnMainThread(
-        FROM_HERE,
-        base::BindOnce(&PDFiumEngine::ContinueFind,
-                       find_weak_factory_.GetWeakPtr()),
-        case_sensitive ? 1 : 0, base::TimeDelta());
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(&PDFiumEngine::ContinueFind,
+                                  find_weak_factory_.GetWeakPtr(),
+                                  case_sensitive ? 1 : 0));
   }
 }
 
@@ -2793,7 +2790,7 @@
   LoadBody();
 
   if (doc_loader_->IsDocumentComplete())
-    FinishLoadingDocument(0);
+    FinishLoadingDocument();
 }
 
 void PDFiumEngine::LoadPageInfo() {
diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h
index 4e91b64..2fea7e4 100644
--- a/pdf/pdfium/pdfium_engine.h
+++ b/pdf/pdfium/pdfium_engine.h
@@ -294,7 +294,7 @@
   // This should only be called after `doc_` has been loaded and the document is
   // fully downloaded.
   // If this has been run once, it will not notify the client again.
-  void FinishLoadingDocument(int32_t /*unused_but_required*/);
+  void FinishLoadingDocument();
 
   // Loads information about the pages in the document and performs layout.
   void LoadPageInfo();
diff --git a/pdf/pdfium/pdfium_engine_unittest.cc b/pdf/pdfium/pdfium_engine_unittest.cc
index 465c2ab..07efdb87 100644
--- a/pdf/pdfium/pdfium_engine_unittest.cc
+++ b/pdf/pdfium/pdfium_engine_unittest.cc
@@ -10,11 +10,13 @@
 
 #include "base/callback.h"
 #include "base/hash/md5.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/gmock_move_support.h"
 #include "base/test/gtest_util.h"
 #include "base/test/mock_callback.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "pdf/document_attachment_info.h"
@@ -73,13 +75,6 @@
               (const DocumentLayout& layout),
               (override));
   MOCK_METHOD(void, ScrollToPage, (int page), (override));
-  MOCK_METHOD(void,
-              ScheduleTaskOnMainThread,
-              (const base::Location& from_here,
-               ResultCallback callback,
-               int32_t result,
-               base::TimeDelta delay),
-              (override));
   MOCK_METHOD(void, DocumentFocusChanged, (bool), (override));
   MOCK_METHOD(void, SetLinkUnderCursor, (const std::string&), (override));
 };
@@ -134,15 +129,13 @@
     return loaded_incrementally;
   }
 
-  void FinishWithPluginSizeUpdated(MockTestClient& client,
-                                   PDFiumEngine& engine) {
-    ResultCallback callback;
-    EXPECT_CALL(client, ScheduleTaskOnMainThread)
-        .WillOnce(MoveArg<1>(&callback));
+  void FinishWithPluginSizeUpdated(PDFiumEngine& engine) {
     engine.PluginSizeUpdated({});
 
-    ASSERT_TRUE(callback);
-    std::move(callback).Run(0);
+    base::RunLoop run_loop;
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                  run_loop.QuitClosure());
+    run_loop.Run();
   }
 
   // Counts the number of available pages. Returns `int` instead of `size_t` for
@@ -279,7 +272,7 @@
   EXPECT_EQ(gfx::Size(343, 1664), engine.ApplyDocumentLayout(options));
 
   EXPECT_CALL(client, ScrollToPage(-1)).Times(1);
-  ASSERT_NO_FATAL_FAILURE(FinishWithPluginSizeUpdated(client, engine));
+  FinishWithPluginSizeUpdated(engine);
 }
 
 TEST_F(PDFiumEngineTest, ApplyDocumentLayoutAvoidsInfiniteLoop) {
@@ -511,7 +504,7 @@
   PDFiumEngine& engine = *initialize_result.engine;
 
   initialize_result.FinishLoading();
-  ASSERT_NO_FATAL_FAILURE(FinishWithPluginSizeUpdated(client, engine));
+  FinishWithPluginSizeUpdated(engine);
 
   EXPECT_EQ(engine.GetNumberOfPages(), CountAvailablePages(engine));
 }
diff --git a/pdf/preview_mode_client.cc b/pdf/preview_mode_client.cc
index 6971c81..1d3bb1a 100644
--- a/pdf/preview_mode_client.cc
+++ b/pdf/preview_mode_client.cc
@@ -173,12 +173,4 @@
   return false;
 }
 
-void PreviewModeClient::ScheduleTaskOnMainThread(
-    const base::Location& from_here,
-    ResultCallback callback,
-    int32_t result,
-    base::TimeDelta delay) {
-  NOTREACHED();
-}
-
 }  // namespace chrome_pdf
diff --git a/pdf/preview_mode_client.h b/pdf/preview_mode_client.h
index ee609e6..05f1cb8d 100644
--- a/pdf/preview_mode_client.h
+++ b/pdf/preview_mode_client.h
@@ -71,10 +71,6 @@
   void SetSelectedText(const std::string& selected_text) override;
   void SetLinkUnderCursor(const std::string& link_under_cursor) override;
   bool IsValidLink(const std::string& url) override;
-  void ScheduleTaskOnMainThread(const base::Location& from_here,
-                                ResultCallback callback,
-                                int32_t result,
-                                base::TimeDelta delay) override;
 
  private:
   const raw_ptr<Client> client_;
diff --git a/pdf/test/test_client.cc b/pdf/test/test_client.cc
index f8692791..c13b61eb 100644
--- a/pdf/test/test_client.cc
+++ b/pdf/test/test_client.cc
@@ -65,9 +65,4 @@
   return !url.empty();
 }
 
-void TestClient::ScheduleTaskOnMainThread(const base::Location& from_here,
-                                          ResultCallback callback,
-                                          int32_t result,
-                                          base::TimeDelta delay) {}
-
 }  // namespace chrome_pdf
diff --git a/pdf/test/test_client.h b/pdf/test/test_client.h
index 904523d..616ff801 100644
--- a/pdf/test/test_client.h
+++ b/pdf/test/test_client.h
@@ -40,10 +40,6 @@
   void SetSelectedText(const std::string& selected_text) override;
   void SetLinkUnderCursor(const std::string& link_under_cursor) override;
   bool IsValidLink(const std::string& url) override;
-  void ScheduleTaskOnMainThread(const base::Location& from_here,
-                                ResultCallback callback,
-                                int32_t result,
-                                base::TimeDelta delay) override;
 
  private:
   // Not owned. Expected to dangle briefly, as the engine usually is destroyed
diff --git a/printing/OWNERS b/printing/OWNERS
index a6ccfab..97f12041 100644
--- a/printing/OWNERS
+++ b/printing/OWNERS
@@ -2,6 +2,5 @@
 awscreen@chromium.org
 rbpotter@chromium.org
 thestig@chromium.org
-weili@chromium.org
 
 per-file printing_context_android*=ctzsm@chromium.org
diff --git a/remoting/base/chromoting_event.cc b/remoting/base/chromoting_event.cc
index 57b518c3..662d8c03 100644
--- a/remoting/base/chromoting_event.cc
+++ b/remoting/base/chromoting_event.cc
@@ -160,19 +160,19 @@
 
 void ChromotingEvent::SetString(const std::string& key,
                                 const std::string& value) {
-  values_map_->SetString(key, value);
+  values_map_->SetStringKey(key, value);
 }
 
 void ChromotingEvent::SetInteger(const std::string& key, int value) {
-  values_map_->SetInteger(key, value);
+  values_map_->SetIntKey(key, value);
 }
 
 void ChromotingEvent::SetBoolean(const std::string& key, bool value) {
-  values_map_->SetBoolean(key, value);
+  values_map_->SetBoolKey(key, value);
 }
 
 void ChromotingEvent::SetDouble(const std::string& key, double value) {
-  values_map_->SetDouble(key, value);
+  values_map_->SetDoubleKey(key, value);
 }
 
 bool ChromotingEvent::IsDataValid() {
diff --git a/sandbox/policy/win/sandbox_win.cc b/sandbox/policy/win/sandbox_win.cc
index 88df0f30..d916c59c 100644
--- a/sandbox/policy/win/sandbox_win.cc
+++ b/sandbox/policy/win/sandbox_win.cc
@@ -1106,7 +1106,7 @@
       delegate->GetAppContainerId(&appcontainer_id)) {
     result = AddAppContainerProfileToPolicy(cmd_line, sandbox_type,
                                             appcontainer_id, policy.get());
-    DCHECK(result == SBOX_ALL_OK);
+    DCHECK_EQ(result, SBOX_ALL_OK);
     if (result != SBOX_ALL_OK)
       return result;
   }
diff --git a/services/device/android/java/src/org/chromium/services/device/InterfaceRegistrar.java b/services/device/android/java/src/org/chromium/services/device/InterfaceRegistrar.java
index 98e17dcc..7f447d8 100644
--- a/services/device/android/java/src/org/chromium/services/device/InterfaceRegistrar.java
+++ b/services/device/android/java/src/org/chromium/services/device/InterfaceRegistrar.java
@@ -19,7 +19,8 @@
 @JNINamespace("device")
 class InterfaceRegistrar {
     @CalledByNative
-    static void createInterfaceRegistryForContext(long nativeHandle, NfcDelegate nfcDelegate) {
+    static void createInterfaceRegistryForContext(
+            int nativeHandle, NfcDelegate nfcDelegate) {
         // Note: The bindings code manages the lifetime of this object, so it
         // is not necessary to hold on to a reference to it explicitly.
         InterfaceRegistry registry = InterfaceRegistry.create(
diff --git a/services/network/first_party_sets/first_party_set_parser.cc b/services/network/first_party_sets/first_party_set_parser.cc
index 0985d64..b3fe9eb5 100644
--- a/services/network/first_party_sets/first_party_set_parser.cc
+++ b/services/network/first_party_sets/first_party_set_parser.cc
@@ -6,6 +6,7 @@
 
 #include <string>
 #include <utility>
+#include <vector>
 
 #include "base/containers/flat_map.h"
 #include "base/containers/flat_set.h"
@@ -59,69 +60,141 @@
 
 const char kFirstPartySetOwnerField[] = "owner";
 const char kFirstPartySetMembersField[] = "members";
+const char kFirstPartySetPolicyReplacementsField[] = "replacements";
+const char kFirstPartySetPolicyAdditionsField[] = "additions";
 
-// Parses a single First-Party Set into a map from member to owner (including an
-// entry owner -> owner). Note that this is intended for use *only* on sets that
-// were received via the Component Updater, so this does not check assertions
-// or versions. It rejects sets which are non-disjoint with
+// Validates a single First-Party Set and parses it into a SingleSet.
+// Note that this is intended for use *only* on sets that were received via the
+// Component Updater or from enterprise policy, so this does not check
+// assertions or versions. It rejects sets which are non-disjoint with
 // previously-encountered sets (i.e. sets which have non-empty intersections
 // with `elements`), and singleton sets (i.e. sets must have an owner and at
 // least one valid member).
 //
-// Uses `elements` to check disjointness of sets; builds the mapping in `map`;
+// Uses `elements` to check disjointness of sets; outputs the set as `out_set`;
 // and augments `elements` to include the elements of the set that was parsed.
 //
-// Returns true if parsing and validation were successful, false otherwise.
-bool ParseSet(const base::Value& value,
-              base::flat_map<net::SchemefulSite, net::SchemefulSite>& map,
-              base::flat_set<net::SchemefulSite>& elements) {
+// Returns a nullopt if parsing and validation were successful, otherwise it
+// returns an optional with an appropriate FirstPartySetParser::ParseError.
+absl::optional<FirstPartySetParser::ParseError> ParseSet(
+    const base::Value& value,
+    base::flat_set<net::SchemefulSite>& elements,
+    FirstPartySetParser::SingleSet& out_set) {
   if (!value.is_dict())
-    return false;
+    return FirstPartySetParser::ParseError::kInvalidType;
 
   // Confirm that the set has an owner, and the owner is a string.
   const std::string* maybe_owner =
-      value.FindStringKey(kFirstPartySetOwnerField);
+      value.GetDict().FindString(kFirstPartySetOwnerField);
   if (!maybe_owner)
-    return false;
+    return FirstPartySetParser::ParseError::kInvalidType;
 
   absl::optional<net::SchemefulSite> canonical_owner =
       Canonicalize(std::move(*maybe_owner), false /* emit_errors */);
   if (!canonical_owner.has_value())
-    return false;
+    return FirstPartySetParser::ParseError::kInvalidOrigin;
 
   // An owner may not be a member of another set.
   if (elements.contains(*canonical_owner))
-    return false;
+    return FirstPartySetParser::ParseError::kNonDisjointSets;
 
   elements.insert(*canonical_owner);
-  map.emplace(*canonical_owner, *canonical_owner);
 
   // Confirm that the members field is present, and is an array of strings.
   const base::Value* maybe_members_list =
       value.FindListKey(kFirstPartySetMembersField);
   if (!maybe_members_list)
-    return false;
+    return FirstPartySetParser::ParseError::kInvalidType;
 
+  if (maybe_members_list->GetListDeprecated().empty())
+    return FirstPartySetParser::ParseError::kSingletonSet;
+
+  std::vector<net::SchemefulSite> members;
   // Add each member to our mapping (assuming the member is a string).
   for (const auto& item : maybe_members_list->GetListDeprecated()) {
     // Members may not be a member of another set, and may not be an owner of
     // another set.
     if (!item.is_string())
-      return false;
+      return FirstPartySetParser::ParseError::kInvalidType;
     absl::optional<net::SchemefulSite> member =
         Canonicalize(item.GetString(), false /* emit_errors */);
-    if (!member.has_value() || elements.contains(*member))
-      return false;
-    map.emplace(*member, *canonical_owner);
+    if (!member.has_value())
+      return FirstPartySetParser::ParseError::kInvalidOrigin;
+
+    if (elements.contains(*member))
+      return FirstPartySetParser::ParseError::kNonDisjointSets;
+
+    members.push_back(*member);
     elements.insert(std::move(*member));
   }
-  return !maybe_members_list->GetListDeprecated().empty();
+
+  out_set = std::make_pair(*canonical_owner,
+                           base::flat_set<net::SchemefulSite>(members));
+  return absl::nullopt;
+}
+
+// Parses each set in `policy_sets` by calling ParseSet on each one.
+//
+// Returns a PolicyParsingError if ParseSet returns an error, which contains the
+// error that ParseSet returned along with the type of policy set that was being
+// parsed and the index of the set that caused the error.
+//
+// If no call to ParseSet returns an error, `out_list` is populated with the
+// list of parsed sets.
+absl::optional<FirstPartySetParser::PolicyParsingError> GetPolicySetsFromList(
+    const base::Value::List* policy_sets,
+    base::flat_set<net::SchemefulSite>& elements,
+    FirstPartySetParser::PolicySetType set_type,
+    std::vector<FirstPartySetParser::SingleSet>& out_list) {
+  if (!policy_sets) {
+    out_list = {};
+    return absl::nullopt;
+  }
+
+  std::vector<FirstPartySetParser::SingleSet> parsed_sets;
+  for (int i = 0; i < static_cast<int>(policy_sets->size()); i++) {
+    FirstPartySetParser::SingleSet out_set;
+    if (absl::optional<FirstPartySetParser::ParseError> error =
+            ParseSet((*policy_sets)[i], elements, out_set);
+        error.has_value()) {
+      return FirstPartySetParser::PolicyParsingError{error.value(), set_type,
+                                                     i};
+    }
+    parsed_sets.push_back(out_set);
+  }
+  out_list = parsed_sets;
+  return absl::nullopt;
 }
 
 }  // namespace
 
-base::flat_map<net::SchemefulSite, net::SchemefulSite>
-FirstPartySetParser::DeserializeFirstPartySets(base::StringPiece value) {
+bool FirstPartySetParser::PolicyParsingError::operator==(
+    const FirstPartySetParser::PolicyParsingError& other) const {
+  return std::tie(error, set_type, error_index) ==
+         std::tie(other.error, other.set_type, other.error_index);
+}
+
+FirstPartySetParser::ParsedPolicySetLists::ParsedPolicySetLists(
+    std::vector<FirstPartySetParser::SingleSet> replacement_list,
+    std::vector<FirstPartySetParser::SingleSet> addition_list)
+    : replacements(std::move(replacement_list)),
+      additions(std::move(addition_list)) {}
+
+FirstPartySetParser::ParsedPolicySetLists::ParsedPolicySetLists() = default;
+FirstPartySetParser::ParsedPolicySetLists::ParsedPolicySetLists(
+    FirstPartySetParser::ParsedPolicySetLists&&) = default;
+FirstPartySetParser::ParsedPolicySetLists::ParsedPolicySetLists(
+    const FirstPartySetParser::ParsedPolicySetLists&) = default;
+FirstPartySetParser::ParsedPolicySetLists::~ParsedPolicySetLists() = default;
+
+bool FirstPartySetParser::ParsedPolicySetLists::operator==(
+    const FirstPartySetParser::ParsedPolicySetLists& other) const {
+  return std::tie(replacements, additions) ==
+         std::tie(other.replacements, other.additions);
+}
+
+FirstPartySetParser::SetsMap FirstPartySetParser::DeserializeFirstPartySets(
+    base::StringPiece value) {
   if (value.empty())
     return {};
 
@@ -167,7 +240,7 @@
 }
 
 std::string FirstPartySetParser::SerializeFirstPartySets(
-    const base::flat_map<net::SchemefulSite, net::SchemefulSite>& sets) {
+    const FirstPartySetParser::SetsMap& sets) {
   base::DictionaryValue dict;
   for (const auto& it : sets) {
     std::string maybe_member = it.first.Serialize();
@@ -201,11 +274,46 @@
         trimmed, base::JSONParserOptions::JSON_ALLOW_TRAILING_COMMAS);
     if (!maybe_value.has_value())
       return {};
-    if (!ParseSet(*maybe_value, map, elements))
+    FirstPartySetParser::SingleSet output;
+    if (ParseSet(*maybe_value, elements, output).has_value())
       return {};
+    auto [owner, members] = output;
+    map.emplace(owner, owner);
+    for (net::SchemefulSite& member : members) {
+      map.emplace(std::move(member), owner);
+    }
+  }
+  return map;
+}
+
+absl::optional<FirstPartySetParser::PolicyParsingError>
+FirstPartySetParser::ParseSetsFromEnterprisePolicy(
+    const base::Value& policy,
+    FirstPartySetParser::ParsedPolicySetLists& out_sets) {
+  std::vector<SingleSet> parsed_replacements, parsed_additions;
+  base::flat_set<net::SchemefulSite> elements;
+
+  if (absl::optional<FirstPartySetParser::PolicyParsingError> error =
+          GetPolicySetsFromList(
+              policy.GetDict().FindList(kFirstPartySetPolicyReplacementsField),
+              elements, FirstPartySetParser::PolicySetType::kReplacement,
+              parsed_replacements);
+      error.has_value()) {
+    return error.value();
   }
 
-  return map;
+  if (absl::optional<FirstPartySetParser::PolicyParsingError> error =
+          GetPolicySetsFromList(
+              policy.GetDict().FindList(kFirstPartySetPolicyAdditionsField),
+              elements, FirstPartySetParser::PolicySetType::kAddition,
+              parsed_additions);
+      error.has_value()) {
+    return error.value();
+  }
+
+  out_sets = FirstPartySetParser::ParsedPolicySetLists(
+      std::move(parsed_replacements), std::move(parsed_additions));
+  return absl::nullopt;
 }
 
 }  // namespace network
diff --git a/services/network/first_party_sets/first_party_set_parser.h b/services/network/first_party_sets/first_party_set_parser.h
index 23d673e..a9f02413 100644
--- a/services/network/first_party_sets/first_party_set_parser.h
+++ b/services/network/first_party_sets/first_party_set_parser.h
@@ -6,11 +6,14 @@
 #define SERVICES_NETWORK_FIRST_PARTY_SETS_FIRST_PARTY_SET_PARSER_H_
 
 #include <istream>
+#include <utility>
 
 #include "base/callback.h"
 #include "base/containers/flat_map.h"
+#include "base/containers/flat_set.h"
 #include "base/files/file_path.h"
 #include "base/strings/string_piece_forward.h"
+#include "base/values.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace net {
@@ -21,6 +24,47 @@
 
 class FirstPartySetParser {
  public:
+  using SetsMap = base::flat_map<net::SchemefulSite, net::SchemefulSite>;
+  using SingleSet =
+      std::pair<net::SchemefulSite, base::flat_set<net::SchemefulSite>>;
+
+  enum ParseError {
+    kInvalidType,
+    kInvalidOrigin,
+    kSingletonSet,
+    kNonDisjointSets
+  };
+
+  enum PolicySetType { kReplacement, kAddition };
+
+  struct PolicyParsingError {
+    bool operator==(const PolicyParsingError& other) const;
+
+    // The kind of error that was found when parsing the policy sets.
+    ParseError error;
+    // The field of the policy that was being parsed when the error was found.
+    PolicySetType set_type;
+    // The index of the set in the 'set_type' list where the error was found.
+    int error_index;
+  };
+
+  struct ParsedPolicySetLists {
+    ParsedPolicySetLists(std::vector<SingleSet> replacement_list,
+                         std::vector<SingleSet> addition_list);
+
+    ParsedPolicySetLists();
+    ParsedPolicySetLists(ParsedPolicySetLists&&);
+    ParsedPolicySetLists& operator=(ParsedPolicySetLists&&) = default;
+    ParsedPolicySetLists(const ParsedPolicySetLists&);
+    ParsedPolicySetLists& operator=(const ParsedPolicySetLists&) = default;
+    ~ParsedPolicySetLists();
+
+    bool operator==(const ParsedPolicySetLists& other) const;
+
+    std::vector<SingleSet> replacements;
+    std::vector<SingleSet> additions;
+  };
+
   FirstPartySetParser() = delete;
   ~FirstPartySetParser() = delete;
 
@@ -34,8 +78,7 @@
   // received by Component Updater.
   //
   // Returns an empty map if parsing or validation of any set failed.
-  static base::flat_map<net::SchemefulSite, net::SchemefulSite>
-  ParseSetsFromStream(std::istream& input);
+  static SetsMap ParseSetsFromStream(std::istream& input);
 
   // Canonicalizes the passed in origin to a registered domain. In particular,
   // this ensures that the origin is non-opaque, is HTTPS, and has a registered
@@ -49,16 +92,27 @@
   // of the domains and the disjointness of the FPSs.
   //
   // Returns an empty map when deserialization fails, or the sets are invalid.
-  static base::flat_map<net::SchemefulSite, net::SchemefulSite>
-  DeserializeFirstPartySets(base::StringPiece value);
+  static SetsMap DeserializeFirstPartySets(base::StringPiece value);
 
   // Returns a serialized JSON-encoded string representation of the input. This
   // function does not check or have any special handling for the content of
   // `sets`, e.g. opaque origins are just serialized as "null".
   // The owner -> owner entry is removed from the serialized representation for
   // brevity.
-  static std::string SerializeFirstPartySets(
-      const base::flat_map<net::SchemefulSite, net::SchemefulSite>& sets);
+  static std::string SerializeFirstPartySets(const SetsMap& sets);
+
+  // Parses two lists of First-Party Sets from `policy` using the "replacements"
+  // and "additions" list fields if present.
+  //
+  // Returns an optional FirstPartySetParseError and the location of the error
+  // if any set in these lists violates the required invariants of First-Party
+  // Sets.
+  //
+  // If no errors are found, `out_sets` will be populated with the parsed
+  // replacement sets and parsed addition sets.
+  [[nodiscard]] static absl::optional<PolicyParsingError>
+  ParseSetsFromEnterprisePolicy(const base::Value& policy,
+                                ParsedPolicySetLists& out_sets);
 };
 
 }  // namespace network
diff --git a/services/network/first_party_sets/first_party_set_parser_unittest.cc b/services/network/first_party_sets/first_party_set_parser_unittest.cc
index e738ed45..70a46c57 100644
--- a/services/network/first_party_sets/first_party_set_parser_unittest.cc
+++ b/services/network/first_party_sets/first_party_set_parser_unittest.cc
@@ -16,6 +16,8 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
+using ::testing::ElementsAre;
+using ::testing::Eq;
 using ::testing::IsEmpty;
 using ::testing::Pair;
 using ::testing::UnorderedElementsAre;
@@ -384,4 +386,426 @@
                         R"({"https://member1.test":"https://example1.test",
             "https://example1.test":"https://example2.test"})")));
 
+TEST(ParseFromEnterpriseSetsTest, Accepts_MissingSetLists) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+              {
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              Eq(absl::nullopt));
+  EXPECT_THAT(out_sets, FirstPartySetParser::ParsedPolicySetLists({}, {}));
+}
+
+TEST(ParseFromEnterpriseSetsTest, Accepts_EmptyLists) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+              {
+                "replacements": [],
+                "additions": []
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              Eq(absl::nullopt));
+  EXPECT_THAT(out_sets, FirstPartySetParser::ParsedPolicySetLists({}, {}));
+}
+
+TEST(ParseFromEnterpriseSetsTest, InvalidTypeError_MissingOwner) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+              {
+                "replacements": [
+                  {
+                    "members": ["https://member1.test"]
+                  }
+                ],
+                "additions": []
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              FirstPartySetParser::PolicyParsingError(
+                  {FirstPartySetParser::ParseError::kInvalidType,
+                   FirstPartySetParser::PolicySetType::kReplacement, 0}));
+  EXPECT_THAT(out_sets, FirstPartySetParser::ParsedPolicySetLists({}, {}));
+}
+
+TEST(ParseFromEnterpriseSetsTest, InvalidTypeError_MissingMembers) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+              {
+                "replacements": [
+                  {
+                    "owner": "https://owner1.test"
+                  }
+                ],
+                "additions": []
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              FirstPartySetParser::PolicyParsingError(
+                  {FirstPartySetParser::ParseError::kInvalidType,
+                   FirstPartySetParser::PolicySetType::kReplacement, 0}));
+  EXPECT_THAT(out_sets, FirstPartySetParser::ParsedPolicySetLists({}, {}));
+}
+
+TEST(ParseFromEnterpriseSetsTest, InvalidTypeError_WrongOwnerType) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+              {
+                "replacements": [
+                  {
+                    "owner": 123,
+                    "members": ["https://member1.test"]
+                  }
+                ],
+                "additions": []
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              FirstPartySetParser::PolicyParsingError(
+                  {FirstPartySetParser::ParseError::kInvalidType,
+                   FirstPartySetParser::PolicySetType::kReplacement, 0}));
+  EXPECT_THAT(out_sets, FirstPartySetParser::ParsedPolicySetLists({}, {}));
+}
+
+TEST(ParseFromEnterpriseSetsTest, InvalidTypeError_WrongMembersFieldType) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+              {
+                "replacements": [
+                  {
+                    "owner": "https://owner1.test",
+                    "members": 123
+                  }
+                ],
+                "additions": []
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              FirstPartySetParser::PolicyParsingError(
+                  {FirstPartySetParser::ParseError::kInvalidType,
+                   FirstPartySetParser::PolicySetType::kReplacement, 0}));
+  EXPECT_THAT(out_sets, FirstPartySetParser::ParsedPolicySetLists({}, {}));
+}
+
+TEST(ParseFromEnterpriseSetsTest, InvalidTypeError_WrongMemberType) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+              {
+          "replacements": [
+            {
+              "owner": "https://owner1.test",
+              "members": ["https://member1.test", 123,
+              "https://member2.test"]
+            }
+          ],
+          "additions": []
+        }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              FirstPartySetParser::PolicyParsingError(
+                  {FirstPartySetParser::ParseError::kInvalidType,
+                   FirstPartySetParser::PolicySetType::kReplacement, 0}));
+  EXPECT_THAT(out_sets, FirstPartySetParser::ParsedPolicySetLists({}, {}));
+}
+
+TEST(ParseFromEnterpriseSetsTest, InvalidOriginError_OwnerOpaque) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+              {
+                "replacements": [
+                  {
+                    "owner": "",
+                    "members": ["https://member1.test"]
+                  }
+                ],
+                "additions": []
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              FirstPartySetParser::PolicyParsingError(
+                  {FirstPartySetParser::ParseError::kInvalidOrigin,
+                   FirstPartySetParser::PolicySetType::kReplacement, 0}));
+  EXPECT_THAT(out_sets, FirstPartySetParser::ParsedPolicySetLists({}, {}));
+}
+
+TEST(ParseFromEnterpriseSetsTest, InvalidOriginError_MemberOpaque) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+               {
+                "replacements": [
+                  {
+                    "owner": "https://owner1.test",
+                    "members": [""]
+                  }
+                ],
+                "additions": []
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              FirstPartySetParser::PolicyParsingError(
+                  {FirstPartySetParser::ParseError::kInvalidOrigin,
+                   FirstPartySetParser::PolicySetType::kReplacement, 0}));
+  EXPECT_THAT(out_sets, FirstPartySetParser::ParsedPolicySetLists({}, {}));
+}
+
+TEST(ParseFromEnterpriseSetsTest, InvalidOriginError_OwnerNonHttps) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+                 {
+                "replacements": [
+                  {
+                    "owner": "http://owner1.test",
+                    "members": ["https://member1.test"]
+                  }
+                ],
+                "additions": []
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              FirstPartySetParser::PolicyParsingError(
+                  {FirstPartySetParser::ParseError::kInvalidOrigin,
+                   FirstPartySetParser::PolicySetType::kReplacement, 0}));
+  EXPECT_THAT(out_sets, FirstPartySetParser::ParsedPolicySetLists({}, {}));
+}
+
+TEST(ParseFromEnterpriseSetsTest, InvalidOriginError_MemberNonHttps) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+               {
+                "replacements": [
+                  {
+                    "owner": "https://owner1.test",
+                    "members": ["http://member1.test"]
+                  }
+                ],
+                "additions": []
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              FirstPartySetParser::PolicyParsingError(
+                  {FirstPartySetParser::ParseError::kInvalidOrigin,
+                   FirstPartySetParser::PolicySetType::kReplacement, 0}));
+  EXPECT_THAT(out_sets, FirstPartySetParser::ParsedPolicySetLists({}, {}));
+}
+
+TEST(ParseFromEnterpriseSetsTest, InvalidOriginError_OwnerNonRegisteredDomain) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+                {
+                "replacements": [
+                  {
+                    "owner": "https://owner1.test..",
+                    "members": ["https://member1.test"]
+                  }
+                ],
+                "additions": []
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              FirstPartySetParser::PolicyParsingError(
+                  {FirstPartySetParser::ParseError::kInvalidOrigin,
+                   FirstPartySetParser::PolicySetType::kReplacement, 0}));
+  EXPECT_THAT(out_sets, FirstPartySetParser::ParsedPolicySetLists({}, {}));
+}
+
+TEST(ParseFromEnterpriseSetsTest,
+     InvalidOriginError_MemberNonRegisteredDomain) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+              {
+                "replacements": [
+                  {
+                    "owner": "https://owner1.test",
+                    "members": ["https://member1.test.."]
+                  }
+                ],
+                "additions": []
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              FirstPartySetParser::PolicyParsingError(
+                  {FirstPartySetParser::ParseError::kInvalidOrigin,
+                   FirstPartySetParser::PolicySetType::kReplacement, 0}));
+  EXPECT_THAT(out_sets, FirstPartySetParser::ParsedPolicySetLists({}, {}));
+}
+
+TEST(ParseFromEnterpriseSetsTest, SingletonSetError_EmptyMembers) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+             {
+                "replacements": [
+                  {
+                    "owner": "https://owner1.test",
+                    "members": []
+                  }
+                ],
+                "additions": []
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              FirstPartySetParser::PolicyParsingError(
+                  {FirstPartySetParser::ParseError::kSingletonSet,
+                   FirstPartySetParser::PolicySetType::kReplacement, 0}));
+  EXPECT_THAT(out_sets, FirstPartySetParser::ParsedPolicySetLists({}, {}));
+}
+
+TEST(ParseFromEnterpriseSetsTest, NonDisjointError_WithinReplacements) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+                   {
+                "replacements": [
+                  {
+                    "owner": "https://owner1.test",
+                    "members": ["https://member1.test"]
+                  },
+                  {
+                    "owner": "https://owner2.test",
+                    "members": ["https://member1.test"]
+                  }
+                ],
+                "additions": []
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              FirstPartySetParser::PolicyParsingError(
+                  {FirstPartySetParser::ParseError::kNonDisjointSets,
+                   FirstPartySetParser::PolicySetType::kReplacement, 1}));
+  EXPECT_THAT(out_sets, FirstPartySetParser::ParsedPolicySetLists({}, {}));
+}
+
+TEST(ParseFromEnterpriseSetsTest, NonDisjointError_WithinAdditions) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+                   {
+                "replacements": [],
+                "additions": [
+                  {
+                    "owner": "https://owner1.test",
+                    "members": ["https://member1.test"]
+                  },
+                  {
+                    "owner": "https://owner2.test",
+                    "members": ["https://member1.test"]
+                  }
+                ]
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              FirstPartySetParser::PolicyParsingError(
+                  {FirstPartySetParser::ParseError::kNonDisjointSets,
+                   FirstPartySetParser::PolicySetType::kAddition, 1}));
+  EXPECT_THAT(out_sets, FirstPartySetParser::ParsedPolicySetLists({}, {}));
+}
+
+TEST(ParseFromEnterpriseSetsTest, NonDisjointError_AcrossBothLists) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+               {
+                "replacements": [
+                  {
+                    "owner": "https://owner1.test",
+                    "members": ["https://member1.test"]
+                  }
+                ],
+                "additions": [
+                  {
+                    "owner": "https://owner2.test",
+                    "members": ["https://member1.test"]
+                  }
+                ]
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              FirstPartySetParser::PolicyParsingError(
+                  {FirstPartySetParser::ParseError::kNonDisjointSets,
+                   FirstPartySetParser::PolicySetType::kAddition, 0}));
+  EXPECT_THAT(out_sets, FirstPartySetParser::ParsedPolicySetLists({}, {}));
+}
+
+TEST(ParseFromEnterpriseSetsTest, SuccessfulMapping_SameList) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+             {
+                "replacements": [
+                  {
+                    "owner": "https://owner1.test",
+                    "members": ["https://member1.test"]
+                  },
+                  {
+                    "owner": "https://owner2.test",
+                    "members": ["https://member2.test"]
+                  }
+                ]
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              Eq(absl::nullopt));
+  EXPECT_THAT(
+      out_sets.replacements,
+      ElementsAre(
+          Pair(SerializesTo("https://owner1.test"),
+               UnorderedElementsAre(SerializesTo("https://member1.test"))),
+          Pair(SerializesTo("https://owner2.test"),
+               UnorderedElementsAre(SerializesTo("https://member2.test")))));
+  EXPECT_THAT(out_sets.additions, IsEmpty());
+}
+
+TEST(ParseFromEnterpriseSetsTest, SuccessfulMapping_CrossList) {
+  base::Value policy_value = base::JSONReader::Read(R"(
+                {
+                "replacements": [
+                  {
+                    "owner": "https://owner1.test",
+                    "members": ["https://member1.test"]
+                  },
+                  {
+                    "owner": "https://owner2.test",
+                    "members": ["https://member2.test"]
+                  }
+                ],
+                "additions": [
+                  {
+                    "owner": "https://owner3.test",
+                    "members": ["https://member3.test"]
+                  }
+                ]
+              }
+            )").value();
+  FirstPartySetParser::ParsedPolicySetLists out_sets;
+  EXPECT_THAT(FirstPartySetParser::ParseSetsFromEnterprisePolicy(policy_value,
+                                                                 out_sets),
+              Eq(absl::nullopt));
+  EXPECT_THAT(
+      out_sets.replacements,
+      ElementsAre(
+          Pair(SerializesTo("https://owner1.test"),
+               UnorderedElementsAre(SerializesTo("https://member1.test"))),
+          Pair(SerializesTo("https://owner2.test"),
+               UnorderedElementsAre(SerializesTo("https://member2.test")))));
+
+  EXPECT_THAT(out_sets.additions,
+              ElementsAre(Pair(
+                  SerializesTo("https://owner3.test"),
+                  UnorderedElementsAre(SerializesTo("https://member3.test")))));
+}
+
 }  // namespace network
diff --git a/services/network/first_party_sets/first_party_sets_loader.cc b/services/network/first_party_sets/first_party_sets_loader.cc
index 7744e98..de0b7ba4 100644
--- a/services/network/first_party_sets/first_party_sets_loader.cc
+++ b/services/network/first_party_sets/first_party_sets_loader.cc
@@ -80,7 +80,6 @@
   manually_specified_set_ = {CanonicalizeSet(base::SplitString(
       flag_value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY))};
 
-  ApplyManuallySpecifiedSet();
   MaybeFinishLoading();
 }
 
@@ -114,7 +113,6 @@
   std::istringstream stream(raw_sets);
   sets_ = FirstPartySetParser::ParseSetsFromStream(stream);
 
-  ApplyManuallySpecifiedSet();
   component_sets_parse_progress_ = Progress::kFinished;
   MaybeFinishLoading();
 }
@@ -133,10 +131,10 @@
 
 void FirstPartySetsLoader::ApplyManuallySpecifiedSet() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (!manually_specified_set_.has_value() ||
-      !manually_specified_set_.value().has_value()) {
+  DCHECK_EQ(component_sets_parse_progress_, Progress::kFinished);
+  DCHECK(manually_specified_set_.has_value());
+  if (!manually_specified_set_.value().has_value())
     return;
-  }
 
   const net::SchemefulSite& manual_owner =
       manually_specified_set_.value()->first;
@@ -179,6 +177,7 @@
   if (component_sets_parse_progress_ != Progress::kFinished ||
       !manually_specified_set_.has_value())
     return;
+  ApplyManuallySpecifiedSet();
   std::move(on_load_complete_).Run(std::move(sets_));
 }
 
diff --git a/services/network/first_party_sets/first_party_sets_loader.h b/services/network/first_party_sets/first_party_sets_loader.h
index dfcabede..2fc4d3b 100644
--- a/services/network/first_party_sets/first_party_sets_loader.h
+++ b/services/network/first_party_sets/first_party_sets_loader.h
@@ -56,15 +56,13 @@
   // declarations, and assigns to `sets_`.
   void OnReadSetsFile(const std::string& raw_sets);
 
-  // We must ensure there's no intersection between the manually-specified set
-  // and the sets that came from Component Updater. (When reconciling the
-  // manually-specified set and `sets_`, entries in the manually-specified set
-  // always win.) We must also ensure that `sets_` includes the set described by
-  // `manually_specified_set_`.
+  // Modifies `sets_` to include the CLI-provided set, if any. Must not be
+  // called until the loader has received the CLI flag value via
+  // `SetManuallySpecifiedSet`, and the public sets via `SetComponentSets`.
   void ApplyManuallySpecifiedSet();
 
   // Checks the required inputs have been received, and if so, invokes the
-  // callback `on_load_complete_`.
+  // callback `on_load_complete_`, after merging sets appropriately.
   void MaybeFinishLoading();
 
   // Represents the mapping of site -> site, where keys are members of sets,
diff --git a/services/network/public/cpp/net_ipc_param_traits.cc b/services/network/public/cpp/net_ipc_param_traits.cc
index c65f02d11..33be0d0 100644
--- a/services/network/public/cpp/net_ipc_param_traits.cc
+++ b/services/network/public/cpp/net_ipc_param_traits.cc
@@ -557,7 +557,14 @@
   WriteParam(m, p.GetTupleOrPrecursorTupleIfOpaque().scheme());
   WriteParam(m, p.GetTupleOrPrecursorTupleIfOpaque().host());
   WriteParam(m, p.GetTupleOrPrecursorTupleIfOpaque().port());
-  WriteParam(m, p.GetNonceForSerialization());
+  // Note: this is somewhat asymmetric with Read() to avoid extra copies during
+  // serialization. The actual serialized wire format matches how absl::optional
+  // values are normally serialized: see `ParamTraits<absl::optional<P>>`.
+  const base::UnguessableToken* nonce = p.GetNonceForSerialization();
+  WriteParam(m, nonce != nullptr);
+  if (nonce) {
+    WriteParam(m, *nonce);
+  }
 }
 
 bool ParamTraits<url::Origin>::Read(const base::Pickle* m,
diff --git a/services/shape_detection/android/java/src/org/chromium/shape_detection/InterfaceRegistrar.java b/services/shape_detection/android/java/src/org/chromium/shape_detection/InterfaceRegistrar.java
index daec82a4..a89d786 100644
--- a/services/shape_detection/android/java/src/org/chromium/shape_detection/InterfaceRegistrar.java
+++ b/services/shape_detection/android/java/src/org/chromium/shape_detection/InterfaceRegistrar.java
@@ -14,12 +14,12 @@
 
 @JNINamespace("shape_detection")
 class InterfaceRegistrar {
-    static MessagePipeHandle messagePipeHandleFromNative(long nativeHandle) {
+    static MessagePipeHandle messagePipeHandleFromNative(int nativeHandle) {
         return CoreImpl.getInstance().acquireNativeHandle(nativeHandle).toMessagePipeHandle();
     }
 
     @CalledByNative
-    static void bindBarcodeDetectionProvider(long nativeHandle) {
+    static void bindBarcodeDetectionProvider(int nativeHandle) {
         // Immediately wrap |nativeHandle| as it cannot be allowed to leak.
         MessagePipeHandle handle = messagePipeHandleFromNative(nativeHandle);
 
@@ -33,13 +33,13 @@
     }
 
     @CalledByNative
-    static void bindFaceDetectionProvider(long nativeHandle) {
+    static void bindFaceDetectionProvider(int nativeHandle) {
         FaceDetectionProvider.MANAGER.bind(
                 new FaceDetectionProviderImpl(), messagePipeHandleFromNative(nativeHandle));
     }
 
     @CalledByNative
-    static void bindTextDetection(long nativeHandle) {
+    static void bindTextDetection(int nativeHandle) {
         // Immediately wrap |nativeHandle| as it cannot be allowed to leak.
         MessagePipeHandle handle = messagePipeHandleFromNative(nativeHandle);
 
diff --git a/services/viz/public/cpp/compositing/copy_output_result_mojom_traits.cc b/services/viz/public/cpp/compositing/copy_output_result_mojom_traits.cc
index 494429cf..29d8b198 100644
--- a/services/viz/public/cpp/compositing/copy_output_result_mojom_traits.cc
+++ b/services/viz/public/cpp/compositing/copy_output_result_mojom_traits.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "mojo/public/cpp/bindings/optional_as_pointer.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 
@@ -143,50 +144,52 @@
 }
 
 // static
-absl::optional<gpu::Mailbox>
+mojo::OptionalAsPointer<const gpu::Mailbox>
 StructTraits<viz::mojom::CopyOutputResultDataView,
              std::unique_ptr<viz::CopyOutputResult>>::
     mailbox(const std::unique_ptr<viz::CopyOutputResult>& result) {
   if (result->destination() !=
           viz::CopyOutputResult::Destination::kNativeTextures ||
       result->IsEmpty()) {
-    return absl::nullopt;
+    return nullptr;
   }
 
   // Only RGBA can travel across process boundaries, in which case there will be
   // only one plane that is relevant in the |result|:
   DCHECK_EQ(result->format(), viz::CopyOutputResult::Format::RGBA);
-  return result->GetTextureResult()->planes[0].mailbox;
+  return mojo::MakeOptionalAsPointer(
+      &result->GetTextureResult()->planes[0].mailbox);
 }
 
 // static
-absl::optional<gpu::SyncToken>
+mojo::OptionalAsPointer<const gpu::SyncToken>
 StructTraits<viz::mojom::CopyOutputResultDataView,
              std::unique_ptr<viz::CopyOutputResult>>::
     sync_token(const std::unique_ptr<viz::CopyOutputResult>& result) {
   if (result->destination() !=
           viz::CopyOutputResult::Destination::kNativeTextures ||
       result->IsEmpty()) {
-    return absl::nullopt;
+    return nullptr;
   }
 
   // Only RGBA can travel across process boundaries, in which case there will be
   // only one plane that is relevant in the |result|:
   DCHECK_EQ(result->format(), viz::CopyOutputResult::Format::RGBA);
-  return result->GetTextureResult()->planes[0].sync_token;
+  return mojo::MakeOptionalAsPointer(
+      &result->GetTextureResult()->planes[0].sync_token);
 }
 
 // static
-absl::optional<gfx::ColorSpace>
+mojo::OptionalAsPointer<const gfx::ColorSpace>
 StructTraits<viz::mojom::CopyOutputResultDataView,
              std::unique_ptr<viz::CopyOutputResult>>::
     color_space(const std::unique_ptr<viz::CopyOutputResult>& result) {
   if (result->destination() !=
           viz::CopyOutputResult::Destination::kNativeTextures ||
       result->IsEmpty()) {
-    return absl::nullopt;
+    return nullptr;
   }
-  return result->GetTextureResult()->color_space;
+  return mojo::MakeOptionalAsPointer(&result->GetTextureResult()->color_space);
 }
 
 // static
diff --git a/services/viz/public/cpp/compositing/copy_output_result_mojom_traits.h b/services/viz/public/cpp/compositing/copy_output_result_mojom_traits.h
index da1946a1..32120dd 100644
--- a/services/viz/public/cpp/compositing/copy_output_result_mojom_traits.h
+++ b/services/viz/public/cpp/compositing/copy_output_result_mojom_traits.h
@@ -10,6 +10,7 @@
 #include "components/viz/common/frame_sinks/copy_output_result.h"
 #include "gpu/ipc/common/mailbox_mojom_traits.h"
 #include "gpu/ipc/common/sync_token_mojom_traits.h"
+#include "mojo/public/cpp/bindings/optional_as_pointer.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "services/viz/public/cpp/compositing/bitmap_in_shared_memory_mojom_traits.h"
 #include "services/viz/public/mojom/compositing/copy_output_result.mojom-shared.h"
@@ -56,13 +57,13 @@
   static absl::optional<viz::CopyOutputResult::ScopedSkBitmap> bitmap(
       const std::unique_ptr<viz::CopyOutputResult>& result);
 
-  static absl::optional<gpu::Mailbox> mailbox(
+  static mojo::OptionalAsPointer<const gpu::Mailbox> mailbox(
       const std::unique_ptr<viz::CopyOutputResult>& result);
 
-  static absl::optional<gpu::SyncToken> sync_token(
+  static mojo::OptionalAsPointer<const gpu::SyncToken> sync_token(
       const std::unique_ptr<viz::CopyOutputResult>& result);
 
-  static absl::optional<gfx::ColorSpace> color_space(
+  static mojo::OptionalAsPointer<const gfx::ColorSpace> color_space(
       const std::unique_ptr<viz::CopyOutputResult>& result);
 
   static mojo::PendingRemote<viz::mojom::TextureReleaser> releaser(
diff --git a/storage/OWNERS b/storage/OWNERS
index 7ccd317f..79b8072 100644
--- a/storage/OWNERS
+++ b/storage/OWNERS
@@ -3,4 +3,3 @@
 jsbell@chromium.org
 pwnall@chromium.org
 mek@chromium.org
-kinuko@chromium.org
diff --git a/storage/browser/BUILD.gn b/storage/browser/BUILD.gn
index 5e80213a..b1c4946 100644
--- a/storage/browser/BUILD.gn
+++ b/storage/browser/BUILD.gn
@@ -347,6 +347,7 @@
     "//services/network/public/cpp",
     "//services/network/public/mojom",
     "//sql:test_support",
+    "//storage/browser/quota:mojo_bindings",
     "//testing/gtest",
     "//third_party/blink/public/common",
     "//third_party/leveldatabase",
diff --git a/storage/browser/quota/quota_internals.mojom b/storage/browser/quota/quota_internals.mojom
index 226b34d..3e882091 100644
--- a/storage/browser/quota/quota_internals.mojom
+++ b/storage/browser/quota/quota_internals.mojom
@@ -4,8 +4,21 @@
 
 module storage.mojom;
 
+import "mojo/public/mojom/base/time.mojom";
 import "url/mojom/origin.mojom";
 
+// Represents a single Storage Bucket entry.
+struct BucketTableEntry {
+    int64 bucket_id;
+    string storage_key;
+    string host;
+    string type;
+    string name;
+    int64 use_count;
+    mojo_base.mojom.Time last_accessed;
+    mojo_base.mojom.Time last_modified;
+};
+
 // Interface for controlling Quota Internals.
 // Hosted on chrome://quota-internals" for WebUI content::QuotaInternalsUI.
 interface QuotaInternalsHandler {
@@ -21,4 +34,7 @@
     // Used by the quota-internals page to test behavior of the storage pressure
     // callback and trigger a storage pressure notification.
     SimulateStoragePressure(url.mojom.Origin origin_url);
+
+    // Returns an array of Storage Bucket entries stored in the QuotaDatabase.
+    RetrieveBucketsTable() => (array<BucketTableEntry> entries);
 };
\ No newline at end of file
diff --git a/storage/browser/quota/quota_manager_impl.cc b/storage/browser/quota/quota_manager_impl.cc
index 1de952cc..1a36867 100644
--- a/storage/browser/quota/quota_manager_impl.cc
+++ b/storage/browser/quota/quota_manager_impl.cc
@@ -101,6 +101,21 @@
   return type == StorageType::kTemporary || type == StorageType::kPersistent;
 }
 
+std::string StorageTypeEnumToString(StorageType type) {
+  switch (type) {
+    case StorageType::kTemporary:
+      return "temporary";
+    case StorageType::kPersistent:
+      return "persistent";
+    case StorageType::kSyncable:
+      return "syncable";
+    case StorageType::kQuotaNotManaged:
+      return "quota-not-managed";
+    case StorageType::kUnknown:
+      return "unknown";
+  }
+}
+
 QuotaErrorOr<BucketInfo> GetOrCreateBucketOnDBThread(
     const StorageKey& storage_key,
     const std::string& bucket_name,
@@ -1992,6 +2007,42 @@
                      base::Owned(helper), weak_factory_.GetWeakPtr(),
                      std::move(callback)));
 }
+void QuotaManagerImpl::DidRetrieveBucketsTable(
+    RetrieveBucketsTableCallback callback,
+    const BucketTableEntries& entries) {
+  std::vector<storage::mojom::BucketTableEntryPtr> mojo_entries;
+
+  for (auto& n : entries) {
+    DCHECK(IsSupportedType(n.type));
+    storage::mojom::BucketTableEntryPtr entry =
+        storage::mojom::BucketTableEntry::New();
+    entry->bucket_id = n.bucket_id.value();
+    entry->storage_key = n.storage_key.Serialize();
+    entry->host = n.storage_key.origin().host();
+    entry->type = StorageTypeEnumToString(n.type);
+    entry->name = n.name;
+    entry->use_count = n.use_count;
+    entry->last_accessed = n.last_accessed;
+    entry->last_modified = n.last_modified;
+    mojo_entries.push_back(std::move(entry));
+  }
+  std::move(callback).Run(std::move(mojo_entries));
+}
+
+void QuotaManagerImpl::RetrieveBucketsTable(
+    RetrieveBucketsTableCallback callback) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(callback);
+
+  if (db_disabled_) {
+    std::move(callback).Run({});
+    return;
+  }
+
+  DumpBucketTable(base::BindOnce(&QuotaManagerImpl::DidRetrieveBucketsTable,
+                                 weak_factory_.GetWeakPtr(),
+                                 std::move(callback)));
+}
 
 void QuotaManagerImpl::StartEviction() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/storage/browser/quota/quota_manager_impl.h b/storage/browser/quota/quota_manager_impl.h
index bc2eb68..61eecaed 100644
--- a/storage/browser/quota/quota_manager_impl.h
+++ b/storage/browser/quota/quota_manager_impl.h
@@ -354,6 +354,7 @@
   // storage::mojom::QuotaInternalsHandler implementation
   void GetDiskAvailability(GetDiskAvailabilityCallback callback) override;
   void GetStatistics(GetStatisticsCallback callback) override;
+  void RetrieveBucketsTable(RetrieveBucketsTableCallback callback) override;
 
   // Called by UI and internal modules.
   void GetPersistentHostQuota(const std::string& host, QuotaCallback callback);
@@ -522,6 +523,8 @@
 
   void DumpQuotaTable(DumpQuotaTableCallback callback);
   void DumpBucketTable(DumpBucketTableCallback callback);
+  void DidRetrieveBucketsTable(RetrieveBucketsTableCallback callback,
+                               const BucketTableEntries& entries);
 
   // Runs BucketDataDeleter which calls QuotaClients to clear data for the
   // bucket. Once the task is complete, calls the QuotaDatabase to delete the
diff --git a/storage/browser/quota/quota_manager_unittest.cc b/storage/browser/quota/quota_manager_unittest.cc
index 59fc4624..6b7a428e 100644
--- a/storage/browser/quota/quota_manager_unittest.cc
+++ b/storage/browser/quota/quota_manager_unittest.cc
@@ -39,6 +39,7 @@
 #include "storage/browser/quota/quota_client_type.h"
 #include "storage/browser/quota/quota_database.h"
 #include "storage/browser/quota/quota_features.h"
+#include "storage/browser/quota/quota_internals.mojom.h"
 #include "storage/browser/quota/quota_manager_impl.h"
 #include "storage/browser/quota/quota_manager_proxy.h"
 #include "storage/browser/quota/quota_override_handle.h"
@@ -110,6 +111,19 @@
   return StorageKey::CreateFromStringForTesting(url);
 }
 
+const storage::mojom::BucketTableEntry* FindBucketTableEntry(
+    const std::vector<storage::mojom::BucketTableEntryPtr>& bucket_entries,
+    BucketId& id) {
+  auto it = base::ranges::find_if(
+      bucket_entries, [id](const storage::mojom::BucketTableEntryPtr& entry) {
+        return entry->bucket_id == id.value();
+      });
+  if (it == bucket_entries.end()) {
+    return nullptr;
+  }
+  return it->get();
+}
+
 MATCHER_P3(MatchesBucketTableEntry, storage_key, type, use_count, "") {
   return testing::ExplainMatchResult(storage_key, arg.storage_key,
                                      result_listener) &&
@@ -436,6 +450,13 @@
     return future.Get();
   }
 
+  std::vector<storage::mojom::BucketTableEntryPtr> RetrieveBucketsTable() {
+    base::test::TestFuture<std::vector<storage::mojom::BucketTableEntryPtr>>
+        future;
+    quota_manager_impl_->RetrieveBucketsTable(future.GetCallback());
+    return future.Take();
+  }
+
   void DidGetUsageAndQuotaWithBreakdown(
       base::OnceClosure quit_closure,
       QuotaStatusCode status,
@@ -2669,6 +2690,64 @@
                            MatchesBucketTableEntry(kStorageKey, kPerm, 2)));
 }
 
+TEST_F(QuotaManagerImplTest, RetrieveBucketsTable) {
+  const StorageKey kStorageKey = ToStorageKey("http://example.com/");
+  const std::string kSerializedStorageKey = kStorageKey.Serialize();
+  const base::Time kAccessTime = base::Time::Now();
+
+  static const ClientBucketData kData[] = {
+      {"http://example.com/", kDefaultBucketName, kTemp, 0},
+      {"http://example.com/", kDefaultBucketName, kPerm, 0},
+  };
+
+  MockQuotaClient* client =
+      CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
+  RegisterClientBucketData(client, kData);
+
+  quota_manager_impl()->NotifyStorageAccessed(kStorageKey, kTemp, kAccessTime);
+  quota_manager_impl()->NotifyStorageAccessed(kStorageKey, kPerm, kAccessTime);
+
+  base::Time time1 = client->IncrementMockTime();
+  client->ModifyStorageKeyAndNotify(ToStorageKey("http://example.com/"), kTemp,
+                                    10);
+  client->ModifyStorageKeyAndNotify(ToStorageKey("http://example.com/"), kPerm,
+                                    10);
+  base::Time time2 = client->IncrementMockTime();
+  client->ModifyStorageKeyAndNotify(ToStorageKey("http://example.com/"), kTemp,
+                                    10);
+  base::Time time3 = client->IncrementMockTime();
+
+  auto temp_bucket = GetBucket(kStorageKey, kDefaultBucketName, kTemp);
+  auto perm_bucket = GetBucket(kStorageKey, kDefaultBucketName, kPerm);
+
+  const std::vector<storage::mojom::BucketTableEntryPtr> bucket_table_entries =
+      RetrieveBucketsTable();
+
+  auto* temp_entry =
+      FindBucketTableEntry(bucket_table_entries, temp_bucket->id);
+  EXPECT_TRUE(temp_entry);
+  EXPECT_EQ(temp_entry->storage_key, kSerializedStorageKey);
+  EXPECT_EQ(temp_entry->host, "example.com");
+  EXPECT_EQ(temp_entry->type, "temporary");
+  EXPECT_EQ(temp_entry->name, kDefaultBucketName);
+  EXPECT_EQ(temp_entry->use_count, 1);
+  EXPECT_EQ(temp_entry->last_accessed, kAccessTime);
+  EXPECT_GE(temp_entry->last_modified, time2);
+  EXPECT_LE(temp_entry->last_modified, time3);
+
+  auto* perm_entry =
+      FindBucketTableEntry(bucket_table_entries, perm_bucket->id);
+  EXPECT_TRUE(perm_entry);
+  EXPECT_EQ(perm_entry->storage_key, kSerializedStorageKey);
+  EXPECT_EQ(perm_entry->host, "example.com");
+  EXPECT_EQ(perm_entry->type, "persistent");
+  EXPECT_EQ(perm_entry->name, kDefaultBucketName);
+  EXPECT_EQ(perm_entry->use_count, 1);
+  EXPECT_EQ(perm_entry->last_accessed, kAccessTime);
+  EXPECT_GE(perm_entry->last_modified, time1);
+  EXPECT_LE(perm_entry->last_modified, time2);
+}
+
 TEST_F(QuotaManagerImplTest, QuotaForEmptyHost) {
   EXPECT_EQ(GetPersistentHostQuota(std::string()), 0);
 
diff --git a/third_party/blink/OWNERS b/third_party/blink/OWNERS
index 106e60d..3daffc1e 100644
--- a/third_party/blink/OWNERS
+++ b/third_party/blink/OWNERS
@@ -6,7 +6,6 @@
 chrishtr@chromium.org
 foolip@chromium.org
 jochen@chromium.org
-kinuko@chromium.org
 mkwst@chromium.org
 rbyers@chromium.org
 tkent@chromium.org
diff --git a/third_party/blink/common/mime_util/OWNERS b/third_party/blink/common/mime_util/OWNERS
index 9b72688d..53e68eb7 100644
--- a/third_party/blink/common/mime_util/OWNERS
+++ b/third_party/blink/common/mime_util/OWNERS
@@ -1,2 +1 @@
 mmenke@chromium.org
-rsleevi@chromium.org
diff --git a/third_party/blink/public/common/mime_util/OWNERS b/third_party/blink/public/common/mime_util/OWNERS
index 9b72688d..53e68eb7 100644
--- a/third_party/blink/public/common/mime_util/OWNERS
+++ b/third_party/blink/public/common/mime_util/OWNERS
@@ -1,2 +1 @@
 mmenke@chromium.org
-rsleevi@chromium.org
diff --git a/third_party/blink/renderer/core/OWNERS b/third_party/blink/renderer/core/OWNERS
index be1e4c4..a13affc 100644
--- a/third_party/blink/renderer/core/OWNERS
+++ b/third_party/blink/renderer/core/OWNERS
@@ -43,7 +43,6 @@
 junov@chromium.org
 kbr@chromium.org
 keishi@chromium.org
-kinuko@chromium.org
 kojii@chromium.org
 kouhei@chromium.org
 masonf@chromium.org
diff --git a/third_party/blink/renderer/core/animation/animation.cc b/third_party/blink/renderer/core/animation/animation.cc
index 9a81ef9..c521a39 100644
--- a/third_party/blink/renderer/core/animation/animation.cc
+++ b/third_party/blink/renderer/core/animation/animation.cc
@@ -615,7 +615,8 @@
   bool should_start = Playing() && (!compositor_state_ || changed);
 
   if (start_on_compositor && should_cancel && should_start &&
-      compositor_state_ && compositor_state_->pending_action == kStart) {
+      compositor_state_ && compositor_state_->pending_action == kStart &&
+      !compositor_state_->effect_changed) {
     // Restarting but still waiting for a start time.
     return false;
   }
diff --git a/third_party/blink/renderer/core/page/print_context_test.cc b/third_party/blink/renderer/core/page/print_context_test.cc
index 59d2b87..1a81a54f 100644
--- a/third_party/blink/renderer/core/page/print_context_test.cc
+++ b/third_party/blink/renderer/core/page/print_context_test.cc
@@ -114,6 +114,7 @@
                            GLuint msaa_sample_count,
                            gpu::raster::MsaaMode msaa_mode,
                            GLboolean can_use_lcd_text,
+                           GLboolean visible,
                            const gfx::ColorSpace& color_space,
                            const GLbyte* mailbox) override {}
   void RasterCHROMIUM(const cc::DisplayItemList* list,
diff --git a/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc b/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc
index e7561bb..893ec7a3 100644
--- a/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc
@@ -175,12 +175,8 @@
   Compositor().BeginFrame();  // update run_state_.
   Compositor().BeginFrame();  // Set start_time = now.
   Compositor().BeginFrame(0.2);
-  ASSERT_NEAR(
-      Window().scrollY(),
-      (base::FeatureList::IsEnabled(::features::kImpulseScrollAnimations)
-           ? 800
-           : 299),
-      1);
+  ASSERT_NEAR(Window().scrollY(),
+              (::features::IsImpulseScrollAnimationEnabled() ? 800 : 299), 1);
 
   // Finish scrolling the container
   Compositor().BeginFrame(1);
@@ -216,12 +212,8 @@
   Compositor().BeginFrame();  // update run_state_.
   Compositor().BeginFrame();  // Set start_time = now.
   Compositor().BeginFrame(0.2);
-  ASSERT_NEAR(
-      Window().scrollY(),
-      (base::FeatureList::IsEnabled(::features::kImpulseScrollAnimations)
-           ? 800
-           : 299),
-      1);
+  ASSERT_NEAR(Window().scrollY(),
+              (::features::IsImpulseScrollAnimationEnabled() ? 800 : 299), 1);
   ASSERT_EQ(container->scrollTop(), 0);
 
   // Finish scrolling the outer container
@@ -232,12 +224,8 @@
   // Scrolling the inner container
   Compositor().BeginFrame();  // Set start_time = now.
   Compositor().BeginFrame(0.2);
-  ASSERT_NEAR(
-      container->scrollTop(),
-      (base::FeatureList::IsEnabled(::features::kImpulseScrollAnimations)
-           ? 794
-           : 299),
-      1);
+  ASSERT_NEAR(container->scrollTop(),
+              (::features::IsImpulseScrollAnimationEnabled() ? 794 : 299), 1);
 
   // Finish scrolling the inner container
   Compositor().BeginFrame(1);
@@ -280,23 +268,16 @@
   Compositor().BeginFrame();  // update run_state_.
   Compositor().BeginFrame();  // Set start_time = now.
   Compositor().BeginFrame(0.2);
-  ASSERT_NEAR(
-      Window().scrollY(),
-      (base::FeatureList::IsEnabled(::features::kImpulseScrollAnimations)
-           ? 800
-           : 299),
-      1);
+  ASSERT_NEAR(Window().scrollY(),
+              (::features::IsImpulseScrollAnimationEnabled() ? 800 : 299), 1);
   ASSERT_EQ(container1->scrollTop(), 0);
 
   content2->scrollIntoView(arg);
   Compositor().BeginFrame();  // update run_state_.
   Compositor().BeginFrame();  // Set start_time = now.
   Compositor().BeginFrame(0.2);
-  ASSERT_NEAR(
-      Window().scrollY(),
-      (base::FeatureList::IsEnabled(::features::kImpulseScrollAnimations) ? 171
-                                                                          : 61),
-      1);
+  ASSERT_NEAR(Window().scrollY(),
+              (::features::IsImpulseScrollAnimationEnabled() ? 71 : 61), 1);
   ASSERT_EQ(container1->scrollTop(), 0);  // container1 should not scroll.
 
   Compositor().BeginFrame(1);
@@ -306,12 +287,8 @@
   // Scrolling content2 in container2
   Compositor().BeginFrame();  // Set start_time = now.
   Compositor().BeginFrame(0.2);
-  ASSERT_NEAR(
-      container2->scrollTop(),
-      (base::FeatureList::IsEnabled(::features::kImpulseScrollAnimations)
-           ? 952
-           : 300),
-      1);
+  ASSERT_NEAR(container2->scrollTop(),
+              (::features::IsImpulseScrollAnimationEnabled() ? 952 : 300), 1);
 
   // Finish all the animation to make sure there is no another animation queued
   // on container1.
@@ -353,12 +330,8 @@
   Compositor().BeginFrame();  // update run_state_.
   Compositor().BeginFrame();  // Set start_time = now.
   Compositor().BeginFrame(0.2);
-  ASSERT_NEAR(
-      Window().scrollY(),
-      (base::FeatureList::IsEnabled(::features::kImpulseScrollAnimations)
-           ? 800
-           : 299),
-      1);
+  ASSERT_NEAR(Window().scrollY(),
+              (::features::IsImpulseScrollAnimationEnabled() ? 800 : 299), 1);
   ASSERT_EQ(container->scrollTop(), 0);
 
   ScrollToOptions* window_option = ScrollToOptions::Create();
@@ -369,11 +342,8 @@
   Compositor().BeginFrame();  // update run_state_.
   Compositor().BeginFrame();  // Set start_time = now.
   Compositor().BeginFrame(0.2);
-  ASSERT_NEAR(
-      Window().scrollY(),
-      (base::FeatureList::IsEnabled(::features::kImpulseScrollAnimations) ? 165
-                                                                          : 58),
-      1);
+  ASSERT_NEAR(Window().scrollY(),
+              (::features::IsImpulseScrollAnimationEnabled() ? 165 : 58), 1);
 
   Compositor().BeginFrame(1);
   ASSERT_EQ(Window().scrollY(), 0);
@@ -480,12 +450,8 @@
   Compositor().BeginFrame();  // update run_state_.
   Compositor().BeginFrame();  // Set start_time = now.
   Compositor().BeginFrame(0.2);
-  ASSERT_NEAR(
-      container->scrollTop(),
-      (base::FeatureList::IsEnabled(::features::kImpulseScrollAnimations)
-           ? 794
-           : 299),
-      1);
+  ASSERT_NEAR(container->scrollTop(),
+              (::features::IsImpulseScrollAnimationEnabled() ? 794 : 299), 1);
 
   // Finish scrolling the container
   Compositor().BeginFrame(1);
@@ -518,12 +484,8 @@
   Compositor().BeginFrame();  // update run_state_.
   Compositor().BeginFrame();  // Set start_time = now.
   Compositor().BeginFrame(0.2);
-  ASSERT_NEAR(
-      container->scrollTop(),
-      (base::FeatureList::IsEnabled(::features::kImpulseScrollAnimations)
-           ? 794
-           : 299),
-      1);
+  ASSERT_NEAR(container->scrollTop(),
+              (::features::IsImpulseScrollAnimationEnabled() ? 794 : 299), 1);
 
   // Finish scrolling the container
   Compositor().BeginFrame(1);
@@ -576,12 +538,8 @@
   Compositor().BeginFrame();  // update run_state_.
   Compositor().BeginFrame();  // Set start_time = now.
   Compositor().BeginFrame(0.2);
-  ASSERT_NEAR(
-      Window().scrollY(),
-      (base::FeatureList::IsEnabled(::features::kImpulseScrollAnimations)
-           ? 800
-           : 299),
-      1);
+  ASSERT_NEAR(Window().scrollY(),
+              (::features::IsImpulseScrollAnimationEnabled() ? 800 : 299), 1);
 
   // Finish scrolling the container
   Compositor().BeginFrame(1);
@@ -752,12 +710,8 @@
   Compositor().BeginFrame();  // update run_state_.
   Compositor().BeginFrame();  // Set start_time = now.
   Compositor().BeginFrame(0.2);
-  ASSERT_NEAR(
-      Window().scrollY(),
-      (base::FeatureList::IsEnabled(::features::kImpulseScrollAnimations)
-           ? 800
-           : 299),
-      1);
+  ASSERT_NEAR(Window().scrollY(),
+              (::features::IsImpulseScrollAnimationEnabled() ? 800 : 299), 1);
 
   // ProgrammaticScroll that could interrupt the current smooth scroll.
   Window().scrollTo(0, 0);
@@ -792,12 +746,9 @@
   Compositor().BeginFrame();  // update run_state_.
   Compositor().BeginFrame();  // Set start_time = now.
   Compositor().BeginFrame(0.2);
-  ASSERT_NEAR(
-      Window().scrollY(),
-      (base::FeatureList::IsEnabled(::features::kImpulseScrollAnimations)
-           ? 79389
-           : 16971),
-      1);
+  ASSERT_NEAR(Window().scrollY(),
+              (::features::IsImpulseScrollAnimationEnabled() ? 79389 : 16971),
+              1);
 
   // Finish scrolling the container
   Compositor().BeginFrame(0.5);
diff --git a/third_party/blink/renderer/core/scroll/scroll_test.cc b/third_party/blink/renderer/core/scroll/scroll_test.cc
index b39a47d..1c76793a 100644
--- a/third_party/blink/renderer/core/scroll/scroll_test.cc
+++ b/third_party/blink/renderer/core/scroll/scroll_test.cc
@@ -33,8 +33,7 @@
 
 namespace {
 const double kScrollAnimationDuration =
-    (base::FeatureList::IsEnabled(::features::kImpulseScrollAnimations) ? 1.5
-                                                                        : 0.5);
+    (::features::IsImpulseScrollAnimationEnabled() ? 1.5 : 0.5);
 }
 
 class FractionalScrollSimTest : public SimTest, public PaintTestConfigurations {
diff --git a/third_party/blink/renderer/modules/OWNERS b/third_party/blink/renderer/modules/OWNERS
index 4e16111..475e6ec7 100644
--- a/third_party/blink/renderer/modules/OWNERS
+++ b/third_party/blink/renderer/modules/OWNERS
@@ -1,7 +1,6 @@
 dcheng@chromium.org
 haraken@chromium.org
 jbroman@chromium.org
-kinuko@chromium.org
 mkwst@chromium.org
 
 # Reviewers for inspector-related code:
diff --git a/third_party/blink/renderer/modules/accessibility/OWNERS b/third_party/blink/renderer/modules/accessibility/OWNERS
index 658c227..83cd0f4 100644
--- a/third_party/blink/renderer/modules/accessibility/OWNERS
+++ b/third_party/blink/renderer/modules/accessibility/OWNERS
@@ -1,4 +1,3 @@
-aboxhall@chromium.org
 aleventhal@chromium.org
 dlibby@microsoft.com
 dtseng@chromium.org
diff --git a/third_party/blink/renderer/platform/OWNERS b/third_party/blink/renderer/platform/OWNERS
index 61e8b6c..14f21ebd 100644
--- a/third_party/blink/renderer/platform/OWNERS
+++ b/third_party/blink/renderer/platform/OWNERS
@@ -10,7 +10,6 @@
 jochen@chromium.org
 junov@chromium.org
 kbr@chromium.org
-kinuko@chromium.org
 kojii@chromium.org
 mkwst@chromium.org
 noel@chromium.org
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
index c750eb5..099d276 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -1459,7 +1459,8 @@
                           /*msaa_sample_count=*/oopr_uses_dmsaa_ ? 1 : 0,
                           oopr_uses_dmsaa_ ? gpu::raster::MsaaMode::kDMSAA
                                            : gpu::raster::MsaaMode::kNoMSAA,
-                          can_use_lcd_text, GetColorSpace(), mailbox.name);
+                          can_use_lcd_text, /*visible=*/true, GetColorSpace(),
+                          mailbox.name);
 
   ri->RasterCHROMIUM(list.get(), GetOrCreateCanvasImageProvider(), size,
                      full_raster_rect, playback_rect, post_translate,
diff --git a/third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h b/third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h
index 4e7c992f..c50e06e6 100644
--- a/third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h
+++ b/third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_SECURITY_ORIGIN_MOJOM_TRAITS_H_
 
 #include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
+#include "mojo/public/cpp/bindings/optional_as_pointer.h"
 #include "mojo/public/cpp/bindings/string_traits_wtf.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -17,7 +18,7 @@
 namespace mojo {
 
 struct UrlOriginAdapter {
-  static absl::optional<base::UnguessableToken> nonce_if_opaque(
+  static const base::UnguessableToken* nonce_if_opaque(
       const scoped_refptr<const ::blink::SecurityOrigin>& origin) {
     return origin->GetNonceForSerialization();
   }
@@ -59,9 +60,10 @@
       const scoped_refptr<const ::blink::SecurityOrigin>& origin) {
     return UrlOriginAdapter::GetOriginOrPrecursorOriginIfOpaque(origin)->Port();
   }
-  static absl::optional<base::UnguessableToken> nonce_if_opaque(
+  static mojo::OptionalAsPointer<const base::UnguessableToken> nonce_if_opaque(
       const scoped_refptr<const ::blink::SecurityOrigin>& origin) {
-    return UrlOriginAdapter::nonce_if_opaque(origin);
+    return mojo::MakeOptionalAsPointer(
+        UrlOriginAdapter::nonce_if_opaque(origin));
   }
   static bool Read(url::mojom::OriginDataView data,
                    scoped_refptr<const ::blink::SecurityOrigin>* out) {
diff --git a/third_party/blink/renderer/platform/weborigin/security_origin.cc b/third_party/blink/renderer/platform/weborigin/security_origin.cc
index e830415..142ff00 100644
--- a/third_party/blink/renderer/platform/weborigin/security_origin.cc
+++ b/third_party/blink/renderer/platform/weborigin/security_origin.cc
@@ -266,9 +266,9 @@
         CreateFromValidTuple(String::FromUTF8(tuple.scheme()),
                              String::FromUTF8(tuple.host()), tuple.port());
   }
-  absl::optional<base::UnguessableToken> nonce_if_opaque =
+  const base::UnguessableToken* nonce_if_opaque =
       origin.GetNonceForSerialization();
-  DCHECK_EQ(nonce_if_opaque.has_value(), origin.opaque());
+  DCHECK_EQ(!!nonce_if_opaque, origin.opaque());
   if (nonce_if_opaque) {
     return base::AdoptRef(new SecurityOrigin(
         url::Origin::Nonce(*nonce_if_opaque), tuple_origin.get()));
@@ -314,14 +314,10 @@
   return domain.IsEmpty() ? String() : domain;
 }
 
-absl::optional<base::UnguessableToken>
-SecurityOrigin::GetNonceForSerialization() const {
+const base::UnguessableToken* SecurityOrigin::GetNonceForSerialization() const {
   // The call to token() forces initialization of the |nonce_if_opaque_| if
   // not already initialized.
-  // TODO(nasko): Consider not making a copy here, but return a reference to
-  // the nonce.
-  return nonce_if_opaque_ ? absl::make_optional(nonce_if_opaque_->token())
-                          : absl::nullopt;
+  return nonce_if_opaque_ ? &nonce_if_opaque_->token() : nullptr;
 }
 
 bool SecurityOrigin::CanAccess(const SecurityOrigin* other,
@@ -367,8 +363,8 @@
     // (e.g., top-level worker script loading) because SecurityOrigin and
     // BlobURLNullOriginMap are thread-specific. For the case, check
     // BlobURLOpaqueOriginNonceMap.
-    absl::optional<base::UnguessableToken> nonce = GetNonceForSerialization();
-    if (nonce && BlobURLOpaqueOriginNonceMap::GetInstance().Get(url) == nonce)
+    const base::UnguessableToken* nonce = GetNonceForSerialization();
+    if (nonce && BlobURLOpaqueOriginNonceMap::GetInstance().Get(url) == *nonce)
       return true;
     return false;
   }
diff --git a/third_party/blink/renderer/platform/weborigin/security_origin.h b/third_party/blink/renderer/platform/weborigin/security_origin.h
index def3999..3fa93aea 100644
--- a/third_party/blink/renderer/platform/weborigin/security_origin.h
+++ b/third_party/blink/renderer/platform/weborigin/security_origin.h
@@ -435,7 +435,7 @@
   // Get the nonce associated with this origin, if it is opaque. This should be
   // used only when trying to send an Origin across an IPC pipe or comparing
   // blob URL's opaque origins in the thread-safe way.
-  absl::optional<base::UnguessableToken> GetNonceForSerialization() const;
+  const base::UnguessableToken* GetNonceForSerialization() const;
 
   const String protocol_ = g_empty_string;
   const String host_ = g_empty_string;
diff --git a/third_party/blink/renderer/platform/weborigin/security_origin_hash.h b/third_party/blink/renderer/platform/weborigin/security_origin_hash.h
index 636b0e1..305105d 100644
--- a/third_party/blink/renderer/platform/weborigin/security_origin_hash.h
+++ b/third_party/blink/renderer/platform/weborigin/security_origin_hash.h
@@ -45,8 +45,7 @@
 struct SecurityOriginHash {
   STATIC_ONLY(SecurityOriginHash);
   static unsigned GetHash(const SecurityOrigin* origin) {
-    absl::optional<base::UnguessableToken> nonce =
-        origin->GetNonceForSerialization();
+    const base::UnguessableToken* nonce = origin->GetNonceForSerialization();
     size_t nonce_hash = nonce ? base::UnguessableTokenHash()(*nonce) : 0;
 
     unsigned hash_codes[] = {
diff --git a/third_party/blink/renderer/platform/weborigin/security_origin_test.cc b/third_party/blink/renderer/platform/weborigin/security_origin_test.cc
index 6cddf06..a5f654525 100644
--- a/third_party/blink/renderer/platform/weborigin/security_origin_test.cc
+++ b/third_party/blink/renderer/platform/weborigin/security_origin_test.cc
@@ -66,8 +66,8 @@
     return origin.nonce_if_opaque_;
   }
 
-  const absl::optional<base::UnguessableToken>
-  GetNonceForSerializationForOrigin(const SecurityOrigin& origin) {
+  const base::UnguessableToken* GetNonceForSerializationForOrigin(
+      const SecurityOrigin& origin) {
     return origin.GetNonceForSerialization();
   }
 };
diff --git a/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc b/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc
index 8e12579..67df035 100644
--- a/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc
+++ b/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc
@@ -209,21 +209,6 @@
   }
 }
 
-WebGestureEvent SynthesizeGestureScrollBegin(
-    const WebGestureEvent& update_event) {
-  DCHECK_EQ(update_event.GetType(), WebInputEvent::Type::kGestureScrollUpdate);
-  WebGestureEvent scroll_begin(update_event);
-  scroll_begin.SetType(WebInputEvent::Type::kGestureScrollBegin);
-  scroll_begin.data.scroll_begin.delta_x_hint =
-      update_event.data.scroll_update.delta_x;
-  scroll_begin.data.scroll_begin.delta_y_hint =
-      update_event.data.scroll_update.delta_y;
-  scroll_begin.data.scroll_begin.delta_hint_units =
-      update_event.data.scroll_update.delta_units;
-  scroll_begin.data.scroll_begin.scrollable_area_element_id = 0;
-  return scroll_begin;
-}
-
 }  // namespace
 
 InputHandlerProxy::InputHandlerProxy(cc::InputHandler& input_handler,
@@ -706,23 +691,11 @@
       return HandleGestureScrollBegin(
           static_cast<const WebGestureEvent&>(event));
 
-    case WebInputEvent::Type::kGestureScrollUpdate: {
-      auto event_disposition = HandleGestureScrollUpdate(
+    case WebInputEvent::Type::kGestureScrollUpdate:
+      return HandleGestureScrollUpdate(
           static_cast<const WebGestureEvent&>(event), original_attribution,
           event_with_callback->metrics());
 
-      if (event_disposition == LOST_LATCHED_NODE) {
-        WebGestureEvent scroll_begin_event = SynthesizeGestureScrollBegin(
-            static_cast<const WebGestureEvent&>(event_with_callback->event()));
-        HandleGestureScrollBegin(
-            static_cast<const WebGestureEvent&>(scroll_begin_event), true);
-        return HandleGestureScrollUpdate(
-            static_cast<const WebGestureEvent&>(event), original_attribution,
-            event_with_callback->metrics());
-      }
-      return event_disposition;
-    }
-
     case WebInputEvent::Type::kGestureScrollEnd:
       return HandleGestureScrollEnd(static_cast<const WebGestureEvent&>(event));
 
@@ -1005,8 +978,7 @@
 }
 
 InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureScrollBegin(
-    const WebGestureEvent& gesture_event,
-    bool trying_to_relatch) {
+    const WebGestureEvent& gesture_event) {
   TRACE_EVENT0("input", "InputHandlerProxy::HandleGestureScrollBegin");
 
   if (scroll_predictor_)
@@ -1014,15 +986,13 @@
 
   // When a GSB is being handled, end any pre-existing gesture scrolls that are
   // in progress.
-  if (!trying_to_relatch) {
-    if (currently_active_gesture_device_.has_value() &&
-        handling_gesture_on_impl_thread_) {
-      // TODO(arakeri): Once crbug.com/1074209 is fixed, delete calls to
-      // RecordScrollEnd.
-      input_handler_->RecordScrollEnd(
-          GestureScrollInputType(*currently_active_gesture_device_));
-      InputHandlerScrollEnd();
-    }
+  if (currently_active_gesture_device_.has_value() &&
+      handling_gesture_on_impl_thread_) {
+    // TODO(arakeri): Once crbug.com/1074209 is fixed, delete calls to
+    // RecordScrollEnd.
+    input_handler_->RecordScrollEnd(
+        GestureScrollInputType(*currently_active_gesture_device_));
+    InputHandlerScrollEnd();
   }
 
   cc::ScrollState scroll_state = CreateScrollStateForGesture(gesture_event);
@@ -1145,10 +1115,6 @@
   cc::InputHandlerScrollResult scroll_result =
       input_handler_->ScrollUpdate(&scroll_state, delay);
 
-  if (scroll_result.currently_scrolling_node_lost) {
-    return LOST_LATCHED_NODE;
-  }
-
   HandleOverscroll(gesture_event.PositionInWidget(), scroll_result);
 
   if (elastic_overscroll_controller_)
diff --git a/third_party/blink/renderer/platform/widget/input/input_handler_proxy.h b/third_party/blink/renderer/platform/widget/input/input_handler_proxy.h
index ebadfd4b..ab4f38b9 100644
--- a/third_party/blink/renderer/platform/widget/input/input_handler_proxy.h
+++ b/third_party/blink/renderer/platform/widget/input/input_handler_proxy.h
@@ -143,12 +143,6 @@
     // scroll node to handle the event and requires a second try with an
     // ElementId provided by a hit test in Blink.
     REQUIRES_MAIN_THREAD_HIT_TEST,
-
-    // Used only in scroll unification; during handling a GSU event, the
-    // compositor found that the currently scrolling node had been lost,
-    // and then the compositor could not handle the event, as a result we will
-    // synthesize a GSB event and try to relatch to a new node.
-    LOST_LATCHED_NODE,
   };
   using EventDispositionCallback = base::OnceCallback<void(
       EventDisposition,
@@ -254,8 +248,8 @@
 
   // Helper functions for handling more complicated input events.
   EventDisposition HandleMouseWheel(const blink::WebMouseWheelEvent& event);
-  EventDisposition HandleGestureScrollBegin(const blink::WebGestureEvent& event,
-                                            bool trying_to_relatch = false);
+  EventDisposition HandleGestureScrollBegin(
+      const blink::WebGestureEvent& event);
   EventDisposition HandleGestureScrollUpdate(
       const blink::WebGestureEvent& event,
       const blink::WebInputEventAttribution& original_attribution,
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index cfccf35e..ef9eb9d 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2110,6 +2110,8 @@
 crbug.com/520611 [ Debug ] fast/filesystem/workers/file-writer-events-shared-worker.html [ Failure Pass ]
 crbug.com/520194 http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-worker-overridesexpires.html [ Failure Pass ]
 
+crbug.com/892032 fast/events/wheel/wheel-latched-scroll-node-removed.html [ Failure Pass ]
+
 crbug.com/1051136 fast/forms/select/listbox-overlay-scrollbar.html [ Failure ]
 
 # These performance-sensitive user-timing tests are flaky in debug on all platforms, and flaky on all configurations of windows.
@@ -5681,11 +5683,13 @@
 crbug.com/476553 virtual/scroll-unification/fast/events/platform-wheelevent-paging-xy-in-scrolling-div.html [ Crash Failure Pass Timeout ]
 crbug.com/476553 virtual/scroll-unification/fast/events/remove-child-onscroll.html [ Crash Failure Pass Timeout ]
 crbug.com/476553 virtual/scroll-unification/fast/events/touch/scroll-without-mouse-lacks-mousemove-events.html [ Crash Failure Pass Timeout ]
+crbug.com/476553 virtual/scroll-unification/fast/events/touch/touch-latched-scroll-node-removed.html [ Crash Failure Pass Timeout ]
 crbug.com/476553 virtual/scroll-unification/fast/events/touch/gesture/focus-selectionchange-on-tap.html [ Crash Failure Pass Timeout ]
 crbug.com/476553 virtual/scroll-unification/fast/events/touch/gesture/gesture-tap-click-common-ancestor.html [ Crash Failure Pass Timeout ]
 crbug.com/476553 virtual/scroll-unification/fast/events/touch/gesture/gesture-tap-frame-removed.html [ Crash Failure Pass Timeout ]
 crbug.com/476553 virtual/scroll-unification/fast/events/touch/gesture/touch-gesture-scroll-input-field.html [ Crash Failure Pass Timeout ]
 crbug.com/476553 virtual/scroll-unification/fast/events/touch/gesture/touch-gesture-scroll-listbox.html [ Crash Failure Pass Timeout ]
+crbug.com/476553 virtual/scroll-unification/fast/events/wheel/wheel-latched-scroll-node-removed.html [ Crash Failure Pass Timeout ]
 crbug.com/476553 virtual/scroll-unification/fast/scrolling/resize-corner-tracking-touch.html [ Crash Failure Pass Timeout ]
 crbug.com/476553 virtual/scroll-unification/fast/scrolling/subpixel-overflow-mouse-drag.html [ Crash Failure Pass Timeout ]
 crbug.com/476553 virtual/scroll-unification/http/tests/misc/destroy-middle-click-locked-target-crash.html [ Crash Failure Pass Skip Timeout ]
@@ -7314,10 +7318,6 @@
 crbug.com/1272955 http/tests/devtools/extensions/extensions-timeline-api.js [ Failure Pass ]
 crbug.com/1302309 external/wpt/streams/transferable/writable-stream.html [ Failure Pass ]
 
-# Flaky as depends upon order of execution.
-crbug.com/1274917 external/wpt/content-security-policy/inheritance/history.sub.html [ Failure Pass Timeout ]
-crbug.com/1274917 external/wpt/content-security-policy/inheritance/history-iframe.sub.html [ Failure Pass Timeout ]
-
 # Test is very flaky (score of 223).
 crbug.com/1274919 http/tests/inspector-protocol/page/consecutive-navigate.js [ Failure Pass Timeout ]
 
@@ -7431,7 +7431,7 @@
 crbug.com/1283865 external/wpt/webmessaging/without-ports/020.html [ Failure Pass ]
 
 # Sheriff 2022-01-05
-crbug.com/1284572 [ Linux ] virtual/threaded/http/tests/devtools/isolated-code-cache/same-origin-module-test.js [ Failure Pass Skip Timeout ]
+crbug.com/1284572 virtual/threaded/http/tests/devtools/isolated-code-cache/same-origin-module-test.js [ Failure Pass Skip Timeout ]
 
 # Incomplete support for mouse wheel in test_driver.
 crbug.com/1285411 external/wpt/css/css-scroll-snap/input/mouse-wheel.html [ Timeout ]
diff --git a/third_party/blink/web_tests/external/wpt/WebCryptoAPI/OWNERS b/third_party/blink/web_tests/external/wpt/WebCryptoAPI/OWNERS
index 81033345..e69de29 100644
--- a/third_party/blink/web_tests/external/wpt/WebCryptoAPI/OWNERS
+++ b/third_party/blink/web_tests/external/wpt/WebCryptoAPI/OWNERS
@@ -1 +0,0 @@
-rsleevi@chromium.org
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/embedded-enforcement/change-csp-attribute-and-history-navigation.html b/third_party/blink/web_tests/external/wpt/content-security-policy/embedded-enforcement/change-csp-attribute-and-history-navigation.html
index b69160c7..64b5206 100644
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/embedded-enforcement/change-csp-attribute-and-history-navigation.html
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/embedded-enforcement/change-csp-attribute-and-history-navigation.html
@@ -8,7 +8,8 @@
     return new Promise(resolve => {
       window.addEventListener('message', msg => {
         if (msg.source == w) {
-          if (!starts_with || msg.data.startsWith(starts_with))
+          if (!starts_with ||
+                  (msg.data.startsWith && msg.data.startsWith(starts_with)))
             resolve(msg.data);
         }
       });
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/history-iframe.sub.html b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/history-iframe.sub.html
index 112e1848..412b3ac3 100644
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/history-iframe.sub.html
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/history-iframe.sub.html
@@ -1,16 +1,17 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
 
 <meta http-equiv="Content-Security-Policy" content="img-src 'none'">
 <body>
 <script>
-  let message_from = (w, starts_with) => {
+  let message_from = (source_token, starts_with) => {
     return new Promise(resolve => {
       window.addEventListener('message', msg => {
-        if (msg.source == w) {
-          if (!starts_with || msg.data.startsWith(starts_with))
-            resolve(msg.data);
+        if (msg.data.token === source_token) {
+          if (!starts_with || msg.data.msg.startsWith(starts_with))
+            resolve(msg.data.msg);
         }
       });
     });
@@ -18,30 +19,34 @@
 
   const img_url = window.origin + "/content-security-policy/support/fail.png";
 
-  const img_tag_string = `
+  const img_tag_string = img_token => `
     <img src="${img_url}"
-         onload="top.postMessage('img loaded', '*');"
-         onerror="top.postMessage('img blocked', '*');"
+         onload="top.postMessage(
+             {msg: 'img loaded', token: '${img_token}'}, '*');"
+         onerror="top.postMessage(
+             {msg: 'img blocked', token: '${img_token}'}, '*');"
     >
    `;
 
-  const html_test_payload = `
+  const html_test_payload = img_token => `
     <!doctype html>
     <script>
       function add_image() {
         let img = document.createElement('img');
-        img.onload = () => top.postMessage('img loaded', '*');
-        img.onerror = () => top.postMessage('img blocked', '*');
+        img.onload = () => top.postMessage(
+            {msg: 'img loaded', token: '${img_token}'}, '*');
+        img.onerror = () => top.postMessage(
+            {msg: 'img blocked', token: '${img_token}'}, '*');
         img.src = '${img_url}';
         document.body.appendChild(img);
       }
     </scr`+`ipt>
     <body onpageshow="add_image();"></body>
   `;
-  let blob_url = URL.createObjectURL(
-    new Blob([html_test_payload], { type: 'text/html' }));
+  let blob_url = blob_token => URL.createObjectURL(
+    new Blob([html_test_payload(blob_token)], { type: 'text/html' }));
 
-  let write_img_to_about_blank = async (t, iframe) => {
+  let write_img_to_about_blank = async (t, iframe, img_token) => {
     await t.step_wait(
       condition = () => {
         try {
@@ -54,52 +59,64 @@
       interval=50);
 
     let div = iframe.contentDocument.createElement('div');
-    div.innerHTML = img_tag_string;
+    div.innerHTML = img_tag_string(img_token);
     iframe.contentDocument.body.appendChild(div);
   };
 
   let testCases = [
-    {
+    test_token => ({
+      token: test_token,
       url: "about:blank",
+      add_img_function: (t, iframe) =>
+          write_img_to_about_blank(t, iframe, test_token),
       other_origin: window.origin,
       name: '"about:blank" document is navigated back from history same-origin.',
-    },
-    {
+    }),
+    test_token => ({
+      token: test_token,
       url: "about:blank",
+      add_img_function: (t, iframe) =>
+          write_img_to_about_blank(t, iframe, test_token),
       other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}",
       name: '"about:blank" document is navigated back from history cross-origin.',
-    },
-    {
-      url: blob_url,
+    }),
+    test_token => ({
+      token: test_token,
+      url: blob_url(test_token),
       other_origin: window.origin,
       name: 'blob URL document is navigated back from history same-origin.',
-    },
-    {
-      url: blob_url,
+    }),
+    test_token => ({
+      token: test_token,
+      url: blob_url(test_token),
       other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}",
       name: 'blob URL document is navigated back from history cross-origin.',
-    },
-    {
-      url: `data:text/html,${html_test_payload}`,
+    }),
+    test_token => ({
+      token: test_token,
+      url: `data:text/html,${html_test_payload(test_token)}`,
       other_origin: window.origin,
       name: 'data URL document is navigated back from history same-origin.',
-    },
-    {
-      url: `data:text/html,${html_test_payload}`,
+    }),
+    test_token => ({
+      token: test_token,
+      url: `data:text/html,${html_test_payload(test_token)}`,
       other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}",
       name: 'data URL document is navigated back from history cross-origin.',
-    },
-    {
-      srcdoc: `${html_test_payload}`,
+    }),
+    test_token => ({
+      token: test_token,
+      srcdoc: `${html_test_payload(test_token)}`,
       other_origin: window.origin,
       name: 'srcdoc iframe is navigated back from history same-origin.',
-    },
-    {
-      srcdoc: `${html_test_payload}`,
+    }),
+    test_token => ({
+      token: test_token,
+      srcdoc: `${html_test_payload(test_token)}`,
       other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}",
       name: 'srcdoc iframe is navigated back from history cross-origin.',
-    },
-  ];
+    }),
+  ].map(f => f(token()));
 
   testCases.forEach(testCase => {
     promise_test(async t => {
@@ -110,13 +127,16 @@
       // Perform a real navigation in the iframe. This is needed because the
       // initial empty document is not stored in history (so there is no way of
       // navigating back to it and test history inheritance).
-      let loaded_1 = message_from(iframe.contentWindow);
-      iframe.contentWindow.location = testCase.other_origin + "/content-security-policy/inheritance/support/postmessage-top.html";
+      const token_1 = token();
+      let loaded_1 = message_from(token_1);
+      iframe.contentWindow.location = testCase.other_origin +
+        "/content-security-policy/inheritance/support" +
+        `/postmessage-top.html?token=${token_1}`;
       assert_equals(await loaded_1, "ready",
                     "Could not navigate iframe.");
 
       // Navigate to the local scheme document.
-      let message = message_from(iframe.contentWindow);
+      let message = message_from(testCase.token);
       if (testCase.url)
         iframe.contentWindow.location = testCase.url;
       else
@@ -124,24 +144,29 @@
 
       // If the local scheme document is "about:blank", we need to write its
       // content now.
-      if (testCase.url === "about:blank")
-        await write_img_to_about_blank(t, iframe);
+      if (testCase.add_img_function) {
+        testCase.add_img_function(t, iframe);
+      }
 
       // Check that the local scheme document inherits CSP from the initiator.
       assert_equals(await message, "img blocked",
                     "Image should be blocked by CSP inherited from navigation initiator.");
 
       // Navigate to another page, which will navigate back.
-      let loaded_2 = message_from(iframe.contentWindow, "ready");
-      let message_2 = message_from(iframe.contentWindow, "img");
-      iframe.contentWindow.location = testCase.other_origin + "/content-security-policy/inheritance/support/message-top-and-navigate-back.html";
+      const token_2 = token();
+      let loaded_2 = message_from(token_2, "ready");
+      let message_2 = message_from(testCase.token, "img");
+      iframe.contentWindow.location = testCase.other_origin +
+        "/content-security-policy/inheritance/support" +
+        `/message-top-and-navigate-back.html?token=${token_2}`;
       assert_equals(await loaded_2, "ready",
                     "Could not navigate iframe.");
 
       // If the local scheme document is "about:blank", we need to write its
       // content again.
-      if (testCase.url === "about:blank")
-        await write_img_to_about_blank(t, iframe);
+      if (testCase.add_img_function) {
+        testCase.add_img_function(t, iframe);
+      }
 
       // Check that the local scheme document reloaded from history still has
       // the original CSPs.
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/history.sub.html b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/history.sub.html
index 672def1..6ebd679 100644
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/history.sub.html
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/history.sub.html
@@ -1,16 +1,17 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
 
 <meta http-equiv="Content-Security-Policy" content="img-src 'none'">
 
 <script>
-  let message_from = (w, starts_with) => {
+  let message_from = (source_token, starts_with) => {
     return new Promise(resolve => {
       window.addEventListener('message', msg => {
-        if (msg.source == w) {
-          if (!starts_with || msg.data.startsWith(starts_with))
-            resolve(msg.data);
+        if (msg.data.token === source_token) {
+          if (!starts_with || msg.data.msg.startsWith(starts_with))
+            resolve(msg.data.msg);
         }
       });
     });
@@ -18,26 +19,30 @@
 
   const img_url = window.origin + "/content-security-policy/support/fail.png";
 
-  const function_addImage_string = `
+  const function_addImage_string = img_token => `
     function addImage() {
       let img = document.createElement('img');
       img.src = '${img_url}';
-      img.onload = () => opener.postMessage('img loaded', '*');
-      img.onerror = () => opener.postMessage('img blocked', '*');
+      img.onload = () => opener.postMessage(
+          {msg: 'img loaded', token: '${img_token}'}, '*');
+      img.onerror = () => opener.postMessage(
+          {msg: 'img blocked', token: '${img_token}'}, '*');
       document.body.appendChild(img);
     }
   `;
 
-  const img_tag_string = `
+  const img_tag_string = img_token => `
     <img src="${img_url}"
-         onload="opener.postMessage('img loaded', '*');"
-         onerror="opener.postMessage('img blocked', '*');"
+         onload="opener.postMessage(
+             {msg: 'img loaded', token: '${img_token}'}, '*');"
+         onerror="opener.postMessage(
+             {msg: 'img blocked', token: '${img_token}'}, '*');"
     >
   `;
 
-  let write_img_to_popup = (popup) => {
+  let write_img_to_popup = (popup, img_token) => {
     let div = popup.document.createElement('div');
-    div.innerHTML = img_tag_string;
+    div.innerHTML = img_tag_string(img_token);
     popup.document.body.appendChild(div);
   };
 
@@ -53,61 +58,65 @@
     });
   `;
 
-  const blob_payload = `
+  const blob_payload = blob_token => `
     <!doctype html>
-    <script>${function_addImage_string}</scr`+`ipt>
+    <script>window.window_token = "${blob_token}";</scr`+`ipt>
+    <script>${function_addImage_string(`${blob_token}`)}</scr`+`ipt>
     <body onpageshow="addImage();"></body>
   `;
-  let blob_url = URL.createObjectURL(
-    new Blob([blob_payload], { type: 'text/html' }));
+  let blob_url = blob_token => URL.createObjectURL(
+    new Blob([blob_payload(blob_token)], { type: 'text/html' }));
 
-  const blob_payload_no_bfcache = `
+  const blob_payload_no_bfcache = blob_token => `
     <!doctype html>
+    <script>window.window_token = "${blob_token}";</scr`+`ipt>
     <script>${disable_bfcache}</scr`+`ipt>
-    <script>${function_addImage_string}</scr`+`ipt>
+    <script>${function_addImage_string(`${blob_token}`)}</scr`+`ipt>
     <body onpageshow="addImage();"></body>
   `;
-  let blob_url_no_bfcache = URL.createObjectURL(
-    new Blob([blob_payload_no_bfcache], { type: 'text/html' }));
+  let blob_url_no_bfcache = blob_token => URL.createObjectURL(
+    new Blob([blob_payload_no_bfcache(blob_token)], { type: 'text/html' }));
 
   let testCases = [
-    {
+    test_token => ({
+      token: test_token,
       url: "about:blank",
-      add_img_function: write_img_to_popup,
+      add_img_function: popup => write_img_to_popup(popup, test_token),
       other_origin: window.origin,
       name: '"about:blank" document is navigated back from history same-origin.',
-    },
-    {
+    }),
+    test_token => ({
+      token: test_token,
       url: "about:blank",
-      add_img_function: write_img_to_popup,
+      add_img_function: popup => write_img_to_popup(popup, test_token),
       other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}",
       name: '"about:blank" document is navigated back from history cross-origin.',
-    },
-    {
-      url: blob_url,
-      add_img_function: () => {},
+    }),
+    test_token => ({
+      token: test_token,
+      url: blob_url(test_token),
       other_origin: window.origin,
       name: 'blob URL document is navigated back from history same-origin.',
-    },
-    {
-      url: blob_url,
-      add_img_function: () => {},
+    }),
+    test_token => ({
+      token: test_token,
+      url: blob_url(test_token),
       other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}",
       name: 'blob URL document is navigated back from history cross-origin.',
-    },
-    {
-      url: blob_url_no_bfcache,
-      add_img_function: () => {},
+    }),
+    test_token => ({
+      token: test_token,
+      url: blob_url_no_bfcache(test_token),
       other_origin: window.origin,
       name: 'blob URL document is navigated back from history (without bfcache on Firefox) same-origin.',
-    },
-    {
-      url: blob_url_no_bfcache,
-      add_img_function: () => {},
+    }),
+    test_token => ({
+      token: test_token,
+      url: blob_url_no_bfcache(test_token),
       other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}",
       name: 'blob URL document is navigated back from history (without bfcache on Firefox) cross-origin.',
-    },
-  ];
+    }),
+  ].map(f => f(token()));
 
   let async_promise_test = (promise, description) => {
     async_test(test => {
@@ -129,8 +138,11 @@
       // Perform a real navigation in the popup. This is needed because the
       // initial empty document is not stored in history (so there is no way of
       // navigating back to it and test history inheritance).
-      let loaded_1 = message_from(popup);
-      popup.location = testCase.other_origin + "/content-security-policy/inheritance/support/postmessage-opener.html";
+      const token_1 = token();
+      let loaded_1 = message_from(token_1);
+      popup.location = testCase.other_origin +
+        `/content-security-policy/inheritance/support` +
+        `/postmessage-opener.html?token=${token_1}`;
       assert_equals(await loaded_1, "ready",
                     "Could not open and navigate popup.");
 
@@ -147,19 +159,24 @@
         timeout=3000,
         interval=50);
 
-      let message = message_from(popup);
+      let message = message_from(testCase.token);
       popup.location = testCase.url;
       await wait();
+      if (testCase.add_img_function) {
+        testCase.add_img_function(popup);
+      }
 
-      testCase.add_img_function(popup);
       // Check that the local scheme document inherits CSP from the initiator.
       assert_equals(await message, "img blocked",
                     "Image should be blocked by CSP inherited from navigation initiator.");
 
-      let loaded_2 = message_from(popup, "ready");
-      let message_2 = message_from(popup, "img");
+      const token_2 = token();
+      let loaded_2 = message_from(token_2, "ready");
+      let message_2 = message_from(testCase.token, "img");
       // Navigate to another page, which will navigate back.
-      popup.location = testCase.other_origin + "/content-security-policy/inheritance/support/message-opener-and-navigate-back.html";
+      popup.location = testCase.other_origin +
+        `/content-security-policy/inheritance/support` +
+        `/message-opener-and-navigate-back.html?token=${token_2}`;
       assert_equals(await loaded_2, "ready",
                     "Could not navigate popup.");
 
@@ -168,7 +185,9 @@
 
       // Check that the "about:blank" document reloaded from history has the
       // original CSPs.
-      testCase.add_img_function(popup);
+      if (testCase.add_img_function) {
+        testCase.add_img_function(popup);
+      }
       assert_equals(await message_2, "img blocked",
                     "Image should be blocked by CSP reloaded from history.");
     }, "History navigation: " + testCase.name);
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/support/message-opener-and-navigate-back.html b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/support/message-opener-and-navigate-back.html
index 6e0d3f5..75ee5be 100644
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/support/message-opener-and-navigate-back.html
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/support/message-opener-and-navigate-back.html
@@ -1,4 +1,5 @@
 <script>
-  opener.postMessage("ready", "*");
+  const params = new URLSearchParams(window.location.search);
+  opener.postMessage({msg: "ready", token: params.get("token")}, "*");
   window.history.back();
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/support/message-top-and-navigate-back.html b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/support/message-top-and-navigate-back.html
index 6fccbaaa..53d5a18 100644
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/support/message-top-and-navigate-back.html
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/support/message-top-and-navigate-back.html
@@ -1,4 +1,5 @@
 <script>
-  top.postMessage("ready", "*");
+  const params = new URLSearchParams(window.location.search);
+  top.postMessage({msg: "ready", token: params.get("token")}, "*");
   window.history.back();
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/support/postmessage-opener.html b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/support/postmessage-opener.html
index 4278c0e..7ee11bc 100644
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/support/postmessage-opener.html
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/support/postmessage-opener.html
@@ -1,3 +1,4 @@
 <script>
-  opener.postMessage("ready", "*");
+  const params = new URLSearchParams(window.location.search);
+  opener.postMessage({msg: "ready", token: params.get("token")}, "*");
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/support/postmessage-top.html b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/support/postmessage-top.html
index 4f83a58..242063a 100644
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/support/postmessage-top.html
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/support/postmessage-top.html
@@ -1,4 +1,5 @@
 <!DOCTYPE html>
 <script>
-  top.postMessage("ready", "*");
+  const params = new URLSearchParams(window.location.search);
+  top.postMessage({msg: "ready", token: params.get("token")}, "*");
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/window-open-local-after-network-scheme.sub.html b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/window-open-local-after-network-scheme.sub.html
index dfae9a3..0cdc03ce 100644
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/window-open-local-after-network-scheme.sub.html
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/window-open-local-after-network-scheme.sub.html
@@ -1,17 +1,18 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
 
 <meta http-equiv="Content-Security-Policy" content="img-src 'none'">
 <title>about:blank in popup inherits CSPs from the navigation initiator</title>
 <body>
 
 <script>
-  const message_from = (w) => {
+  const message_from = (source_token, w) => {
     return new Promise(resolve => {
       window.addEventListener('message', msg => {
-        if (msg.source == w)
-          resolve(msg.data);
+        if (msg.data.token === source_token)
+          resolve(msg.data.msg);
       });
     });
   };
@@ -30,9 +31,14 @@
   testCases.forEach(testCase => {
     promise_test(async t => {
       // Create a popup and navigate it.
-      const popup = window.open("about:blank", testCase.name);
-      const loaded = message_from(popup);
-      window.open(testCase.previous_origin + "/content-security-policy/inheritance/support/postmessage-opener.html", testCase.name);
+      const popup_token = token();
+      // const popup = window.open("about:blank", testCase.name);
+      const loaded = message_from(popup_token);
+      const popup = window.open(
+        testCase.previous_origin +
+          "/content-security-policy/inheritance/support" +
+          `/postmessage-opener.html?token=${popup_token}`,
+        testCase.name);
       t.add_cleanup(() => popup.close());
 
       assert_equals(await loaded, "ready");
@@ -60,15 +66,16 @@
       popup.document.head.appendChild(script);
       const div = popup.document.createElement('div');
 
+      const img_token = token();
       const img_url = window.origin + "/content-security-policy/support/fail.png";
       div.innerHTML = `
         <img src="${img_url}"
-             onload="messageBack('img loaded');"
-             onerror="messageBack('img blocked');"
+             onload="messageBack({msg: 'img loaded', token: '${img_token}'});"
+             onerror="messageBack({msg: 'img blocked', token: '${img_token}'});"
         >
       `;
 
-      const msg = message_from(popup);
+      const msg = message_from(img_token);
       popup.document.body.appendChild(div);
       assert_equals(await msg, "img blocked");
     }, testCase.name);
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/crashtests/replace-keyframes-animating-filter-001.html b/third_party/blink/web_tests/external/wpt/css/css-animations/crashtests/replace-keyframes-animating-filter-001.html
new file mode 100644
index 0000000..e635537
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-animations/crashtests/replace-keyframes-animating-filter-001.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html class="test-wait">
+<title>CSS Test (Animations): Changing an @keyframes that animates filter</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/">
+<link rel="author" title="Google" href="http://www.google.com/">
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1301937">
+<link rel="help" href="https://drafts.csswg.org/css-animations-1/#keyframes">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects/#supported-filter-functions">
+<link rel="help" href="https://drafts.csswg.org/cssom-1/#the-cssstylesheet-interface">
+<meta name="assert" content="This should not crash.">
+
+<style>
+#el1 {
+  height: 100px;
+  width: 100px;
+  animation: kf1 2s linear;
+}
+@keyframes kf1 {
+  from { filter: grayscale(0.9) }
+  to { filter: grayscale(0.8) }
+}
+</style>
+<div id="el1"></div>
+<script>
+
+document.documentElement.addEventListener("TestRendered", step1);
+
+function step1() {
+  requestAnimationFrame(function() { requestAnimationFrame(step2); });
+}
+
+function step2() {
+  let css = document.styleSheets[0];
+  css.insertRule("@keyframes kf1 { from { color: blue } to { color: blue } } ", css.rules.length);
+  requestAnimationFrame(step3);
+}
+
+function step3() {
+  document.documentElement.classList.remove("test-wait");
+}
+
+</script>
diff --git a/third_party/boringssl/OWNERS b/third_party/boringssl/OWNERS
index 411f841..89fd9d4 100644
--- a/third_party/boringssl/OWNERS
+++ b/third_party/boringssl/OWNERS
@@ -1,4 +1,3 @@
 agl@chromium.org
 davidben@chromium.org
-rsleevi@chromium.org
 svaldez@chromium.org
diff --git a/third_party/dav1d/dav1d_generated.gni b/third_party/dav1d/dav1d_generated.gni
index be9e1e3..8a11cf1 100644
--- a/third_party/dav1d/dav1d_generated.gni
+++ b/third_party/dav1d/dav1d_generated.gni
@@ -60,7 +60,6 @@
 arm32_asm_sources = [
   "libdav1d/src/arm/32/cdef.S",
   "libdav1d/src/arm/32/cdef16.S",
-  "libdav1d/src/arm/32/cdef_tmpl.S",
   "libdav1d/src/arm/32/film_grain.S",
   "libdav1d/src/arm/32/film_grain16.S",
   "libdav1d/src/arm/32/ipred.S",
@@ -72,18 +71,15 @@
   "libdav1d/src/arm/32/looprestoration.S",
   "libdav1d/src/arm/32/looprestoration16.S",
   "libdav1d/src/arm/32/looprestoration_common.S",
-  "libdav1d/src/arm/32/looprestoration_tmpl.S",
   "libdav1d/src/arm/32/mc.S",
   "libdav1d/src/arm/32/mc16.S",
   "libdav1d/src/arm/32/msac.S",
   "libdav1d/src/arm/32/refmvs.S",
-  "libdav1d/src/arm/32/util.S",
 ]
 
 arm64_asm_sources = [
   "libdav1d/src/arm/64/cdef.S",
   "libdav1d/src/arm/64/cdef16.S",
-  "libdav1d/src/arm/64/cdef_tmpl.S",
   "libdav1d/src/arm/64/film_grain.S",
   "libdav1d/src/arm/64/film_grain16.S",
   "libdav1d/src/arm/64/ipred.S",
@@ -95,12 +91,10 @@
   "libdav1d/src/arm/64/looprestoration.S",
   "libdav1d/src/arm/64/looprestoration16.S",
   "libdav1d/src/arm/64/looprestoration_common.S",
-  "libdav1d/src/arm/64/looprestoration_tmpl.S",
   "libdav1d/src/arm/64/mc.S",
   "libdav1d/src/arm/64/mc16.S",
   "libdav1d/src/arm/64/msac.S",
   "libdav1d/src/arm/64/refmvs.S",
-  "libdav1d/src/arm/64/util.S",
 ]
 
 arm_template_sources = [
diff --git a/third_party/dav1d/generate_configs.py b/third_party/dav1d/generate_configs.py
index e139e43e..fe771704 100755
--- a/third_party/dav1d/generate_configs.py
+++ b/third_party/dav1d/generate_configs.py
@@ -53,7 +53,7 @@
   output = subprocess.check_output([
       os.path.join(CHROMIUM_ROOT_DIR, 'build', 'vs_toolchain.py'),
       'get_toolchain_dir'
-  ])
+  ], universal_newlines=True)
 
   # Turn this into a dictionary.
   win_dirs = gn_helpers.FromGNArgs(output)
@@ -65,7 +65,7 @@
       os.path.join(CHROMIUM_ROOT_DIR, 'build', 'toolchain', 'win',
                    'setup_toolchain.py'), win_dirs['vs_path'],
       win_dirs['sdk_path'], win_dirs['runtime_dirs'], 'win', target_arch, 'none'
-  ])
+  ], universal_newlines=True)
 
   flags = gn_helpers.FromGNArgs(output)
   cwd = os.getcwd()
diff --git a/third_party/dav1d/generate_source.py b/third_party/dav1d/generate_source.py
index 833dc00..5c319fa9 100755
--- a/third_party/dav1d/generate_source.py
+++ b/third_party/dav1d/generate_source.py
@@ -52,9 +52,12 @@
   _WriteArray(fd, "x86_asm_sources", _Glob("libdav1d/src/x86/*.asm"))
   _WriteArray(fd, "x86_template_sources", _Glob("libdav1d/src/x86/*_tmpl.c"))
 
-  # TODO(dalecurtis): May want to exclude "util.S" here.
-  _WriteArray(fd, "arm32_asm_sources", _Glob("libdav1d/src/arm/32/*.S"))
-  _WriteArray(fd, "arm64_asm_sources", _Glob("libdav1d/src/arm/64/*.S"))
+  _WriteArray(fd, "arm32_asm_sources", _Glob("libdav1d/src/arm/32/*.S"),
+              _Glob("libdav1d/src/arm/32/*_tmpl.S") +
+              ["libdav1d/src/arm/32/util.S"])
+  _WriteArray(fd, "arm64_asm_sources", _Glob("libdav1d/src/arm/64/*.S"),
+              _Glob("libdav1d/src/arm/64/*_tmpl.S") +
+              ["libdav1d/src/arm/64/util.S"])
   _WriteArray(fd, "arm_template_sources", _Glob("libdav1d/src/arm/*_tmpl.c"))
 
   template_sources = _Glob("libdav1d/src/*_tmpl.c")
@@ -72,7 +75,7 @@
 
 
 def main():
-  with open("dav1d_generated.gni", "wb") as fd:
+  with open("dav1d_generated.gni", "w") as fd:
     _WriteGn(fd)
 
 
diff --git a/third_party/google_trust_services/OWNERS b/third_party/google_trust_services/OWNERS
index d114fa83..0faa4b5f 100644
--- a/third_party/google_trust_services/OWNERS
+++ b/third_party/google_trust_services/OWNERS
@@ -1,3 +1,2 @@
 asymmetric@chromium.org
 awhalley@chromium.org
-rsleevi@chromium.org
diff --git a/third_party/modp_b64/OWNERS b/third_party/modp_b64/OWNERS
index 81033345..e69de29 100644
--- a/third_party/modp_b64/OWNERS
+++ b/third_party/modp_b64/OWNERS
@@ -1 +0,0 @@
-rsleevi@chromium.org
diff --git a/tools/ipc_fuzzer/fuzzer/fuzzer.cc b/tools/ipc_fuzzer/fuzzer/fuzzer.cc
index c1f1cba..16694cb 100644
--- a/tools/ipc_fuzzer/fuzzer/fuzzer.cc
+++ b/tools/ipc_fuzzer/fuzzer/fuzzer.cc
@@ -1593,10 +1593,12 @@
       origin = url::Origin::UnsafelyCreateTupleOriginWithoutNormalization(
           scheme, host, port);
     } else {
-      absl::optional<base::UnguessableToken> token =
-          p->GetNonceForSerialization();
-      if (!token)
+      absl::optional<base::UnguessableToken> token;
+      if (auto* nonce = p->GetNonceForSerialization()) {
+        token = *nonce;
+      } else {
         token = base::UnguessableToken::Deserialize(RandU64(), RandU64());
+      }
       if (!FuzzParam(&(*token), fuzzer))
         return false;
       origin = url::Origin::UnsafelyCreateOpaqueOriginWithoutNormalization(
diff --git a/tools/luci-go/OWNERS b/tools/luci-go/OWNERS
index 65f9d1f..93f505a 100644
--- a/tools/luci-go/OWNERS
+++ b/tools/luci-go/OWNERS
@@ -1,3 +1,2 @@
 maruel@chromium.org
-tandrii@google.com
 vadimsh@chromium.org
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 27cf13b..05b86b1 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -19182,6 +19182,15 @@
   </description>
 </action>
 
+<action name="MobileTabGridSearchCloseTabFromAnotherWindow">
+  <owner>michaeldo@chromium.org</owner>
+  <owner>mrefaat@chromium.org</owner>
+  <description>
+    User in the iOS tab grid closed a tab from another window by closing it from
+    search results.
+  </description>
+</action>
+
 <action name="MobileTabGridSearchTabs">
   <owner>mrefaat@chromium.org</owner>
   <owner>michaeldo@chromium.org</owner>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index ef38dd71..6844c5d8 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -53201,6 +53201,7 @@
   <int value="-926039080" label="VaapiVp9kSVCHWEncoding:disabled"/>
   <int value="-920204598" label="ScrollAnchorSerialization:enabled"/>
   <int value="-918900957" label="AutofillCreditCardAssist:disabled"/>
+  <int value="-918899240" label="HistoryClustersOnDeviceClustering:disabled"/>
   <int value="-918618075" label="enable-service-worker"/>
   <int value="-916780902" label="ExternalPciDevicesAllowed:enabled"/>
   <int value="-915328316" label="CupsIppPrintingBackend:disabled"/>
@@ -55381,6 +55382,7 @@
   <int value="632324382"
       label="ExperimentalAccessibilityDictationListening:disabled"/>
   <int value="632340413" label="network-settings-config"/>
+  <int value="632456816" label="HistoryClustersOnDeviceClustering:enabled"/>
   <int value="633442161" label="ExperimentalUi:disabled"/>
   <int value="634789085" label="LayeredAPI:disabled"/>
   <int value="635076832" label="MarkHttpAs:disabled"/>
@@ -71260,6 +71262,11 @@
   <int value="2" label="Serialization error"/>
 </enum>
 
+<enum name="PerUserDaemonStoreFail">
+  <int value="0" label="Failed disabling consent"/>
+  <int value="1" label="Failed enabling consent"/>
+</enum>
+
 <enum name="PerUserIdType">
   <int value="0" label="Client ID"/>
   <int value="1" label="User ID"/>
diff --git a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
index 17a915d..e32d365 100644
--- a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
+++ b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
@@ -1313,6 +1313,17 @@
   </summary>
 </histogram>
 
+<histogram name="SafeBrowsing.PageLoadToken.HasExpired" units="BooleanExpired"
+    expires_after="2022-09-02">
+  <owner>xinghuilu@chromium.org</owner>
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
+  <summary>
+    Records whether a page load token has expired when it is retrieved. Logged
+    each time GetPageLoadToken is called and the token is found in the token
+    map.
+  </summary>
+</histogram>
+
 <histogram name="SafeBrowsing.PageLoadToken.PasswordProtectionHasToken"
     units="BooleanExists" expires_after="2022-10-08">
   <owner>xinghuilu@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/uma/histograms.xml b/tools/metrics/histograms/metadata/uma/histograms.xml
index 6ea32472..0e1e49e 100644
--- a/tools/metrics/histograms/metadata/uma/histograms.xml
+++ b/tools/metrics/histograms/metadata/uma/histograms.xml
@@ -180,6 +180,17 @@
   <summary>The source of the client id when its creation is forced.</summary>
 </histogram>
 
+<histogram name="UMA.CrosPerUser.DaemonStoreWriteFailed"
+    enum="PerUserDaemonStoreFail" expires_after="2022-10-01">
+  <owner>jongahn@chromium.org</owner>
+  <owner>src/base/metrics/OWNERS</owner>
+  <summary>
+    Records the state that metrics service is in when user log store was set or
+    unset. This should be recorded once when a valid user that can use per-user
+    logs in and unsetting should be recorded once when a user logs out.
+  </summary>
+</histogram>
+
 <histogram name="UMA.CrosPerUser.IdReset" enum="PerUserIdType"
     expires_after="2022-10-01">
   <owner>jongahn@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 48ddf55..33d31061 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,8 +5,8 @@
             "remote_path": "perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "win": {
-            "hash": "d72bd5a879fefaf5836c78b9f2224fd74eeb8ef9",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/11de3dcf8b4e4c727906a0fb055b5493e9d2de82/trace_processor_shell.exe"
+            "hash": "602e7e88bc8db05ca82760aa5a63db3465334418",
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/b6557e37c41e01d2cb0508b4c6583e23e2838a17/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893",
@@ -21,8 +21,8 @@
             "remote_path": "perfetto_binaries/trace_processor_shell/mac_arm64/cefb3e0ec3a0580c996f801e854fe02963c03d5c/trace_processor_shell"
         },
         "linux": {
-            "hash": "5557a39925471dc411ec48c5f6a0b8e715772d36",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/11de3dcf8b4e4c727906a0fb055b5493e9d2de82/trace_processor_shell"
+            "hash": "791e1b35991b872ca7b35da945a4ee293b50a5c4",
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/b6557e37c41e01d2cb0508b4c6583e23e2838a17/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/ui/accessibility/platform/fuchsia/semantic_provider_unittest.cc b/ui/accessibility/platform/fuchsia/semantic_provider_unittest.cc
index dac5ac8..655d9fc 100644
--- a/ui/accessibility/platform/fuchsia/semantic_provider_unittest.cc
+++ b/ui/accessibility/platform/fuchsia/semantic_provider_unittest.cc
@@ -179,8 +179,7 @@
   std::unique_ptr<ui::AXFuchsiaSemanticProviderImpl> semantic_provider_;
 };
 
-TEST_F(AXFuchsiaSemanticProviderTest,
-       DISABLED_HandlesOnSemanticsConnectionClosed) {
+TEST_F(AXFuchsiaSemanticProviderTest, HandlesOnSemanticsConnectionClosed) {
   semantic_tree_binding_.Close(ZX_ERR_PEER_CLOSED);
 
   // Spin the loop to allow the channel-close to be handled.
@@ -189,7 +188,7 @@
   EXPECT_TRUE(delegate_->on_semantics_manager_connection_closed_called_);
 }
 
-TEST_F(AXFuchsiaSemanticProviderTest, DISABLED_HandlesOnAccessibilityAction) {
+TEST_F(AXFuchsiaSemanticProviderTest, HandlesOnAccessibilityAction) {
   bool action_handled = false;
   semantic_listener_->OnAccessibilityActionRequested(
       /*node_id=*/1u, fuchsia::accessibility::semantics::Action::DEFAULT,
@@ -205,7 +204,7 @@
             fuchsia::accessibility::semantics::Action::DEFAULT);
 }
 
-TEST_F(AXFuchsiaSemanticProviderTest, DISABLED_HandlesOnHitTest) {
+TEST_F(AXFuchsiaSemanticProviderTest, HandlesOnHitTest) {
   // Note that the point is sent here and will be converted according to the
   // device scale used. Only then it gets sent to the handler, which receives
   // the value already with the proper scaling.
@@ -222,7 +221,7 @@
   EXPECT_EQ(delegate_->on_hit_test_point_.y, 12.0);
 }
 
-TEST_F(AXFuchsiaSemanticProviderTest, DISABLED_HandlesOnSemanticsEnabled) {
+TEST_F(AXFuchsiaSemanticProviderTest, HandlesOnSemanticsEnabled) {
   semantic_listener_->OnSemanticsModeChanged(false, [](auto...) {});
 
   // Spin the loop to handle the call.
@@ -231,7 +230,7 @@
   EXPECT_TRUE(delegate_->on_semantics_enabled_called_);
 }
 
-TEST_F(AXFuchsiaSemanticProviderTest, DISABLED_SendsRootOnly) {
+TEST_F(AXFuchsiaSemanticProviderTest, SendsRootOnly) {
   Node root;
   root.set_node_id(0u);
   EXPECT_TRUE(semantic_provider_->Update(std::move(root)));
@@ -243,7 +242,7 @@
   EXPECT_FALSE(semantic_provider_->HasPendingUpdates());
 }
 
-TEST_F(AXFuchsiaSemanticProviderTest, DISABLED_SendsNodesFromRootToLeaves) {
+TEST_F(AXFuchsiaSemanticProviderTest, SendsNodesFromRootToLeaves) {
   auto tree_nodes = TreeNodes();
   for (auto& node : tree_nodes) {
     EXPECT_TRUE(semantic_provider_->Update(std::move(node)));
@@ -256,7 +255,7 @@
   EXPECT_FALSE(semantic_provider_->HasPendingUpdates());
 }
 
-TEST_F(AXFuchsiaSemanticProviderTest, DISABLED_SendsNodesFromLeavesToRoot) {
+TEST_F(AXFuchsiaSemanticProviderTest, SendsNodesFromLeavesToRoot) {
   auto nodes = TreeNodes();
   std::reverse(nodes.begin(), nodes.end());
   for (auto& node : nodes) {
@@ -271,7 +270,7 @@
 }
 
 TEST_F(AXFuchsiaSemanticProviderTest,
-       DISABLED_SendsNodesOnlyAfterParentNoLongerPointsToDeletedChild) {
+       SendsNodesOnlyAfterParentNoLongerPointsToDeletedChild) {
   auto tree_nodes = TreeNodes();
   for (auto& node : tree_nodes) {
     EXPECT_TRUE(semantic_provider_->Update(std::move(node)));
@@ -307,7 +306,7 @@
 }
 
 TEST_F(AXFuchsiaSemanticProviderTest,
-       DISABLED_SendsNodesOnlyAfterDanglingChildIsDeleted) {
+       SendsNodesOnlyAfterDanglingChildIsDeleted) {
   auto tree_nodes = TreeNodes();
   for (auto& node : tree_nodes) {
     EXPECT_TRUE(semantic_provider_->Update(std::move(node)));
@@ -339,7 +338,7 @@
   EXPECT_FALSE(semantic_provider_->HasPendingUpdates());
 }
 
-TEST_F(AXFuchsiaSemanticProviderTest, DISABLED_ReparentsNodeWithADeletion) {
+TEST_F(AXFuchsiaSemanticProviderTest, ReparentsNodeWithADeletion) {
   auto tree_nodes = TreeNodes();
   for (auto& node : tree_nodes) {
     EXPECT_TRUE(semantic_provider_->Update(std::move(node)));
@@ -383,7 +382,7 @@
   EXPECT_FALSE(semantic_provider_->HasPendingUpdates());
 }
 
-TEST_F(AXFuchsiaSemanticProviderTest, DISABLED_ReparentsNodeWithAnUpdate) {
+TEST_F(AXFuchsiaSemanticProviderTest, ReparentsNodeWithAnUpdate) {
   auto tree_nodes = TreeNodes();
   for (auto& node : tree_nodes) {
     EXPECT_TRUE(semantic_provider_->Update(std::move(node)));
@@ -421,7 +420,7 @@
   EXPECT_FALSE(semantic_provider_->HasPendingUpdates());
 }
 
-TEST_F(AXFuchsiaSemanticProviderTest, DISABLED_ChangesRoot) {
+TEST_F(AXFuchsiaSemanticProviderTest, ChangesRoot) {
   auto tree_nodes = TreeNodes();
   for (auto& node : tree_nodes) {
     EXPECT_TRUE(semantic_provider_->Update(std::move(node)));
@@ -446,7 +445,7 @@
   EXPECT_FALSE(semantic_provider_->HasPendingUpdates());
 }
 
-TEST_F(AXFuchsiaSemanticProviderTest, DISABLED_BatchesUpdates) {
+TEST_F(AXFuchsiaSemanticProviderTest, BatchesUpdates) {
   std::vector<Node> updates;
   for (uint32_t i = 0; i < 30; ++i) {
     Node node;
@@ -469,7 +468,7 @@
   EXPECT_FALSE(semantic_provider_->HasPendingUpdates());
 }
 
-TEST_F(AXFuchsiaSemanticProviderTest, DISABLED_ClearsTree) {
+TEST_F(AXFuchsiaSemanticProviderTest, ClearsTree) {
   auto tree_nodes = TreeNodes();
   for (auto& node : tree_nodes) {
     EXPECT_TRUE(semantic_provider_->Update(std::move(node)));
diff --git a/ui/aura/demo/demo_main.cc b/ui/aura/demo/demo_main.cc
index 9943382..c2e8dcd2 100644
--- a/ui/aura/demo/demo_main.cc
+++ b/ui/aura/demo/demo_main.cc
@@ -169,7 +169,7 @@
   ui::OzonePlatform::InitializeForUI(params);
   ui::OzonePlatform::InitializeForGPU(params);
 #endif
-  gl::init::InitializeGLOneOff();
+  gl::init::InitializeGLOneOff(/*system_device_id=*/0);
 
 #if BUILDFLAG(IS_WIN)
   display::win::SetDefaultDeviceScaleFactor(1.0f);
diff --git a/ui/gl/delegated_ink_point_renderer_gpu_unittest.cc b/ui/gl/delegated_ink_point_renderer_gpu_unittest.cc
index a96ff17..78f7442 100644
--- a/ui/gl/delegated_ink_point_renderer_gpu_unittest.cc
+++ b/ui/gl/delegated_ink_point_renderer_gpu_unittest.cc
@@ -97,7 +97,8 @@
  protected:
   void SetUp() override {
     // Without this, the following check always fails.
-    gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings=*/true);
+    gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings=*/true,
+                                             /*system_device_id=*/0);
     if (!gl::DirectCompositionSurfaceWin::GetDirectCompositionDevice()) {
       LOG(WARNING)
           << "GL implementation not using DirectComposition, skipping test.";
diff --git a/ui/gl/direct_composition_surface_win_unittest.cc b/ui/gl/direct_composition_surface_win_unittest.cc
index 476c02c..28858e1 100644
--- a/ui/gl/direct_composition_surface_win_unittest.cc
+++ b/ui/gl/direct_composition_surface_win_unittest.cc
@@ -123,7 +123,8 @@
     fake_power_monitor_source_.SetOnBatteryPower(true);
 
     // Without this, the following check always fails.
-    gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ true);
+    gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings=*/true,
+                                             /*system_device_id=*/0);
     if (!DirectCompositionSurfaceWin::GetDirectCompositionDevice()) {
       LOG(WARNING) << "DirectComposition not supported, skipping test.";
       return;
diff --git a/ui/gl/egl_api_unittest.cc b/ui/gl/egl_api_unittest.cc
index 64b35c3d..ffd94d0 100644
--- a/ui/gl/egl_api_unittest.cc
+++ b/ui/gl/egl_api_unittest.cc
@@ -50,7 +50,8 @@
       SetDisabledExtensionsEGL(disabled_extensions);
     }
     g_driver_egl.InitializeClientExtensionBindings();
-    GLSurfaceEGL::InitializeDisplay(EGLDisplayPlatform(EGL_DEFAULT_DISPLAY));
+    GLSurfaceEGL::InitializeDisplay(EGLDisplayPlatform(EGL_DEFAULT_DISPLAY),
+                                    /*system_device_id=*/0);
     g_driver_egl.InitializeExtensionBindings();
   }
 
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc
index acfd4af..4124a5f 100644
--- a/ui/gl/gl_surface_egl.cc
+++ b/ui/gl/gl_surface_egl.cc
@@ -154,6 +154,12 @@
 #define EGL_HIGH_POWER_ANGLE 0x0002
 #endif /* EGL_ANGLE_power_preference */
 
+#ifndef EGL_ANGLE_platform_angle_device_id
+#define EGL_ANGLE_platform_angle_device_id
+#define EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE 0x34D6
+#define EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE 0x34D7
+#endif /* EGL_ANGLE_platform_angle_device_id */
+
 // From ANGLE's egl/eglext.h.
 #ifndef EGL_ANGLE_feature_control
 #define EGL_ANGLE_feature_control 1
@@ -209,6 +215,7 @@
 bool g_egl_angle_feature_control_supported = false;
 bool g_egl_angle_power_preference_supported = false;
 bool g_egl_angle_display_power_preference_supported = false;
+bool g_egl_angle_platform_angle_device_id_supported = false;
 bool g_egl_angle_external_context_and_surface_supported = false;
 bool g_egl_ext_query_device_supported = false;
 bool g_egl_angle_context_virtualization_supported = false;
@@ -397,12 +404,23 @@
     EGLDisplayPlatform native_display,
     const std::vector<std::string>& enabled_angle_features,
     const std::vector<std::string>& disabled_angle_features,
-    bool disable_all_angle_features) {
+    bool disable_all_angle_features,
+    uint64_t system_device_id) {
   std::vector<EGLAttrib> extra_display_attribs;
   if (disable_all_angle_features) {
     extra_display_attribs.push_back(EGL_FEATURE_ALL_DISABLED_ANGLE);
     extra_display_attribs.push_back(EGL_TRUE);
   }
+  if (system_device_id != 0 &&
+      GLSurfaceEGL::IsANGLEPlatformANGLEDeviceIdSupported()) {
+    uint32_t low_part = system_device_id & 0xffffffff;
+    extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE);
+    extra_display_attribs.push_back(low_part);
+
+    uint32_t high_part = (system_device_id >> 32) & 0xffffffff;
+    extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE);
+    extra_display_attribs.push_back(high_part);
+  }
   switch (display_type) {
     case DEFAULT:
     case SWIFT_SHADER:
@@ -978,14 +996,15 @@
 }
 
 // static
-bool GLSurfaceEGL::InitializeOneOff(EGLDisplayPlatform native_display) {
+bool GLSurfaceEGL::InitializeOneOff(EGLDisplayPlatform native_display,
+                                    uint64_t system_device_id) {
   if (initialized_)
     return true;
 
   // Must be called before InitializeDisplay().
   g_driver_egl.InitializeClientExtensionBindings();
 
-  InitializeDisplay(native_display);
+  InitializeDisplay(native_display, system_device_id);
   if (g_egl_display == EGL_NO_DISPLAY)
     return false;
 
@@ -1293,6 +1312,10 @@
   return g_egl_angle_display_power_preference_supported;
 }
 
+bool GLSurfaceEGL::IsANGLEPlatformANGLEDeviceIdSupported() {
+  return g_egl_angle_platform_angle_device_id_supported;
+}
+
 bool GLSurfaceEGL::IsANGLEExternalContextAndSurfaceSupported() {
   return g_egl_angle_external_context_and_surface_supported;
 }
@@ -1316,7 +1339,8 @@
 // InitializeDisplay is necessary because the static binding code
 // needs a full Display init before it can query the Display extensions.
 // static
-EGLDisplay GLSurfaceEGL::InitializeDisplay(EGLDisplayPlatform native_display) {
+EGLDisplay GLSurfaceEGL::InitializeDisplay(EGLDisplayPlatform native_display,
+                                           uint64_t system_device_id) {
   if (g_egl_display != EGL_NO_DISPLAY) {
     return g_egl_display;
   }
@@ -1379,6 +1403,9 @@
   g_egl_angle_display_power_preference_supported =
       HasEGLClientExtension("EGL_ANGLE_display_power_preference");
 
+  g_egl_angle_platform_angle_device_id_supported =
+      HasEGLClientExtension("EGL_ANGLE_platform_angle_device_id");
+
   std::vector<DisplayType> init_displays;
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   GetEGLInitDisplays(supports_angle_d3d, supports_angle_opengl,
@@ -1400,7 +1427,7 @@
     DisplayType display_type = init_displays[disp_index];
     EGLDisplay display = GetDisplayFromType(
         display_type, g_native_display, enabled_angle_features,
-        disabled_angle_features, disable_all_angle_features);
+        disabled_angle_features, disable_all_angle_features, system_device_id);
     if (display == EGL_NO_DISPLAY) {
       LOG(ERROR) << "EGL display query failed with error "
                  << GetLastEGLErrorString();
diff --git a/ui/gl/gl_surface_egl.h b/ui/gl/gl_surface_egl.h
index 61faca3..87f34e2 100644
--- a/ui/gl/gl_surface_egl.h
+++ b/ui/gl/gl_surface_egl.h
@@ -98,12 +98,18 @@
   EGLConfig GetConfig() override;
   GLSurfaceFormat GetFormat() override;
 
-  static bool InitializeOneOff(EGLDisplayPlatform native_display);
+  // |system_device_id| specifies which GPU to use on a multi-GPU system.
+  // If its value is 0, use the default GPU of the system.
+  static bool InitializeOneOff(EGLDisplayPlatform native_display,
+                               uint64_t system_device_id);
   static bool InitializeOneOffForTesting();
   static bool InitializeExtensionSettingsOneOff();
   static void ShutdownOneOff();
   static EGLDisplay GetHardwareDisplay();
-  static EGLDisplay InitializeDisplay(EGLDisplayPlatform native_display);
+  // |system_device_id| specifies which GPU to use on a multi-GPU system.
+  // If its value is 0, use the default GPU of the system.
+  static EGLDisplay InitializeDisplay(EGLDisplayPlatform native_display,
+                                      uint64_t system_device_id);
   static EGLNativeDisplayType GetNativeDisplay();
   static DisplayType GetDisplayType();
 
@@ -130,10 +136,10 @@
   static bool IsANGLEFeatureControlSupported();
   static bool IsANGLEPowerPreferenceSupported();
   static bool IsANGLEDisplayPowerPreferenceSupported();
+  static bool IsANGLEPlatformANGLEDeviceIdSupported();
   static bool IsANGLEExternalContextAndSurfaceSupported();
   static bool IsANGLEContextVirtualizationSupported();
   static bool IsANGLEVulkanImageSupported();
-
   static bool IsEGLQueryDeviceSupported();
 
  protected:
diff --git a/ui/gl/init/gl_factory.cc b/ui/gl/init/gl_factory.cc
index e917391..7ed039c 100644
--- a/ui/gl/init/gl_factory.cc
+++ b/ui/gl/init/gl_factory.cc
@@ -138,7 +138,8 @@
   return GLImplementationParts(kGLImplementationNone);
 }
 
-bool InitializeGLOneOffPlatformHelper(bool init_extensions) {
+bool InitializeGLOneOffPlatformHelper(bool init_extensions,
+                                      uint64_t system_device_id) {
   TRACE_EVENT1("gpu,startup", "gl::init::InitializeGLOneOffPlatformHelper",
                "init_extensions", init_extensions);
 
@@ -147,12 +148,13 @@
   bool disable_gl_drawing = cmd->HasSwitch(switches::kDisableGLDrawingForTests);
 
   return InitializeGLOneOffPlatformImplementation(
-      fallback_to_software_gl, disable_gl_drawing, init_extensions);
+      fallback_to_software_gl, disable_gl_drawing, init_extensions,
+      system_device_id);
 }
 
 }  // namespace
 
-bool InitializeGLOneOff() {
+bool InitializeGLOneOff(uint64_t system_device_id) {
   TRACE_EVENT0("gpu,startup", "gl::init::InitializeOneOff");
 
   if (!InitializeStaticGLBindingsOneOff())
@@ -160,10 +162,11 @@
   if (GetGLImplementation() == kGLImplementationDisabled)
     return true;
 
-  return InitializeGLOneOffPlatformHelper(true);
+  return InitializeGLOneOffPlatformHelper(true, system_device_id);
 }
 
-bool InitializeGLNoExtensionsOneOff(bool init_bindings) {
+bool InitializeGLNoExtensionsOneOff(bool init_bindings,
+                                    uint64_t system_device_id) {
   TRACE_EVENT1("gpu,startup", "gl::init::InitializeNoExtensionsOneOff",
                "init_bindings", init_bindings);
   if (init_bindings) {
@@ -173,7 +176,7 @@
       return true;
   }
 
-  return InitializeGLOneOffPlatformHelper(false);
+  return InitializeGLOneOffPlatformHelper(false, system_device_id);
 }
 
 bool InitializeStaticGLBindingsOneOff() {
@@ -213,16 +216,17 @@
 
 bool InitializeGLOneOffPlatformImplementation(bool fallback_to_software_gl,
                                               bool disable_gl_drawing,
-                                              bool init_extensions) {
+                                              bool init_extensions,
+                                              uint64_t system_device_id) {
   if (IsSoftwareGLImplementation(GetGLImplementationParts()))
     fallback_to_software_gl = false;
 
-  bool initialized = InitializeGLOneOffPlatform();
+  bool initialized = InitializeGLOneOffPlatform(system_device_id);
   if (!initialized && fallback_to_software_gl) {
     ShutdownGL(/*due_to_fallback*/ true);
     initialized =
         InitializeStaticGLBindings(GetSoftwareGLImplementationForPlatform()) &&
-        InitializeGLOneOffPlatform();
+        InitializeGLOneOffPlatform(system_device_id);
   }
   if (initialized && init_extensions) {
     initialized = InitializeExtensionSettingsOneOffPlatform();
diff --git a/ui/gl/init/gl_factory.h b/ui/gl/init/gl_factory.h
index 1836eac..bf6765f 100644
--- a/ui/gl/init/gl_factory.h
+++ b/ui/gl/init/gl_factory.h
@@ -33,10 +33,15 @@
 GL_INIT_EXPORT std::vector<GLImplementationParts> GetAllowedGLImplementations();
 
 // Initializes GL bindings and extension settings.
-GL_INIT_EXPORT bool InitializeGLOneOff();
+// |system_device_id| specifies which GPU to use on a multi-GPU system.
+// If its value is 0, use the default GPU of the system.
+GL_INIT_EXPORT bool InitializeGLOneOff(uint64_t system_device_id);
 
 // Initializes GL bindings without initializing extension settings.
-GL_INIT_EXPORT bool InitializeGLNoExtensionsOneOff(bool init_bindings);
+// |system_device_id| specifies which GPU to use on a multi-GPU system.
+// If its value is 0, use the default GPU of the system.
+GL_INIT_EXPORT bool InitializeGLNoExtensionsOneOff(bool init_bindings,
+                                                   uint64_t system_device_id);
 
 // Initializes GL bindings - load dlls and get proc address according to gl
 // command line switch.
@@ -55,10 +60,13 @@
 // Initializes GL platform using the provided parameters. This might be required
 // for use in tests. This should be called only after GL bindings are initilzed
 // successfully.
+// |system_device_id| specifies which GPU to use on a multi-GPU system.
+// If its value is 0, use the default GPU of the system.
 GL_INIT_EXPORT bool InitializeGLOneOffPlatformImplementation(
     bool fallback_to_software_gl,
     bool disable_gl_drawing,
-    bool init_extensions);
+    bool init_extensions,
+    uint64_t system_device_id);
 
 // Clears GL bindings and resets GL implementation.
 GL_INIT_EXPORT void ShutdownGL(bool due_to_fallback);
diff --git a/ui/gl/init/gl_initializer.h b/ui/gl/init/gl_initializer.h
index 95a5a55..06445b3 100644
--- a/ui/gl/init/gl_initializer.h
+++ b/ui/gl/init/gl_initializer.h
@@ -18,7 +18,9 @@
 // InitializeGLNoExtensionsOneOff(). For tests possibly
 // InitializeStaticGLBindingsImplementation() +
 // InitializeGLOneOffPlatformImplementation() instead.
-bool InitializeGLOneOffPlatform();
+// |system_device_id| specifies which GPU to use on a multi-GPU system.
+// If its value is 0, use the default GPU of the system.
+bool InitializeGLOneOffPlatform(uint64_t system_device_id);
 
 // Initializes a particular GL implementation.
 bool InitializeStaticGLBindings(GLImplementationParts implementation);
diff --git a/ui/gl/init/gl_initializer_android.cc b/ui/gl/init/gl_initializer_android.cc
index 175fd82..d26c601 100644
--- a/ui/gl/init/gl_initializer_android.cc
+++ b/ui/gl/init/gl_initializer_android.cc
@@ -76,12 +76,12 @@
 
 }  // namespace
 
-bool InitializeGLOneOffPlatform() {
+bool InitializeGLOneOffPlatform(uint64_t system_device_id) {
   switch (GetGLImplementation()) {
     case kGLImplementationEGLGLES2:
     case kGLImplementationEGLANGLE:
       if (!GLSurfaceEGL::InitializeOneOff(
-              EGLDisplayPlatform(EGL_DEFAULT_DISPLAY))) {
+              EGLDisplayPlatform(EGL_DEFAULT_DISPLAY), system_device_id)) {
         LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
         return false;
       }
diff --git a/ui/gl/init/gl_initializer_mac.cc b/ui/gl/init/gl_initializer_mac.cc
index 98f3c5a4..4c78f4c1 100644
--- a/ui/gl/init/gl_initializer_mac.cc
+++ b/ui/gl/init/gl_initializer_mac.cc
@@ -184,7 +184,7 @@
 
 }  // namespace
 
-bool InitializeGLOneOffPlatform() {
+bool InitializeGLOneOffPlatform(uint64_t system_device_id) {
   switch (GetGLImplementation()) {
     case kGLImplementationDesktopGL:
     case kGLImplementationDesktopGLCoreProfile:
@@ -198,7 +198,8 @@
     case kGLImplementationEGLGLES2:
     case kGLImplementationEGLANGLE:
     case kGLImplementationSwiftShaderGL:
-      if (!GLSurfaceEGL::InitializeOneOff(EGLDisplayPlatform(0))) {
+      if (!GLSurfaceEGL::InitializeOneOff(EGLDisplayPlatform(0),
+                                          system_device_id)) {
         LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
         return false;
       }
diff --git a/ui/gl/init/gl_initializer_ozone.cc b/ui/gl/init/gl_initializer_ozone.cc
index 4fd2a2d2..36aef21 100644
--- a/ui/gl/init/gl_initializer_ozone.cc
+++ b/ui/gl/init/gl_initializer_ozone.cc
@@ -19,7 +19,7 @@
 namespace gl {
 namespace init {
 
-bool InitializeGLOneOffPlatform() {
+bool InitializeGLOneOffPlatform(uint64_t) {
   if (HasGLOzone()) {
     gl::GLDisplayEglUtil::SetInstance(gl::GLDisplayEglUtilOzone::GetInstance());
     return GetGLOzone()->InitializeGLOneOffPlatform();
diff --git a/ui/gl/init/gl_initializer_win.cc b/ui/gl/init/gl_initializer_win.cc
index 7c2c13b..05b9e03 100644
--- a/ui/gl/init/gl_initializer_win.cc
+++ b/ui/gl/init/gl_initializer_win.cc
@@ -132,13 +132,14 @@
 
 }  // namespace
 
-bool InitializeGLOneOffPlatform() {
+bool InitializeGLOneOffPlatform(uint64_t system_device_id) {
   VSyncProviderWin::InitializeOneOff();
 
   switch (GetGLImplementation()) {
     case kGLImplementationSwiftShaderGL:
     case kGLImplementationEGLANGLE:
-      if (!GLSurfaceEGL::InitializeOneOff(EGLDisplayPlatform(GetDC(nullptr)))) {
+      if (!GLSurfaceEGL::InitializeOneOff(EGLDisplayPlatform(GetDC(nullptr)),
+                                          system_device_id)) {
         LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
         return false;
       }
diff --git a/ui/gl/test/gl_surface_test_support.cc b/ui/gl/test/gl_surface_test_support.cc
index 836ea1a0..9f63da7 100644
--- a/ui/gl/test/gl_surface_test_support.cc
+++ b/ui/gl/test/gl_surface_test_support.cc
@@ -70,7 +70,8 @@
   CHECK(gl::init::InitializeStaticGLBindingsImplementation(
       impl, fallback_to_software_gl));
   CHECK(gl::init::InitializeGLOneOffPlatformImplementation(
-      fallback_to_software_gl, disable_gl_drawing, init_extensions));
+      fallback_to_software_gl, disable_gl_drawing, init_extensions,
+      /*system_device_id=*/0));
 }
 }  // namespace
 
@@ -96,11 +97,13 @@
   init::ShutdownGL(false);
 
   bool disable_gl_drawing = false;
+  bool init_extensions = true;
 
   CHECK(gl::init::InitializeStaticGLBindingsImplementation(
       impl, fallback_to_software_gl));
   CHECK(gl::init::InitializeGLOneOffPlatformImplementation(
-      fallback_to_software_gl, disable_gl_drawing, true));
+      fallback_to_software_gl, disable_gl_drawing, init_extensions,
+      /*system_device_id=*/0));
 }
 
 // static
diff --git a/ui/ozone/common/gl_ozone_egl.cc b/ui/ozone/common/gl_ozone_egl.cc
index 194d29f..2034d0a 100644
--- a/ui/ozone/common/gl_ozone_egl.cc
+++ b/ui/ozone/common/gl_ozone_egl.cc
@@ -16,7 +16,8 @@
 namespace ui {
 
 bool GLOzoneEGL::InitializeGLOneOffPlatform() {
-  if (!gl::GLSurfaceEGL::InitializeOneOff(GetNativeDisplay())) {
+  if (!gl::GLSurfaceEGL::InitializeOneOff(GetNativeDisplay(),
+                                          /*system_device_id=*/0)) {
     LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
     return false;
   }
diff --git a/ui/ozone/demo/simple_renderer_factory.cc b/ui/ozone/demo/simple_renderer_factory.cc
index 98ac818d..da58010 100644
--- a/ui/ozone/demo/simple_renderer_factory.cc
+++ b/ui/ozone/demo/simple_renderer_factory.cc
@@ -65,7 +65,8 @@
     }
   }
 #endif
-  if (!command_line->HasSwitch(kDisableGpu) && gl::init::InitializeGLOneOff()) {
+  if (!command_line->HasSwitch(kDisableGpu) &&
+      gl::init::InitializeGLOneOff(/*system_device_id=*/0)) {
     type_ = GL;
   } else {
     type_ = SOFTWARE;
diff --git a/ui/ozone/demo/skia/skia_renderer_factory.cc b/ui/ozone/demo/skia/skia_renderer_factory.cc
index 005c224..bbad1df 100644
--- a/ui/ozone/demo/skia/skia_renderer_factory.cc
+++ b/ui/ozone/demo/skia/skia_renderer_factory.cc
@@ -38,7 +38,7 @@
 SkiaRendererFactory::~SkiaRendererFactory() {}
 
 bool SkiaRendererFactory::Initialize() {
-  if (!gl::init::InitializeGLOneOff()) {
+  if (!gl::init::InitializeGLOneOff(/*system_device_id=*/0)) {
     LOG(FATAL) << "Failed to initialize GL";
   }
 
diff --git a/ui/views/OWNERS b/ui/views/OWNERS
index e244df5..bd1791d 100644
--- a/ui/views/OWNERS
+++ b/ui/views/OWNERS
@@ -13,7 +13,6 @@
 sky@chromium.org
 tapted@chromium.org
 tluk@chromium.org
-weili@chromium.org
 
 # Prefer avi@, ellyjones@, lgrey@, or tapted@ for mac specific changes.
 per-file *_mac.*=avi@chromium.org
diff --git a/ui/views/examples/examples_main_proc.cc b/ui/views/examples/examples_main_proc.cc
index f298342..567df516 100644
--- a/ui/views/examples/examples_main_proc.cc
+++ b/ui/views/examples/examples_main_proc.cc
@@ -114,7 +114,7 @@
   ui::OzonePlatform::InitializeForGPU(params);
 #endif
 
-  gl::init::InitializeGLOneOff();
+  gl::init::InitializeGLOneOff(/*system_device_id=*/0);
 
   // Viz depends on the task environment to correctly tear down.
   base::test::TaskEnvironment task_environment(
diff --git a/url/mojom/origin_mojom_traits.h b/url/mojom/origin_mojom_traits.h
index e47d7a7..f5d4dbc3 100644
--- a/url/mojom/origin_mojom_traits.h
+++ b/url/mojom/origin_mojom_traits.h
@@ -8,6 +8,7 @@
 #include "base/component_export.h"
 #include "base/unguessable_token.h"
 #include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
+#include "mojo/public/cpp/bindings/optional_as_pointer.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/mojom/origin.mojom-shared.h"
 #include "url/origin.h"
@@ -26,10 +27,9 @@
   static uint16_t port(const url::Origin& r) {
     return r.GetTupleOrPrecursorTupleIfOpaque().port();
   }
-  static const absl::optional<base::UnguessableToken> nonce_if_opaque(
+  static mojo::OptionalAsPointer<const base::UnguessableToken> nonce_if_opaque(
       const url::Origin& r) {
-    // TODO(nasko): Consider returning a const reference here.
-    return r.GetNonceForSerialization();
+    return mojo::MakeOptionalAsPointer(r.GetNonceForSerialization());
   }
   static bool Read(url::mojom::OriginDataView data, url::Origin* out);
 };
diff --git a/url/origin.cc b/url/origin.cc
index 48bc050..0600b696 100644
--- a/url/origin.cc
+++ b/url/origin.cc
@@ -150,11 +150,8 @@
   return tuple_.GetURL();
 }
 
-absl::optional<base::UnguessableToken> Origin::GetNonceForSerialization()
-    const {
-  // TODO(nasko): Consider not making a copy here, but return a reference to
-  // the nonce.
-  return nonce_ ? absl::make_optional(nonce_->token()) : absl::nullopt;
+const base::UnguessableToken* Origin::GetNonceForSerialization() const {
+  return nonce_ ? &nonce_->token() : nullptr;
 }
 
 bool Origin::IsSameOriginWith(const Origin& other) const {
diff --git a/url/origin.h b/url/origin.h
index 181941ab..1ad8f28 100644
--- a/url/origin.h
+++ b/url/origin.h
@@ -403,9 +403,10 @@
   // given |nonce|.
   Origin(const Nonce& nonce, SchemeHostPort precursor);
 
-  // Get the nonce associated with this origin, if it is opaque. This should be
-  // used only when trying to send an Origin across an IPC pipe.
-  absl::optional<base::UnguessableToken> GetNonceForSerialization() const;
+  // Get the nonce associated with this origin, if it is opaque, or nullptr
+  // otherwise. This should be used only when trying to send an Origin across an
+  // IPC pipe.
+  const base::UnguessableToken* GetNonceForSerialization() const;
 
   // Serializes this Origin, including its nonce if it is opaque. If an opaque
   // origin's |tuple_| is invalid nullopt is returned. If the nonce is not
diff --git a/url/origin_unittest.cc b/url/origin_unittest.cc
index d2899b37a..82354b1 100644
--- a/url/origin_unittest.cc
+++ b/url/origin_unittest.cc
@@ -69,7 +69,7 @@
     return Origin::Nonce(nonce);
   }
 
-  absl::optional<base::UnguessableToken> GetNonce(const Origin& origin) {
+  const base::UnguessableToken* GetNonce(const Origin& origin) {
     return origin.GetNonceForSerialization();
   }
 
@@ -364,7 +364,7 @@
       << "UnsafelyCreateOpaqueOriginWithoutNormalization, so long as it is "
       << "the canonical form of the invalid tuple.";
   EXPECT_TRUE(anonymous_opaque->opaque());
-  EXPECT_EQ(GetNonce(anonymous_opaque.value()), token);
+  EXPECT_EQ(*GetNonce(anonymous_opaque.value()), token);
   EXPECT_EQ(anonymous_opaque->GetTupleOrPrecursorTupleIfOpaque(),
             url::SchemeHostPort());
 }
diff --git a/weblayer/BUILD.gn b/weblayer/BUILD.gn
index 07c513f1..692f00d0 100644
--- a/weblayer/BUILD.gn
+++ b/weblayer/BUILD.gn
@@ -687,6 +687,8 @@
       "browser/url_bar/trusted_cdn_observer.h",
       "browser/verdict_cache_manager_factory.cc",
       "browser/verdict_cache_manager_factory.h",
+      "browser/webapps/webapps_utils.cc",
+      "browser/webapps/webapps_utils.h",
       "browser/webapps/weblayer_webapps_client.cc",
       "browser/webapps/weblayer_webapps_client.h",
       "browser/weblayer_factory_impl_android.cc",
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/WebappsHelper.java b/weblayer/browser/java/org/chromium/weblayer_private/WebappsHelper.java
index 7e6f370..963c21a2 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/WebappsHelper.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/WebappsHelper.java
@@ -15,8 +15,8 @@
     private WebappsHelper() {}
 
     @CalledByNative
-    public static void addShortcut(String id, String url, String userTitle, Bitmap icon,
-            boolean isIconAdaptive, int source, String iconUrl) {
+    public static void addShortcutToHomescreen(
+            String id, String url, String userTitle, Bitmap icon, boolean isIconAdaptive) {
         Intent shortcutIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
         WebappsUtils.addShortcutToHomescreen(id, userTitle, icon, isIconAdaptive, shortcutIntent);
     }
diff --git a/weblayer/browser/webapps/webapps_utils.cc b/weblayer/browser/webapps/webapps_utils.cc
new file mode 100644
index 0000000..f63684d
--- /dev/null
+++ b/weblayer/browser/webapps/webapps_utils.cc
@@ -0,0 +1,41 @@
+// 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 "weblayer/browser/webapps/webapps_utils.h"
+
+#include <string>
+
+#include "base/android/jni_string.h"
+#include "ui/gfx/android/java_bitmap.h"
+#include "url/gurl.h"
+#include "weblayer/browser/java/jni/WebappsHelper_jni.h"
+
+using base::android::ConvertUTF16ToJavaString;
+using base::android::ConvertUTF8ToJavaString;
+using base::android::ScopedJavaLocalRef;
+
+namespace webapps {
+
+void addShortcutToHomescreen(const std::string& id,
+                             const GURL& url,
+                             const std::u16string& user_title,
+                             const SkBitmap& primary_icon,
+                             bool is_primary_icon_maskable) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> java_id = ConvertUTF8ToJavaString(env, id);
+  ScopedJavaLocalRef<jstring> java_url =
+      ConvertUTF8ToJavaString(env, url.spec());
+  ScopedJavaLocalRef<jstring> java_user_title =
+      ConvertUTF16ToJavaString(env, user_title);
+
+  ScopedJavaLocalRef<jobject> java_bitmap;
+  if (!primary_icon.drawsNothing())
+    java_bitmap = gfx::ConvertToJavaBitmap(primary_icon);
+
+  Java_WebappsHelper_addShortcutToHomescreen(env, java_id, java_url,
+                                             java_user_title, java_bitmap,
+                                             is_primary_icon_maskable);
+}
+
+}  // namespace webapps
diff --git a/weblayer/browser/webapps/webapps_utils.h b/weblayer/browser/webapps/webapps_utils.h
new file mode 100644
index 0000000..efa6e7f
--- /dev/null
+++ b/weblayer/browser/webapps/webapps_utils.h
@@ -0,0 +1,25 @@
+// 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 WEBLAYER_BROWSER_WEBAPPS_WEBAPPS_UTILS_H_
+#define WEBLAYER_BROWSER_WEBAPPS_WEBAPPS_UTILS_H_
+
+#include <string>
+
+class GURL;
+class SkBitmap;
+
+namespace webapps {
+
+// Adds a shortcut to the home screen. Calls the native method
+// addShortcutToHomescreen in WebappsHelper.java
+void addShortcutToHomescreen(const std::string& id,
+                             const GURL& url,
+                             const std::u16string& user_title,
+                             const SkBitmap& primary_icon,
+                             bool is_primary_icon_maskable);
+
+}  // namespace webapps
+
+#endif  // WEBLAYER_BROWSER_WEBAPPS_WEBAPPS_UTILS_H_
diff --git a/weblayer/browser/webapps/weblayer_webapps_client.cc b/weblayer/browser/webapps/weblayer_webapps_client.cc
index cf981c4..3f6b0c0 100644
--- a/weblayer/browser/webapps/weblayer_webapps_client.cc
+++ b/weblayer/browser/webapps/weblayer_webapps_client.cc
@@ -6,24 +6,21 @@
 
 #include <string>
 
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/guid.h"
 #include "base/logging.h"
 #include "base/no_destructor.h"
 #include "build/build_config.h"
 #include "components/infobars/content/content_infobar_manager.h"
 #include "components/security_state/content/content_utils.h"
-#include "components/webapps/browser/installable/installable_metrics.h"
-#include "weblayer/browser/java/jni/WebappsHelper_jni.h"
-
-#if BUILDFLAG(IS_ANDROID)
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/guid.h"
 #include "components/webapps/browser/android/add_to_homescreen_params.h"
 #include "components/webapps/browser/android/shortcut_info.h"
+#include "components/webapps/browser/installable/installable_metrics.h"
 #include "ui/android/color_utils_android.h"
 #include "ui/gfx/android/java_bitmap.h"
 #include "url/gurl.h"
-#endif
+#include "weblayer/browser/webapps/webapps_utils.h"
 
 namespace weblayer {
 
@@ -66,7 +63,6 @@
   return nullptr;
 }
 
-#if BUILDFLAG(IS_ANDROID)
 bool WebLayerWebappsClient::IsInstallationInProgress(
     content::WebContents* web_contents,
     const GURL& manifest_url) {
@@ -93,22 +89,10 @@
     content::WebContents* web_contents,
     const webapps::AddToHomescreenParams& params) {
   const webapps::ShortcutInfo& info = *params.shortcut_info;
-  JNIEnv* env = base::android::AttachCurrentThread();
-  ScopedJavaLocalRef<jstring> java_id =
-      ConvertUTF8ToJavaString(env, base::GenerateGUID());
-  ScopedJavaLocalRef<jstring> java_url =
-      ConvertUTF8ToJavaString(env, info.url.spec());
-  ScopedJavaLocalRef<jstring> java_user_title =
-      ConvertUTF16ToJavaString(env, info.user_title);
-  ScopedJavaLocalRef<jstring> java_best_primary_icon_url =
-      ConvertUTF8ToJavaString(env, info.best_primary_icon_url.spec());
-  ScopedJavaLocalRef<jobject> java_bitmap;
-  if (!params.primary_icon.drawsNothing())
-    java_bitmap = gfx::ConvertToJavaBitmap(params.primary_icon);
-  Java_WebappsHelper_addShortcut(env, java_id, java_url, java_user_title,
-                                 java_bitmap, params.has_maskable_primary_icon,
-                                 info.source, java_best_primary_icon_url);
+
+  webapps::addShortcutToHomescreen(base::GenerateGUID(), info.url,
+                                   info.user_title, params.primary_icon,
+                                   params.has_maskable_primary_icon);
 }
-#endif
 
 }  // namespace weblayer