diff --git a/AUTHORS b/AUTHORS
index ebbd358..31ddb044 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1090,6 +1090,7 @@
 Trevor Perrin <unsafe@trevp.net>
 Tripta Gupta <tripta.g@samsung.com>
 Tristan Fraipont <tristan.fraipont@gmail.com>
+Tudor Brindus <me@tbrindus.ca>
 Tuukka Toivonen <tuukka.toivonen@intel.com>
 U. Artie Eoff <ullysses.a.eoff@intel.com>
 Umar Hansa <umar.hansa@gmail.com>
diff --git a/DEPS b/DEPS
index 8bb8b1f0..33c011f 100644
--- a/DEPS
+++ b/DEPS
@@ -209,11 +209,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '8f39137a45339830691d0911894eabf3fb25a89e',
+  'skia_revision': '9c4f705e5b0d6348a5153e5b0dfcc45f05995302',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'a296b0203c48c3de8d65c1274abe8062e0f2dc81',
+  'v8_revision': '547ce4eca0f04fd08ea36a4865b4a0882adb2356',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -288,7 +288,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': 'c0969ff0ad4faf423ed1cc3a20feec97990b2580',
+  'devtools_frontend_revision': '2fc6ae15275cc85e5433c92bc172001883324f22',
   # 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.
@@ -328,7 +328,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'c74af7037817b2b5324d2097ea0f277044424b19',
+  'dawn_revision': '6e62e2f8e529067d15113ed3b1d7e4057ca06bd3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -966,7 +966,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '4570dcf468ca11d56a9ca89131e20c42248e7b3b',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '029279376e6c57e8725ddcabe6fb5d8a9be0a7b5',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1321,7 +1321,7 @@
     Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '3dd5b80bc4f172dd82925bb259cb7c82348409c5',
 
   'src/third_party/openscreen/src':
-    Var('chromium_git') + '/openscreen' + '@' + '6f8ee344b38f3e9e801deaa3d8acfb3119704fe9',
+    Var('chromium_git') + '/openscreen' + '@' + '37e21e8e06746c3106ff4c22ca8e41d29ffc27d6',
 
   'src/third_party/openxr/src': {
     'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '97cfe495bb7a3853266b646d1c79e169387f9c7a',
@@ -1416,7 +1416,7 @@
       'packages': [
           {
               'package': 'fuchsia/third_party/aemu/linux-amd64',
-              'version': '5N6FwgqmyBS24hwziHWxZLR4nhoKE0nBTCcAalD07zUC'
+              'version': 'Q9wrtYCFy4whHc75FrdwzygrqI5DSmX_tuj8UJUcrckC'
           },
       ],
       'condition': 'host_os == "linux" and checkout_fuchsia',
@@ -1435,7 +1435,7 @@
   },
 
   'src/third_party/re2/src':
-    Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '969c3bd5a820ea0613b9a7ddcd97c3de1bb19285',
+    Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + 'fdba2677f32812e823c54d214fe54c73e60b5163',
 
   'src/third_party/r8': {
       'packages': [
@@ -1552,7 +1552,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '3692cbbd3224f9d7e2ae138ef26bd584855249a1',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '410d70d965d68ead2daa83ee7f0b694cebd0dad2',
+    Var('webrtc_git') + '/src.git' + '@' + '612ddd74f07bac7977d4bc1cb6ae91c000a505f2',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1613,7 +1613,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b68eec027db1b3577ef16b716d6c877cab33913c',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@fca5899fefdc23c7beb0cd412fd851bcb7019fbb',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/DIR_METADATA b/android_webview/DIR_METADATA
index 5d6b8f66..b364c24 100644
--- a/android_webview/DIR_METADATA
+++ b/android_webview/DIR_METADATA
@@ -1,10 +1,10 @@
 # Metadata information for this directory.
 #
 # For more information on DIR_METADATA files, see:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
 #
 # For the schema of this file, see Metadata message:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
 
 monorail {
   component: "Mobile>WebView"
diff --git a/android_webview/docs/aosp-system-integration.md b/android_webview/docs/aosp-system-integration.md
index 5743672..883d085e 100644
--- a/android_webview/docs/aosp-system-integration.md
+++ b/android_webview/docs/aosp-system-integration.md
@@ -127,7 +127,7 @@
 ### Choosing a WebView version
 
 WebView follows the same branching and release model as the rest of the Chromium
-project: a beta version is branched from the master branch approximately every
+project: a beta version is branched from the main branch approximately every
 six weeks, and after approximately six weeks of beta testing it is released to
 stable. If critical security or functionality issues are discovered after the
 stable release, a new version may be released from the same stable branch at any
@@ -144,7 +144,7 @@
 
 If you're intending to build WebView just in order to develop, modify, or
 customise it, it's usually best to work directly on the latest version of the
-master branch. Chromium's master branch is covered by a large number of
+main branch. Chromium's main branch is covered by a large number of
 automated build and test systems that ensure it is sufficiently stable for
 development purposes at almost all times.
 
diff --git a/android_webview/docs/commandline-flags.md b/android_webview/docs/commandline-flags.md
index dff24ae..cb90f01 100644
--- a/android_webview/docs/commandline-flags.md
+++ b/android_webview/docs/commandline-flags.md
@@ -145,12 +145,12 @@
    [`aw_switches.cc`](/android_webview/common/aw_switches.cc). We use
    [`java_cpp_strings`](/docs/android_accessing_cpp_switches_in_java.md) to
    automatically generate Java switch constants from the C++ switches (see
-   [`AwSwitches.java`](https://source.chromium.org/chromium/chromium/src/+/master:out/android-Debug/gen/android_webview/common_java/generated_java/input_srcjars/org/chromium/android_webview/common/AwSwitches.java)).
+   [`AwSwitches.java`](https://source.chromium.org/chromium/chromium/src/+/main:out/android-Debug/gen/android_webview/common_java/generated_java/input_srcjars/org/chromium/android_webview/common/AwSwitches.java)).
  * C++ `base::Features` are defined in
    [`aw_features.cc`](/android_webview/common/aw_features.cc). We use
    [`java_cpp_features`](/docs/android_accessing_cpp_features_in_java.md) to
    automatically generate Java constants from the C++ Features (see
-   [`AwFeatures.java`](https://source.chromium.org/chromium/chromium/src/+/master:out/android-Debug/gen/android_webview/common_java/generated_java/input_srcjars/org/chromium/android_webview/common/AwFeatures.java)).
+   [`AwFeatures.java`](https://source.chromium.org/chromium/chromium/src/+/main:out/android-Debug/gen/android_webview/common_java/generated_java/input_srcjars/org/chromium/android_webview/common/AwFeatures.java)).
 
 ## Implementation
 
diff --git a/android_webview/docs/how-does-on-create-window-work.md b/android_webview/docs/how-does-on-create-window-work.md
index 5a931255..b71ab63 100644
--- a/android_webview/docs/how-does-on-create-window-work.md
+++ b/android_webview/docs/how-does-on-create-window-work.md
@@ -46,13 +46,13 @@
 ## What happened under the hood
 
 1. When the parent WebView loads the web page and runs the JavaScript snippet,
-   [`AwWebContentsDelegate::AddNewContents`](https://source.chromium.org/chromium/chromium/src/+/master:android_webview/browser/aw_web_contents_delegate.h;drc=a418951d0e0939a779baf00842b77806ba2c2fda;l=44)
+   [`AwWebContentsDelegate::AddNewContents`](https://source.chromium.org/chromium/chromium/src/+/main:android_webview/browser/aw_web_contents_delegate.h;l=43;drc=3abb32da2944ffe178dd66f404e7e1bb88a58ed0)
    will be called. The corresponding Java side
-   [`AwWebContentsDelegate#addNewContents`](https://source.chromium.org/chromium/chromium/src/+/master:android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java;drc=c3df19e6cd403bebb24b7418b441c861332fbfda;l=29)
+   [`AwWebContentsDelegate#addNewContents`](https://source.chromium.org/chromium/chromium/src/+/main:android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java;l=30;drc=a19051603849d7810b3569daf158aceb23aad1da)
    is called from the native.
 
 1. At the same time,
-   [`AwContents::SetPendingWebContentsForPopup`](https://source.chromium.org/chromium/chromium/src/+/master:android_webview/browser/aw_contents.cc;drc=f32bfd577cabaabfb08dfa06ce2317ac65cb8aab;l=1072)
+   [`AwContents::SetPendingWebContentsForPopup`](https://source.chromium.org/chromium/chromium/src/+/main:android_webview/browser/aw_contents.cc;l=1099;drc=7776bbb38c4e394b5be085bc8c5bc02df5fa22dc)
    creates native popup AwContents with the given `WebContents` and stores it as
    `pending_contents_` in the parent `AwContents` object without Java
    counterpart created. Note that since `pending_contents_` can only store one
@@ -64,13 +64,13 @@
 
 1. `WebViewContentsClientAdapter` has a handler that receives the message sent
    from `resultMsg.sendToTarget()`. It will trigger
-   [`WebViewChromium#completeWindowCreation`](https://source.chromium.org/chromium/chromium/src/+/master:android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java;drc=8988f749860f6299bab8d76a89e56134ccdf4bdb;l=268),
+   [`WebViewChromium#completeWindowCreation`](https://source.chromium.org/chromium/chromium/src/+/main:android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java;l=265;drc=da3bb54157d4603b9c820d6cfdf61859f804dfb2),
    then
-   [`AwContents#supplyContentsForPopup`](https://source.chromium.org/chromium/chromium/src/+/master:android_webview/java/src/org/chromium/android_webview/AwContents.java;drc=83df35b1f2713897ff958dab849d103438f4457a;l=1300)
+   [`AwContents#supplyContentsForPopup`](https://source.chromium.org/chromium/chromium/src/+/main:android_webview/java/src/org/chromium/android_webview/AwContents.java;l=1455;drc=4afe92995db1279895f8a40b69c374bc298d750f)
    is called on the parent WebView/AwContents.
 
 1. `AwContents#supplyContentsForPopup` calls
-   [`AwContents#receivePopupContents`](https://source.chromium.org/chromium/chromium/src/+/master:android_webview/java/src/org/chromium/android_webview/AwContents.java;drc=83df35b1f2713897ff958dab849d103438f4457a;l=1319)
+   [`AwContents#receivePopupContents`](https://source.chromium.org/chromium/chromium/src/+/main:android_webview/java/src/org/chromium/android_webview/AwContents.java;l=1475;drc=4afe92995db1279895f8a40b69c374bc298d750f)
    on the child WebView/AwContents. Child AwContents deletes the existing native
    AwContents from the child WebView/AwContents, and pairs it with the
    `pending_contents_` from the parent WebView/AwContents. In order to preserve
diff --git a/android_webview/docs/quick-start.md b/android_webview/docs/quick-start.md
index cffd940..6e1976f 100644
--- a/android_webview/docs/quick-start.md
+++ b/android_webview/docs/quick-start.md
@@ -136,7 +136,7 @@
 
 *** note
 **Note:** we only support local development using the latest revision of the
-master branch. Checking out release branches introduces a lot of complexity, and
+main branch. Checking out release branches introduces a lot of complexity, and
 it might not even be possible to build WebView for your device.
 ***
 
diff --git a/android_webview/docs/threading.md b/android_webview/docs/threading.md
index 4c77111..1aa2f00c 100644
--- a/android_webview/docs/threading.md
+++ b/android_webview/docs/threading.md
@@ -66,7 +66,7 @@
 Views in android are expected to be created and used on its single **view**
 thread, unless otherwise noted in the API. For WebView, this is enforced for
 apps targeting JB MR2 or above. The code lives in the
-[WebView](https://github.com/android/platform_frameworks_base/blob/master/core/java/android/webkit/WebView.java).
+[WebView](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/webkit/WebView.java).
 Note this is an orthogonal concern to the single **UI** thread described above,
 as this check still allows different WebViews to be used on different **view**
 threads.
diff --git a/android_webview/nonembedded/java/src/org/chromium/android_webview/nonembedded/AwNonembeddedUmaRecorder.java b/android_webview/nonembedded/java/src/org/chromium/android_webview/nonembedded/AwNonembeddedUmaRecorder.java
index 4a61d1e48..7be8e47 100644
--- a/android_webview/nonembedded/java/src/org/chromium/android_webview/nonembedded/AwNonembeddedUmaRecorder.java
+++ b/android_webview/nonembedded/java/src/org/chromium/android_webview/nonembedded/AwNonembeddedUmaRecorder.java
@@ -134,7 +134,7 @@
 
     /**
      * Records a user action. Action names must be documented in {@code actions.xml}. See {@link
-     * https://source.chromium.org/chromium/chromium/src/+/master:tools/metrics/actions/README.md}
+     * https://source.chromium.org/chromium/chromium/src/+/main:tools/metrics/actions/README.md}
      *
      * @param name Name of the user action.
      * @param elapsedRealtimeMillis Value of {@link android.os.SystemClock.elapsedRealtime()} when
diff --git a/android_webview/tools/generate_flag_labels.py b/android_webview/tools/generate_flag_labels.py
index 3894b13..050cd1a 100755
--- a/android_webview/tools/generate_flag_labels.py
+++ b/android_webview/tools/generate_flag_labels.py
@@ -245,7 +245,7 @@
 case-sensitive!), add these to enums.xml, run `git-cl format`, and then follow
 these steps as a final check:
 
-https://chromium.googlesource.com/chromium/src/+/master/tools/metrics/histograms/README.md#flag-histograms
+https://chromium.googlesource.com/chromium/src/+/main/tools/metrics/histograms/README.md#flag-histograms
 
 If any labels were generated incorrectly, please edit this script and change
 KNOWN_MISTAKES.
diff --git a/android_webview/tools/remove_preinstalled_webview.py b/android_webview/tools/remove_preinstalled_webview.py
index 9e436cbe..b9eeb23 100755
--- a/android_webview/tools/remove_preinstalled_webview.py
+++ b/android_webview/tools/remove_preinstalled_webview.py
@@ -93,7 +93,7 @@
       # get lost.
       logging.error('Did you start the emulator with "-writable-system?"\n'
                     'See https://chromium.googlesource.com/chromium/src/+/'
-                    'master/docs/android_emulator.md#writable-system-partition'
+                    'main/docs/android_emulator.md#writable-system-partition'
                     '\n')
     raise
   device.SetWebViewFallbackLogic(False)  # Allow standalone WebView on N+
diff --git a/ash/app_list/views/expand_arrow_view.cc b/ash/app_list/views/expand_arrow_view.cc
index 9e72218..f81b688 100644
--- a/ash/app_list/views/expand_arrow_view.cc
+++ b/ash/app_list/views/expand_arrow_view.cc
@@ -272,10 +272,8 @@
 }
 
 std::unique_ptr<views::InkDrop> ExpandArrowView::CreateInkDrop() {
-  auto ink_drop = std::make_unique<views::InkDropImpl>(this, size());
-  ink_drop->SetAutoHighlightMode(views::InkDropImpl::AutoHighlightMode::NONE);
-  ink_drop->SetShowHighlightOnHover(false);
-  return ink_drop;
+  return views::InkDrop::CreateInkDropWithoutAutoHighlight(
+      this, /*highlight_on_hover=*/false);
 }
 
 std::unique_ptr<views::InkDropRipple> ExpandArrowView::CreateInkDropRipple()
diff --git a/ash/app_list/views/search_result_suggestion_chip_view.cc b/ash/app_list/views/search_result_suggestion_chip_view.cc
index b35287b6..d2fcfd4 100644
--- a/ash/app_list/views/search_result_suggestion_chip_view.cc
+++ b/ash/app_list/views/search_result_suggestion_chip_view.cc
@@ -155,11 +155,8 @@
 
 std::unique_ptr<views::InkDrop>
 SearchResultSuggestionChipView::CreateInkDrop() {
-  auto ink_drop = std::make_unique<views::InkDropImpl>(this, size());
-  ink_drop->SetAutoHighlightMode(views::InkDropImpl::AutoHighlightMode::NONE);
-  ink_drop->SetShowHighlightOnHover(false);
-  ink_drop->SetShowHighlightOnFocus(false);
-  return ink_drop;
+  return views::InkDrop::CreateInkDropWithoutAutoHighlight(
+      this, /*highlight_on_hover=*/false);
 }
 
 std::unique_ptr<views::InkDropRipple>
diff --git a/ash/app_list/views/search_result_tile_item_view.cc b/ash/app_list/views/search_result_tile_item_view.cc
index cfea1ce..ee500f4c 100644
--- a/ash/app_list/views/search_result_tile_item_view.cc
+++ b/ash/app_list/views/search_result_tile_item_view.cc
@@ -18,6 +18,7 @@
 #include "ash/public/cpp/app_list/app_list_features.h"
 #include "ash/public/cpp/app_list/app_list_types.h"
 #include "ash/public/cpp/app_list/vector_icons/vector_icons.h"
+#include "ash/public/cpp/ash_typography.h"
 #include "ash/public/cpp/pagination/pagination_model.h"
 #include "base/bind.h"
 #include "base/i18n/number_formatting.h"
@@ -151,6 +152,7 @@
     return;
 
   SetTitle(result()->title());
+  SetTitleTags(result()->title_tags());
   SetRating(result()->rating());
   SetPrice(result()->formatted_price());
 
@@ -312,6 +314,7 @@
 void SearchResultTileItemView::OnMetadataChanged() {
   SetIcon(result()->icon());
   SetTitle(result()->title());
+  SetTitleTags(result()->title_tags());
   SetBadgeIcon(result()->badge_icon(), result()->use_badge_icon_background());
   SetRating(result()->rating());
   SetPrice(result()->formatted_price());
@@ -454,6 +457,17 @@
   title_->SetText(title);
 }
 
+void SearchResultTileItemView::SetTitleTags(const SearchResultTags& tags) {
+  if (!app_list_features::IsLauncherQueryHighlightingEnabled())
+    return;
+
+  for (const auto& tag : tags) {
+    if (tag.styles & SearchResult::Tag::MATCH) {
+      title_->SetTextStyleRange(AshTextStyle::STYLE_EMPHASIZED, tag.range);
+    }
+  }
+}
+
 void SearchResultTileItemView::SetRating(float rating) {
   if (!rating_)
     return;
diff --git a/ash/app_list/views/search_result_tile_item_view.h b/ash/app_list/views/search_result_tile_item_view.h
index a7c9e25..dadbefe 100644
--- a/ash/app_list/views/search_result_tile_item_view.h
+++ b/ash/app_list/views/search_result_tile_item_view.h
@@ -11,6 +11,7 @@
 #include "ash/app_list/views/app_list_menu_model_adapter.h"
 #include "ash/app_list/views/search_result_base_view.h"
 #include "ash/ash_export.h"
+#include "ash/public/cpp/app_list/app_list_types.h"
 #include "base/macros.h"
 #include "ui/views/context_menu_controller.h"
 
@@ -89,6 +90,7 @@
   void SetBadgeIcon(const ui::ImageModel& badge_icon,
                     bool use_badge_icon_background);
   void SetTitle(const std::u16string& title);
+  void SetTitleTags(const SearchResultTags& tags);
   void SetRating(float rating);
   void SetPrice(const std::u16string& price);
 
@@ -111,7 +113,7 @@
   gfx::Size CalculatePreferredSize() const override;
   std::u16string GetTooltipText(const gfx::Point& p) const override;
 
-  AppListViewDelegate* const view_delegate_;           // Owned by AppListView.
+  AppListViewDelegate* const view_delegate_;  // Owned by AppListView.
 
   views::ImageView* icon_ = nullptr;         // Owned by views hierarchy.
   views::ImageView* badge_ = nullptr;        // Owned by views hierarchy.
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 43828ed..564fcd3 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -453,6 +453,10 @@
 const base::Feature kInstantTethering{"InstantTethering",
                                       base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Enables or disables noise cancellation UI toggle.
+const base::Feature kEnableInputNoiseCancellationUi{
+    "EnableInputNoiseCancellationUi", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enables the Kerberos Section in ChromeOS settings. When disabled, Kerberos
 // settings will stay under People Section. https://crbug.com/983041
 const base::Feature kKerberosSettingsSection{"KerberosSettingsSection",
@@ -830,6 +834,10 @@
   return base::FeatureList::IsEnabled(kGaiaReauthEndpoint);
 }
 
+bool IsInputNoiseCancellationUiEnabled() {
+  return base::FeatureList::IsEnabled(kEnableInputNoiseCancellationUi);
+}
+
 bool IsInstantTetheringBackgroundAdvertisingSupported() {
   return base::FeatureList::IsEnabled(
       kInstantTetheringBackgroundAdvertisementSupport);
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index 341f42f..730b5a9 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -138,6 +138,8 @@
 extern const base::Feature kEnableLocalSearchService;
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kEnableNetworkingInDiagnosticsApp;
+COMPONENT_EXPORT(ASH_CONSTANTS)
+extern const base::Feature kEnableInputNoiseCancellationUi;
 extern const base::Feature kEnableOobeChromeVoxHint;
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kEnablePciguardUi;
@@ -371,6 +373,7 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsMinimumChromeVersionEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsNetworkingInDiagnosticsAppEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsNewOobeLayoutEnabled();
+COMPONENT_EXPORT(ASH_CONSTANTS) bool IsInputNoiseCancellationUiEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeChromeVoxHintEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeScreensPriorityEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsPciguardUiEnabled();
diff --git a/ash/lock_screen_action/lock_screen_action_background_view.cc b/ash/lock_screen_action/lock_screen_action_background_view.cc
index be49b52..7c707b3f 100644
--- a/ash/lock_screen_action/lock_screen_action_background_view.cc
+++ b/ash/lock_screen_action/lock_screen_action_background_view.cc
@@ -35,10 +35,9 @@
   ~NoteBackground() override = default;
 
   std::unique_ptr<views::InkDrop> CreateInkDrop() override {
-    auto ink_drop = std::make_unique<views::InkDropImpl>(this, size());
-    ink_drop->SetAutoHighlightMode(views::InkDropImpl::AutoHighlightMode::NONE);
-    ink_drop->SetShowHighlightOnHover(false);
-    ink_drop->SetShowHighlightOnFocus(false);
+    std::unique_ptr<views::InkDrop> ink_drop =
+        views::InkDrop::CreateInkDropWithoutAutoHighlight(
+            this, /*highlight_on_hover=*/false);
     ink_drop->AddObserver(observer_);
     return ink_drop;
   }
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index fda5d05..a02fc4a1 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -321,6 +321,7 @@
     "//ash/public/cpp/external_arc",
     "//components/arc",
     "//components/exo",
+    "//components/soda",
   ]
 
   deps = [
diff --git a/ash/public/cpp/ash_pref_names.cc b/ash/public/cpp/ash_pref_names.cc
index 59d05bd..81df253a 100644
--- a/ash/public/cpp/ash_pref_names.cc
+++ b/ash/public/cpp/ash_pref_names.cc
@@ -625,6 +625,13 @@
 const char kPciePeripheralDisplayNotificationRemaining[] =
     "ash.pcie_peripheral_display_notification_remaining";
 
+// Boolean prefs storing whether various IME-related keyboard shortcut reminders
+// have previously been dismissed or not.
+const char kLastUsedImeShortcutReminderDismissed[] =
+    "ash.shortcut_reminders.last_used_ime_dismissed";
+const char kNextImeShortcutReminderDismissed[] =
+    "ash.shortcut_reminders.next_ime_dismissed";
+
 // NOTE: New prefs should start with the "ash." prefix. Existing prefs moved
 // into this file should not be renamed, since they may be synced.
 
diff --git a/ash/public/cpp/ash_pref_names.h b/ash/public/cpp/ash_pref_names.h
index 82ef6af..242c5c1 100644
--- a/ash/public/cpp/ash_pref_names.h
+++ b/ash/public/cpp/ash_pref_names.h
@@ -231,6 +231,9 @@
 ASH_PUBLIC_EXPORT extern const char
     kPciePeripheralDisplayNotificationRemaining[];
 
+ASH_PUBLIC_EXPORT extern const char kLastUsedImeShortcutReminderDismissed[];
+ASH_PUBLIC_EXPORT extern const char kNextImeShortcutReminderDismissed[];
+
 }  // namespace prefs
 
 }  // namespace ash
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc
index 97cff1bb..ef3e97a2 100644
--- a/ash/shelf/login_shelf_view.cc
+++ b/ash/shelf/login_shelf_view.cc
@@ -260,10 +260,8 @@
   }
 
   std::unique_ptr<views::InkDrop> CreateInkDrop() override {
-    auto ink_drop = std::make_unique<views::InkDropImpl>(this, size());
-    ink_drop->SetShowHighlightOnHover(false);
-    ink_drop->SetShowHighlightOnFocus(false);
-    return ink_drop;
+    return views::InkDrop::CreateInkDropWithoutAutoHighlight(
+        this, /*highlight_on_hover=*/false);
   }
 
   std::u16string GetTooltipText(const gfx::Point& p) const override {
@@ -397,10 +395,8 @@
   }
 
   std::unique_ptr<views::InkDrop> CreateInkDrop() override {
-    auto ink_drop = std::make_unique<views::InkDropImpl>(this, size());
-    ink_drop->SetShowHighlightOnHover(false);
-    ink_drop->SetShowHighlightOnFocus(false);
-    return ink_drop;
+    return views::InkDrop::CreateInkDropWithoutAutoHighlight(
+        this, /*highlight_on_hover=*/false);
   }
 
   void UpdateButtonColors() {
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc
index 0e1a241..774801f6 100644
--- a/ash/shelf/shelf_view_unittest.cc
+++ b/ash/shelf/shelf_view_unittest.cc
@@ -2388,9 +2388,8 @@
   void InitHomeButtonInkDrop() {
     home_button_ = GetPrimaryShelf()->navigation_widget()->GetHomeButton();
 
-    auto home_button_ink_drop =
-        std::make_unique<InkDropSpy>(std::make_unique<views::InkDropImpl>(
-            home_button_, home_button_->size()));
+    auto home_button_ink_drop = std::make_unique<InkDropSpy>(
+        views::InkDrop::CreateInkDropWithoutAutoHighlight(home_button_));
     home_button_ink_drop_ = home_button_ink_drop.get();
     views::test::InkDropHostViewTestApi(home_button_)
         .SetInkDrop(std::move(home_button_ink_drop), false);
diff --git a/ash/wm/default_state.cc b/ash/wm/default_state.cc
index e72264e3..6f28dca 100644
--- a/ash/wm/default_state.cc
+++ b/ash/wm/default_state.cc
@@ -261,12 +261,15 @@
       if (window_state->HasRestoreBounds() &&
           (window->bounds().height() == work_area.height() &&
            window->bounds().y() == work_area.y())) {
-        window_state->SetAndClearRestoreBounds();
+        window_state->SetBoundsDirectCrossFade(
+            window_state->GetRestoreBoundsInParent());
+        window_state->ClearRestoreBounds();
       } else {
         window_state->SaveCurrentBoundsForRestore();
-        window->SetBounds(gfx::Rect(window->bounds().x(), work_area.y(),
-                                    window->bounds().width(),
-                                    work_area.height()));
+        const gfx::Rect new_bounds =
+            gfx::Rect(window->bounds().x(), work_area.y(),
+                      window->bounds().width(), work_area.height());
+        window_state->SetBoundsDirectCrossFade(new_bounds);
       }
       return;
     }
@@ -284,7 +287,9 @@
           window_state->HasRestoreBounds() &&
           (window->bounds().width() == work_area.width() &&
            window->bounds().x() == work_area.x())) {
-        window_state->SetAndClearRestoreBounds();
+        window_state->SetBoundsDirectCrossFade(
+            window_state->GetRestoreBoundsInParent());
+        window_state->ClearRestoreBounds();
       } else {
         gfx::Rect new_bounds(work_area.x(), window->bounds().y(),
                              work_area.width(), window->bounds().height());
@@ -300,7 +305,7 @@
         }
 
         window_state->SetRestoreBoundsInParent(restore_bounds);
-        window->SetBounds(new_bounds);
+        window_state->SetBoundsDirectCrossFade(new_bounds);
       }
       return;
     }
diff --git a/ash/wm/resize_shadow_and_cursor_unittest.cc b/ash/wm/resize_shadow_and_cursor_unittest.cc
index 5610491f..2b086cf 100644
--- a/ash/wm/resize_shadow_and_cursor_unittest.cc
+++ b/ash/wm/resize_shadow_and_cursor_unittest.cc
@@ -12,12 +12,14 @@
 #include "ash/wm/window_state.h"
 #include "base/bind.h"
 #include "chromeos/ui/base/chromeos_ui_constants.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
 #include "ui/base/hit_test.h"
 #include "ui/compositor/layer.h"
 #include "ui/events/test/event_generator.h"
+#include "ui/views/bubble/bubble_dialog_delegate_view.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
 
@@ -181,6 +183,96 @@
   EXPECT_EQ(ui::mojom::CursorType::kNull, GetCurrentCursorType());
 }
 
+// For windows that are not resizable, checks that there is no resize shadow,
+// and for the correct cursor type for the cursor position.
+TEST_F(ResizeShadowAndCursorTest, MouseHoverOverNonresizable) {
+  ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
+  ASSERT_TRUE(WindowState::Get(window())->IsNormalStateType());
+
+  // Make the window nonresizable.
+  auto* const widget = views::Widget::GetWidgetForNativeWindow(window());
+  auto* widget_delegate = widget->widget_delegate();
+  widget_delegate->SetCanResize(false);
+
+  generator.MoveMouseTo(gfx::Point(50, 50));
+  VerifyResizeShadow(false);
+  EXPECT_EQ(ui::mojom::CursorType::kNull, GetCurrentCursorType());
+
+  generator.MoveMouseTo(gfx::Point(50, 0));
+  VerifyResizeShadow(false);
+  EXPECT_EQ(ui::mojom::CursorType::kNorthSouthNoResize, GetCurrentCursorType());
+
+  generator.MoveMouseTo(gfx::Point(50, 50));
+  VerifyResizeShadow(false);
+  EXPECT_EQ(ui::mojom::CursorType::kNull, GetCurrentCursorType());
+
+  generator.MoveMouseTo(gfx::Point(199, 99));
+  VerifyResizeShadow(false);
+  EXPECT_EQ(ui::mojom::CursorType::kNorthWestSouthEastNoResize,
+            GetCurrentCursorType());
+
+  generator.MoveMouseTo(gfx::Point(50, 99));
+  VerifyResizeShadow(false);
+  EXPECT_EQ(ui::mojom::CursorType::kNorthSouthNoResize, GetCurrentCursorType());
+
+  generator.MoveMouseTo(gfx::Point(50, 100 + kResizeOutsideBoundsSize - 1));
+  VerifyResizeShadow(false);
+  EXPECT_EQ(ui::mojom::CursorType::kNull, GetCurrentCursorType());
+
+  generator.MoveMouseTo(gfx::Point(50, 100 + kResizeOutsideBoundsSize + 10));
+  VerifyResizeShadow(false);
+  EXPECT_EQ(ui::mojom::CursorType::kNull, GetCurrentCursorType());
+
+  generator.MoveMouseTo(gfx::Point(50, 100 - kResizeInsideBoundsSize));
+  VerifyResizeShadow(false);
+  EXPECT_EQ(ui::mojom::CursorType::kNorthSouthNoResize, GetCurrentCursorType());
+
+  generator.MoveMouseTo(gfx::Point(50, 100 - kResizeInsideBoundsSize - 10));
+  VerifyResizeShadow(false);
+  EXPECT_EQ(ui::mojom::CursorType::kNull, GetCurrentCursorType());
+}
+
+TEST_F(ResizeShadowAndCursorTest, DefaultCursorOnBubbleWidgetCorners) {
+  ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
+
+  // Create a dummy view for the bubble, adding it to the window.
+  views::View* child_view = new views::View();
+  child_view->SetBounds(200, 200, 10, 10);
+  views::Widget::GetWidgetForNativeWindow(window())
+      ->GetRootView()
+      ->AddChildView(child_view);
+
+  // Create the bubble widget.
+  views::Widget* bubble(views::BubbleDialogDelegateView::CreateBubble(
+      new views::BubbleDialogDelegateView(child_view,
+                                          views::BubbleBorder::NONE)));
+  bubble->Show();
+
+  // Get the screen rectangle for the bubble frame
+  const gfx::Rect bounds = bubble->GetNativeView()->GetBoundsInScreen();
+  EXPECT_THAT(
+      bounds,
+      ::testing::AllOf(::testing::Property(&gfx::Rect::x, ::testing::Gt(0)),
+                       ::testing::Property(&gfx::Rect::y, ::testing::Gt(0))));
+
+  // The cursor at the frame corners should be the default cursor.
+  generator.MoveMouseTo(bounds.origin());
+  EXPECT_THAT(GetCurrentCursorType(),
+              ::testing::Eq(ui::mojom::CursorType::kNull));
+
+  generator.MoveMouseTo(bounds.top_right());
+  EXPECT_THAT(GetCurrentCursorType(),
+              ::testing::Eq(ui::mojom::CursorType::kNull));
+
+  generator.MoveMouseTo(bounds.bottom_left());
+  EXPECT_THAT(GetCurrentCursorType(),
+              ::testing::Eq(ui::mojom::CursorType::kNull));
+
+  generator.MoveMouseTo(bounds.bottom_right());
+  EXPECT_THAT(GetCurrentCursorType(),
+              ::testing::Eq(ui::mojom::CursorType::kNull));
+}
+
 TEST_F(ResizeShadowAndCursorTest, NoResizeShadowOnNonToplevelWindow) {
   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
   ASSERT_TRUE(WindowState::Get(window())->IsNormalStateType());
diff --git a/ash/wm/toplevel_window_event_handler.cc b/ash/wm/toplevel_window_event_handler.cc
index 426963e8..205ba62 100644
--- a/ash/wm/toplevel_window_event_handler.cc
+++ b/ash/wm/toplevel_window_event_handler.cc
@@ -68,8 +68,11 @@
   // Don't show resize shadow if
   // 1) the window is not toplevel.
   // 2) the device is in tablet mode.
+  // 3) the window is not resizable.
   if (Shell::Get()->tablet_mode_controller()->InTabletMode() ||
-      window != window->GetToplevelWindow()) {
+      window != window->GetToplevelWindow() ||
+      ((window->GetProperty(aura::client::kResizeBehaviorKey) &
+        aura::client::kResizeBehaviorCanResize) == 0)) {
     return;
   }
 
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 4a589b28..7c26f19f 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-4.20210503.1.1
+4.20210503.3.1
diff --git a/build/fuchsia/run_test_package.py b/build/fuchsia/run_test_package.py
index eb4b0e1..090bd07 100644
--- a/build/fuchsia/run_test_package.py
+++ b/build/fuchsia/run_test_package.py
@@ -259,7 +259,9 @@
                                        BuildIdsPaths(package_paths))
 
       for next_line in output_stream:
-        print(next_line.rstrip())
+        # TODO(crbug/1198733): Switch to having stream encode to utf-8 directly
+        # once we drop Python 2 support.
+        print(next_line.encode('utf-8').rstrip())
 
       process.wait()
       if process.returncode == 0:
diff --git a/chrome/VERSION b/chrome/VERSION
index 74b3fed..003a7a4 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=92
 MINOR=0
-BUILD=4497
+BUILD=4498
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index e33bca3..26f4b91a 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -308,6 +308,8 @@
     "//chrome/browser/android/crypto:java",
     "//chrome/browser/android/lifecycle:java",
     "//chrome/browser/android/webapps/launchpad:java",
+    "//chrome/browser/attribution_reporting/android:factory_java",
+    "//chrome/browser/attribution_reporting/android:java",
     "//chrome/browser/banners/android:java",
     "//chrome/browser/browser_controls/android:java",
     "//chrome/browser/commerce/merchant_viewer/android:java",
@@ -686,6 +688,7 @@
   deps = [
     ":chrome_java",
     "//chrome/android/features/keyboard_accessory:internal_java",
+    "//chrome/browser/attribution_reporting/android/internal:java",
     "//chrome/browser/commerce/merchant_viewer/android:java",
     "//chrome/browser/commerce/subscriptions/android:java",
     "//chrome/browser/download/internal/android:java",
@@ -1155,6 +1158,7 @@
     "//chrome/browser/android/metrics:ukm_javatests",
     "//chrome/browser/android/webapps/launchpad:java",
     "//chrome/browser/android/webapps/launchpad:javatests",
+    "//chrome/browser/attribution_reporting/android:java",
     "//chrome/browser/banners/android:java",
     "//chrome/browser/browser_controls/android:java",
     "//chrome/browser/commerce/merchant_viewer/android:javatests",
diff --git a/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected b/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected
index da0f67ce..d5372cbf 100644
--- a/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected
+++ b/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected
@@ -779,6 +779,10 @@
         <action android:name="android.speech.action.VOICE_SEARCH_RESULTS"/>
         <category android:name="android.intent.category.DEFAULT"/>
       </intent-filter>  # DIFF-ANCHOR: 2a3a3c3d
+      <intent-filter>  # DIFF-ANCHOR: 19f73fdc
+        <action android:name="android.web.action.APP_ATTRIBUTION"/>
+        <category android:name="android.intent.category.DEFAULT"/>
+      </intent-filter>  # DIFF-ANCHOR: 19f73fdc
       <intent-filter>  # DIFF-ANCHOR: 83919a44
         <action android:name="com.sec.android.airview.HOVER"/>
       </intent-filter>  # DIFF-ANCHOR: 83919a44
diff --git a/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected b/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected
index dc6c387..ed1cd4fd 100644
--- a/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected
+++ b/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected
@@ -752,6 +752,10 @@
         <action android:name="android.speech.action.VOICE_SEARCH_RESULTS"/>
         <category android:name="android.intent.category.DEFAULT"/>
       </intent-filter>  # DIFF-ANCHOR: 2a3a3c3d
+      <intent-filter>  # DIFF-ANCHOR: 19f73fdc
+        <action android:name="android.web.action.APP_ATTRIBUTION"/>
+        <category android:name="android.intent.category.DEFAULT"/>
+      </intent-filter>  # DIFF-ANCHOR: 19f73fdc
       <intent-filter>  # DIFF-ANCHOR: 83919a44
         <action android:name="com.sec.android.airview.HOVER"/>
       </intent-filter>  # DIFF-ANCHOR: 83919a44
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index 75896d9..ca626dbb 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -306,6 +306,10 @@
             <intent-filter>
                 <action android:name="com.sec.android.airview.HOVER" />
             </intent-filter>
+            <intent-filter>
+                <action android:name="android.web.action.APP_ATTRIBUTION" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
             <meta-data android:name="android.app.searchable"
                 android:resource="@xml/searchable" />
         </activity-alias>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index a6d4979..f5b7066 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -1755,8 +1755,10 @@
         return new TabbedAppMenuPropertiesDelegate(this, getActivityTabProvider(),
                 getMultiWindowModeStateDispatcher(), getTabModelSelector(), getToolbarManager(),
                 getWindow().getDecorView(), this, mOverviewModeBehaviorSupplier,
-                mBookmarkBridgeSupplier, getModalDialogManager(), getSnackbarManager(),
-                new WebFeedBridge());
+                mBookmarkBridgeSupplier,
+                ()
+                        -> getTabCreator(/*incognito=*/false).launchNTP(),
+                getModalDialogManager(), getSnackbarManager(), new WebFeedBridge());
     }
 
     private TabDelegateFactory getTabDelegateFactory() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
index cf66dac..8d54aaa 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
@@ -32,6 +32,8 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.browser.app.ChromeActivity;
 import org.chromium.chrome.browser.app.video_tutorials.VideoTutorialShareHelper;
+import org.chromium.chrome.browser.attribution_reporting.AttributionIntentHandler;
+import org.chromium.chrome.browser.attribution_reporting.AttributionIntentHandlerFactory;
 import org.chromium.chrome.browser.browserservices.SessionDataHolder;
 import org.chromium.chrome.browser.browserservices.ui.splashscreen.trustedwebactivity.TwaSplashController;
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
@@ -77,9 +79,10 @@
     private static final int MAX_NUM_TASKS = 100;
 
     private final Activity mActivity;
-    private final Intent mIntent;
+    private Intent mIntent;
     private final boolean mIsCustomTabIntent;
     private final boolean mIsVrIntent;
+    private final AttributionIntentHandler mAttributionIntentHandler;
 
     @IntDef({Action.CONTINUE, Action.FINISH_ACTIVITY, Action.FINISH_ACTIVITY_REMOVE_TASK})
     @Retention(RetentionPolicy.SOURCE)
@@ -130,6 +133,7 @@
     private LaunchIntentDispatcher(Activity activity, Intent intent) {
         mActivity = activity;
         mIntent = IntentUtils.sanitizeIntent(intent);
+        mAttributionIntentHandler = AttributionIntentHandlerFactory.create();
 
         // Needs to be called as early as possible, to accurately capture the
         // time at which the intent was received.
@@ -155,6 +159,10 @@
         PartnerBrowserCustomizations.getInstance().initializeAsync(
                 mActivity.getApplicationContext());
 
+        // Must come before processing other intents, as we may un-wrap |mIntent| to another type of
+        // Intent.
+        if (handleAppAttributionIntent()) return Action.FINISH_ACTIVITY;
+
         int tabId = IntentHandler.getBringTabToFrontId(mIntent);
         boolean incognito =
                 mIntent.getBooleanExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, false);
@@ -534,4 +542,12 @@
         return IntentUtils.safeGetBooleanExtra(
                 intent, TrustedWebUtils.EXTRA_LAUNCH_AS_TRUSTED_WEB_ACTIVITY, false);
     }
+
+    private boolean handleAppAttributionIntent() {
+        if (mAttributionIntentHandler.handleOuterAttributionIntent(mIntent)) return true;
+
+        Intent launchIntent = mAttributionIntentHandler.handleInnerAttributionIntent(mIntent);
+        if (launchIntent != null) mIntent = IntentUtils.sanitizeIntent(launchIntent);
+        return false;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SectionHeaderView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SectionHeaderView.java
index 2d9d36983..8526ea4a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SectionHeaderView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SectionHeaderView.java
@@ -167,7 +167,7 @@
         if (tab != null) {
             tab.getCustomView()
                     .findViewById(R.id.badge)
-                    .setVisibility(hasBadge ? View.VISIBLE : View.GONE);
+                    .setVisibility(hasBadge ? View.VISIBLE : View.INVISIBLE);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java
index 6504c951..337bad6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java
@@ -19,6 +19,7 @@
 import org.chromium.chrome.browser.feed.shared.FeedFeatures;
 import org.chromium.chrome.browser.feed.webfeed.WebFeedBridge;
 import org.chromium.chrome.browser.feed.webfeed.WebFeedMainMenuItem;
+import org.chromium.chrome.browser.feed.webfeed.WebFeedSnackbarController;
 import org.chromium.chrome.browser.flags.CachedFeatureFlags;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.multiwindow.MultiWindowModeStateDispatcher;
@@ -40,6 +41,7 @@
  */
 public class TabbedAppMenuPropertiesDelegate extends AppMenuPropertiesDelegateImpl {
     AppMenuDelegate mAppMenuDelegate;
+    WebFeedSnackbarController.FeedLauncher mFeedLauncher;
     ModalDialogManager mModalDialogManager;
     SnackbarManager mSnackbarManager;
     WebFeedBridge mWebFeedBridge;
@@ -50,11 +52,13 @@
             AppMenuDelegate appMenuDelegate,
             OneshotSupplier<OverviewModeBehavior> overviewModeBehaviorSupplier,
             ObservableSupplier<BookmarkBridge> bookmarkBridgeSupplier,
+            WebFeedSnackbarController.FeedLauncher feedLauncher,
             ModalDialogManager modalDialogManager, SnackbarManager snackbarManager,
             WebFeedBridge webFeedBridge) {
         super(context, activityTabProvider, multiWindowModeStateDispatcher, tabModelSelector,
                 toolbarManager, decorView, overviewModeBehaviorSupplier, bookmarkBridgeSupplier);
         mAppMenuDelegate = appMenuDelegate;
+        mFeedLauncher = feedLauncher;
         mModalDialogManager = modalDialogManager;
         mSnackbarManager = snackbarManager;
         mWebFeedBridge = webFeedBridge;
@@ -93,7 +97,7 @@
         if (view instanceof WebFeedMainMenuItem) {
             ((WebFeedMainMenuItem) view)
                     .initialize(mActivityTabProvider.get().getOriginalUrl(), appMenuHandler,
-                            new LargeIconBridge(Profile.getLastUsedRegularProfile()),
+                            new LargeIconBridge(Profile.getLastUsedRegularProfile()), mFeedLauncher,
                             mModalDialogManager, mSnackbarManager, mWebFeedBridge);
         }
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
index 369d458d..a8227ab 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
@@ -458,10 +458,12 @@
                 mActivity.getWindowAndroid(), mAppBannerInProductHelpController);
 
         if (FeedFeatures.isWebFeedUIEnabled()) {
-            mWebFeedFollowIntroController =
-                    new WebFeedFollowIntroController(mActivity, mTabSupplier,
-                            mToolbarManager.getMenuButtonView(), mActivity.getModalDialogManager(),
-                            mActivity.getSnackbarManager(), new WebFeedBridge());
+            mWebFeedFollowIntroController = new WebFeedFollowIntroController(mActivity,
+                    mTabSupplier, mToolbarManager.getMenuButtonView(),
+                    ()
+                            -> mActivity.getTabCreator(/*incognito=*/false).launchNTP(),
+                    mActivity.getModalDialogManager(), mActivity.getSnackbarManager(),
+                    new WebFeedBridge());
         }
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/IntentFilterUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/IntentFilterUnitTest.java
index 2a2f66b..26afff4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/IntentFilterUnitTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/IntentFilterUnitTest.java
@@ -19,6 +19,7 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.base.test.util.Batch;
+import org.chromium.chrome.browser.attribution_reporting.AttributionConstants;
 
 /**
  * Unit tests for Intent Filters in chrome/android/java/AndroidManifest.xml
@@ -196,4 +197,11 @@
         mIntent.addCategory(Intent.CATEGORY_BROWSABLE);
         verifyIntent(false);
     }
+
+    @Test
+    @SmallTest
+    public void testAttributionIntent() {
+        mIntent.setAction(AttributionConstants.ACTION_APP_ATTRIBUTION);
+        verifyIntent(true);
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java
index 5a4b356..d252a1af 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java
@@ -161,6 +161,7 @@
 
     @Test
     @SmallTest
+    @DisabledTest(message = "https://crbug.com/1205167")
     public void testCloseChromeAtHistoryStackHead() {
         loadNewTabPage();
         final Activity activity = mActivityTestRule.getActivity();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java
index 647e2c6b..04f3b580 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java
@@ -41,6 +41,7 @@
 import org.chromium.chrome.browser.enterprise.util.ManagedBrowserUtils;
 import org.chromium.chrome.browser.enterprise.util.ManagedBrowserUtilsJni;
 import org.chromium.chrome.browser.feed.webfeed.WebFeedBridge;
+import org.chromium.chrome.browser.feed.webfeed.WebFeedSnackbarController;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.multiwindow.MultiWindowModeStateDispatcher;
 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
@@ -123,6 +124,8 @@
     @Mock
     private ContentFeatureListImpl.Natives mContentFeatureListJniMock;
     @Mock
+    private WebFeedSnackbarController.FeedLauncher mFeedLauncher;
+    @Mock
     private ModalDialogManager mDialogManager;
     @Mock
     private SnackbarManager mSnackbarManager;
@@ -172,11 +175,11 @@
         OfflinePageUtils.setInstanceForTesting(mOfflinePageUtils);
         FeatureList.setTestCanUseDefaultsForTesting();
 
-        mTabbedAppMenuPropertiesDelegate = Mockito.spy(
-                new TabbedAppMenuPropertiesDelegate(ContextUtils.getApplicationContext(),
-                        mActivityTabProvider, mMultiWindowModeStateDispatcher, mTabModelSelector,
-                        mToolbarManager, mDecorView, mAppMenuDelegate, mOverviewModeSupplier,
-                        mBookmarkBridgeSupplier, mDialogManager, mSnackbarManager, mWebFeedBridge));
+        mTabbedAppMenuPropertiesDelegate = Mockito.spy(new TabbedAppMenuPropertiesDelegate(
+                ContextUtils.getApplicationContext(), mActivityTabProvider,
+                mMultiWindowModeStateDispatcher, mTabModelSelector, mToolbarManager, mDecorView,
+                mAppMenuDelegate, mOverviewModeSupplier, mBookmarkBridgeSupplier, mFeedLauncher,
+                mDialogManager, mSnackbarManager, mWebFeedBridge));
     }
 
     @Test
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h
index 80444a7d..9b6d999 100644
--- a/chrome/app/chrome_command_ids.h
+++ b/chrome/app/chrome_command_ids.h
@@ -121,6 +121,7 @@
 #define IDC_SAVE_AUTOFILL_ADDRESS       35025
 #define IDC_OFFERS_AND_REWARDS_FOR_PAGE 35026
 #define IDC_WEBAUTHN                    35027
+#define IDC_SHARING_HUB                 35028
 
 // Page-manipulation commands that target a specified tab, which may not be the
 // active one.
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index e9d4ebb..7defaa9e 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -304,7 +304,7 @@
     An error occured during activation.
   </message>
   <message name="IDS_CELLULAR_SETUP_ESIM_FINAL_PAGE_MESSAGE" desc="Message displayed under title in final success screen of eSIM cellular setup that tells user that their profile has been activated.">
-    Profile has been added successfully.
+    Profile has been added successfully. This connection will be available to all users of this device.
   </message>
   <message name="IDS_CELLULAR_SETUP_ESIM_FINAL_PAGE_ERROR_MESSAGE" desc="Message displayed under title in final screen of eSIM cellular setup when ChromeOS encountered an error installing eSIM profiles.">
     Unable to connect to a mobile network. For technical support, please contact your carrier.
diff --git a/chrome/app/chromeos_strings_grdp/IDS_CELLULAR_SETUP_ESIM_FINAL_PAGE_MESSAGE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_CELLULAR_SETUP_ESIM_FINAL_PAGE_MESSAGE.png.sha1
index 2465a0b..13a54bf 100644
--- a/chrome/app/chromeos_strings_grdp/IDS_CELLULAR_SETUP_ESIM_FINAL_PAGE_MESSAGE.png.sha1
+++ b/chrome/app/chromeos_strings_grdp/IDS_CELLULAR_SETUP_ESIM_FINAL_PAGE_MESSAGE.png.sha1
@@ -1 +1 @@
-ee5a3f9282e24d012df8db178b9a93d764d48e07
\ No newline at end of file
+442e2d96d04c94b03081fe9f1e0914cc2a12aaa3
\ No newline at end of file
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index 0172632c..bce8c45f 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -625,6 +625,9 @@
         <message name="IDS_UPDATE_NOW" desc="In Title Case: The text label of the Update Chrome Now menu item">
           Update &amp;Chromium
         </message>
+        <message name="IDS_RELAUNCH_TO_UPDATE" desc="In Title Case: The text label of the Update Chrome menu item, when relaunch to update experiment is enabled">
+          Relaunch to Update &amp;Chromium
+        </message>
       </if>
       <if expr="not use_titlecase and not chromeos">
         <message name="IDS_ABOUT" desc="The text label of the About Chrome menu item">
@@ -633,6 +636,9 @@
         <message name="IDS_UPDATE_NOW" desc="The text label of the Update Chrome Now menu item">
           Update &amp;Chromium
         </message>
+        <message name="IDS_RELAUNCH_TO_UPDATE" desc="The text label of the Update Chrome menu item, when relaunch to update experiment is enabled">
+          Relaunch to update &amp;Chromium
+        </message>
       </if>
       <if expr="chromeos">
         <message name="IDS_ABOUT" desc="The text label of the About Chrome menu item">
@@ -641,6 +647,9 @@
         <message name="IDS_UPDATE_NOW" desc="The text label of the Update Chrome OS Now menu item">
           Update &amp;Chromium OS
         </message>
+        <message name="IDS_RELAUNCH_TO_UPDATE" desc="The text label of the Update Chrome OS menu item, when relaunch to update experiment is enabled">
+          Relaunch to update &amp;Chromium OS
+        </message>
       </if>
 
       <if expr="is_macosx">
diff --git a/chrome/app/chromium_strings_grd/IDS_RELAUNCH_TO_UPDATE.png.sha1 b/chrome/app/chromium_strings_grd/IDS_RELAUNCH_TO_UPDATE.png.sha1
new file mode 100644
index 0000000..f7633e8
--- /dev/null
+++ b/chrome/app/chromium_strings_grd/IDS_RELAUNCH_TO_UPDATE.png.sha1
@@ -0,0 +1 @@
+a449eadb2c57137e5f208ebfa3cd2f636ca4b164
\ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 236fcd9..5fe7a15 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5726,17 +5726,23 @@
       <message name="IDS_NTP_MODULES_DRIVE_TITLE" desc="Title shown in the header of the drive module and various other UIs.">
         From your Google Drive
       </message>
+      <message name="IDS_NTP_MODULES_DRIVE_INFO" desc="Text shown in the body of the info dialog of the drive module.">
+        You’re seeing your recent and suggested documents based on your previous activity using Google Drive.
+        <ph name="BREAK">&lt;br&gt;</ph>
+        <ph name="BREAK">&lt;br&gt;</ph>
+        Learn about the data Google Drive collects and why <ph name="BEGIN_LINK">&lt;a href="https://support.google.com/drive/answer/2450387" target="_blank"&gt;</ph>here<ph name="END_LINK">&lt;/a&gt;</ph>.
+      </message>
       <message name="IDS_NTP_MODULES_KALEIDOSCOPE_TITLE" desc="Title shown in the header of the Kaleidoscope module.">
         Top picks for you
       </message>
       <message name="IDS_NTP_MODULES_SHOPPING_TASKS_INFO_TITLE" desc="Title shown on the info dialog of a task module.">
         Why am I seeing this?
       </message>
-      <message name="IDS_NTP_MODULES_SHOPPING_TASKS_INFO_1" desc="First paragraph shown in the body of the info dialog of a task module.">
-        You're seeing this item based on your previous activity using Google services. You can see your data, delete it, and change your settings at <ph name="BEGIN_LINK">&lt;a href="$1" target="_blank"&gt;</ph>myactivity.google.com<ph name="END_LINK">&lt;/a&gt;</ph>.
-      </message>
-      <message name="IDS_NTP_MODULES_SHOPPING_TASKS_INFO_2" desc="Second paragraph shown in the body of the info dialog of a task module.">
-        Learn about the data Google collects and why at <ph name="BEGIN_LINK">&lt;a href="$1" target="_blank"&gt;</ph>policies.google.com<ph name="END_LINK">&lt;/a&gt;</ph>.
+      <message name="IDS_NTP_MODULES_TASKS_INFO" desc="Text shown in the body of the info dialog of a task module.">
+        You're seeing this item based on your previous activity using Google services. You can see your data, delete it, and change your settings at <ph name="BEGIN_LINK">&lt;a href="https://myactivity.google.com/" target="_blank"&gt;</ph>myactivity.google.com<ph name="END_LINK">&lt;/a&gt;</ph>.
+        <ph name="BREAK">&lt;br&gt;</ph>
+        <ph name="BREAK">&lt;br&gt;</ph>
+        Learn about the data Google collects and why at <ph name="BEGIN_LINK">&lt;a href="https://policies.google.com/" target="_blank"&gt;</ph>policies.google.com<ph name="END_LINK">&lt;/a&gt;</ph>.
       </message>
       <message name="IDS_NTP_MODULES_SHOPPING_TASKS_INFO_CLOSE" desc="Text shown on close button of a task module.">
         Close
@@ -7525,6 +7531,11 @@
           Can't create QR code
       </message>
 
+      <!-- Sharing Hub feature strings. -->
+      <message name="IDS_SHARING_HUB_TITLE" desc="The title for the Sharing Hub.">
+        Share
+      </message>
+
       <!-- Clipboard History Menu feature. -->
       <message name="IDS_CONTEXT_MENU_SHOW_CLIPBOARD_HISTORY_MENU"
           desc="Show the clipboard history menu.">
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_MODULES_DRIVE_INFO.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_MODULES_DRIVE_INFO.png.sha1
new file mode 100644
index 0000000..a0fe299
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_NTP_MODULES_DRIVE_INFO.png.sha1
@@ -0,0 +1 @@
+9be1516c60e8b6fad67eb5f8e4d8548895b84c5c
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_MODULES_SHOPPING_TASKS_INFO_1.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_MODULES_SHOPPING_TASKS_INFO_1.png.sha1
deleted file mode 100644
index b706f146..0000000
--- a/chrome/app/generated_resources_grd/IDS_NTP_MODULES_SHOPPING_TASKS_INFO_1.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-17d84613543ae607815f2dafdc944ba72db70da8
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_MODULES_SHOPPING_TASKS_INFO_2.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_MODULES_SHOPPING_TASKS_INFO_2.png.sha1
deleted file mode 100644
index b706f146..0000000
--- a/chrome/app/generated_resources_grd/IDS_NTP_MODULES_SHOPPING_TASKS_INFO_2.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-17d84613543ae607815f2dafdc944ba72db70da8
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_MODULES_TASKS_INFO.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_MODULES_TASKS_INFO.png.sha1
new file mode 100644
index 0000000..b87b633
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_NTP_MODULES_TASKS_INFO.png.sha1
@@ -0,0 +1 @@
+57ad4fcc2a9146b761389089dc78e696734bdf9d
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_SHARING_HUB_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_SHARING_HUB_TITLE.png.sha1
new file mode 100644
index 0000000..ee3a3e1e
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_SHARING_HUB_TITLE.png.sha1
@@ -0,0 +1 @@
+81363aad74312e77f6fdd0339e1deb3a585fa0e0
\ No newline at end of file
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index f574502..cb0bab9 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -633,6 +633,9 @@
         <message name="IDS_UPDATE_NOW" desc="In Title Case: The text label of the Update Chrome Now menu item">
           Update &amp;Google Chrome
         </message>
+        <message name="IDS_RELAUNCH_TO_UPDATE" desc="In Title Case: The text label of the Update Chrome menu item, when relaunch to update experiment is enabled">
+          Relaunch to Update &amp;Chrome
+        </message>
       </if>
       <if expr="not use_titlecase and not chromeos">
         <message name="IDS_ABOUT" desc="The text label of the About Chrome menu item">
@@ -641,6 +644,9 @@
         <message name="IDS_UPDATE_NOW" desc="The text label of the Update Chrome Now menu item">
           Update &amp;Google Chrome
         </message>
+        <message name="IDS_RELAUNCH_TO_UPDATE" desc="The text label of the Update Chrome menu item, when relaunch to update experiment is enabled">
+          Relaunch to update &amp;Chrome
+        </message>
       </if>
       <if expr="chromeos">
         <message name="IDS_ABOUT" desc="The text label of the About Chrome menu item">
@@ -649,6 +655,9 @@
         <message name="IDS_UPDATE_NOW" desc="The text label of the Update Chrome OS Now menu item">
           Update &amp;Chrome OS
         </message>
+        <message name="IDS_RELAUNCH_TO_UPDATE" desc="The text label of the Update Chrome OS menu item, when relaunch to update experiment is enabled">
+          Relaunch to update &amp;Chrome OS
+        </message>
       </if>
 
       <if expr="is_macosx">
diff --git a/chrome/app/google_chrome_strings_grd/IDS_RELAUNCH_TO_UPDATE.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_RELAUNCH_TO_UPDATE.png.sha1
new file mode 100644
index 0000000..9d715fa
--- /dev/null
+++ b/chrome/app/google_chrome_strings_grd/IDS_RELAUNCH_TO_UPDATE.png.sha1
@@ -0,0 +1 @@
+0421a5c52da7ae8a089245edc743bd1f172e41f8
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp
index 5cbceedb..4693b44d 100644
--- a/chrome/app/os_settings_strings.grdp
+++ b/chrome/app/os_settings_strings.grdp
@@ -354,6 +354,15 @@
   <message name="IDS_OS_SETTINGS_LANGUAGES_INPUT_METHOD_LIST_TITLE" desc="Title for the list of enabled input methods (keyboard layouts and input method editors).">
     Input methods
   </message>
+  <message name="IDS_OS_SETTINGS_LANGUAGES_SHORTCUT_REMINDER_TITLE" desc="Title for the reminder to the user that some shortcuts are available for this feature.">
+    Keyboard shortcut available
+  </message>
+  <message name="IDS_OS_SETTINGS_LANGUAGES_SHORTCUT_REMINDER_LAST_USED_IME_DESCRIPTION" desc="The body of the shortcut reminder for switching to the last used input method. Note that 'Ctrl' shouldn't be translated in almost all languages.">
+    To switch to the last used input method, press <ph name="BEGIN_SHORTCUT">&lt;kbd&gt;</ph><ph name="BEGIN_CTRL">&lt;kbd&gt;</ph>Ctrl<ph name="END_CTRL">&lt;/kbd&gt;</ph><ph name="SEPARATOR">+</ph><ph name="BEGIN_SPACE">&lt;kbd&gt;</ph>Space<ph name="END_SPACE">&lt;/kbd&gt;</ph><ph name="END_SHORTCUT">&lt;/kbd&gt;</ph>
+  </message>
+  <message name="IDS_OS_SETTINGS_LANGUAGES_SHORTCUT_REMINDER_NEXT_IME_DESCRIPTION" desc="The body of the shortcut reminder for switching to the next input method. Note that 'Ctrl' shouldn't be translated in almost all languages, and 'Shift' shouldn't be translated in most languages.">
+    To switch to the next input method, press <ph name="BEGIN_SHORTCUT">&lt;kbd&gt;</ph><ph name="BEGIN_CTRL">&lt;kbd&gt;</ph>Ctrl<ph name="END_CTRL">&lt;/kbd&gt;</ph><ph name="SEPARATOR1">+</ph><ph name="BEGIN_SHIFT">&lt;kbd&gt;</ph>Shift<ph name="END_SHIFT">&lt;/kbd&gt;</ph><ph name="SEPARATOR2">+</ph><ph name="BEGIN_SPACE">&lt;kbd&gt;</ph>Space<ph name="END_SPACE">&lt;/kbd&gt;</ph><ph name="END_SHORTCUT">&lt;/kbd&gt;</ph>
+  </message>
   <message name="IDS_OS_SETTINGS_LANGUAGES_OPEN_OPTIONS_PAGE_LABEL" desc="Description read by screenreader for the button to open the settings page for a input method (keyboard layout and input method editor).">
     Open settings page for <ph name="INPUT_METHOD_NAME">$1<ex>US keyboard</ex></ph>
   </message>
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_LANGUAGES_SHORTCUT_REMINDER_LAST_USED_IME_DESCRIPTION.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_LANGUAGES_SHORTCUT_REMINDER_LAST_USED_IME_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..90b53a4
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_LANGUAGES_SHORTCUT_REMINDER_LAST_USED_IME_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+35e31d0a4aeb6eb667791d2912662cc420e9b874
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_LANGUAGES_SHORTCUT_REMINDER_NEXT_IME_DESCRIPTION.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_LANGUAGES_SHORTCUT_REMINDER_NEXT_IME_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..90b53a4
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_LANGUAGES_SHORTCUT_REMINDER_NEXT_IME_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+35e31d0a4aeb6eb667791d2912662cc420e9b874
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_LANGUAGES_SHORTCUT_REMINDER_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_LANGUAGES_SHORTCUT_REMINDER_TITLE.png.sha1
new file mode 100644
index 0000000..90b53a4
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_LANGUAGES_SHORTCUT_REMINDER_TITLE.png.sha1
@@ -0,0 +1 @@
+35e31d0a4aeb6eb667791d2912662cc420e9b874
\ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index aa07c14..48a30d4 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -1749,20 +1749,6 @@
   <message name="IDS_SETTINGS_SEARCH_ENGINES_MANAGE_EXTENSION" desc="Text displayed for a button that allows the user to manage a Chrome extension">
     Manage
   </message>
-  <!-- TODO(yoangela): These strings are placeholder strings, to be updated when these strings are finalized -->
-  <message name="IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_OPTIONS" desc="Label for scoped search mode trigger options section">
-    Keyboard shortcuts for search keywords
-  </message>
-  <message name="IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_DESCRIPTION" desc="Text explaining how to use keyword mode">
-    In the address bar, enter the keyword for the website you want to search. Then, use a keyboard shortcut to continue.
-  </message>
-  <message name="IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_SPACE_ENABLED" desc="Label for setting that toggles whether scoped search mode can be triggered by space">
-    Space or Tab
-  </message>
-  <message name="IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_SPACE_DISABLED" desc="Label for setting that toggles whether scoped search mode can be triggered by space">
-    Tab
-  </message>
-
 
   <!-- Site Settings Page -->
   <message name="IDS_SETTINGS_EXCEPTIONS_EMBEDDED_ON_HOST" desc="Template text for a child row in the content Exceptions page view. Controls the permission setting for the parent page when embedded on the specified site.">
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_DESCRIPTION.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_DESCRIPTION.png.sha1
deleted file mode 100644
index 2c5493f0..0000000
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_DESCRIPTION.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0c55720dff7d7452b6441b30c10fbbdb53d3157e
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_OPTIONS.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_OPTIONS.png.sha1
deleted file mode 100644
index 2c5493f0..0000000
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_OPTIONS.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0c55720dff7d7452b6441b30c10fbbdb53d3157e
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_SPACE_DISABLED.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_SPACE_DISABLED.png.sha1
deleted file mode 100644
index 2c5493f0..0000000
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_SPACE_DISABLED.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0c55720dff7d7452b6441b30c10fbbdb53d3157e
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_SPACE_ENABLED.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_SPACE_ENABLED.png.sha1
deleted file mode 100644
index 2c5493f0..0000000
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_SPACE_ENABLED.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0c55720dff7d7452b6441b30c10fbbdb53d3157e
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 651e476..135c0bc 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2211,7 +2211,6 @@
     "//components/site_engagement/content",
     "//components/site_engagement/core/mojom:mojo_bindings",
     "//components/site_isolation",
-    "//components/soda:constants",
     "//components/spellcheck:buildflags",
     "//components/sqlite_proto",
     "//components/ssl_errors",
@@ -3390,8 +3389,6 @@
       "accessibility/caption_host_impl.h",
       "accessibility/invert_bubble_prefs.cc",
       "accessibility/invert_bubble_prefs.h",
-      "accessibility/soda_installer.cc",
-      "accessibility/soda_installer.h",
       "apps/app_service/app_icon_factory.cc",
       "apps/app_service/app_icon_factory.h",
       "apps/app_service/app_icon_source.cc",
@@ -4215,6 +4212,7 @@
       "//components/services/app_service/public/cpp:protocol_handling",
       "//components/services/app_service/public/cpp:publisher",
       "//components/shared_highlighting/core/common",
+      "//components/soda",
       "//components/soda:constants",
       "//components/ukm/content",
       "//components/web_modal",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index cca7d06..7a336fd3 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -4347,10 +4347,6 @@
      FEATURE_WITH_PARAMS_VALUE_TYPE(omnibox::kKeywordSpaceTriggering,
                                     kOmniboxKeywordSpaceTriggeringVariations,
                                     "OmniboxBundledExperimentV1")},
-    {"omnibox-keyword-space-triggering-setting",
-     flag_descriptions::kOmniboxKeywordSpaceTriggeringSettingName,
-     flag_descriptions::kOmniboxKeywordSpaceTriggeringSettingDescription,
-     kOsDesktop, FEATURE_VALUE_TYPE(omnibox::kKeywordSpaceTriggeringSetting)},
 #endif  // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_MAC) ||
         // defined(OS_WIN)
 
@@ -7269,6 +7265,11 @@
      flag_descriptions::kLauncherQueryHighlightingName,
      flag_descriptions::kLauncherQueryHighlightingDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(app_list_features::kLauncherQueryHighlighting)},
+
+    {"enable-input-noise-cancellation-ui",
+     flag_descriptions::kEnableInputNoiseCancellationUiName,
+     flag_descriptions::kEnableInputNoiseCancellationUiDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(chromeos::features::kEnableInputNoiseCancellationUi)},
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
     {"update-history-entry-points-in-incognito",
diff --git a/chrome/browser/accessibility/caption_controller.cc b/chrome/browser/accessibility/caption_controller.cc
index da4d845..7a00397 100644
--- a/chrome/browser/accessibility/caption_controller.cc
+++ b/chrome/browser/accessibility/caption_controller.cc
@@ -11,7 +11,6 @@
 #include "base/metrics/histogram_functions.h"
 #include "chrome/browser/accessibility/caption_host_impl.h"
 #include "chrome/browser/accessibility/caption_util.h"
-#include "chrome/browser/accessibility/soda_installer.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/caption_bubble_controller.h"
@@ -20,6 +19,7 @@
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/soda/constants.h"
+#include "components/soda/soda_installer.h"
 #include "components/sync_preferences/pref_service_syncable.h"
 #include "content/public/browser/browser_accessibility_state.h"
 #include "media/base/media_switches.h"
diff --git a/chrome/browser/accessibility/caption_controller.h b/chrome/browser/accessibility/caption_controller.h
index 765c5af..0123a84 100644
--- a/chrome/browser/accessibility/caption_controller.h
+++ b/chrome/browser/accessibility/caption_controller.h
@@ -7,9 +7,9 @@
 
 #include <memory>
 
-#include "chrome/browser/accessibility/soda_installer.h"
 #include "chrome/common/caption.mojom.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/soda/soda_installer.h"
 #include "media/mojo/mojom/speech_recognition_service.mojom.h"
 #include "ui/native_theme/caption_style.h"
 #include "ui/native_theme/native_theme_observer.h"
diff --git a/chrome/browser/accessibility/soda_installer_impl.h b/chrome/browser/accessibility/soda_installer_impl.h
index b4c4f20..16006b1 100644
--- a/chrome/browser/accessibility/soda_installer_impl.h
+++ b/chrome/browser/accessibility/soda_installer_impl.h
@@ -11,8 +11,8 @@
 #include "base/files/file_path.h"
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observer.h"
-#include "chrome/browser/accessibility/soda_installer.h"
 #include "components/component_updater/component_updater_service.h"
+#include "components/soda/soda_installer.h"
 
 class PrefService;
 
diff --git a/chrome/browser/apps/app_service/app_platform_metrics.cc b/chrome/browser/apps/app_service/app_platform_metrics.cc
index 5440dfc8..cad30a41 100644
--- a/chrome/browser/apps/app_service/app_platform_metrics.cc
+++ b/chrome/browser/apps/app_service/app_platform_metrics.cc
@@ -31,10 +31,14 @@
 // UMA metrics for a snapshot count of installed apps.
 constexpr char kAppsCountHistogramPrefix[] = "Apps.AppsCount.";
 constexpr char kAppsRunningDurationHistogramPrefix[] = "Apps.RunningDuration.";
+constexpr char kAppsActivatedCountHistogramPrefix[] = "Apps.ActivatedCount.";
+constexpr char kAppsUsageTimeHistogramPrefix[] = "Apps.UsageTime.";
 
 constexpr base::TimeDelta kMinDuration = base::TimeDelta::FromSeconds(1);
 constexpr base::TimeDelta kMaxDuration = base::TimeDelta::FromDays(1);
+constexpr base::TimeDelta kMaxUsageDuration = base::TimeDelta::FromMinutes(5);
 constexpr int kDurationBuckets = 100;
+constexpr int kUsageTimeBuckets = 50;
 
 std::set<apps::AppTypeName>& GetAppTypeNameSet() {
   static base::NoDestructor<std::set<apps::AppTypeName>> app_type_name_map;
@@ -256,6 +260,8 @@
 
 constexpr char kAppRunningDuration[] =
     "app_platform_metrics.app_running_duration";
+constexpr char kAppActivatedCount[] =
+    "app_platform_metrics.app_activated_count";
 
 constexpr char kArcHistogramName[] = "Arc";
 constexpr char kBuiltInHistogramName[] = "BuiltIn";
@@ -340,6 +346,7 @@
   }
 
   OnTenMinutes();
+  RecordAppsUsageTime();
 }
 
 // static
@@ -355,6 +362,18 @@
          GetAppTypeHistogramName(app_type_name);
 }
 
+// static
+std::string AppPlatformMetrics::GetAppsActivatedCountHistogramNameForTest(
+    AppTypeName app_type_name) {
+  return kAppsActivatedCountHistogramPrefix +
+         GetAppTypeHistogramName(app_type_name);
+}
+
+std::string AppPlatformMetrics::GetAppsUsageTimeHistogramNameForTest(
+    AppTypeName app_type_name) {
+  return kAppsUsageTimeHistogramPrefix + GetAppTypeHistogramName(app_type_name);
+}
+
 void AppPlatformMetrics::OnNewDay() {
   // Ignores the first report. Apps and extensions may sync slowly after the
   // OOBE process, biasing the metrics downwards toward zero.
@@ -369,17 +388,34 @@
 }
 
 void AppPlatformMetrics::OnTenMinutes() {
+  if (should_refresh_activated_count_pref) {
+    should_refresh_activated_count_pref = false;
+    DictionaryPrefUpdate activated_count_update(profile_->GetPrefs(),
+                                                kAppActivatedCount);
+    for (auto it : activated_count_) {
+      std::string app_type_name = GetAppTypeHistogramName(it.first);
+      DCHECK(!app_type_name.empty());
+      activated_count_update->SetIntKey(app_type_name, it.second);
+    }
+  }
+
   if (should_refresh_duration_pref) {
     should_refresh_duration_pref = false;
-    DictionaryPrefUpdate update(profile_->GetPrefs(), kAppRunningDuration);
+    DictionaryPrefUpdate running_duration_update(profile_->GetPrefs(),
+                                                 kAppRunningDuration);
     for (auto it : running_duration_) {
       std::string app_type_name = GetAppTypeHistogramName(it.first);
       DCHECK(!app_type_name.empty());
-      update->SetPath(app_type_name, util::TimeDeltaToValue(it.second));
+      running_duration_update->SetPath(app_type_name,
+                                       util::TimeDeltaToValue(it.second));
     }
   }
 }
 
+void AppPlatformMetrics::OnFiveMinutes() {
+  RecordAppsUsageTime();
+}
+
 void AppPlatformMetrics::OnAppTypeInitialized(apps::mojom::AppType app_type) {
   if (should_record_metrics_on_new_day_) {
     RecordAppsCount(app_type);
@@ -424,6 +460,14 @@
 
       running_start_time_[update.Window()].start_time = base::TimeTicks::Now();
       running_start_time_[update.Window()].app_type_name = app_type_name;
+
+      ++activated_count_[app_type_name];
+      should_refresh_activated_count_pref = true;
+
+      start_time_per_five_minutes_[update.Window()].start_time =
+          base::TimeTicks::Now();
+      start_time_per_five_minutes_[update.Window()].app_type_name =
+          app_type_name;
     }
     return;
   }
@@ -437,6 +481,12 @@
   running_duration_[app_type_name] +=
       base::TimeTicks::Now() - it->second.start_time;
   running_start_time_.erase(it);
+
+  running_time_per_five_minutes_[app_type_name] +=
+      base::TimeTicks::Now() -
+      start_time_per_five_minutes_[update.Window()].start_time;
+  start_time_per_five_minutes_.erase(update.Window());
+
   should_refresh_duration_pref = true;
 }
 
@@ -446,7 +496,11 @@
 }
 
 void AppPlatformMetrics::InitRunningDuration() {
-  DictionaryPrefUpdate update(profile_->GetPrefs(), kAppRunningDuration);
+  DictionaryPrefUpdate running_duration_update(profile_->GetPrefs(),
+                                               kAppRunningDuration);
+  DictionaryPrefUpdate activated_count_update(profile_->GetPrefs(),
+                                              kAppActivatedCount);
+
   for (auto app_type_name : GetAppTypeNameSet()) {
     std::string key = GetAppTypeHistogramName(app_type_name);
     if (key.empty()) {
@@ -454,19 +508,28 @@
     }
 
     base::Optional<base::TimeDelta> unreported_duration =
-        util::ValueToTimeDelta(update->FindPath(key));
-    if (!unreported_duration.has_value()) {
-      continue;
+        util::ValueToTimeDelta(running_duration_update->FindPath(key));
+    if (unreported_duration.has_value()) {
+      running_duration_[app_type_name] = unreported_duration.value();
     }
 
-    running_duration_[app_type_name] = unreported_duration.value();
+    base::Optional<int> count = activated_count_update->FindIntPath(key);
+    if (count.has_value()) {
+      activated_count_[app_type_name] = count.value();
+    }
   }
 }
 
 void AppPlatformMetrics::ClearRunningDuration() {
   running_duration_.clear();
-  DictionaryPrefUpdate update(profile_->GetPrefs(), kAppRunningDuration);
-  update->Clear();
+  activated_count_.clear();
+
+  DictionaryPrefUpdate running_duration_update(profile_->GetPrefs(),
+                                               kAppRunningDuration);
+  running_duration_update->Clear();
+  DictionaryPrefUpdate activated_count_update(profile_->GetPrefs(),
+                                              kAppActivatedCount);
+  activated_count_update->Clear();
 }
 
 void AppPlatformMetrics::RecordAppsCount(apps::mojom::AppType app_type) {
@@ -516,7 +579,29 @@
         kAppsRunningDurationHistogramPrefix + GetAppTypeHistogramName(it.first),
         it.second, kMinDuration, kMaxDuration, kDurationBuckets);
   }
+
+  for (auto it : activated_count_) {
+    base::UmaHistogramCounts10000(
+        kAppsActivatedCountHistogramPrefix + GetAppTypeHistogramName(it.first),
+        it.second);
+  }
+
   ClearRunningDuration();
 }
 
+void AppPlatformMetrics::RecordAppsUsageTime() {
+  for (auto& it : start_time_per_five_minutes_) {
+    running_time_per_five_minutes_[it.second.app_type_name] +=
+        base::TimeTicks::Now() - it.second.start_time;
+    it.second.start_time = base::TimeTicks::Now();
+  }
+
+  for (auto it : running_time_per_five_minutes_) {
+    base::UmaHistogramCustomTimes(
+        kAppsUsageTimeHistogramPrefix + GetAppTypeHistogramName(it.first),
+        it.second, kMinDuration, kMaxUsageDuration, kUsageTimeBuckets);
+  }
+  running_time_per_five_minutes_.clear();
+}
+
 }  // namespace apps
diff --git a/chrome/browser/apps/app_service/app_platform_metrics.h b/chrome/browser/apps/app_service/app_platform_metrics.h
index 7d676e6..85cdc1c 100644
--- a/chrome/browser/apps/app_service/app_platform_metrics.h
+++ b/chrome/browser/apps/app_service/app_platform_metrics.h
@@ -43,6 +43,7 @@
 };
 
 extern const char kAppRunningDuration[];
+extern const char kAppActivatedCount[];
 
 extern const char kArcHistogramName[];
 extern const char kBuiltInHistogramName[];
@@ -85,8 +86,17 @@
   static std::string GetAppsRunningDurationHistogramNameForTest(
       AppTypeName app_type_name);
 
+  // UMA metrics name for app window activated count in Chrome OS.
+  static std::string GetAppsActivatedCountHistogramNameForTest(
+      AppTypeName app_type_name);
+
+  // UMA metrics name for apps usage time in Chrome OS.
+  static std::string GetAppsUsageTimeHistogramNameForTest(
+      AppTypeName app_type_name);
+
   void OnNewDay();
   void OnTenMinutes();
+  void OnFiveMinutes();
 
  private:
   struct RunningStartTime {
@@ -115,16 +125,29 @@
   // Records the app running duration.
   void RecordAppsRunningDuration();
 
+  // Records the app usage time in five minutes.
+  void RecordAppsUsageTime();
+
   Profile* const profile_ = nullptr;
 
   AppRegistryCache& app_registry_cache_;
 
   bool should_record_metrics_on_new_day_ = false;
   bool first_report_on_current_device_ = false;
-  bool should_refresh_duration_pref = false;
 
+  bool should_refresh_duration_pref = false;
+  bool should_refresh_activated_count_pref = false;
+
+  // |running_start_time_| and |running_duration_| are used for accumulating app
+  // running duration per each day interval.
   std::map<aura::Window*, RunningStartTime> running_start_time_;
   std::map<AppTypeName, base::TimeDelta> running_duration_;
+  std::map<AppTypeName, int> activated_count_;
+
+  // |start_time_per_five_minutes_| and |running_time_per_five_minutes_| are
+  // used for accumulating app running duration per 5 minutes interval.
+  std::map<aura::Window*, RunningStartTime> start_time_per_five_minutes_;
+  std::map<AppTypeName, base::TimeDelta> running_time_per_five_minutes_;
 };
 
 }  // namespace apps
diff --git a/chrome/browser/apps/app_service/app_platform_metrics_service.cc b/chrome/browser/apps/app_service/app_platform_metrics_service.cc
index ff22aa78..742d42aa 100644
--- a/chrome/browser/apps/app_service/app_platform_metrics_service.cc
+++ b/chrome/browser/apps/app_service/app_platform_metrics_service.cc
@@ -15,6 +15,7 @@
 namespace {
 
 constexpr base::TimeDelta kTimerInterval = base::TimeDelta::FromMinutes(10);
+constexpr base::TimeDelta kFiveMinutes = base::TimeDelta::FromMinutes(5);
 
 // Returns the number of days since the origin.
 int GetDayId(base::Time time) {
@@ -39,6 +40,7 @@
     PrefRegistrySimple* registry) {
   registry->RegisterIntegerPref(kAppPlatformMetricsDayId, 0);
   registry->RegisterDictionaryPref(kAppRunningDuration);
+  registry->RegisterDictionaryPref(kAppActivatedCount);
 }
 
 // static
@@ -58,6 +60,10 @@
   // Check for a new day every |kTimerInterval| as well.
   timer_.Start(FROM_HERE, kTimerInterval, this,
                &AppPlatformMetricsService::CheckForNewDay);
+
+  // Check every |kFiveMinutes|.
+  five_minutes_timer_.Start(FROM_HERE, kFiveMinutes, this,
+                            &AppPlatformMetricsService::CheckForFiveMinutes);
 }
 
 void AppPlatformMetricsService::CheckForNewDay() {
@@ -73,4 +79,8 @@
   }
 }
 
+void AppPlatformMetricsService::CheckForFiveMinutes() {
+  app_platform_app_metrics_->OnFiveMinutes();
+}
+
 }  // namespace apps
diff --git a/chrome/browser/apps/app_service/app_platform_metrics_service.h b/chrome/browser/apps/app_service/app_platform_metrics_service.h
index 89755fd8..c7c68716 100644
--- a/chrome/browser/apps/app_service/app_platform_metrics_service.h
+++ b/chrome/browser/apps/app_service/app_platform_metrics_service.h
@@ -43,6 +43,9 @@
   // Helper function to check if a new day has arrived.
   void CheckForNewDay();
 
+  // Helper function to check if 5 mintues have arrived.
+  void CheckForFiveMinutes();
+
   Profile* const profile_;
 
   int day_id_;
@@ -50,6 +53,9 @@
   // A periodic timer that checks if a new day has arrived.
   base::RepeatingTimer timer_;
 
+  // A periodic timer that checks if five minutes have arrived.
+  base::RepeatingTimer five_minutes_timer_;
+
   std::unique_ptr<AppPlatformMetrics> app_platform_app_metrics_;
 };
 
diff --git a/chrome/browser/apps/app_service/app_platform_metrics_service_unittest.cc b/chrome/browser/apps/app_service/app_platform_metrics_service_unittest.cc
index 218e4f4..17ab5ba 100644
--- a/chrome/browser/apps/app_service/app_platform_metrics_service_unittest.cc
+++ b/chrome/browser/apps/app_service/app_platform_metrics_service_unittest.cc
@@ -250,6 +250,52 @@
         time_delta, count);
   }
 
+  void VerifyAppActivatedCount(int count, AppTypeName app_type_name) {
+    DictionaryPrefUpdate update(GetPrefService(), kAppActivatedCount);
+    std::string key = GetAppTypeHistogramName(app_type_name);
+
+    base::Optional<int> activated_count = update->FindIntPath(key);
+    if (count == 0) {
+      EXPECT_FALSE(activated_count.has_value());
+      return;
+    }
+
+    ASSERT_TRUE(activated_count.has_value());
+    EXPECT_EQ(count, activated_count.value());
+  }
+
+  void VerifyAppActivatedCountHistogram(base::HistogramBase::Count count,
+                                        AppTypeName app_type_name) {
+    histogram_tester().ExpectTotalCount(
+        AppPlatformMetrics::GetAppsActivatedCountHistogramNameForTest(
+            app_type_name),
+        count);
+  }
+
+  void VerifyAppActivatedHistogram(int count,
+                                   base::HistogramBase::Count expected_count,
+                                   AppTypeName app_type_name) {
+    histogram_tester().ExpectBucketCount(
+        AppPlatformMetrics::GetAppsActivatedCountHistogramNameForTest(
+            app_type_name),
+        count, expected_count);
+  }
+
+  void VerifyAppUsageTimeCountHistogram(base::HistogramBase::Count count,
+                                        AppTypeName app_type_name) {
+    histogram_tester_.ExpectTotalCount(
+        AppPlatformMetrics::GetAppsUsageTimeHistogramNameForTest(app_type_name),
+        count);
+  }
+
+  void VerifyAppUsageTimeHistogram(base::TimeDelta time_delta,
+                                   base::HistogramBase::Count count,
+                                   AppTypeName app_type_name) {
+    histogram_tester().ExpectTimeBucketCount(
+        AppPlatformMetrics::GetAppsUsageTimeHistogramNameForTest(app_type_name),
+        time_delta, count);
+  }
+
  protected:
   sync_preferences::TestingPrefServiceSyncable* GetPrefService() {
     return testing_profile_.GetTestingPrefService();
@@ -337,8 +383,10 @@
   // Set the browser window active.
   ModifyInstance(extension_misc::kChromeAppId,
                  browser1->window()->GetNativeWindow(), kActiveInstanceState);
+  task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(10));
+  VerifyAppActivatedCount(/*expected_count=*/1, AppTypeName::kChromeBrowser);
 
-  task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(30));
+  task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(20));
   // Set the browser window running in the background.
   ModifyInstance(extension_misc::kChromeAppId,
                  browser1->window()->GetNativeWindow(), kInactiveInstanceState);
@@ -353,8 +401,10 @@
 
   ModifyInstance(extension_misc::kChromeAppId,
                  browser2->window()->GetNativeWindow(), kActiveInstanceState);
+  task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(10));
+  VerifyAppActivatedCount(/*expected_count=*/2, AppTypeName::kChromeBrowser);
 
-  task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(30));
+  task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(20));
   ModifyInstance(extension_misc::kChromeAppId,
                  browser2->window()->GetNativeWindow(),
                  apps::InstanceState::kDestroyed);
@@ -370,6 +420,10 @@
   VerifyAppRunningDurationHistogram(base::TimeDelta::FromHours(1),
                                     /*expected_count=*/1,
                                     AppTypeName::kChromeBrowser);
+  VerifyAppActivatedCountHistogram(/*expected_count=*/1,
+                                   AppTypeName::kChromeBrowser);
+  VerifyAppActivatedHistogram(/*count*/ 2, /*expected_count=*/1,
+                              AppTypeName::kChromeBrowser);
 }
 
 // Tests the UMA metrics when launching an app in one day .
@@ -382,8 +436,11 @@
   window->Init(ui::LAYER_NOT_DRAWN);
   ModifyInstance(app_id, window.get(), apps::InstanceState::kActive);
 
+  task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(10));
+  VerifyAppActivatedCount(/*expected_count=*/1, AppTypeName::kArc);
+
   // Close the window after running one hour.
-  task_environment_.FastForwardBy(base::TimeDelta::FromHours(1));
+  task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(50));
   ModifyInstance(app_id, window.get(), apps::InstanceState::kDestroyed);
 
   task_environment_.FastForwardBy(base::TimeDelta::FromHours(1));
@@ -396,7 +453,11 @@
                                          AppTypeName::kArc);
   VerifyAppRunningDurationHistogram(base::TimeDelta::FromHours(1),
                                     /*expected_count=*/1, AppTypeName::kArc);
+  VerifyAppActivatedCountHistogram(/*expected_count=*/1, AppTypeName::kArc);
+  VerifyAppActivatedHistogram(/*count*/ 1, /*expected_count=*/1,
+                              AppTypeName::kArc);
   VerifyAppRunningDuration(base::TimeDelta(), AppTypeName::kArc);
+  VerifyAppActivatedCount(/*expected_count=*/0, AppTypeName::kArc);
 
   // One more day passes.
   task_environment_.FastForwardBy(base::TimeDelta::FromDays(1));
@@ -404,6 +465,7 @@
                                          AppTypeName::kArc);
   VerifyAppRunningDurationHistogram(base::TimeDelta::FromHours(1),
                                     /*expected_count=*/1, AppTypeName::kArc);
+  VerifyAppActivatedCountHistogram(/*expected_count=*/1, AppTypeName::kArc);
 }
 
 // Tests the UMA metrics when launching an app multiple days.
@@ -416,10 +478,16 @@
   window->Init(ui::LAYER_NOT_DRAWN);
   ModifyInstance(app_id, window.get(), apps::InstanceState::kActive);
 
+  task_environment_.FastForwardBy(base::TimeDelta::FromHours(1));
+  VerifyAppActivatedCount(/*expected_count=*/1, AppTypeName::kArc);
+
   // One day passes.
-  task_environment_.FastForwardBy(base::TimeDelta::FromHours(3));
+  task_environment_.FastForwardBy(base::TimeDelta::FromHours(2));
   VerifyAppRunningDurationCountHistogram(/*expected_count=*/1,
                                          AppTypeName::kArc);
+  VerifyAppActivatedCountHistogram(/*expected_count=*/1, AppTypeName::kArc);
+  VerifyAppActivatedHistogram(/*count*/ 1, /*expected_count=*/1,
+                              AppTypeName::kArc);
 
   task_environment_.FastForwardBy(base::TimeDelta::FromHours(2));
 
@@ -441,7 +509,9 @@
                                     /*expected_count=*/1, AppTypeName::kArc);
   VerifyAppRunningDurationHistogram(base::TimeDelta::FromHours(2),
                                     /*expected_count=*/1, AppTypeName::kArc);
+  VerifyAppActivatedCountHistogram(/*expected_count=*/1, AppTypeName::kArc);
   VerifyAppRunningDuration(base::TimeDelta::FromHours(0), AppTypeName::kArc);
+  VerifyAppActivatedCount(/*expected_count=*/0, AppTypeName::kArc);
 }
 
 // Tests the UMA metrics when an app window is reactivated.
@@ -455,6 +525,7 @@
   ModifyInstance(app_id, window.get(), apps::InstanceState::kActive);
   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(30));
   ModifyInstance(app_id, window.get(), kActiveInstanceState);
+  VerifyAppActivatedCount(/*expected_count=*/1, AppTypeName::kArc);
 
   // Inactiva the window after running one hour.
   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(30));
@@ -463,9 +534,11 @@
   // Activa the window after running one hour.
   task_environment_.FastForwardBy(base::TimeDelta::FromHours(1));
   ModifyInstance(app_id, window.get(), kActiveInstanceState);
+  task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(10));
+  VerifyAppActivatedCount(/*expected_count=*/2, AppTypeName::kArc);
 
   // Close the window after running half hour.
-  task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(30));
+  task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(20));
   ModifyInstance(app_id, window.get(), apps::InstanceState::kDestroyed);
 
   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(10));
@@ -480,6 +553,9 @@
   VerifyAppRunningDurationHistogram(
       base::TimeDelta::FromHours(1) + base::TimeDelta::FromMinutes(30),
       /*expected_count=*/1, AppTypeName::kArc);
+  VerifyAppActivatedCountHistogram(/*expected_count=*/1, AppTypeName::kArc);
+  VerifyAppActivatedHistogram(/*count*/ 2, /*expected_count=*/1,
+                              AppTypeName::kArc);
 
   // 20 hours passes.
   task_environment_.FastForwardBy(base::TimeDelta::FromHours(20));
@@ -489,20 +565,29 @@
   window->Init(ui::LAYER_NOT_DRAWN);
   ModifyInstance(app_id, window.get(), kActiveInstanceState);
 
+  task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(10));
+  VerifyAppActivatedCount(/*expected_count=*/1, AppTypeName::kArc);
+
   // Inactiva the window after running one hour.
-  task_environment_.FastForwardBy(base::TimeDelta::FromHours(1));
+  task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(50));
   ModifyInstance(app_id, window.get(), kInactiveInstanceState);
 
   // Activa the window after running one hour.
   task_environment_.FastForwardBy(base::TimeDelta::FromHours(1));
   ModifyInstance(app_id, window.get(), kActiveInstanceState);
 
+  task_environment_.FastForwardBy(base::TimeDelta::FromHours(1));
+  VerifyAppActivatedCount(/*expected_count=*/2, AppTypeName::kArc);
+
   // One more day passes.
-  task_environment_.FastForwardBy(base::TimeDelta::FromHours(2));
+  task_environment_.FastForwardBy(base::TimeDelta::FromHours(1));
   VerifyAppRunningDurationCountHistogram(/*expected_count=*/2,
                                          AppTypeName::kArc);
   VerifyAppRunningDurationHistogram(base::TimeDelta::FromHours(3),
                                     /*expected_count=*/1, AppTypeName::kArc);
+  VerifyAppActivatedCountHistogram(/*expected_count=*/2, AppTypeName::kArc);
+  VerifyAppActivatedHistogram(/*count*/ 2, /*expected_count=*/2,
+                              AppTypeName::kArc);
 
   // Inactiva the window after running one hour.
   task_environment_.FastForwardBy(base::TimeDelta::FromHours(3));
@@ -521,7 +606,53 @@
                                          AppTypeName::kArc);
   VerifyAppRunningDurationHistogram(base::TimeDelta::FromHours(3),
                                     /*expected_count=*/2, AppTypeName::kArc);
+  VerifyAppActivatedCountHistogram(/*expected_count=*/2, AppTypeName::kArc);
   VerifyAppRunningDuration(base::TimeDelta::FromHours(0), AppTypeName::kArc);
+  VerifyAppActivatedCount(/*expected_count=*/0, AppTypeName::kArc);
+}
+
+TEST_F(AppPlatformMetricsServiceTest, UsageTime) {
+  // Create an ARC app window.
+  std::string app_id = "aa";
+  InstallOneApp(app_id, apps::mojom::AppType::kArc);
+  auto window = std::make_unique<aura::Window>(nullptr);
+  window->Init(ui::LAYER_NOT_DRAWN);
+  ModifyInstance(app_id, window.get(), apps::InstanceState::kActive);
+
+  task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(5));
+  VerifyAppUsageTimeCountHistogram(/*expected_count=*/1, AppTypeName::kArc);
+  VerifyAppUsageTimeHistogram(base::TimeDelta::FromMinutes(5),
+                              /*expected_count=*/1, AppTypeName::kArc);
+
+  task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(2));
+  ModifyInstance(app_id, window.get(), kInactiveInstanceState);
+
+  // Create a browser window
+  InstallOneApp(extension_misc::kChromeAppId, apps::mojom::AppType::kExtension);
+  std::unique_ptr<Browser> browser = CreateBrowserWithAuraWindow1();
+  EXPECT_EQ(1U, BrowserList::GetInstance()->size());
+
+  // Set the browser window active.
+  ModifyInstance(extension_misc::kChromeAppId,
+                 browser->window()->GetNativeWindow(), kActiveInstanceState);
+
+  task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(3));
+  VerifyAppUsageTimeCountHistogram(/*expected_count=*/2, AppTypeName::kArc);
+  VerifyAppUsageTimeHistogram(base::TimeDelta::FromMinutes(2),
+                              /*expected_count=*/1, AppTypeName::kArc);
+  VerifyAppUsageTimeCountHistogram(/*expected_count=*/1,
+                                   AppTypeName::kChromeBrowser);
+  VerifyAppUsageTimeHistogram(base::TimeDelta::FromMinutes(3),
+                              /*expected_count=*/1,
+                              AppTypeName::kChromeBrowser);
+
+  task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(15));
+  VerifyAppUsageTimeCountHistogram(/*expected_count=*/2, AppTypeName::kArc);
+  VerifyAppUsageTimeCountHistogram(/*expected_count=*/4,
+                                   AppTypeName::kChromeBrowser);
+  VerifyAppUsageTimeHistogram(base::TimeDelta::FromMinutes(5),
+                              /*expected_count=*/3,
+                              AppTypeName::kChromeBrowser);
 }
 
 }  // namespace apps
diff --git a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
index bc5a607..bd71e98f 100644
--- a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
+++ b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
@@ -733,8 +733,8 @@
   result_dictionary->Set(kAttachedImagesBlobInfoKey,
                          std::make_unique<base::ListValue>());
   metadata::AttachedImage* first_image = &attached_images->front();
-  content::BrowserContext::CreateMemoryBackedBlob(
-      browser_context(), base::as_bytes(base::make_span(first_image->data)), "",
+  browser_context()->CreateMemoryBackedBlob(
+      base::as_bytes(base::make_span(first_image->data)), "",
       base::BindOnce(&MediaGalleriesGetMetadataFunction::ConstructNextBlob,
                      this, std::move(result_dictionary),
                      std::move(attached_images),
@@ -788,9 +788,8 @@
   if (blob_uuids->size() < attached_images->size()) {
     metadata::AttachedImage* next_image =
         &(*attached_images)[blob_uuids->size()];
-    content::BrowserContext::CreateMemoryBackedBlob(
-        browser_context(), base::as_bytes(base::make_span(next_image->data)),
-        "",
+    browser_context()->CreateMemoryBackedBlob(
+        base::as_bytes(base::make_span(next_image->data)), "",
         base::BindOnce(&MediaGalleriesGetMetadataFunction::ConstructNextBlob,
                        this, std::move(result_dictionary),
                        std::move(attached_images), std::move(blob_uuids)));
diff --git a/chrome/browser/ash/accessibility/accessibility_manager.cc b/chrome/browser/ash/accessibility/accessibility_manager.cc
index 0f3cf0956..57c5d232 100644
--- a/chrome/browser/ash/accessibility/accessibility_manager.cc
+++ b/chrome/browser/ash/accessibility/accessibility_manager.cc
@@ -38,7 +38,6 @@
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
 #include "chrome/browser/accessibility/accessibility_extension_api.h"
-#include "chrome/browser/accessibility/soda_installer.h"
 #include "chrome/browser/ash/accessibility/accessibility_extension_loader.h"
 #include "chrome/browser/ash/accessibility/dictation.h"
 #include "chrome/browser/ash/accessibility/magnification_manager.h"
@@ -66,6 +65,7 @@
 #include "components/language/core/browser/pref_names.h"
 #include "components/prefs/pref_member.h"
 #include "components/prefs/pref_service.h"
+#include "components/soda/soda_installer.h"
 #include "components/user_manager/known_user.h"
 #include "content/public/browser/browser_accessibility_state.h"
 #include "content/public/browser/browser_task_traits.h"
diff --git a/chrome/browser/ash/accessibility/dictation_browsertest.cc b/chrome/browser/ash/accessibility/dictation_browsertest.cc
index 43824145..e3d2e69b 100644
--- a/chrome/browser/ash/accessibility/dictation_browsertest.cc
+++ b/chrome/browser/ash/accessibility/dictation_browsertest.cc
@@ -9,13 +9,13 @@
 #include "base/optional.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/timer/timer.h"
-#include "chrome/browser/accessibility/soda_installer.h"
 #include "chrome/browser/ash/accessibility/accessibility_manager.h"
 #include "chrome/browser/ash/accessibility/soda_installer_impl_chromeos.h"
 #include "chrome/browser/speech/cros_speech_recognition_service_factory.h"
 #include "chrome/browser/speech/fake_speech_recognition_service.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "components/soda/soda_installer.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/fake_speech_recognition_manager.h"
 #include "media/mojo/mojom/speech_recognition_service.mojom.h"
diff --git a/chrome/browser/ash/accessibility/soda_installer_impl_chromeos.h b/chrome/browser/ash/accessibility/soda_installer_impl_chromeos.h
index b73d07b..eaf65a5 100644
--- a/chrome/browser/ash/accessibility/soda_installer_impl_chromeos.h
+++ b/chrome/browser/ash/accessibility/soda_installer_impl_chromeos.h
@@ -6,8 +6,8 @@
 #define CHROME_BROWSER_ASH_ACCESSIBILITY_SODA_INSTALLER_IMPL_CHROMEOS_H_
 
 #include "base/files/file_path.h"
-#include "chrome/browser/accessibility/soda_installer.h"
 #include "chromeos/dbus/dlcservice/dlcservice_client.h"
+#include "components/soda/soda_installer.h"
 
 class PrefService;
 class OnDeviceSpeechRecognizerTest;
diff --git a/chrome/browser/ash/crosapi/browser_util.cc b/chrome/browser/ash/crosapi/browser_util.cc
index 24d7339..4a1ba17e 100644
--- a/chrome/browser/ash/crosapi/browser_util.cc
+++ b/chrome/browser/ash/crosapi/browser_util.cc
@@ -199,6 +199,7 @@
     MakeInterfaceVersionEntry<crosapi::mojom::Prefs>(),
     MakeInterfaceVersionEntry<crosapi::mojom::ScreenManager>(),
     MakeInterfaceVersionEntry<crosapi::mojom::SnapshotCapturer>(),
+    MakeInterfaceVersionEntry<crosapi::mojom::SystemDisplay>(),
     MakeInterfaceVersionEntry<crosapi::mojom::TaskManager>(),
     MakeInterfaceVersionEntry<crosapi::mojom::TestController>(),
     MakeInterfaceVersionEntry<crosapi::mojom::UrlHandler>(),
@@ -224,7 +225,7 @@
 }
 
 static_assert(
-    crosapi::mojom::Crosapi::Version_ == 23,
+    crosapi::mojom::Crosapi::Version_ == 24,
     "if you add a new crosapi, please add it to the version map here");
 static_assert(!HasDuplicatedUuid(),
               "Each Crosapi Mojom interface should have unique UUID.");
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.cc b/chrome/browser/ash/crosapi/crosapi_ash.cc
index bb606d29..046c100 100644
--- a/chrome/browser/ash/crosapi/crosapi_ash.cc
+++ b/chrome/browser/ash/crosapi/crosapi_ash.cc
@@ -29,6 +29,7 @@
 #include "chrome/browser/ash/crosapi/prefs_ash.h"
 #include "chrome/browser/ash/crosapi/screen_manager_ash.h"
 #include "chrome/browser/ash/crosapi/select_file_ash.h"
+#include "chrome/browser/ash/crosapi/system_display_ash.h"
 #include "chrome/browser/ash/crosapi/task_manager_ash.h"
 #include "chrome/browser/ash/crosapi/test_controller_ash.h"
 #include "chrome/browser/ash/crosapi/url_handler_ash.h"
@@ -73,6 +74,7 @@
                                      g_browser_process->local_state())),
       screen_manager_ash_(std::make_unique<ScreenManagerAsh>()),
       select_file_ash_(std::make_unique<SelectFileAsh>()),
+      system_display_ash_(std::make_unique<SystemDisplayAsh>()),
       task_manager_ash_(std::make_unique<TaskManagerAsh>()),
       test_controller_ash_(std::make_unique<TestControllerAsh>()),
       url_handler_ash_(std::make_unique<UrlHandlerAsh>()),
@@ -211,6 +213,11 @@
   cert_database_ash_->BindReceiver(std::move(receiver));
 }
 
+void CrosapiAsh::BindSystemDisplay(
+    mojo::PendingReceiver<mojom::SystemDisplay> receiver) {
+  system_display_ash_->BindReceiver(std::move(receiver));
+}
+
 void CrosapiAsh::BindTaskManager(
     mojo::PendingReceiver<mojom::TaskManager> receiver) {
   task_manager_ash_->BindReceiver(std::move(receiver));
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.h b/chrome/browser/ash/crosapi/crosapi_ash.h
index 789a8de..3ca5228 100644
--- a/chrome/browser/ash/crosapi/crosapi_ash.h
+++ b/chrome/browser/ash/crosapi/crosapi_ash.h
@@ -33,6 +33,7 @@
 class PrefsAsh;
 class ScreenManagerAsh;
 class SelectFileAsh;
+class SystemDisplayAsh;
 class TaskManagerAsh;
 class TestControllerAsh;
 class UrlHandlerAsh;
@@ -98,6 +99,8 @@
   void BindMediaSessionAudioFocusDebug(
       mojo::PendingReceiver<media_session::mojom::AudioFocusManagerDebug>
           receiver) override;
+  void BindSystemDisplay(
+      mojo::PendingReceiver<mojom::SystemDisplay> receiver) override;
   void BindTaskManager(
       mojo::PendingReceiver<mojom::TaskManager> receiver) override;
   void BindTestController(
@@ -141,6 +144,7 @@
   std::unique_ptr<PrefsAsh> prefs_ash_;
   std::unique_ptr<ScreenManagerAsh> screen_manager_ash_;
   std::unique_ptr<SelectFileAsh> select_file_ash_;
+  std::unique_ptr<SystemDisplayAsh> system_display_ash_;
   std::unique_ptr<TaskManagerAsh> task_manager_ash_;
   std::unique_ptr<TestControllerAsh> test_controller_ash_;
   std::unique_ptr<UrlHandlerAsh> url_handler_ash_;
diff --git a/chrome/browser/ash/crosapi/system_display_ash.cc b/chrome/browser/ash/crosapi/system_display_ash.cc
new file mode 100644
index 0000000..06b0519
--- /dev/null
+++ b/chrome/browser/ash/crosapi/system_display_ash.cc
@@ -0,0 +1,49 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/crosapi/system_display_ash.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "chrome/browser/extensions/system_display/system_display_serialization.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/mojom/geometry.mojom.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace crosapi {
+
+SystemDisplayAsh::SystemDisplayAsh() = default;
+
+SystemDisplayAsh::~SystemDisplayAsh() = default;
+
+void SystemDisplayAsh::BindReceiver(
+    mojo::PendingReceiver<mojom::SystemDisplay> receiver) {
+  receivers_.Add(this, std::move(receiver));
+}
+
+void SystemDisplayAsh::GetDisplayUnitInfoList(
+    bool single_unified,
+    GetDisplayUnitInfoListCallback callback) {
+  extensions::DisplayInfoProvider* provider =
+      extensions::DisplayInfoProvider::Get();
+  provider->GetAllDisplaysInfo(
+      single_unified,
+      base::BindOnce(&SystemDisplayAsh::OnDisplayInfoResult,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void SystemDisplayAsh::OnDisplayInfoResult(
+    GetDisplayUnitInfoListCallback callback,
+    std::vector<DisplayUnitInfo> src_info_list) {
+  std::vector<crosapi::mojom::DisplayUnitInfoPtr> dst_info_list;
+  for (const auto& src_info : src_info_list) {
+    dst_info_list.emplace_back(
+        extensions::api::system_display::SerializeDisplayUnitInfo(src_info));
+  }
+  std::move(callback).Run(std::move(std::move(dst_info_list)));
+}
+
+}  // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/system_display_ash.h b/chrome/browser/ash/crosapi/system_display_ash.h
new file mode 100644
index 0000000..cac871a
--- /dev/null
+++ b/chrome/browser/ash/crosapi/system_display_ash.h
@@ -0,0 +1,51 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_CROSAPI_SYSTEM_DISPLAY_ASH_H_
+#define CHROME_BROWSER_ASH_CROSAPI_SYSTEM_DISPLAY_ASH_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "chromeos/crosapi/mojom/system_display.mojom.h"
+#include "extensions/browser/api/system_display/display_info_provider.h"
+#include "extensions/common/api/system_display.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+
+namespace crosapi {
+
+// The ash-chrome implementation of the SystemDisplay crosapi interface.
+// This class must only be used from the main thread.
+class SystemDisplayAsh : public mojom::SystemDisplay {
+ public:
+  // This type was generated from IDL.
+  using DisplayUnitInfo = extensions::api::system_display::DisplayUnitInfo;
+
+  SystemDisplayAsh();
+  SystemDisplayAsh(const SystemDisplayAsh&) = delete;
+  SystemDisplayAsh& operator=(const SystemDisplayAsh&) = delete;
+  ~SystemDisplayAsh() override;
+
+  void BindReceiver(mojo::PendingReceiver<mojom::SystemDisplay> receiver);
+
+  // crosapi::mojom::SystemDisplay:
+  void GetDisplayUnitInfoList(bool single_unified,
+                              GetDisplayUnitInfoListCallback callback) override;
+
+ private:
+  // Receiver for extensions::DisplayInfoProvider::GetAllDisplaysInfo().
+  void OnDisplayInfoResult(GetDisplayUnitInfoListCallback callback,
+                           std::vector<DisplayUnitInfo> src_info_list);
+
+  // Support any number of connections.
+  mojo::ReceiverSet<mojom::SystemDisplay> receivers_;
+
+  base::WeakPtrFactory<SystemDisplayAsh> weak_ptr_factory_{this};
+};
+
+}  // namespace crosapi
+
+#endif  // CHROME_BROWSER_ASH_CROSAPI_SYSTEM_DISPLAY_ASH_H_
diff --git a/chrome/browser/ash/web_applications/OWNERS b/chrome/browser/ash/web_applications/OWNERS
index 3252852..3e61eda5 100644
--- a/chrome/browser/ash/web_applications/OWNERS
+++ b/chrome/browser/ash/web_applications/OWNERS
@@ -8,7 +8,6 @@
 per-file chrome_file_manager*=file://chromeos/components/file_manager/OWNERS
 per-file crosh*=joelhockey@chromium.org
 per-file file_manager*=file://chromeos/components/file_manager/OWNERS
-per-file *media_app*=file://chromeos/components/media_app_ui/OWNERS
 per-file terminal*=calamity@chromium.org
 per-file terminal*=joelhockey@chromium.org
 per-file eche*=dhnishi@chromium.org
diff --git a/chrome/browser/ash/web_applications/media_app/OWNERS b/chrome/browser/ash/web_applications/media_app/OWNERS
new file mode 100644
index 0000000..c672d4d
--- /dev/null
+++ b/chrome/browser/ash/web_applications/media_app/OWNERS
@@ -0,0 +1 @@
+file://chromeos/components/media_app_ui/OWNERS
diff --git a/chrome/browser/ash/web_applications/chrome_media_app_ui_delegate.cc b/chrome/browser/ash/web_applications/media_app/chrome_media_app_ui_delegate.cc
similarity index 94%
rename from chrome/browser/ash/web_applications/chrome_media_app_ui_delegate.cc
rename to chrome/browser/ash/web_applications/media_app/chrome_media_app_ui_delegate.cc
index a64164f..da7b9fe 100644
--- a/chrome/browser/ash/web_applications/chrome_media_app_ui_delegate.cc
+++ b/chrome/browser/ash/web_applications/media_app/chrome_media_app_ui_delegate.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/web_applications/chrome_media_app_ui_delegate.h"
+#include "chrome/browser/ash/web_applications/media_app/chrome_media_app_ui_delegate.h"
 
 #include "ash/constants/ash_features.h"
 #include "chrome/browser/browser_process.h"
diff --git a/chrome/browser/ash/web_applications/chrome_media_app_ui_delegate.h b/chrome/browser/ash/web_applications/media_app/chrome_media_app_ui_delegate.h
similarity index 77%
rename from chrome/browser/ash/web_applications/chrome_media_app_ui_delegate.h
rename to chrome/browser/ash/web_applications/media_app/chrome_media_app_ui_delegate.h
index ab7a15d..f712ea6e 100644
--- a/chrome/browser/ash/web_applications/chrome_media_app_ui_delegate.h
+++ b/chrome/browser/ash/web_applications/media_app/chrome_media_app_ui_delegate.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_WEB_APPLICATIONS_CHROME_MEDIA_APP_UI_DELEGATE_H_
-#define CHROME_BROWSER_ASH_WEB_APPLICATIONS_CHROME_MEDIA_APP_UI_DELEGATE_H_
+#ifndef CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_APP_CHROME_MEDIA_APP_UI_DELEGATE_H_
+#define CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_APP_CHROME_MEDIA_APP_UI_DELEGATE_H_
 
 #include "base/optional.h"
 #include "chromeos/components/media_app_ui/media_app_ui_delegate.h"
@@ -30,4 +30,4 @@
   content::WebUI* web_ui_;  // Owns |this|.
 };
 
-#endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_CHROME_MEDIA_APP_UI_DELEGATE_H_
+#endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_APP_CHROME_MEDIA_APP_UI_DELEGATE_H_
diff --git a/chrome/browser/ash/web_applications/media_app_guest_ui_config.cc b/chrome/browser/ash/web_applications/media_app/media_app_guest_ui_config.cc
similarity index 95%
rename from chrome/browser/ash/web_applications/media_app_guest_ui_config.cc
rename to chrome/browser/ash/web_applications/media_app/media_app_guest_ui_config.cc
index bfbc124..fc818892 100644
--- a/chrome/browser/ash/web_applications/media_app_guest_ui_config.cc
+++ b/chrome/browser/ash/web_applications/media_app/media_app_guest_ui_config.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/web_applications/media_app_guest_ui_config.h"
+#include "chrome/browser/ash/web_applications/media_app/media_app_guest_ui_config.h"
 
 #include <memory>
 
diff --git a/chrome/browser/ash/web_applications/media_app_guest_ui_config.h b/chrome/browser/ash/web_applications/media_app/media_app_guest_ui_config.h
similarity index 83%
rename from chrome/browser/ash/web_applications/media_app_guest_ui_config.h
rename to chrome/browser/ash/web_applications/media_app/media_app_guest_ui_config.h
index 79a9f7b..99410ba 100644
--- a/chrome/browser/ash/web_applications/media_app_guest_ui_config.h
+++ b/chrome/browser/ash/web_applications/media_app/media_app_guest_ui_config.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_APP_GUEST_UI_CONFIG_H_
-#define CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_APP_GUEST_UI_CONFIG_H_
+#ifndef CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_APP_MEDIA_APP_GUEST_UI_CONFIG_H_
+#define CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_APP_MEDIA_APP_GUEST_UI_CONFIG_H_
 
 #include "chromeos/components/media_app_ui/media_app_guest_ui.h"
 #include "ui/webui/webui_config.h"
@@ -37,4 +37,4 @@
       content::WebUI* web_ui) override;
 };
 
-#endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_APP_GUEST_UI_CONFIG_H_
+#endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_APP_MEDIA_APP_GUEST_UI_CONFIG_H_
diff --git a/chrome/browser/ash/web_applications/media_app_integration_browsertest.cc b/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc
similarity index 98%
rename from chrome/browser/ash/web_applications/media_app_integration_browsertest.cc
rename to chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc
index d066096..d96f2471 100644
--- a/chrome/browser/ash/web_applications/media_app_integration_browsertest.cc
+++ b/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc
@@ -253,16 +253,14 @@
   // Ensure test image loaded.
   EXPECT_EQ("640x480", WaitForImageAlt(app, kFileJpeg640x480));
 
-  // TODO(b/175766054): Decipher if we can one line getting the annotate button
-  // in `waitForNode`.
   // Note the button id (icon-button-3709949292) corresponds to the annotation
   // button and is calculated from a hash of the label ("Annotate"). This id is
   // used since cl/366443893 because the UI toolkit has loose guarantees about
   // where the actual label appears in the shadow DOM.
   constexpr char clickAnnotate[] = R"(
     (async () => {
-      const appBar = await waitForNode('backlight-app-bar', ['backlight-app']);
-      const annotateButton = appBar.shadowRoot.querySelector('#icon-button-3709949292');
+      const annotateButton = await waitForNode(
+          '#icon-button-3709949292', ['backlight-app-bar', 'backlight-app']);
       annotateButton.click();
       return true;
     })();
@@ -275,7 +273,8 @@
   // Note: The loading of ink engine elements can be async.
   constexpr char checkInkLoaded[] = R"(
     (async () => {
-      const inkEngineCanvas = await waitForNode('canvas#ink-engine[width]', ['backlight-image-handler']);
+      const inkEngineCanvas = await waitForNode(
+          'canvas#ink-engine[width]', ['backlight-image-handler']);
       return !!inkEngineCanvas &&
         !!inkEngineCanvas.getAttribute('height') &&
         inkEngineCanvas.getAttribute('height') !== '0' &&
diff --git a/chrome/browser/ash/web_applications/media_web_app_info.cc b/chrome/browser/ash/web_applications/media_app/media_web_app_info.cc
similarity index 98%
rename from chrome/browser/ash/web_applications/media_web_app_info.cc
rename to chrome/browser/ash/web_applications/media_app/media_web_app_info.cc
index 8cf79bca..4af83e4 100644
--- a/chrome/browser/ash/web_applications/media_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/media_app/media_web_app_info.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/web_applications/media_web_app_info.h"
+#include "chrome/browser/ash/web_applications/media_app/media_web_app_info.h"
 
 #include <memory>
 #include <string>
diff --git a/chrome/browser/ash/web_applications/media_app/media_web_app_info.h b/chrome/browser/ash/web_applications/media_app/media_web_app_info.h
new file mode 100644
index 0000000..dffb1ff3
--- /dev/null
+++ b/chrome/browser/ash/web_applications/media_app/media_web_app_info.h
@@ -0,0 +1,15 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_APP_MEDIA_WEB_APP_INFO_H_
+#define CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_APP_MEDIA_WEB_APP_INFO_H_
+
+#include <memory>
+
+struct WebApplicationInfo;
+
+// Return a WebApplicationInfo used to install the app.
+std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForMediaWebApp();
+
+#endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_APP_MEDIA_WEB_APP_INFO_H_
diff --git a/chrome/browser/ash/web_applications/media_web_app_info.h b/chrome/browser/ash/web_applications/media_web_app_info.h
deleted file mode 100644
index a665b30f..0000000
--- a/chrome/browser/ash/web_applications/media_web_app_info.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_WEB_APP_INFO_H_
-#define CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_WEB_APP_INFO_H_
-
-#include <memory>
-
-struct WebApplicationInfo;
-
-// Return a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForMediaWebApp();
-
-#endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_WEB_APP_INFO_H_
diff --git a/chrome/browser/conversions/OWNERS b/chrome/browser/attribution_reporting/OWNERS
similarity index 100%
rename from chrome/browser/conversions/OWNERS
rename to chrome/browser/attribution_reporting/OWNERS
diff --git a/chrome/browser/attribution_reporting/android/BUILD.gn b/chrome/browser/attribution_reporting/android/BUILD.gn
new file mode 100644
index 0000000..3a20409
--- /dev/null
+++ b/chrome/browser/attribution_reporting/android/BUILD.gn
@@ -0,0 +1,15 @@
+import("//build/config/android/rules.gni")
+import("//chrome/android/features/android_library_factory_tmpl.gni")
+
+android_library("java") {
+  sources = [
+    "java/src/org/chromium/chrome/browser/attribution_reporting/AttributionConstants.java",
+    "java/src/org/chromium/chrome/browser/attribution_reporting/AttributionIntentHandler.java",
+  ]
+}
+
+android_library_factory("factory_java") {
+  deps = [ ":java" ]
+
+  sources = [ "internal/java/src/org/chromium/chrome/browser/attribution_reporting/AttributionIntentHandlerFactory.java" ]
+}
diff --git a/chrome/browser/attribution_reporting/android/DIR_METADATA b/chrome/browser/attribution_reporting/android/DIR_METADATA
new file mode 100644
index 0000000..5777c4c
--- /dev/null
+++ b/chrome/browser/attribution_reporting/android/DIR_METADATA
@@ -0,0 +1,12 @@
+# Metadata information for this directory.
+#
+# For more information on DIR_METADATA files, see:
+#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
+#
+# For the schema of this file, see Metadata message:
+#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+
+monorail {
+  component: "Internals>ConversionMeasurement"
+}
+os: ANDROID
diff --git a/chrome/browser/attribution_reporting/android/OWNERS b/chrome/browser/attribution_reporting/android/OWNERS
new file mode 100644
index 0000000..c19374d6
--- /dev/null
+++ b/chrome/browser/attribution_reporting/android/OWNERS
@@ -0,0 +1 @@
+mthiesse@chromium.org
diff --git a/chrome/browser/attribution_reporting/android/internal/BUILD.gn b/chrome/browser/attribution_reporting/android/internal/BUILD.gn
new file mode 100644
index 0000000..605c7cc
--- /dev/null
+++ b/chrome/browser/attribution_reporting/android/internal/BUILD.gn
@@ -0,0 +1,9 @@
+import("//build/config/android/rules.gni")
+
+android_library("java") {
+  sources = [
+    "java/src/org/chromium/chrome/browser/attribution_reporting/AttributionIntentHandlerFactory.java",
+    "java/src/org/chromium/chrome/browser/attribution_reporting/NoopAttributionIntentHandler.java",
+  ]
+  deps = [ "//chrome/browser/attribution_reporting/android:java" ]
+}
diff --git a/chrome/browser/attribution_reporting/android/internal/java/src/org/chromium/chrome/browser/attribution_reporting/AttributionIntentHandlerFactory.java b/chrome/browser/attribution_reporting/android/internal/java/src/org/chromium/chrome/browser/attribution_reporting/AttributionIntentHandlerFactory.java
new file mode 100644
index 0000000..ebf154a
--- /dev/null
+++ b/chrome/browser/attribution_reporting/android/internal/java/src/org/chromium/chrome/browser/attribution_reporting/AttributionIntentHandlerFactory.java
@@ -0,0 +1,18 @@
+// 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.
+
+package org.chromium.chrome.browser.attribution_reporting;
+
+/**
+ * Factory for creating instances of the AttributionIntentHandler from the attribution_reporting
+ * module.
+ */
+public class AttributionIntentHandlerFactory {
+    /**
+     * @return a AttributionIntentHandler instance.
+     */
+    public static AttributionIntentHandler create() {
+        return new NoopAttributionIntentHandler();
+    }
+}
diff --git a/chrome/browser/attribution_reporting/android/internal/java/src/org/chromium/chrome/browser/attribution_reporting/NoopAttributionIntentHandler.java b/chrome/browser/attribution_reporting/android/internal/java/src/org/chromium/chrome/browser/attribution_reporting/NoopAttributionIntentHandler.java
new file mode 100644
index 0000000..3cc3c77
--- /dev/null
+++ b/chrome/browser/attribution_reporting/android/internal/java/src/org/chromium/chrome/browser/attribution_reporting/NoopAttributionIntentHandler.java
@@ -0,0 +1,20 @@
+// 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.
+
+package org.chromium.chrome.browser.attribution_reporting;
+
+import android.content.Intent;
+
+/** Noops Attribution Intent handling when the App Attribution feature isn't enabled. */
+public class NoopAttributionIntentHandler implements AttributionIntentHandler {
+    @Override
+    public boolean handleOuterAttributionIntent(Intent intent) {
+        return false;
+    }
+
+    @Override
+    public Intent handleInnerAttributionIntent(Intent intent) {
+        return null;
+    }
+}
diff --git a/chrome/browser/attribution_reporting/android/java/src/org/chromium/chrome/browser/attribution_reporting/AttributionConstants.java b/chrome/browser/attribution_reporting/android/java/src/org/chromium/chrome/browser/attribution_reporting/AttributionConstants.java
new file mode 100644
index 0000000..0caa288
--- /dev/null
+++ b/chrome/browser/attribution_reporting/android/java/src/org/chromium/chrome/browser/attribution_reporting/AttributionConstants.java
@@ -0,0 +1,11 @@
+// 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.
+
+package org.chromium.chrome.browser.attribution_reporting;
+
+/** Public constants for the attribution_reporting module. */
+public class AttributionConstants {
+    public static final String ACTION_APP_ATTRIBUTION = "android.web.action.APP_ATTRIBUTION";
+    public static final String EXTRA_ATTRIBUTION_INTENT = "android.web.extra.ATTRIBUTION_INTENT";
+}
diff --git a/chrome/browser/attribution_reporting/android/java/src/org/chromium/chrome/browser/attribution_reporting/AttributionIntentHandler.java b/chrome/browser/attribution_reporting/android/java/src/org/chromium/chrome/browser/attribution_reporting/AttributionIntentHandler.java
new file mode 100644
index 0000000..3bb0248
--- /dev/null
+++ b/chrome/browser/attribution_reporting/android/java/src/org/chromium/chrome/browser/attribution_reporting/AttributionIntentHandler.java
@@ -0,0 +1,22 @@
+// 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.
+
+package org.chromium.chrome.browser.attribution_reporting;
+
+import android.content.Intent;
+
+/** Public interface for the AttributionIntentHandler from the attribution_reporting module. */
+public interface AttributionIntentHandler {
+    /**
+     * If |intent| is an outer App to Web Attribution Intent, processes the Intent and returns true,
+     * otherwise returns false.
+     */
+    boolean handleOuterAttributionIntent(Intent intent);
+
+    /**
+     * If the intent is an inner App to Web Attribution Intent, processes the Attribution data, and
+     * returns the View intent provided by the original outer intent.
+     */
+    Intent handleInnerAttributionIntent(Intent intent);
+}
diff --git a/chrome/browser/conversions/conversions_usage_restriction_trial_browsertest.cc b/chrome/browser/attribution_reporting/conversions_usage_restriction_trial_browsertest.cc
similarity index 100%
rename from chrome/browser/conversions/conversions_usage_restriction_trial_browsertest.cc
rename to chrome/browser/attribution_reporting/conversions_usage_restriction_trial_browsertest.cc
diff --git a/chrome/browser/conversions/conversions_usecounter_browsertest.cc b/chrome/browser/attribution_reporting/conversions_usecounter_browsertest.cc
similarity index 100%
rename from chrome/browser/conversions/conversions_usecounter_browsertest.cc
rename to chrome/browser/attribution_reporting/conversions_usecounter_browsertest.cc
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index eb77e25..919e17b 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -185,7 +185,6 @@
 #include "chrome/browser/ui/page_info/chrome_page_info_client.h"
 #include "ui/base/resource/resource_bundle_android.h"
 #else
-#include "chrome/browser/accessibility/soda_installer.h"
 #include "chrome/browser/resource_coordinator/tab_activity_watcher.h"
 #include "chrome/browser/resource_coordinator/tab_manager.h"
 #include "chrome/browser/ui/browser.h"
@@ -193,6 +192,7 @@
 #include "chrome/browser/ui/uma_browsing_activity_observer.h"
 #include "chrome/browser/upgrade_detector/upgrade_detector.h"
 #include "chrome/browser/usb/web_usb_detector.h"
+#include "components/soda/soda_installer.h"
 #endif  // defined(OS_ANDROID)
 
 #if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/chrome_security_exploit_browsertest.cc b/chrome/browser/chrome_security_exploit_browsertest.cc
index fd8ec071..9c17de1 100644
--- a/chrome/browser/chrome_security_exploit_browsertest.cc
+++ b/chrome/browser/chrome_security_exploit_browsertest.cc
@@ -66,8 +66,8 @@
       const std::string& content_type) {
     std::unique_ptr<content::BlobHandle> result;
     base::RunLoop loop;
-    content::BrowserContext::CreateMemoryBackedBlob(
-        profile(), base::as_bytes(base::make_span(contents)), content_type,
+    profile()->CreateMemoryBackedBlob(
+        base::as_bytes(base::make_span(contents)), content_type,
         base::BindOnce(
             [](std::unique_ptr<content::BlobHandle>* out_blob,
                base::OnceClosure done,
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 235c525..f3bb33b 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -349,6 +349,7 @@
     "//components/session_manager/core",
     "//components/signin/public/identity_manager",
     "//components/signin/public/webdata",
+    "//components/soda",
     "//components/soda:constants",
     "//components/spellcheck/browser:browser",
     "//components/spellcheck/common:spellcheck_result",
@@ -1115,6 +1116,8 @@
     "../ash/crosapi/screen_manager_ash.h",
     "../ash/crosapi/select_file_ash.cc",
     "../ash/crosapi/select_file_ash.h",
+    "../ash/crosapi/system_display_ash.cc",
+    "../ash/crosapi/system_display_ash.h",
     "../ash/crosapi/task_manager_ash.cc",
     "../ash/crosapi/task_manager_ash.h",
     "../ash/crosapi/test_controller_ash.cc",
@@ -1825,8 +1828,6 @@
     "../ash/web_applications/chrome_camera_app_ui_constants.h",
     "../ash/web_applications/chrome_camera_app_ui_delegate.cc",
     "../ash/web_applications/chrome_camera_app_ui_delegate.h",
-    "../ash/web_applications/chrome_media_app_ui_delegate.cc",
-    "../ash/web_applications/chrome_media_app_ui_delegate.h",
     "../ash/web_applications/chrome_personalization_app_ui_delegate.cc",
     "../ash/web_applications/chrome_personalization_app_ui_delegate.h",
     "../ash/web_applications/connectivity_diagnostics_system_web_app_info.cc",
@@ -1849,10 +1850,12 @@
     "../ash/web_applications/help_app/help_app_ui_delegate.h",
     "../ash/web_applications/help_app/help_app_web_app_info.cc",
     "../ash/web_applications/help_app/help_app_web_app_info.h",
-    "../ash/web_applications/media_app_guest_ui_config.cc",
-    "../ash/web_applications/media_app_guest_ui_config.h",
-    "../ash/web_applications/media_web_app_info.cc",
-    "../ash/web_applications/media_web_app_info.h",
+    "../ash/web_applications/media_app/chrome_media_app_ui_delegate.cc",
+    "../ash/web_applications/media_app/chrome_media_app_ui_delegate.h",
+    "../ash/web_applications/media_app/media_app_guest_ui_config.cc",
+    "../ash/web_applications/media_app/media_app_guest_ui_config.h",
+    "../ash/web_applications/media_app/media_web_app_info.cc",
+    "../ash/web_applications/media_app/media_web_app_info.h",
     "../ash/web_applications/os_settings_web_app_info.cc",
     "../ash/web_applications/os_settings_web_app_info.h",
     "../ash/web_applications/personalization_app_info.cc",
diff --git a/chrome/browser/chromeos/extensions/printing/printing_api_handler_unittest.cc b/chrome/browser/chromeos/extensions/printing/printing_api_handler_unittest.cc
index 2b65a45..dfbb882 100644
--- a/chrome/browser/chromeos/extensions/printing/printing_api_handler_unittest.cc
+++ b/chrome/browser/chromeos/extensions/printing/printing_api_handler_unittest.cc
@@ -215,8 +215,8 @@
     const std::string& content_type) {
   std::unique_ptr<content::BlobHandle> result;
   base::RunLoop run_loop;
-  content::BrowserContext::CreateMemoryBackedBlob(
-      browser_context, base::as_bytes(base::make_span(content)), content_type,
+  browser_context->CreateMemoryBackedBlob(
+      base::as_bytes(base::make_span(content)), content_type,
       base::BindOnce(
           [](std::unique_ptr<content::BlobHandle>* out_blob,
              base::OnceClosure closure,
diff --git a/chrome/browser/chromeos/input_method/autocorrect_manager.cc b/chrome/browser/chromeos/input_method/autocorrect_manager.cc
index f615d81e..3f0b1bd5 100644
--- a/chrome/browser/chromeos/input_method/autocorrect_manager.cc
+++ b/chrome/browser/chromeos/input_method/autocorrect_manager.cc
@@ -210,10 +210,44 @@
       ui::IMEBridge::Get()->GetInputContextHandler();
   const gfx::Range range = input_context->GetAutocorrectRange();
 
-  input_context->SetComposingRange(range.start(), range.end(), {});
-  input_context->CommitText(
-      original_text_,
-      ui::TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText);
+  if (input_context->HasCompositionText()) {
+    input_context->SetComposingRange(range.start(), range.end(), {});
+    input_context->CommitText(
+        original_text_,
+        ui::TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText);
+  } else {
+    // NOTE: GetSurroundingTextInfo() could return a stale cache that no longer
+    // reflects reality, due to async-ness between IMF and TextInputClient.
+    // TODO(crbug/1194424): Work around the issue or fix
+    // GetSurroundingTextInfo().
+    const ui::SurroundingTextInfo surrounding_text =
+        input_context->GetSurroundingTextInfo();
+
+    // TODO(crbug/1111135): Can we get away with deleting less text?
+    // This will not quite work properly if there is text actually highlighted,
+    // and cursor is at end of the highlight block, but no easy way around it.
+    // First delete everything before cursor.
+    input_context->DeleteSurroundingText(
+        -static_cast<int>(surrounding_text.selection_range.start()),
+        surrounding_text.surrounding_text.length());
+
+    // Submit the text after the cursor in composition mode to leave the cursor
+    // at the start
+    ui::CompositionText composition_text;
+    composition_text.text =
+        surrounding_text.surrounding_text.substr(range.end());
+    input_context->UpdateCompositionText(composition_text,
+                                         /*cursor_pos=*/0, /*visible=*/true);
+    input_context->ConfirmCompositionText(/*reset_engine=*/false,
+                                          /*keep_selection=*/true);
+
+    // Insert the text before the cursor - now there should be the correct text
+    // and the cursor position will not have changed.
+    input_context->CommitText(
+        surrounding_text.surrounding_text.substr(0, range.start()) +
+            original_text_,
+        ui::TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText);
+  }
 
   LogAssistiveAutocorrectAction(AutocorrectActions::kReverted);
   RecordAssistiveCoverage(AssistiveType::kAutocorrectReverted);
diff --git a/chrome/browser/chromeos/input_method/autocorrect_manager_unittest.cc b/chrome/browser/chromeos/input_method/autocorrect_manager_unittest.cc
index 3b341b04..4c70611 100644
--- a/chrome/browser/chromeos/input_method/autocorrect_manager_unittest.cc
+++ b/chrome/browser/chromeos/input_method/autocorrect_manager_unittest.cc
@@ -205,27 +205,6 @@
   EXPECT_EQ(fake_text_input_client.text(), u"helloworld ");
 }
 
-TEST(AutocorrectManagerTest, UndoAutocorrectNoComposition) {
-  ui::IMEBridge::Initialize();
-  ui::FakeTextInputClient fake_text_input_client(ui::TEXT_INPUT_TYPE_TEXT);
-  ui::InputMethodChromeOS ime(nullptr);
-  ui::IMEBridge::Get()->SetInputContextHandler(&ime);
-  ime.SetFocusedTextInputClient(&fake_text_input_client);
-
-  ::testing::NiceMock<MockSuggestionHandler> mock_suggestion_handler;
-  AutocorrectManager manager(&mock_suggestion_handler);
-  manager.OnSurroundingTextChanged(u"the ", /*cursor_pos=*/4,
-                                   /*anchor_pos=*/4);
-  manager.HandleAutocorrect(gfx::Range(0, 3), u"teh", u"the");
-
-  // Move cursor to the middle of 'the'.
-  fake_text_input_client.SetTextAndSelection(u"the ", gfx::Range(2));
-
-  manager.UndoAutocorrect();
-
-  EXPECT_EQ(fake_text_input_client.text(), u"teh ");
-}
-
 TEST(AutocorrectManagerTest, RecordVirtualKeyboardMetricsWhenVisible) {
   ui::IMEBridge::Initialize();
   ui::MockIMEInputContextHandler mock_ime_input_context_handler;
diff --git a/chrome/browser/chromeos/input_method/native_input_method_engine.cc b/chrome/browser/chromeos/input_method/native_input_method_engine.cc
index 4b8a92d8d..763088d 100644
--- a/chrome/browser/chromeos/input_method/native_input_method_engine.cc
+++ b/chrome/browser/chromeos/input_method/native_input_method_engine.cc
@@ -571,6 +571,11 @@
           base::Unretained(this), std::move(callback)));
 }
 
+void NativeInputMethodEngine::ImeObserver::DisplaySuggestions(
+    const std::vector<ime::TextSuggestion>& suggestions) {
+  assistive_suggester_->OnExternalSuggestionsUpdated(suggestions);
+}
+
 void NativeInputMethodEngine::ImeObserver::FlushForTesting() {
   remote_manager_.FlushForTesting();
   if (remote_to_engine_.is_bound())
diff --git a/chrome/browser/chromeos/input_method/native_input_method_engine.h b/chrome/browser/chromeos/input_method/native_input_method_engine.h
index 2b36ffb..2716e3b 100644
--- a/chrome/browser/chromeos/input_method/native_input_method_engine.h
+++ b/chrome/browser/chromeos/input_method/native_input_method_engine.h
@@ -156,6 +156,8 @@
         ime::mojom::AutocorrectSpanPtr autocorrect_span) override;
     void RequestSuggestions(ime::mojom::SuggestionsRequestPtr request,
                             RequestSuggestionsCallback callback) override;
+    void DisplaySuggestions(
+        const std::vector<ime::TextSuggestion>& suggestions) override;
 
     // Called when suggestions are collected from the system via
     // suggestions_collector_.
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc
index 42e259ec..bc16522 100644
--- a/chrome/browser/chromeos/preferences.cc
+++ b/chrome/browser/chromeos/preferences.cc
@@ -310,6 +310,10 @@
       chromeos::prefs::kEmojiSuggestionEnterpriseAllowed, true);
   registry->RegisterDictionaryPref(
       ::prefs::kLanguageInputMethodSpecificSettings);
+  registry->RegisterBooleanPref(prefs::kLastUsedImeShortcutReminderDismissed,
+                                false);
+  registry->RegisterBooleanPref(prefs::kNextImeShortcutReminderDismissed,
+                                false);
 
   registry->RegisterIntegerPref(
       ::prefs::kLanguageRemapSearchKeyTo,
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry_browsertest.cc b/chrome/browser/custom_handlers/protocol_handler_registry_browsertest.cc
index 2fab860..acdffcf3 100644
--- a/chrome/browser/custom_handlers/protocol_handler_registry_browsertest.cc
+++ b/chrome/browser/custom_handlers/protocol_handler_registry_browsertest.cc
@@ -262,8 +262,9 @@
   }
 };
 
+// TODO(crbug.com/1204127): Fix flakiness.
 IN_PROC_BROWSER_TEST_F(RegisterProtocolHandlerAndServiceWorkerInterceptor,
-                       RegisterFetchListenerForHTMLHandler) {
+                       DISABLED_RegisterFetchListenerForHTMLHandler) {
   WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
 
diff --git a/chrome/browser/download/android/download_manager_bridge.cc b/chrome/browser/download/android/download_manager_bridge.cc
index 473df60..da32e79 100644
--- a/chrome/browser/download/android/download_manager_bridge.cc
+++ b/chrome/browser/download/android/download_manager_bridge.cc
@@ -34,10 +34,8 @@
 void DownloadManagerBridge::AddCompletedDownload(
     download::DownloadItem* download,
     AddCompletedDownloadCallback callback) {
-  if (!base::FeatureList::IsEnabled(
-          download::features::kUseDownloadOfflineContentProvider)) {
-    return;
-  }
+  DCHECK(base::FeatureList::IsEnabled(
+      download::features::kUseDownloadOfflineContentProvider));
 
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jstring> jfile_name =
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index 7c66199..6d340cf 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -4755,7 +4755,7 @@
 // same GUID.
 // TODO(crbug.com/1204298): Disabled due to flakines.
 IN_PROC_BROWSER_TEST_F(InProgressDownloadTest,
-                       DISABLED_DownloadURLWithInProgressManager) {
+                       DownloadURLWithInProgressManager) {
   embedded_test_server()->ServeFilesFromDirectory(GetTestDataDirectory());
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL url = embedded_test_server()->GetURL("/downloads/a_zip_file.zip");
diff --git a/chrome/browser/download/download_offline_content_provider.cc b/chrome/browser/download/download_offline_content_provider.cc
index d6ca49bf..2f652ce 100644
--- a/chrome/browser/download/download_offline_content_provider.cc
+++ b/chrome/browser/download/download_offline_content_provider.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/thumbnail/generator/image_thumbnail_request.h"
+#include "components/download/public/common/download_features.h"
 #include "components/download/public/common/download_item.h"
 #include "content/public/browser/browser_context.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -450,6 +451,10 @@
 }
 
 void DownloadOfflineContentProvider::OnDownloadStarted(DownloadItem* item) {
+  if (!base::FeatureList::IsEnabled(
+          download::features::kUseDownloadOfflineContentProvider)) {
+    return;
+  }
   item->RemoveObserver(this);
   item->AddObserver(this);
 
@@ -459,8 +464,9 @@
 void DownloadOfflineContentProvider::OnDownloadUpdated(DownloadItem* item) {
   // Wait until the target path is determined or the download is canceled.
   if (item->GetTargetFilePath().empty() &&
-      item->GetState() != DownloadItem::CANCELLED)
+      item->GetState() != DownloadItem::CANCELLED) {
     return;
+  }
 
   if (!ShouldShowDownloadItem(item))
     return;
diff --git a/chrome/browser/download/download_service_factory.cc b/chrome/browser/download/download_service_factory.cc
index 416cb68..6f5b75e 100644
--- a/chrome/browser/download/download_service_factory.cc
+++ b/chrome/browser/download/download_service_factory.cc
@@ -77,8 +77,7 @@
 // Called on profile created to retrieve the BlobStorageContextGetter.
 void DownloadOnProfileCreated(download::BlobContextGetterCallback callback,
                               Profile* profile) {
-  auto blob_context_getter =
-      content::BrowserContext::GetBlobStorageContext(profile);
+  auto blob_context_getter = profile->GetBlobStorageContext();
   DCHECK(callback);
   std::move(callback).Run(blob_context_getter);
 }
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index 98b97b4..e4e65a91 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -982,6 +982,8 @@
       "api/platform_keys/platform_keys_api.h",
       "clipboard_extension_helper_chromeos.cc",
       "clipboard_extension_helper_chromeos.h",
+      "system_display/system_display_serialization.cc",
+      "system_display/system_display_serialization.h",
     ]
     deps += [
       "//chromeos/crosapi/cpp",
@@ -997,6 +999,8 @@
         "api/messaging/native_message_host_lacros.cc",
         "api/platform_keys/platform_keys_api_lacros.cc",
         "api/platform_keys/platform_keys_api_lacros.h",
+        "system_display/display_info_provider_lacros.cc",
+        "system_display/display_info_provider_lacros.h",
       ]
       deps += [ "//chromeos/lacros" ]
     } else {
@@ -1239,7 +1243,7 @@
       "setupapi.lib",
       "propsys.lib",
     ]
-  } else if (use_aura && !is_chromeos_ash) {
+  } else if (use_aura && !is_chromeos_ash && !is_chromeos_lacros) {
     sources += [
       "system_display/display_info_provider_aura.cc",
       "system_display/display_info_provider_aura.h",
diff --git a/chrome/browser/extensions/api/declarative_content/content_action.cc b/chrome/browser/extensions/api/declarative_content/content_action.cc
index 5a9f3b1..b05def4 100644
--- a/chrome/browser/extensions/api/declarative_content/content_action.cc
+++ b/chrome/browser/extensions/api/declarative_content/content_action.cc
@@ -365,11 +365,17 @@
   ContentScriptTracker::WillExecuteCode(base::PassKey<RequestContentScript>(),
                                         contents->GetMainFrame(), *extension);
 
-  ExtensionWebContentsObserver::GetForWebContents(contents)
-      ->GetLocalFrame(contents->GetMainFrame())
-      ->ExecuteDeclarativeScript(
-          sessions::SessionTabHelper::IdForTab(contents).id(), extension->id(),
-          script_.id(), contents->GetLastCommittedURL());
+  mojom::LocalFrame* local_frame =
+      ExtensionWebContentsObserver::GetForWebContents(contents)->GetLocalFrame(
+          contents->GetMainFrame());
+  if (!local_frame) {
+    // TODO(https://crbug.com/1203579): Need to review when this method is
+    // called with non-live frame.
+    return;
+  }
+  local_frame->ExecuteDeclarativeScript(
+      sessions::SessionTabHelper::IdForTab(contents).id(), extension->id(),
+      script_.id(), contents->GetLastCommittedURL());
 }
 
 void RequestContentScript::OnScriptsLoaded(
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc
index 2b552805..a9104773 100644
--- a/chrome/browser/extensions/api/settings_private/prefs_util.cc
+++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -336,6 +336,10 @@
       settings_api::PrefType::PREF_TYPE_BOOLEAN;
   (*s_allowlist)[::prefs::kLanguageInputMethodSpecificSettings] =
       settings_api::PrefType::PREF_TYPE_DICTIONARY;
+  (*s_allowlist)[ash::prefs::kLastUsedImeShortcutReminderDismissed] =
+      settings_api::PrefType::PREF_TYPE_BOOLEAN;
+  (*s_allowlist)[ash::prefs::kNextImeShortcutReminderDismissed] =
+      settings_api::PrefType::PREF_TYPE_BOOLEAN;
 #endif
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -355,8 +359,6 @@
   // Search page.
   (*s_allowlist)[DefaultSearchManager::kDefaultSearchProviderDataPrefName] =
       settings_api::PrefType::PREF_TYPE_DICTIONARY;
-  (*s_allowlist)[::omnibox::kKeywordSpaceTriggeringEnabled] =
-      settings_api::PrefType::PREF_TYPE_BOOLEAN;
 
   // Site Settings prefs.
   (*s_allowlist)[::content_settings::kCookiePrimarySetting] =
diff --git a/chrome/browser/extensions/system_display/display_info_provider_lacros.cc b/chrome/browser/extensions/system_display/display_info_provider_lacros.cc
new file mode 100644
index 0000000..bca7987
--- /dev/null
+++ b/chrome/browser/extensions/system_display/display_info_provider_lacros.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 "chrome/browser/extensions/system_display/display_info_provider_lacros.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "chrome/browser/extensions/system_display/system_display_serialization.h"
+#include "chromeos/lacros/lacros_service.h"
+#include "extensions/common/api/system_display.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/mojom/geometry.mojom.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace extensions {
+
+DisplayInfoProviderLacros::DisplayInfoProviderLacros() = default;
+
+DisplayInfoProviderLacros::~DisplayInfoProviderLacros() = default;
+
+void DisplayInfoProviderLacros::GetAllDisplaysInfo(
+    bool single_unified,
+    base::OnceCallback<void(DisplayUnitInfoList)> callback) {
+  auto* lacros_service = chromeos::LacrosService::Get();
+  if (lacros_service->IsAvailable<crosapi::mojom::SystemDisplay>()) {
+    auto cb =
+        base::BindOnce(&DisplayInfoProviderLacros::OnCrosapiResult,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback));
+    chromeos::LacrosChromeServiceImpl::Get()
+        ->GetRemote<crosapi::mojom::SystemDisplay>()
+        ->GetDisplayUnitInfoList(single_unified, std::move(cb));
+
+  } else {
+    std::move(callback).Run(DisplayUnitInfoList());
+  }
+}
+
+void DisplayInfoProviderLacros::OnCrosapiResult(
+    base::OnceCallback<void(DisplayUnitInfoList)> callback,
+    std::vector<crosapi::mojom::DisplayUnitInfoPtr> src_info_list) {
+  DisplayUnitInfoList dst_info_list(src_info_list.size());
+  for (size_t i = 0; i < src_info_list.size(); ++i) {
+    DCHECK(src_info_list[i]);
+    extensions::api::system_display::DeserializeDisplayUnitInfo(
+        *src_info_list[i], &dst_info_list[i]);
+  }
+  std::move(callback).Run(std::move(dst_info_list));
+}
+
+std::unique_ptr<DisplayInfoProvider> CreateChromeDisplayInfoProvider() {
+  return std::make_unique<DisplayInfoProviderLacros>();
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/system_display/display_info_provider_lacros.h b/chrome/browser/extensions/system_display/display_info_provider_lacros.h
new file mode 100644
index 0000000..9ac647e
--- /dev/null
+++ b/chrome/browser/extensions/system_display/display_info_provider_lacros.h
@@ -0,0 +1,44 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_SYSTEM_DISPLAY_DISPLAY_INFO_PROVIDER_LACROS_H_
+#define CHROME_BROWSER_EXTENSIONS_SYSTEM_DISPLAY_DISPLAY_INFO_PROVIDER_LACROS_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "chromeos/crosapi/mojom/system_display.mojom.h"
+#include "extensions/browser/api/system_display/display_info_provider.h"
+#include "extensions/common/api/system_display.h"
+
+namespace extensions {
+
+// DisplayInfoProvider used by lacros-chrome that uses crosapi to get
+// DisplayUnitInfoList from ash-chrome, and handle potential version skew.
+class DisplayInfoProviderLacros : public DisplayInfoProvider {
+ public:
+  DisplayInfoProviderLacros();
+  ~DisplayInfoProviderLacros() override;
+  DisplayInfoProviderLacros(const DisplayInfoProviderLacros&) = delete;
+  const DisplayInfoProviderLacros& operator=(const DisplayInfoProviderLacros&) =
+      delete;
+
+  // DisplayInfoProvider:
+  void GetAllDisplaysInfo(
+      bool single_unified,
+      base::OnceCallback<void(DisplayUnitInfoList)> callback) override;
+
+ private:
+  // Receiver for SystemDisplayAsh::GetDisplayUnitInfoList().
+  void OnCrosapiResult(
+      base::OnceCallback<void(DisplayUnitInfoList)> callback,
+      std::vector<crosapi::mojom::DisplayUnitInfoPtr> src_info_list);
+
+  base::WeakPtrFactory<DisplayInfoProviderLacros> weak_ptr_factory_{this};
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_SYSTEM_DISPLAY_DISPLAY_INFO_PROVIDER_LACROS_H_
diff --git a/chrome/browser/extensions/system_display/system_display_serialization.cc b/chrome/browser/extensions/system_display/system_display_serialization.cc
new file mode 100644
index 0000000..193465b68
--- /dev/null
+++ b/chrome/browser/extensions/system_display/system_display_serialization.cc
@@ -0,0 +1,219 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/system_display/system_display_serialization.h"
+
+#include "extensions/common/api/system_display.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace extensions {
+namespace api {
+namespace system_display {
+
+namespace {
+
+// Mojo does not support optional primitive types. Serializing these require
+// an ancillary |has_*| bool.
+template <class T>
+void SerializeOptionalPrimitive(const std::unique_ptr<T>& src_val,
+                                bool* dst_has_val,
+                                T* dst_val) {
+  if (src_val.get()) {
+    *dst_has_val = true;
+    *dst_val = *src_val;
+  } else {
+    *dst_has_val = false;
+    *dst_val = {};
+  }
+}
+
+template <class T>
+void DeserializeOptionalPrimitive(bool src_has_val,
+                                  T src_val,
+                                  std::unique_ptr<T>* dst_val) {
+  DCHECK(!dst_val->get());
+  if (src_has_val)
+    *dst_val = std::make_unique<T>(src_val);
+}
+
+// (int, int) <==> gfx::Size
+
+gfx::Size SerializeSize(int src_width, int src_height) {
+  return gfx::Size(src_width, src_height);
+}
+
+void DeserializeSize(const gfx::Size& src, int* dst_width, int* dst_height) {
+  *dst_width = src.width();
+  *dst_height = src.height();
+}
+
+// extensions::api::system_display::Bounds <==> gfx::Rect.
+
+gfx::Rect SerializeBoundsAsRect(
+    const extensions::api::system_display::Bounds& src) {
+  gfx::Rect dst;
+  dst.set_x(src.left);
+  dst.set_y(src.top);
+  dst.set_width(src.width);
+  dst.set_height(src.height);
+  return dst;
+}
+
+void DeserializeRectToBounds(const gfx::Rect& src,
+                             extensions::api::system_display::Bounds* dst) {
+  dst->left = src.x();
+  dst->top = src.y();
+  dst->width = src.width();
+  dst->height = src.height();
+}
+
+// extensions::api::system_display::Insets <==> gfx::Insets.
+
+gfx::Insets SerializeInsets(
+    const extensions::api::system_display::Insets& src) {
+  gfx::Insets dst;
+  // Follow element order in gfx::Insets.
+  dst.set_top(src.top);
+  dst.set_left(src.left);
+  dst.set_bottom(src.bottom);
+  dst.set_right(src.right);
+  return dst;
+}
+
+void DeserializeInsets(const gfx::Insets& src,
+                       extensions::api::system_display::Insets* dst) {
+  // Follow element order in extensions::api::system_display::Insets.
+  dst->left = src.left();
+  dst->top = src.top();
+  dst->right = src.right();
+  dst->bottom = src.bottom();
+}
+
+}  // namespace
+
+// extensions::api::system_display::DisplayMode <==>
+//     crosapi::mojom::DisplayMode.
+
+crosapi::mojom::DisplayModePtr SerializeDisplayMode(
+    const extensions::api::system_display::DisplayMode& src) {
+  auto dst = crosapi::mojom::DisplayMode::New();
+  dst->size = SerializeSize(src.width, src.height);
+  dst->size_in_native_pixels =
+      SerializeSize(src.width_in_native_pixels, src.height_in_native_pixels);
+  dst->device_scale_factor = src.device_scale_factor;
+  dst->refresh_rate = src.refresh_rate;
+  dst->is_native = src.is_native;
+  dst->is_selected = src.is_selected;
+  SerializeOptionalPrimitive<bool>(src.is_interlaced, &dst->has_is_interlaced,
+                                   &dst->is_interlaced);
+  return dst;
+}
+
+void DeserializeDisplayMode(const crosapi::mojom::DisplayMode& src,
+                            extensions::api::system_display::DisplayMode* dst) {
+  DeserializeSize(src.size, &dst->width, &dst->height);
+  DeserializeSize(src.size_in_native_pixels, &dst->width_in_native_pixels,
+                  &dst->height_in_native_pixels);
+  dst->device_scale_factor = src.device_scale_factor;
+  dst->refresh_rate = src.refresh_rate;
+  dst->is_native = src.is_native;
+  dst->is_selected = src.is_selected;
+  DeserializeOptionalPrimitive<bool>(src.has_is_interlaced, src.is_interlaced,
+                                     &dst->is_interlaced);
+}
+
+// extensions::api::system_display::Edid <==> crosapi::mojom::Edid.
+
+crosapi::mojom::EdidPtr SerializeEdid(
+    const extensions::api::system_display::Edid& src) {
+  auto dst = crosapi::mojom::Edid::New();
+  dst->manufacturer_id = src.manufacturer_id;
+  dst->product_id = src.product_id;
+  dst->year_of_manufacture = src.year_of_manufacture;
+  return dst;
+}
+
+void DeserializeEdid(const crosapi::mojom::Edid& src,
+                     extensions::api::system_display::Edid* dst) {
+  dst->manufacturer_id = src.manufacturer_id;
+  dst->product_id = src.product_id;
+  dst->year_of_manufacture = src.year_of_manufacture;
+}
+
+// extensions::api::system_display::DisplayUnitInfo <==>
+//     crosapi::mojom::DisplayUnitInfo.
+
+crosapi::mojom::DisplayUnitInfoPtr SerializeDisplayUnitInfo(
+    const extensions::api::system_display::DisplayUnitInfo& src) {
+  auto dst = crosapi::mojom::DisplayUnitInfo::New();
+  dst->id = src.id;
+  dst->name = src.name;
+  if (src.edid)
+    dst->edid = SerializeEdid(*src.edid);
+  dst->mirroring_source_id = src.mirroring_source_id;
+  dst->mirroring_destination_ids = src.mirroring_destination_ids;
+  dst->is_primary = src.is_primary;
+  dst->is_internal = src.is_internal;
+  dst->is_enabled = src.is_enabled;
+  dst->is_unified = src.is_unified;
+  SerializeOptionalPrimitive<bool>(src.is_in_tablet_physical_state,
+                                   &dst->has_is_in_tablet_physical_state,
+                                   &dst->is_in_tablet_physical_state);
+  dst->dpi_x = src.dpi_x;
+  dst->dpi_y = src.dpi_y;
+  dst->rotation = src.rotation;
+  dst->bounds_as_rect = SerializeBoundsAsRect(src.bounds);
+  dst->overscan = SerializeInsets(src.overscan);
+  dst->work_area_as_rect = SerializeBoundsAsRect(src.work_area);
+  dst->display_zoom_factor = src.display_zoom_factor;
+  for (const auto& src_mode : src.modes) {
+    dst->modes.emplace_back(SerializeDisplayMode(src_mode));
+  }
+  dst->has_touch_support = src.has_touch_support;
+  dst->has_accelerometer_support = src.has_accelerometer_support;
+  dst->available_display_zoom_factors = src.available_display_zoom_factors;
+  dst->display_zoom_factor = src.display_zoom_factor;
+  return dst;
+}
+
+void DeserializeDisplayUnitInfo(
+    const crosapi::mojom::DisplayUnitInfo& src,
+    extensions::api::system_display::DisplayUnitInfo* dst) {
+  dst->id = src.id;
+  dst->name = src.name;
+  if (src.edid) {
+    dst->edid = std::make_unique<extensions::api::system_display::Edid>();
+    DeserializeEdid(*src.edid, dst->edid.get());
+  }
+  dst->mirroring_source_id = src.mirroring_source_id;
+  dst->mirroring_destination_ids = src.mirroring_destination_ids;
+  dst->is_primary = src.is_primary;
+  dst->is_internal = src.is_internal;
+  dst->is_enabled = src.is_enabled;
+  dst->is_unified = src.is_unified;
+  DeserializeOptionalPrimitive<bool>(src.has_is_in_tablet_physical_state,
+                                     src.is_in_tablet_physical_state,
+                                     &dst->is_in_tablet_physical_state);
+  dst->dpi_x = src.dpi_x;
+  dst->dpi_y = src.dpi_y;
+  dst->rotation = src.rotation;
+  DeserializeRectToBounds(src.bounds_as_rect, &dst->bounds);
+  DeserializeInsets(src.overscan, &dst->overscan);
+  DeserializeRectToBounds(src.work_area_as_rect, &dst->work_area);
+  dst->display_zoom_factor = src.display_zoom_factor;
+  dst->modes.resize(src.modes.size());
+  for (size_t i = 0; i < src.modes.size(); ++i) {
+    DeserializeDisplayMode(*src.modes[i], &dst->modes[i]);
+  }
+  dst->has_touch_support = src.has_touch_support;
+  dst->has_accelerometer_support = src.has_accelerometer_support;
+  dst->available_display_zoom_factors = src.available_display_zoom_factors;
+  dst->display_zoom_factor = src.display_zoom_factor;
+}
+
+}  // namespace system_display
+}  // namespace api
+}  // namespace extensions
diff --git a/chrome/browser/extensions/system_display/system_display_serialization.h b/chrome/browser/extensions/system_display/system_display_serialization.h
new file mode 100644
index 0000000..a2bc26a
--- /dev/null
+++ b/chrome/browser/extensions/system_display/system_display_serialization.h
@@ -0,0 +1,88 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_SYSTEM_DISPLAY_SYSTEM_DISPLAY_SERIALIZATION_H_
+#define CHROME_BROWSER_EXTENSIONS_SYSTEM_DISPLAY_SYSTEM_DISPLAY_SERIALIZATION_H_
+
+#include "base/component_export.h"
+#include "chromeos/crosapi/mojom/system_display.mojom.h"
+
+// This file declares utilities to serialize / deserialize system_display.idl
+// structs under
+//   extensions::api::system_display::
+// to / from Stable crosapi Mojo system_display structs under
+//   crosapi::mojom::
+// which needs to be Stable and need to handle version skew.
+
+// Approach: Use serialize / deserialize function pairs:
+// * Serialize: Converts extensions::api::system_display objects to
+//   crosapi::mojom (include possible StructTrait mapped) objects. The results
+//   are returned by value, or are allocated and returned as Mojo Ptr.
+// * Deserialize: Reads crosapi::mojom (include possible StructTraits mapped)
+//   objects and writes to extensions::api::system_display objects or fields.
+//   The deserialized objects are written via |dst| pointer(s), to accommodate a
+//   wider variety of deserialized values. Also, it's the caller's
+//   responsibility to check the presence of serialized |src| data, and allocate
+//   |dst| data as needed.
+
+// Rejected alternatives:
+// * Use extensions::api::system_display objects' generated ToValue() and
+//   FromValue() functions: Unfortunately, FromValue() is unforgiving, so it
+//   won't handle version skews. If a less stringent API becomes available
+//   (e.g., FromValueAllowMissing()) then we can revisit this alternative.
+// * Use ash/public/mojom/cros_display_config.mojom: These are not meant to be
+//   Stable, and deviate from system_display.idl.
+// * Use StructTraits to map crosapi Mojo to extensions::api::system_display::
+//   objects: This is viable, but the resulting code can be bulky. The function
+//   pair approach is more direct (i.e., less prone to leakage of abstraction),
+//   and allows matching serialization / deserialization code to be in
+//   close proximity, so future modifications and version skew handling code
+//   can be better juxtaposed.
+
+namespace extensions {
+namespace api {
+namespace system_display {
+
+struct DisplayMode;
+struct DisplayUnitInfo;
+struct Edid;
+
+// extensions::api::system_display::DisplayMode <==>
+//     crosapi::mojom::DisplayMode.
+
+COMPONENT_EXPORT(CROSAPI)
+crosapi::mojom::DisplayModePtr SerializeDisplayMode(
+    const extensions::api::system_display::DisplayMode& src);
+
+COMPONENT_EXPORT(CROSAPI)
+void DeserializeDisplayMode(const crosapi::mojom::DisplayMode& src,
+                            extensions::api::system_display::DisplayMode* dst);
+
+// extensions::api::system_display::Edid <==> crosapi::mojom::Edid.
+
+COMPONENT_EXPORT(CROSAPI)
+crosapi::mojom::EdidPtr SerializeEdid(
+    const extensions::api::system_display::Edid& src);
+
+COMPONENT_EXPORT(CROSAPI)
+void DeserializeEdid(const crosapi::mojom::Edid& src,
+                     extensions::api::system_display::Edid* dst);
+
+// extensions::api::system_display::DisplayUnitInfo <==>
+//     crosapi::mojom::DisplayUnitInfo.
+
+COMPONENT_EXPORT(CROSAPI)
+crosapi::mojom::DisplayUnitInfoPtr SerializeDisplayUnitInfo(
+    const extensions::api::system_display::DisplayUnitInfo& src);
+
+COMPONENT_EXPORT(CROSAPI)
+void DeserializeDisplayUnitInfo(
+    const crosapi::mojom::DisplayUnitInfo& src,
+    extensions::api::system_display::DisplayUnitInfo* dst);
+
+}  // namespace system_display
+}  // namespace api
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_SYSTEM_DISPLAY_SYSTEM_DISPLAY_SERIALIZATION_H_
diff --git a/chrome/browser/extensions/system_display/system_display_serialization_unittest.cc b/chrome/browser/extensions/system_display/system_display_serialization_unittest.cc
new file mode 100644
index 0000000..e8e4506
--- /dev/null
+++ b/chrome/browser/extensions/system_display/system_display_serialization_unittest.cc
@@ -0,0 +1,228 @@
+// 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 <memory>
+#include <string>
+#include <vector>
+
+#include "base/json/json_parser.h"
+#include "base/json/json_string_value_serializer.h"
+#include "base/strings/strcat.h"
+#include "base/strings/string_util.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/system_display/system_display_serialization.h"
+#include "chromeos/crosapi/mojom/system_display.mojom.h"
+#include "extensions/common/api/system_display.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// Converts |obj| to a JSON string, assuming T::ToValue() is defined.
+template <class T>
+std::string ObjectToString(const T& obj) {
+  std::unique_ptr<base::Value> value = obj.ToValue();
+  std::string json_string;
+  JSONStringValueSerializer serializer(&json_string);
+  EXPECT_TRUE(serializer.Serialize(*value));
+  return json_string;
+}
+
+// Converts JSON string to |obj|, assuming static T::FromValue() is defined.
+template <class T>
+std::unique_ptr<T> StringToObject(const std::string& json_string) {
+  JSONStringValueDeserializer deserializer(json_string);
+  int err_code = 0;
+  std::string err_message;
+  std::unique_ptr<base::Value> value =
+      deserializer.Deserialize(&err_code, &err_message);
+  EXPECT_EQ(base::ValueDeserializer::kErrorCodeNoError, err_code)
+      << "Unexpected error: " << err_message;
+  EXPECT_NE(nullptr, value.get());
+  std::unique_ptr<T> obj = T::FromValue(*value);
+  EXPECT_NE(nullptr, obj.get());
+  return obj;
+}
+
+// Returns a valid JSON string by concatenating a list of strings while making
+// the following transforms:
+// * Remove all prettifying double spaces.
+// * Replace all prettifying "'" with "\"",
+// * If |include_optional == false| the ignore all lines starting with "??".
+//   Otherwise just strip "??".
+std::string MakeJsonString(const std::vector<std::string>& lines,
+                           bool include_optional) {
+  std::vector<std::string> used_lines;
+  for (const std::string& line : lines) {
+    if (include_optional || line.substr(0, 2) != "??")
+      used_lines.push_back(line);
+  }
+  std::string ret = base::StrCat(used_lines);
+  base::ReplaceSubstringsAfterOffset(&ret, 0, "??", "");
+  base::ReplaceSubstringsAfterOffset(&ret, 0, "'", "\"");
+  base::ReplaceSubstringsAfterOffset(&ret, 0, "  ", "");
+  return ret;
+}
+
+}  // namespace
+
+namespace extensions {
+namespace api {
+namespace system_display {
+
+// This test fails if extensions::api::system_display::DisplayMode changes.
+// To fix, update |original_json_string|, and fix SerializeDisplayMode() and
+// DeserializeDisplayMode().
+TEST(SystemDisplaySerialization, DisplayMode) {
+  std::vector<std::string> test_lines = {
+      "{",
+      "  'deviceScaleFactor':3.14159,",
+      "  'height':487,",
+      "  'heightInNativePixels':512,",
+      "??'isInterlaced':true,",
+      "  'isNative':true,",
+      "  'isSelected':true,",
+      "  'refreshRate':59.5,",
+      "  'width':640,",
+      "  'widthInNativePixels':671",
+      "}",
+  };
+
+  for (int iter = 0; iter < 2; ++iter) {
+    std::string original_json_string =
+        MakeJsonString(test_lines, /*include_optional=*/iter > 0);
+    auto original_obj = StringToObject<DisplayMode>(original_json_string);
+    crosapi::mojom::DisplayModePtr serialized_obj =
+        SerializeDisplayMode(*original_obj);
+    DisplayMode copied_obj;
+    DeserializeDisplayMode(*serialized_obj, &copied_obj);
+    std::string copied_json_string = ObjectToString(copied_obj);
+
+    EXPECT_EQ(original_json_string, copied_json_string);
+  }
+}
+
+// This test fails if extensions::api::system_display::Edid changes. To fix,
+// update |original_json_string|, and fix SerializeEdid() and DeserializeEdid().
+TEST(SystemDisplaySerialization, Edid) {
+  std::vector<std::string> test_lines = {
+      "{",
+      "  'manufacturerId':'ACME Display 3000',",
+      "  'productId':'ABC-123-XYZ',",
+      "  'yearOfManufacture':2038",
+      "}",
+  };
+
+  std::string original_json_string = MakeJsonString(test_lines, true);
+  auto original_obj = StringToObject<Edid>(original_json_string);
+  crosapi::mojom::EdidPtr serialized_obj = SerializeEdid(*original_obj);
+  Edid copied_obj;
+  DeserializeEdid(*serialized_obj, &copied_obj);
+  std::string copied_json_string = ObjectToString(copied_obj);
+
+  EXPECT_EQ(original_json_string, copied_json_string);
+}
+
+// This test fails if extensions::api::system_display::DisplayUnitInfo changes.
+// To fix, update |original_json_string|, and fix  SerializeDisplayUnitInfo()
+// and DeserializeDisplayUnitInfo().
+TEST(SystemDisplaySerialization, DisplayUnitInfo) {
+  // Prettified lines used to create test cases. This was created by first
+  // taking the output form running the following:
+  //
+  //   LOG(ERROR) << ObjectToString(DisplayUnitInfo());
+  //
+  // followed by populating lists and adding optional fields, obtained by
+  // inspecting system_display.idl.
+  std::vector<std::string> test_lines = {
+      "{",
+      "  'availableDisplayZoomFactors':[",
+      "??  0.8,",
+      "??  1.2,",
+      "??  1.0",
+      "  ],",
+      "  'bounds':{",
+      "    'height':749,",
+      "    'left':7,",
+      "    'top':11,",
+      "    'width':1024",
+      "  },",
+      "  'displayZoomFactor':1.0,",
+      "  'dpiX':90.0,",
+      "  'dpiY':88.25,",
+      "??'edid':{",
+      "??  'manufacturerId':'ACME Display 3000',",
+      "??  'productId':'ABC-123-XYZ',",
+      "??  'yearOfManufacture':2038",
+      "??},",
+      "  'hasAccelerometerSupport':true,",
+      "  'hasTouchSupport':true,",
+      "  'id':'AWESOME-display-ID',",
+      "  'isEnabled':true,",
+      "??'isInTabletPhysicalState':true,",
+      "  'isInternal':true,",
+      "  'isPrimary':true,",
+      "  'isUnified':true,",
+      "  'mirroringDestinationIds':[",
+      "    'DEST-ID-2',",
+      "    'DEST-ID-1',",
+      "    'DEST-ID-3'",
+      "  ],",
+      "  'mirroringSourceId':'SOURCE-ID-0',",
+      "  'modes':[",
+      "??  {",
+      "??    'deviceScaleFactor':3.14159,",
+      "??    'height':487,",
+      "??    'heightInNativePixels':512,",
+      "??    'isNative':true,",
+      "??    'isSelected':true,",
+      "??    'refreshRate':59.5,",
+      "??    'width':640,",
+      "??    'widthInNativePixels':671",
+      "??  },",
+      "??  {",
+      "??    'deviceScaleFactor':2.71828,",
+      "??    'height':30,",
+      "??    'heightInNativePixels':30,",
+      "??    'isInterlaced':true,",
+      "??    'isNative':false,",
+      "??    'isSelected':false,",
+      "??    'refreshRate':122.0,",
+      "??    'width':50,",
+      "??    'widthInNativePixels':50",
+      "??  }",
+      "  ],",
+      "  'name':'Display--123456789',",
+      "  'overscan':{",
+      "    'bottom':6,",
+      "    'left':7,",
+      "    'right':8,",
+      "    'top':9",
+      "  },",
+      "  'rotation':90,",
+      "  'workArea':{",
+      "    'height':300,",
+      "    'left':11,",
+      "    'top':23,",
+      "    'width':400",
+      "  }",
+      "}",
+  };
+
+  for (int iter = 0; iter < 2; ++iter) {
+    std::string original_json_string =
+        MakeJsonString(test_lines, /*include_optional=*/iter > 0);
+    auto original_obj = StringToObject<DisplayUnitInfo>(original_json_string);
+    crosapi::mojom::DisplayUnitInfoPtr serialized_obj =
+        SerializeDisplayUnitInfo(*original_obj);
+    DisplayUnitInfo copied_obj;
+    DeserializeDisplayUnitInfo(*serialized_obj, &copied_obj);
+    std::string copied_json_string = ObjectToString(copied_obj);
+
+    EXPECT_EQ(original_json_string, copied_json_string);
+  }
+}
+
+}  // namespace system_display
+}  // namespace api
+}  // namespace extensions
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedDialogCoordinator.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedDialogCoordinator.java
index 80e5ad3..d0fe906f 100644
--- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedDialogCoordinator.java
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedDialogCoordinator.java
@@ -13,6 +13,7 @@
 import android.view.View;
 
 import org.chromium.base.Callback;
+import org.chromium.chrome.browser.feed.webfeed.WebFeedSnackbarController.FeedLauncher;
 import org.chromium.ui.modaldialog.DialogDismissalCause;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 import org.chromium.ui.modelutil.PropertyModel;
@@ -39,14 +40,15 @@
      * Initializes the {@link WebFeedDialogCoordinator}.
      *
      * @param context The {@link Context}.
+     * @param feedLauncher {@link FeedLauncher} for launching the NTP.
      * @param title The title of the site that was just followed.
      * @param isActive Whether the followed site is active (has content available).
      */
-    void initialize(Context context, String title, boolean isActive) {
+    void initialize(Context context, FeedLauncher feedLauncher, String title, boolean isActive) {
         mContext = context;
         View webFeedDialogView =
                 LayoutInflater.from(context).inflate(R.layout.web_feed_dialog, null);
-        WebFeedDialogContents dialogContents = buildDialogContents(isActive, title);
+        WebFeedDialogContents dialogContents = buildDialogContents(feedLauncher, isActive, title);
         PropertyModel model = buildModel(dialogContents);
         mMediator.initialize(webFeedDialogView, dialogContents);
         PropertyModelChangeProcessor.create(
@@ -57,7 +59,8 @@
         mMediator.showDialog();
     }
 
-    private WebFeedDialogContents buildDialogContents(boolean isActive, String title) {
+    private WebFeedDialogContents buildDialogContents(
+            FeedLauncher feedLauncher, boolean isActive, String title) {
         String description;
         String primaryButtonText;
         String secondaryButtonText;
@@ -70,7 +73,7 @@
             secondaryButtonText = mContext.getString(R.string.close);
             buttonClickCallback = dismissalCause -> {
                 if (dismissalCause.equals(DialogDismissalCause.POSITIVE_BUTTON_CLICKED)) {
-                    // TODO(crbug.com/1152592): Implement go to feed.
+                    feedLauncher.openFeed();
                 }
             };
         } else {
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroController.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroController.java
index 7b6dd24..470c763 100644
--- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroController.java
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroController.java
@@ -14,6 +14,7 @@
 
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
+import org.chromium.chrome.browser.feed.webfeed.WebFeedSnackbarController.FeedLauncher;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.Pref;
@@ -84,18 +85,19 @@
      * @param activity The current {@link Activity}.
      * @param tabSupplier The supplier for the currently active {@link Tab}.
      * @param menuButtonAnchorView The menu button {@link View} to serve as an anchor.
+     * @param feedLauncher The {@link FeedLauncher} to launch the feed.
      * @param dialogManager {@link ModalDialogManager} for managing the dialog.
      * @param snackbarManager The {@link SnackbarManager} to show snackbars.
      * @param webFeedBridge The {@link WebFeedBridge} to connect to the Web Feed backend.
      */
     public WebFeedFollowIntroController(Activity activity, ObservableSupplier<Tab> tabSupplier,
-            View menuButtonAnchorView, ModalDialogManager dialogManager,
+            View menuButtonAnchorView, FeedLauncher feedLauncher, ModalDialogManager dialogManager,
             SnackbarManager snackbarManager, WebFeedBridge webFeedBridge) {
         mActivity = activity;
         mFeatureEngagementTracker =
                 TrackerFactory.getTrackerForProfile(Profile.getLastUsedRegularProfile());
         mWebFeedSnackbarController = new WebFeedSnackbarController(
-                activity, dialogManager, snackbarManager, webFeedBridge);
+                activity, feedLauncher, dialogManager, snackbarManager, webFeedBridge);
         mWebFeedFollowIntroView = new WebFeedFollowIntroView(mActivity, menuButtonAnchorView);
 
         mAppearanceThresholdMs = TimeUnit.MINUTES.toMillis(
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItem.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItem.java
index 9644b67b..efed3a9 100644
--- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItem.java
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItem.java
@@ -19,6 +19,7 @@
 import androidx.annotation.Nullable;
 
 import org.chromium.chrome.browser.feed.webfeed.WebFeedBridge.WebFeedMetadata;
+import org.chromium.chrome.browser.feed.webfeed.WebFeedSnackbarController.FeedLauncher;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuHandler;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.components.browser_ui.widget.RoundedIconGenerator;
@@ -66,20 +67,21 @@
      *
      * @param url {@link GURL} of the page.
      * @param appMenuHandler {@link AppMenuHandler} to control hiding the app menu.
+     * @param feedLauncher {@link FeedLauncher}
      * @param largeIconBridge {@link LargeIconBridge} to get the favicon of the page.
      * @param dialogManager {@link ModalDialogManager} for managing the dialog.
      * @param snackbarManager {@link SnackbarManager} to display snackbars.
      * @param webFeedBridge {@link WebFeedBridge} to display the menu item and follow/unfollow.
      */
     public void initialize(GURL url, AppMenuHandler appMenuHandler, LargeIconBridge largeIconBridge,
-            ModalDialogManager dialogManager, SnackbarManager snackbarManager,
-            WebFeedBridge webFeedBridge) {
+            FeedLauncher feedLauncher, ModalDialogManager dialogManager,
+            SnackbarManager snackbarManager, WebFeedBridge webFeedBridge) {
         mUrl = url;
         mAppMenuHandler = appMenuHandler;
         mLargeIconBridge = largeIconBridge;
         mWebFeedBridge = webFeedBridge;
         mWebFeedSnackbarController = new WebFeedSnackbarController(
-                mContext, dialogManager, snackbarManager, webFeedBridge);
+                mContext, feedLauncher, dialogManager, snackbarManager, webFeedBridge);
 
         initializeFavicon();
         mWebFeedBridge.getWebFeedMetadataForPage(mUrl, result -> {
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarController.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarController.java
index fa330a5..581c202 100644
--- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarController.java
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarController.java
@@ -15,11 +15,24 @@
 import org.chromium.ui.modaldialog.ModalDialogManager;
 import org.chromium.url.GURL;
 
+import java.util.concurrent.TimeUnit;
+
 /**
  * Controller for showing Web Feed snackbars.
  */
-class WebFeedSnackbarController {
+public class WebFeedSnackbarController {
+    /**
+     * A helper interface for exposing a method to launch the feed.
+     */
+    @FunctionalInterface
+    public interface FeedLauncher {
+        void openFeed();
+    }
+
+    static final int SNACKBAR_DURATION_MS = (int) TimeUnit.SECONDS.toMillis(8);
+
     private final Context mContext;
+    private final FeedLauncher mFeedLauncher;
     private final SnackbarManager mSnackbarManager;
     private final WebFeedDialogCoordinator mWebFeedDialogCoordinator;
     private final WebFeedBridge mWebFeedBridge;
@@ -28,13 +41,16 @@
      * Constructs an instance of {@link WebFeedSnackbarController}.
      *
      * @param context The {@link Context} to retrieve strings for the snackbars.
+     * @param feedLauncher The {@link FeedLauncher} to launch the feed.
      * @param dialogManager {@link ModalDialogManager} for managing the dialog.
      * @param snackbarManager {@link SnackbarManager} to manage the snackbars.
      * @param webFeedBridge {@link WebFeedBridge} to connect with the backend to follow/unfollow.
      */
-    WebFeedSnackbarController(Context context, ModalDialogManager dialogManager,
-            SnackbarManager snackbarManager, WebFeedBridge webFeedBridge) {
+    WebFeedSnackbarController(Context context, FeedLauncher feedLauncher,
+            ModalDialogManager dialogManager, SnackbarManager snackbarManager,
+            WebFeedBridge webFeedBridge) {
         mContext = context;
+        mFeedLauncher = feedLauncher;
         mSnackbarManager = snackbarManager;
         mWebFeedDialogCoordinator = new WebFeedDialogCoordinator(dialogManager);
         mWebFeedBridge = webFeedBridge;
@@ -78,13 +94,13 @@
         if (TrackerFactory.getTrackerForProfile(Profile.getLastUsedRegularProfile())
                         .shouldTriggerHelpUI(
                                 FeatureConstants.IPH_WEB_FEED_POST_FOLLOW_DIALOG_FEATURE)) {
-            mWebFeedDialogCoordinator.initialize(mContext, title, isActive);
+            mWebFeedDialogCoordinator.initialize(mContext, mFeedLauncher, title, isActive);
             mWebFeedDialogCoordinator.showDialog();
         } else {
             SnackbarController snackbarController = new SnackbarController() {
                 @Override
                 public void onAction(Object actionData) {
-                    // TODO(crbug/1152592): Implement go to feed.
+                    mFeedLauncher.openFeed();
                 }
             };
             showSnackbar(
@@ -125,7 +141,8 @@
         Snackbar snackbar =
                 Snackbar.make(message, snackbarController, Snackbar.TYPE_ACTION, umaId)
                         .setAction(mContext.getString(snackbarActionId), /*actionData=*/null)
-                        .setSingleLine(false);
+                        .setSingleLine(false)
+                        .setDuration(SNACKBAR_DURATION_MS);
         mSnackbarManager.showSnackbar(snackbar);
     }
 
diff --git a/chrome/browser/feed/android/javatests/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroControllerTest.java b/chrome/browser/feed/android/javatests/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroControllerTest.java
index e20ab3c..6a4c185 100644
--- a/chrome/browser/feed/android/javatests/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroControllerTest.java
+++ b/chrome/browser/feed/android/javatests/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroControllerTest.java
@@ -36,6 +36,7 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
+import org.chromium.chrome.browser.feed.webfeed.WebFeedSnackbarController.FeedLauncher;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
@@ -60,6 +61,8 @@
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
 
     @Mock
+    FeedLauncher mFeedLauncher;
+    @Mock
     private ObservableSupplier<Tab> mTabSupplier;
     @Mock
     private Tracker mTracker;
@@ -99,7 +102,7 @@
 
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             mWebFeedFollowIntroController = new WebFeedFollowIntroController(mActivity,
-                    mTabSupplier, mActivity.getToolbarManager().getMenuButtonView(),
+                    mTabSupplier, mActivity.getToolbarManager().getMenuButtonView(), mFeedLauncher,
                     mActivity.getModalDialogManager(), mActivity.getSnackbarManager(),
                     mWebFeedBridge);
         });
diff --git a/chrome/browser/feed/android/javatests/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItemTest.java b/chrome/browser/feed/android/javatests/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItemTest.java
index 0b78450..661e1c8 100644
--- a/chrome/browser/feed/android/javatests/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItemTest.java
+++ b/chrome/browser/feed/android/javatests/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItemTest.java
@@ -33,6 +33,7 @@
 import org.chromium.base.test.UiThreadTest;
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.chrome.browser.feed.webfeed.WebFeedSnackbarController.FeedLauncher;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuHandler;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
@@ -57,6 +58,8 @@
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
 
     @Mock
+    private FeedLauncher mFeedLauncher;
+    @Mock
     private WebFeedBridge mWebFeedBridge;
 
     private static final Bitmap ICON = Bitmap.createBitmap(48, 84, Bitmap.Config.ALPHA_8);
@@ -118,7 +121,8 @@
     @UiThreadTest
     public void initialize_emptyUrl_removesIcon() {
         mWebFeedMainMenuItem.initialize(GURL.emptyGURL(), mAppMenuHandler,
-                new MockLargeIconBridge(null), mDialogManager, mSnackBarManager, mWebFeedBridge);
+                new MockLargeIconBridge(null), mFeedLauncher, mDialogManager, mSnackBarManager,
+                mWebFeedBridge);
 
         ImageView imageView = mWebFeedMainMenuItem.findViewById(R.id.icon);
         assertEquals("Icon should be gone.", View.GONE, imageView.getVisibility());
@@ -295,7 +299,7 @@
      */
     private void initializeWebFeedMainMenuItem(Bitmap bitmap) {
         mWebFeedMainMenuItem.initialize(TEST_URL, mAppMenuHandler, new MockLargeIconBridge(bitmap),
-                mDialogManager, mSnackBarManager, mWebFeedBridge);
+                mFeedLauncher, mDialogManager, mSnackBarManager, mWebFeedBridge);
     }
 
     /**
diff --git a/chrome/browser/feed/android/javatests/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarControllerTest.java b/chrome/browser/feed/android/javatests/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarControllerTest.java
index c0e45ed7..9a6b0c5 100644
--- a/chrome/browser/feed/android/javatests/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarControllerTest.java
+++ b/chrome/browser/feed/android/javatests/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarControllerTest.java
@@ -30,6 +30,7 @@
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
+import org.chromium.chrome.browser.feed.webfeed.WebFeedSnackbarController.FeedLauncher;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
@@ -53,6 +54,8 @@
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
 
     @Mock
+    private FeedLauncher mFeedLauncher;
+    @Mock
     private Tracker mTracker;
     @Mock
     public WebFeedBridge mWebFeedBridge;
@@ -77,8 +80,8 @@
                 .thenReturn(false);
         TrackerFactory.setTrackerForTests(mTracker);
 
-        mWebFeedSnackbarController = new WebFeedSnackbarController(
-                mActivityTestRule.getActivity(), mDialogManager, mSnackbarManager, mWebFeedBridge);
+        mWebFeedSnackbarController = new WebFeedSnackbarController(mActivityTestRule.getActivity(),
+                mFeedLauncher, mDialogManager, mSnackbarManager, mWebFeedBridge);
     }
 
     @After
@@ -129,6 +132,22 @@
 
     @Test
     @SmallTest
+    public void showSnackbarForFollow_correctDuration() {
+        WebFeedBridge.FollowResults followResults = new WebFeedBridge.FollowResults(
+                WebFeedSubscriptionRequestStatus.SUCCESS, /*metadata=*/null);
+
+        TestThreadUtils.runOnUiThreadBlocking(
+                ()
+                        -> mWebFeedSnackbarController.showPostFollowHelp(
+                                followResults, sFollowId, sTestUrl, sTitle));
+
+        Snackbar snackbar = mSnackbarManager.getCurrentSnackbarForTesting();
+        assertEquals("Snackbar duration for follow should be correct.",
+                WebFeedSnackbarController.SNACKBAR_DURATION_MS, snackbar.getDuration());
+    }
+
+    @Test
+    @SmallTest
     public void showPromoDialogForFollow_successful_active() {
         when(mTracker.shouldTriggerHelpUI(FeatureConstants.IPH_WEB_FEED_POST_FOLLOW_DIALOG_FEATURE))
                 .thenReturn(true);
@@ -304,4 +323,18 @@
         verify(mWebFeedBridge, description("Unfollow should be called on unfollow try again."))
                 .unfollow(eq(sFollowId), any());
     }
+
+    @Test
+    @SmallTest
+    public void showSnackbarForUnfollow_correctDuration() {
+        TestThreadUtils.runOnUiThreadBlocking(
+                ()
+                        -> mWebFeedSnackbarController
+                                   .showSnackbarForUnfollow(/*successfulUnfollow=*/
+                                           true, sFollowId, sTestUrl, sTitle));
+
+        Snackbar snackbar = mSnackbarManager.getCurrentSnackbarForTesting();
+        assertEquals("Snackbar duration for unfollow should be correct.",
+                WebFeedSnackbarController.SNACKBAR_DURATION_MS, snackbar.getDuration());
+    }
 }
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 078fa7b..18593db 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1959,6 +1959,11 @@
     "expiry_milestone": 83
   },
   {
+    "name": "enable-input-noise-cancellation-ui",
+    "owners": [ "swifton@google.com", "cros-peripherals@google.com" ],
+    "expiry_milestone": 98
+  },
+  {
     "name": "enable-instant-start",
     "owners": [ "hanxi", "wychen" ],
     "expiry_milestone": 100
@@ -3926,11 +3931,6 @@
     "expiry_milestone": 99
   },
   {
-    "name": "omnibox-keyword-space-triggering-setting",
-    "owners": [ "yoangela", "chrome-omnibox-team@google.com" ],
-    "expiry_milestone": 99
-  },
-  {
     "name": "omnibox-local-history-zero-suggest",
     "owners": ["rkgibson@google.com", "stkhapugin", "chrome-omnibox-team@google.com"],
     "expiry_milestone": 92
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 2cae537..ec7b9fd02 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1718,12 +1718,6 @@
     "Controls whether keyword mode can be triggered by space, double space, or "
     "neither.";
 
-const char kOmniboxKeywordSpaceTriggeringSettingName[] =
-    "Omnibox Keyword Space Triggering Setting";
-const char kOmniboxKeywordSpaceTriggeringSettingDescription[] =
-    "Adds a setting to the search engines setting page to control whether "
-    "spacebar activates keyword mode.";
-
 const char kOmniboxMostVisitedTilesName[] = "Omnibox Most Visited Tiles";
 const char kOmniboxMostVisitedTilesDescription[] =
     "Display a list of frquently visited pages from history as a single row "
@@ -4284,6 +4278,12 @@
     "Enable additional heuristic palm rejection logic when interacting with "
     "stylus usage. Not intended for all devices.";
 
+const char kEnableInputNoiseCancellationUiName[] =
+    "Enable Input Noise Cancellation UI.";
+const char kEnableInputNoiseCancellationUiDescription[] =
+    "Enable toggling input noise cancellation through the Quick Settings. By "
+    "default, this flag is disabled.";
+
 const char kEnableLauncherSearchNormalizationName[] =
     "Enable normalization of launcher search results";
 const char kEnableLauncherSearchNormalizationDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index a5b00e2..f076992 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -995,9 +995,6 @@
 extern const char kOmniboxKeywordSpaceTriggeringName[];
 extern const char kOmniboxKeywordSpaceTriggeringDescription[];
 
-extern const char kOmniboxKeywordSpaceTriggeringSettingName[];
-extern const char kOmniboxKeywordSpaceTriggeringSettingDescription[];
-
 extern const char kOmniboxExperimentalSuggestScoringName[];
 extern const char kOmniboxExperimentalSuggestScoringDescription[];
 
@@ -2468,6 +2465,9 @@
 extern const char kEnableHeuristicStylusPalmRejectionName[];
 extern const char kEnableHeuristicStylusPalmRejectionDescription[];
 
+extern const char kEnableInputNoiseCancellationUiName[];
+extern const char kEnableInputNoiseCancellationUiDescription[];
+
 extern const char kEnableLauncherSearchNormalizationName[];
 extern const char kEnableLauncherSearchNormalizationDescription[];
 
diff --git a/chrome/browser/policy/messaging_layer/public/report_client.cc b/chrome/browser/policy/messaging_layer/public/report_client.cc
index 79e429f..ae36742 100644
--- a/chrome/browser/policy/messaging_layer/public/report_client.cc
+++ b/chrome/browser/policy/messaging_layer/public/report_client.cc
@@ -53,16 +53,40 @@
 
 }  // namespace
 
+ReportingClient::AsyncStartUploaderRequest::AsyncStartUploaderRequest(
+    Priority priority,
+    bool need_encryption_key,
+    UploaderInterface::UploaderInterfaceResultCb start_uploader_cb)
+    : priority_(priority),
+      need_encryption_key_(need_encryption_key),
+      start_uploader_cb_(std::move(start_uploader_cb)) {}
+ReportingClient::AsyncStartUploaderRequest::~AsyncStartUploaderRequest() =
+    default;
+
+Priority ReportingClient::AsyncStartUploaderRequest::priority() const {
+  return priority_;
+}
+bool ReportingClient::AsyncStartUploaderRequest::need_encryption_key() const {
+  return need_encryption_key_;
+}
+UploaderInterface::UploaderInterfaceResultCb&
+ReportingClient::AsyncStartUploaderRequest::start_uploader_cb() {
+  return start_uploader_cb_;
+}
+
 // Uploader is passed to Storage in order to upload messages using the
 // UploadClient.
 class ReportingClient::Uploader : public UploaderInterface {
  public:
   using UploadCallback =
-      base::OnceCallback<Status(std::unique_ptr<std::vector<EncryptedRecord>>)>;
+      base::OnceCallback<Status(bool,
+                                std::unique_ptr<std::vector<EncryptedRecord>>)>;
 
   static StatusOr<std::unique_ptr<Uploader>> Create(
+      bool need_encryption_key,
       UploadCallback upload_callback) {
-    auto uploader = base::WrapUnique(new Uploader(std::move(upload_callback)));
+    auto uploader = base::WrapUnique(
+        new Uploader(need_encryption_key, std::move(upload_callback)));
     return uploader;
   }
 
@@ -90,7 +114,9 @@
   // Helper class that performs actions, wrapped in SequenceBound by |Uploader|.
   class Helper {
    public:
-    explicit Helper(UploadCallback upload_callback);
+    Helper(bool need_encryption_key, UploadCallback upload_callback);
+    Helper(const Helper& other) = delete;
+    Helper& operator=(const Helper& other) = delete;
     void ProcessRecord(EncryptedRecord data,
                        base::OnceCallback<void(bool)> processed_cb);
     void ProcessGap(SequencingInformation start,
@@ -100,21 +126,25 @@
 
    private:
     bool completed_{false};
+    const bool need_encryption_key_;
     std::unique_ptr<std::vector<EncryptedRecord>> encrypted_records_;
 
     UploadCallback upload_callback_;
   };
 
-  explicit Uploader(UploadCallback upload_callback)
+  Uploader(bool need_encryption_key, UploadCallback upload_callback)
       : helper_(base::ThreadPool::CreateSequencedTaskRunner({}),
+                need_encryption_key,
                 std::move(upload_callback)) {}
 
   base::SequenceBound<Helper> helper_;
 };
 
 ReportingClient::Uploader::Helper::Helper(
+    bool need_encryption_key,
     ReportingClient::Uploader::UploadCallback upload_callback)
-    : encrypted_records_(std::make_unique<std::vector<EncryptedRecord>>()),
+    : need_encryption_key_(need_encryption_key),
+      encrypted_records_(std::make_unique<std::vector<EncryptedRecord>>()),
       upload_callback_(std::move(upload_callback)) {}
 
 void ReportingClient::Uploader::Helper::ProcessRecord(
@@ -156,12 +186,13 @@
   }
   completed_ = true;
   DCHECK(encrypted_records_);
-  if (encrypted_records_->empty()) {
+  if (encrypted_records_->empty() && !need_encryption_key_) {
     return;
   }
   DCHECK(upload_callback_);
   Status upload_status =
-      std::move(upload_callback_).Run(std::move(encrypted_records_));
+      std::move(upload_callback_)
+          .Run(need_encryption_key_, std::move(encrypted_records_));
   if (!upload_status.ok()) {
     LOG(ERROR) << "Unable to upload records: " << upload_status;
   }
@@ -234,17 +265,9 @@
 }
 
 void ReportingClient::ClientInitializingContext::ConfigureStorageModule() {
-  // Storage location in the local file system (if local storage is enabled).
-  base::FilePath user_data_dir;
-  if (!base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
-    Complete(
-        Status(error::FAILED_PRECONDITION, "Could not retrieve base path"));
-    return;
-  }
-  base::FilePath reporting_path = user_data_dir.Append(kReportingDirectory);
-
   StorageSelector::CreateStorageModule(
-      reporting_path, std::move(async_start_upload_cb_),
+      client_->reporting_path_, client_->verification_key_,
+      std::move(async_start_upload_cb_),
       base::BindOnce(&ClientInitializingContext::OnStorageModuleConfigured,
                      base::Unretained(this)));
 }
@@ -297,14 +320,23 @@
   }
   if (upload_client_) {
     DCHECK(!client_->upload_client_) << "Upload client already recorded";
-    client_->upload_client_ = std::move(upload_client_);
+    client_->SetUploadClient(std::move(upload_client_));
   }
   DCHECK(!client_->storage_) << "Storage module already recorded";
   client_->storage_ = std::move(storage_);
 }
 
 ReportingClient::ReportingClient()
-    : build_cloud_policy_client_cb_(GetCloudPolicyClientCb()) {}
+    : verification_key_(SignatureVerifier::VerificationKey()),
+      build_cloud_policy_client_cb_(GetCloudPolicyClientCb()),
+      uploaders_queue_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
+          {base::TaskPriority::BEST_EFFORT, base::MayBlock()})) {
+  // Storage location in the local file system (if local storage is enabled).
+  base::FilePath user_data_dir;
+  DCHECK(base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
+      << "Could not retrieve base path";
+  reporting_path_ = user_data_dir.Append(kReportingDirectory);
+}
 
 ReportingClient::~ReportingClient() = default;
 
@@ -333,18 +365,71 @@
     UploaderInterface::UploaderInterfaceResultCb start_uploader_cb) {
   ReportingClient* const instance =
       static_cast<ReportingClient*>(GetInstance());
-  DCHECK(instance->upload_client_);
-  auto uploader = Uploader::Create(base::BindOnce(
-      &UploadClient::EnqueueUpload,
-      base::Unretained(instance->upload_client_.get()), need_encryption_key));
-  std::move(start_uploader_cb).Run(std::move(uploader));
+  instance->DeliverAsyncStartUploader(priority, need_encryption_key,
+                                      std::move(start_uploader_cb));
+}
+
+void ReportingClient::DeliverAsyncStartUploader(
+    Priority priority,
+    bool need_encryption_key,
+    UploaderInterface::UploaderInterfaceResultCb start_uploader_cb) {
+  uploaders_queue_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          [](Priority priority, bool need_encryption_key,
+             UploaderInterface::UploaderInterfaceResultCb start_uploader_cb,
+             ReportingClient* instance) {
+            if (instance->upload_client_) {
+              auto uploader = Uploader::Create(
+                  need_encryption_key,
+                  base::BindOnce(
+                      &UploadClient::EnqueueUpload,
+                      base::Unretained(instance->upload_client_.get())));
+              std::move(start_uploader_cb).Run(std::move(uploader));
+              return;
+            }
+            // Not set yet. Enqueue it.
+            instance->async_start_uploaders_queue_.emplace(
+                priority, need_encryption_key, std::move(start_uploader_cb));
+          },
+          priority, need_encryption_key, std::move(start_uploader_cb),
+          base::Unretained(this)));
+}
+
+void ReportingClient::FlushAsyncStartUploaderQueue() {
+  // Executed on sequential task runner.
+  while (!async_start_uploaders_queue_.empty()) {
+    auto& request = async_start_uploaders_queue_.front();
+    auto uploader = Uploader::Create(
+        request.need_encryption_key(),
+        base::BindOnce(&UploadClient::EnqueueUpload,
+                       base::Unretained(upload_client_.get())));
+    std::move(request.start_uploader_cb()).Run(std::move(uploader));
+    async_start_uploaders_queue_.pop();
+  }
+}
+
+void ReportingClient::SetUploadClient(
+    std::unique_ptr<UploadClient> upload_client) {
+  // This can only happen once.
+  DCHECK(!upload_client_);
+  upload_client_ = std::move(upload_client);
+  uploaders_queue_task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&ReportingClient::FlushAsyncStartUploaderQueue,
+                                base::Unretained(this)));
 }
 
 ReportingClient::TestEnvironment::TestEnvironment(
+    const base::FilePath& reporting_path,
+    base::StringPiece verification_key,
     policy::CloudPolicyClient* client)
     : saved_build_cloud_policy_client_cb_(
           std::move(static_cast<ReportingClient*>(GetInstance())
                         ->build_cloud_policy_client_cb_)) {
+  static_cast<ReportingClient*>(GetInstance())->reporting_path_ =
+      reporting_path;
+  static_cast<ReportingClient*>(GetInstance())->verification_key_ =
+      std::string(verification_key);
   static_cast<ReportingClient*>(GetInstance())->build_cloud_policy_client_cb_ =
       base::BindRepeating(
           [](policy::CloudPolicyClient* client,
diff --git a/chrome/browser/policy/messaging_layer/public/report_client.h b/chrome/browser/policy/messaging_layer/public/report_client.h
index a07c908..c6bbe7a0 100644
--- a/chrome/browser/policy/messaging_layer/public/report_client.h
+++ b/chrome/browser/policy/messaging_layer/public/report_client.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_POLICY_MESSAGING_LAYER_PUBLIC_REPORT_CLIENT_H_
 
 #include <memory>
+#include <queue>
 #include <utility>
 
 #include "base/memory/singleton.h"
@@ -88,11 +89,14 @@
   StatusOr<std::unique_ptr<ReportQueue>> CreateNewQueue(
       std::unique_ptr<ReportQueueConfiguration> config) override;
 
-  // RAII class for testing ReportingClient - substitutes a cloud policy client
-  // builder to return given client and resets it when destructed.
+  // RAII class for testing ReportingClient - substitutes reporting files
+  // location, signature verification public key and a cloud policy client
+  // builder to return given client. Resets client when destructed.
   class TestEnvironment {
    public:
-    explicit TestEnvironment(policy::CloudPolicyClient* client);
+    TestEnvironment(const base::FilePath& reporting_path,
+                    base::StringPiece verification_key,
+                    policy::CloudPolicyClient* client);
     TestEnvironment(const TestEnvironment& other) = delete;
     TestEnvironment& operator=(const TestEnvironment& other) = delete;
     ~TestEnvironment();
@@ -108,6 +112,30 @@
 
  private:
   class Uploader;
+
+  // Request for async start uploader (to be held in queue until upload_client
+  // is set).
+  class AsyncStartUploaderRequest {
+   public:
+    AsyncStartUploaderRequest(
+        Priority priority,
+        bool need_encryption_key,
+        UploaderInterface::UploaderInterfaceResultCb start_uploader_cb);
+    AsyncStartUploaderRequest(const AsyncStartUploaderRequest& other) = delete;
+    AsyncStartUploaderRequest& operator=(
+        const AsyncStartUploaderRequest& other) = delete;
+    ~AsyncStartUploaderRequest();
+
+    Priority priority() const;
+    bool need_encryption_key() const;
+    UploaderInterface::UploaderInterfaceResultCb& start_uploader_cb();
+
+   private:
+    const Priority priority_;
+    const bool need_encryption_key_;
+    UploaderInterface::UploaderInterfaceResultCb start_uploader_cb_;
+  };
+
   friend class TestEnvironment;
   friend class ReportQueueProvider;
   friend struct base::DefaultSingletonTraits<ReportingClient>;
@@ -130,6 +158,17 @@
       bool need_encryption_key,
       UploaderInterface::UploaderInterfaceResultCb start_uploader_cb);
 
+  void DeliverAsyncStartUploader(
+      Priority priority,
+      bool need_encryption_key,
+      UploaderInterface::UploaderInterfaceResultCb start_uploader_cb);
+
+  void FlushAsyncStartUploaderQueue();
+
+  void SetUploadClient(std::unique_ptr<UploadClient> upload_client);
+
+  base::FilePath reporting_path_;
+  std::string verification_key_;
   GetCloudPolicyClientCallback build_cloud_policy_client_cb_;
 
   // TODO(chromium:1078512) Passing around a raw pointer is unsafe. Wrap
@@ -137,6 +176,12 @@
   policy::CloudPolicyClient* cloud_policy_client_ = nullptr;
   std::unique_ptr<UploadClient> upload_client_;
   scoped_refptr<StorageModuleInterface> storage_;
+
+  // Queue of async start uploader requests protected by sequenced task runner.
+  // When new request is posted, upload_client_ might be not set yet; in that
+  // case it is added to the queue and executed only once upload_client_ is set.
+  std::queue<AsyncStartUploaderRequest> async_start_uploaders_queue_;
+  scoped_refptr<base::SequencedTaskRunner> uploaders_queue_task_runner_;
 };
 }  // namespace reporting
 
diff --git a/chrome/browser/policy/messaging_layer/public/report_client_unittest.cc b/chrome/browser/policy/messaging_layer/public/report_client_unittest.cc
index 0bea165..095c963 100644
--- a/chrome/browser/policy/messaging_layer/public/report_client_unittest.cc
+++ b/chrome/browser/policy/messaging_layer/public/report_client_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/policy/messaging_layer/public/report_client.h"
 
+#include "base/base64.h"
+#include "base/files/scoped_temp_dir.h"
 #include "base/memory/singleton.h"
 #include "base/task/post_task.h"
 #include "base/test/scoped_feature_list.h"
@@ -14,6 +16,11 @@
 #include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
 #include "components/reporting/client/report_queue_configuration.h"
 #include "components/reporting/client/report_queue_provider.h"
+#include "components/reporting/encryption/decryption.h"
+#include "components/reporting/encryption/encryption_module_interface.h"
+#include "components/reporting/encryption/primitives.h"
+#include "components/reporting/encryption/testing_primitives.h"
+#include "components/reporting/encryption/verification.h"
 #include "components/reporting/proto/record_constants.pb.h"
 #include "components/reporting/util/status.h"
 #include "components/reporting/util/status_macros.h"
@@ -31,6 +38,7 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 using ::testing::_;
+using ::testing::Eq;
 using ::testing::Invoke;
 using ::testing::Ne;
 using ::testing::SizeIs;
@@ -39,9 +47,10 @@
 namespace reporting {
 namespace {
 
-class ReportClientTest : public testing::Test {
- public:
+class ReportClientTest : public ::testing::TestWithParam<bool> {
+ protected:
   void SetUp() override {
+    ASSERT_TRUE(location_.CreateUniqueTempDir());
 #if BUILDFLAG(IS_CHROMEOS_ASH)
     // Set up fake primary profile.
     auto mock_user_manager =
@@ -58,30 +67,156 @@
     user_manager_ = std::make_unique<user_manager::ScopedUserManager>(
         std::move(mock_user_manager));
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
+    // Encryption is disabled by default.
+    ASSERT_FALSE(EncryptionModuleInterface::is_enabled());
+    if (is_encryption_enabled()) {
+      // Enable encryption.
+      scoped_feature_list_.InitFromCommandLine(
+          "EncryptedReportingPipeline,EncryptedReporting", "");
+      // Generate signing key pair.
+      test::GenerateSigningKeyPair(signing_private_key_,
+                                   signature_verification_public_key_);
+      // Create decryption module.
+      auto decryptor_result = test::Decryptor::Create();
+      ASSERT_OK(decryptor_result.status()) << decryptor_result.status();
+      decryptor_ = std::move(decryptor_result.ValueOrDie());
+      // Prepare the key.
+      signed_encryption_key_ = GenerateAndSignKey();
+    } else {
+      scoped_feature_list_.InitFromCommandLine("EncryptedReportingPipeline",
+                                               "EncryptedReporting");
+    }
+
     // Provide a mock cloud policy client.
     client_ = std::make_unique<policy::MockCloudPolicyClient>();
     client_->SetDMToken("FAKE_DM_TOKEN");
-    test_reporting_ =
-        std::make_unique<ReportingClient::TestEnvironment>(client_.get());
-
-    scoped_feature_list_.InitAndEnableFeature(
-        ReportQueueProvider::kEncryptedReportingPipeline);
+    test_reporting_ = std::make_unique<ReportingClient::TestEnvironment>(
+        base::FilePath(location_.GetPath()),
+        base::StringPiece(
+            reinterpret_cast<const char*>(signature_verification_public_key_),
+            kKeySize),
+        client_.get());
   }
 
   void TearDown() override {
+    // Let everything ongoing to finish.
+    task_environment_.RunUntilIdle();
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
     user_manager_.reset();
     profile_.reset();
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   }
 
- protected:
+  SignedEncryptionInfo GenerateAndSignKey() {
+    DCHECK(decryptor_) << "Decryptor not created";
+    // Generate new pair of private key and public value.
+    uint8_t private_key[kKeySize];
+    Encryptor::PublicKeyId public_key_id;
+    uint8_t public_value[kKeySize];
+    test::GenerateEncryptionKeyPair(private_key, public_value);
+    test::TestEvent<StatusOr<Encryptor::PublicKeyId>> prepare_key_pair;
+    decryptor_->RecordKeyPair(
+        std::string(reinterpret_cast<const char*>(private_key), kKeySize),
+        std::string(reinterpret_cast<const char*>(public_value), kKeySize),
+        prepare_key_pair.cb());
+    auto prepare_key_result = prepare_key_pair.result();
+    DCHECK(prepare_key_result.ok());
+    public_key_id = prepare_key_result.ValueOrDie();
+    // Deliver public key to storage.
+    SignedEncryptionInfo signed_encryption_key;
+    signed_encryption_key.set_public_asymmetric_key(
+        std::string(reinterpret_cast<const char*>(public_value), kKeySize));
+    signed_encryption_key.set_public_key_id(public_key_id);
+    // Sign public key.
+    uint8_t value_to_sign[sizeof(Encryptor::PublicKeyId) + kKeySize];
+    memcpy(value_to_sign, &public_key_id, sizeof(Encryptor::PublicKeyId));
+    memcpy(value_to_sign + sizeof(Encryptor::PublicKeyId), public_value,
+           kKeySize);
+    uint8_t signature[kSignatureSize];
+    test::SignMessage(
+        signing_private_key_,
+        base::StringPiece(reinterpret_cast<const char*>(value_to_sign),
+                          sizeof(value_to_sign)),
+        signature);
+    signed_encryption_key.set_signature(
+        std::string(reinterpret_cast<const char*>(signature), kSignatureSize));
+    // Double check signature.
+    DCHECK(VerifySignature(
+        signature_verification_public_key_,
+        base::StringPiece(reinterpret_cast<const char*>(value_to_sign),
+                          sizeof(value_to_sign)),
+        signature));
+    return signed_encryption_key;
+  }
+
+  std::unique_ptr<ReportQueue> CreateQueue(bool expect_key_roundtrip) {
+    auto config_result = ReportQueueConfiguration::Create(
+        dm_token_, destination_, policy_checker_callback_);
+    EXPECT_TRUE(config_result.ok());
+
+    test::TestEvent<StatusOr<std::unique_ptr<ReportQueue>>> create_queue_event;
+    if (expect_key_roundtrip) {
+      EXPECT_CALL(*client_, UploadEncryptedReport(_, _, _))
+          .WillOnce(WithArgs<0, 2>(Invoke(
+              [this](base::Value payload,
+                     policy::CloudPolicyClient::ResponseCallback done_cb) {
+                base::Optional<bool> const attach_encryption_settings =
+                    payload.FindBoolKey("attachEncryptionSettings");
+                ASSERT_TRUE(attach_encryption_settings.has_value());
+                ASSERT_TRUE(attach_encryption_settings
+                                .value());  // If set, must be true.
+                ASSERT_TRUE(is_encryption_enabled());
+
+                base::Value encryption_settings{base::Value::Type::DICTIONARY};
+                std::string public_key;
+                base::Base64Encode(
+                    signed_encryption_key_.public_asymmetric_key(),
+                    &public_key);
+                encryption_settings.SetStringKey("publicKey", public_key);
+                encryption_settings.SetIntKey(
+                    "publicKeyId", signed_encryption_key_.public_key_id());
+                std::string public_key_signature;
+                base::Base64Encode(signed_encryption_key_.signature(),
+                                   &public_key_signature);
+                encryption_settings.SetStringKey("publicKeySignature",
+                                                 public_key_signature);
+                base::Value response{base::Value::Type::DICTIONARY};
+                response.SetPath("encryptionSettings",
+                                 std::move(encryption_settings));
+                std::move(done_cb).Run(std::move(response));
+              })))
+          .RetiresOnSaturation();
+    }
+    ReportQueueProvider::CreateQueue(std::move(config_result.ValueOrDie()),
+                                     create_queue_event.cb());
+    auto result = create_queue_event.result();
+    EXPECT_OK(result);
+    auto report_queue = std::move(result.ValueOrDie());
+
+    // Let everything ongoing to finish.
+    task_environment_.RunUntilIdle();
+
+    return report_queue;
+  }
+
+  bool is_encryption_enabled() const { return GetParam(); }
+
   base::test::ScopedFeatureList scoped_feature_list_;
   // BrowserTaskEnvironment must be instantiated before other classes that posts
   // tasks.
   content::BrowserTaskEnvironment task_environment_{
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
   std::unique_ptr<ReportingClient::TestEnvironment> test_reporting_;
+
+  base::ScopedTempDir location_;
+
+  uint8_t signature_verification_public_key_[kKeySize];
+  uint8_t signing_private_key_[kSignKeySize];
+  scoped_refptr<test::Decryptor> decryptor_;
+  SignedEncryptionInfo signed_encryption_key_;
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<TestingProfile> profile_;
   std::unique_ptr<user_manager::ScopedUserManager> user_manager_;
@@ -94,76 +229,76 @@
 };
 
 // Tests that a ReportQueue can be created using the ReportingClient.
-TEST_F(ReportClientTest, CreatesReportQueue) {
-  auto config_result = ReportQueueConfiguration::Create(
-      dm_token_, destination_, policy_checker_callback_);
-  ASSERT_OK(config_result);
-
-  test::TestEvent<StatusOr<std::unique_ptr<ReportQueue>>> a;
-  ReportQueueProvider::CreateQueue(std::move(config_result.ValueOrDie()),
-                                   a.cb());
-  ASSERT_OK(a.result());
+TEST_P(ReportClientTest, CreatesReportQueue) {
+  auto report_queue = CreateQueue(is_encryption_enabled());
+  ASSERT_THAT(report_queue.get(), Ne(nullptr));
 }
 
 // Ensures that created ReportQueues are actually different.
-TEST_F(ReportClientTest, CreatesTwoDifferentReportQueues) {
-  auto config_result = ReportQueueConfiguration::Create(
-      dm_token_, destination_, policy_checker_callback_);
-  EXPECT_TRUE(config_result.ok());
+TEST_P(ReportClientTest, CreatesTwoDifferentReportQueues) {
+  // Create first queue.
+  auto report_queue_1 = CreateQueue(is_encryption_enabled());
+  ASSERT_THAT(report_queue_1.get(), Ne(nullptr));
 
-  test::TestEvent<StatusOr<std::unique_ptr<ReportQueue>>> a1;
-  ReportQueueProvider::CreateQueue(std::move(config_result.ValueOrDie()),
-                                   a1.cb());
-  auto result = a1.result();
-  ASSERT_OK(result);
-  auto report_queue_1 = std::move(result.ValueOrDie());
-
-  test::TestEvent<StatusOr<std::unique_ptr<ReportQueue>>> a2;
-  config_result = ReportQueueConfiguration::Create(dm_token_, destination_,
-                                                   policy_checker_callback_);
-  ReportQueueProvider::CreateQueue(std::move(config_result.ValueOrDie()),
-                                   a2.cb());
-  result = a2.result();
-  ASSERT_OK(result);
-  auto report_queue_2 = std::move(result.ValueOrDie());
+  // Create second queue. It will reuse the same ReportClient, so even if
+  // encryption is enabled, there will be no roundtrip to server to get the key.
+  auto report_queue_2 = CreateQueue(/*expect_key_roundtrip=*/false);
+  ASSERT_THAT(report_queue_2.get(), Ne(nullptr));
 
   EXPECT_NE(report_queue_1.get(), report_queue_2.get());
 }
 
 // Creates queue, enqueues messages and verifies they are uploaded.
-TEST_F(ReportClientTest, EnqueueMessageAndUpload) {
-  auto config_result = ReportQueueConfiguration::Create(
-      dm_token_, destination_, policy_checker_callback_);
-  EXPECT_TRUE(config_result.ok());
+TEST_P(ReportClientTest, EnqueueMessageAndUpload) {
+  // Create queue.
+  auto report_queue = CreateQueue(is_encryption_enabled());
 
-  test::TestEvent<StatusOr<std::unique_ptr<ReportQueue>>> create_queue_event;
-  ReportQueueProvider::CreateQueue(std::move(config_result.ValueOrDie()),
-                                   create_queue_event.cb());
-  auto result = create_queue_event.result();
-  ASSERT_OK(result);
-  auto report_queue = std::move(result.ValueOrDie());
-
+  // Enqueue event.
   test::TestEvent<Status> enqueue_record_event;
   report_queue->Enqueue("Record", FAST_BATCH, enqueue_record_event.cb());
-  ASSERT_OK(enqueue_record_event.result());
+  const auto enqueue_record_result = enqueue_record_event.result();
+  EXPECT_OK(enqueue_record_result) << enqueue_record_result;
 
   EXPECT_CALL(*client_, UploadEncryptedReport(_, _, _))
       .WillOnce(WithArgs<0, 2>(
-          Invoke([](base::Value payload,
-                    policy::CloudPolicyClient::ResponseCallback done_cb) {
+          Invoke([this](base::Value payload,
+                        policy::CloudPolicyClient::ResponseCallback done_cb) {
             base::Value* const records = payload.FindListKey("encryptedRecord");
             ASSERT_THAT(records, Ne(nullptr));
             base::Value::ListView records_list = records->GetList();
             ASSERT_THAT(records_list, SizeIs(1));
+            base::Value& record = records_list[0];
+            if (is_encryption_enabled()) {
+              const base::Value* const enctyption_info =
+                  record.FindDictKey("encryptionInfo");
+              ASSERT_THAT(enctyption_info, Ne(nullptr));
+              const std::string* const encryption_key =
+                  enctyption_info->FindStringKey("encryptionKey");
+              ASSERT_THAT(encryption_key, Ne(nullptr));
+              const std::string* const public_key_id =
+                  enctyption_info->FindStringKey("publicKeyId");
+              ASSERT_THAT(public_key_id, Ne(nullptr));
+              int64_t key_id;
+              ASSERT_TRUE(base::StringToInt64(*public_key_id, &key_id));
+              EXPECT_THAT(key_id, Eq(signed_encryption_key_.public_key_id()));
+            } else {
+              ASSERT_THAT(record.FindKey("encryptionInfo"), Eq(nullptr));
+            }
             base::Value* const seq_info =
-                records_list[0].FindDictKey("sequenceInformation");
+                record.FindDictKey("sequenceInformation");
             ASSERT_THAT(seq_info, Ne(nullptr));
             base::Value response{base::Value::Type::DICTIONARY};
             response.SetPath("lastSucceedUploadedRecord", std::move(*seq_info));
             std::move(done_cb).Run(std::move(response));
           })));
+
   // Trigger upload.
   task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
 }
+
+INSTANTIATE_TEST_SUITE_P(ReportClientTestSuite,
+                         ReportClientTest,
+                         ::testing::Bool() /* true - encryption enabled */);
+
 }  // namespace
 }  // namespace reporting
diff --git a/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc b/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc
index 80ad5c1..f49fad9f 100644
--- a/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc
+++ b/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc
@@ -162,7 +162,7 @@
     return;
   }
 
-  if (records_->empty()) {
+  if (records_->empty() && !need_encryption_key_) {
     Status empty_records =
         Status(error::INVALID_ARGUMENT, "records_ was empty");
     LOG(ERROR) << empty_records;
@@ -232,7 +232,7 @@
 }
 
 void RecordHandlerImpl::ReportUploader::HandleSuccessfulUpload() {
-  // Decypher 'response' containing a base::Value dictionary that looks like:
+  // Decipher 'response' containing a base::Value dictionary that looks like:
   //  {
   //    "lastSucceedUploadedRecord": ... // SequencingInformation proto
   //    "firstFailedUploadedRecord": {
diff --git a/chrome/browser/policy/messaging_layer/upload/record_upload_request_builder.cc b/chrome/browser/policy/messaging_layer/upload/record_upload_request_builder.cc
index c0775354..462f340 100644
--- a/chrome/browser/policy/messaging_layer/upload/record_upload_request_builder.cc
+++ b/chrome/browser/policy/messaging_layer/upload/record_upload_request_builder.cc
@@ -43,8 +43,6 @@
 UploadEncryptedReportingRequestBuilder::UploadEncryptedReportingRequestBuilder(
     bool attach_encryption_settings) {
   result_ = base::Value{base::Value::Type::DICTIONARY};
-  result_.value().SetKey(GetEncryptedRecordListPath(),
-                         base::Value{base::Value::Type::LIST});
   if (attach_encryption_settings) {
     result_.value().SetBoolKey(GetAttachEncryptionSettingsPath(), true);
   }
@@ -60,9 +58,13 @@
     // Some errors were already detected.
     return *this;
   }
-  base::Value* const records_list =
+  base::Value* records_list =
       result_.value().FindListKey(GetEncryptedRecordListPath());
-  if (!records_list || !records_list->is_list()) {
+  if (!records_list) {
+    records_list = result_.value().SetKey(GetEncryptedRecordListPath(),
+                                          base::Value{base::Value::Type::LIST});
+  }
+  if (!records_list->is_list()) {
     NOTREACHED();  // Should not happen.
     return *this;
   }
@@ -235,8 +237,9 @@
     return;
   }
 
-  encryption_info_dictionary.SetStringKey(GetEncryptionKeyPath(),
-                                          encryption_info.encryption_key());
+  std::string base64_key;
+  base::Base64Encode(encryption_info.encryption_key(), &base64_key);
+  encryption_info_dictionary.SetStringKey(GetEncryptionKeyPath(), base64_key);
   encryption_info_dictionary.SetStringKey(
       GetPublicKeyIdPath(),
       base::NumberToString(encryption_info.public_key_id()));
diff --git a/chrome/browser/policy/messaging_layer/upload/upload_client.cc b/chrome/browser/policy/messaging_layer/upload/upload_client.cc
index 5b16a76..9bd8b24 100644
--- a/chrome/browser/policy/messaging_layer/upload/upload_client.cc
+++ b/chrome/browser/policy/messaging_layer/upload/upload_client.cc
@@ -48,7 +48,7 @@
     std::unique_ptr<std::vector<EncryptedRecord>> records) {
   DCHECK(records);
 
-  if (records->empty()) {
+  if (records->empty() && !need_encryption_keys) {
     return Status::StatusOK();
   }
 
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js
index 90c133b..8e69fdd 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js
@@ -2147,13 +2147,19 @@
     }
 
     // Ancestry based hints.
+    /** @type {AutomationNode|undefined} */
+    let foundAncestor;
     if (uniqueAncestors.find(
             /** @type {function(?) : boolean} */ (AutomationPredicate.table))) {
       ret.push({msgId: 'hint_table'});
     }
-    if (uniqueAncestors.find(/** @type {function(?) : boolean} */ (
-            AutomationPredicate.roles([RoleType.MENU, RoleType.MENU_BAR])))) {
-      ret.push({msgId: 'hint_menu'});
+    if ((foundAncestor = uniqueAncestors.find(
+             /** @type {function(?) : boolean} */ (AutomationPredicate.roles(
+                 [RoleType.MENU, RoleType.MENU_BAR]))))) {
+      ret.push({
+        msgId: foundAncestor.state.horizontal ? 'hint_menu_horizontal' :
+                                                'hint_menu'
+      });
     }
     if (uniqueAncestors.find(
             /** @type {function(?) : boolean} */ (function(n) {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_test.js
index 98fa37ae..f301d5cd 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_test.js
@@ -494,33 +494,56 @@
 });
 
 TEST_F('ChromeVoxOutputE2ETest', 'Menu', function() {
-  this.runWithLoadedTree(
-      `
+  const site = `
     <div role="menu">
       <div role="menuitem">a</div>
       <div role="menuitemcheckbox">b</div>
       <div role="menuitemradio">c</div>
     </div>
-  `,
-      function(root) {
-        const el = root.firstChild.firstChild;
-        const range = cursors.Range.fromNode(el);
-        const o = new Output().withSpeechAndBraille(range, null, 'navigate');
-        checkSpeechOutput(
-            'a|Menu item| 1 of 3 |Menu',
-            [
-              {value: 'name', start: 0, end: 1},
-              {value: 'role', start: 21, end: 25}
-            ],
-            o);
-        checkBrailleOutput(
-            'a mnuitm 1/3 mnu',
-            [
-              {value: new OutputNodeSpan(el), start: 0, end: 12},
-              {value: new OutputNodeSpan(el.parent), start: 13, end: 16}
-            ],
-            o);
-      });
+    <div role="menubar" aria-orientation="horizontal"></div>
+  `;
+  this.runWithLoadedTree(site, function(root) {
+    let el = root.firstChild.firstChild;
+    let range = cursors.Range.fromNode(el);
+    let o = new Output().withSpeechAndBraille(range, null, 'navigate');
+    checkSpeechOutput(
+        'a|Menu item| 1 of 3 |Menu',
+        [
+          {value: 'name', start: 0, end: 1}, {value: 'role', start: 21, end: 25}
+        ],
+        o);
+    checkBrailleOutput(
+        'a mnuitm 1/3 mnu',
+        [
+          {value: new OutputNodeSpan(el), start: 0, end: 12},
+          {value: new OutputNodeSpan(el.parent), start: 13, end: 16}
+        ],
+        o);
+
+    // Ancestry.
+    el = root.firstChild;
+    range = cursors.Range.fromNode(el);
+    o = new Output().withSpeechAndBraille(range, null, 'navigate');
+    checkSpeechOutput(
+        'Menu|with 3 items|' +
+            'Press up or down arrow to navigate; enter to activate',
+        [
+          {value: 'role', start: 0, end: 4},
+          {value: {delay: true}, start: 18, end: 71}
+        ],
+        o);
+
+    el = root.lastChild;
+    range = cursors.Range.fromNode(el);
+    o = new Output().withSpeechAndBraille(range, null, 'navigate');
+    checkSpeechOutput(
+        'Menu bar|Press left or right arrow to navigate; enter to activate',
+        [
+          {value: 'role', start: 0, end: 8},
+          {value: {delay: true}, start: 9, end: 65}
+        ],
+        o);
+  });
 });
 
 TEST_F('ChromeVoxOutputE2ETest', 'ListBox', function() {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/testing/mock_feedback.js b/chrome/browser/resources/chromeos/accessibility/chromevox/testing/mock_feedback.js
index 4803ef4..4c34c44 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/testing/mock_feedback.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/testing/mock_feedback.js
@@ -275,7 +275,7 @@
           }
           if (MockFeedback.matchAndConsume_(
                   text, {}, this.pendingUtterances_)) {
-            throw new Error('Got denied utterance "' + text + '".');
+            assertFalse(true, 'Got denied utterance "' + text + '".');
           }
           return true;
         }.bind(this),
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp b/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp
index cdbb517..202e611 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp
+++ b/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp
@@ -2300,6 +2300,9 @@
   <message desc="A hint to the user for interacting with the menu control." name="IDS_CHROMEVOX_HINT_MENU">
     Press up or down arrow to navigate; enter to activate
   </message>
+  <message desc="A hint to the user for interacting with the menu control. This variant has a horizontal orientation." name="IDS_CHROMEVOX_HINT_MENU_HORIZONTAL" is_accessibility_with_no_ui="true">
+    Press left or right arrow to navigate; enter to activate
+  </message>
   <message desc="A hint to the user that there are details associated with this element." name="IDS_CHROMEVOX_HINT_DETAILS">
     Press Search+A, J to jump to details
   </message>
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/action_manager.js b/chrome/browser/resources/chromeos/accessibility/switch_access/action_manager.js
index 4b3732eb..ad5486f 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/action_manager.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/action_manager.js
@@ -69,7 +69,8 @@
    */
   static onSelect() {
     const node = Navigator.byItem.currentNode;
-    if (node.actions.length <= 1 || !node.location) {
+    if (MenuManager.isMenuOpen() || node.actions.length <= 1 ||
+        !node.location) {
       node.doDefaultAction();
       return;
     }
diff --git a/chrome/browser/resources/new_tab_page/BUILD.gn b/chrome/browser/resources/new_tab_page/BUILD.gn
index 6626fb5d..4d63ef4 100644
--- a/chrome/browser/resources/new_tab_page/BUILD.gn
+++ b/chrome/browser/resources/new_tab_page/BUILD.gn
@@ -49,6 +49,7 @@
     ":promo_browser_command_proxy",
     ":utils",
     ":window_proxy",
+    "modules:info_dialog",
     "modules:module_descriptor",
     "modules:module_header",
     "modules:module_registry",
diff --git a/chrome/browser/resources/new_tab_page/modules/BUILD.gn b/chrome/browser/resources/new_tab_page/modules/BUILD.gn
index 61e965c..2b36071 100644
--- a/chrome/browser/resources/new_tab_page/modules/BUILD.gn
+++ b/chrome/browser/resources/new_tab_page/modules/BUILD.gn
@@ -72,11 +72,20 @@
   ]
 }
 
+js_library("info_dialog") {
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
+    "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
+  ]
+}
+
 html_to_js("web_components_local") {
   js_files = [
     "module_header.js",
     "module_wrapper.js",
     "modules.js",
+    "info_dialog.js",
   ]
 }
 
@@ -139,6 +148,7 @@
     "module_header.js",
     "module_wrapper.js",
     "modules.js",
+    "info_dialog.js",
     "task_module/module.js",
     "cart/module.js",
     "drive/module.js",
diff --git a/chrome/browser/resources/new_tab_page/modules/drive/BUILD.gn b/chrome/browser/resources/new_tab_page/modules/drive/BUILD.gn
index 17b584e..cd67cb4 100644
--- a/chrome/browser/resources/new_tab_page/modules/drive/BUILD.gn
+++ b/chrome/browser/resources/new_tab_page/modules/drive/BUILD.gn
@@ -8,9 +8,11 @@
 js_library("module") {
   deps = [
     ":drive_module_proxy",
+    "..:info_dialog",
     "..:module_descriptor",
     "../..:i18n_setup",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render.m",
     "//ui/webui/resources/js:i18n_behavior.m",
   ]
 }
diff --git a/chrome/browser/resources/new_tab_page/modules/drive/module.html b/chrome/browser/resources/new_tab_page/modules/drive/module.html
index cc2797ea..88aa2196 100644
--- a/chrome/browser/resources/new_tab_page/modules/drive/module.html
+++ b/chrome/browser/resources/new_tab_page/modules/drive/module.html
@@ -70,6 +70,7 @@
     disable-text="[[i18nRecursive('',
                                   'modulesDisableButtonText',
                                   'modulesDriveSentence')]]"
+    show-info-button on-info-button-click="onInfoButtonClick_"
     on-disable-button-click="onDisableButtonClick_">
   $i18n{modulesDriveTitle}
 </ntp-module-header>
@@ -90,3 +91,8 @@
     </a>
   </template>
 </div>
+<cr-lazy-render id="infoDialogRender">
+  <template>
+    <ntp-info-dialog>$i18nRaw{modulesDriveInfo}</ntp-info-dialog>
+  </template>
+</cr-lazy-render>
diff --git a/chrome/browser/resources/new_tab_page/modules/drive/module.js b/chrome/browser/resources/new_tab_page/modules/drive/module.js
index c87bd614..c2c83f5 100644
--- a/chrome/browser/resources/new_tab_page/modules/drive/module.js
+++ b/chrome/browser/resources/new_tab_page/modules/drive/module.js
@@ -3,11 +3,13 @@
 // found in the LICENSE file.
 
 import '../module_header.js';
+import 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js';
 
 import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {loadTimeData} from '../../i18n_setup.js';
+import {InfoDialogElement} from '../info_dialog.js';
 import {ModuleDescriptor} from '../module_descriptor.js';
 
 import {DriveProxy} from './drive_module_proxy.js';
@@ -36,6 +38,12 @@
   }
 
   /** @private */
+  onInfoButtonClick_() {
+    /** @type {InfoDialogElement} */ (this.$.infoDialogRender.get())
+        .showModal();
+  }
+
+  /** @private */
   onDisableButtonClick_() {
     this.dispatchEvent(new CustomEvent('disable-module', {
       bubbles: true,
diff --git a/chrome/browser/resources/new_tab_page/modules/info_dialog.html b/chrome/browser/resources/new_tab_page/modules/info_dialog.html
new file mode 100644
index 0000000..730de21
--- /dev/null
+++ b/chrome/browser/resources/new_tab_page/modules/info_dialog.html
@@ -0,0 +1,26 @@
+<style>
+  cr-dialog::part(dialog) {
+    position: fixed;
+    width: 459px;
+  }
+
+  cr-dialog [slot='body'] {
+    line-height: 20px;
+  }
+
+  cr-dialog [slot='body'] a[href] {
+    color: var(--cr-link-color);
+    text-decoration: none;
+  }
+</style>
+<cr-dialog id="dialog" consume-keydown-event>
+  <div slot="title">$i18n{modulesTasksInfoTitle}</div>
+  <div slot="body">
+    <slot></slot>
+  </div>
+  <div slot="button-container">
+    <cr-button id="closeButton" class="action-button" on-click="onCloseClick_">
+      $i18n{modulesTasksInfoClose}
+    </cr-button>
+  </div>
+</cr-dialog>
diff --git a/chrome/browser/resources/new_tab_page/modules/info_dialog.js b/chrome/browser/resources/new_tab_page/modules/info_dialog.js
new file mode 100644
index 0000000..b6b765a3
--- /dev/null
+++ b/chrome/browser/resources/new_tab_page/modules/info_dialog.js
@@ -0,0 +1,33 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
+import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
+
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+/**
+ * Info dialog that can be populated with custom text via slotting.
+ * @polymer
+ */
+export class InfoDialogElement extends PolymerElement {
+  static get is() {
+    return 'ntp-info-dialog';
+  }
+
+  static get template() {
+    return html`{__html_template__}`;
+  }
+
+  showModal() {
+    this.$.dialog.showModal();
+  }
+
+  /** @private */
+  onCloseClick_() {
+    this.$.dialog.close();
+  }
+}
+
+customElements.define(InfoDialogElement.is, InfoDialogElement);
diff --git a/chrome/browser/resources/new_tab_page/modules/task_module/BUILD.gn b/chrome/browser/resources/new_tab_page/modules/task_module/BUILD.gn
index 8f88741..68d2e03 100644
--- a/chrome/browser/resources/new_tab_page/modules/task_module/BUILD.gn
+++ b/chrome/browser/resources/new_tab_page/modules/task_module/BUILD.gn
@@ -8,11 +8,13 @@
 js_library("module") {
   deps = [
     ":task_module_handler_proxy",
+    "..:info_dialog",
     "..:module_descriptor",
     "../..:i18n_setup",
     "../..:img",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/cr_elements/cr_grid",
+    "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render.m",
     "//ui/webui/resources/js:i18n_behavior.m",
   ]
 }
diff --git a/chrome/browser/resources/new_tab_page/modules/task_module/module.html b/chrome/browser/resources/new_tab_page/modules/task_module/module.html
index 2293d89..fb5c6a96 100644
--- a/chrome/browser/resources/new_tab_page/modules/task_module/module.html
+++ b/chrome/browser/resources/new_tab_page/modules/task_module/module.html
@@ -184,20 +184,6 @@
     margin-inline-end: 12px;
     margin-inline-start: 8px;
   }
-
-  cr-dialog::part(dialog) {
-    position: fixed;
-    width: 459px;
-  }
-
-  cr-dialog [slot='body'] div:not(:last-of-type) {
-    margin-bottom: 24px;
-  }
-
-  cr-dialog [slot='body'] a[href] {
-    color: var(--cr-link-color);
-    text-decoration: none;
-  }
 </style>
 <ntp-module-header
     dismiss-text="[[i18n('modulesDismissButtonText', dismissName_)]]"
@@ -245,17 +231,8 @@
     </template>
   </div>
 </div>
-<template is="dom-if" if="[[showInfoDialog]]" restamp>
-  <cr-dialog show-on-attach>
-    <div slot="title">$i18n{modulesTasksInfoTitle}</div>
-    <div slot="body">
-      <div>$i18nRaw{modulesTasksInfo1}</div>
-      <div>$i18nRaw{modulesTasksInfo2}</div>
-    </div>
-    <div slot="button-container">
-      <cr-button class="action-button" on-click="onCloseClick_">
-        $i18n{modulesTasksInfoClose}
-      </cr-button>
-    </div>
-  </cr-dialog>
-</template>
+<cr-lazy-render id="infoDialogRender">
+  <template>
+    <ntp-info-dialog>$i18nRaw{modulesTasksInfo}</ntp-info-dialog>
+  </template>
+</cr-lazy-render>
diff --git a/chrome/browser/resources/new_tab_page/modules/task_module/module.js b/chrome/browser/resources/new_tab_page/modules/task_module/module.js
index 2f8d733..9d5316d 100644
--- a/chrome/browser/resources/new_tab_page/modules/task_module/module.js
+++ b/chrome/browser/resources/new_tab_page/modules/task_module/module.js
@@ -4,12 +4,14 @@
 
 import '../../img.js';
 import '../module_header.js';
+import 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js';
 import 'chrome://resources/cr_elements/hidden_style_css.m.js';
 
 import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {loadTimeData} from '../../i18n_setup.js';
+import {InfoDialogElement} from '../info_dialog.js';
 import {ModuleDescriptor} from '../module_descriptor.js';
 
 import {TaskModuleHandlerProxy} from './task_module_handler_proxy.js';
@@ -42,9 +44,6 @@
       /** @type {!taskModule.mojom.Task} */
       task: Object,
 
-      /** @type {boolean} */
-      showInfoDialog: Boolean,
-
       /** @private {string} */
       dismissName_: {
         type: String,
@@ -147,12 +146,8 @@
 
   /** @private */
   onInfoButtonClick_() {
-    this.showInfoDialog = true;
-  }
-
-  /** @private */
-  onCloseClick_() {
-    this.showInfoDialog = false;
+    /** @type {InfoDialogElement} */ (this.$.infoDialogRender.get())
+        .showModal();
   }
 
   /** @private */
diff --git a/chrome/browser/resources/new_tab_page/new_tab_page.js b/chrome/browser/resources/new_tab_page/new_tab_page.js
index 62c9cec..976d67a 100644
--- a/chrome/browser/resources/new_tab_page/new_tab_page.js
+++ b/chrome/browser/resources/new_tab_page/new_tab_page.js
@@ -24,6 +24,7 @@
 export {FooProxy} from './modules/dummy/foo_proxy.js';
 export {dummyDescriptor} from './modules/dummy/module.js';
 // </if>
+export {InfoDialogElement} from './modules/info_dialog.js';
 export {Module, ModuleDescriptor} from './modules/module_descriptor.js';
 export {ModuleHeaderElement} from './modules/module_header.js';
 export {ModuleRegistry} from './modules/module_registry.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn
index a1ad7cb..e69b0be 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn
@@ -89,6 +89,7 @@
     "..:os_route.m",
     "../..:i18n_setup",
     "../..:router",
+    "../keyboard_shortcut_banner:keyboard_shortcut_banner",
     "//ui/webui/resources/js:assert.m",
     "//ui/webui/resources/js:i18n_behavior.m",
     "//ui/webui/resources/js:load_time_data.m",
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.html b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.html
index 7e9240b..e387823 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.html
@@ -15,6 +15,7 @@
 <link rel="import" href="../deep_linking_behavior.html">
 <link rel="import" href="../metrics_recorder.html">
 <link rel="import" href="../os_route.html">
+<link rel="import" href="../keyboard_shortcut_banner/keyboard_shortcut_banner.html">
 <link rel="import" href="../../controls/settings_toggle_button.html">
 <link rel="import" href="../../prefs/prefs_behavior.html">
 <link rel="import" href="../../i18n_setup.html">
@@ -141,6 +142,13 @@
       </settings-toggle-button>
 
       <div class="hr bottom-margin">
+        <template is="dom-if" if="[[shouldShowShortcutReminder_(
+            languageSettingsV2Update2Enabled_, shortcutReminderBody_.length)]]">
+          <keyboard-shortcut-banner title="$i18n{imeShortcutReminderTitle}"
+              body="[[shortcutReminderBody_]]"
+              on-dismiss="onShortcutReminderDismiss_">
+          </keyboard-shortcut-banner>
+        </template>
         <h2>$i18n{inputMethodListTitle}</h2>
         <template is="dom-if" if="[[inputMethodsLimitedByPolicy_(
             prefs.settings.language.allowed_input_methods.*)]]">
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js
index 2e16ea1..4d65a2d8 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js
@@ -80,6 +80,38 @@
         return loadTimeData.getBoolean('enableLanguageSettingsV2Update2');
       },
     },
+
+    /**
+     * Whether the shortcut reminder for the last used IME is currently showing.
+     * @private
+     */
+    showLastUsedIMEShortcutReminder_: {
+      type: Boolean,
+      computed: `shouldShowLastUsedIMEShortcutReminder_(
+          languages.inputMethods.enabled.length,
+          prefs.ash.shortcut_reminders.last_used_ime_dismissed.value)`,
+    },
+
+    /**
+     * Whether the shortcut reminder for the next IME is currently showing.
+     * @private
+     */
+    showNextIMEShortcutReminder_: {
+      type: Boolean,
+      computed: `shouldShowNextIMEShortcutReminder_(
+          languages.inputMethods.enabled.length,
+          prefs.ash.shortcut_reminders.next_ime_dismissed.value)`,
+    },
+
+    /**
+     * The body of the currently showing shortcut reminders.
+     * @private {!Array<string>}
+     */
+    shortcutReminderBody_: {
+      type: Array,
+      computed: `getShortcutReminderBody_(showLastUsedIMEShortcutReminder_,
+          showNextIMEShortcutReminder_)`,
+    },
   },
 
   /** @private {?settings.LanguagesMetricsProxy} */
@@ -510,4 +542,64 @@
   isCollapseOpened_(update2Enabled, spellCheckOn) {
     return !update2Enabled || spellCheckOn;
   },
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  shouldShowLastUsedIMEShortcutReminder_() {
+    // User has already dismissed the shortcut reminder.
+    if (this.getPref('ash.shortcut_reminders.last_used_ime_dismissed').value) {
+      return false;
+    }
+    // Need at least 2 input methods to be shown the reminder.
+    return !!this.languages && this.languages.inputMethods.enabled.length >= 2;
+  },
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  shouldShowNextIMEShortcutReminder_() {
+    // User has already dismissed the shortcut reminder.
+    if (this.getPref('ash.shortcut_reminders.next_ime_dismissed').value) {
+      return false;
+    }
+    // Need at least 3 input methods to be shown the reminder.
+    return !!this.languages && this.languages.inputMethods.enabled.length >= 3;
+  },
+
+  /**
+   * @return {!Array<string>}
+   * @private
+   */
+  getShortcutReminderBody_() {
+    const /** !Array<string> */ reminderBody = [];
+    if (this.showLastUsedIMEShortcutReminder_) {
+      reminderBody.push(this.i18nAdvanced('imeShortcutReminderLastUsed'));
+    }
+    if (this.showNextIMEShortcutReminder_) {
+      reminderBody.push(this.i18nAdvanced('imeShortcutReminderNext'));
+    }
+    return reminderBody;
+  },
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  shouldShowShortcutReminder_() {
+    return this.languageSettingsV2Update2Enabled_ &&
+        this.shortcutReminderBody_ && this.shortcutReminderBody_.length > 0;
+  },
+
+  /** @private */
+  onShortcutReminderDismiss_() {
+    if (this.showLastUsedIMEShortcutReminder_) {
+      this.setPrefValue('ash.shortcut_reminders.last_used_ime_dismissed', true);
+    }
+    if (this.showNextIMEShortcutReminder_) {
+      this.setPrefValue('ash.shortcut_reminders.next_ime_dismissed', true);
+    }
+  },
 });
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engines_page.html b/chrome/browser/resources/settings/search_engines_page/search_engines_page.html
index 95a7141..eeb770e 100644
--- a/chrome/browser/resources/settings/search_engines_page/search_engines_page.html
+++ b/chrome/browser/resources/settings/search_engines_page/search_engines_page.html
@@ -3,29 +3,6 @@
         border-top: var(--cr-separator-line);
       }
     </style>
-    <div class="cr-row first" hidden="[[!showKeywordTriggerSetting_]]">
-      <div class="flex cr-padded-text"
-          hidden="[[!showKeywordTriggerSetting_]]">
-        <h2>$i18n{searchEnginesTriggerOptions}</h2>
-        $i18n{searchEnginesTriggerDescription}
-      </div>
-    </div>
-    <div class="list-frame" hidden="[[!showKeywordTriggerSetting_]]">
-      <settings-radio-group
-          pref="{{prefs.omnibox.keyword_space_triggering_enabled}}">
-        <controlled-radio-button class="list-item" name="true"
-            pref="{{prefs.omnibox.keyword_space_triggering_enabled}}"
-            label="$i18n{searchEnginesTriggerSpaceEnabled}"
-            no-extension-indicator>
-        </controlled-radio-button>
-        <controlled-radio-button class="list-item" name="false"
-            pref="{{prefs.omnibox.keyword_space_triggering_enabled}}"
-            label="$i18n{searchEnginesTriggerSpaceDisabled}"
-            no-extension-indicator>
-        </controlled-radio-button>
-      </settings-radio-group>
-    </div>
-
     <div class="cr-row first">
       <h2>$i18n{searchEnginesDefault}</h2>
     </div>
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engines_page.js b/chrome/browser/resources/settings/search_engines_page/search_engines_page.js
index 695789c..29ab6d2 100644
--- a/chrome/browser/resources/settings/search_engines_page/search_engines_page.js
+++ b/chrome/browser/resources/settings/search_engines_page/search_engines_page.js
@@ -11,8 +11,6 @@
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/js/cr.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
-import '../controls/controlled_radio_button.js';
-import '../controls/settings_radio_group';
 import './search_engine_dialog.js';
 import './search_engines_list.js';
 import './omnibox_extension_entry.js';
@@ -25,7 +23,6 @@
 import {afterNextRender, html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {GlobalScrollTargetBehavior} from '../global_scroll_target_behavior.js';
-import {loadTimeData} from '../i18n_setup';
 import {routes} from '../route.js';
 
 import {SearchEngine, SearchEnginesBrowserProxyImpl, SearchEnginesInfo} from './search_engines_browser_proxy.js';
@@ -38,14 +35,6 @@
   behaviors: [GlobalScrollTargetBehavior, WebUIListenerBehavior],
 
   properties: {
-    /**
-     * Preferences state.
-     */
-    prefs: {
-      type: Object,
-      notify: true,
-    },
-
     /** @type {!Array<!SearchEngine>} */
     defaultEngines: Array,
 
@@ -117,12 +106,6 @@
       type: Boolean,
       value: false,
     },
-
-    /** @private */
-    showKeywordTriggerSetting_: {
-      type: Boolean,
-      value: () => loadTimeData.getBoolean('showKeywordTriggerSetting'),
-    },
   },
 
   // Since the iron-list for extensions is enclosed in a dom-if, observe both
diff --git a/chrome/browser/resources/settings/search_page/search_page.html b/chrome/browser/resources/settings/search_page/search_page.html
index f6913ff..0304c49 100644
--- a/chrome/browser/resources/settings/search_page/search_page.html
+++ b/chrome/browser/resources/settings/search_page/search_page.html
@@ -60,8 +60,7 @@
         page-title="$i18n{searchEnginesManage}"
         search-label="$i18n{searchEnginesSearch}"
         search-term="{{searchEnginesFilter_}}">
-      <settings-search-engines-page prefs="{{prefs}}"
-          filter="[[searchEnginesFilter_]]">
+      <settings-search-engines-page filter="[[searchEnginesFilter_]]">
     </settings-subpage>
   </template>
 </settings-animated-pages>
diff --git a/chrome/browser/safe_browsing/download_protection/download_reporter.cc b/chrome/browser/safe_browsing/download_protection/download_reporter.cc
index b262e07..5b8aa3d 100644
--- a/chrome/browser/safe_browsing/download_protection/download_reporter.cc
+++ b/chrome/browser/safe_browsing/download_protection/download_reporter.cc
@@ -145,7 +145,8 @@
 
 void DownloadReporter::OnDownloadCreated(download::DownloadItem* download) {
   danger_types_[download] = download->GetDangerType();
-  observed_downloads_.Add(download);
+  if (!observed_downloads_.IsObserving(download))
+    observed_downloads_.Add(download);
 }
 
 void DownloadReporter::OnDownloadDestroyed(download::DownloadItem* download) {
diff --git a/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/SigninCheckerTest.java b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/SigninCheckerTest.java
index db5c7773..9985f5a8 100644
--- a/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/SigninCheckerTest.java
+++ b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/SigninCheckerTest.java
@@ -65,7 +65,7 @@
     @Test
     @MediumTest
     public void signinWhenPrimaryAccountIsRenamedToAKnownAccount() {
-        mAccountManagerTestRule.addAccount("the.second.account@gmail.com");
+        mAccountManagerTestRule.addAccountAndWaitForSeeding("the.second.account@gmail.com");
         final CoreAccountInfo oldAccount =
                 mAccountManagerTestRule.addTestAccountThenSigninAndEnableSync();
         final String newAccountEmail = "test.new.account@gmail.com";
@@ -85,7 +85,7 @@
     @Test
     @MediumTest
     public void signoutWhenPrimaryAccountIsRenamedToAnUnknownAccount() {
-        mAccountManagerTestRule.addAccount("the.second.account@gmail.com");
+        mAccountManagerTestRule.addAccountAndWaitForSeeding("the.second.account@gmail.com");
         final CoreAccountInfo oldAccount =
                 mAccountManagerTestRule.addTestAccountThenSigninAndEnableSync();
         final String newAccountEmail = "test.new.account@gmail.com";
@@ -105,7 +105,7 @@
     @Test
     @MediumTest
     public void signoutWhenPrimaryAccountIsRemoved() {
-        mAccountManagerTestRule.addAccount("the.second.account@gmail.com");
+        mAccountManagerTestRule.addAccountAndWaitForSeeding("the.second.account@gmail.com");
         final CoreAccountInfo oldAccount =
                 mAccountManagerTestRule.addTestAccountThenSigninAndEnableSync();
 
diff --git a/chrome/browser/speech/cros_speech_recognition_service.cc b/chrome/browser/speech/cros_speech_recognition_service.cc
index 4189d95..c783fd26 100644
--- a/chrome/browser/speech/cros_speech_recognition_service.cc
+++ b/chrome/browser/speech/cros_speech_recognition_service.cc
@@ -4,10 +4,10 @@
 
 #include "chrome/browser/speech/cros_speech_recognition_service.h"
 
-#include "chrome/browser/accessibility/soda_installer.h"
 #include "chrome/services/speech/audio_source_fetcher_impl.h"
 #include "chrome/services/speech/cros_speech_recognition_recognizer_impl.h"
 #include "components/soda/constants.h"
+#include "components/soda/soda_installer.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "media/base/media_switches.h"
diff --git a/chrome/browser/speech/on_device_speech_recognizer.cc b/chrome/browser/speech/on_device_speech_recognizer.cc
index 2477cb8e..cd3c7bc 100644
--- a/chrome/browser/speech/on_device_speech_recognizer.cc
+++ b/chrome/browser/speech/on_device_speech_recognizer.cc
@@ -7,11 +7,11 @@
 #include <algorithm>
 
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/accessibility/soda_installer.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/speech/cros_speech_recognition_service.h"
 #include "chrome/browser/speech/cros_speech_recognition_service_factory.h"
 #include "chrome/browser/speech/speech_recognizer_delegate.h"
+#include "components/soda/soda_installer.h"
 #include "content/public/browser/audio_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "media/audio/audio_system.h"
diff --git a/chrome/browser/speech/on_device_speech_recognizer_browsertest.cc b/chrome/browser/speech/on_device_speech_recognizer_browsertest.cc
index 0e5cb8e9..a1c4191 100644
--- a/chrome/browser/speech/on_device_speech_recognizer_browsertest.cc
+++ b/chrome/browser/speech/on_device_speech_recognizer_browsertest.cc
@@ -7,7 +7,6 @@
 #include <map>
 #include <memory>
 
-#include "chrome/browser/accessibility/soda_installer.h"
 #include "chrome/browser/ash/accessibility/soda_installer_impl_chromeos.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/speech/cros_speech_recognition_service_factory.h"
@@ -15,6 +14,7 @@
 #include "chrome/browser/speech/speech_recognizer_delegate.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "components/soda/soda_installer.h"
 #include "content/public/test/browser_test.h"
 #include "media/audio/audio_system.h"
 #include "media/base/audio_parameters.h"
diff --git a/chrome/browser/speech/speech_recognition_client_browser_interface.cc b/chrome/browser/speech/speech_recognition_client_browser_interface.cc
index ab95a32..ebe2b1a 100644
--- a/chrome/browser/speech/speech_recognition_client_browser_interface.cc
+++ b/chrome/browser/speech/speech_recognition_client_browser_interface.cc
@@ -6,11 +6,11 @@
 
 #include <memory>
 
-#include "chrome/browser/accessibility/soda_installer.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/live_caption/pref_names.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_service.h"
+#include "components/soda/soda_installer.h"
 #include "media/base/media_switches.h"
 
 class PrefChangeRegistrar;
diff --git a/chrome/browser/speech/speech_recognition_client_browser_interface.h b/chrome/browser/speech/speech_recognition_client_browser_interface.h
index d23fd44..467a01e 100644
--- a/chrome/browser/speech/speech_recognition_client_browser_interface.h
+++ b/chrome/browser/speech/speech_recognition_client_browser_interface.h
@@ -5,8 +5,8 @@
 #ifndef CHROME_BROWSER_SPEECH_SPEECH_RECOGNITION_CLIENT_BROWSER_INTERFACE_H_
 #define CHROME_BROWSER_SPEECH_SPEECH_RECOGNITION_CLIENT_BROWSER_INTERFACE_H_
 
-#include "chrome/browser/accessibility/soda_installer.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/soda/soda_installer.h"
 #include "media/mojo/mojom/speech_recognition_service.mojom.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
 #include "mojo/public/cpp/bindings/remote_set.h"
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc
index 55910ec..aa24422 100644
--- a/chrome/browser/supervised_user/supervised_user_service.cc
+++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -724,10 +724,8 @@
       profile_->GetPrefs()->GetDictionary(prefs::kSupervisedUserManualHosts);
   std::map<std::string, bool> host_map;
   for (auto it : dict->DictItems()) {
-    bool allow = false;
-    bool result = it.second.GetAsBoolean(&allow);
-    DCHECK(result);
-    host_map[it.first] = allow;
+    DCHECK(it.second.is_bool());
+    host_map[it.first] = it.second.GetIfBool().value_or(false);
   }
   url_filter_.SetManualHosts(std::move(host_map));
 
@@ -740,10 +738,8 @@
       profile_->GetPrefs()->GetDictionary(prefs::kSupervisedUserManualURLs);
   std::map<GURL, bool> url_map;
   for (auto it : dict->DictItems()) {
-    bool allow = false;
-    bool result = it.second.GetAsBoolean(&allow);
-    DCHECK(result);
-    url_map[GURL(it.first)] = allow;
+    DCHECK(it.second.is_bool());
+    url_map[GURL(it.first)] = it.second.GetIfBool().value_or(false);
   }
   url_filter_.SetManualURLs(std::move(url_map));
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index f442bcf..ce57ff7 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1590,7 +1590,6 @@
       "//components/search_provider_logos",
       "//components/services/app_service/public/cpp:app_update",
       "//components/services/app_service/public/mojom",
-      "//components/soda:constants",
       "//components/ui_metrics",
       "//components/url_formatter",
       "//components/vector_icons",
@@ -2017,12 +2016,14 @@
       "ash/sharesheet/sharesheet_bubble_view.cc",
       "ash/sharesheet/sharesheet_bubble_view.h",
       "ash/sharesheet/sharesheet_constants.h",
-      "ash/sharesheet/sharesheet_content_previews.cc",
-      "ash/sharesheet/sharesheet_content_previews.h",
       "ash/sharesheet/sharesheet_expand_button.cc",
       "ash/sharesheet/sharesheet_expand_button.h",
+      "ash/sharesheet/sharesheet_header_view.cc",
+      "ash/sharesheet/sharesheet_header_view.h",
       "ash/sharesheet/sharesheet_target_button.cc",
       "ash/sharesheet/sharesheet_target_button.h",
+      "ash/sharesheet/sharesheet_util.cc",
+      "ash/sharesheet/sharesheet_util.h",
       "ash/shelf/app_service/app_service_app_window_arc_tracker.cc",
       "ash/shelf/app_service/app_service_app_window_arc_tracker.h",
       "ash/shelf/app_service/app_service_app_window_crostini_tracker.cc",
@@ -3530,6 +3531,9 @@
       "send_tab_to_self/send_tab_to_self_bubble_controller.cc",
       "send_tab_to_self/send_tab_to_self_bubble_controller.h",
       "send_tab_to_self/send_tab_to_self_bubble_view.h",
+      "sharing_hub/sharing_hub_bubble_controller.cc",
+      "sharing_hub/sharing_hub_bubble_controller.h",
+      "sharing_hub/sharing_hub_bubble_view.h",
 
       # This test header is included because it contains forward declarations
       # needed for "friend" statements for use in tests.
@@ -4130,6 +4134,10 @@
       "views/sharing/sharing_dialog_view.h",
       "views/sharing/sharing_icon_view.cc",
       "views/sharing/sharing_icon_view.h",
+      "views/sharing_hub/sharing_hub_bubble_view_impl.cc",
+      "views/sharing_hub/sharing_hub_bubble_view_impl.h",
+      "views/sharing_hub/sharing_hub_icon_view.cc",
+      "views/sharing_hub/sharing_hub_icon_view.h",
       "views/side_panel.cc",
       "views/side_panel.h",
       "views/ssl_client_certificate_selector.cc",
@@ -4377,6 +4385,8 @@
       "//components/payments/core",
       "//components/qr_code_generator",
       "//components/reading_list/features:flags",
+      "//components/soda",
+      "//components/soda:constants",
       "//components/tab_count_metrics",
       "//components/ui_devtools/views",
       "//device/vr/buildflags:buildflags",
diff --git a/chrome/browser/ui/app_list/search/app_search_provider.cc b/chrome/browser/ui/app_list/search/app_search_provider.cc
index 9cf5815..b4f0b7a 100644
--- a/chrome/browser/ui/app_list/search/app_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/app_search_provider.cc
@@ -40,6 +40,7 @@
 #include "chrome/browser/ui/app_list/search/app_service_app_result.h"
 #include "chrome/browser/ui/app_list/search/search_result_ranker/app_search_result_ranker.h"
 #include "chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.h"
+#include "chrome/browser/ui/app_list/search/search_tags_util.h"
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/components/string_matching/fuzzy_tokenized_string_match.h"
 #include "chromeos/components/string_matching/tokenized_string.h"
@@ -569,7 +570,12 @@
       }
       std::unique_ptr<AppResult> result =
           app->data_source()->CreateResult(app->id(), list_controller_, false);
-      result->UpdateFromMatch(*indexed_name, match);
+
+      // Update result from match.
+      result->SetTitle(indexed_name->text());
+      result->SetTitleTags(CalculateTags(query_, indexed_name->text()));
+      result->set_relevance(match.relevance());
+
       MaybeAddResult(&new_results, std::move(result), &seen_or_filtered_apps);
     } else {
       FuzzyTokenizedStringMatch match;
@@ -582,13 +588,8 @@
 
         // Update result from match.
         result->SetTitle(indexed_name->text());
+        result->SetTitleTags(CalculateTags(query_, indexed_name->text()));
         result->set_relevance(match.relevance());
-        ash::SearchResultTags tags;
-        for (const auto& hit : match.hits()) {
-          tags.push_back(ash::SearchResultTag(ash::SearchResultTag::MATCH,
-                                              hit.start(), hit.end()));
-        }
-        result->SetTitleTags(tags);
 
         MaybeAddResult(&new_results, std::move(result), &seen_or_filtered_apps);
       }
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc
index 7f360a8..0608c95 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc
+++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
+#include "chrome/browser/ui/app_list/search/search_tags_util.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -33,11 +34,15 @@
     arc::mojom::AppShortcutItemPtr data,
     Profile* profile,
     AppListControllerDelegate* list_controller,
-    bool is_recommendation)
+    bool is_recommendation,
+    const std::u16string& query)
     : data_(std::move(data)),
       profile_(profile),
       list_controller_(list_controller) {
-  SetTitle(base::UTF8ToUTF16(data_->short_label));
+  const auto title = base::UTF8ToUTF16(data_->short_label);
+  SetTitle(title);
+  if (!query.empty())
+    SetTitleTags(CalculateTags(query, title));
   set_id(kAppShortcutSearchPrefix + GetAppId() + "/" + data_->shortcut_id);
   SetAccessibleName(ComputeAccessibleName());
   SetResultType(ash::AppListSearchResultType::kArcAppShortcut);
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h
index 9f04a25..065c868 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h
+++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h
@@ -29,11 +29,13 @@
                                    public AppIconLoaderDelegate {
  public:
   // Constructor for ArcAppShortcutSearchResult. |is_recommendation|
-  // defines the display type of search results.
+  // defines the display type of search results. |query| will take on the
+  // default value for zero state results.
   ArcAppShortcutSearchResult(arc::mojom::AppShortcutItemPtr data,
                              Profile* profile,
                              AppListControllerDelegate* list_controller,
-                             bool is_recommendation);
+                             bool is_recommendation,
+                             const std::u16string& query);
   ~ArcAppShortcutSearchResult() override;
 
   // ChromeSearchResult:
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc
index 2f83d9c..6fec7b8d3 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc
@@ -47,6 +47,7 @@
     ClearResults();
     return;
   }
+  last_query_ = query;
 
   if (query.empty()) {
     app_instance->GetAppShortcutGlobalQueryItems(
@@ -83,8 +84,8 @@
     if (!app_info || !app_info->show_in_launcher)
       continue;
     auto result = std::make_unique<ArcAppShortcutSearchResult>(
-        std::move(item), profile_, list_controller_,
-        true /*is_recommendation*/);
+        std::move(item), profile_, list_controller_, true /*is_recommendation*/,
+        std::u16string() /*query*/);
 
     if (!app_info->install_time.is_null() ||
         !app_info->last_launch_time.is_null()) {
@@ -116,7 +117,7 @@
       continue;
     search_results.emplace_back(std::make_unique<ArcAppShortcutSearchResult>(
         std::move(item), profile_, list_controller_,
-        false /*is_recommendation*/));
+        false /*is_recommendation*/, last_query_));
   }
   SwapResults(&search_results);
 }
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h
index f88de7b..094ac9b 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h
+++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h
@@ -35,6 +35,7 @@
   void UpdateRecommendedResults(
       std::vector<arc::mojom::AppShortcutItemPtr> shortcut_items);
 
+  std::u16string last_query_;
   const int max_results_;
   Profile* const profile_;                            // Owned by ProfileInfo.
   AppListControllerDelegate* const list_controller_;  // Owned by AppListClient.
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.cc b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.cc
index e43a4fe..51caf40 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.cc
@@ -172,7 +172,7 @@
       continue;
 
     new_results.emplace_back(std::make_unique<ArcPlayStoreSearchResult>(
-        std::move(result), profile_, list_controller_));
+        std::move(result), profile_, list_controller_, last_query_));
   }
   SwapResults(&new_results);
 
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc
index 2b5641b..bf7d39f 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc
+++ b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
 #include "chrome/browser/ui/app_list/arc/arc_playstore_app_context_menu.h"
+#include "chrome/browser/ui/app_list/search/search_tags_util.h"
 #include "chrome/common/chrome_features.h"
 #include "components/arc/arc_service_manager.h"
 #include "components/arc/mojom/app.mojom.h"
@@ -102,11 +103,14 @@
 ArcPlayStoreSearchResult::ArcPlayStoreSearchResult(
     arc::mojom::AppDiscoveryResultPtr data,
     Profile* profile,
-    AppListControllerDelegate* list_controller)
+    AppListControllerDelegate* list_controller,
+    const std::u16string& query)
     : data_(std::move(data)),
       profile_(profile),
       list_controller_(list_controller) {
-  SetTitle(base::UTF8ToUTF16(label().value()));
+  const auto title = base::UTF8ToUTF16(label().value());
+  SetTitle(title);
+  SetTitleTags(CalculateTags(query, title));
   set_id(kPlayAppPrefix +
          crx_file::id_util::GenerateId(install_intent_uri().value()));
   SetDisplayType(ash::SearchResultDisplayType::kTile);
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h
index 235b88a..56633ef7 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h
+++ b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h
@@ -31,7 +31,8 @@
  public:
   ArcPlayStoreSearchResult(arc::mojom::AppDiscoveryResultPtr data,
                            Profile* profile,
-                           AppListControllerDelegate* list_controller);
+                           AppListControllerDelegate* list_controller,
+                           const std::u16string& query);
   ~ArcPlayStoreSearchResult() override;
 
   // ChromeSearchResult overrides:
diff --git a/chrome/browser/ui/app_list/search/files/file_result.cc b/chrome/browser/ui/app_list/search/files/file_result.cc
index 921e5fcb..9ad74a0d 100644
--- a/chrome/browser/ui/app_list/search/files/file_result.cc
+++ b/chrome/browser/ui/app_list/search/files/file_result.cc
@@ -67,8 +67,10 @@
   return match.relevance();
 }
 
-void LogRelevance(FileResult::ResultType result_type, const double relevance) {
+void LogRelevance(ChromeSearchResult::ResultType result_type,
+                  const double relevance) {
   // Relevance scores are between 0 and 1, so we scale to 0 to 100 for logging.
+  DCHECK((relevance >= 0) && (relevance <= 1));
   const int scaled_relevance = floor(100 * relevance);
   switch (result_type) {
     case FileResult::ResultType::kFileSearch:
@@ -79,6 +81,15 @@
       UMA_HISTOGRAM_EXACT_LINEAR("Apps.AppList.DriveSearchProvider.Relevance",
                                  scaled_relevance, /*exclusive_max=*/101);
       break;
+    case FileResult::ResultType::kZeroStateFile:
+      UMA_HISTOGRAM_EXACT_LINEAR("Apps.AppList.ZeroStateFileProvider.Relevance",
+                                 scaled_relevance, /*exclusive_max=*/101);
+      break;
+    case FileResult::ResultType::kZeroStateDrive:
+      UMA_HISTOGRAM_EXACT_LINEAR(
+          "Apps.AppList.ZeroStateDriveProvider.Relevance", scaled_relevance,
+          /*exclusive_max=*/101);
+      break;
     default:
       NOTREACHED();
   }
@@ -140,7 +151,11 @@
                  Type::kFile,
                  profile) {
   set_relevance(relevance);
-  // TODO(crbug.com/1188495): Add relevance metrics for zero state files.
+  if (display_type == DisplayType::kList) {
+    // Chip and list results overlap, and only list results are fully launched.
+    // So we only log metrics for list results.
+    LogRelevance(result_type, relevance);
+  }
 
   // Launcher search results UI is light by default, so use icons for light
   // background if dark/light mode feature is not enabled.
@@ -174,7 +189,6 @@
                  type,
                  profile) {
   const double relevance = CalculateRelevance(tokenized_query, title());
-  DCHECK((relevance >= 0) && (relevance <= 1));
   set_relevance(relevance);
   LogRelevance(result_type, relevance);
 
diff --git a/chrome/browser/ui/ash/projector/projector_client_impl.cc b/chrome/browser/ui/ash/projector/projector_client_impl.cc
index 5e1ad94..208c155 100644
--- a/chrome/browser/ui/ash/projector/projector_client_impl.cc
+++ b/chrome/browser/ui/ash/projector/projector_client_impl.cc
@@ -6,9 +6,9 @@
 
 #include "ash/public/cpp/projector/projector_controller.h"
 #include "base/optional.h"
-#include "chrome/browser/accessibility/soda_installer.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/speech/on_device_speech_recognizer.h"
+#include "components/soda/soda_installer.h"
 #include "media/base/media_switches.h"
 
 namespace {
diff --git a/chrome/browser/ui/ash/projector/projector_client_impl.h b/chrome/browser/ui/ash/projector/projector_client_impl.h
index 4a2984e5..fdee81b 100644
--- a/chrome/browser/ui/ash/projector/projector_client_impl.h
+++ b/chrome/browser/ui/ash/projector/projector_client_impl.h
@@ -10,8 +10,8 @@
 #include "ash/public/cpp/projector/projector_client.h"
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
-#include "chrome/browser/accessibility/soda_installer.h"
 #include "chrome/browser/speech/speech_recognizer_delegate.h"
+#include "components/soda/soda_installer.h"
 
 class OnDeviceSpeechRecognizer;
 
diff --git a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.cc b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.cc
index 3c1c450..187f447 100644
--- a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.cc
+++ b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.cc
@@ -19,9 +19,10 @@
 #include "chrome/browser/sharesheet/sharesheet_metrics.h"
 #include "chrome/browser/sharesheet/sharesheet_service_delegate.h"
 #include "chrome/browser/ui/ash/sharesheet/sharesheet_constants.h"
-#include "chrome/browser/ui/ash/sharesheet/sharesheet_content_previews.h"
 #include "chrome/browser/ui/ash/sharesheet/sharesheet_expand_button.h"
+#include "chrome/browser/ui/ash/sharesheet/sharesheet_header_view.h"
 #include "chrome/browser/ui/ash/sharesheet/sharesheet_target_button.h"
+#include "chrome/browser/ui/ash/sharesheet/sharesheet_util.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
@@ -116,22 +117,6 @@
          key_code == ui::VKEY_RIGHT || key_code == ui::VKEY_LEFT;
 }
 
-// TODO(crbug.com/1188938): Create sharesheet_util and move there.
-// Then use this for all sharesheet labels.
-std::unique_ptr<views::Label> CreateShareLabel(
-    const std::u16string& text,
-    const int text_context,
-    const int line_height,
-    const SkColor color,
-    const gfx::HorizontalAlignment alignment,
-    const int text_style = ash::STYLE_SHARESHEET) {
-  auto label = std::make_unique<views::Label>(text, text_context, text_style);
-  label->SetLineHeight(line_height);
-  label->SetEnabledColor(color);
-  label->SetHorizontalAlignment(alignment);
-  return label;
-}
-
 }  // namespace
 
 namespace ash {
@@ -180,8 +165,6 @@
   parent_view_ =
       views::Widget::GetWidgetForNativeWindow(native_window)->GetRootView();
   AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
-  UpdateAnchorPosition();
-
   CreateBubble();
 }
 
@@ -199,27 +182,9 @@
       /* inside_border_insets */ gfx::Insets(),
       /* between_child_spacing */ 0, /* collapse_margins_spacing */ true));
 
-  std::unique_ptr<views::Label> share_title_view =
-      CreateShareLabel(l10n_util::GetStringUTF16(IDS_SHARESHEET_TITLE_LABEL),
-                       CONTEXT_SHARESHEET_BUBBLE_TITLE, kTitleTextLineHeight,
-                       kTitleTextColor, gfx::ALIGN_LEFT);
-
-  if (targets.empty() ||
-      !(base::FeatureList::IsEnabled(features::kSharesheetContentPreviews))) {
-    // Only the share title is displayed if there are no targets or if the
-    // content previews flag is off.
-    share_title_view->SetProperty(
-        views::kMarginsKey,
-        gfx::Insets(kSpacing, kSpacing, kSpacing, kSpacing));
-    share_title_view_ = main_view_->AddChildView(std::move(share_title_view));
-  } else {
-    // Adds view for content previews including the title, text descriptor
-    // and image preview.
-    content_previews_ =
-        main_view_->AddChildView(std::make_unique<SharesheetContentPreviews>(
-            intent_->Clone(), delegate_->GetProfile(),
-            std::move(share_title_view)));
-  }
+  header_view_ =
+      main_view_->AddChildView(std::make_unique<SharesheetHeaderView>(
+          intent_->Clone(), delegate_->GetProfile()));
 
   if (targets.empty()) {
     auto* image =
@@ -264,7 +229,8 @@
     SetToDefaultBubbleSizing();
   } else {
     width_ = kDefaultBubbleWidth;
-    height_ = kNoExtensionBubbleBodyHeight + GetBubbleHeadHeight();
+    height_ = kNoExtensionBubbleBodyHeight +
+              header_view_->GetPreferredSize().height();
     expand_button_->SetVisible(false);
     expand_button_separator_->SetVisible(false);
   }
@@ -742,26 +708,10 @@
 int SharesheetBubbleView::GetBubbleHeight() {
   int height = (show_expanded_view_ ? kExpandedBubbleBodyHeight
                                     : kDefaultBubbleBodyHeight) +
-               GetBubbleHeadHeight();
+               header_view_->GetPreferredSize().height();
   return height;
 }
 
-int SharesheetBubbleView::GetBubbleHeadHeight() {
-  // |head_height| is the max height of |content_previews_| and
-  // |share_title_view_|.
-  int head_height = 0;
-  if (content_previews_) {
-    // The bubble height is increased by the height of the additional lines from
-    // text preview.
-    head_height = content_previews_->GetPreferredSize().height();
-  }
-  if (share_title_view_) {
-    head_height = share_title_view_->GetProperty(views::kMarginsKey)->height() +
-                  share_title_view_->GetPreferredSize().height();
-  }
-  return head_height;
-}
-
 void SharesheetBubbleView::RecordFormFactorMetric() {
   auto form_factor =
       TabletMode::Get()->InTabletMode()
diff --git a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h
index 6ae8c909..8c9fafaa 100644
--- a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h
+++ b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h
@@ -15,7 +15,6 @@
 namespace views {
 class GridLayout;
 class Separator;
-class Label;
 }  // namespace views
 
 namespace sharesheet {
@@ -25,7 +24,7 @@
 namespace ash {
 namespace sharesheet {
 
-class SharesheetContentPreviews;
+class SharesheetHeaderView;
 class SharesheetExpandButton;
 
 class SharesheetBubbleView : public views::BubbleDialogDelegateView {
@@ -84,7 +83,6 @@
   void CloseWidgetWithAnimateFadeOut(views::Widget::ClosedReason closed_reason);
   void CloseWidgetWithReason(views::Widget::ClosedReason closed_reason);
   int GetBubbleHeight();
-  int GetBubbleHeadHeight();
   void RecordFormFactorMetric();
 
   // Owns this class.
@@ -103,6 +101,7 @@
   size_t keyboard_highlighted_target_ = 0;
 
   views::View* main_view_ = nullptr;
+  SharesheetHeaderView* header_view_ = nullptr;
   views::View* default_view_ = nullptr;
   views::View* expanded_view_ = nullptr;
   views::View* share_action_view_ = nullptr;
@@ -112,8 +111,6 @@
   views::Separator* expanded_view_separator_ = nullptr;
   views::View* parent_view_ = nullptr;
   SharesheetExpandButton* expand_button_ = nullptr;
-  SharesheetContentPreviews* content_previews_ = nullptr;
-  views::Label* share_title_view_ = nullptr;
 
   std::unique_ptr<SharesheetParentWidgetObserver> parent_widget_observer_;
 };
diff --git a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view_browsertest.cc b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view_browsertest.cc
index 160339d..ae4bc42 100644
--- a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view_browsertest.cc
@@ -50,8 +50,7 @@
         ::sharesheet::SharesheetServiceFactory::GetForProfile(
             browser()->profile());
 
-    GURL test_url = GURL("https://www.google.com/");
-    auto intent = apps_util::CreateIntentFromUrl(test_url);
+    auto intent = apps_util::CreateShareIntentFromText("text", "");
     intent->action = apps_util::kIntentActionSend;
     sharesheet_service->ShowBubble(
         browser()->tab_strip_model()->GetActiveWebContents(), std::move(intent),
diff --git a/chrome/browser/ui/ash/sharesheet/sharesheet_constants.h b/chrome/browser/ui/ash/sharesheet/sharesheet_constants.h
index 9b1cfd7..30b6004 100644
--- a/chrome/browser/ui/ash/sharesheet/sharesheet_constants.h
+++ b/chrome/browser/ui/ash/sharesheet/sharesheet_constants.h
@@ -14,6 +14,11 @@
 constexpr int kSpacing = 24;
 
 constexpr size_t kTextPreviewMaximumLines = 3;
+constexpr int kImagePreviewCornerRadius = 4;
+constexpr SkColor kImagePreviewPlaceholderBackgroundColor = gfx::kGoogleBlue050;
+
+constexpr int kHeaderViewBetweenChildSpacing = 12;
+constexpr int kHeaderViewNarrowInsideBorderInsets = 14;
 
 constexpr int kTitleTextLineHeight = 24;
 constexpr int kSubtitleTextLineHeight = 22;
diff --git a/chrome/browser/ui/ash/sharesheet/sharesheet_content_previews.cc b/chrome/browser/ui/ash/sharesheet/sharesheet_header_view.cc
similarity index 76%
rename from chrome/browser/ui/ash/sharesheet/sharesheet_content_previews.cc
rename to chrome/browser/ui/ash/sharesheet/sharesheet_header_view.cc
index 30ff7595..817455e3 100644
--- a/chrome/browser/ui/ash/sharesheet/sharesheet_content_previews.cc
+++ b/chrome/browser/ui/ash/sharesheet/sharesheet_header_view.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/ash/sharesheet/sharesheet_content_previews.h"
+#include "chrome/browser/ui/ash/sharesheet/sharesheet_header_view.h"
 
 #include <algorithm>
 #include <utility>
@@ -18,6 +18,7 @@
 #include "chrome/browser/sharesheet/sharesheet_types.h"
 #include "chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h"
 #include "chrome/browser/ui/ash/sharesheet/sharesheet_constants.h"
+#include "chrome/browser/ui/ash/sharesheet/sharesheet_util.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/grit/generated_resources.h"
 #include "storage/browser/file_system/file_system_context.h"
@@ -36,8 +37,6 @@
 
 namespace {
 
-constexpr int kBetweenChildSpacing = 12;
-
 // Concatenates all the strings in |file_names| with a comma delineator.
 const std::u16string ConcatenateFileNames(
     const std::vector<std::string>& file_names) {
@@ -50,54 +49,62 @@
 namespace ash {
 namespace sharesheet {
 
-SharesheetContentPreviews::SharesheetContentPreviews(
-    apps::mojom::IntentPtr intent,
-    Profile* profile,
-    std::unique_ptr<views::Label> share_title)
+SharesheetHeaderView::SharesheetHeaderView(apps::mojom::IntentPtr intent,
+                                           Profile* profile)
     : profile_(profile),
       intent_(std::move(intent)),
       thumbnail_loader_(profile) {
   auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
       views::BoxLayout::Orientation::kHorizontal,
       /* inside_border_insets */ gfx::Insets(kSpacing),
-      /* between_child_spacing */ kBetweenChildSpacing,
+      /* between_child_spacing */ kHeaderViewBetweenChildSpacing,
       /* collapse_margins_spacing */ false));
   // Sets all views to be left-aligned.
   layout->set_main_axis_alignment(views::BoxLayout::MainAxisAlignment::kStart);
-  // Sets all views to be top-aligned.
+  // Sets all views to be vertically centre-aligned.
   layout->set_cross_axis_alignment(
-      views::BoxLayout::CrossAxisAlignment::kStart);
+      views::BoxLayout::CrossAxisAlignment::kCenter);
 
   // The image view is initialised first to ensure its left most placement.
-  InitaliseImageView();
-
+  if (base::FeatureList::IsEnabled(features::kSharesheetContentPreviews)) {
+    InitaliseImageView();
+  }
   // A separate view is created for the share title and preview string views.
   text_view_ = AddChildView(std::make_unique<views::View>());
   text_view_->SetLayoutManager(std::make_unique<views::BoxLayout>(
       views::BoxLayout::Orientation::kVertical,
       /* inside_border_insets */ gfx::Insets(),
       /* between_child_spacing */ 0, /* collapse_margins_spacing */ true));
+  text_view_->AddChildView(
+      CreateShareLabel(l10n_util::GetStringUTF16(IDS_SHARESHEET_TITLE_LABEL),
+                       CONTEXT_SHARESHEET_BUBBLE_TITLE, kTitleTextLineHeight,
+                       kTitleTextColor, gfx::ALIGN_LEFT));
+  if (base::FeatureList::IsEnabled(features::kSharesheetContentPreviews)) {
+    ShowTextPreview();
 
-  text_view_->AddChildView(std::move(share_title));
-  ShowTextPreview();
-
-  if (intent_->file_urls.has_value() && !intent_->file_urls.value().empty()) {
-    LoadImage();
-  } else {
-    // TODO(crbug.com/2650014): Update to text icon.
-    image_preview_->SetImage(gfx::CreateVectorIcon(kAddIcon));
+    if (intent_->file_urls.has_value() && !intent_->file_urls.value().empty()) {
+      LoadImage();
+    } else {
+      // TODO(crbug.com/2650014): Update to text icon.
+      image_preview_->SetImage(gfx::CreateVectorIcon(kAddIcon));
+    }
   }
 }
 
-SharesheetContentPreviews::~SharesheetContentPreviews() = default;
+SharesheetHeaderView::~SharesheetHeaderView() = default;
 
-void SharesheetContentPreviews::InitaliseImageView() {
+void SharesheetHeaderView::InitaliseImageView() {
   image_preview_ = AddChildView(std::make_unique<views::ImageView>());
   image_preview_->SetImageSize(
       gfx::Size(::sharesheet::kIconSize, ::sharesheet::kIconSize));
+  image_preview_->SetPaintToLayer();
+  image_preview_->layer()->SetRoundedCornerRadius(
+      gfx::RoundedCornersF(kImagePreviewCornerRadius));
+  image_preview_->SetBackground(
+      views::CreateSolidBackground(kImagePreviewPlaceholderBackgroundColor));
 }
 
-void SharesheetContentPreviews::ShowTextPreview() {
+void SharesheetHeaderView::ShowTextPreview() {
   std::vector<std::u16string> text_fields = ExtractShareText();
 
   std::u16string filenames_tooltip_text = u"";
@@ -131,11 +138,18 @@
   // empty and the tooltip will instead be set to what the text says.
   DCHECK_LT(index, text_fields.size());
   AddTextLine(text_fields[index], filenames_tooltip_text);
+
+  // If we have 2 or more lines of text, shorten the vertical insets.
+  if (index >= 1) {
+    static_cast<views::BoxLayout*>(GetLayoutManager())
+        ->set_inside_border_insets(
+            gfx::Insets(/* vertical */ kHeaderViewNarrowInsideBorderInsets,
+                        /* horizontal */ kSpacing));
+  }
 }
 
-void SharesheetContentPreviews::AddTextLine(
-    const std::u16string& text,
-    const std::u16string& tooltip_text) {
+void SharesheetHeaderView::AddTextLine(const std::u16string& text,
+                                       const std::u16string& tooltip_text) {
   auto* new_line = text_view_->AddChildView(
       std::make_unique<views::Label>(text, CONTEXT_SHARESHEET_BUBBLE_BODY));
   new_line->SetLineHeight(kPrimaryTextLineHeight);
@@ -153,7 +167,7 @@
       base::StrCat({new_line->GetText(), u" ", tooltip_text}));
 }
 
-std::vector<std::u16string> SharesheetContentPreviews::ExtractShareText() {
+std::vector<std::u16string> SharesheetHeaderView::ExtractShareText() {
   std::vector<std::u16string> text_fields;
 
   if (intent_->share_title.has_value() &&
@@ -198,7 +212,7 @@
 }
 
 // TODO(crbug.com/2650014) Optimise to load several images.
-void SharesheetContentPreviews::LoadImage() {
+void SharesheetHeaderView::LoadImage() {
   base::FilePath file_path;
   storage::FileSystemContext* fs_context =
       file_manager::util::GetFileSystemContextForExtensionId(
@@ -213,12 +227,12 @@
   // If those implementations change, this will need to be updated.
   thumbnail_loader_.Load(
       {file_path, gfx::Size(::sharesheet::kIconSize, ::sharesheet::kIconSize)},
-      base::BindOnce(&SharesheetContentPreviews::OnImageLoaded,
+      base::BindOnce(&SharesheetHeaderView::OnImageLoaded,
                      weak_ptr_factory_.GetWeakPtr()));
 }
 
-void SharesheetContentPreviews::OnImageLoaded(const SkBitmap* bitmap,
-                                              base::File::Error error) {
+void SharesheetHeaderView::OnImageLoaded(const SkBitmap* bitmap,
+                                         base::File::Error error) {
   if (error != base::File::FILE_OK) {
     // TODO(crbug.com/2650014): Handle error case:
     // Add placeholder icons for each mimetype.
@@ -232,7 +246,7 @@
       gfx::Image::CreateFrom1xBitmap(*bitmap).AsImageSkia());
 }
 
-BEGIN_METADATA(SharesheetContentPreviews, views::View)
+BEGIN_METADATA(SharesheetHeaderView, views::View)
 END_METADATA
 
 }  // namespace sharesheet
diff --git a/chrome/browser/ui/ash/sharesheet/sharesheet_content_previews.h b/chrome/browser/ui/ash/sharesheet/sharesheet_header_view.h
similarity index 64%
rename from chrome/browser/ui/ash/sharesheet/sharesheet_content_previews.h
rename to chrome/browser/ui/ash/sharesheet/sharesheet_header_view.h
index 63f77676..8a64780a 100644
--- a/chrome/browser/ui/ash/sharesheet/sharesheet_content_previews.h
+++ b/chrome/browser/ui/ash/sharesheet/sharesheet_header_view.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_ASH_SHARESHEET_SHARESHEET_CONTENT_PREVIEWS_H_
-#define CHROME_BROWSER_UI_ASH_SHARESHEET_SHARESHEET_CONTENT_PREVIEWS_H_
+#ifndef CHROME_BROWSER_UI_ASH_SHARESHEET_SHARESHEET_HEADER_VIEW_H_
+#define CHROME_BROWSER_UI_ASH_SHARESHEET_SHARESHEET_HEADER_VIEW_H_
 
 #include "chrome/browser/ui/ash/thumbnail_loader.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
@@ -14,25 +14,22 @@
 
 namespace views {
 class ImageView;
-class Label;
 }  // namespace views
 
 namespace ash {
 namespace sharesheet {
 
-// The SharesheetContentPreviews class is the view for the image
+// The SharesheetHeaderView class is the view for the image
 // previews feature.
-class SharesheetContentPreviews : public views::View {
+class SharesheetHeaderView : public views::View {
  public:
-  METADATA_HEADER(SharesheetContentPreviews);
+  METADATA_HEADER(SharesheetHeaderView);
 
-  explicit SharesheetContentPreviews(apps::mojom::IntentPtr intent,
-                                     Profile* profile,
-                                     std::unique_ptr<views::Label> share_title);
-  ~SharesheetContentPreviews() override;
-  SharesheetContentPreviews(const SharesheetContentPreviews&) = delete;
-  SharesheetContentPreviews& operator=(const SharesheetContentPreviews&) =
-      delete;
+  explicit SharesheetHeaderView(apps::mojom::IntentPtr intent,
+                                Profile* profile);
+  ~SharesheetHeaderView() override;
+  SharesheetHeaderView(const SharesheetHeaderView&) = delete;
+  SharesheetHeaderView& operator=(const SharesheetHeaderView&) = delete;
 
  private:
   // Adds the view for image previews and sets the required properties.
@@ -63,10 +60,10 @@
   apps::mojom::IntentPtr intent_;
   ThumbnailLoader thumbnail_loader_;
 
-  base::WeakPtrFactory<SharesheetContentPreviews> weak_ptr_factory_{this};
+  base::WeakPtrFactory<SharesheetHeaderView> weak_ptr_factory_{this};
 };
 
 }  // namespace sharesheet
 }  // namespace ash
 
-#endif  // CHROME_BROWSER_UI_ASH_SHARESHEET_SHARESHEET_CONTENT_PREVIEWS_H_
+#endif  // CHROME_BROWSER_UI_ASH_SHARESHEET_SHARESHEET_HEADER_VIEW_H_
diff --git a/chrome/browser/ui/ash/sharesheet/sharesheet_util.cc b/chrome/browser/ui/ash/sharesheet/sharesheet_util.cc
new file mode 100644
index 0000000..74d4d8c
--- /dev/null
+++ b/chrome/browser/ui/ash/sharesheet/sharesheet_util.cc
@@ -0,0 +1,27 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/ash/sharesheet/sharesheet_util.h"
+
+#include "ui/views/controls/label.h"
+
+namespace ash {
+namespace sharesheet {
+
+std::unique_ptr<views::Label> CreateShareLabel(
+    const std::u16string& text,
+    const int text_context,
+    const int line_height,
+    const SkColor color,
+    const gfx::HorizontalAlignment alignment,
+    const int text_style) {
+  auto label = std::make_unique<views::Label>(text, text_context, text_style);
+  label->SetLineHeight(line_height);
+  label->SetEnabledColor(color);
+  label->SetHorizontalAlignment(alignment);
+  return label;
+}
+
+}  // namespace sharesheet
+}  // namespace ash
diff --git a/chrome/browser/ui/ash/sharesheet/sharesheet_util.h b/chrome/browser/ui/ash/sharesheet/sharesheet_util.h
new file mode 100644
index 0000000..9534f4a
--- /dev/null
+++ b/chrome/browser/ui/ash/sharesheet/sharesheet_util.h
@@ -0,0 +1,33 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_ASH_SHARESHEET_SHARESHEET_UTIL_H_
+#define CHROME_BROWSER_UI_ASH_SHARESHEET_SHARESHEET_UTIL_H_
+
+#include <memory>
+#include <string>
+
+#include "ash/public/cpp/ash_typography.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/text_constants.h"
+
+namespace views {
+class Label;
+}  // namespace views
+
+namespace ash {
+namespace sharesheet {
+
+std::unique_ptr<views::Label> CreateShareLabel(
+    const std::u16string& text,
+    const int text_context,
+    const int line_height,
+    const SkColor color,
+    const gfx::HorizontalAlignment alignment,
+    const int text_style = ash::STYLE_SHARESHEET);
+
+}  // namespace sharesheet
+}  // namespace ash
+
+#endif  // CHROME_BROWSER_UI_ASH_SHARESHEET_SHARESHEET_UTIL_H_
diff --git a/chrome/browser/ui/sharing_hub/DIR_METADATA b/chrome/browser/ui/sharing_hub/DIR_METADATA
new file mode 100644
index 0000000..167ca6e
--- /dev/null
+++ b/chrome/browser/ui/sharing_hub/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "UI>Browser>Sharing"
+}
diff --git a/chrome/browser/ui/sharing_hub/OWNERS b/chrome/browser/ui/sharing_hub/OWNERS
new file mode 100644
index 0000000..17451040
--- /dev/null
+++ b/chrome/browser/ui/sharing_hub/OWNERS
@@ -0,0 +1 @@
+file://components/send_tab_to_self/OWNERS
diff --git a/chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.cc b/chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.cc
new file mode 100644
index 0000000..794d5bc
--- /dev/null
+++ b/chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.cc
@@ -0,0 +1,69 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/sharing_hub/sharing_hub_bubble_view.h"
+#include "chrome/grit/generated_resources.h"
+#include "content/public/browser/web_contents.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace sharing_hub {
+
+SharingHubBubbleController::~SharingHubBubbleController() {
+  if (sharing_hub_bubble_view_) {
+    sharing_hub_bubble_view_->Hide();
+  }
+}
+
+// static
+SharingHubBubbleController*
+SharingHubBubbleController::CreateOrGetFromWebContents(
+    content::WebContents* web_contents) {
+  SharingHubBubbleController::CreateForWebContents(web_contents);
+  SharingHubBubbleController* controller =
+      SharingHubBubbleController::FromWebContents(web_contents);
+  return controller;
+}
+
+void SharingHubBubbleController::HideBubble() {
+  if (sharing_hub_bubble_view_) {
+    sharing_hub_bubble_view_->Hide();
+    sharing_hub_bubble_view_ = nullptr;
+  }
+}
+
+void SharingHubBubbleController::ShowBubble() {
+  // TODO(1186843): Add omnibox integration.
+}
+
+SharingHubBubbleView* SharingHubBubbleController::sharing_hub_bubble_view()
+    const {
+  return sharing_hub_bubble_view_;
+}
+
+std::u16string SharingHubBubbleController::GetWindowTitle() const {
+  return l10n_util::GetStringUTF16(IDS_SHARING_HUB_TITLE);
+}
+
+Profile* SharingHubBubbleController::GetProfile() const {
+  return Profile::FromBrowserContext(web_contents_->GetBrowserContext());
+}
+
+void SharingHubBubbleController::OnBubbleClosed() {
+  sharing_hub_bubble_view_ = nullptr;
+}
+
+SharingHubBubbleController::SharingHubBubbleController() = default;
+
+SharingHubBubbleController::SharingHubBubbleController(
+    content::WebContents* web_contents)
+    : web_contents_(web_contents) {
+  DCHECK(web_contents);
+}
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(SharingHubBubbleController)
+
+}  // namespace sharing_hub
diff --git a/chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.h b/chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.h
new file mode 100644
index 0000000..627f193a
--- /dev/null
+++ b/chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.h
@@ -0,0 +1,64 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_SHARING_HUB_SHARING_HUB_BUBBLE_CONTROLLER_H_
+#define CHROME_BROWSER_UI_SHARING_HUB_SHARING_HUB_BUBBLE_CONTROLLER_H_
+
+#include "content/public/browser/web_contents_user_data.h"
+
+class Profile;
+
+namespace content {
+class WebContents;
+}  // namespace content
+
+namespace sharing_hub {
+
+class SharingHubBubbleView;
+
+// Controller component of the Sharing Hub dialog bubble.
+// Responsible for showing and hiding an owned bubble.
+class SharingHubBubbleController
+    : public content::WebContentsUserData<SharingHubBubbleController> {
+ public:
+  ~SharingHubBubbleController() override;
+
+  static SharingHubBubbleController* CreateOrGetFromWebContents(
+      content::WebContents* web_contents);
+
+  // Hides the Sharing Hub bubble.
+  void HideBubble();
+  // Displays the Sharing Hub bubble.
+  void ShowBubble();
+
+  // Returns nullptr if no bubble is currently shown.
+  SharingHubBubbleView* sharing_hub_bubble_view() const;
+  // Returns the title of the Sharing Hub bubble.
+  std::u16string GetWindowTitle() const;
+  // Returns the current profile.
+  Profile* GetProfile() const;
+
+  // Handler for when the bubble is closed.
+  void OnBubbleClosed();
+
+ protected:
+  SharingHubBubbleController();
+  explicit SharingHubBubbleController(content::WebContents* web_contents);
+
+ private:
+  friend class content::WebContentsUserData<SharingHubBubbleController>;
+
+  // The web_contents associated with this controller.
+  content::WebContents* web_contents_;
+  // Weak reference. Will be nullptr if no bubble is currently shown.
+  SharingHubBubbleView* sharing_hub_bubble_view_ = nullptr;
+
+  WEB_CONTENTS_USER_DATA_KEY_DECL();
+
+  DISALLOW_COPY_AND_ASSIGN(SharingHubBubbleController);
+};
+
+}  // namespace sharing_hub
+
+#endif  // CHROME_BROWSER_UI_SHARING_HUB_SHARING_HUB_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/sharing_hub/sharing_hub_bubble_view.h b/chrome/browser/ui/sharing_hub/sharing_hub_bubble_view.h
new file mode 100644
index 0000000..e7e8618
--- /dev/null
+++ b/chrome/browser/ui/sharing_hub/sharing_hub_bubble_view.h
@@ -0,0 +1,22 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_SHARING_HUB_SHARING_HUB_BUBBLE_VIEW_H_
+#define CHROME_BROWSER_UI_SHARING_HUB_SHARING_HUB_BUBBLE_VIEW_H_
+
+namespace sharing_hub {
+
+// Interface to display the Sharing hub bubble.
+// This object is responsible for its own lifetime.
+class SharingHubBubbleView {
+ public:
+  virtual ~SharingHubBubbleView() = default;
+
+  // Closes the bubble and prevents future calls into the controller.
+  virtual void Hide() = 0;
+};
+
+}  // namespace sharing_hub
+
+#endif  // CHROME_BROWSER_UI_SHARING_HUB_SHARING_HUB_BUBBLE_VIEW_H_
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc
index 02127324..81e6351 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.cc
+++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -126,7 +126,10 @@
       UpgradeDetector::GetInstance()->is_outdated_install_no_au()) {
     return l10n_util::GetStringUTF16(IDS_UPGRADE_BUBBLE_MENU_ITEM);
   } else {
-    return l10n_util::GetStringUTF16(IDS_UPDATE_NOW);
+    return l10n_util::GetStringUTF16(
+        base::FeatureList::IsEnabled(features::kUseRelaunchToUpdateString)
+            ? IDS_RELAUNCH_TO_UPDATE
+            : IDS_UPDATE_NOW);
   }
 }
 
diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc
index 9240f12..8f26920 100644
--- a/chrome/browser/ui/ui_features.cc
+++ b/chrome/browser/ui/ui_features.cc
@@ -162,6 +162,9 @@
 const base::Feature kToolbarUseHardwareBitmapDraw{
     "ToolbarUseHardwareBitmapDraw", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kUseRelaunchToUpdateString{
+    "UseRelaunchToUpdateString", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enables a web-based separator that's only used for performance testing. See
 // https://crbug.com/993502.
 const base::Feature kWebFooterExperiment{"WebFooterExperiment",
diff --git a/chrome/browser/ui/ui_features.h b/chrome/browser/ui/ui_features.h
index 7a5e3382..76dbf0a 100644
--- a/chrome/browser/ui/ui_features.h
+++ b/chrome/browser/ui/ui_features.h
@@ -118,6 +118,10 @@
 // Works on Android 10+.
 extern const base::Feature kToolbarUseHardwareBitmapDraw;
 
+// Whether to label the update menu item as "Relaunch to update Chrome", rather
+// than "Update Google Chrome".
+extern const base::Feature kUseRelaunchToUpdateString;
+
 extern const base::Feature kWebFooterExperiment;
 
 extern const base::Feature kWebUIBubblePerProfilePersistence;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
index d5d3005..d2c03ecc 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <utility>
 
+#include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "build/buildflag.h"
 #include "build/chromeos_buildflags.h"
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
index 843f8f87..04a50cf 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
@@ -12,6 +12,7 @@
 #include "base/containers/adapters.h"
 #include "base/numerics/ranges.h"
 #include "base/stl_util.h"
+#include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view.h b/chrome/browser/ui/views/global_media_controls/media_dialog_view.h
index d37be90..eeb5f2e8 100644
--- a/chrome/browser/ui/views/global_media_controls/media_dialog_view.h
+++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view.h
@@ -11,10 +11,10 @@
 
 #include "base/observer_list.h"
 #include "base/optional.h"
-#include "chrome/browser/accessibility/soda_installer.h"
 #include "chrome/browser/ui/global_media_controls/media_dialog_delegate.h"
 #include "chrome/browser/ui/global_media_controls/media_notification_container_observer.h"
 #include "chrome/browser/ui/views/global_media_controls/global_media_controls_types.h"
+#include "components/soda/soda_installer.h"
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
 #include "ui/views/metadata/metadata_header_macros.h"
 
diff --git a/chrome/browser/ui/views/sharing_hub/DIR_METADATA b/chrome/browser/ui/views/sharing_hub/DIR_METADATA
new file mode 100644
index 0000000..167ca6e
--- /dev/null
+++ b/chrome/browser/ui/views/sharing_hub/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "UI>Browser>Sharing"
+}
diff --git a/chrome/browser/ui/views/sharing_hub/OWNERS b/chrome/browser/ui/views/sharing_hub/OWNERS
new file mode 100644
index 0000000..17451040
--- /dev/null
+++ b/chrome/browser/ui/views/sharing_hub/OWNERS
@@ -0,0 +1 @@
+file://components/send_tab_to_self/OWNERS
diff --git a/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.cc b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.cc
new file mode 100644
index 0000000..f59104d
--- /dev/null
+++ b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.cc
@@ -0,0 +1,75 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.h"
+
+#include "chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.h"
+#include "chrome/browser/ui/views/chrome_layout_provider.h"
+#include "chrome/grit/generated_resources.h"
+#include "ui/views/controls/scroll_view.h"
+#include "ui/views/layout/fill_layout.h"
+
+namespace sharing_hub {
+
+SharingHubBubbleViewImpl::SharingHubBubbleViewImpl(
+    views::View* anchor_view,
+    content::WebContents* web_contents,
+    SharingHubBubbleController* controller)
+    : LocationBarBubbleDelegateView(anchor_view, web_contents),
+      controller_(controller) {
+  SetButtons(ui::DIALOG_BUTTON_NONE);
+  set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric(
+      views::DISTANCE_BUBBLE_PREFERRED_WIDTH));
+  DCHECK(controller);
+}
+
+SharingHubBubbleViewImpl::~SharingHubBubbleViewImpl() = default;
+
+void SharingHubBubbleViewImpl::Hide() {
+  if (controller_) {
+    controller_->OnBubbleClosed();
+    controller_ = nullptr;
+  }
+  CloseBubble();
+}
+
+bool SharingHubBubbleViewImpl::ShouldShowCloseButton() const {
+  return true;
+}
+
+std::u16string SharingHubBubbleViewImpl::GetWindowTitle() const {
+  return controller_->GetWindowTitle();
+}
+
+void SharingHubBubbleViewImpl::WindowClosing() {
+  if (controller_) {
+    controller_->OnBubbleClosed();
+    controller_ = nullptr;
+  }
+}
+
+void SharingHubBubbleViewImpl::OnPaint(gfx::Canvas* canvas) {
+  views::BubbleDialogDelegateView::OnPaint(canvas);
+}
+
+void SharingHubBubbleViewImpl::Show(DisplayReason reason) {
+  ShowForReason(reason);
+}
+
+const views::View* SharingHubBubbleViewImpl::GetButtonContainerForTesting()
+    const {
+  return scroll_view_->contents();
+}
+
+void SharingHubBubbleViewImpl::Init() {
+  SetLayoutManager(std::make_unique<views::FillLayout>());
+
+  CreateScrollView();
+}
+
+void SharingHubBubbleViewImpl::CreateScrollView() {
+  scroll_view_ = AddChildView(std::make_unique<views::ScrollView>());
+}
+
+}  // namespace sharing_hub
diff --git a/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.h b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.h
new file mode 100644
index 0000000..af6d75e
--- /dev/null
+++ b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.h
@@ -0,0 +1,73 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_SHARING_HUB_SHARING_HUB_BUBBLE_VIEW_IMPL_H_
+#define CHROME_BROWSER_UI_VIEWS_SHARING_HUB_SHARING_HUB_BUBBLE_VIEW_IMPL_H_
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ui/sharing_hub/sharing_hub_bubble_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h"
+
+namespace gfx {
+class Canvas;
+}  // namespace gfx
+
+namespace content {
+class WebContents;
+}  // namespace content
+
+namespace sharing_hub {
+
+class SharingHubBubbleController;
+
+// View component of the Sharing Hub bubble that allows users to share/save the
+// current page.
+class SharingHubBubbleViewImpl : public SharingHubBubbleView,
+                                 public LocationBarBubbleDelegateView {
+ public:
+  // Bubble will be anchored to |anchor_view|.
+  SharingHubBubbleViewImpl(views::View* anchor_view,
+                           content::WebContents* web_contents,
+                           SharingHubBubbleController* controller);
+
+  ~SharingHubBubbleViewImpl() override;
+
+  // SharingHubBubbleView:
+  void Hide() override;
+
+  // views::WidgetDelegateView:
+  bool ShouldShowCloseButton() const override;
+  std::u16string GetWindowTitle() const override;
+  void WindowClosing() override;
+
+  // LocationBarBubbleDelegateView:
+  void OnPaint(gfx::Canvas* canvas) override;
+
+  // Shows the bubble view.
+  void Show(DisplayReason reason);
+
+  const views::View* GetButtonContainerForTesting() const;
+
+ private:
+  // views::BubbleDialogDelegateView:
+  void Init() override;
+
+  // Creates the scroll view.
+  void CreateScrollView();
+
+  // A raw pointer is safe since our controller will outlive us (the bubble is
+  // lazily created with the controller).
+  SharingHubBubbleController* controller_;
+
+  // ScrollView containing the list of share/save actions.
+  views::ScrollView* scroll_view_ = nullptr;
+
+  base::WeakPtrFactory<SharingHubBubbleViewImpl> weak_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(SharingHubBubbleViewImpl);
+};
+
+}  // namespace sharing_hub
+
+#endif  // CHROME_BROWSER_UI_VIEWS_SHARING_HUB_SHARING_HUB_BUBBLE_VIEW_IMPL_H_
diff --git a/chrome/browser/ui/views/sharing_hub/sharing_hub_icon_view.cc b/chrome/browser/ui/views/sharing_hub/sharing_hub_icon_view.cc
new file mode 100644
index 0000000..44ef046f
--- /dev/null
+++ b/chrome/browser/ui/views/sharing_hub/sharing_hub_icon_view.cc
@@ -0,0 +1,77 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/sharing_hub/sharing_hub_icon_view.h"
+
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/ui/browser_command_controller.h"
+#include "chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.h"
+#include "chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.h"
+#include "components/omnibox/browser/omnibox_view.h"
+#include "ui/views/metadata/metadata_impl_macros.h"
+
+namespace sharing_hub {
+
+SharingHubIconView::SharingHubIconView(
+    CommandUpdater* command_updater,
+    IconLabelBubbleView::Delegate* icon_label_bubble_delegate,
+    PageActionIconView::Delegate* page_action_icon_delegate)
+    : PageActionIconView(command_updater,
+                         IDC_SHARING_HUB,
+                         icon_label_bubble_delegate,
+                         page_action_icon_delegate) {
+  SetVisible(false);
+}
+
+SharingHubIconView::~SharingHubIconView() = default;
+
+views::BubbleDialogDelegate* SharingHubIconView::GetBubble() const {
+  SharingHubBubbleController* controller = GetController();
+  if (!controller) {
+    return nullptr;
+  }
+
+  return static_cast<SharingHubBubbleViewImpl*>(
+      controller->sharing_hub_bubble_view());
+}
+
+void SharingHubIconView::UpdateImpl() {
+  content::WebContents* web_contents = GetWebContents();
+  if (!web_contents) {
+    return;
+  }
+
+  const OmniboxView* omnibox_view = delegate()->GetOmniboxView();
+  if (!omnibox_view) {
+    return;
+  }
+
+  SetVisible(true);
+}
+
+void SharingHubIconView::OnExecuting(
+    PageActionIconView::ExecuteSource execute_source) {}
+
+const gfx::VectorIcon& SharingHubIconView::GetVectorIcon() const {
+  // TODO(1186843): Add Share icon.
+  return kAddIcon;
+}
+
+bool SharingHubIconView::ShouldShowLabel() const {
+  return false;
+}
+
+SharingHubBubbleController* SharingHubIconView::GetController() const {
+  content::WebContents* web_contents = GetWebContents();
+  if (!web_contents) {
+    return nullptr;
+  }
+  return SharingHubBubbleController::CreateOrGetFromWebContents(web_contents);
+}
+
+BEGIN_METADATA(SharingHubIconView, PageActionIconView)
+END_METADATA
+
+}  // namespace sharing_hub
diff --git a/chrome/browser/ui/views/sharing_hub/sharing_hub_icon_view.h b/chrome/browser/ui/views/sharing_hub/sharing_hub_icon_view.h
new file mode 100644
index 0000000..fc883911
--- /dev/null
+++ b/chrome/browser/ui/views/sharing_hub/sharing_hub_icon_view.h
@@ -0,0 +1,46 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_SHARING_HUB_SHARING_HUB_ICON_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_SHARING_HUB_SHARING_HUB_ICON_VIEW_H_
+
+#include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
+#include "ui/views/metadata/metadata_header_macros.h"
+
+class CommandUpdater;
+
+namespace sharing_hub {
+
+class SharingHubBubbleController;
+
+// The location bar icon to show the Sharing Hub bubble, where the user can
+// choose to share the current page to a sharing target or save the page using
+// first party actions.
+class SharingHubIconView : public PageActionIconView {
+ public:
+  METADATA_HEADER(SharingHubIconView);
+  SharingHubIconView(CommandUpdater* command_updater,
+                     IconLabelBubbleView::Delegate* icon_label_bubble_delegate,
+                     PageActionIconView::Delegate* page_action_icon_delegate);
+  SharingHubIconView(const SharingHubIconView&) = delete;
+  SharingHubIconView& operator=(const SharingHubIconView&) = delete;
+  ~SharingHubIconView() override;
+
+  // PageActionIconView:
+  views::BubbleDialogDelegate* GetBubble() const override;
+  void UpdateImpl() override;
+  bool ShouldShowLabel() const override;
+
+ protected:
+  // PageActionIconView:
+  void OnExecuting(PageActionIconView::ExecuteSource execute_source) override;
+  const gfx::VectorIcon& GetVectorIcon() const override;
+
+ private:
+  SharingHubBubbleController* GetController() const;
+};
+
+}  // namespace sharing_hub
+
+#endif  // CHROME_BROWSER_UI_VIEWS_SHARING_HUB_SHARING_HUB_ICON_VIEW_H_
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
index 7288082..8e62718 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -16,6 +16,7 @@
 #include "base/i18n/rtl.h"
 #include "base/numerics/ranges.h"
 #include "base/numerics/safe_conversions.h"
+#include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/chrome_notification_types.h"
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_controller.cc b/chrome/browser/ui/views/tabs/tab_hover_card_controller.cc
index a3b3a7a7..1cffdf7 100644
--- a/chrome/browser/ui/views/tabs/tab_hover_card_controller.cc
+++ b/chrome/browser/ui/views/tabs/tab_hover_card_controller.cc
@@ -201,6 +201,10 @@
 void TabHoverCardController::UpdateHoverCard(
     Tab* tab,
     TabController::HoverCardUpdateType update_type) {
+  // Never display a hover card for a closing tab.
+  if (tab && tab->closing())
+    tab = nullptr;
+
   // Update this ASAP so that if we try to fade-in and we have the wrong target
   // then when the fade timer elapses we won't incorrectly try to fade in on the
   // wrong tab.
@@ -301,17 +305,18 @@
     delayed_show_timer_.Start(
         FROM_HERE, GetShowDelay(tab->width()),
         base::BindOnce(&TabHoverCardController::ShowHoverCard,
-                       base::Unretained(this), true));
+                       base::Unretained(this), true, tab));
   } else {
     DCHECK_EQ(target_tab_, tab);
-    ShowHoverCard(is_initial);
+    ShowHoverCard(is_initial, tab);
   }
 }
 
-void TabHoverCardController::ShowHoverCard(bool is_initial) {
+void TabHoverCardController::ShowHoverCard(bool is_initial,
+                                           const Tab* intended_tab) {
   // Make sure the hover card isn't accidentally shown if it's already visible
-  // or if the anchor is gone.
-  if (hover_card_ || !target_tab_)
+  // or if the anchor is gone or changed.
+  if (hover_card_ || target_tab_ != intended_tab)
     return;
 
   CreateHoverCard(target_tab_);
@@ -547,8 +552,16 @@
     TabHoverCardThumbnailObserver* observer,
     gfx::ImageSkia thumbnail_image) {
   DCHECK_EQ(thumbnail_observer_.get(), observer);
-  if (waiting_for_preview_)
-    metrics_->ImageLoadedForTab(target_tab_);
+
+  const bool was_waiting_for_preview = waiting_for_preview_;
   waiting_for_preview_ = false;
+
+  // The hover card could be destroyed before the preview image is delivered.
+  if (!hover_card_)
+    return;
+  if (was_waiting_for_preview && target_tab_)
+    metrics_->ImageLoadedForTab(target_tab_);
+  // Can still set image on a fading-out hover card (we can change this behavior
+  // later if we want).
   hover_card_->SetPreviewImage(thumbnail_image);
 }
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_controller.h b/chrome/browser/ui/views/tabs/tab_hover_card_controller.h
index 753d8998..bdf1840 100644
--- a/chrome/browser/ui/views/tabs/tab_hover_card_controller.h
+++ b/chrome/browser/ui/views/tabs/tab_hover_card_controller.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/callback_list.h"
+#include "base/gtest_prod_util.h"
 #include "base/scoped_observation.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/ui/views/tabs/tab_controller.h"
@@ -48,6 +49,9 @@
   friend class TabHoverCardBubbleViewBrowserTest;
   friend class TabHoverCardBubbleViewInteractiveUiTest;
   friend class TabHoverCardMetrics;
+  FRIEND_TEST_ALL_PREFIXES(TabHoverCardControllerTest, ShowWrongTabDoesntCrash);
+  FRIEND_TEST_ALL_PREFIXES(TabHoverCardControllerTest,
+                           SetPreviewWithNoHoverCardDoesntCrash);
   class EventSniffer;
 
   static bool UseAnimations();
@@ -68,7 +72,7 @@
 
   void UpdateOrShowCard(Tab* tab,
                         TabController::HoverCardUpdateType update_type);
-  void ShowHoverCard(bool is_initial);
+  void ShowHoverCard(bool is_initial, const Tab* intended_tab);
   void HideHoverCard();
 
   bool ShouldShowImmediately(const Tab* tab) const;
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_controller_unittest.cc b/chrome/browser/ui/views/tabs/tab_hover_card_controller_unittest.cc
new file mode 100644
index 0000000..981c99f
--- /dev/null
+++ b/chrome/browser/ui/views/tabs/tab_hover_card_controller_unittest.cc
@@ -0,0 +1,29 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/tabs/tab_hover_card_controller.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+// These are regression tests for possible crashes.
+
+TEST(TabHoverCardControllerTest, ShowWrongTabDoesntCrash) {
+  auto controller = std::make_unique<TabHoverCardController>(nullptr);
+  // Create some completely invalid pointer values (these should never be
+  // dereferenced).
+  Tab* const tab1 = reinterpret_cast<Tab*>(3);
+  Tab* const tab2 = reinterpret_cast<Tab*>(7);
+  controller->target_tab_ = tab1;
+  // If the safeguard is not in place, this will crash because the target tab is
+  // not a valid pointer.
+  controller->ShowHoverCard(false, tab2);
+}
+
+TEST(TabHoverCardControllerTest, SetPreviewWithNoHoverCardDoesntCrash) {
+  auto controller = std::make_unique<TabHoverCardController>(nullptr);
+  // If the safeguard is not in place, this could crash in either metrics
+  // collection *or* in trying to set the actual thumbnail image on the card.
+  controller->OnPreviewImageAvaialble(controller->thumbnail_observer_.get(),
+                                      gfx::ImageSkia());
+}
diff --git a/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc b/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc
index 500ddf0..1445164 100644
--- a/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc
+++ b/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc
@@ -150,35 +150,24 @@
   // Terminal should be launched with crostini::LaunchTerminal*.
   DCHECK(type != SystemAppType::TERMINAL);
 
-  // TODO(https://crbug.com/1135863): Implement a SWA-wide approach to handle
-  // launching (or link capturing) from incognito.
-  if (type == SystemAppType::SETTINGS) {
-    // In non-guest incognito profile, OS Settings will silently launch into
-    // the original profile.
-    if (!profile->IsGuestSession() && profile->IsIncognitoProfile()) {
-      profile = profile->GetOriginalProfile();
-    }
-  }
-
+  // TODO(https://crbug.com/1135863): Implement a confirmation dialog when
+  // changing to a different profile.
   Profile* profile_for_launch = GetProfileForSystemWebAppLaunch(profile);
-  if (profile_for_launch == nullptr || profile_for_launch != profile) {
-    // The provided profile can't launch system web apps. Complain about this so
-    // we can catch the call site, and ask them to pick the right profile.
+  if (profile_for_launch == nullptr) {
+    // We can't find a suitable profile to launch. Complain about this so we
+    // can identify the call site, and ask them to pick the right profile.
     base::debug::DumpWithoutCrashing();
 
     DVLOG(1)
         << "LaunchSystemWebAppAsync is called on a profile that can't launch "
-           "system web apps. Please check the profile you are using is correct."
-        << (profile_for_launch
-                ? "Instead, launch the app into a suitable profile "
-                  "based on your intention."
-                : "Can't find a suitable profile based on the provided "
-                  "argument. Thus ignore the launch request.");
+           "system web apps. The launch request is ignored. Please check the "
+           "profile you are using is correct.";
 
+    // This will DCHECK in debug builds. But no-op in production builds.
     NOTREACHED();
 
-    if (profile_for_launch == nullptr)
-      return;
+    // Early return if we can't find a profile to launch.
+    return;
   }
 
   const base::Optional<AppId> app_id =
diff --git a/chrome/browser/ui/web_applications/system_web_app_ui_utils.h b/chrome/browser/ui/web_applications/system_web_app_ui_utils.h
index b74da854..4e4be0f 100644
--- a/chrome/browser/ui/web_applications/system_web_app_ui_utils.h
+++ b/chrome/browser/ui/web_applications/system_web_app_ui_utils.h
@@ -55,6 +55,16 @@
 // launch behavior (e.g. launch to app's subpage, specifying launch source for
 // metrics). Terminal App should use crostini::LaunchTerminal*.
 //
+// This function will try to find an appropriate launch profile in these
+// circumstances:
+//
+//   - Incognito profile of a normal session: Launch to original profile, which
+//     the incognito profile is created from
+//   - Profiles in guest session: Launch to the primary off-the-record profile
+//     (the profile used to browser websites in guest sessions)
+//   - Other unsuitable profiles (e.g. Sign-in profile): Don't launch, and send
+//     a crash report
+//
 // In tests, remember to call FlushSystemWebAppLaunchesForTesting on the same
 // |profile|, or use TestNavigationObserver to wait the navigation.
 void LaunchSystemWebAppAsync(
diff --git a/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc b/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc
index 544bd8b..37c5755 100644
--- a/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc
+++ b/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc
@@ -422,19 +422,8 @@
                           ->GetLastCommittedURL());
 }
 
-// TODO(crbug.com/1135863): Decide and formalize this behavior. This test is
-// disabled in DCHECK builds, because it hits a DCHECK in
-// LaunchSystemWebAppAsync. In production builds, SWA is link captured to the
-// original profile. The goal is to behave reasonably, and not crashing.
-#if DCHECK_IS_ON()
-#define MAYBE_IncognitoBrowserOmniboxLinkCapture \
-  DISABLED_IncognitoBrowserOmniboxLinkCapture
-#else
-#define MAYBE_IncognitoBrowserOmniboxLinkCapture \
-  IncognitoBrowserOmniboxLinkCapture
-#endif
 IN_PROC_BROWSER_TEST_P(SystemWebAppLinkCaptureBrowserTest,
-                       MAYBE_IncognitoBrowserOmniboxLinkCapture) {
+                       IncognitoBrowserOmniboxLinkCapture) {
   WaitForTestSystemAppInstall();
 
   Browser* incognito_browser = CreateIncognitoBrowser();
@@ -676,13 +665,7 @@
 
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-// The following tests are disabled in DCHECK builds. LaunchSystemWebAppAsync
-// DCHECKs if the wrong profile is used. EXPECT_DCHECK_DEATH (or its variants)
-// aren't reliable in browsertests, so we don't test this. This is okay because
-// these tests are used to verify that in release builds,
-// LaunchSystemWebAppAsync doesn't crash and behaves reasonably (pick an
-// appropriate profile).
-#if BUILDFLAG(IS_CHROMEOS_ASH) && !DCHECK_IS_ON()
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 using SystemWebAppLaunchProfileBrowserTest = SystemWebAppManagerBrowserTest;
 
 IN_PROC_BROWSER_TEST_P(SystemWebAppLaunchProfileBrowserTest,
@@ -703,6 +686,11 @@
   EXPECT_TRUE(FindSystemWebAppBrowser(startup_profile, GetMockAppType()));
 }
 
+#if !DCHECK_IS_ON()
+// The following tests are disabled in DCHECK builds. LaunchSystemWebAppAsync
+// DCHECKs if it can't find a suitable profile. EXPECT_DCHECK_DEATH (or its
+// variants) aren't reliable in browsertests, so we don't test this. Here we
+// to verify LaunchSystemWebAppAsync doesn't crash in release builds
 IN_PROC_BROWSER_TEST_P(SystemWebAppLaunchProfileBrowserTest,
                        LaunchFromSignInProfile) {
   WaitForTestSystemAppInstall();
@@ -723,6 +711,7 @@
 
   EXPECT_EQ(1U, chrome::GetTotalBrowserCount());
 }
+#endif  // !DCHECK_IS_ON()
 
 using SystemWebAppLaunchProfileGuestSessionBrowserTest =
     SystemWebAppLaunchProfileBrowserTest;
@@ -765,7 +754,7 @@
 
   EXPECT_TRUE(FindSystemWebAppBrowser(startup_profile, GetMockAppType()));
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) && !DCHECK_IS_ON()
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 using SystemWebAppLaunchOmniboxNavigateBrowsertest =
@@ -868,7 +857,7 @@
 INSTANTIATE_SYSTEM_WEB_APP_MANAGER_TEST_SUITE_REGULAR_PROFILE_P(
     SystemWebAppLinkCaptureBrowserTest);
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) && !DCHECK_IS_ON()
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 INSTANTIATE_SYSTEM_WEB_APP_MANAGER_TEST_SUITE_REGULAR_PROFILE_P(
     SystemWebAppLaunchProfileBrowserTest);
 
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 429142a2..81d623db 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
@@ -21,7 +21,7 @@
 #endif  // defined(OS_ANDROID)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "chrome/browser/ash/web_applications/media_app_guest_ui_config.h"
+#include "chrome/browser/ash/web_applications/media_app/media_app_guest_ui_config.h"
 #include "chrome/browser/ash/web_applications/terminal_ui.h"
 #include "chromeos/components/personalization_app/untrusted_personalization_app_ui_config.h"
 #if !defined(OFFICIAL_BUILD)
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index 6e950d2..7601cd4 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -165,9 +165,9 @@
 #include "chrome/browser/ash/scanning/scan_service.h"
 #include "chrome/browser/ash/scanning/scan_service_factory.h"
 #include "chrome/browser/ash/web_applications/chrome_camera_app_ui_delegate.h"
-#include "chrome/browser/ash/web_applications/chrome_media_app_ui_delegate.h"
 #include "chrome/browser/ash/web_applications/chrome_personalization_app_ui_delegate.h"
 #include "chrome/browser/ash/web_applications/help_app/help_app_ui_delegate.h"
+#include "chrome/browser/ash/web_applications/media_app/chrome_media_app_ui_delegate.h"
 #include "chrome/browser/chromeos/device_sync/device_sync_client_factory.h"
 #include "chrome/browser/chromeos/eche_app/eche_app_manager_factory.h"
 #include "chrome/browser/chromeos/multidevice_setup/multidevice_setup_service_factory.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
index f06c846..349a855 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -32,6 +32,7 @@
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
 #include "base/timer/timer.h"
+#include "base/trace_event/trace_event.h"
 #include "base/values.h"
 #include "chrome/browser/ash/authpolicy/authpolicy_helper.h"
 #include "chrome/browser/ash/certificate_provider/certificate_provider_service.h"
diff --git a/chrome/browser/ui/webui/download_shelf/download_shelf_page_handler.cc b/chrome/browser/ui/webui/download_shelf/download_shelf_page_handler.cc
index e5dd348..2d292fb 100644
--- a/chrome/browser/ui/webui/download_shelf/download_shelf_page_handler.cc
+++ b/chrome/browser/ui/webui/download_shelf/download_shelf_page_handler.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/webui/download_shelf/download_shelf_page_handler.h"
 
 #include "base/strings/utf_string_conversions.h"
+#include "base/trace_event/trace_event.h"
 #include "chrome/browser/download/download_item_model.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/download_shelf/download_shelf_ui.h"
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
index 00acc8a..ae39cb9 100644
--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
+++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
@@ -218,6 +218,7 @@
       {"modulesRecipeTasksLower", IDS_NTP_MODULES_RECIPE_TASKS_LOWER},
       {"modulesRecipeTasksLowerThese",
        IDS_NTP_MODULES_RECIPE_TASKS_LOWER_THESE},
+      {"modulesTasksInfo", IDS_NTP_MODULES_TASKS_INFO},
       {"modulesCartSentence", IDS_NTP_MODULES_CART_SENTENCE},
       {"modulesCartLower", IDS_NTP_MODULES_CART_LOWER},
       {"modulesCartLowerThese", IDS_NTP_MODULES_CART_LOWER_THESE},
@@ -225,6 +226,7 @@
       {"modulesDriveSentence", IDS_NTP_MODULES_DRIVE_SENTENCE},
       {"modulesDummyLower", IDS_NTP_MODULES_DUMMY_LOWER},
       {"modulesDriveTitle", IDS_NTP_MODULES_DRIVE_TITLE},
+      {"modulesDriveInfo", IDS_NTP_MODULES_DRIVE_INFO},
       {"modulesDummyTitle", IDS_NTP_MODULES_DUMMY_TITLE},
       {"modulesDummy2Title", IDS_NTP_MODULES_DUMMY2_TITLE},
       {"modulesKaleidoscopeTitle", IDS_NTP_MODULES_KALEIDOSCOPE_TITLE},
@@ -261,15 +263,6 @@
   };
   source->AddLocalizedStrings(kStrings);
 
-  source->AddString(
-      "modulesTasksInfo1",
-      l10n_util::GetStringFUTF16(IDS_NTP_MODULES_SHOPPING_TASKS_INFO_1,
-                                 u"https://myactivity.google.com/"));
-  source->AddString(
-      "modulesTasksInfo2",
-      l10n_util::GetStringFUTF16(IDS_NTP_MODULES_SHOPPING_TASKS_INFO_2,
-                                 u"https://policies.google.com/"));
-
   // Register images that are purposefully not inlined in the HTML and instead
   // are set in Javascript.
   static constexpr webui::ResourcePath kImages[] = {
diff --git a/chrome/browser/ui/webui/settings/captions_handler.h b/chrome/browser/ui/webui/settings/captions_handler.h
index 53cd6a2d..5bc1df6 100644
--- a/chrome/browser/ui/webui/settings/captions_handler.h
+++ b/chrome/browser/ui/webui/settings/captions_handler.h
@@ -5,8 +5,8 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CAPTIONS_HANDLER_H_
 #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CAPTIONS_HANDLER_H_
 
-#include "chrome/browser/accessibility/soda_installer.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
+#include "components/soda/soda_installer.h"
 
 class PrefService;
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/languages_section.cc b/chrome/browser/ui/webui/settings/chromeos/languages_section.cc
index c4cd972..ca66dd75 100644
--- a/chrome/browser/ui/webui/settings/chromeos/languages_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/languages_section.cc
@@ -342,6 +342,12 @@
        IDS_OS_SETTINGS_LANGUAGES_DELETE_DICTIONARY_WORD_TOOLTIP},
       {"noDictionaryWordsLabel",
        IDS_OS_SETTINGS_LANGUAGES_NO_DICTIONARY_WORDS_LABEL},
+      {"imeShortcutReminderTitle",
+       IDS_OS_SETTINGS_LANGUAGES_SHORTCUT_REMINDER_TITLE},
+      {"imeShortcutReminderLastUsed",
+       IDS_OS_SETTINGS_LANGUAGES_SHORTCUT_REMINDER_LAST_USED_IME_DESCRIPTION},
+      {"imeShortcutReminderNext",
+       IDS_OS_SETTINGS_LANGUAGES_SHORTCUT_REMINDER_NEXT_IME_DESCRIPTION},
   };
   html_source->AddLocalizedStrings(kLocalizedStrings);
 }
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index 2dfaa79..8097e76 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -1611,22 +1611,8 @@
        IDS_SETTINGS_SEARCH_ENGINES_REMOVE_FROM_LIST},
       {"searchEnginesManageExtension",
        IDS_SETTINGS_SEARCH_ENGINES_MANAGE_EXTENSION},
-      // TODO(yoangela): Placeholder strings, update when these strings are
-      // finalized.
-      {"searchEnginesTriggerOptions",
-       IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_OPTIONS},
-      {"searchEnginesTriggerDescription",
-       IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_DESCRIPTION},
-      {"searchEnginesTriggerSpaceEnabled",
-       IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_SPACE_ENABLED},
-      {"searchEnginesTriggerSpaceDisabled",
-       IDS_SETTINGS_SEARCH_ENGINES_TRIGGER_SPACE_DISABLED},
-
   };
   html_source->AddLocalizedStrings(kLocalizedStrings);
-  html_source->AddBoolean(
-      "showKeywordTriggerSetting",
-      base::FeatureList::IsEnabled(omnibox::kKeywordSpaceTriggeringSetting));
 }
 
 void AddSiteSettingsStrings(content::WebUIDataSource* html_source,
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
index e1c5246..2288f7ca 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
+++ b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
@@ -6,6 +6,7 @@
 
 #include "base/metrics/histogram_functions.h"
 #include "base/numerics/ranges.h"
+#include "base/trace_event/trace_event.h"
 #include "build/branding_buildflags.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/ui_features.h"
diff --git a/chrome/browser/web_applications/system_web_apps/system_web_app_manager.cc b/chrome/browser/web_applications/system_web_apps/system_web_app_manager.cc
index d83be9a..51f5721 100644
--- a/chrome/browser/web_applications/system_web_apps/system_web_app_manager.cc
+++ b/chrome/browser/web_applications/system_web_apps/system_web_app_manager.cc
@@ -66,7 +66,7 @@
 #include "chrome/browser/ash/web_applications/diagnostics_system_web_app_info.h"
 #include "chrome/browser/ash/web_applications/eche_app_info.h"
 #include "chrome/browser/ash/web_applications/help_app/help_app_web_app_info.h"
-#include "chrome/browser/ash/web_applications/media_web_app_info.h"
+#include "chrome/browser/ash/web_applications/media_app/media_web_app_info.h"
 #include "chrome/browser/ash/web_applications/os_settings_web_app_info.h"
 #include "chrome/browser/ash/web_applications/personalization_app_info.h"
 #include "chrome/browser/ash/web_applications/print_management_web_app_info.h"
diff --git a/chrome/browser/webshare/share_service_unittest.cc b/chrome/browser/webshare/share_service_unittest.cc
index 0e6d1ec..7491e1e 100644
--- a/chrome/browser/webshare/share_service_unittest.cc
+++ b/chrome/browser/webshare/share_service_unittest.cc
@@ -111,8 +111,7 @@
     blob->content_type = content_type;
 
     base::RunLoop run_loop;
-    auto blob_context_getter =
-        content::BrowserContext::GetBlobStorageContext(browser_context());
+    auto blob_context_getter = browser_context()->GetBlobStorageContext();
     content::GetIOThreadTaskRunner({})->PostTaskAndReply(
         FROM_HERE,
         base::BindLambdaForTesting(
diff --git a/chrome/browser/webshare/win/share_operation.cc b/chrome/browser/webshare/win/share_operation.cc
index 2a4d3917..daefc8c0 100644
--- a/chrome/browser/webshare/win/share_operation.cc
+++ b/chrome/browser/webshare/win/share_operation.cc
@@ -535,8 +535,7 @@
       // target app has finished fully processing the shared content this could
       // be updated to be owned/maintained by this ShareOperation instance.
       auto operation = base::MakeRefCounted<OutputStreamWriteOperation>(
-          content::BrowserContext::GetBlobStorageContext(
-              web_contents()->GetBrowserContext()),
+          web_contents()->GetBrowserContext()->GetBlobStorageContext(),
           file_bytes_shared, file->blob->uuid);
       auto name_h = base::win::ScopedHString::Create(file->name);
       auto raw_data_requested_callback =
diff --git a/chrome/browser/webshare/win/share_operation_unittest.cc b/chrome/browser/webshare/win/share_operation_unittest.cc
index 7b59ea3..4f1196c8 100644
--- a/chrome/browser/webshare/win/share_operation_unittest.cc
+++ b/chrome/browser/webshare/win/share_operation_unittest.cc
@@ -156,8 +156,7 @@
     blob->size = contents.size();
 
     base::RunLoop run_loop;
-    auto blob_context_getter =
-        content::BrowserContext::GetBlobStorageContext(browser_context());
+    auto blob_context_getter = browser_context()->GetBlobStorageContext();
     content::GetIOThreadTaskRunner({})->PostTaskAndReply(
         FROM_HERE,
         base::BindLambdaForTesting([&blob_context_getter, &blob, &uuid,
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index c256118..17573d5 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1620064732-359230b552c10051e48ede786a3daf21a06c920e.profdata
+chrome-mac-master-1620106970-3da1f844236021b977ea7e73f73beb8a8a3a068b.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 1677cfd8..8a10e75 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-master-1620064732-fb58268a2310bb74346e8ce0e830efe60236a731.profdata
+chrome-win32-master-1620086341-acf69520ac7a2dab94ac1fe0825c2d2cb271be7b.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index fa2ee7d7..4e4f93a 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-master-1620064732-66e46f2666604e702dbe45771dfc3aede981a242.profdata
+chrome-win64-master-1620097082-ee014ee6157d2427c1736e90c4bcec29d18cca73.profdata
diff --git a/chrome/common/chrome_utility_printing_messages.h b/chrome/common/chrome_utility_printing_messages.h
index 41dbe04..19e287c 100644
--- a/chrome/common/chrome_utility_printing_messages.h
+++ b/chrome/common/chrome_utility_printing_messages.h
@@ -9,6 +9,7 @@
 
 #include "build/build_config.h"
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 #include "ipc/ipc_param_traits.h"
 #include "printing/backend/print_backend.h"
 #include "printing/buildflags/buildflags.h"
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index e81fd82..7a62613d 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -996,6 +996,8 @@
       "../browser/apps/platform_apps/event_page_browsertest.cc",
       "../browser/apps/platform_apps/platform_app_navigation_redirector_browsertest.cc",
       "../browser/apps/platform_apps/service_worker_browsertest.cc",
+      "../browser/attribution_reporting/conversions_usage_restriction_trial_browsertest.cc",
+      "../browser/attribution_reporting/conversions_usecounter_browsertest.cc",
       "../browser/autocomplete/autocomplete_browsertest.cc",
       "../browser/autofill/autofill_autocomplete_browsertest.cc",
       "../browser/autofill/autofill_browsertest.cc",
@@ -1050,8 +1052,6 @@
       "../browser/component_updater/component_patcher_operation_browsertest.cc",
       "../browser/content_index/content_index_browsertest.cc",
       "../browser/content_settings/content_settings_browsertest.cc",
-      "../browser/conversions/conversions_usage_restriction_trial_browsertest.cc",
-      "../browser/conversions/conversions_usecounter_browsertest.cc",
       "../browser/crash_recovery_browsertest.cc",
       "../browser/custom_handlers/protocol_handler_registry_browsertest.cc",
       "../browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc",
@@ -2691,7 +2691,7 @@
         "../browser/ash/web_applications/diagnostics_app_integration_browsertest.cc",
         "../browser/ash/web_applications/eche_app_integration_browsertest.cc",
         "../browser/ash/web_applications/help_app/help_app_integration_browsertest.cc",
-        "../browser/ash/web_applications/media_app_integration_browsertest.cc",
+        "../browser/ash/web_applications/media_app/media_app_integration_browsertest.cc",
         "../browser/ash/web_applications/print_management_app_integration_browsertest.cc",
         "../browser/ash/web_applications/scanning_app_integration_browsertest.cc",
         "../browser/ash/web_applications/settings_app_integration_browsertest.cc",
@@ -4295,6 +4295,12 @@
     "//components/page_load_metrics/common:test_support",
     "//components/query_tiles:unit_tests",
     "//components/reporting/client:test_support",
+    "//components/reporting/encryption:decryption",
+    "//components/reporting/encryption:encryption",
+    "//components/reporting/encryption:encryption_module",
+    "//components/reporting/encryption:encryption_module_interface",
+    "//components/reporting/encryption:test_support",
+    "//components/reporting/encryption:testing_primitives",
     "//components/reporting/storage:storage_uploader_interface",
     "//components/reporting/storage:test_support",
     "//components/reporting/util:test_callbacks_support",
@@ -4309,7 +4315,6 @@
     "//components/services/app_service/public/cpp:protocol_handling",
     "//components/services/patch/content",
     "//components/services/unzip/content",
-    "//components/soda:constants",
     "//components/spellcheck:buildflags",
     "//components/strings",
     "//components/subresource_filter/core/browser:test_support",
@@ -5002,7 +5007,10 @@
       "../renderer/media/webrtc_logging_agent_impl_unittest.cc",
     ]
 
-    deps += [ "//services/network:test_support" ]
+    deps += [
+      "//components/soda:constants",
+      "//services/network:test_support",
+    ]
 
     if (include_js_tests) {
       deps += [ "//chrome/test/data/webui:unit_tests_js" ]
@@ -5624,6 +5632,7 @@
         "../browser/extensions/extension_garbage_collector_chromeos_unittest.cc",
         "../browser/extensions/external_provider_impl_chromeos_unittest.cc",
         "../browser/extensions/system_display/display_info_provider_chromeos_unittest.cc",
+        "../browser/extensions/system_display/system_display_serialization_unittest.cc",
       ]
     }
 
@@ -6257,6 +6266,7 @@
       "../browser/ui/views/tabs/fake_base_tab_strip_controller.cc",
       "../browser/ui/views/tabs/fake_base_tab_strip_controller.h",
       "../browser/ui/views/tabs/stacked_tab_strip_layout_unittest.cc",
+      "../browser/ui/views/tabs/tab_hover_card_controller_unittest.cc",
       "../browser/ui/views/tabs/tab_hover_card_metrics_unittest.cc",
       "../browser/ui/views/tabs/tab_strip_layout_unittest.cc",
       "../browser/ui/views/tabs/tab_strip_unittest.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
index 305ae90c..a3a82417 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
@@ -116,9 +116,6 @@
 
     /**
      * Waits for the AccountTrackerService to seed system accounts.
-     *
-     * TODO(crbug/1185712): We can remove this method once the accounts change event will
-     * be handled properly.
      */
     static void seedAccounts() {
         ThreadUtils.assertOnBackgroundThread();
diff --git a/chrome/test/data/webui/new_tab_page/BUILD.gn b/chrome/test/data/webui/new_tab_page/BUILD.gn
index 2291942..2a02905 100644
--- a/chrome/test/data/webui/new_tab_page/BUILD.gn
+++ b/chrome/test/data/webui/new_tab_page/BUILD.gn
@@ -15,6 +15,7 @@
     ":img_test",
     ":metrics_utils_test",
     ":test_support",
+    "modules:info_dialog_test",
     "modules:module_header_test",
     "modules:module_registry_test",
     "modules:modules_test",
diff --git a/chrome/test/data/webui/new_tab_page/modules/BUILD.gn b/chrome/test/data/webui/new_tab_page/modules/BUILD.gn
index 3cd27df..932ef6c 100644
--- a/chrome/test/data/webui/new_tab_page/modules/BUILD.gn
+++ b/chrome/test/data/webui/new_tab_page/modules/BUILD.gn
@@ -29,3 +29,8 @@
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
 }
+
+js_library("info_dialog_test") {
+  deps = [ "//chrome/browser/resources/new_tab_page" ]
+  externs_list = [ "$externs_path/mocha-2.5.js" ]
+}
diff --git a/chrome/test/data/webui/new_tab_page/modules/drive/module_test.js b/chrome/test/data/webui/new_tab_page/modules/drive/module_test.js
index 60296fb..8d2dc5d 100644
--- a/chrome/test/data/webui/new_tab_page/modules/drive/module_test.js
+++ b/chrome/test/data/webui/new_tab_page/modules/drive/module_test.js
@@ -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 {driveDescriptor, DriveProxy} from 'chrome://new-tab-page/new_tab_page.js';
+import {$$, driveDescriptor, DriveProxy} from 'chrome://new-tab-page/new_tab_page.js';
 import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.m.js';
-import {eventToPromise, isVisible} from 'chrome://test/test_util.m.js';
+import {isVisible} from 'chrome://test/test_util.m.js';
 
 suite('NewTabPageModulesDriveModuleTest', () => {
   /**
@@ -84,4 +84,29 @@
     await testProxy.handler.whenCalled('getFiles');
     assertFalse(!!module);
   });
+
+  test('info button click opens info dialog', async () => {
+    // Arrange.
+    const data = {
+      files: [
+        {
+          justificationText: '',
+          title: '',
+          id: '',
+          mimeType: '',
+          itemUrl: {url: ''},
+        },
+      ]
+    };
+    testProxy.handler.setResultFor('getFiles', Promise.resolve(data));
+    const module = await driveDescriptor.initialize();
+    document.body.append(module);
+
+    // Act.
+    $$(module, 'ntp-module-header')
+        .dispatchEvent(new Event('info-button-click'));
+
+    // Assert.
+    assertTrue(!!$$(module, 'ntp-info-dialog'));
+  });
 });
diff --git a/chrome/test/data/webui/new_tab_page/modules/info_dialog_test.js b/chrome/test/data/webui/new_tab_page/modules/info_dialog_test.js
new file mode 100644
index 0000000..9ce0d259
--- /dev/null
+++ b/chrome/test/data/webui/new_tab_page/modules/info_dialog_test.js
@@ -0,0 +1,34 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {$$, InfoDialogElement} from 'chrome://new-tab-page/new_tab_page.js';
+import {assertFalse, assertTrue} from '../../chai_assert.js';
+
+suite('NewTabPageModulesInfoDialogTest', () => {
+  /** @type {!InfoDialogElement} */
+  let infoDialog;
+
+  setup(() => {
+    document.body.innerHTML = '';
+    infoDialog = new InfoDialogElement();
+    document.body.appendChild(infoDialog);
+  });
+
+  test('can open dialog', () => {
+    assertFalse($$(infoDialog, '#dialog').open);
+    infoDialog.showModal();
+    assertTrue($$(infoDialog, '#dialog').open);
+  });
+
+  test('clicking close button closes cr dialog', () => {
+    // Arrange.
+    infoDialog.showModal();
+
+    // Act.
+    $$(infoDialog, '#closeButton').click();
+
+    // Assert.
+    assertFalse($$(infoDialog, '#dialog').open);
+  });
+});
diff --git a/chrome/test/data/webui/new_tab_page/modules/task_module/module_test.js b/chrome/test/data/webui/new_tab_page/modules/task_module/module_test.js
index d6f362ae..3cba7c18 100644
--- a/chrome/test/data/webui/new_tab_page/modules/task_module/module_test.js
+++ b/chrome/test/data/webui/new_tab_page/modules/task_module/module_test.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {shoppingTasksDescriptor, TaskModuleHandlerProxy} from 'chrome://new-tab-page/new_tab_page.js';
+import {$$, shoppingTasksDescriptor, TaskModuleHandlerProxy} from 'chrome://new-tab-page/new_tab_page.js';
 import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.m.js';
 import {eventToPromise, flushTasks} from 'chrome://test/test_util.m.js';
 
@@ -207,4 +207,23 @@
         [taskModule.mojom.TaskModuleType.kShopping, 'Hello world'],
         await testProxy.handler.whenCalled('restoreTask'));
   });
+
+  test('info button click opens info dialog', async () => {
+    // Arrange.
+    const task = {
+      title: '',
+      taskItems: [],
+      relatedSearches: [],
+    };
+    testProxy.handler.setResultFor('getPrimaryTask', Promise.resolve({task}));
+    const moduleElement = await shoppingTasksDescriptor.initialize();
+    document.body.append(moduleElement);
+
+    // Act.
+    $$(moduleElement, 'ntp-module-header')
+        .dispatchEvent(new Event('info-button-click'));
+
+    // Assert.
+    assertTrue(!!$$(moduleElement, 'ntp-info-dialog'));
+  });
 });
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 3193514..e72a258b 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
@@ -244,6 +244,18 @@
   mocha.run();
 });
 
+// eslint-disable-next-line no-var
+var NewTabPageModulesInfoDialogTest = class extends NewTabPageBrowserTest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://new-tab-page/test_loader.html?module=new_tab_page/modules/info_dialog_test.js';
+  }
+};
+
+TEST_F('NewTabPageModulesInfoDialogTest', 'All', function() {
+  mocha.run();
+});
+
 // The dummy module is not available in official builds.
 GEN('#if !defined(OFFICIAL_BUILD)');
 
diff --git a/chrome/test/data/webui/settings/chromeos/input_page_test.js b/chrome/test/data/webui/settings/chromeos/input_page_test.js
index c7e6fb5..3a1db15e 100644
--- a/chrome/test/data/webui/settings/chromeos/input_page_test.js
+++ b/chrome/test/data/webui/settings/chromeos/input_page_test.js
@@ -1108,6 +1108,8 @@
     //     spell check language" behaviour when the user has no spell check
     //     languages.
 
+    // TODO(crbug.com/1201540): Add a test for the shortcut reminder.
+
     test('error handling', () => {
       // Enable Swahili so we have two languages for testing.
       languageHelper.setPrefValue('spellcheck.dictionaries', ['en-US', 'sw']);
diff --git a/chrome/test/data/webui/settings/fake_language_settings_private.js b/chrome/test/data/webui/settings/fake_language_settings_private.js
index e0d57df..22ebb479 100644
--- a/chrome/test/data/webui/settings/fake_language_settings_private.js
+++ b/chrome/test/data/webui/settings/fake_language_settings_private.js
@@ -586,6 +586,16 @@
       type: chrome.settingsPrivate.PrefType.LIST,
       value: [],
     });
+    fakePrefs.push({
+      key: 'ash.shortcut_reminders.last_used_ime_dismissed',
+      type: chrome.settingsPrivate.PrefType.BOOLEAN,
+      value: false,
+    });
+    fakePrefs.push({
+      key: 'ash.shortcut_reminders.next_ime_dismissed',
+      type: chrome.settingsPrivate.PrefType.BOOLEAN,
+      value: false,
+    });
   }
   return fakePrefs;
 }
diff --git a/chromecast/bindings/public/mojom/BUILD.gn b/chromecast/bindings/public/mojom/BUILD.gn
new file mode 100644
index 0000000..e01f5a1
--- /dev/null
+++ b/chromecast/bindings/public/mojom/BUILD.gn
@@ -0,0 +1,10 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("mojom") {
+  sources = [ "api_bindings.mojom" ]
+  deps = [ "//third_party/blink/public/mojom:mojom_core" ]
+}
diff --git a/chromecast/bindings/public/mojom/OWNERS b/chromecast/bindings/public/mojom/OWNERS
new file mode 100644
index 0000000..61b5e28
--- /dev/null
+++ b/chromecast/bindings/public/mojom/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
\ No newline at end of file
diff --git a/chromecast/bindings/public/mojom/api_bindings.mojom b/chromecast/bindings/public/mojom/api_bindings.mojom
new file mode 100644
index 0000000..a270f0fc
--- /dev/null
+++ b/chromecast/bindings/public/mojom/api_bindings.mojom
@@ -0,0 +1,28 @@
+// 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.
+
+module chromecast.mojom;
+
+import "third_party/blink/public/mojom/messaging/message_port_descriptor.mojom";
+
+// Provides Cast platform API binding scripts and methods for connecting those
+// scripts with Cast service backends.
+interface ApiBindings {
+  // Gets the list of bindings to early-inject into the page at load time.
+  GetAll() => (array<ApiBinding> bindings);
+
+  // Should be invoked when a connecting a named MessagePort to a native
+  // bindings backend.
+  // |port_name| is a string-based ID. It is used to locate corresponding
+  // native bindings backend.
+  // |port| is one end of a paired message channel. It can be deserilized
+  // to bind a blink::WebMessagePort to perform bi-directional communication.
+  Connect(string port_name, blink.mojom.MessagePortDescriptor port);
+};
+
+struct ApiBinding {
+  // Script to execute before the load of a web document. |script| uses
+  // UTF-8 encoding.
+  string script;
+};
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn
index f4c255d..3743fa8 100644
--- a/chromecast/browser/BUILD.gn
+++ b/chromecast/browser/BUILD.gn
@@ -201,6 +201,7 @@
     "//chromecast/base",
     "//chromecast/base:cast_sys_info_util",
     "//chromecast/base:cast_version",
+    "//chromecast/bindings/public/mojom",
     "//chromecast/browser/bluetooth/public/mojom",
     "//chromecast/browser/general_audience_browsing/mojom",
     "//chromecast/browser/mojom",
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc
index 307152c..457278a 100644
--- a/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -165,7 +165,7 @@
   }
 
   char message[48] = "Received close signal: ";
-  strncat(message, sys_siglist[signum], sizeof(message) - strlen(message) - 1);
+  strncat(message, strsignal(signum), sizeof(message) - strlen(message) - 1);
   RAW_LOG(INFO, message);
 
   DCHECK(g_signal_closure);
diff --git a/chromeos/components/help_app_ui/search/search_handler.cc b/chromeos/components/help_app_ui/search/search_handler.cc
index b431dcd..3f27d93 100644
--- a/chromeos/components/help_app_ui/search/search_handler.cc
+++ b/chromeos/components/help_app_ui/search/search_handler.cc
@@ -13,6 +13,15 @@
 
 namespace chromeos {
 namespace help_app {
+namespace {
+
+// Order search results by relevance score. Higher relevance first.
+bool CompareSearchResults(const mojom::SearchResultPtr& first,
+                          const mojom::SearchResultPtr& second) {
+  return first->relevance_score > second->relevance_score;
+}
+
+}  // namespace
 
 SearchHandler::SearchHandler(
     SearchTagRegistry* search_tag_registry,
@@ -73,16 +82,15 @@
     uint32_t max_num_results) const {
   std::vector<mojom::SearchResultPtr> search_results;
   for (const auto& result : local_search_service_results) {
+    if (search_results.size() == max_num_results) {
+      break;
+    }
     mojom::SearchResultPtr result_ptr = ResultToSearchResult(result);
     if (result_ptr)
       search_results.push_back(std::move(result_ptr));
   }
-  // TODO(b/182855408): Sort the search results.
+  std::sort(search_results.begin(), search_results.end(), CompareSearchResults);
 
-  // Now that the results have been sorted, limit the size of to
-  // |max_num_results|.
-  search_results.resize(
-      std::min(static_cast<size_t>(max_num_results), search_results.size()));
   return search_results;
 }
 
diff --git a/chromeos/components/help_app_ui/search/search_handler_unittest.cc b/chromeos/components/help_app_ui/search/search_handler_unittest.cc
index 1cbadbf..9853fc2c 100644
--- a/chromeos/components/help_app_ui/search/search_handler_unittest.cc
+++ b/chromeos/components/help_app_ui/search/search_handler_unittest.cc
@@ -145,5 +145,44 @@
   EXPECT_GT(search_results[0]->relevance_score, 0.01);
 }
 
+TEST_F(HelpAppSearchHandlerTest, SearchResultOrdering) {
+  // Add some search tags.
+  std::vector<mojom::SearchConceptPtr> search_concepts;
+  mojom::SearchConceptPtr new_concept_1 = mojom::SearchConcept::New(
+      /*id=*/"test-id-less",
+      /*title=*/u"Title 1",
+      /*main_category=*/u"Help",
+      /*tags=*/std::vector<std::u16string>{u"less relevance"},
+      /*url_path_with_parameters=*/"help",
+      /*locale=*/"");
+  mojom::SearchConceptPtr new_concept_2 = mojom::SearchConcept::New(
+      /*id=*/"test-id-more",
+      /*title=*/u"Title 2",
+      /*main_category=*/u"Help",
+      /*tags=*/std::vector<std::u16string>{u"more relevant tag", u"Tag 2"},
+      /*url_path_with_parameters=*/"help",
+      /*locale=*/"");
+  search_concepts.push_back(std::move(new_concept_1));
+  search_concepts.push_back(std::move(new_concept_2));
+
+  search_tag_registry_.Update(search_concepts, base::BindOnce([]() {}));
+  handler_remote_.FlushForTesting();
+  task_environment_.RunUntilIdle();
+
+  std::vector<mojom::SearchResultPtr> search_results;
+  mojom::SearchHandlerAsyncWaiter(handler_remote_.get())
+      .Search(u"relevant tag",
+              /*max_num_results=*/3u, &search_results);
+
+  // The more relevant concept should be first, but the other concept still has
+  // some relevance.
+  ASSERT_EQ(search_results.size(), 2u);
+  EXPECT_EQ(search_results[0]->id, "test-id-more");
+  EXPECT_EQ(search_results[1]->id, "test-id-less");
+  EXPECT_GT(search_results[0]->relevance_score,
+            search_results[1]->relevance_score);
+  EXPECT_GT(search_results[1]->relevance_score, 0.01);
+}
+
 }  // namespace help_app
 }  // namespace chromeos
diff --git a/chromeos/crosapi/mojom/BUILD.gn b/chromeos/crosapi/mojom/BUILD.gn
index 286ad2ce..d079b53d 100644
--- a/chromeos/crosapi/mojom/BUILD.gn
+++ b/chromeos/crosapi/mojom/BUILD.gn
@@ -26,6 +26,7 @@
     "prefs.mojom",
     "screen_manager.mojom",
     "select_file.mojom",
+    "system_display.mojom",
     "task_manager.mojom",
     "test_controller.mojom",
     "url_handler.mojom",
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom
index ec8f4a87..9d1909d 100644
--- a/chromeos/crosapi/mojom/crosapi.mojom
+++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -21,6 +21,7 @@
 import "chromeos/crosapi/mojom/prefs.mojom";
 import "chromeos/crosapi/mojom/screen_manager.mojom";
 import "chromeos/crosapi/mojom/select_file.mojom";
+import "chromeos/crosapi/mojom/system_display.mojom";
 import "chromeos/crosapi/mojom/task_manager.mojom";
 import "chromeos/crosapi/mojom/test_controller.mojom";
 import "chromeos/crosapi/mojom/url_handler.mojom";
@@ -54,8 +55,8 @@
 // please note the milestone when you added it, to help us reason about
 // compatibility between the client applications and older ash-chrome binaries.
 //
-// Next version: 24
-// Next method id: 29
+// Next version: 25
+// Next method id: 30
 [Stable, Uuid="8b79c34f-2bf8-4499-979a-b17cac522c1e",
  RenamedFrom="crosapi.mojom.AshChromeService"]
 interface Crosapi {
@@ -179,6 +180,11 @@
   [MinVersion=6] BindMediaSessionAudioFocusDebug@11(
       pending_receiver<media_session.mojom.AudioFocusManagerDebug> receiver);
 
+  // Binds the System Display interface for querying display info.
+  // Added in M92.
+  [MinVersion=24] BindSystemDisplay@29(
+      pending_receiver<SystemDisplay> receiver);
+
   // Binds the Task Manager interface for integrating lacros tasks in ash
   // task manager.
   // Added in M91.
diff --git a/chromeos/crosapi/mojom/system_display.mojom b/chromeos/crosapi/mojom/system_display.mojom
new file mode 100644
index 0000000..140c610
--- /dev/null
+++ b/chromeos/crosapi/mojom/system_display.mojom
@@ -0,0 +1,150 @@
+// 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.
+
+module crosapi.mojom;
+
+import "ui/gfx/geometry/mojom/geometry.mojom";
+
+// The structs in this file are copied from
+//   extensions/common/api/system_display.idl,
+// with explicit versioning added to allow skew. Some simplifications (e.g.,
+// using gfx.mojom classes) are taken from
+//   ash/public/mojom/cros_display_config.mojom.
+// However, the two mojoms operate at different layers and have different
+// version stability requirements, so should not be mixed.
+
+[Stable]
+struct DisplayMode {
+  // The display mode sizes in device independent (user visible) pixels.
+  gfx.mojom.Size size@0;
+
+  // The display mode size in native pixels.
+  gfx.mojom.Size size_in_native_pixels@1;
+
+  // double? |ui_scale| is long deprecated, and therefore excluded.
+
+  // The display mode device scale factor.
+  double device_scale_factor@2;
+
+  // The display mode refresh rate in hertz.
+  double refresh_rate@3;
+
+  // True if the mode is the display's native mode.
+  bool is_native@4;
+
+  // True if the display mode is currently selected.
+  bool is_selected@5;
+
+  // Whether |is_interlaced| is defined.
+  bool has_is_interlaced@6;
+
+  // True if this mode is interlaced, false if not provided.
+  bool is_interlaced@7;
+};
+
+// EDID extracted parameters. Field description refers to "VESA ENHANCED
+// EXTENDED DISPLAY IDENTIFICATION DATA STANDARD (Defines EDID Structure
+// Version 1, Revision 4)" Release A, Revision 2 September 25, 2006.
+// https://www.vesa.org/vesa-standards
+[Stable]
+struct Edid {
+  // Three character manufacturer code, Sec. 3.4.1 page 21.
+  string manufacturer_id@0;
+
+  // Two byte manufacturer-assigned code, Sec. 3.4.2 page 21.
+  string product_id@1;
+
+  // Year of manufacture. Sec. 3.4.4 page 22.
+  int32 year_of_manufacture@2;
+};
+
+// Struct to transmit extensions::api::system_display::DisplayUnitInfo.
+[Stable]
+struct DisplayUnitInfo {
+  // The unique identifier of the display.
+  string id@0;
+
+  // The user-friendly name (e.g. "Acme LCD monitor").
+  string name@1;
+
+  // EDID properties when available.
+  Edid? edid@2;
+
+  // Identifier of the display that is being mirrored if mirroring is enabled,
+  // otherwise empty. This will be set for all displays (including the display
+  // being mirrored).
+  string mirroring_source_id@3;
+
+  // Identifiers of the displays to which the source display is being mirrored.
+  // Empty if no displays are being mirrored. This will be set to the same value
+  // for all displays. This must not include |mirroringSourceId|.
+  array<string> mirroring_destination_ids@4;
+
+  // True if this is the primary display.
+  bool is_primary@5;
+
+  // True if this is an internal display.
+  bool is_internal@6;
+
+  // True if this display is enabled.
+  bool is_enabled@7;
+
+  // True for all displays when in unified desktop mode. See documentation
+  // for $(ref:enableUnifiedDesktop).
+  bool is_unified@8;
+
+  // Whether |is_in_tablet_physical_state| is defined.
+  bool has_is_in_tablet_physical_state@9;
+
+  // Optional: True when the device is in tablet physical state.
+  bool is_in_tablet_physical_state@10;
+
+  // The number of pixels per inch along the x-axis.
+  double dpi_x@11;
+
+  // The number of pixels per inch along the y-axis.
+  double dpi_y@12;
+
+  // The display's clockwise rotation in degrees relative to the vertical
+  // position. A value of -1 will be interpreted as auto-rotate when the device
+  // is in a physical tablet state.
+  int32 rotation@13;
+
+  // The display's logical bounds, represented using Rect.
+  gfx.mojom.Rect bounds_as_rect@14;
+
+  // The display's ovserscan insets within its screen's bounds.
+  gfx.mojom.Insets overscan@15;
+
+  // The usable work area of the display within the display bounds, represented
+  // using Rect. Excludes areas of the display reserved for the OS, e.g. the
+  // taskbar and launcher.
+  gfx.mojom.Rect work_area_as_rect@16;
+
+  // The list of available display modes. The current mode will have
+  // is_selected=true.
+  array<DisplayMode> modes@17;
+
+  // True if this display has a touch input device associated with it.
+  bool has_touch_support@18;
+
+  // True if this display has an accelerometer associated with it.
+  bool has_accelerometer_support@19;
+
+  // The list of allowed zoom factor values for the display.
+  array<double> available_display_zoom_factors@20;
+
+  // The ratio between the display's current and default zoom. i.e. 1.0 is
+  // is equivalent to 100% zoom, and value 1.5 is equivalent to 150% zoom.
+  double display_zoom_factor@21;
+};
+
+// Crosapi support for chrome.system.display extensions API.
+[Stable, Uuid="07f25a88-9762-4876-a8ce-2c1e6ad9f797"]
+interface SystemDisplay {
+  // Returns the properties for all displays. If |single_unified| is true, a
+  // single display will be returned if the display layout is in unifed mode.
+  GetDisplayUnitInfoList@0(bool single_unified) =>
+    (array<DisplayUnitInfo> info_list);
+};
diff --git a/chromeos/lacros/lacros_chrome_service_impl.cc b/chromeos/lacros/lacros_chrome_service_impl.cc
index cd7cd7c..a729d238 100644
--- a/chromeos/lacros/lacros_chrome_service_impl.cc
+++ b/chromeos/lacros/lacros_chrome_service_impl.cc
@@ -21,6 +21,7 @@
 #include "chromeos/crosapi/mojom/prefs.mojom.h"
 #include "chromeos/crosapi/mojom/screen_manager.mojom.h"
 #include "chromeos/crosapi/mojom/select_file.mojom.h"
+#include "chromeos/crosapi/mojom/system_display.mojom.h"
 #include "chromeos/crosapi/mojom/task_manager.mojom.h"
 #include "chromeos/crosapi/mojom/test_controller.mojom.h"
 #include "chromeos/crosapi/mojom/url_handler.mojom.h"
@@ -216,6 +217,8 @@
   ConstructRemote<crosapi::mojom::SelectFile,
                   &crosapi::mojom::Crosapi::BindSelectFile,
                   Crosapi::MethodMinVersions::kBindSelectFileMinVersion>();
+  ConstructRemote<crosapi::mojom::SystemDisplay, &Crosapi::BindSystemDisplay,
+                  Crosapi::MethodMinVersions::kBindSystemDisplayMinVersion>();
   ConstructRemote<crosapi::mojom::TaskManager,
                   &crosapi::mojom::Crosapi::BindTaskManager,
                   Crosapi::MethodMinVersions::kBindTaskManagerMinVersion>();
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt
index 5394669..33036f7 100644
--- a/chromeos/profiles/orderfile.newest.txt
+++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@
-chromeos-chrome-orderfile-field-92-4472.10-1618825180-benchmark-92.0.4486.0-r1.orderfile.xz
+chromeos-chrome-orderfile-field-92-4484.0-1619431291-benchmark-92.0.4489.0-r1.orderfile.xz
diff --git a/chromeos/services/ime/decoder/proto_conversion.cc b/chromeos/services/ime/decoder/proto_conversion.cc
index eb32d09..e4329370 100644
--- a/chromeos/services/ime/decoder/proto_conversion.cc
+++ b/chromeos/services/ime/decoder/proto_conversion.cc
@@ -4,6 +4,7 @@
 
 #include "chromeos/services/ime/decoder/proto_conversion.h"
 
+#include "base/optional.h"
 #include "chromeos/services/ime/public/cpp/suggestions.h"
 
 namespace chromeos {
@@ -83,7 +84,7 @@
   }
 }
 
-TextSuggestionMode ProtoToSuggestionMode(
+TextSuggestionMode ProtoToTextSuggestionMode(
     const SuggestionMode& suggestion_mode) {
   switch (suggestion_mode) {
     case SuggestionMode::SUGGESTION_MODE_PREDICTION:
@@ -95,6 +96,20 @@
   }
 }
 
+base::Optional<TextSuggestionType> ProtoToTextSuggestionType(
+    const SuggestionType& suggestion_type) {
+  switch (suggestion_type) {
+    case SuggestionType::SUGGESTION_TYPE_ASSISTIVE_EMOJI:
+      return TextSuggestionType::kAssistiveEmoji;
+    case SuggestionType::SUGGESTION_TYPE_ASSISTIVE_PERSONAL_INFO:
+      return TextSuggestionType::kAssistivePersonalInfo;
+    case SuggestionType::SUGGESTION_TYPE_MULTI_WORD:
+      return TextSuggestionType::kMultiWord;
+    default:
+      return base::nullopt;
+  }
+}
+
 }  // namespace
 
 ime::PublicMessage OnInputMethodChangedToProto(uint64_t seq_id,
@@ -207,7 +222,7 @@
   auto mojo_suggestions_request = mojom::SuggestionsRequest::New();
   mojo_suggestions_request->text = suggestions_request.text();
   mojo_suggestions_request->mode =
-      ProtoToSuggestionMode(suggestions_request.suggestion_mode());
+      ProtoToTextSuggestionMode(suggestions_request.suggestion_mode());
   for (const auto& candidate : suggestions_request.completion_candidates()) {
     auto mojo_candidate = mojom::CompletionCandidate::New();
     mojo_candidate->text = candidate.text();
@@ -218,5 +233,22 @@
   return mojo_suggestions_request;
 }
 
+std::vector<TextSuggestion> ProtoToTextSuggestions(
+    const chromeos::ime::DisplaySuggestions& display_suggestions) {
+  std::vector<TextSuggestion> suggestions;
+  for (const auto& candidate : display_suggestions.candidates()) {
+    base::Optional<TextSuggestionType> suggestion_type =
+        ProtoToTextSuggestionType(candidate.type());
+    if (suggestion_type) {
+      // Drop any unexpected suggestion types
+      suggestions.push_back(
+          TextSuggestion{.mode = ProtoToTextSuggestionMode(candidate.mode()),
+                         .type = suggestion_type.value(),
+                         .text = candidate.text()});
+    }
+  }
+  return suggestions;
+}
+
 }  // namespace ime
 }  // namespace chromeos
diff --git a/chromeos/services/ime/decoder/proto_conversion.h b/chromeos/services/ime/decoder/proto_conversion.h
index 7d2ebbef..ebfd474 100644
--- a/chromeos/services/ime/decoder/proto_conversion.h
+++ b/chromeos/services/ime/decoder/proto_conversion.h
@@ -54,6 +54,10 @@
 mojom::SuggestionsRequestPtr ProtoToSuggestionsRequest(
     const chromeos::ime::SuggestionsRequest& suggestions_request);
 
+// Converts a proto to a list of ime::TextSuggestion.
+std::vector<TextSuggestion> ProtoToTextSuggestions(
+    const chromeos::ime::DisplaySuggestions& display_suggestions);
+
 }  // namespace ime
 }  // namespace chromeos
 
diff --git a/chromeos/services/ime/decoder/system_engine.cc b/chromeos/services/ime/decoder/system_engine.cc
index b137a4c4..d6d9591 100644
--- a/chromeos/services/ime/decoder/system_engine.cc
+++ b/chromeos/services/ime/decoder/system_engine.cc
@@ -282,6 +282,11 @@
                          base::Unretained(this)));
       break;
     }
+    case ime::PublicMessage::kDisplaySuggestions: {
+      remote->DisplaySuggestions(
+          ProtoToTextSuggestions(reply.display_suggestions()));
+      break;
+    }
     default:
       NOTREACHED();
       break;
diff --git a/chromeos/services/ime/decoder/system_engine_unittest.cc b/chromeos/services/ime/decoder/system_engine_unittest.cc
index dc488c9..dc549e1 100644
--- a/chromeos/services/ime/decoder/system_engine_unittest.cc
+++ b/chromeos/services/ime/decoder/system_engine_unittest.cc
@@ -413,5 +413,37 @@
   client.FlushForTesting();
 }
 
+TEST_F(SystemEngineTest, DisplaySuggestionsSendsMessageToReceiver) {
+  SystemEngine engine(/*platform=*/nullptr);
+  MockInputChannel mock_channel;
+  mojo::Remote<mojom::InputChannel> client;
+  ASSERT_TRUE(engine.BindRequest(kImeSpec, client.BindNewPipeAndPassReceiver(),
+                                 mock_channel.CreatePendingRemote(), {}));
+
+  ime::Wrapper proto;
+  auto* candidate = proto.mutable_public_message()
+                        ->mutable_display_suggestions()
+                        ->add_candidates();
+  candidate->set_mode(SuggestionMode::SUGGESTION_MODE_PREDICTION);
+  candidate->set_type(SuggestionType::SUGGESTION_TYPE_MULTI_WORD);
+  candidate->set_text("gday mate");
+
+  std::vector<TextSuggestion> expected_suggestions = {
+      TextSuggestion{.mode = TextSuggestionMode::kPrediction,
+                     .type = TextSuggestionType::kMultiWord,
+                     .text = "gday mate"},
+  };
+
+  EXPECT_CALL(mock_channel,
+              DisplaySuggestions(testing::ContainerEq(expected_suggestions)));
+
+  const std::string serialized = proto.SerializeAsString();
+  base::span<const uint8_t> serialized_bytes =
+      base::as_bytes(base::make_span(serialized));
+  decoder_entry_points_.delegate()->Process(serialized_bytes.data(),
+                                            serialized_bytes.size());
+  mock_channel.FlushForTesting();
+}
+
 }  // namespace ime
 }  // namespace chromeos
diff --git a/chromeos/services/ime/input_engine.cc b/chromeos/services/ime/input_engine.cc
index bd9513b..bee594a 100644
--- a/chromeos/services/ime/input_engine.cc
+++ b/chromeos/services/ime/input_engine.cc
@@ -227,5 +227,10 @@
   NOTIMPLEMENTED();  // Not used in the rulebased engine.
 }
 
+void InputEngine::DisplaySuggestions(
+    const std::vector<TextSuggestion>& suggestions) {
+  NOTIMPLEMENTED();  // Not used in the rulebased engine.
+}
+
 }  // namespace ime
 }  // namespace chromeos
diff --git a/chromeos/services/ime/input_engine.h b/chromeos/services/ime/input_engine.h
index 82fe597..b6c731da 100644
--- a/chromeos/services/ime/input_engine.h
+++ b/chromeos/services/ime/input_engine.h
@@ -5,6 +5,7 @@
 #ifndef CHROMEOS_SERVICES_IME_INPUT_ENGINE_H_
 #define CHROMEOS_SERVICES_IME_INPUT_ENGINE_H_
 
+#include "chromeos/services/ime/public/cpp/suggestions.h"
 #include "chromeos/services/ime/public/mojom/input_engine.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
@@ -73,6 +74,8 @@
   void HandleAutocorrect(mojom::AutocorrectSpanPtr autocorrect_span) override;
   void RequestSuggestions(mojom::SuggestionsRequestPtr request,
                           RequestSuggestionsCallback callback) override;
+  void DisplaySuggestions(
+      const std::vector<TextSuggestion>& suggestions) override;
 
   // TODO(https://crbug.com/837156): Implement a state for the interface.
 
diff --git a/chromeos/services/ime/mock_input_channel.h b/chromeos/services/ime/mock_input_channel.h
index 379422a..9acc0773 100644
--- a/chromeos/services/ime/mock_input_channel.h
+++ b/chromeos/services/ime/mock_input_channel.h
@@ -85,6 +85,10 @@
               (mojom::SuggestionsRequestPtr request,
                RequestSuggestionsCallback callback),
               (override));
+  MOCK_METHOD(void,
+              DisplaySuggestions,
+              (const std::vector<ime::TextSuggestion>& suggestions),
+              (override));
 
  private:
   mojo::Receiver<mojom::InputChannel> receiver_;
diff --git a/chromeos/services/ime/public/mojom/input_engine.mojom b/chromeos/services/ime/public/mojom/input_engine.mojom
index 9a73567..c3172f5 100644
--- a/chromeos/services/ime/public/mojom/input_engine.mojom
+++ b/chromeos/services/ime/public/mojom/input_engine.mojom
@@ -350,6 +350,9 @@
   // prediction context.
   RequestSuggestions(SuggestionsRequest request)
     => (SuggestionsResponse response);
+
+  // Asks the system to display the given suggestions to the user
+  DisplaySuggestions(array<SuggestionCandidate> suggestions);
 };
 
 // Implemented in the browser process, used to perform network requests or
diff --git a/chromeos/services/ime/public/proto/messages.proto b/chromeos/services/ime/public/proto/messages.proto
index 3c11470..af102717 100644
--- a/chromeos/services/ime/public/proto/messages.proto
+++ b/chromeos/services/ime/public/proto/messages.proto
@@ -42,6 +42,7 @@
     HandleAutocorrect handle_autocorrect = 14;
     SuggestionsRequest suggestions_request = 15;
     SuggestionsResponse suggestions_response = 16;
+    DisplaySuggestions display_suggestions = 17;
   }
 }
 
@@ -255,3 +256,9 @@
 message SuggestionsResponse {
   repeated SuggestionCandidate candidates = 1;
 }
+
+// Protobuf version of DisplaySuggestions in
+// chromeos/services/ime/public/mojom/input_engine.mojom
+message DisplaySuggestions {
+  repeated SuggestionCandidate candidates = 1;
+}
diff --git a/chromeos/ui/frame/frame_utils.cc b/chromeos/ui/frame/frame_utils.cc
index 0e493197d..ab8e598 100644
--- a/chromeos/ui/frame/frame_utils.cc
+++ b/chromeos/ui/frame/frame_utils.cc
@@ -34,18 +34,16 @@
   // Check the frame first, as we allow a small area overlapping the contents
   // to be used for resize handles.
   views::Widget* widget = view->GetWidget();
-  bool can_ever_resize = widget->widget_delegate()->CanResize();
-  // Don't allow overlapping resize handles when the window is maximized or
-  // fullscreen, as it can't be resized in those states.
-  int resize_border = chromeos::kResizeInsideBoundsSize;
-  if (widget->IsMaximized() || widget->IsFullscreen()) {
-    resize_border = 0;
-    can_ever_resize = false;
-  }
+  // Ignore the resize border when maximized or full screen.
+  const bool has_resize_border =
+      !widget->IsMaximized() && !widget->IsFullscreen();
+  const int resize_border_size =
+      has_resize_border ? chromeos::kResizeInsideBoundsSize : 0;
+
   int frame_component = view->GetHTComponentForFrame(
-      point_in_widget, resize_border, resize_border,
+      point_in_widget, resize_border_size, resize_border_size,
       chromeos::kResizeAreaCornerSize, chromeos::kResizeAreaCornerSize,
-      can_ever_resize);
+      has_resize_border);
   if (frame_component != HTNOWHERE)
     return frame_component;
 
diff --git a/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDialogTest.java b/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDialogTest.java
index 902c5c58..78fa99d 100644
--- a/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDialogTest.java
+++ b/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDialogTest.java
@@ -9,6 +9,7 @@
 import android.content.res.Configuration;
 import android.net.Uri;
 import android.os.Build;
+import android.os.Build.VERSION_CODES;
 import android.os.StrictMode;
 import android.provider.MediaStore;
 import android.view.View;
@@ -621,6 +622,8 @@
 
     @Test
     @LargeTest
+    @DisableIf.Build(sdk_is_greater_than = VERSION_CODES.O_MR1, sdk_is_less_than = VERSION_CODES.Q,
+            supported_abis_includes = "x86", message = "https://crbug.com/1205234")
     public void testOrientationChanges() throws Throwable {
         setupTestFiles();
         createDialog(true, Arrays.asList("image/*")); // Multi-select = true.
diff --git a/components/cdm/browser/cdm_message_filter_android.cc b/components/cdm/browser/cdm_message_filter_android.cc
index c7c260af..63eb9bd6 100644
--- a/components/cdm/browser/cdm_message_filter_android.cc
+++ b/components/cdm/browser/cdm_message_filter_android.cc
@@ -17,6 +17,7 @@
 #include "components/cdm/common/cdm_messages_android.h"
 #include "content/public/browser/android/android_overlay_provider.h"
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 #include "media/base/android/media_codec_util.h"
 #include "media/base/android/media_drm_bridge.h"
 #include "media/base/audio_codecs.h"
diff --git a/components/cdm/common/cdm_messages_android.h b/components/cdm/common/cdm_messages_android.h
index 27f4b50..80c848b3 100644
--- a/components/cdm/common/cdm_messages_android.h
+++ b/components/cdm/common/cdm_messages_android.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 #include "media/base/eme_constants.h"
 
 #define IPC_MESSAGE_START EncryptedMediaMsgStart
diff --git a/components/exo/client_controlled_shell_surface_unittest.cc b/components/exo/client_controlled_shell_surface_unittest.cc
index bb04755..fa76475 100644
--- a/components/exo/client_controlled_shell_surface_unittest.cc
+++ b/components/exo/client_controlled_shell_surface_unittest.cc
@@ -1017,7 +1017,7 @@
   EXPECT_FALSE(shell_surface->GetWidget()->widget_delegate()->CanResize());
 }
 
-// The shell surface in SystemModal container should not become target
+// The shell surface in SystemModal container should be a target
 // at the edge.
 TEST_F(ClientControlledShellSurfaceTest, ShellSurfaceInSystemModalHitTest) {
   std::unique_ptr<Surface> surface(new Surface);
@@ -1043,7 +1043,7 @@
   aura::WindowTargeter targeter;
   aura::Window* found =
       static_cast<aura::Window*>(targeter.FindTargetForEvent(root, &event));
-  EXPECT_FALSE(window->Contains(found));
+  EXPECT_TRUE(window->Contains(found));
 }
 
 // Test the snap functionalities in splitscreen in tablet mode.
diff --git a/components/feed/core/v2/feed_stream.cc b/components/feed/core/v2/feed_stream.cc
index 32dd6cd7..fe74fbd8 100644
--- a/components/feed/core/v2/feed_stream.cc
+++ b/components/feed/core/v2/feed_stream.cc
@@ -874,6 +874,7 @@
   LoadStreamTask::Options options;
   options.stream_type = stream_type;
   options.load_type = LoadStreamTask::LoadType::kBackgroundRefresh;
+  options.refresh_even_when_not_stale = true;
   task_queue_.AddTask(std::make_unique<LoadStreamTask>(
       options, this,
       base::BindOnce(&FeedStream::BackgroundRefreshComplete,
diff --git a/components/feed/core/v2/public/types.cc b/components/feed/core/v2/public/types.cc
index 1e3afd7..98fa6b4e 100644
--- a/components/feed/core/v2/public/types.cc
+++ b/components/feed/core/v2/public/types.cc
@@ -36,6 +36,17 @@
 // operator<< functions below are for test purposes, and shouldn't be called
 // from production code to avoid a binary size impact.
 
+std::ostream& operator<<(std::ostream& os, const NetworkResponseInfo& o) {
+  return os << "NetworkResponseInfo{"
+            << " status_code=" << o.status_code
+            << " fetch_duration=" << o.fetch_duration
+            << " fetch_time=" << o.fetch_time
+            << " bless_nonce=" << o.bless_nonce
+            << " base_request_url=" << o.base_request_url
+            << " response_body_bytes=" << o.response_body_bytes
+            << " was_signed_in=" << o.was_signed_in << "}";
+}
+
 std::ostream& operator<<(std::ostream& out, WebFeedSubscriptionStatus value) {
   switch (value) {
     case WebFeedSubscriptionStatus::kUnknown:
diff --git a/components/feed/core/v2/public/types.h b/components/feed/core/v2/public/types.h
index 6b23e41..ac7b33e 100644
--- a/components/feed/core/v2/public/types.h
+++ b/components/feed/core/v2/public/types.h
@@ -64,6 +64,8 @@
   bool was_signed_in = false;
 };
 
+std::ostream& operator<<(std::ostream& os, const NetworkResponseInfo& o);
+
 struct NetworkResponse {
   // HTTP response body.
   std::string response_bytes;
diff --git a/components/feed/core/v2/tasks/load_stream_from_store_task.cc b/components/feed/core/v2/tasks/load_stream_from_store_task.cc
index 378e1dc..06cb568 100644
--- a/components/feed/core/v2/tasks/load_stream_from_store_task.cc
+++ b/components/feed/core/v2/tasks/load_stream_from_store_task.cc
@@ -58,11 +58,6 @@
   }
   pending_actions_ = std::move(result.pending_actions);
 
-  if (load_type_ == LoadType::kPendingActionsOnly) {
-    Complete(LoadStreamStatus::kLoadedFromStore);
-    return;
-  }
-
   if (result.stream_structures.empty()) {
     Complete(LoadStreamStatus::kNoStreamDataInStore);
     return;
@@ -85,6 +80,11 @@
     }
   }
 
+  if (load_type_ == LoadType::kLoadNoContent) {
+    Complete(LoadStreamStatus::kLoadedFromStore);
+    return;
+  }
+
   std::vector<ContentId> referenced_content_ids;
   for (const feedstore::StreamStructureSet& structure_set :
        result.stream_structures) {
diff --git a/components/feed/core/v2/tasks/load_stream_from_store_task.h b/components/feed/core/v2/tasks/load_stream_from_store_task.h
index bc6292a..c0987d12 100644
--- a/components/feed/core/v2/tasks/load_stream_from_store_task.h
+++ b/components/feed/core/v2/tasks/load_stream_from_store_task.h
@@ -30,9 +30,9 @@
     LoadStreamStatus status = LoadStreamStatus::kNoStatus;
     // Only provided if using |LoadType::kFullLoad| AND successful.
     std::unique_ptr<StreamModelUpdateRequest> update_request;
-    // This data is provided when |LoadType::kPendingActionsOnly|, or
-    // when loading fails.
-    std::string consistency_token;
+
+    // The fields below are provided for all `LoadType`s.
+
     // Pending actions to be uploaded if the stream is to be loaded from the
     // network.
     std::vector<feedstore::StoredAction> pending_actions;
@@ -43,9 +43,12 @@
     base::Time last_added_time;
   };
 
+  // Determines what kind of data is loaded. See `Result` for what is loaded.
   enum class LoadType {
+    // Load the full stream content.
     kFullLoad = 0,
-    kPendingActionsOnly = 1,
+    // Skips loading stream content.
+    kLoadNoContent = 1,
   };
 
   LoadStreamFromStoreTask(LoadType load_type,
diff --git a/components/feed/core/v2/tasks/load_stream_task.cc b/components/feed/core/v2/tasks/load_stream_task.cc
index 1795396e..4c6dd98e 100644
--- a/components/feed/core/v2/tasks/load_stream_task.cc
+++ b/components/feed/core/v2/tasks/load_stream_task.cc
@@ -91,12 +91,12 @@
     return;
   }
 
-  // Use |kPendingActionsOnly| to short-circuit loading from store if we don't
+  // Use |kLoadNoContent| to short-circuit loading from store if we don't
   // need the full stream state.
   auto load_from_store_type =
       (options_.load_type == LoadType::kInitialLoad)
           ? LoadStreamFromStoreTask::LoadType::kFullLoad
-          : LoadStreamFromStoreTask::LoadType::kPendingActionsOnly;
+          : LoadStreamFromStoreTask::LoadType::kLoadNoContent;
   load_from_store_task_ = std::make_unique<LoadStreamFromStoreTask>(
       load_from_store_type, stream_, options_.stream_type, stream_->GetStore(),
       stream_->MissedLastRefresh(options_.stream_type),
@@ -111,11 +111,9 @@
   stored_content_age_ = result.content_age;
   last_added_time_ = result.last_added_time;
 
-  // Phase 2.
-  //  - If loading from store works, update the model.
-  //  - Otherwise, try to load from the network.
+  // Phase 2. Process the result of `LoadStreamFromStoreTask`.
 
-  if (options_.load_type == LoadType::kInitialLoad &&
+  if (!options_.refresh_even_when_not_stale &&
       result.status == LoadStreamStatus::kLoadedFromStore) {
     update_request_ = std::move(result.update_request);
     Done(LoadStreamStatus::kLoadedFromStore);
@@ -293,4 +291,22 @@
   TaskComplete();
 }
 
+std::ostream& operator<<(std::ostream& os,
+                         const LoadStreamTask::Result& result) {
+  os << "LoadStreamTask::Result{" << result.stream_type
+     << " final_status=" << result.final_status
+     << " load_from_store_status=" << result.load_from_store_status
+     << " stored_content_age=" << result.stored_content_age
+     << " last_added_time=" << result.last_added_time
+     << " load_type=" << static_cast<int>(result.load_type)
+     << " update_request=" << result.update_request
+     << " request_schedule?=" << result.request_schedule.has_value();
+  if (result.network_response_info)
+    os << " network_response_info=" << *result.network_response_info;
+  return os << " loaded_new_content_from_network="
+            << result.loaded_new_content_from_network
+            << " latencies=" << result.latencies
+            << " upload_actions_result=" << result.upload_actions_result << "}";
+}
+
 }  // namespace feed
diff --git a/components/feed/core/v2/tasks/load_stream_task.h b/components/feed/core/v2/tasks/load_stream_task.h
index d20393f..e4441fe 100644
--- a/components/feed/core/v2/tasks/load_stream_task.h
+++ b/components/feed/core/v2/tasks/load_stream_task.h
@@ -45,6 +45,7 @@
     LoadType load_type = LoadType::kInitialLoad;
     // Abort the background refresh if there's already unread content.
     bool abort_if_unread_content = false;
+    bool refresh_even_when_not_stale = false;
   };
 
   struct Result {
@@ -127,6 +128,8 @@
   base::Optional<bool> fetched_content_has_notice_card_;
   base::WeakPtrFactory<LoadStreamTask> weak_ptr_factory_{this};
 };
+
+std::ostream& operator<<(std::ostream& os, const LoadStreamTask::Result&);
 }  // namespace feed
 
 #endif  // COMPONENTS_FEED_CORE_V2_TASKS_LOAD_STREAM_TASK_H_
diff --git a/components/guest_view/common/guest_view_messages.h b/components/guest_view/common/guest_view_messages.h
index be5ada1..82a0d4ea 100644
--- a/components/guest_view/common/guest_view_messages.h
+++ b/components/guest_view/common/guest_view_messages.h
@@ -9,6 +9,7 @@
 
 #include "base/values.h"
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 
 #define IPC_MESSAGE_START GuestViewMsgStart
 
diff --git a/components/guest_view/renderer/guest_view_container_dispatcher.cc b/components/guest_view/renderer/guest_view_container_dispatcher.cc
index 23a5b51..a21c582 100644
--- a/components/guest_view/renderer/guest_view_container_dispatcher.cc
+++ b/components/guest_view/renderer/guest_view_container_dispatcher.cc
@@ -7,6 +7,7 @@
 #include "components/guest_view/common/guest_view_constants.h"
 #include "components/guest_view/renderer/guest_view_container.h"
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 
 namespace guest_view {
 
diff --git a/components/history_clusters/core/memories_remote_model_helper.cc b/components/history_clusters/core/memories_remote_model_helper.cc
index e951c8dc..c0cce64 100644
--- a/components/history_clusters/core/memories_remote_model_helper.cc
+++ b/components/history_clusters/core/memories_remote_model_helper.cc
@@ -135,9 +135,7 @@
 MemoriesRemoteModelHelper::MemoriesRemoteModelHelper(
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     base::Optional<DebugLoggerCallback> debug_logger)
-    : url_loader_(nullptr),
-      url_loader_factory_(url_loader_factory),
-      debug_logger_(debug_logger) {}
+    : url_loader_factory_(url_loader_factory), debug_logger_(debug_logger) {}
 
 MemoriesRemoteModelHelper::~MemoriesRemoteModelHelper() = default;
 
@@ -149,7 +147,6 @@
     std::move(callback).Run({});
     return;
   }
-  StopPendingRequests();
 
   // It's weird but the endpoint only accepts JSON, so wrap our serialized proto
   // like this: {"data":"<base64-encoded-proto-serialization>"}
@@ -166,13 +163,13 @@
   std::string request_body;
   base::JSONWriter::Write(container_value, &request_body);
 
-  auto request = CreateRequest(endpoint);
-  url_loader_ = CreateLoader(CreateRequest(endpoint), request_body);
-
-  url_loader_->DownloadToString(
+  auto url_loader = CreateLoader(CreateRequest(endpoint), request_body);
+  network::SimpleURLLoader* unowned_url_loader = url_loader.get();
+  unowned_url_loader->DownloadToString(
       url_loader_factory_.get(),
       base::BindOnce(
-          [](base::Optional<DebugLoggerCallback> debug_logger,
+          [](std::unique_ptr<network::SimpleURLLoader> url_loader,
+             base::Optional<DebugLoggerCallback> debug_logger,
              const std::vector<history::ClusterVisit>& visits,
              std::unique_ptr<std::string> response) {
             if (!response) {
@@ -185,16 +182,11 @@
             response_proto.ParseFromString(*response);
             return ParseResponseProto(visits, response_proto, debug_logger);
           },
-          debug_logger_, visits)
+          std::move(url_loader), debug_logger_, visits)
           .Then(std::move(callback)),
       kMaxExpectedResponseSize);
 }
 
-void MemoriesRemoteModelHelper::StopPendingRequests() {
-  // TODO(manukh): Ensure the callback for the pending request is invoked.
-  url_loader_.reset();
-}
-
 // static
 std::unique_ptr<network::ResourceRequest>
 MemoriesRemoteModelHelper::CreateRequest(const GURL& endpoint) {
diff --git a/components/history_clusters/core/memories_remote_model_helper.h b/components/history_clusters/core/memories_remote_model_helper.h
index 7996003..9af0f36 100644
--- a/components/history_clusters/core/memories_remote_model_helper.h
+++ b/components/history_clusters/core/memories_remote_model_helper.h
@@ -41,10 +41,6 @@
                    const std::vector<history::ClusterVisit>& visits);
 
  private:
-  // Stops pending requests. Invoking |GetMemories| multiple times will stop
-  // incomplete previous requests.
-  void StopPendingRequests();
-
   // Helpers for making requests used by |GetMemories()|.
   static std::unique_ptr<network::ResourceRequest> CreateRequest(
       const GURL& endpoint);
@@ -52,8 +48,6 @@
       std::unique_ptr<network::ResourceRequest> request,
       const std::string& request_body);
 
-  // The most recent request.
-  std::unique_ptr<network::SimpleURLLoader> url_loader_;
   // Used to make requests.
   const scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
 
diff --git a/components/history_clusters/core/memories_service_unittest.cc b/components/history_clusters/core/memories_service_unittest.cc
index ff6ec28..5c169ba 100644
--- a/components/history_clusters/core/memories_service_unittest.cc
+++ b/components/history_clusters/core/memories_service_unittest.cc
@@ -465,10 +465,17 @@
       mojom::QueryParams::New(),
       base::BindLambdaForTesting(
           [&](MemoriesService::QueryMemoriesResponse response) {
-            ADD_FAILURE() << "This should not be reached.";
+            // Verify that the continuation query params is nullptr.
+            ASSERT_FALSE(!!response.query_params);
+            // Verify the parsed response.
+            EXPECT_EQ(response.clusters.size(), 2u);
           }),
       &task_tracker_);
 
+  // Verify there's a single request to the endpoint.
+  EXPECT_TRUE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+  EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
+
   EXPECT_TRUE(test_url_loader_factory_.IsPending(kFakeEndpoint));
   memories_service_->QueryMemories(
       mojom::QueryParams::New(),
@@ -482,9 +489,9 @@
           }),
       &task_tracker_);
 
-  // Verify there's a single request to the endpoint.
+  // Verify there are two requests to the endpoint.
   EXPECT_TRUE(test_url_loader_factory_.IsPending(kFakeEndpoint));
-  EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
+  EXPECT_EQ(test_url_loader_factory_.NumPending(), 2);
 
   // Fake a response from the endpoint with two clusters.
   proto::GetClustersResponse response;
@@ -494,7 +501,7 @@
                                        response.SerializeAsString());
   EXPECT_FALSE(test_url_loader_factory_.IsPending(kFakeEndpoint));
 
-  // Verify the callback is invoked.
+  // Verify both callbacks are invoked.
   run_loop_.Run();
 }
 
@@ -507,7 +514,7 @@
               {{"MemoriesStoreVisitsInHistoryDb", "true"}},
           },
           {
-              history_clusters::kRemoteModelForDebugging,
+              kRemoteModelForDebugging,
               {{"MemoriesRemoteModelEndpoint", kFakeEndpoint}},
           },
       },
diff --git a/components/nacl/common/nacl_host_messages.h b/components/nacl/common/nacl_host_messages.h
index a75eb25..93c8488 100644
--- a/components/nacl/common/nacl_host_messages.h
+++ b/components/nacl/common/nacl_host_messages.h
@@ -16,6 +16,7 @@
 #include "components/nacl/common/pnacl_types.h"
 #include "ipc/ipc_channel_handle.h"
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 #include "ipc/ipc_platform_file.h"
 #include "url/gurl.h"
 #include "url/ipc/url_param_traits.h"
diff --git a/components/nacl/common/nacl_messages.h b/components/nacl/common/nacl_messages.h
index 528f448..498b5e9f 100644
--- a/components/nacl/common/nacl_messages.h
+++ b/components/nacl/common/nacl_messages.h
@@ -15,6 +15,7 @@
 #include "components/nacl/common/nacl_types_param_traits.h"
 #include "ipc/ipc_channel_handle.h"
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 #include "ipc/ipc_mojo_param_traits.h"
 #include "ipc/ipc_platform_file.h"
 #include "mojo/public/cpp/system/message_pipe.h"
diff --git a/components/omnibox/browser/location_bar_model_util.cc b/components/omnibox/browser/location_bar_model_util.cc
index 7422f6f..7a20e59 100644
--- a/components/omnibox/browser/location_bar_model_util.cc
+++ b/components/omnibox/browser/location_bar_model_util.cc
@@ -4,9 +4,11 @@
 
 #include "components/omnibox/browser/location_bar_model_util.h"
 
+#include "base/feature_list.h"
 #include "base/notreached.h"
 #include "build/build_config.h"
 #include "components/omnibox/browser/buildflags.h"
+#include "components/omnibox/common/omnibox_features.h"
 #include "ui/gfx/vector_icon_types.h"
 
 #if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS)
@@ -22,8 +24,12 @@
   switch (security_level) {
     case security_state::NONE:
       return omnibox::kHttpIcon;
-    case security_state::SECURE:
-      return vector_icons::kHttpsValidIcon;
+    case security_state::SECURE: {
+      return base::FeatureList::IsEnabled(
+                 omnibox::kUpdatedConnectionSecurityIndicators)
+                 ? vector_icons::kHttpsValidArrowIcon
+                 : vector_icons::kHttpsValidIcon;
+    }
     case security_state::SECURE_WITH_POLICY_INSTALLED_CERT:
       return vector_icons::kBusinessIcon;
     case security_state::WARNING:
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc
index df6b630..40a336b9 100644
--- a/components/omnibox/browser/omnibox_edit_model.cc
+++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -40,13 +40,11 @@
 #include "components/omnibox/browser/omnibox_pedal_concepts.h"
 #include "components/omnibox/browser/omnibox_popup_model.h"
 #include "components/omnibox/browser/omnibox_popup_view.h"
-#include "components/omnibox/browser/omnibox_prefs.h"
 #include "components/omnibox/browser/omnibox_view.h"
 #include "components/omnibox/browser/search_provider.h"
 #include "components/omnibox/browser/suggestion_answer.h"
 #include "components/omnibox/browser/verbatim_match.h"
 #include "components/omnibox/common/omnibox_features.h"
-#include "components/prefs/pref_service.h"
 #include "components/search_engines/omnibox_focus_type.h"
 #include "components/search_engines/template_url.h"
 #include "components/search_engines/template_url_prepopulate_data.h"
@@ -1515,9 +1513,10 @@
   // If entering keyword mode by space is disabled, do not set
   // |allow_exact_keyword_match_|.
   allow_exact_keyword_match_ =
-      AllowKeywordSpaceTriggering() && state_changes.text_differs &&
-      allow_keyword_ui_change && !state_changes.just_deleted_text &&
-      no_selection &&
+      (OmniboxFieldTrial::GetKeywordSpaceTrigger() !=
+       OmniboxFieldTrial::SPACE_TRIGGERING_DISABLED) &&
+      state_changes.text_differs && allow_keyword_ui_change &&
+      !state_changes.just_deleted_text && no_selection &&
       CreatedKeywordSearchByInsertingSpaceInMiddle(
           *state_changes.old_text, user_text_, state_changes.new_sel_start);
   view_->UpdatePopup();
@@ -1699,19 +1698,10 @@
   return controller()->GetLocationBarModel()->ShouldPreventElision();
 }
 
-bool OmniboxEditModel::AllowKeywordSpaceTriggering() const {
-  PrefService* pref_service =
-      autocomplete_controller()->autocomplete_provider_client()->GetPrefs();
-  return (OmniboxFieldTrial::GetKeywordSpaceTrigger() !=
-          OmniboxFieldTrial::SPACE_TRIGGERING_DISABLED) &&
-         (!base::FeatureList::IsEnabled(
-              omnibox::kKeywordSpaceTriggeringSetting) ||
-          pref_service->GetBoolean(omnibox::kKeywordSpaceTriggeringEnabled));
-}
-
 bool OmniboxEditModel::MaybeAcceptKeywordBySpace(
     const std::u16string& new_text) {
-  if (!AllowKeywordSpaceTriggering())
+  if (OmniboxFieldTrial::GetKeywordSpaceTrigger() ==
+      OmniboxFieldTrial::SPACE_TRIGGERING_DISABLED)
     return false;
 
   size_t keyword_length = new_text.length() - 1;
diff --git a/components/omnibox/browser/omnibox_edit_model.h b/components/omnibox/browser/omnibox_edit_model.h
index 547e94ab..ba84a7a0 100644
--- a/components/omnibox/browser/omnibox_edit_model.h
+++ b/components/omnibox/browser/omnibox_edit_model.h
@@ -474,12 +474,6 @@
   void GetInfoForCurrentText(AutocompleteMatch* match,
                              GURL* alternate_nav_url) const;
 
-  // Checks whether keyword mode space-triggering has been disabled either by
-  // a pref or relevant feature flags. If the setting isn't available on the
-  // search engines page, the pref should be ignored.  Returns true if space
-  // triggering is enabled, false otherwise.
-  bool AllowKeywordSpaceTriggering() const;
-
   // Accepts current keyword if the user just typed a space at the end of
   // |new_text|.  This handles both of the following cases:
   //   (assume "foo" is a keyword, | is the input caret, [] is selected text)
diff --git a/components/omnibox/browser/omnibox_prefs.cc b/components/omnibox/browser/omnibox_prefs.cc
index 3bb4ad2..4e3a866 100644
--- a/components/omnibox/browser/omnibox_prefs.cc
+++ b/components/omnibox/browser/omnibox_prefs.cc
@@ -30,10 +30,6 @@
 // Values are defined in omnibox::IntranetRedirectorBehavior.
 const char kIntranetRedirectBehavior[] = "browser.intranet_redirect_behavior";
 
-// Boolean that controls whether scoped search mode can be triggered by <space>.
-const char kKeywordSpaceTriggeringEnabled[] =
-    "omnibox.keyword_space_triggering_enabled";
-
 // A dictionary of visibility preferences for suggestion groups. The key is the
 // suggestion group ID serialized as a string, and the value is
 // SuggestionGroupVisibility serialized as an integer.
@@ -47,7 +43,6 @@
 
 void RegisterProfilePrefs(PrefRegistrySimple* registry) {
   registry->RegisterDictionaryPref(kSuggestionGroupVisibility);
-  registry->RegisterBooleanPref(kKeywordSpaceTriggeringEnabled, true);
 }
 
 SuggestionGroupVisibility GetUserPreferenceForSuggestionGroupVisibility(
diff --git a/components/omnibox/browser/omnibox_prefs.h b/components/omnibox/browser/omnibox_prefs.h
index 379337b..1652f16d 100644
--- a/components/omnibox/browser/omnibox_prefs.h
+++ b/components/omnibox/browser/omnibox_prefs.h
@@ -33,7 +33,6 @@
 // Keep alphabetized, and document each in the .cc file.
 extern const char kDocumentSuggestEnabled[];
 extern const char kIntranetRedirectBehavior[];
-extern const char kKeywordSpaceTriggeringEnabled[];
 extern const char kSuggestionGroupVisibility[];
 extern const char kPreventUrlElisionsInOmnibox[];
 extern const char kZeroSuggestCachedResults[];
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc
index 86e1fa8..09a0605 100644
--- a/components/omnibox/common/omnibox_features.cc
+++ b/components/omnibox/common/omnibox_features.cc
@@ -304,10 +304,10 @@
 const base::Feature kKeywordSpaceTriggering{"OmniboxKeywordSpaceTriggering",
                                             base::FEATURE_ENABLED_BY_DEFAULT};
 
-// When enabled, a setting is added to chrome://settings/searchEngines to
-// control whether <space> can be used to trigger keyword mode.
-const base::Feature kKeywordSpaceTriggeringSetting{
-    "OmniboxKeywordSpaceTriggeringSetting", base::FEATURE_DISABLED_BY_DEFAULT};
+// Experiment to introduce new security indicators for HTTPS.
+const base::Feature kUpdatedConnectionSecurityIndicators{
+    "OmniboxUpdatedConnectionSecurityIndicators",
+    base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Feature used to reveal the path, query and ref from steady state URLs
 // on hover.
diff --git a/components/omnibox/common/omnibox_features.h b/components/omnibox/common/omnibox_features.h
index a12e3ab..9de1f877 100644
--- a/components/omnibox/common/omnibox_features.h
+++ b/components/omnibox/common/omnibox_features.h
@@ -81,7 +81,8 @@
 extern const base::Feature kIntranetRedirectBehaviorPolicyRollout;
 extern const base::Feature kOmniboxAssistantVoiceSearch;
 extern const base::Feature kKeywordSpaceTriggering;
-extern const base::Feature kKeywordSpaceTriggeringSetting;
+// Experiment to introduce new security indicators for HTTPS.
+extern const base::Feature kUpdatedConnectionSecurityIndicators;
 
 // Path-hiding experiments - these hide the path and other URL components in
 // some circumstances in the steady-state omnibox.
diff --git a/components/reporting/storage/storage.cc b/components/reporting/storage/storage.cc
index 83640c76..354243db 100644
--- a/components/reporting/storage/storage.cc
+++ b/components/reporting/storage/storage.cc
@@ -122,7 +122,7 @@
   static void AsyncProvideUploader(
       Priority priority,
       Storage* storage,
-      UploaderInterface::UploaderInterfaceResultCb start_uploader_cb) {
+      UploaderInterfaceResultCb start_uploader_cb) {
     storage->async_start_upload_cb_.Run(
         priority,
         /*need_encryption_key=*/EncryptionModuleInterface::is_enabled() &&
@@ -157,7 +157,7 @@
  private:
   static void WrapInstantiatedUploader(
       Priority priority,
-      UploaderInterface::UploaderInterfaceResultCb start_uploader_cb,
+      UploaderInterfaceResultCb start_uploader_cb,
       StatusOr<std::unique_ptr<UploaderInterface>> uploader_result) {
     if (!uploader_result.ok()) {
       std::move(start_uploader_cb).Run(uploader_result.status());
@@ -500,11 +500,15 @@
       } else {
         if (EncryptionModuleInterface::is_enabled()) {
           // Initiate upload with need_encryption_key flag and no records.
+          UploaderInterface::UploaderInterfaceResultCb start_uploader_cb =
+              base::BindOnce(&StorageInitContext::EncryptionKeyReceiverReady,
+                             base::Unretained(this));
           storage_->async_start_upload_cb_.Run(
               /*priority=*/MANUAL_BATCH,  // Any priority would do.
               /*need_encryption_key=*/true,
-              base::BindOnce(&StorageInitContext::EncryptionKeyReceiverReady,
-                             base::Unretained(this)));
+              base::BindOnce(&StorageInitContext::WrapInstantiatedKeyUploader,
+                             /*priority=*/MANUAL_BATCH,
+                             std::move(start_uploader_cb)));
           // Continue initialization without waiting for it to respond.
           // Until the response arrives, we will reject Enqueues.
         }
@@ -527,6 +531,19 @@
       }
     }
 
+    static void WrapInstantiatedKeyUploader(
+        Priority priority,
+        UploaderInterface::UploaderInterfaceResultCb start_uploader_cb,
+        StatusOr<std::unique_ptr<UploaderInterface>> uploader_result) {
+      if (!uploader_result.ok()) {
+        std::move(start_uploader_cb).Run(uploader_result.status());
+        return;
+      }
+      std::move(start_uploader_cb)
+          .Run(std::make_unique<QueueUploaderInterface>(
+              priority, std::move(uploader_result.ValueOrDie())));
+    }
+
     void EncryptionKeyReceiverReady(
         StatusOr<std::unique_ptr<UploaderInterface>> uploader_result) {
       if (uploader_result.ok()) {
@@ -645,9 +662,18 @@
       }));
 
   // Serialize whole signed_encryption_key to a new file, discard the old
-  // one(s).
-  const Status status = key_in_storage_->UploadKeyFile(signed_encryption_key);
-  LOG_IF(ERROR, !status.ok()) << "Failed to upload the new encription key.";
+  // one(s). Do it on a thread which may block doing file operations.
+  base::ThreadPool::PostTask(
+      FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
+      base::BindOnce(
+          [](SignedEncryptionInfo signed_encryption_key,
+             KeyInStorage* key_in_storage) {
+            const Status status =
+                key_in_storage->UploadKeyFile(signed_encryption_key);
+            LOG_IF(ERROR, !status.ok())
+                << "Failed to upload the new encription key.";
+          },
+          std::move(signed_encryption_key), key_in_storage_.get()));
 }
 
 StatusOr<scoped_refptr<StorageQueue>> Storage::GetQueue(Priority priority) {
diff --git a/components/reporting/storage_selector/storage_selector.cc b/components/reporting/storage_selector/storage_selector.cc
index ef4994a..0c94d81 100644
--- a/components/reporting/storage_selector/storage_selector.cc
+++ b/components/reporting/storage_selector/storage_selector.cc
@@ -14,7 +14,6 @@
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "components/reporting/encryption/encryption_module.h"
-#include "components/reporting/encryption/verification.h"
 #include "components/reporting/storage/storage_module.h"
 #include "components/reporting/storage/storage_module_interface.h"
 #include "components/reporting/storage/storage_uploader_interface.h"
@@ -60,6 +59,7 @@
 // static
 void StorageSelector::CreateStorageModule(
     const base::FilePath& local_reporting_path,
+    base::StringPiece verification_key,
     UploaderInterface::AsyncStartUploaderCb async_start_upload_cb,
     base::OnceCallback<void(StatusOr<scoped_refptr<StorageModuleInterface>>)>
         cb) {
@@ -89,12 +89,12 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Use Storage in a local file system.
-  StorageModule::Create(StorageOptions()
-                            .set_directory(local_reporting_path)
-                            .set_signature_verification_public_key(
-                                SignatureVerifier::VerificationKey()),
-                        std::move(async_start_upload_cb),
-                        EncryptionModule::Create(), std::move(cb));
+  StorageModule::Create(
+      StorageOptions()
+          .set_directory(local_reporting_path)
+          .set_signature_verification_public_key(verification_key),
+      std::move(async_start_upload_cb), EncryptionModule::Create(),
+      std::move(cb));
 }
 
 }  // namespace reporting
diff --git a/components/reporting/storage_selector/storage_selector.h b/components/reporting/storage_selector/storage_selector.h
index 8071572..1b4c40c 100644
--- a/components/reporting/storage_selector/storage_selector.h
+++ b/components/reporting/storage_selector/storage_selector.h
@@ -35,6 +35,7 @@
   static bool is_uploader_required();
   static void CreateStorageModule(
       const base::FilePath& local_reporting_path,
+      base::StringPiece verification_key,
       UploaderInterface::AsyncStartUploaderCb async_start_upload_cb,
       base::OnceCallback<void(StatusOr<scoped_refptr<StorageModuleInterface>>)>
           cb);
diff --git a/components/safe_browsing/core/features.cc b/components/safe_browsing/core/features.cc
index 0d00087..afe99fa 100644
--- a/components/safe_browsing/core/features.cc
+++ b/components/safe_browsing/core/features.cc
@@ -64,10 +64,6 @@
 const base::Feature kLimitedListSizeForIOS{"SafeBrowsingLimitedListSizeForIOS",
                                            base::FEATURE_DISABLED_BY_DEFAULT};
 
-const base::Feature kPasswordProtectionReferringAppEnabledAndroid{
-    "SafeBrowsingPasswordProtectionReferringAppEnabledAndroid",
-    base::FEATURE_ENABLED_BY_DEFAULT};
-
 const base::Feature kPasswordProtectionForSignedInUsers {
   "SafeBrowsingPasswordProtectionForSignedInUsers",
 #if BUILDFLAG(FULL_SAFE_BROWSING)
@@ -153,7 +149,6 @@
     {&kDelayedWarnings, true},
     {&kDownloadRequestWithToken, true},
     {&kLimitedListSizeForIOS, true},
-    {&kPasswordProtectionReferringAppEnabledAndroid, true},
     {&kPasswordProtectionForSignedInUsers, true},
     {&kPasswordProtectionWithToken, true},
     {&kRealTimeUrlLookupEnabled, true},
diff --git a/components/safe_browsing/core/features.h b/components/safe_browsing/core/features.h
index 518f6ab..a67558d 100644
--- a/components/safe_browsing/core/features.h
+++ b/components/safe_browsing/core/features.h
@@ -55,9 +55,6 @@
 // limits the number of entries stored in each Safe Browsing list.
 extern const base::Feature kLimitedListSizeForIOS;
 
-// Include referring app info in password protection requests on Android.
-extern const base::Feature kPasswordProtectionReferringAppEnabledAndroid;
-
 // Enable GAIA password protection for signed-in users.
 extern const base::Feature kPasswordProtectionForSignedInUsers;
 
diff --git a/components/safe_browsing/core/password_protection/password_protection_request.cc b/components/safe_browsing/core/password_protection/password_protection_request.cc
index 442fdfb..54793f27 100644
--- a/components/safe_browsing/core/password_protection/password_protection_request.cc
+++ b/components/safe_browsing/core/password_protection/password_protection_request.cc
@@ -231,10 +231,6 @@
   SetReferringAppInfo();
 #endif  // defined(OS_ANDROID)
 
-#if defined(OS_ANDROID)
-  SetReferringAppInfo();
-#endif  // defined(OS_ANDROID)
-
   switch (trigger_type_) {
     case LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE: {
       LoginReputationClientRequest::Frame::Form* password_form;
diff --git a/components/signin/public/android/BUILD.gn b/components/signin/public/android/BUILD.gn
index 0c63b2a..dd15ee8e 100644
--- a/components/signin/public/android/BUILD.gn
+++ b/components/signin/public/android/BUILD.gn
@@ -33,8 +33,6 @@
     "java/src/org/chromium/components/signin/ChildAccountInfoFetcher.java",
     "java/src/org/chromium/components/signin/ChildAccountStatus.java",
     "java/src/org/chromium/components/signin/ConnectionRetry.java",
-    "java/src/org/chromium/components/signin/MutableObservableValue.java",
-    "java/src/org/chromium/components/signin/ObservableValue.java",
     "java/src/org/chromium/components/signin/PatternMatcher.java",
     "java/src/org/chromium/components/signin/ProfileDataSource.java",
     "java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java",
@@ -129,7 +127,6 @@
   sources = [
     "junit/src/org/chromium/components/signin/AccountManagerFacadeImplTest.java",
     "junit/src/org/chromium/components/signin/AccountRenameCheckerTest.java",
-    "junit/src/org/chromium/components/signin/ObservableValueTest.java",
     "junit/src/org/chromium/components/signin/PatternMatcherTest.java",
     "junit/src/org/chromium/components/signin/identitymanager/AccountInfoServiceTest.java",
     "junit/src/org/chromium/components/signin/identitymanager/AccountTrackerServiceTest.java",
diff --git a/components/signin/public/android/java/src/org/chromium/components/signin/AccountManagerFacadeImpl.java b/components/signin/public/android/java/src/org/chromium/components/signin/AccountManagerFacadeImpl.java
index f4605b2a..adbf055 100644
--- a/components/signin/public/android/java/src/org/chromium/components/signin/AccountManagerFacadeImpl.java
+++ b/components/signin/public/android/java/src/org/chromium/components/signin/AccountManagerFacadeImpl.java
@@ -12,7 +12,6 @@
 import android.os.SystemClock;
 import android.text.TextUtils;
 
-import androidx.annotation.MainThread;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
@@ -64,7 +63,6 @@
 
     private int mUpdateTasksCounter;
     private final Queue<Runnable> mCallbacksWaitingForAccountsFetch = new ArrayDeque<>();
-    private ObservableValue<Boolean> mUpdatePendingState = new MutableObservableValue<>(true);
 
     /**
      * @param delegate the AccountManagerDelegate to use as a backend
@@ -252,17 +250,6 @@
     }
 
     /**
-     * Checks whether there are pending updates for account list cache.
-     * @return true if there are no pending updates, false otherwise
-     */
-    @VisibleForTesting
-    @MainThread
-    public ObservableValue<Boolean> isUpdatePending() {
-        ThreadUtils.assertOnUiThread();
-        return mUpdatePendingState;
-    }
-
-    /**
      * Returns the Gaia id for the account associated with the given email address.
      * If an account with the given email address is not installed on the device
      * then null is returned.
@@ -347,8 +334,6 @@
     private void incrementUpdateCounter() {
         assert mUpdateTasksCounter >= 0;
         if (mUpdateTasksCounter++ > 0) return;
-
-        mUpdatePendingState.set(true);
     }
 
     private void decrementUpdateCounter() {
@@ -359,7 +344,6 @@
             final Runnable runnable = mCallbacksWaitingForAccountsFetch.remove();
             runnable.run();
         }
-        mUpdatePendingState.set(false);
     }
 
     private class InitializeTask extends AsyncTask<Void> {
diff --git a/components/signin/public/android/java/src/org/chromium/components/signin/MutableObservableValue.java b/components/signin/public/android/java/src/org/chromium/components/signin/MutableObservableValue.java
deleted file mode 100644
index 62ed539..0000000
--- a/components/signin/public/android/java/src/org/chromium/components/signin/MutableObservableValue.java
+++ /dev/null
@@ -1,29 +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.
-
-package org.chromium.components.signin;
-
-import androidx.annotation.MainThread;
-
-/**
- * {@link ObservableValue} subclass that allow value modification using {@link #set} method. Should
- * only be used from the main thread.
- * @param <T> The type of the stored value.
- */
-@MainThread
-public class MutableObservableValue<T> extends ObservableValue<T> {
-    public MutableObservableValue(T initialValue) {
-        super(initialValue);
-    }
-
-    /**
-     * Sets the value. Calling this will synchronously notify all observers. Please note that the
-     * internal state is updated before observers are notified, so {@link #get} invoked from
-     * observer will return the updated value.
-     */
-    @Override
-    public void set(T value) {
-        super.set(value);
-    }
-}
diff --git a/components/signin/public/android/java/src/org/chromium/components/signin/ObservableValue.java b/components/signin/public/android/java/src/org/chromium/components/signin/ObservableValue.java
deleted file mode 100644
index 99d450d8b..0000000
--- a/components/signin/public/android/java/src/org/chromium/components/signin/ObservableValue.java
+++ /dev/null
@@ -1,76 +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.
-
-package org.chromium.components.signin;
-
-import androidx.annotation.MainThread;
-import androidx.core.util.ObjectsCompat;
-
-import org.chromium.base.ObserverList;
-import org.chromium.base.ThreadUtils;
-
-/**
- * Simple observable value that notifies all observers whenever the value changes. Should only be
- * used from the main thread.
- * @param <T> The type of the stored value.
- */
-@MainThread
-public class ObservableValue<T> {
-    /**
-     * Observer to get notifications when the value is changed.
-     */
-    public interface Observer {
-        /**
-         * After an observer has been added using {@link ObservableValue#addObserver}, this method
-         * is invoked whenever the value is changed.
-         */
-        void onValueChanged();
-    }
-
-    private T mValue;
-    private final ObserverList<Observer> mObserverList = new ObserverList<>();
-
-    protected ObservableValue(T initialValue) {
-        mValue = initialValue;
-    }
-
-    /**
-     * Returns the current value.
-     */
-    public T get() {
-        ThreadUtils.assertOnUiThread();
-        return mValue;
-    }
-
-    /**
-     * Adds observer to watch value changes. Use {@link #removeObserver} to remove.
-     * @param observer The observer to receive notifications trough {@link Observer#onValueChanged}.
-     */
-    public void addObserver(Observer observer) {
-        ThreadUtils.assertOnUiThread();
-        assert observer != null;
-        mObserverList.addObserver(observer);
-    }
-
-    /**
-     * Removes observer that was added by {@link #addObserver}. The removed observer will no longer
-     * receive notifications when value changes.
-     * @param observer The observer to remove.
-     */
-    public void removeObserver(Observer observer) {
-        ThreadUtils.assertOnUiThread();
-        assert observer != null;
-        boolean result = mObserverList.removeObserver(observer);
-        assert result : "No such observer";
-    }
-
-    protected void set(T value) {
-        ThreadUtils.assertOnUiThread();
-        if (ObjectsCompat.equals(mValue, value)) return;
-        mValue = value;
-        for (Observer observer : mObserverList) {
-            observer.onValueChanged();
-        }
-    }
-}
diff --git a/components/signin/public/android/junit/src/org/chromium/components/signin/ObservableValueTest.java b/components/signin/public/android/junit/src/org/chromium/components/signin/ObservableValueTest.java
deleted file mode 100644
index ab684c8..0000000
--- a/components/signin/public/android/junit/src/org/chromium/components/signin/ObservableValueTest.java
+++ /dev/null
@@ -1,109 +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.
-package org.chromium.components.signin;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNull;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
-
-import org.chromium.base.test.BaseRobolectricTestRunner;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Robolectric tests for {@link ObservableValue}.
- */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-public class ObservableValueTest {
-    @Test
-    public void testNullAllowed() {
-        MutableObservableValue<Integer> value = new MutableObservableValue<>(null);
-        // Using null as a value should be allowed.
-        assertNull(value.get());
-    }
-
-    @Test
-    public void testAddObserverNoCallsToOnValueChanged() {
-        MutableObservableValue<Integer> value = new MutableObservableValue<>(0);
-        ObservableValue.Observer observer = mock(ObservableValue.Observer.class);
-        value.addObserver(observer);
-        verifyZeroInteractions(observer);
-    }
-
-    @Test
-    public void testObserverIsNotifiedOnSet() {
-        MutableObservableValue<Integer> value = new MutableObservableValue<>(0);
-        ObservableValue.Observer observer = mock(ObservableValue.Observer.class);
-        value.addObserver(observer);
-
-        value.set(1);
-        assertEquals(1, (int) value.get());
-        verify(observer, times(1)).onValueChanged();
-    }
-
-    @Test
-    public void testObserverIsNotNotifiedOnSetWithTheSameValue() {
-        MutableObservableValue<Integer> value = new MutableObservableValue<>(123);
-        ObservableValue.Observer observer = mock(ObservableValue.Observer.class);
-        value.addObserver(observer);
-
-        // Manually allocate the new value to make sure it's a different object and not a reference
-        // to the same object from Java integer pool.
-        @SuppressWarnings("UnnecessaryBoxing")
-        Integer newValue = new Integer(123);
-
-        value.set(newValue);
-        assertEquals(123, (int) value.get());
-        verifyZeroInteractions(observer);
-    }
-
-    @Test
-    public void testObserverIsNotNotifiedAfterRemoval() {
-        MutableObservableValue<Integer> value = new MutableObservableValue<>(0);
-        ObservableValue.Observer observer = mock(ObservableValue.Observer.class);
-        value.addObserver(observer);
-
-        value.removeObserver(observer);
-        value.set(321);
-        assertEquals(321, (int) value.get());
-        verifyZeroInteractions(observer);
-    }
-
-    @Test
-    public void testGetReturnsUpdatedValueFromObserver() {
-        MutableObservableValue<Integer> value = new MutableObservableValue<>(0);
-        AtomicInteger valueHolder = new AtomicInteger(0);
-        value.addObserver(() -> valueHolder.set(value.get()));
-
-        value.set(123);
-        assertEquals(123, valueHolder.get());
-    }
-
-    @Test
-    public void testCanModifyObserverListFromOnValueChanged() {
-        MutableObservableValue<Integer> value = new MutableObservableValue<>(0);
-        AtomicInteger callCounter = new AtomicInteger(0);
-        ObservableValue.Observer observer = new ObservableValue.Observer() {
-            @Override
-            public void onValueChanged() {
-                callCounter.incrementAndGet();
-                value.removeObserver(this);
-            }
-        };
-        value.addObserver(observer);
-        value.set(234);
-        assertEquals("Observer should be invoked once", 1, callCounter.get());
-        value.set(345);
-        assertEquals("Observer should've been removed after the first call", 1, callCounter.get());
-    }
-}
diff --git a/components/soda/BUILD.gn b/components/soda/BUILD.gn
index 161d7a7..869c8ef 100644
--- a/components/soda/BUILD.gn
+++ b/components/soda/BUILD.gn
@@ -2,6 +2,27 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
+
+source_set("soda") {
+  sources = [
+    "soda_installer.cc",
+    "soda_installer.h",
+  ]
+
+  deps = [
+    ":constants",
+    "//base",
+    "//components/live_caption:constants",
+    "//components/prefs",
+    "//media",
+  ]
+
+  if (is_chromeos_ash) {
+    deps += [ "//ash/public/cpp" ]
+  }
+}
+
 source_set("constants") {
   sources = [
     "constants.cc",
diff --git a/components/soda/DEPS b/components/soda/DEPS
index 9ebf19d..bba2923 100644
--- a/components/soda/DEPS
+++ b/components/soda/DEPS
@@ -1,4 +1,8 @@
 include_rules = [
+  "+ash/public/cpp",
   "+components/component_updater/component_updater_paths.h",
+  "+components/live_caption",
+  "+components/prefs",
   "+components/strings/grit/components_strings.h",
+  "+media/base",
 ]
diff --git a/chrome/browser/accessibility/soda_installer.cc b/components/soda/soda_installer.cc
similarity index 97%
rename from chrome/browser/accessibility/soda_installer.cc
rename to components/soda/soda_installer.cc
index c1f7911..9fe046a 100644
--- a/chrome/browser/accessibility/soda_installer.cc
+++ b/components/soda/soda_installer.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/accessibility/soda_installer.h"
+#include "components/soda/soda_installer.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/public/cpp/ash_pref_names.h"
diff --git a/chrome/browser/accessibility/soda_installer.h b/components/soda/soda_installer.h
similarity index 96%
rename from chrome/browser/accessibility/soda_installer.h
rename to components/soda/soda_installer.h
index b86a703..79c0fa99 100644
--- a/chrome/browser/accessibility/soda_installer.h
+++ b/components/soda/soda_installer.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ACCESSIBILITY_SODA_INSTALLER_H_
-#define CHROME_BROWSER_ACCESSIBILITY_SODA_INSTALLER_H_
+#ifndef COMPONENTS_SODA_SODA_INSTALLER_H_
+#define COMPONENTS_SODA_SODA_INSTALLER_H_
 
 #include "base/files/file_path.h"
 #include "base/observer_list.h"
@@ -121,4 +121,4 @@
 
 }  // namespace speech
 
-#endif  // CHROME_BROWSER_ACCESSIBILITY_SODA_INSTALLER_H_
+#endif  // COMPONENTS_SODA_SODA_INSTALLER_H_
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc
index 3ddc3cf..2403966 100644
--- a/components/translate/core/browser/translate_manager.cc
+++ b/components/translate/core/browser/translate_manager.cc
@@ -1142,7 +1142,7 @@
                   GetLanguageState()->InTranslateNavigation()
                       ? TranslationType::kAutomaticTranslationByLink
                       : TranslationType::kAutomaticTranslationByPref);
-    return false;
+    return true;
   }
 
   if (decision.can_auto_href_translate()) {
@@ -1152,7 +1152,7 @@
                       : TranslationType::kAutomaticTranslationByPref);
     GetActiveTranslateMetricsLogger()->LogTriggerDecision(
         TriggerDecision::kAutomaticTranslationByHref);
-    return false;
+    return true;
   }
 
   // Auto-translate didn't happen, so check if the UI should be shown. It must
diff --git a/components/vector_icons/BUILD.gn b/components/vector_icons/BUILD.gn
index 39074ee..c4123667 100644
--- a/components/vector_icons/BUILD.gn
+++ b/components/vector_icons/BUILD.gn
@@ -48,6 +48,7 @@
     "help.icon",
     "help_outline.icon",
     "https_valid.icon",
+    "https_valid_arrow.icon",
     "info_outline.icon",
     "insert_drive_file_outline.icon",
     "launch.icon",
diff --git a/components/vector_icons/https_valid_arrow.icon b/components/vector_icons/https_valid_arrow.icon
new file mode 100644
index 0000000..9548363
--- /dev/null
+++ b/components/vector_icons/https_valid_arrow.icon
@@ -0,0 +1,20 @@
+// 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.
+
+CANVAS_DIMENSIONS, 16,
+NEW_PATH,
+MOVE_TO, 8.59f, 10.75f,
+CUBIC_TO, 8.44f, 10.9f, 8.23f, 11, 8, 11,
+CUBIC_TO, 7.77f, 11, 7.56f, 10.9f, 7.41f, 10.75f,
+LINE_TO, 3.24f, 6.46f,
+CUBIC_TO, 3.09f, 6.31f, 3, 6.09f, 3, 5.86f,
+CUBIC_TO, 3, 5.38f, 3.37f, 5, 3.83f, 5,
+CUBIC_TO, 4.06f, 5, 4.27f, 5.1f, 4.42f, 5.25f,
+LINE_TO, 8, 8.93f,
+LINE_TO, 11.58f, 5.25f,
+CUBIC_TO, 11.73f, 5.1f, 11.94f, 5, 12.17f, 5,
+CUBIC_TO, 12.63f, 5, 13, 5.38f, 13, 5.86f,
+CUBIC_TO, 13, 6.09f, 12.91f, 6.31f, 12.76f, 6.46f,
+LINE_TO, 8.59f, 10.75f,
+CLOSE
\ No newline at end of file
diff --git a/content/browser/browser_context.cc b/content/browser/browser_context.cc
index 3895246..967334f3 100644
--- a/content/browser/browser_context.cc
+++ b/content/browser/browser_context.cc
@@ -198,15 +198,13 @@
   return GetStoragePartition(StoragePartitionConfig::CreateDefault(this));
 }
 
-// static
-void BrowserContext::CreateMemoryBackedBlob(BrowserContext* self,
-                                            base::span<const uint8_t> data,
+void BrowserContext::CreateMemoryBackedBlob(base::span<const uint8_t> data,
                                             const std::string& content_type,
                                             BlobCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   ChromeBlobStorageContext* blob_context =
-      ChromeBlobStorageContext::GetFor(self);
+      ChromeBlobStorageContext::GetFor(this);
   GetIOThreadTaskRunner({})->PostTaskAndReplyWithResult(
       FROM_HERE,
       base::BindOnce(&ChromeBlobStorageContext::CreateMemoryBackedBlob,
@@ -214,22 +212,18 @@
       std::move(callback));
 }
 
-// static
-BrowserContext::BlobContextGetter BrowserContext::GetBlobStorageContext(
-    BrowserContext* self) {
+BrowserContext::BlobContextGetter BrowserContext::GetBlobStorageContext() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   scoped_refptr<ChromeBlobStorageContext> chrome_blob_context =
-      ChromeBlobStorageContext::GetFor(self);
+      ChromeBlobStorageContext::GetFor(this);
   return base::BindRepeating(&BlobStorageContextGetterForBrowser,
                              chrome_blob_context);
 }
 
-// static
 mojo::PendingRemote<blink::mojom::Blob> BrowserContext::GetBlobRemote(
-    BrowserContext* self,
     const std::string& uuid) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  return ChromeBlobStorageContext::GetBlobRemote(self, uuid);
+  return ChromeBlobStorageContext::GetBlobRemote(this, uuid);
 }
 
 // static
diff --git a/content/browser/conversions/conversion_internals_browsertest.cc b/content/browser/conversions/conversion_internals_browsertest.cc
index 3c611c08..8429931 100644
--- a/content/browser/conversions/conversion_internals_browsertest.cc
+++ b/content/browser/conversions/conversion_internals_browsertest.cc
@@ -85,11 +85,10 @@
 
   // Execute script to ensure the page has loaded correctly, executing similarly
   // to ExecJsInWebUI().
-  EXPECT_EQ(
-      true,
-      EvalJs(shell()->web_contents()->GetMainFrame(),
-             "document.body.innerHTML.search('Conversion Internals') >= 0;",
-             EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+  EXPECT_EQ(true, EvalJs(shell()->web_contents()->GetMainFrame(),
+                         "document.body.innerHTML.search('Conversion "
+                         "Measurement API Internals') >= 0;",
+                         EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
 }
 
 IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest,
diff --git a/content/browser/loader/prefetch_url_loader.cc b/content/browser/loader/prefetch_url_loader.cc
index 8f842070..0619250 100644
--- a/content/browser/loader/prefetch_url_loader.cc
+++ b/content/browser/loader/prefetch_url_loader.cc
@@ -77,8 +77,8 @@
       prefetched_signed_exchange_cache_adapter_ =
           std::make_unique<PrefetchedSignedExchangeCacheAdapter>(
               std::move(prefetched_signed_exchange_cache),
-              BrowserContext::GetBlobStorageContext(browser_context),
-              resource_request.url, this);
+              browser_context->GetBlobStorageContext(), resource_request.url,
+              this);
     }
   }
 
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index 43c4bd0..e7cb1cfc 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -48,9 +48,8 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
 #include "ipc/ipc_channel_proxy.h"
-#include "ipc/ipc_platform_file.h"
 #include "media/media_buildflags.h"
-#include "media/mojo/mojom/video_decode_perf_history.mojom.h"
+#include "media/mojo/mojom/video_decode_perf_history.mojom-forward.h"
 #include "mojo/public/cpp/bindings/associated_receiver.h"
 #include "mojo/public/cpp/bindings/associated_receiver_set.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
@@ -64,30 +63,27 @@
 #include "net/base/network_isolation_key.h"
 #include "net/net_buildflags.h"
 #include "ppapi/buildflags/buildflags.h"
-#include "services/network/public/mojom/mdns_responder.mojom.h"
+#include "services/network/public/mojom/mdns_responder.mojom-forward.h"
 #include "services/network/public/mojom/p2p.mojom-forward.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/public/mojom/url_loader_factory.mojom-forward.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
-#include "services/tracing/public/mojom/traced_process.mojom.h"
+#include "services/tracing/public/mojom/traced_process.mojom-forward.h"
 #include "services/viz/public/mojom/compositing/compositing_mode_watcher.mojom.h"
-#include "services/viz/public/mojom/gpu.mojom.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
 #include "third_party/blink/public/common/tokens/tokens.h"
-#include "third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom.h"
+#include "third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom-forward.h"
 #include "third_party/blink/public/mojom/background_sync/background_sync.mojom-forward.h"
-#include "third_party/blink/public/mojom/broadcastchannel/broadcast_channel.mojom.h"
-#include "third_party/blink/public/mojom/buckets/bucket_manager_host.mojom.h"
+#include "third_party/blink/public/mojom/broadcastchannel/broadcast_channel.mojom-forward.h"
+#include "third_party/blink/public/mojom/buckets/bucket_manager_host.mojom-forward.h"
 #include "third_party/blink/public/mojom/dom_storage/dom_storage.mojom.h"
-#include "third_party/blink/public/mojom/filesystem/file_system.mojom.h"
+#include "third_party/blink/public/mojom/filesystem/file_system.mojom-forward.h"
 #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-shared.h"
-#include "third_party/blink/public/mojom/loader/code_cache.mojom.h"
-#include "third_party/blink/public/mojom/media/renderer_audio_output_stream_factory.mojom.h"
-#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom-forward.h"
 #include "third_party/blink/public/mojom/native_io/native_io.mojom-forward.h"
 #include "third_party/blink/public/mojom/plugins/plugin_registry.mojom-forward.h"
 #include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom-forward.h"
-#include "third_party/blink/public/mojom/webdatabase/web_database.mojom.h"
+#include "third_party/blink/public/mojom/webdatabase/web_database.mojom-forward.h"
 #include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h"
 #include "ui/gfx/gpu_memory_buffer.h"
 
diff --git a/content/browser/resources/conversions/conversion_internals.css b/content/browser/resources/conversions/conversion_internals.css
index 87cb09c..8926c0aa 100644
--- a/content/browser/resources/conversions/conversion_internals.css
+++ b/content/browser/resources/conversions/conversion_internals.css
@@ -31,6 +31,15 @@
   font-weight: bold;
 }
 
+#feature-status-content.disabled {
+  color: red;
+}
+
+hr {
+  border-top: 1px solid rgb(48, 57, 66);
+  width: 100%;
+}
+
 .content {
   background-color: #fbfbfb;
   border: 1px solid #cecece;
@@ -73,4 +82,5 @@
 
 button {
   font: inherit;
+  margin-inline-end: 30px;
 }
diff --git a/content/browser/resources/conversions/conversion_internals.html b/content/browser/resources/conversions/conversion_internals.html
index 85e1b902a..8b1e7f21 100644
--- a/content/browser/resources/conversions/conversion_internals.html
+++ b/content/browser/resources/conversions/conversion_internals.html
@@ -10,27 +10,25 @@
 
   <link rel="stylesheet" href="conversion_internals.css">
   <script type="module" src="conversion_internals.js"></script>
-  <title>Conversion Internals</title>
+  <title>Conversion Measurement API Internals</title>
 </head>
 <body>
 
 <div id="page-heading">
-  Conversion Internals
+  Conversion Measurement API Internals
 </div>
+<div id="info">
+  <p>Learn more:
+    <a href="https://web.dev/using-conversion-measurement/" target="_blank">
+      Conversion Measurement API
+    </a>
+  <p>Conversion measurement is currently <span id="feature-status-content"></span>.
+</div>
+<hr>
 <div id="page-content">
-  <h2> General Info </h2>
-  <div class="content">
-    <div>
-      Conversion measurement is currently <span id="feature-status-content"></span>.
-      For a detailed explanation of the API and its behavior, see
-      <a href="https://github.com/WICG/conversion-measurement-api/blob/master/README.md" target="_blank">
-        the explainer
-      </a>.
-    </div>
-    <div>
-      <button id="refresh">Refresh all page data</button>
-      <button id="clear-data">Clear all conversions data</button>
-    </div>
+  <div>
+    <button id="refresh">Refresh all page data</button>
+    <button id="clear-data">Clear all conversions data</button>
   </div>
   <h2> Active Impressions </h2>
   <div class="content">
@@ -66,7 +64,7 @@
       </table>
     </div>
   </div>
-  <h2> Pending Reports </h2>
+  <h2> Pending Conversion Reports </h2>
   <div class="content">
     <div>
       <span id="debug-mode-content"></span>
diff --git a/content/browser/resources/conversions/conversion_internals.js b/content/browser/resources/conversions/conversion_internals.js
index 844521bf..4e54d70 100644
--- a/content/browser/resources/conversions/conversion_internals.js
+++ b/content/browser/resources/conversions/conversion_internals.js
@@ -159,6 +159,7 @@
   pageHandler.isMeasurementEnabled().then((response) => {
     $('feature-status-content').innerText =
         response.enabled ? 'enabled' : 'disabled';
+    $('feature-status-content').classList.toggle('disabled', !response.enabled);
 
     const htmlString = 'The #conversion-measurement-debug-mode flag is ' +
         '<strong>enabled</strong>, ' +
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index ddf3679d..6a633fe 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -180,8 +180,8 @@
     const std::string& content_type) {
   std::unique_ptr<content::BlobHandle> result;
   base::RunLoop loop;
-  BrowserContext::CreateMemoryBackedBlob(
-      browser_context, base::as_bytes(base::make_span(contents)), content_type,
+  browser_context->CreateMemoryBackedBlob(
+      base::as_bytes(base::make_span(contents)), content_type,
       base::BindOnce(
           [](std::unique_ptr<content::BlobHandle>* out_blob,
              base::OnceClosure done,
diff --git a/content/browser/service_sandbox_type.h b/content/browser/service_sandbox_type.h
index 350b237..d64c355 100644
--- a/content/browser/service_sandbox_type.h
+++ b/content/browser/service_sandbox_type.h
@@ -16,15 +16,15 @@
 // require a non-utility sandbox can be added here.  See
 // ServiceProcessHost::Launch() for how these templates are consumed.
 
-// auction_worklet::mojom::AdAuctionService
+// auction_worklet::mojom::AuctionWorkletService
 namespace auction_worklet {
 namespace mojom {
-class AdAuctionService;
+class AuctionWorkletService;
 }
 }  // namespace auction_worklet
 template <>
-inline sandbox::policy::SandboxType
-content::GetServiceSandboxType<auction_worklet::mojom::AdAuctionService>() {
+inline sandbox::policy::SandboxType content::GetServiceSandboxType<
+    auction_worklet::mojom::AuctionWorkletService>() {
   return sandbox::policy::SandboxType::kService;
 }
 
diff --git a/content/browser/web_package/web_bundle_interceptor_for_history_navigation_from_network.cc b/content/browser/web_package/web_bundle_interceptor_for_history_navigation_from_network.cc
index bd7bf157..f170488 100644
--- a/content/browser/web_package/web_bundle_interceptor_for_history_navigation_from_network.cc
+++ b/content/browser/web_package/web_bundle_interceptor_for_history_navigation_from_network.cc
@@ -117,8 +117,7 @@
   DCHECK(browser_context);
   reader_ = base::MakeRefCounted<WebBundleReader>(
       std::move(source_), length_hint, std::move(*response_body),
-      url_loader->Unbind(),
-      BrowserContext::GetBlobStorageContext(browser_context));
+      url_loader->Unbind(), browser_context->GetBlobStorageContext());
   reader_->ReadMetadata(base::BindOnce(
       &WebBundleInterceptorForHistoryNavigationFromNetwork::OnMetadataReady,
       weak_factory_.GetWeakPtr(), request));
diff --git a/content/browser/web_package/web_bundle_interceptor_for_network.cc b/content/browser/web_package/web_bundle_interceptor_for_network.cc
index 69c9a92..231c3694 100644
--- a/content/browser/web_package/web_bundle_interceptor_for_network.cc
+++ b/content/browser/web_package/web_bundle_interceptor_for_network.cc
@@ -92,8 +92,7 @@
 
   reader_ = base::MakeRefCounted<WebBundleReader>(
       std::move(source), length_hint, std::move(*response_body),
-      url_loader->Unbind(),
-      BrowserContext::GetBlobStorageContext(browser_context_));
+      url_loader->Unbind(), browser_context_->GetBlobStorageContext());
   reader_->ReadMetadata(
       base::BindOnce(&WebBundleInterceptorForNetwork::OnMetadataReady,
                      weak_factory_.GetWeakPtr(), request));
diff --git a/content/common/gin_java_bridge_messages.h b/content/common/gin_java_bridge_messages.h
index 69efa4f..c38e4694 100644
--- a/content/common/gin_java_bridge_messages.h
+++ b/content/common/gin_java_bridge_messages.h
@@ -12,6 +12,7 @@
 #include "content/common/android/gin_java_bridge_errors.h"
 #include "content/common/content_export.h"
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 
 #undef IPC_MESSAGE_EXPORT
 #define IPC_MESSAGE_EXPORT CONTENT_EXPORT
diff --git a/content/public/browser/browser_context.h b/content/public/browser/browser_context.h
index 7eb0e57..f0edf20 100644
--- a/content/public/browser/browser_context.h
+++ b/content/public/browser/browser_context.h
@@ -171,13 +171,12 @@
   // This method should be called on UI thread and calls back on UI thread
   // as well. Note that retrieving a blob ptr out of BlobHandle can only be
   // done on IO. |callback| returns a nullptr on failure.
-  static void CreateMemoryBackedBlob(BrowserContext* self,
-                                     base::span<const uint8_t> data,
-                                     const std::string& content_type,
-                                     BlobCallback callback);
+  void CreateMemoryBackedBlob(base::span<const uint8_t> data,
+                              const std::string& content_type,
+                              BlobCallback callback);
 
   // Get a BlobStorageContext getter that needs to run on IO thread.
-  static BlobContextGetter GetBlobStorageContext(BrowserContext* self);
+  BlobContextGetter GetBlobStorageContext();
 
   // Returns a mojom::mojo::PendingRemote<blink::mojom::Blob> for a specific
   // blob. If no blob exists with the given UUID, the
@@ -186,8 +185,7 @@
   // TODO(mek): Blob UUIDs should be entirely internal to the blob system, so
   // eliminate this method in favor of just passing around the
   // mojo::PendingRemote<blink::mojom::Blob> directly.
-  static mojo::PendingRemote<blink::mojom::Blob> GetBlobRemote(
-      BrowserContext* self,
+  mojo::PendingRemote<blink::mojom::Blob> GetBlobRemote(
       const std::string& uuid);
 
   // Delivers a push message with |data| to the Service Worker identified by
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 670d3ad..b4efbde 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -93,8 +93,6 @@
     "media/media_interface_factory.h",
     "media/media_permission_dispatcher.cc",
     "media/media_permission_dispatcher.h",
-    "media/power_status_helper_impl.cc",
-    "media/power_status_helper_impl.h",
     "media/render_media_client.cc",
     "media/render_media_client.h",
     "media/render_media_event_handler.cc",
diff --git a/content/renderer/media/media_factory.cc b/content/renderer/media/media_factory.cc
index 77e39f1..fd6e474 100644
--- a/content/renderer/media/media_factory.cc
+++ b/content/renderer/media/media_factory.cc
@@ -25,7 +25,6 @@
 #include "content/renderer/media/batching_media_log.h"
 #include "content/renderer/media/inspector_media_event_handler.h"
 #include "content/renderer/media/media_interface_factory.h"
-#include "content/renderer/media/power_status_helper_impl.h"
 #include "content/renderer/media/render_media_event_handler.h"
 #include "content/renderer/media/renderer_webmediaplayer_delegate.h"
 #include "content/renderer/render_frame_impl.h"
@@ -37,6 +36,7 @@
 #include "media/base/demuxer.h"
 #include "media/base/media_switches.h"
 #include "media/base/renderer_factory_selector.h"
+#include "media/blink/power_status_helper.h"
 #include "media/blink/remote_playback_client_wrapper_impl.h"
 #include "media/blink/resource_fetch_context.h"
 #include "media/blink/url_index.h"
@@ -503,8 +503,8 @@
           return battery_monitor;
         },
         remote_interfaces);
-    power_status_helper =
-        std::make_unique<PowerStatusHelperImpl>(std::move(battery_monitor_cb));
+    power_status_helper = std::make_unique<media::PowerStatusHelper>(
+        std::move(battery_monitor_cb));
   }
 
   scoped_refptr<base::SingleThreadTaskRunner>
diff --git a/content/renderer/media/power_status_helper_impl.h b/content/renderer/media/power_status_helper_impl.h
deleted file mode 100644
index 09f0560..0000000
--- a/content/renderer/media/power_status_helper_impl.h
+++ /dev/null
@@ -1,141 +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.
-
-#ifndef CONTENT_RENDERER_MEDIA_POWER_STATUS_HELPER_IMPL_H_
-#define CONTENT_RENDERER_MEDIA_POWER_STATUS_HELPER_IMPL_H_
-
-#include "base/macros.h"
-#include "base/optional.h"
-#include "base/sequence_checker.h"
-#include "content/common/content_export.h"
-#include "media/blink/power_status_helper.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "services/device/public/mojom/battery_monitor.mojom.h"
-
-namespace content {
-
-class PowerStatusHelperImplBucketTest;
-
-class CONTENT_EXPORT PowerStatusHelperImpl : public media::PowerStatusHelper {
- public:
-  using CreateBatteryMonitorCB = base::RepeatingCallback<
-      mojo::PendingRemote<device::mojom::BatteryMonitor>()>;
-
-  // Bits used to construct UMA buckets.
-  // These values are persisted to logs. Entries should not be renumbered and
-  // numeric values should never be reused.
-  enum /* not class */ Bits {
-    // Bit layout is: [msb] xx f F RR CC [lsb]
-    // R == resolution
-    // C == codec
-    // F == frame rate
-    // f == full screen
-    // x == unused
-    // Remember that we can't use more than 6 bits, since we shouldn't go over
-    // 100 UMA buckets.
-
-    // Codec bits, values 0x00 to 0x03
-    // Named "CodecBits" to prevent a name collision with media::VideoCodec.
-    kCodecBitsH264 = (0x00) << 0,
-    kCodecBitsVP9Profile0 = (0x01) << 0,
-    // Ignore Profile1
-    kCodecBitsVP9Profile2 = (0x02) << 0,
-    // TODO(liberato): add AV1
-
-    // Resolution bits, values 0x00 to 0x03
-    kResolution360p = (0x00) << 2,
-    kResolution720p = (0x01) << 2,
-    kResolution1080p = (0x02) << 2,
-
-    // Frame rate bits, values 0x00 to 0x01
-    kFrameRate30 = (0x00) << 4,
-    kFrameRate60 = (0x01) << 4,
-
-    // Fullscreen bits, values 0x00 to 0x01
-    kFullScreenNo = (0x00) << 5,
-    kFullScreenYes = (0x01) << 5,
-
-    // This is not a valid bit for, you know, testing.
-    kNotAValidBitForTesting = (0x01) << 10,
-  };
-
-  // If |stats_cb| is not provided, then we'll record to UMA.  It's just for
-  // the tests.
-  PowerStatusHelperImpl(CreateBatteryMonitorCB create_battery_monitor_cb);
-  ~PowerStatusHelperImpl() override;
-
-  // media::PowerStatusHelper
-  void SetIsPlaying(bool is_playing) override;
-  void SetMetadata(const media::PipelineMetadata& metadata) override;
-  void SetIsFullscreen(bool is_fullscreen) override;
-  void SetAverageFrameRate(base::Optional<int> average_fps) override;
-  void UpdatePowerExperimentState(bool state) override;
-
- private:
-  friend class PowerStatusHelperImplTest;
-  friend class PowerStatusHelperImplBucketTest;
-
-  // Return the UMA bucket for the given video configuration, or nullopt if we
-  // don't want to record it.
-  static base::Optional<int> BucketFor(bool is_playing,
-                                       bool has_video,
-                                       media::VideoCodec codec,
-                                       media::VideoCodecProfile profile,
-                                       gfx::Size natural_size,
-                                       bool is_fullscreen,
-                                       base::Optional<int> average_fps);
-
-  // Return the histogram names.  Here so that tests can find them too.
-  static const char* BatteryDeltaHistogram();
-  static const char* ElapsedTimeHistogram();
-
-  // Recompute everything when playback state or power experiment state changes.
-  void OnAnyStateChange();
-
-  // Handle updates about the current battery status.
-  void OnBatteryStatus(device::mojom::BatteryStatusPtr battery_status);
-
-  // Start monitoring if we haven't already.  Any outstanding callbacks will be
-  // cancelled if monitoring was already in progress.
-  void StartMonitoring();
-  void StopMonitoring();
-
-  // Register to receive a power update the next time it changes.
-  void QueryNextStatus();
-
-  CreateBatteryMonitorCB create_battery_monitor_cb_;
-
-  // Most recent parameters we were given.
-  bool is_playing_ = false;
-  bool has_video_ = false;
-  media::VideoCodec codec_ = media::VideoCodec::kUnknownVideoCodec;
-  media::VideoCodecProfile profile_ =
-      media::VideoCodecProfile::VIDEO_CODEC_PROFILE_UNKNOWN;
-  gfx::Size natural_size_;
-  bool is_fullscreen_ = false;
-  // For estimating fps.  Can be unset if we don't know.
-  base::Optional<int> average_fps_;
-
-  // Current UMA bucket, if any.
-  base::Optional<int> current_bucket_;
-
-  // If set, our previous battery level, from 0-100.
-  base::Optional<float> battery_level_baseline_;
-  // The time at which we last got an update from |battery_monitor_|.
-  base::TimeTicks last_update_;
-
-  // Are we currently the player that should be recording power for the power
-  // experiment, according to the MediaPowerExperimentManager?
-  bool experiment_state_ = false;
-
-  mojo::Remote<device::mojom::BatteryMonitor> battery_monitor_;
-
-  SEQUENCE_CHECKER(sequence_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(PowerStatusHelperImpl);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_MEDIA_POWER_STATUS_HELPER_IMPL_H_
diff --git a/content/renderer/render_thread_impl_browsertest.cc b/content/renderer/render_thread_impl_browsertest.cc
index 90ea0f858..9d8369a0 100644
--- a/content/renderer/render_thread_impl_browsertest.cc
+++ b/content/renderer/render_thread_impl_browsertest.cc
@@ -64,6 +64,7 @@
 #undef IPC_MESSAGE_EXTRA
 #define IPC_MESSAGE_IMPL
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 #include "ipc/ipc_message_templates_impl.h"
 
 #undef IPC_MESSAGE_START
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index b35c0f9..f9d8657 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -2193,7 +2193,6 @@
     "../renderer/loader/navigation_body_loader_unittest.cc",
     "../renderer/media/batching_media_log_unittest.cc",
     "../renderer/media/inspector_media_event_handler_unittest.cc",
-    "../renderer/media/power_status_helper_impl_unittest.cc",
     "../renderer/media/renderer_webaudiodevice_impl_unittest.cc",
     "../renderer/render_thread_impl_unittest.cc",
     "../renderer/service_worker/service_worker_fetch_context_impl_unittest.cc",
diff --git a/content/web_test/browser/web_test_background_fetch_delegate.cc b/content/web_test/browser/web_test_background_fetch_delegate.cc
index baef547..f03b74e6 100644
--- a/content/web_test/browser/web_test_background_fetch_delegate.cc
+++ b/content/web_test/browser/web_test_background_fetch_delegate.cc
@@ -48,8 +48,7 @@
   // download::BlobContextGetterFactory implementation.
   void RetrieveBlobContextGetter(
       download::BlobContextGetterCallback callback) override {
-    auto blob_context_getter =
-        content::BrowserContext::GetBlobStorageContext(browser_context_);
+    auto blob_context_getter = browser_context_->GetBlobStorageContext();
     std::move(callback).Run(blob_context_getter);
   }
 
diff --git a/extensions/browser/api/device_permissions_manager.cc b/extensions/browser/api/device_permissions_manager.cc
index 4653ef1c..c1ace5a 100644
--- a/extensions/browser/api/device_permissions_manager.cc
+++ b/extensions/browser/api/device_permissions_manager.cc
@@ -97,7 +97,9 @@
   }
 
   std::unique_ptr<base::Value> device_entry(entry->ToValue());
-  DCHECK(devices->Find(*device_entry) == devices->end());
+  // TODO(crbug.com/1187106): Use base::Contains once |devices| not a ListValue.
+  DCHECK(std::find(devices->begin(), devices->end(), *device_entry) ==
+         devices->end());
   devices->Append(std::move(device_entry));
 }
 
diff --git a/extensions/browser/api/printer_provider/printer_provider_internal_api.cc b/extensions/browser/api/printer_provider/printer_provider_internal_api.cc
index 992dce7..13c57cc 100644
--- a/extensions/browser/api/printer_provider/printer_provider_internal_api.cc
+++ b/extensions/browser/api/printer_provider/printer_provider_internal_api.cc
@@ -189,8 +189,7 @@
 
   // |job->document_bytes| are passed to the callback to make sure the ref
   // counted memory does not go away before the memory backed blob is created.
-  content::BrowserContext::CreateMemoryBackedBlob(
-      browser_context(),
+  browser_context()->CreateMemoryBackedBlob(
       base::make_span(job->document_bytes->front(),
                       job->document_bytes->size()),
       "",
diff --git a/extensions/browser/api/system_display/system_display_api.cc b/extensions/browser/api/system_display/system_display_api.cc
index 5315f4a8..ba37efc6f 100644
--- a/extensions/browser/api/system_display/system_display_api.cc
+++ b/extensions/browser/api/system_display/system_display_api.cc
@@ -209,8 +209,13 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   if (ShouldRestrictEdidInformation(*this)) {
     for (auto& display_info : all_displays_info)
-      display_info.edid.release();
+      display_info.edid.reset();
   }
+#elif BUILDFLAG(IS_CHROMEOS_LACROS)
+  // Kiosk mode work for Lacros has not been scoped out. For now, just strip
+  // all EDID information by default.
+  for (auto& display_info : all_displays_info)
+    display_info.edid.reset();
 #endif
   Respond(ArgumentList(display::GetInfo::Results::Create(all_displays_info)));
 }
diff --git a/extensions/browser/api/webcam_private/visca_webcam.cc b/extensions/browser/api/webcam_private/visca_webcam.cc
index e7409fc..56c5c40 100644
--- a/extensions/browser/api/webcam_private/visca_webcam.cc
+++ b/extensions/browser/api/webcam_private/visca_webcam.cc
@@ -191,8 +191,8 @@
   }
 
   Send(CHAR_VECTOR_FROM_ARRAY(kSetAddressCommand),
-       base::Bind(&ViscaWebcam::OnAddressSetCompleted, base::Unretained(this),
-                  open_callback));
+       base::BindRepeating(&ViscaWebcam::OnAddressSetCompleted,
+                           base::Unretained(this), open_callback));
 }
 
 void ViscaWebcam::OnAddressSetCompleted(
@@ -206,8 +206,8 @@
   }
 
   Send(CHAR_VECTOR_FROM_ARRAY(kClearAllCommand),
-       base::Bind(&ViscaWebcam::OnClearAllCompleted, base::Unretained(this),
-                  open_callback));
+       base::BindRepeating(&ViscaWebcam::OnClearAllCompleted,
+                           base::Unretained(this), open_callback));
 }
 
 void ViscaWebcam::OnClearAllCompleted(const OpenCompleteCallback& open_callback,
@@ -359,26 +359,26 @@
 
 void ViscaWebcam::GetPan(const GetPTZCompleteCallback& callback) {
   Send(CHAR_VECTOR_FROM_ARRAY(kGetPanTiltCommand),
-       base::Bind(&ViscaWebcam::OnInquiryCompleted, base::Unretained(this),
-                  INQUIRY_PAN, callback));
+       base::BindRepeating(&ViscaWebcam::OnInquiryCompleted,
+                           base::Unretained(this), INQUIRY_PAN, callback));
 }
 
 void ViscaWebcam::GetTilt(const GetPTZCompleteCallback& callback) {
   Send(CHAR_VECTOR_FROM_ARRAY(kGetPanTiltCommand),
-       base::Bind(&ViscaWebcam::OnInquiryCompleted, base::Unretained(this),
-                  INQUIRY_TILT, callback));
+       base::BindRepeating(&ViscaWebcam::OnInquiryCompleted,
+                           base::Unretained(this), INQUIRY_TILT, callback));
 }
 
 void ViscaWebcam::GetZoom(const GetPTZCompleteCallback& callback) {
   Send(CHAR_VECTOR_FROM_ARRAY(kGetZoomCommand),
-       base::Bind(&ViscaWebcam::OnInquiryCompleted, base::Unretained(this),
-                  INQUIRY_ZOOM, callback));
+       base::BindRepeating(&ViscaWebcam::OnInquiryCompleted,
+                           base::Unretained(this), INQUIRY_ZOOM, callback));
 }
 
 void ViscaWebcam::GetFocus(const GetPTZCompleteCallback& callback) {
   Send(CHAR_VECTOR_FROM_ARRAY(kGetFocusCommand),
-       base::Bind(&ViscaWebcam::OnInquiryCompleted, base::Unretained(this),
-                  INQUIRY_FOCUS, callback));
+       base::BindRepeating(&ViscaWebcam::OnInquiryCompleted,
+                           base::Unretained(this), INQUIRY_FOCUS, callback));
 }
 
 void ViscaWebcam::SetPan(int value,
@@ -393,8 +393,8 @@
   command[5] |= kDefaultTiltSpeed;
   ResponseToCommand(&command, 6, static_cast<uint16_t>(pan_));
   ResponseToCommand(&command, 10, static_cast<uint16_t>(tilt_));
-  Send(command, base::Bind(&ViscaWebcam::OnCommandCompleted,
-                           base::Unretained(this), callback));
+  Send(command, base::BindRepeating(&ViscaWebcam::OnCommandCompleted,
+                                    base::Unretained(this), callback));
 }
 
 void ViscaWebcam::SetTilt(int value,
@@ -409,24 +409,24 @@
   command[5] |= actual_tilt_speed;
   ResponseToCommand(&command, 6, static_cast<uint16_t>(pan_));
   ResponseToCommand(&command, 10, static_cast<uint16_t>(tilt_));
-  Send(command, base::Bind(&ViscaWebcam::OnCommandCompleted,
-                           base::Unretained(this), callback));
+  Send(command, base::BindRepeating(&ViscaWebcam::OnCommandCompleted,
+                                    base::Unretained(this), callback));
 }
 
 void ViscaWebcam::SetZoom(int value, const SetPTZCompleteCallback& callback) {
   int actual_value = std::max(value, 0);
   std::vector<char> command = CHAR_VECTOR_FROM_ARRAY(kSetZoomCommand);
   ResponseToCommand(&command, 4, actual_value);
-  Send(command, base::Bind(&ViscaWebcam::OnCommandCompleted,
-                           base::Unretained(this), callback));
+  Send(command, base::BindRepeating(&ViscaWebcam::OnCommandCompleted,
+                                    base::Unretained(this), callback));
 }
 
 void ViscaWebcam::SetFocus(int value, const SetPTZCompleteCallback& callback) {
   int actual_value = std::max(value, 0);
   std::vector<char> command = CHAR_VECTOR_FROM_ARRAY(kSetFocusCommand);
   ResponseToCommand(&command, 4, actual_value);
-  Send(command, base::Bind(&ViscaWebcam::OnCommandCompleted,
-                           base::Unretained(this), callback));
+  Send(command, base::BindRepeating(&ViscaWebcam::OnCommandCompleted,
+                                    base::Unretained(this), callback));
 }
 
 void ViscaWebcam::SetAutofocusState(AutofocusState state,
@@ -437,8 +437,8 @@
   } else {
     command = CHAR_VECTOR_FROM_ARRAY(kSetManualFocusCommand);
   }
-  Send(command, base::Bind(&ViscaWebcam::OnCommandCompleted,
-                           base::Unretained(this), callback));
+  Send(command, base::BindRepeating(&ViscaWebcam::OnCommandCompleted,
+                                    base::Unretained(this), callback));
 }
 
 void ViscaWebcam::SetPanDirection(PanDirection direction,
@@ -461,8 +461,8 @@
       command[5] |= kDefaultTiltSpeed;
       break;
   }
-  Send(command, base::Bind(&ViscaWebcam::OnCommandCompleted,
-                           base::Unretained(this), callback));
+  Send(command, base::BindRepeating(&ViscaWebcam::OnCommandCompleted,
+                                    base::Unretained(this), callback));
 }
 
 void ViscaWebcam::SetTiltDirection(TiltDirection direction,
@@ -485,8 +485,8 @@
       command[5] |= actual_tilt_speed;
       break;
   }
-  Send(command, base::Bind(&ViscaWebcam::OnCommandCompleted,
-                           base::Unretained(this), callback));
+  Send(command, base::BindRepeating(&ViscaWebcam::OnCommandCompleted,
+                                    base::Unretained(this), callback));
 }
 
 void ViscaWebcam::Reset(bool pan,
@@ -496,8 +496,8 @@
   // pan and tilt are always reset together in Visca Webcams.
   if (pan || tilt) {
     Send(CHAR_VECTOR_FROM_ARRAY(kResetPanTiltCommand),
-         base::Bind(&ViscaWebcam::OnCommandCompleted, base::Unretained(this),
-                    callback));
+         base::BindRepeating(&ViscaWebcam::OnCommandCompleted,
+                             base::Unretained(this), callback));
   }
   if (zoom) {
     // Set the default zoom value to 100 to be consistent with V4l2 webcam.
diff --git a/extensions/browser/api/webcam_private/visca_webcam.h b/extensions/browser/api/webcam_private/visca_webcam.h
index 94313aa..98b69f4 100644
--- a/extensions/browser/api/webcam_private/visca_webcam.h
+++ b/extensions/browser/api/webcam_private/visca_webcam.h
@@ -25,7 +25,7 @@
  public:
   ViscaWebcam();
 
-  using OpenCompleteCallback = base::Callback<void(bool)>;
+  using OpenCompleteCallback = base::RepeatingCallback<void(bool)>;
 
   // Open and initialize the web camera. This is done by the following three
   // steps (in order): 1. Open the serial port; 2. Request address; 3. Clear the
@@ -47,7 +47,7 @@
   };
 
   using CommandCompleteCallback =
-      base::Callback<void(bool, const std::vector<char>&)>;
+      base::RepeatingCallback<void(bool, const std::vector<char>&)>;
 
   // Private because WebCam is base::RefCounted.
   ~ViscaWebcam() override;
diff --git a/extensions/browser/api/webcam_private/visca_webcam_unittest.cc b/extensions/browser/api/webcam_private/visca_webcam_unittest.cc
index e7209b2..04bf05d 100644
--- a/extensions/browser/api/webcam_private/visca_webcam_unittest.cc
+++ b/extensions/browser/api/webcam_private/visca_webcam_unittest.cc
@@ -129,8 +129,8 @@
   const char kGetZoomResponse[] = {0x00, 0x50, 0x01, 0x02, 0x03, 0x04, 0xFF};
   serial_connection()->SetReceiveBuffer(ToByteVector(kGetZoomResponse));
   Webcam::GetPTZCompleteCallback receive_callback =
-      base::Bind(&GetPTZExpectations::OnCallback,
-                 base::Owned(new GetPTZExpectations(true, 0x1234)));
+      base::BindRepeating(&GetPTZExpectations::OnCallback,
+                          base::Owned(new GetPTZExpectations(true, 0x1234)));
   webcam()->GetZoom(receive_callback);
   base::RunLoop().RunUntilIdle();
   serial_connection()->CheckSendBufferAndClear(ToByteVector(kGetZoomCommand));
@@ -142,8 +142,8 @@
   const char kSetZoomResponse[] = {0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0xFF};
   serial_connection()->SetReceiveBuffer(ToByteVector(kSetZoomResponse));
   Webcam::SetPTZCompleteCallback send_callback =
-      base::Bind(&SetPTZExpectations::OnCallback,
-                 base::Owned(new SetPTZExpectations(true)));
+      base::BindRepeating(&SetPTZExpectations::OnCallback,
+                          base::Owned(new SetPTZExpectations(true)));
   serial_connection()->SetReceiveBuffer(ToByteVector(kSetZoomResponse));
   webcam()->SetZoom(0x6253, send_callback);
   base::RunLoop().RunUntilIdle();
diff --git a/extensions/browser/app_window/app_window_contents.cc b/extensions/browser/app_window/app_window_contents.cc
index f542a23..0b64fc6b 100644
--- a/extensions/browser/app_window/app_window_contents.cc
+++ b/extensions/browser/app_window/app_window_contents.cc
@@ -77,6 +77,9 @@
 }
 
 void AppWindowContentsImpl::NativeWindowClosed(bool send_onclosed) {
+  // Return early if this method is called when the render frame is not live.
+  if (!web_contents_->GetMainFrame()->IsRenderFrameLive())
+    return;
   ExtensionWebContentsObserver::GetForWebContents(web_contents())
       ->GetLocalFrame(web_contents_->GetMainFrame())
       ->AppWindowClosed(send_onclosed);
diff --git a/extensions/browser/blob_reader.cc b/extensions/browser/blob_reader.cc
index 23a277c..b87b2eacf 100644
--- a/extensions/browser/blob_reader.cc
+++ b/extensions/browser/blob_reader.cc
@@ -42,8 +42,7 @@
                       BlobReader::BlobReadCallback callback,
                       base::Optional<BlobReader::Range> range) {
   std::unique_ptr<BlobReader> reader(new BlobReader(
-      content::BrowserContext::GetBlobRemote(browser_context, blob_uuid),
-      std::move(range)));
+      browser_context->GetBlobRemote(blob_uuid), std::move(range)));
 
   // Move the reader to be owned by the callback, so hold onto a temporary
   // pointer to it so we can still call Start on it.
diff --git a/extensions/browser/extension_web_contents_observer.cc b/extensions/browser/extension_web_contents_observer.cc
index ae94562..c5ea7a0 100644
--- a/extensions/browser/extension_web_contents_observer.cc
+++ b/extensions/browser/extension_web_contents_observer.cc
@@ -315,6 +315,12 @@
 
 mojom::LocalFrame* ExtensionWebContentsObserver::GetLocalFrame(
     content::RenderFrameHost* render_frame_host) {
+  // Attempting to get a remote interface before IsRenderFrameLive() will fail,
+  // leaving a broken pipe that will block all further messages. Return nullptr
+  // instead. Callers should try again after RenderFrameCreated().
+  if (!render_frame_host->IsRenderFrameLive())
+    return nullptr;
+
   mojo::AssociatedRemote<mojom::LocalFrame>& remote =
       local_frame_map_[render_frame_host];
   if (!remote.is_bound()) {
diff --git a/extensions/browser/extension_web_contents_observer.h b/extensions/browser/extension_web_contents_observer.h
index 200111dd..f11dcaa 100644
--- a/extensions/browser/extension_web_contents_observer.h
+++ b/extensions/browser/extension_web_contents_observer.h
@@ -74,7 +74,8 @@
 
   // Returns mojom::LocalFrame* corresponding |render_frame_host|. It emplaces
   // AssociatedRemote<mojom::LocalFrame> to |local_frame_map_| if the map
-  // doesn't have it. Note that it does not return nullptr.
+  // doesn't have it. Note that it could return nullptr if |render_frame_host|
+  // is not live.
   mojom::LocalFrame* GetLocalFrame(content::RenderFrameHost* render_frame_host);
 
  protected:
diff --git a/extensions/common/extension_messages.h b/extensions/common/extension_messages.h
index f7b1c23..def87f2 100644
--- a/extensions/common/extension_messages.h
+++ b/extensions/common/extension_messages.h
@@ -50,6 +50,7 @@
 #include "extensions/common/url_pattern_set.h"
 #include "extensions/common/user_script.h"
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 #include "ipc/ipc_message_utils.h"
 #include "ui/accessibility/ax_param_traits.h"
 #include "url/gurl.h"
diff --git a/extensions/common/guest_view/extensions_guest_view_messages.h b/extensions/common/guest_view/extensions_guest_view_messages.h
index 0e3c3ee..d67335b 100644
--- a/extensions/common/guest_view/extensions_guest_view_messages.h
+++ b/extensions/common/guest_view/extensions_guest_view_messages.h
@@ -10,6 +10,7 @@
 #include <string>
 
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/ipc/gfx_param_traits.h"
 
diff --git a/extensions/renderer/guest_view/extensions_guest_view_container_dispatcher.cc b/extensions/renderer/guest_view/extensions_guest_view_container_dispatcher.cc
index 16f1f47..84921460 100644
--- a/extensions/renderer/guest_view/extensions_guest_view_container_dispatcher.cc
+++ b/extensions/renderer/guest_view/extensions_guest_view_container_dispatcher.cc
@@ -6,6 +6,7 @@
 
 #include "ipc/ipc_message.h"
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 
 namespace extensions {
 
diff --git a/gpu/command_buffer/service/shared_image_video.cc b/gpu/command_buffer/service/shared_image_video.cc
index 9564ea3..da9a5f5 100644
--- a/gpu/command_buffer/service/shared_image_video.cc
+++ b/gpu/command_buffer/service/shared_image_video.cc
@@ -43,7 +43,6 @@
     GrSurfaceOrigin surface_origin,
     SkAlphaType alpha_type,
     scoped_refptr<StreamTextureSharedImageInterface> stream_texture_sii,
-    std::unique_ptr<gles2::AbstractTexture> abstract_texture,
     scoped_refptr<SharedContextState> context_state,
     bool is_thread_safe)
     : SharedImageBackingAndroid(
@@ -59,7 +58,6 @@
           is_thread_safe,
           base::ScopedFD()),
       stream_texture_sii_(std::move(stream_texture_sii)),
-      abstract_texture_(std::move(abstract_texture)),
       context_state_(std::move(context_state)) {
   DCHECK(stream_texture_sii_);
   DCHECK(context_state_);
@@ -89,10 +87,11 @@
 }
 
 bool SharedImageVideo::ProduceLegacyMailbox(MailboxManager* mailbox_manager) {
-  DCHECK(abstract_texture_);
-  mailbox_manager->ProduceTexture(mailbox(),
-                                  abstract_texture_->GetTextureBase());
-  return true;
+  // Android does not use legacy mailbox anymore. Hence marking this as
+  // NOTREACHED() now. Once all platform stops using legacy mailbox, this method
+  // can be removed.
+  NOTREACHED();
+  return false;
 }
 
 size_t SharedImageVideo::EstimatedSizeForMemTracking() const {
diff --git a/gpu/command_buffer/service/shared_image_video.h b/gpu/command_buffer/service/shared_image_video.h
index a30bcc8..fa6c0b7 100644
--- a/gpu/command_buffer/service/shared_image_video.h
+++ b/gpu/command_buffer/service/shared_image_video.h
@@ -37,7 +37,6 @@
       GrSurfaceOrigin surface_origin,
       SkAlphaType alpha_type,
       scoped_refptr<StreamTextureSharedImageInterface> stream_texture_sii,
-      std::unique_ptr<gles2::AbstractTexture> abstract_texture,
       scoped_refptr<SharedContextState> shared_context_state,
       bool is_thread_safe);
 
@@ -101,9 +100,6 @@
   void BeginGLReadAccess(const GLuint service_id);
 
   scoped_refptr<StreamTextureSharedImageInterface> stream_texture_sii_;
-
-  // |abstract_texture_| is only used for legacy mailbox.
-  std::unique_ptr<gles2::AbstractTexture> abstract_texture_;
   scoped_refptr<SharedContextState> context_state_;
 
   DISALLOW_COPY_AND_ASSIGN(SharedImageVideo);
diff --git a/gpu/ipc/common/gpu_messages.h b/gpu/ipc/common/gpu_messages.h
index 4c4d4470..5e38362 100644
--- a/gpu/ipc/common/gpu_messages.h
+++ b/gpu/ipc/common/gpu_messages.h
@@ -31,6 +31,7 @@
 #include "gpu/ipc/common/vulkan_ycbcr_info.h"
 #include "ipc/ipc_channel_handle.h"
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 #include "third_party/skia/include/core/SkImageInfo.h"
 #include "third_party/skia/include/gpu/GrTypes.h"
 #include "ui/gfx/color_space.h"
diff --git a/gpu/ipc/service/stream_texture_android.cc b/gpu/ipc/service/stream_texture_android.cc
index c268909..20bc28d 100644
--- a/gpu/ipc/service/stream_texture_android.cc
+++ b/gpu/ipc/service/stream_texture_android.cc
@@ -336,34 +336,16 @@
   // need to ensure that it gets updated here.
 
   auto scoped_make_current = MakeCurrent(context_state_.get());
-
-  bool use_passthrough =
-      context_state_->feature_info()->is_passthrough_cmd_decoder();
-  std::unique_ptr<gles2::AbstractTexture> legacy_mailbox_texture;
-  if (use_passthrough) {
-    legacy_mailbox_texture =
-        std::make_unique<gles2::AbstractTextureImplOnSharedContextPassthrough>(
-            GL_TEXTURE_EXTERNAL_OES, context_state_);
-  } else {
-    legacy_mailbox_texture =
-        std::make_unique<gles2::AbstractTextureImplOnSharedContext>(
-            GL_TEXTURE_EXTERNAL_OES, GL_RGBA, coded_size.width(),
-            coded_size.height(), 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
-            context_state_);
-  }
-  legacy_mailbox_texture->BindStreamTextureImage(
-      this, texture_owner_->GetTextureId());
-
   auto mailbox = gpu::Mailbox::GenerateForSharedImage();
 
   // TODO(vikassoni): Hardcoding colorspace to SRGB. Figure how if we have a
   // colorspace and wire it here.
   auto shared_image = std::make_unique<SharedImageVideo>(
       mailbox, coded_size, gfx::ColorSpace::CreateSRGB(),
-      kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, this,
-      std::move(legacy_mailbox_texture), context_state_, false);
+      kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, this, context_state_,
+      false);
   channel_->shared_image_stub()->factory()->RegisterBacking(
-      std::move(shared_image), true /* allow_legacy_mailbox */);
+      std::move(shared_image), /*allow_legacy_mailbox=*/false);
 
   return mailbox;
 }
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index d4d3883..0161b97 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -20672,7 +20672,7 @@
       dimensions: "builder:android-official"
       dimensions: "cores:32"
       dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-16.04|Ubuntu-18.04"
+      dimensions: "os:Ubuntu-18.04"
       dimensions: "pool:luci.chromium.ci"
       exe {
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
@@ -26466,7 +26466,7 @@
       dimensions: "builder:linux-official"
       dimensions: "cores:32"
       dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-16.04|Ubuntu-18.04"
+      dimensions: "os:Ubuntu-18.04"
       dimensions: "pool:luci.chromium.ci"
       exe {
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
@@ -35232,7 +35232,7 @@
       dimensions: "builderless:1"
       dimensions: "cores:32"
       dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-16.04|Ubuntu-18.04"
+      dimensions: "os:Ubuntu-18.04"
       dimensions: "pool:luci.chromium.try"
       dimensions: "ssd:0"
       exe {
@@ -39823,7 +39823,7 @@
       dimensions: "builderless:1"
       dimensions: "cores:32"
       dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-16.04|Ubuntu-18.04"
+      dimensions: "os:Ubuntu-18.04"
       dimensions: "pool:luci.chromium.try"
       dimensions: "ssd:0"
       exe {
@@ -47351,7 +47351,7 @@
       dimensions: "builderless:1"
       dimensions: "cores:32"
       dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-16.04|Ubuntu-18.04"
+      dimensions: "os:Ubuntu-18.04"
       dimensions: "pool:luci.chromium.try"
       dimensions: "ssd:0"
       exe {
diff --git a/infra/config/lib/try.star b/infra/config/lib/try.star
index d6cf3ec..010b3cc 100644
--- a/infra/config/lib/try.star
+++ b/infra/config/lib/try.star
@@ -218,7 +218,7 @@
     )
 
 def chromium_builder(*, name, **kwargs):
-    kwargs.setdefault("os", builders.os.LINUX_XENIAL_OR_BIONIC_REMOVE)
+    kwargs.setdefault("os", builders.os.LINUX_BIONIC_REMOVE)
     return try_builder(
         name = name,
         builder_group = "tryserver.chromium",
diff --git a/infra/config/subprojects/chromium/ci.star b/infra/config/subprojects/chromium/ci.star
index 808bd50d..8a65c34d 100644
--- a/infra/config/subprojects/chromium/ci.star
+++ b/infra/config/subprojects/chromium/ci.star
@@ -1454,7 +1454,7 @@
         short_name = "off",
     ),
     cores = 32,
-    os = os.LINUX_XENIAL_OR_BIONIC_REMOVE,
+    os = os.LINUX_BIONIC_REMOVE,
     tree_closing = False,
 
     # See https://crbug.com/1153349#c22, as we update symbol_level=2, build
@@ -1516,7 +1516,7 @@
     # have populated their cached by getting through the compile step
     execution_timeout = 10 * time.hour,
     main_console_view = main_console_if_on_branch(),
-    os = os.LINUX_XENIAL_OR_BIONIC_REMOVE,
+    os = os.LINUX_BIONIC_REMOVE,
     tree_closing = False,
 )
 
diff --git a/ios/chrome/app/main_application_delegate.mm b/ios/chrome/app/main_application_delegate.mm
index 4b396d61..bca4705 100644
--- a/ios/chrome/app/main_application_delegate.mm
+++ b/ios/chrome/app/main_application_delegate.mm
@@ -328,14 +328,6 @@
   }
 }
 
-#pragma mark Downloading Data in the Background
-
-- (void)application:(UIApplication*)application
-    handleEventsForBackgroundURLSession:(NSString*)identifier
-                      completionHandler:(void (^)(void))completionHandler {
-  completionHandler();
-}
-
 #pragma mark Continuing User Activity and Handling Quick Actions
 
 - (BOOL)application:(UIApplication*)application
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 6ace97a..c3d5a37 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -1796,7 +1796,8 @@
         base::mac::ObjCCastStrict<UINavigationController>(
             viewControllerToPresent);
     if ([navController.topViewController
-            isMemberOfClass:[WelcomeToChromeViewController class]]) {
+            isMemberOfClass:[WelcomeToChromeViewController class]] ||
+        base::FeatureList::IsEnabled(kEnableFREUIModuleIOS)) {
       self.hideStatusBar = YES;
 
       // Load view from Launch Screen and add it to window.
diff --git a/ios/chrome/browser/ui/first_run/first_run_coordinator.mm b/ios/chrome/browser/ui/first_run/first_run_coordinator.mm
index 6813184b..990bf3a 100644
--- a/ios/chrome/browser/ui/first_run/first_run_coordinator.mm
+++ b/ios/chrome/browser/ui/first_run/first_run_coordinator.mm
@@ -11,6 +11,7 @@
 #import "ios/chrome/browser/ui/first_run/first_run_screen_delegate.h"
 #import "ios/chrome/browser/ui/first_run/first_run_screen_provider.h"
 #import "ios/chrome/browser/ui/first_run/first_run_screen_type.h"
+#import "ios/chrome/browser/ui/first_run/first_run_util.h"
 #import "ios/chrome/browser/ui/first_run/signin/signin_screen_coordinator.h"
 #import "ios/chrome/browser/ui/first_run/sync/sync_screen_coordinator.h"
 #import "ios/chrome/browser/ui/first_run/welcome/welcome_screen_coordinator.h"
@@ -58,6 +59,7 @@
 - (void)stop {
   void (^completion)(void) = ^{
     base::UmaHistogramEnumeration("FirstRun.Stage", first_run::kComplete);
+    WriteFirstRunSentinel();
     [self.delegate didFinishPresentingScreens];
   };
   [self.baseViewController dismissViewControllerAnimated:YES
diff --git a/ios/chrome/browser/ui/first_run/first_run_util.h b/ios/chrome/browser/ui/first_run/first_run_util.h
index f07e985..be2335bc 100644
--- a/ios/chrome/browser/ui/first_run/first_run_util.h
+++ b/ios/chrome/browser/ui/first_run/first_run_util.h
@@ -34,6 +34,9 @@
     first_run::SignInAttemptStatus sign_in_attempt_status,
     BOOL has_sso_accounts);
 
+// Records the completion of the first run.
+void WriteFirstRunSentinel();
+
 // Methods for writing sentinel and recording metrics and posting notifications
 void FinishFirstRun(ChromeBrowserState* browserState,
                     web::WebState* web_state,
diff --git a/ios/chrome/browser/ui/first_run/first_run_util.mm b/ios/chrome/browser/ui/first_run/first_run_util.mm
index eab2d26..18cfe86 100644
--- a/ios/chrome/browser/ui/first_run/first_run_util.mm
+++ b/ios/chrome/browser/ui/first_run/first_run_util.mm
@@ -110,6 +110,10 @@
                     web::WebState* web_state,
                     FirstRunConfiguration* config,
                     id<SyncPresenter> presenter) {
+  // This method souldn't be called with the new FRE, and should be removed
+  // after the new FRE module is shipped.
+  DCHECK(!base::FeatureList::IsEnabled(kEnableFREUIModuleIOS));
+
   [[NSNotificationCenter defaultCenter]
       postNotificationName:kChromeFirstRunUIWillFinishNotification
                     object:nil];
@@ -120,6 +124,13 @@
   DisplaySyncErrors(browserState, web_state, presenter);
 }
 
+void WriteFirstRunSentinel() {
+  kFirstRunSentinelCreated = true;
+  base::ThreadPool::PostTask(
+      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+      base::BindOnce(&CreateSentinel));
+}
+
 void FirstRunDismissed() {
   [[NSNotificationCenter defaultCenter]
       postNotificationName:kChromeFirstRunUIDidFinishNotification
diff --git a/ipc/ipc_channel_proxy_unittest_messages.h b/ipc/ipc_channel_proxy_unittest_messages.h
index ae45059..27430bb9 100644
--- a/ipc/ipc_channel_proxy_unittest_messages.h
+++ b/ipc/ipc_channel_proxy_unittest_messages.h
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 
 // Singly-included section for enums and custom IPC traits.
 #ifndef IPC_CHANNEL_PROXY_UNITTEST_MESSAGES_H_
diff --git a/ipc/ipc_fuzzing_tests.cc b/ipc/ipc_fuzzing_tests.cc
index a777705..3e67ad4 100644
--- a/ipc/ipc_fuzzing_tests.cc
+++ b/ipc/ipc_fuzzing_tests.cc
@@ -21,6 +21,7 @@
 
 #define IPC_MESSAGE_IMPL
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 
 #define IPC_MESSAGE_START TestMsgStart
 
diff --git a/ipc/ipc_message_unittest.cc b/ipc/ipc_message_unittest.cc
index 5c966ee..2a4c1b7 100644
--- a/ipc/ipc_message_unittest.cc
+++ b/ipc/ipc_message_unittest.cc
@@ -23,6 +23,7 @@
 
 #define IPC_MESSAGE_IMPL
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 
 #define IPC_MESSAGE_START TestMsgStart
 
diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h
index 82a3502..18ae067 100644
--- a/ipc/ipc_message_utils.h
+++ b/ipc/ipc_message_utils.h
@@ -34,7 +34,6 @@
 #include "base/strings/string_util.h"
 #include "base/util/type_safety/id_type.h"
 #include "build/build_config.h"
-#include "ipc/ipc_message_start.h"
 #include "ipc/ipc_param_traits.h"
 #include "ipc/ipc_sync_message.h"
 
diff --git a/ipc/ipc_perftest_messages.h b/ipc/ipc_perftest_messages.h
index 1dc0890..3370ded 100644
--- a/ipc/ipc_perftest_messages.h
+++ b/ipc/ipc_perftest_messages.h
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 
 #define IPC_MESSAGE_START TestMsgStart
 
diff --git a/ipc/ipc_sync_message_unittest.h b/ipc/ipc_sync_message_unittest.h
index 114aca6f..da1699a7 100644
--- a/ipc/ipc_sync_message_unittest.h
+++ b/ipc/ipc_sync_message_unittest.h
@@ -5,6 +5,7 @@
 #include <string>
 
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 
 #define IPC_MESSAGE_START TestMsgStart
 
diff --git a/ipc/message_filter_router.cc b/ipc/message_filter_router.cc
index 685443b..c7e102a 100644
--- a/ipc/message_filter_router.cc
+++ b/ipc/message_filter_router.cc
@@ -9,6 +9,7 @@
 
 #include "base/stl_util.h"
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 #include "ipc/ipc_message_utils.h"
 #include "ipc/message_filter.h"
 
diff --git a/ipc/sync_socket_unittest.cc b/ipc/sync_socket_unittest.cc
index f6c0aa8..fbe0959 100644
--- a/ipc/sync_socket_unittest.cc
+++ b/ipc/sync_socket_unittest.cc
@@ -28,6 +28,7 @@
 
 #define IPC_MESSAGE_IMPL
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 
 #define IPC_MESSAGE_START TestMsgStart
 
diff --git a/media/blink/BUILD.gn b/media/blink/BUILD.gn
index 3537092..f96c86f9 100644
--- a/media/blink/BUILD.gn
+++ b/media/blink/BUILD.gn
@@ -35,6 +35,7 @@
     "multibuffer_reader.h",
     "new_session_cdm_result_promise.cc",
     "new_session_cdm_result_promise.h",
+    "power_status_helper.cc",
     "power_status_helper.h",
     "remote_playback_client_wrapper_impl.cc",
     "remote_playback_client_wrapper_impl.h",
@@ -82,6 +83,7 @@
     "//media/learning/mojo/public/cpp:cpp",
     "//media/mojo/mojom",
     "//net",
+    "//services/device/public/mojom",
     "//services/network/public/cpp:cpp",
     "//services/service_manager/public/cpp:cpp",
     "//third_party/blink/public:blink",
@@ -116,6 +118,7 @@
     "//mojo/core/embedder",
     "//net",
     "//services/device:test_support",
+    "//services/device/public/mojom",
     "//testing/gmock",
     "//testing/gtest",
     "//third_party/blink/public:blink",
@@ -149,6 +152,7 @@
     "mock_webassociatedurlloader.h",
     "multibuffer_data_source_unittest.cc",
     "multibuffer_unittest.cc",
+    "power_status_helper_unittest.cc",
     "resource_multibuffer_data_provider_unittest.cc",
     "run_all_unittests.cc",
     "smoothness_helper_unittest.cc",
diff --git a/content/renderer/media/power_status_helper_impl.cc b/media/blink/power_status_helper.cc
similarity index 84%
rename from content/renderer/media/power_status_helper_impl.cc
rename to media/blink/power_status_helper.cc
index 606435e..fd9b3f4 100644
--- a/content/renderer/media/power_status_helper_impl.cc
+++ b/media/blink/power_status_helper.cc
@@ -2,17 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/renderer/media/power_status_helper_impl.h"
+#include "media/blink/power_status_helper.h"
 
+#include <utility>
+
+#include "base/check.h"
+#include "base/check_op.h"
 #include "base/metrics/histogram_macros.h"
+#include "media/base/pipeline_metadata.h"
 #include "services/device/public/mojom/battery_status.mojom.h"
 
-using ::device::mojom::BatteryStatusPtr;
-
-namespace content {
-
+namespace media {
 namespace {
 
+using ::device::mojom::BatteryStatusPtr;
+
 static constexpr const char* kBatteryDeltaHistogram =
     "Media.PlaybackPower.BatteryDelta";
 static constexpr const char* kElapsedTimeHistogram =
@@ -23,19 +27,19 @@
 
 // Maximum enum value that we'll generate, inclusive.
 static constexpr int kMaxEnumValue =
-    PowerStatusHelperImpl::Bits::kCodecBitsH264 |
-    PowerStatusHelperImpl::Bits::kCodecBitsVP9Profile0 |
-    PowerStatusHelperImpl::Bits::kCodecBitsVP9Profile2 |
+    PowerStatusHelper::Bits::kCodecBitsH264 |
+    PowerStatusHelper::Bits::kCodecBitsVP9Profile0 |
+    PowerStatusHelper::Bits::kCodecBitsVP9Profile2 |
 
-    PowerStatusHelperImpl::Bits::kResolution360p |
-    PowerStatusHelperImpl::Bits::kResolution720p |
-    PowerStatusHelperImpl::Bits::kResolution1080p |
+    PowerStatusHelper::Bits::kResolution360p |
+    PowerStatusHelper::Bits::kResolution720p |
+    PowerStatusHelper::Bits::kResolution1080p |
 
-    PowerStatusHelperImpl::Bits::kFrameRate30 |
-    PowerStatusHelperImpl::Bits::kFrameRate60 |
+    PowerStatusHelper::Bits::kFrameRate30 |
+    PowerStatusHelper::Bits::kFrameRate60 |
 
-    PowerStatusHelperImpl::Bits::kFullScreenNo |
-    PowerStatusHelperImpl::Bits::kFullScreenYes;
+    PowerStatusHelper::Bits::kFullScreenNo |
+    PowerStatusHelper::Bits::kFullScreenYes;
 
 // UMA buckets are always [uma_min, uma_max).  The first bucket is an implicit
 // underflow bucket [0, uma_min), and the last is the overflow bucket
@@ -82,14 +86,14 @@
 
 }  // namespace
 
-PowerStatusHelperImpl::PowerStatusHelperImpl(
+PowerStatusHelper::PowerStatusHelper(
     CreateBatteryMonitorCB create_battery_monitor_cb)
     : create_battery_monitor_cb_(std::move(create_battery_monitor_cb)) {}
 
-PowerStatusHelperImpl::~PowerStatusHelperImpl() = default;
+PowerStatusHelper::~PowerStatusHelper() = default;
 
 // static
-base::Optional<int> PowerStatusHelperImpl::BucketFor(
+base::Optional<int> PowerStatusHelper::BucketFor(
     bool is_playing,
     bool has_video,
     media::VideoCodec codec,
@@ -141,22 +145,21 @@
 }
 
 // static
-const char* PowerStatusHelperImpl::BatteryDeltaHistogram() {
+const char* PowerStatusHelper::BatteryDeltaHistogram() {
   return kBatteryDeltaHistogram;
 }
 
 // static
-const char* PowerStatusHelperImpl::ElapsedTimeHistogram() {
+const char* PowerStatusHelper::ElapsedTimeHistogram() {
   return kElapsedTimeHistogram;
 }
 
-void PowerStatusHelperImpl::SetIsPlaying(bool is_playing) {
+void PowerStatusHelper::SetIsPlaying(bool is_playing) {
   is_playing_ = is_playing;
   OnAnyStateChange();
 }
 
-void PowerStatusHelperImpl::SetMetadata(
-    const media::PipelineMetadata& metadata) {
+void PowerStatusHelper::SetMetadata(const media::PipelineMetadata& metadata) {
   has_video_ = metadata.has_video;
   codec_ = metadata.video_decoder_config.codec();
   profile_ = metadata.video_decoder_config.profile();
@@ -164,24 +167,23 @@
   OnAnyStateChange();
 }
 
-void PowerStatusHelperImpl::SetIsFullscreen(bool is_fullscreen) {
+void PowerStatusHelper::SetIsFullscreen(bool is_fullscreen) {
   is_fullscreen_ = is_fullscreen;
   OnAnyStateChange();
 }
 
-void PowerStatusHelperImpl::SetAverageFrameRate(
-    base::Optional<int> average_fps) {
+void PowerStatusHelper::SetAverageFrameRate(base::Optional<int> average_fps) {
   average_fps_ = average_fps;
   OnAnyStateChange();
 }
 
-void PowerStatusHelperImpl::UpdatePowerExperimentState(bool state) {
+void PowerStatusHelper::UpdatePowerExperimentState(bool state) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   experiment_state_ = state;
   OnAnyStateChange();
 }
 
-void PowerStatusHelperImpl::OnAnyStateChange() {
+void PowerStatusHelper::OnAnyStateChange() {
   base::Optional<int> old_bucket = current_bucket_;
   current_bucket_.reset();
 
@@ -204,7 +206,7 @@
   }
 }
 
-void PowerStatusHelperImpl::OnBatteryStatus(
+void PowerStatusHelper::OnBatteryStatus(
     device::mojom::BatteryStatusPtr battery_status) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
@@ -268,7 +270,7 @@
   }
 }
 
-void PowerStatusHelperImpl::StartMonitoring() {
+void PowerStatusHelper::StartMonitoring() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!battery_monitor_.is_bound()) {
@@ -290,19 +292,19 @@
   battery_level_baseline_.reset();
 }
 
-void PowerStatusHelperImpl::StopMonitoring() {
+void PowerStatusHelper::StopMonitoring() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   battery_monitor_.reset();
 }
 
-void PowerStatusHelperImpl::QueryNextStatus() {
+void PowerStatusHelper::QueryNextStatus() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(battery_monitor_.is_bound());
 
   // Remember that overlapping calls are not allowed by BatteryMonitor, and are
   // treated as a connection error.  Unretained since we own |battery_monitor_|.
   battery_monitor_->QueryNextStatus(base::BindOnce(
-      &PowerStatusHelperImpl::OnBatteryStatus, base::Unretained(this)));
+      &PowerStatusHelper::OnBatteryStatus, base::Unretained(this)));
 }
 
-}  // namespace content
+}  // namespace media
diff --git a/media/blink/power_status_helper.h b/media/blink/power_status_helper.h
index 828055a..2219a043 100644
--- a/media/blink/power_status_helper.h
+++ b/media/blink/power_status_helper.h
@@ -5,35 +5,142 @@
 #ifndef MEDIA_BLINK_POWER_STATUS_HELPER_H_
 #define MEDIA_BLINK_POWER_STATUS_HELPER_H_
 
-#include "base/macros.h"
+#include "base/callback.h"
 #include "base/optional.h"
+#include "base/sequence_checker.h"
 #include "base/time/time.h"
-#include "media/base/pipeline_metadata.h"
 #include "media/base/video_codecs.h"
 #include "media/blink/media_blink_export.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/device/public/mojom/battery_monitor.mojom.h"
+#include "ui/gfx/geometry/size.h"
 
 namespace media {
+struct PipelineMetadata;
 
-// Base class to monitor for power events during playback and record them to
-// UMA / UKM.
+// Class to monitor for power events during playback and record them to UMA/UKM.
 class MEDIA_BLINK_EXPORT PowerStatusHelper {
  public:
-  PowerStatusHelper() = default;
-  virtual ~PowerStatusHelper() = default;
+  using CreateBatteryMonitorCB = base::RepeatingCallback<
+      mojo::PendingRemote<device::mojom::BatteryMonitor>()>;
+
+  // Bits used to construct UMA buckets.
+  // These values are persisted to logs. Entries should not be renumbered and
+  // numeric values should never be reused.
+  enum /* not class */ Bits {
+    // Bit layout is: [msb] xx f F RR CC [lsb]
+    // R == resolution
+    // C == codec
+    // F == frame rate
+    // f == full screen
+    // x == unused
+    // Remember that we can't use more than 6 bits, since we shouldn't go over
+    // 100 UMA buckets.
+
+    // Codec bits, values 0x00 to 0x03
+    // Named "CodecBits" to prevent a name collision with media::VideoCodec.
+    kCodecBitsH264 = (0x00) << 0,
+    kCodecBitsVP9Profile0 = (0x01) << 0,
+    // Ignore Profile1
+    kCodecBitsVP9Profile2 = (0x02) << 0,
+    // TODO(liberato): add AV1
+
+    // Resolution bits, values 0x00 to 0x03
+    kResolution360p = (0x00) << 2,
+    kResolution720p = (0x01) << 2,
+    kResolution1080p = (0x02) << 2,
+
+    // Frame rate bits, values 0x00 to 0x01
+    kFrameRate30 = (0x00) << 4,
+    kFrameRate60 = (0x01) << 4,
+
+    // Fullscreen bits, values 0x00 to 0x01
+    kFullScreenNo = (0x00) << 5,
+    kFullScreenYes = (0x01) << 5,
+
+    // This is not a valid bit for, you know, testing.
+    kNotAValidBitForTesting = (0x01) << 10,
+  };
+
+  // If |stats_cb| is not provided, then we'll record to UMA.  It's just for
+  // the tests.
+  explicit PowerStatusHelper(CreateBatteryMonitorCB create_battery_monitor_cb);
+  PowerStatusHelper(const PowerStatusHelper&) = delete;
+  PowerStatusHelper& operator=(const PowerStatusHelper&) = delete;
+  ~PowerStatusHelper();
 
   // Notify us about changes to the player.
-  virtual void SetIsPlaying(bool is_playing) = 0;
-  virtual void SetMetadata(const PipelineMetadata& metadata) = 0;
-  virtual void SetIsFullscreen(bool is_fullscreen) = 0;
-  virtual void SetAverageFrameRate(base::Optional<int> average_fps) = 0;
+  void SetIsPlaying(bool is_playing);
+  void SetMetadata(const media::PipelineMetadata& metadata);
+  void SetIsFullscreen(bool is_fullscreen);
+  void SetAverageFrameRate(base::Optional<int> average_fps);
 
   // Handle notifications about the experiment state from the power experiment.
   // manager.  |state| indicates whether our player is eligible to record power
   // experiments readings.
-  virtual void UpdatePowerExperimentState(bool state) = 0;
+  void UpdatePowerExperimentState(bool state);
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(PowerStatusHelper);
+  friend class PowerStatusHelperTest;
+  friend class PowerStatusHelperBucketTest;
+
+  // Return the UMA bucket for the given video configuration, or nullopt if we
+  // don't want to record it.
+  static base::Optional<int> BucketFor(bool is_playing,
+                                       bool has_video,
+                                       media::VideoCodec codec,
+                                       media::VideoCodecProfile profile,
+                                       gfx::Size natural_size,
+                                       bool is_fullscreen,
+                                       base::Optional<int> average_fps);
+
+  // Return the histogram names.  Here so that tests can find them too.
+  static const char* BatteryDeltaHistogram();
+  static const char* ElapsedTimeHistogram();
+
+  // Recompute everything when playback state or power experiment state changes.
+  void OnAnyStateChange();
+
+  // Handle updates about the current battery status.
+  void OnBatteryStatus(device::mojom::BatteryStatusPtr battery_status);
+
+  // Start monitoring if we haven't already.  Any outstanding callbacks will be
+  // cancelled if monitoring was already in progress.
+  void StartMonitoring();
+  void StopMonitoring();
+
+  // Register to receive a power update the next time it changes.
+  void QueryNextStatus();
+
+  CreateBatteryMonitorCB create_battery_monitor_cb_;
+
+  // Most recent parameters we were given.
+  bool is_playing_ = false;
+  bool has_video_ = false;
+  media::VideoCodec codec_ = media::VideoCodec::kUnknownVideoCodec;
+  media::VideoCodecProfile profile_ =
+      media::VideoCodecProfile::VIDEO_CODEC_PROFILE_UNKNOWN;
+  gfx::Size natural_size_;
+  bool is_fullscreen_ = false;
+  // For estimating fps.  Can be unset if we don't know.
+  base::Optional<int> average_fps_;
+
+  // Current UMA bucket, if any.
+  base::Optional<int> current_bucket_;
+
+  // If set, our previous battery level, from 0-100.
+  base::Optional<float> battery_level_baseline_;
+  // The time at which we last got an update from |battery_monitor_|.
+  base::TimeTicks last_update_;
+
+  // Are we currently the player that should be recording power for the power
+  // experiment, according to the MediaPowerExperimentManager?
+  bool experiment_state_ = false;
+
+  mojo::Remote<device::mojom::BatteryMonitor> battery_monitor_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
 };
 
 }  // namespace media
diff --git a/content/renderer/media/power_status_helper_impl_unittest.cc b/media/blink/power_status_helper_unittest.cc
similarity index 76%
rename from content/renderer/media/power_status_helper_impl_unittest.cc
rename to media/blink/power_status_helper_unittest.cc
index c3eedcd..caae527 100644
--- a/content/renderer/media/power_status_helper_impl_unittest.cc
+++ b/media/blink/power_status_helper_unittest.cc
@@ -2,34 +2,37 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/renderer/media/power_status_helper_impl.h"
+#include "media/blink/power_status_helper.h"
 
+#include <memory>
 #include <tuple>
+#include <utility>
+#include <vector>
 
-//#include "base/metrics/histogram.h"
-//#include "base/metrics/statistics_recorder.h"
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/mock_callback.h"
 #include "base/test/task_environment.h"
+#include "media/base/pipeline_metadata.h"
+#include "media/blink/blink_platform_with_task_environment.h"
 #include "services/device/public/mojom/battery_status.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace content {
+namespace media {
 
-using testing::_;
-using testing::AnyNumber;
-using testing::Bool;
-using testing::Combine;
-using testing::Eq;
-using testing::Gt;
-using testing::Lt;
-using testing::ResultOf;
-using testing::Return;
-using testing::Values;
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::Bool;
+using ::testing::Combine;
+using ::testing::Eq;
+using ::testing::Gt;
+using ::testing::Lt;
+using ::testing::ResultOf;
+using ::testing::Return;
+using ::testing::Values;
 
-class PowerStatusHelperImplTest : public testing::Test {
+class PowerStatusHelperTest : public testing::Test {
  public:
   class MockBatteryMonitor : public device::mojom::BatteryMonitor {
    public:
@@ -71,7 +74,7 @@
 
     // Would be nice if this were base::MockCallback, but move-only types don't
     // seem to work.
-    PowerStatusHelperImpl::CreateBatteryMonitorCB cb() {
+    PowerStatusHelper::CreateBatteryMonitorCB cb() {
       return base::BindRepeating(&MockBatteryMonitor::GetBatteryMonitor,
                                  base::Unretained(this));
     }
@@ -105,7 +108,7 @@
   };
 
   void SetUp() override {
-    helper_ = std::make_unique<PowerStatusHelperImpl>(monitor_.cb());
+    helper_ = std::make_unique<PowerStatusHelper>(monitor_.cb());
   }
 
   // Set up |helper_| to be in a state that should record. Returns the bucket.
@@ -132,15 +135,16 @@
     helper_->UpdatePowerExperimentState(true);
     base::RunLoop().RunUntilIdle();
 
-    return PowerStatusHelperImpl::kCodecBitsH264 |
-           PowerStatusHelperImpl::kResolution360p |
-           PowerStatusHelperImpl::kFrameRate60 |
-           (alternate ? PowerStatusHelperImpl::kFullScreenYes
-                      : PowerStatusHelperImpl::kFullScreenNo);
+    return PowerStatusHelper::kCodecBitsH264 |
+           PowerStatusHelper::kResolution360p |
+           PowerStatusHelper::kFrameRate60 |
+           (alternate ? PowerStatusHelper::kFullScreenYes
+                      : PowerStatusHelper::kFullScreenNo);
   }
 
   void FastForward(base::TimeDelta delta) {
-    task_environment_.FastForwardBy(delta);
+    BlinkPlatformWithTaskEnvironment::GetTaskEnvironment()->FastForwardBy(
+        delta);
   }
 
   // Verify that we've added |battery_delta| and |time_delta| to |bucket| in
@@ -162,18 +166,15 @@
   int total_battery_delta = 0;
   int total_time_delta = 0;  // msec
 
-  base::test::TaskEnvironment task_environment_{
-      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
-
   MockBatteryMonitor monitor_;
 
   // Helper under test
-  std::unique_ptr<PowerStatusHelperImpl> helper_;
+  std::unique_ptr<PowerStatusHelper> helper_;
 
   base::HistogramTester histogram_tester_;
 };
 
-TEST_F(PowerStatusHelperImplTest, EmptyPendingRemoteIsOkay) {
+TEST_F(PowerStatusHelperTest, EmptyPendingRemoteIsOkay) {
   // Enable power monitoring, but have the callback fail to provide a remote.
   // This should be handled gracefully.
 
@@ -183,7 +184,7 @@
   MakeRecordable();
 }
 
-TEST_F(PowerStatusHelperImplTest, UnboundPendingRemoteIsOkay) {
+TEST_F(PowerStatusHelperTest, UnboundPendingRemoteIsOkay) {
   // TODO: this doesn't run the "is bound" part.  maybe we should just delete
   // the "is bound" part, or switch to a disconnection handler, etc.
   monitor_.remote_type_ = MockBatteryMonitor::RemoteType::kDisconnected;
@@ -191,7 +192,7 @@
   MakeRecordable();
 }
 
-TEST_F(PowerStatusHelperImplTest, BasicReportingWithFractionalAmounts) {
+TEST_F(PowerStatusHelperTest, BasicReportingWithFractionalAmounts) {
   // Send three power updates, and verify that an update is called for the
   // last two.  The update should be fractional, so that some of it is rolled
   // over to the next call.
@@ -225,7 +226,7 @@
   VerifyHistogramDelta(bucket, 11, time_delta);
 }
 
-TEST_F(PowerStatusHelperImplTest, ChargingResetsBaseline) {
+TEST_F(PowerStatusHelperTest, ChargingResetsBaseline) {
   // Send some power updates, then send an update that's marked as 'charging'.
   // Make sure that the baseline resets.
   EXPECT_CALL(monitor_, DidGetBatteryMonitor()).Times(1);
@@ -256,7 +257,7 @@
   VerifyHistogramDelta(bucket, 10, time_delta);
 }
 
-TEST_F(PowerStatusHelperImplTest, ExperimentStateStopsRecording) {
+TEST_F(PowerStatusHelperTest, ExperimentStateStopsRecording) {
   // Verify that stopping the power experiment stops recording.
   EXPECT_CALL(monitor_, DidGetBatteryMonitor()).Times(1);
   EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
@@ -272,7 +273,7 @@
   monitor_.ProvidePowerUpdate(false, 1.0);
 }
 
-TEST_F(PowerStatusHelperImplTest, ChangingBucketsWorks) {
+TEST_F(PowerStatusHelperTest, ChangingBucketsWorks) {
   // Switch buckets mid-recording, and make sure that we get a new bucket and
   // use a new baseline.
   EXPECT_CALL(monitor_, DidGetBatteryMonitor()).Times(1);
@@ -303,7 +304,7 @@
   VerifyHistogramDelta(second_bucket, 10, time_delta);
 }
 
-TEST_F(PowerStatusHelperImplTest, UnbucketedVideoStopsRecording) {
+TEST_F(PowerStatusHelperTest, UnbucketedVideoStopsRecording) {
   // If we switch to video that doesn't have a bucket, then recording should
   // stop too.
   EXPECT_CALL(monitor_, DidGetBatteryMonitor()).Times(1);
@@ -317,7 +318,7 @@
   base::RunLoop().RunUntilIdle();
 }
 
-TEST_F(PowerStatusHelperImplTest, UnbucketedFrameRateStopsRecording) {
+TEST_F(PowerStatusHelperTest, UnbucketedFrameRateStopsRecording) {
   // If we switch to an unbucketed frame rate, then it should stop recording.
   EXPECT_CALL(monitor_, DidGetBatteryMonitor()).Times(1);
   EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
@@ -330,16 +331,15 @@
   base::RunLoop().RunUntilIdle();
 }
 
-using PlaybackParamsTuple =
-    std::tuple<bool,                        /* is_playing */
-               bool,                        /* has_video */
-               PowerStatusHelperImpl::Bits, /* codec */
-               PowerStatusHelperImpl::Bits, /* resolution */
-               PowerStatusHelperImpl::Bits, /* frame rate */
-               PowerStatusHelperImpl::Bits  /* full screen */
-               >;
+using PlaybackParamsTuple = std::tuple<bool,                    /* is_playing */
+                                       bool,                    /* has_video */
+                                       PowerStatusHelper::Bits, /* codec */
+                                       PowerStatusHelper::Bits, /* resolution */
+                                       PowerStatusHelper::Bits, /* frame rate */
+                                       PowerStatusHelper::Bits /* full screen */
+                                       >;
 
-class PowerStatusHelperImplBucketTest
+class PowerStatusHelperBucketTest
     : public testing::TestWithParam<PlaybackParamsTuple> {
  public:
   base::Optional<int> BucketFor(bool is_playing,
@@ -349,13 +349,12 @@
                                 gfx::Size coded_size,
                                 bool is_fullscreen,
                                 base::Optional<int> average_fps) {
-    return PowerStatusHelperImpl::BucketFor(is_playing, has_video, codec,
-                                            profile, coded_size, is_fullscreen,
-                                            average_fps);
+    return PowerStatusHelper::BucketFor(is_playing, has_video, codec, profile,
+                                        coded_size, is_fullscreen, average_fps);
   }
 };
 
-TEST_P(PowerStatusHelperImplBucketTest, TestBucket) {
+TEST_P(PowerStatusHelperBucketTest, TestBucket) {
   // Construct a params that should end up in the bucket specified by the test
   // parameter, if one exists.
   bool expect_bucket = true;
@@ -370,13 +369,13 @@
   auto codec_bits = std::get<2>(GetParam());
   media::VideoCodec codec;
   media::VideoCodecProfile profile;
-  if (codec_bits == PowerStatusHelperImpl::Bits::kCodecBitsH264) {
+  if (codec_bits == PowerStatusHelper::Bits::kCodecBitsH264) {
     codec = media::kCodecH264;
     profile = media::H264PROFILE_MAIN;
-  } else if (codec_bits == PowerStatusHelperImpl::Bits::kCodecBitsVP9Profile0) {
+  } else if (codec_bits == PowerStatusHelper::Bits::kCodecBitsVP9Profile0) {
     codec = media::kCodecVP9;
     profile = media::VP9PROFILE_PROFILE0;
-  } else if (codec_bits == PowerStatusHelperImpl::Bits::kCodecBitsVP9Profile2) {
+  } else if (codec_bits == PowerStatusHelper::Bits::kCodecBitsVP9Profile2) {
     codec = media::kCodecVP9;
     profile = media::VP9PROFILE_PROFILE2;
   } else {
@@ -388,11 +387,11 @@
 
   auto res = std::get<3>(GetParam());
   gfx::Size coded_size;
-  if (res == PowerStatusHelperImpl::Bits::kResolution360p) {
+  if (res == PowerStatusHelper::Bits::kResolution360p) {
     coded_size = gfx::Size(640, 360);
-  } else if (res == PowerStatusHelperImpl::Bits::kResolution720p) {
+  } else if (res == PowerStatusHelper::Bits::kResolution720p) {
     coded_size = gfx::Size(1280, 720);
-  } else if (res == PowerStatusHelperImpl::Bits::kResolution1080p) {
+  } else if (res == PowerStatusHelper::Bits::kResolution1080p) {
     coded_size = gfx::Size(1920, 1080);
   } else {
     coded_size = gfx::Size(1234, 5678);
@@ -401,9 +400,9 @@
 
   auto fps = std::get<4>(GetParam());
   base::Optional<int> average_fps;
-  if (fps == PowerStatusHelperImpl::Bits::kFrameRate30) {
+  if (fps == PowerStatusHelper::Bits::kFrameRate30) {
     average_fps = 30;
-  } else if (fps == PowerStatusHelperImpl::Bits::kFrameRate60) {
+  } else if (fps == PowerStatusHelper::Bits::kFrameRate60) {
     average_fps = 60;
   } else {
     average_fps = 90;
@@ -411,7 +410,7 @@
   }
 
   bool is_fullscreen =
-      (std::get<5>(GetParam()) == PowerStatusHelperImpl::Bits::kFullScreenYes);
+      (std::get<5>(GetParam()) == PowerStatusHelper::Bits::kFullScreenYes);
 
   auto bucket = BucketFor(is_playing, has_video, codec, profile, coded_size,
                           is_fullscreen, average_fps);
@@ -426,21 +425,21 @@
 // Instantiate all valid combinations, plus some that aren't.
 INSTANTIATE_TEST_SUITE_P(
     All,
-    PowerStatusHelperImplBucketTest,
+    PowerStatusHelperBucketTest,
     Combine(Bool(),
             Bool(),
-            Values(PowerStatusHelperImpl::Bits::kCodecBitsH264,
-                   PowerStatusHelperImpl::Bits::kCodecBitsVP9Profile0,
-                   PowerStatusHelperImpl::Bits::kCodecBitsVP9Profile2,
-                   PowerStatusHelperImpl::Bits::kNotAValidBitForTesting),
-            Values(PowerStatusHelperImpl::Bits::kResolution360p,
-                   PowerStatusHelperImpl::Bits::kResolution720p,
-                   PowerStatusHelperImpl::Bits::kResolution1080p,
-                   PowerStatusHelperImpl::Bits::kNotAValidBitForTesting),
-            Values(PowerStatusHelperImpl::Bits::kFrameRate30,
-                   PowerStatusHelperImpl::Bits::kFrameRate60,
-                   PowerStatusHelperImpl::Bits::kNotAValidBitForTesting),
-            Values(PowerStatusHelperImpl::Bits::kFullScreenNo,
-                   PowerStatusHelperImpl::Bits::kFullScreenYes)));
+            Values(PowerStatusHelper::Bits::kCodecBitsH264,
+                   PowerStatusHelper::Bits::kCodecBitsVP9Profile0,
+                   PowerStatusHelper::Bits::kCodecBitsVP9Profile2,
+                   PowerStatusHelper::Bits::kNotAValidBitForTesting),
+            Values(PowerStatusHelper::Bits::kResolution360p,
+                   PowerStatusHelper::Bits::kResolution720p,
+                   PowerStatusHelper::Bits::kResolution1080p,
+                   PowerStatusHelper::Bits::kNotAValidBitForTesting),
+            Values(PowerStatusHelper::Bits::kFrameRate30,
+                   PowerStatusHelper::Bits::kFrameRate60,
+                   PowerStatusHelper::Bits::kNotAValidBitForTesting),
+            Values(PowerStatusHelper::Bits::kFullScreenNo,
+                   PowerStatusHelper::Bits::kFullScreenYes)));
 
-}  // namespace content
+}  // namespace media
diff --git a/media/gpu/android/direct_shared_image_video_provider.cc b/media/gpu/android/direct_shared_image_video_provider.cc
index 11efbbe4..8fcc9ca 100644
--- a/media/gpu/android/direct_shared_image_video_provider.cc
+++ b/media/gpu/android/direct_shared_image_video_provider.cc
@@ -71,10 +71,8 @@
       .WithArgs(std::move(gpu_init_cb));
 }
 
-void DirectSharedImageVideoProvider::RequestImage(
-    ImageReadyCB cb,
-    const ImageSpec& spec,
-    scoped_refptr<gpu::TextureOwner> texture_owner) {
+void DirectSharedImageVideoProvider::RequestImage(ImageReadyCB cb,
+                                                  const ImageSpec& spec) {
   // It's unclear that we should handle the image group, but since CodecImages
   // have to be registered on it, we do.  If the CodecImage is ever re-used,
   // then part of that re-use would be to call the (then mis-named)
@@ -87,8 +85,7 @@
   // Note: `cb` is only run on successful creation, so this does not use
   // `AsyncCall()` + `Then()` to chain the callbacks.
   gpu_factory_.AsyncCall(&GpuSharedImageVideoFactory::CreateImage)
-      .WithArgs(BindToCurrentLoop(std::move(cb)), spec,
-                std::move(texture_owner));
+      .WithArgs(BindToCurrentLoop(std::move(cb)), spec);
 }
 
 GpuSharedImageVideoFactory::GpuSharedImageVideoFactory(
@@ -113,8 +110,6 @@
     return;
   }
 
-  decoder_helper_ = GLES2DecoderHelper::Create(stub_->decoder_context());
-
   gpu::ContextResult result;
   auto shared_context = GetSharedContext(stub_, &result);
   if (!shared_context) {
@@ -145,8 +140,7 @@
 
 void GpuSharedImageVideoFactory::CreateImage(
     FactoryImageReadyCB image_ready_cb,
-    const SharedImageVideoProvider::ImageSpec& spec,
-    scoped_refptr<gpu::TextureOwner> texture_owner) {
+    const SharedImageVideoProvider::ImageSpec& spec) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   // Generate a shared image mailbox.
@@ -155,8 +149,7 @@
 
   TRACE_EVENT0("media", "GpuSharedImageVideoFactory::CreateVideoFrame");
 
-  if (!CreateImageInternal(spec, std::move(texture_owner), mailbox,
-                           codec_image)) {
+  if (!CreateImageInternal(spec, mailbox, codec_image)) {
     return;
   }
 
@@ -192,7 +185,6 @@
 
 bool GpuSharedImageVideoFactory::CreateImageInternal(
     const SharedImageVideoProvider::ImageSpec& spec,
-    scoped_refptr<gpu::TextureOwner> texture_owner,
     gpu::Mailbox mailbox,
     scoped_refptr<CodecImage> image) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -205,28 +197,6 @@
 
   const auto& coded_size = spec.coded_size;
 
-  // Create a Texture and a CodecImage to back it.
-  // TODO(liberato): Once legacy mailbox support is removed, we don't need to
-  // create this texture.  So, we won't need |texture_owner| either.
-  std::unique_ptr<AbstractTexture> texture = decoder_helper_->CreateTexture(
-      GL_TEXTURE_EXTERNAL_OES, GL_RGBA, coded_size.width(), coded_size.height(),
-      GL_RGBA, GL_UNSIGNED_BYTE);
-
-  // Attach the image to the texture.
-  // Either way, we expect this to be UNBOUND (i.e., decoder-managed).  For
-  // overlays, BindTexImage will return true, causing it to transition to the
-  // BOUND state, and thus receive ScheduleOverlayPlane calls.  For TextureOwner
-  // backed images, BindTexImage will return false, and CopyTexImage will be
-  // tried next.
-  // TODO(liberato): consider not binding this as a StreamTextureImage if we're
-  // using an overlay.  There's no advantage.  We'd likely want to create (and
-  // initialize to a 1x1 texture) a 2D texture above in that case, in case
-  // somebody tries to sample from it.  Be sure that promotion hints still
-  // work properly, though -- they might require a stream texture image.
-  GLuint texture_owner_service_id =
-      texture_owner ? texture_owner->GetTextureId() : 0;
-  texture->BindStreamTextureImage(image.get(), texture_owner_service_id);
-
   gpu::ContextResult result;
   auto shared_context = GetSharedContext(stub_, &result);
   if (!shared_context) {
@@ -244,8 +214,7 @@
   auto shared_image = std::make_unique<gpu::SharedImageVideo>(
       mailbox, coded_size, gfx::ColorSpace::CreateSRGB(),
       kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, std::move(image),
-      std::move(texture), std::move(shared_context),
-      false /* is_thread_safe */);
+      std::move(shared_context), false /* is_thread_safe */);
 
   // Register it with shared image mailbox as well as legacy mailbox. This
   // keeps |shared_image| around until its destruction cb is called.
@@ -253,7 +222,7 @@
   // mailbox.
   DCHECK(stub_->channel()->gpu_channel_manager()->shared_image_manager());
   stub_->channel()->shared_image_stub()->factory()->RegisterBacking(
-      std::move(shared_image), /* legacy_mailbox */ true);
+      std::move(shared_image), /*allow_legacy_mailbox=*/false);
 
   return true;
 }
@@ -262,7 +231,6 @@
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(stub_);
   stub_ = nullptr;
-  decoder_helper_ = nullptr;
 }
 
 }  // namespace media
diff --git a/media/gpu/android/direct_shared_image_video_provider.h b/media/gpu/android/direct_shared_image_video_provider.h
index e140b6cad..71e59616c 100644
--- a/media/gpu/android/direct_shared_image_video_provider.h
+++ b/media/gpu/android/direct_shared_image_video_provider.h
@@ -41,9 +41,7 @@
 
   // SharedImageVideoProvider
   void Initialize(GpuInitCB get_stub_cb) override;
-  void RequestImage(ImageReadyCB cb,
-                    const ImageSpec& spec,
-                    scoped_refptr<gpu::TextureOwner> texture_owner) override;
+  void RequestImage(ImageReadyCB cb, const ImageSpec& spec) override;
 
  private:
   base::SequenceBound<GpuSharedImageVideoFactory> gpu_factory_;
@@ -79,23 +77,17 @@
   // create the per-frame texture.  All of that is only needed for legacy
   // mailbox support, where we have to have one texture per CodecImage.
   void CreateImage(FactoryImageReadyCB cb,
-                   const SharedImageVideoProvider::ImageSpec& spec,
-                   scoped_refptr<gpu::TextureOwner> texture_owner);
+                   const SharedImageVideoProvider::ImageSpec& spec);
 
  private:
   // Creates a SharedImage for |mailbox|, and returns success or failure.
   bool CreateImageInternal(const SharedImageVideoProvider::ImageSpec& spec,
-                           scoped_refptr<gpu::TextureOwner> texture_owner,
                            gpu::Mailbox mailbox,
                            scoped_refptr<CodecImage> image);
 
   void OnWillDestroyStub(bool have_context) override;
 
   gpu::CommandBufferStub* stub_ = nullptr;
-
-  // A helper for creating textures. Only valid while |stub_| is valid.
-  std::unique_ptr<GLES2DecoderHelper> decoder_helper_;
-
   bool is_vulkan_ = false;
 
   THREAD_CHECKER(thread_checker_);
diff --git a/media/gpu/android/mock_shared_image_video_provider.cc b/media/gpu/android/mock_shared_image_video_provider.cc
index c131f4ac..ecde0e5 100644
--- a/media/gpu/android/mock_shared_image_video_provider.cc
+++ b/media/gpu/android/mock_shared_image_video_provider.cc
@@ -8,11 +8,8 @@
 
 MockSharedImageVideoProvider::RequestImageArgs::RequestImageArgs(
     ImageReadyCB cb,
-    ImageSpec spec,
-    scoped_refptr<gpu::TextureOwner> texture_owner)
-    : cb_(std::move(cb)),
-      spec_(std::move(spec)),
-      texture_owner_(std::move(texture_owner)) {}
+    ImageSpec spec)
+    : cb_(std::move(cb)), spec_(std::move(spec)) {}
 
 MockSharedImageVideoProvider::RequestImageArgs::~RequestImageArgs() = default;
 
diff --git a/media/gpu/android/mock_shared_image_video_provider.h b/media/gpu/android/mock_shared_image_video_provider.h
index cd554aa..4412dc9 100644
--- a/media/gpu/android/mock_shared_image_video_provider.h
+++ b/media/gpu/android/mock_shared_image_video_provider.h
@@ -25,10 +25,8 @@
 
   MOCK_METHOD1(Initialize_, void(GpuInitCB& gpu_init_cb));
 
-  void RequestImage(ImageReadyCB cb,
-                    const ImageSpec& spec,
-                    scoped_refptr<gpu::TextureOwner> texture_owner) override {
-    requests_.emplace_back(std::move(cb), spec, std::move(texture_owner));
+  void RequestImage(ImageReadyCB cb, const ImageSpec& spec) override {
+    requests_.emplace_back(std::move(cb), spec);
 
     MockRequestImage();
   }
@@ -59,13 +57,10 @@
 
   // Most recent arguments to RequestImage.
   struct RequestImageArgs {
-    RequestImageArgs(ImageReadyCB cb,
-                     ImageSpec spec,
-                     scoped_refptr<gpu::TextureOwner> texture_owner);
+    RequestImageArgs(ImageReadyCB cb, ImageSpec spec);
     ~RequestImageArgs();
     ImageReadyCB cb_;
     ImageSpec spec_;
-    scoped_refptr<gpu::TextureOwner> texture_owner_;
   };
 
   std::list<RequestImageArgs> requests_;
diff --git a/media/gpu/android/pooled_shared_image_video_provider.cc b/media/gpu/android/pooled_shared_image_video_provider.cc
index a4b10ff..b4e3d0a3 100644
--- a/media/gpu/android/pooled_shared_image_video_provider.cc
+++ b/media/gpu/android/pooled_shared_image_video_provider.cc
@@ -52,10 +52,8 @@
   provider_->Initialize(std::move(gpu_init_cb));
 }
 
-void PooledSharedImageVideoProvider::RequestImage(
-    ImageReadyCB cb,
-    const ImageSpec& spec,
-    scoped_refptr<gpu::TextureOwner> texture_owner) {
+void PooledSharedImageVideoProvider::RequestImage(ImageReadyCB cb,
+                                                  const ImageSpec& spec) {
   // See if the pool matches the requested spec.
   if (pool_spec_ != spec) {
     // Nope -- mark any outstanding images for destruction and start a new pool.
@@ -106,7 +104,7 @@
   auto ready_cb =
       base::BindOnce(&PooledSharedImageVideoProvider::OnImageCreated,
                      weak_factory_.GetWeakPtr(), spec);
-  provider_->RequestImage(std::move(ready_cb), spec, std::move(texture_owner));
+  provider_->RequestImage(std::move(ready_cb), spec);
 }
 
 void PooledSharedImageVideoProvider::OnImageCreated(ImageSpec spec,
diff --git a/media/gpu/android/pooled_shared_image_video_provider.h b/media/gpu/android/pooled_shared_image_video_provider.h
index a4d0239..8f13b656 100644
--- a/media/gpu/android/pooled_shared_image_video_provider.h
+++ b/media/gpu/android/pooled_shared_image_video_provider.h
@@ -46,9 +46,7 @@
 
   // SharedImageVideoProvider
   void Initialize(GpuInitCB gpu_init_cb) override;
-  void RequestImage(ImageReadyCB cb,
-                    const ImageSpec& spec,
-                    scoped_refptr<gpu::TextureOwner> texture_owner) override;
+  void RequestImage(ImageReadyCB cb, const ImageSpec& spec) override;
 
  private:
   friend class PooledSharedImageVideoProviderTest;
diff --git a/media/gpu/android/pooled_shared_image_video_provider_unittest.cc b/media/gpu/android/pooled_shared_image_video_provider_unittest.cc
index 174c8bb8..9a606c74 100644
--- a/media/gpu/android/pooled_shared_image_video_provider_unittest.cc
+++ b/media/gpu/android/pooled_shared_image_video_provider_unittest.cc
@@ -70,7 +70,7 @@
   // |mock_provider_raw_|.  Have |mock_provider_raw_| return an image, too.
   void RequestAndProvideImage(const SharedImageVideoProvider::ImageSpec& spec) {
     EXPECT_CALL(*mock_provider_raw_, MockRequestImage()).Times(1);
-    provider_->RequestImage(SaveImageRecordCB(), spec, texture_owner_);
+    provider_->RequestImage(SaveImageRecordCB(), spec);
     base::RunLoop().RunUntilIdle();
     Mock::VerifyAndClearExpectations(mock_provider_raw_);
     mock_provider_raw_->ProvideOneRequestedImage();
@@ -155,7 +155,7 @@
 
   // Shouldn't call MockRequestImage a third time.
   EXPECT_CALL(*mock_provider_raw_, MockRequestImage()).Times(0);
-  provider_->RequestImage(SaveImageRecordCB(), spec, texture_owner_);
+  provider_->RequestImage(SaveImageRecordCB(), spec);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(image_records_.size(), 2u);
 }
@@ -164,7 +164,7 @@
        DeletingProviderWithOutstandingImagesDoesntCrash) {
   // Destroying |provider_| with outstanding images shouldn't break anything.
   SharedImageVideoProvider::ImageSpec spec(gfx::Size(1, 1), 0u);
-  provider_->RequestImage(SaveImageRecordCB(), spec, texture_owner_);
+  provider_->RequestImage(SaveImageRecordCB(), spec);
   base::RunLoop().RunUntilIdle();
   provider_.reset();
   base::RunLoop().RunUntilIdle();
@@ -229,8 +229,8 @@
 
   // Request both images before providing either.
   EXPECT_CALL(*mock_provider_raw_, MockRequestImage()).Times(2);
-  provider_->RequestImage(SaveImageRecordCB(), spec_1, texture_owner_);
-  provider_->RequestImage(SaveImageRecordCB(), spec_2, texture_owner_);
+  provider_->RequestImage(SaveImageRecordCB(), spec_1);
+  provider_->RequestImage(SaveImageRecordCB(), spec_2);
   base::RunLoop().RunUntilIdle();
 
   // Provide the |spec_1| image.  Nothing should be released since it should
diff --git a/media/gpu/android/shared_image_video_provider.h b/media/gpu/android/shared_image_video_provider.h
index ffbac1331..87fa7ec 100644
--- a/media/gpu/android/shared_image_video_provider.h
+++ b/media/gpu/android/shared_image_video_provider.h
@@ -94,9 +94,7 @@
 
   // Call |cb| when we have a shared image that matches |spec|.  We may call
   // |cb| back before returning, or we might post it for later.
-  virtual void RequestImage(ImageReadyCB cb,
-                            const ImageSpec& spec,
-                            scoped_refptr<gpu::TextureOwner> texture_owner) = 0;
+  virtual void RequestImage(ImageReadyCB cb, const ImageSpec& spec) = 0;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(SharedImageVideoProvider);
diff --git a/media/gpu/android/video_frame_factory_impl.cc b/media/gpu/android/video_frame_factory_impl.cc
index 8be7a01f..6671c30 100644
--- a/media/gpu/android/video_frame_factory_impl.cc
+++ b/media/gpu/android/video_frame_factory_impl.cc
@@ -202,8 +202,7 @@
     ImageWithInfoReadyCB image_ready_cb) {
   auto info_cb =
       base::BindOnce(&VideoFrameFactoryImpl::CreateVideoFrame_OnFrameInfoReady,
-                     weak_factory_.GetWeakPtr(), std::move(image_ready_cb),
-                     codec_buffer_wait_coordinator_);
+                     weak_factory_.GetWeakPtr(), std::move(image_ready_cb));
 
   frame_info_helper_->GetFrameInfo(std::move(buffer_renderer),
                                    std::move(info_cb));
@@ -211,7 +210,6 @@
 
 void VideoFrameFactoryImpl::CreateVideoFrame_OnFrameInfoReady(
     ImageWithInfoReadyCB image_ready_cb,
-    scoped_refptr<CodecBufferWaitCoordinator> codec_buffer_wait_coordinator,
     std::unique_ptr<CodecOutputBufferRenderer> output_buffer_renderer,
     FrameInfoHelper::FrameInfo frame_info) {
   // If we don't have output buffer here we can't rely on reply from
@@ -237,11 +235,7 @@
 
   auto cb = base::BindOnce(std::move(image_ready_cb),
                            std::move(output_buffer_renderer), frame_info);
-
-  auto texture_owner = codec_buffer_wait_coordinator
-                           ? codec_buffer_wait_coordinator->texture_owner()
-                           : nullptr;
-  image_provider_->RequestImage(std::move(cb), image_spec_, texture_owner);
+  image_provider_->RequestImage(std::move(cb), image_spec_);
 }
 
 // static
diff --git a/media/gpu/android/video_frame_factory_impl.h b/media/gpu/android/video_frame_factory_impl.h
index dbee06d..0f0ab87 100644
--- a/media/gpu/android/video_frame_factory_impl.h
+++ b/media/gpu/android/video_frame_factory_impl.h
@@ -102,7 +102,6 @@
 
   void CreateVideoFrame_OnFrameInfoReady(
       ImageWithInfoReadyCB image_ready_cb,
-      scoped_refptr<CodecBufferWaitCoordinator> codec_buffer_wait_coordinator,
       std::unique_ptr<CodecOutputBufferRenderer> output_buffer_renderer,
       FrameInfoHelper::FrameInfo frame_info);
 
diff --git a/media/gpu/ipc/common/media_messages.h b/media/gpu/ipc/common/media_messages.h
index 3f47f08..8d0e1f8 100644
--- a/media/gpu/ipc/common/media_messages.h
+++ b/media/gpu/ipc/common/media_messages.h
@@ -11,6 +11,7 @@
 #include "gpu/config/gpu_info.h"
 #include "gpu/ipc/common/gpu_param_traits_macros.h"
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 #include "ipc/param_traits_macros.h"
 #include "media/base/overlay_info.h"
 #include "media/gpu/ipc/common/media_param_traits.h"
diff --git a/pdf/pdf_view_web_plugin.cc b/pdf/pdf_view_web_plugin.cc
index 0f85077f..68b9644 100644
--- a/pdf/pdf_view_web_plugin.cc
+++ b/pdf/pdf_view_web_plugin.cc
@@ -41,6 +41,7 @@
 #include "third_party/blink/public/mojom/input/focus_type.mojom-shared.h"
 #include "third_party/blink/public/platform/web_input_event_result.h"
 #include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/platform/web_text_input_type.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/platform/web_url_error.h"
 #include "third_party/blink/public/platform/web_url_request.h"
@@ -48,6 +49,7 @@
 #include "third_party/blink/public/web/web_associated_url_loader.h"
 #include "third_party/blink/public/web/web_associated_url_loader_options.h"
 #include "third_party/blink/public/web/web_document.h"
+#include "third_party/blink/public/web/web_frame_widget.h"
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/blink/public/web/web_plugin_container.h"
 #include "third_party/blink/public/web/web_plugin_params.h"
@@ -287,6 +289,10 @@
 
 void PdfViewWebPlugin::DidFailLoading(const blink::WebURLError& error) {}
 
+blink::WebTextInputType PdfViewWebPlugin::GetPluginTextInputType() {
+  return text_input_type_;
+}
+
 void PdfViewWebPlugin::UpdateCursor(ui::mojom::CursorType new_cursor_type) {
   set_cursor_type(new_cursor_type);
 }
@@ -394,17 +400,13 @@
 void PdfViewWebPlugin::SetReferrerForRequest(
     blink::WebURLRequest& request,
     const blink::WebURL& referrer_url) {
-  DCHECK(IsValid());
-  Container()->GetDocument().GetFrame()->SetReferrerForRequest(request,
-                                                               referrer_url);
+  GetValidContainerFrame()->SetReferrerForRequest(request, referrer_url);
 }
 
 std::unique_ptr<blink::WebAssociatedURLLoader>
 PdfViewWebPlugin::CreateAssociatedURLLoader(
     const blink::WebAssociatedURLLoaderOptions& options) {
-  DCHECK(IsValid());
-  return Container()->GetDocument().GetFrame()->CreateAssociatedURLLoader(
-      options);
+  return GetValidContainerFrame()->CreateAssociatedURLLoader(options);
 }
 
 void PdfViewWebPlugin::OnMessage(const base::Value& message) {
@@ -456,7 +458,10 @@
 }
 
 void PdfViewWebPlugin::SetFormFieldInFocus(bool in_focus) {
-  NOTIMPLEMENTED();
+  text_input_type_ = in_focus ? blink::WebTextInputType::kWebTextInputTypeText
+                              : blink::WebTextInputType::kWebTextInputTypeNone;
+  // Notify the frame widget.
+  GetValidContainerFrame()->FrameWidget()->UpdateTextInputState();
 }
 
 // TODO(https://crbug.com/1144444): Add a Pepper-free implementation to set
@@ -503,6 +508,11 @@
   base::RecordAction(base::UserMetricsAction(action.c_str()));
 }
 
+blink::WebLocalFrame* PdfViewWebPlugin::GetValidContainerFrame() const {
+  DCHECK(IsValid());
+  return Container()->GetDocument().GetFrame();
+}
+
 void PdfViewWebPlugin::OnViewportChanged(const gfx::Rect& view_rect,
                                          float new_device_scale) {
   UpdateGeometryOnViewChanged(view_rect, new_device_scale);
diff --git a/pdf/pdf_view_web_plugin.h b/pdf/pdf_view_web_plugin.h
index f84206a..385b2e3 100644
--- a/pdf/pdf_view_web_plugin.h
+++ b/pdf/pdf_view_web_plugin.h
@@ -14,11 +14,13 @@
 #include "pdf/post_message_sender.h"
 #include "pdf/ppapi_migration/graphics.h"
 #include "pdf/ppapi_migration/url_loader.h"
+#include "third_party/blink/public/platform/web_text_input_type.h"
 #include "third_party/blink/public/web/web_plugin.h"
 #include "third_party/blink/public/web/web_plugin_params.h"
 #include "v8/include/v8.h"
 
 namespace blink {
+class WebLocalFrame;
 class WebPluginContainer;
 }  // namespace blink
 
@@ -71,6 +73,7 @@
   void DidReceiveData(const char* data, size_t data_length) override;
   void DidFinishLoading() override;
   void DidFailLoading(const blink::WebURLError& error) override;
+  blink::WebTextInputType GetPluginTextInputType() override;
 
   // PdfViewPluginBase:
   void UpdateCursor(ui::mojom::CursorType new_cursor_type) override;
@@ -153,12 +156,19 @@
 
   bool InitializeCommon(std::unique_ptr<ContainerWrapper> container_wrapper);
 
+  // Returns the local frame to which the web plugin container belongs to. May
+  // only be called when the plugin has the container inside a valid frame.
+  blink::WebLocalFrame* GetValidContainerFrame() const;
+
   void OnViewportChanged(const gfx::Rect& view_rect, float new_device_scale);
 
   // Invalidates the entire web plugin container and schedules a paint of the
   // page in it.
   void InvalidatePluginContainer();
 
+  blink::WebTextInputType text_input_type_ =
+      blink::WebTextInputType::kWebTextInputTypeNone;
+
   blink::WebPluginParams initial_params_;
 
   std::unique_ptr<ContainerWrapper> container_wrapper_;
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index e244bca..7eebdaab 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -30,6 +30,7 @@
 #include "gpu/ipc/common/gpu_command_buffer_traits.h"
 #include "ipc/ipc_channel_handle.h"
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
 #include "ipc/ipc_message_utils.h"
 #include "ipc/ipc_platform_file.h"
 #include "ppapi/c/dev/pp_video_capture_dev.h"
diff --git a/remoting/host/chromoting_messages.h b/remoting/host/chromoting_messages.h
index 9375f3b..6fc9131a 100644
--- a/remoting/host/chromoting_messages.h
+++ b/remoting/host/chromoting_messages.h
@@ -11,6 +11,7 @@
 #include "base/memory/unsafe_shared_memory_region.h"
 #include "base/time/time.h"
 #include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_message_start.h"
 #include "ipc/ipc_platform_file.h"
 #include "remoting/host/chromoting_param_traits.h"
 #include "remoting/host/desktop_environment_options.h"
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index ba56c42c..ad9e5e9 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -4675,11 +4675,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.205"
+            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.206"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.205",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.206",
         "resultdb": {
           "enable": true
         },
@@ -4689,7 +4689,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.205"
+              "revision": "version:90.0.4430.206"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -4754,11 +4754,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 91.0.4472.33"
+            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 91.0.4472.34"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 91.0.4472.33",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 91.0.4472.34",
         "resultdb": {
           "enable": true
         },
@@ -4768,7 +4768,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.33"
+              "revision": "version:91.0.4472.34"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -4912,11 +4912,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.205"
+            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.206"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.205",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.206",
         "resultdb": {
           "enable": true
         },
@@ -4926,7 +4926,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.205"
+              "revision": "version:90.0.4430.206"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -4991,11 +4991,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 91.0.4472.33"
+            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 91.0.4472.34"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 91.0.4472.33",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 91.0.4472.34",
         "resultdb": {
           "enable": true
         },
@@ -5005,7 +5005,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.33"
+              "revision": "version:91.0.4472.34"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index ca843bb..1a79bbb4 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -53838,11 +53838,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 90.0.4430.205"
+            "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 90.0.4430.206"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 90.0.4430.205",
+        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 90.0.4430.206",
         "resultdb": {
           "enable": true
         },
@@ -53852,7 +53852,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.205"
+              "revision": "version:90.0.4430.206"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -53918,11 +53918,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 91.0.4472.33"
+            "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 91.0.4472.34"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 91.0.4472.33",
+        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 91.0.4472.34",
         "resultdb": {
           "enable": true
         },
@@ -53932,7 +53932,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.33"
+              "revision": "version:91.0.4472.34"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54078,11 +54078,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 90.0.4430.205"
+            "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 90.0.4430.206"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 90.0.4430.205",
+        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 90.0.4430.206",
         "resultdb": {
           "enable": true
         },
@@ -54092,7 +54092,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.205"
+              "revision": "version:90.0.4430.206"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54158,11 +54158,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 91.0.4472.33"
+            "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 91.0.4472.34"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 91.0.4472.33",
+        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 91.0.4472.34",
         "resultdb": {
           "enable": true
         },
@@ -54172,7 +54172,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.33"
+              "revision": "version:91.0.4472.34"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54383,11 +54383,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.205"
+            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.206"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.205",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.206",
         "resultdb": {
           "enable": true
         },
@@ -54397,7 +54397,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.205"
+              "revision": "version:90.0.4430.206"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54462,11 +54462,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 91.0.4472.33"
+            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 91.0.4472.34"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 91.0.4472.33",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 91.0.4472.34",
         "resultdb": {
           "enable": true
         },
@@ -54476,7 +54476,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.33"
+              "revision": "version:91.0.4472.34"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54620,11 +54620,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.205"
+            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.206"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.205",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.206",
         "resultdb": {
           "enable": true
         },
@@ -54634,7 +54634,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.205"
+              "revision": "version:90.0.4430.206"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54699,11 +54699,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 91.0.4472.33"
+            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 91.0.4472.34"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 91.0.4472.33",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 91.0.4472.34",
         "resultdb": {
           "enable": true
         },
@@ -54713,7 +54713,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.33"
+              "revision": "version:91.0.4472.34"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54924,11 +54924,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.205"
+            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.206"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.205",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 90.0.4430.206",
         "resultdb": {
           "enable": true
         },
@@ -54938,7 +54938,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.205"
+              "revision": "version:90.0.4430.206"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -55003,11 +55003,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 91.0.4472.33"
+            "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 91.0.4472.34"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 91.0.4472.33",
+        "name": "weblayer_instrumentation_test_versions_apk_Client Library Skew Tests For 91.0.4472.34",
         "resultdb": {
           "enable": true
         },
@@ -55017,7 +55017,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.33"
+              "revision": "version:91.0.4472.34"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -55161,11 +55161,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.205"
+            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.206"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.205",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 90.0.4430.206",
         "resultdb": {
           "enable": true
         },
@@ -55175,7 +55175,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.205"
+              "revision": "version:90.0.4430.206"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -55240,11 +55240,11 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 91.0.4472.33"
+            "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 91.0.4472.34"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
         },
-        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 91.0.4472.33",
+        "name": "weblayer_instrumentation_test_versions_apk_Implementation Library Skew Tests For 91.0.4472.34",
         "resultdb": {
           "enable": true
         },
@@ -55254,7 +55254,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.33"
+              "revision": "version:91.0.4472.34"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index 10dcd90..73b1c39 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -920,7 +920,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -940,7 +940,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -958,7 +958,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -975,7 +975,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -992,7 +992,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1009,7 +1009,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1026,7 +1026,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1044,7 +1044,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1061,7 +1061,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1078,7 +1078,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1098,7 +1098,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1115,7 +1115,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1132,7 +1132,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1149,7 +1149,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1166,7 +1166,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1184,7 +1184,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1201,7 +1201,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1218,7 +1218,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1252,7 +1252,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1269,7 +1269,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1286,7 +1286,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1303,7 +1303,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1323,7 +1323,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -1341,7 +1341,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1358,7 +1358,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1375,7 +1375,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1392,7 +1392,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1409,7 +1409,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1426,7 +1426,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1443,7 +1443,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1460,7 +1460,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1477,7 +1477,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1494,7 +1494,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1511,7 +1511,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1528,7 +1528,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1545,7 +1545,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1562,7 +1562,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1579,7 +1579,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1596,7 +1596,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1613,7 +1613,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1630,7 +1630,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1647,7 +1647,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1664,7 +1664,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1681,7 +1681,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1698,7 +1698,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1715,7 +1715,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1732,7 +1732,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1749,7 +1749,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1766,7 +1766,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1783,7 +1783,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1800,7 +1800,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1817,7 +1817,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1834,7 +1834,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1852,7 +1852,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1869,7 +1869,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -1886,7 +1886,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3162,7 +3162,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3183,7 +3183,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3204,7 +3204,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3225,7 +3225,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3246,7 +3246,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3267,7 +3267,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3288,7 +3288,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3309,7 +3309,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3331,7 +3331,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3352,7 +3352,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3373,7 +3373,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3394,7 +3394,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3415,7 +3415,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3436,7 +3436,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3457,7 +3457,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3478,7 +3478,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -3500,7 +3500,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3522,7 +3522,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3543,7 +3543,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3564,7 +3564,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3585,7 +3585,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3606,7 +3606,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3627,7 +3627,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3648,7 +3648,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3669,7 +3669,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3690,7 +3690,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3711,7 +3711,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3729,7 +3729,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3751,7 +3751,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3772,7 +3772,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3793,7 +3793,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3814,7 +3814,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3835,7 +3835,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3856,7 +3856,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3877,7 +3877,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3898,7 +3898,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3919,7 +3919,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3941,7 +3941,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -3963,7 +3963,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3984,7 +3984,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4006,7 +4006,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4027,7 +4027,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4048,7 +4048,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4069,7 +4069,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4090,7 +4090,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4112,7 +4112,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4134,7 +4134,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4155,7 +4155,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4177,7 +4177,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4198,7 +4198,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4219,7 +4219,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4240,7 +4240,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4258,7 +4258,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4279,7 +4279,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4305,7 +4305,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4334,7 +4334,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4365,7 +4365,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "idempotent": false,
@@ -4397,7 +4397,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "idempotent": false,
@@ -4429,7 +4429,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "idempotent": false,
@@ -4467,7 +4467,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "idempotent": false,
@@ -4499,7 +4499,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "idempotent": false,
@@ -4531,7 +4531,7 @@
           "dimension_sets": [
             {
               "kvm": "1",
-              "os": "Ubuntu-16.04"
+              "os": "Ubuntu-18.04"
             }
           ],
           "idempotent": false,
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 9f7bba2..f669c7d5 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -331,13 +331,13 @@
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
       '--impl-version=91',
     ],
-    'identifier': 'Implementation Library Skew Tests For 91.0.4472.33',
+    'identifier': 'Implementation Library Skew Tests For 91.0.4472.34',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M91',
-          'revision': 'version:91.0.4472.33',
+          'revision': 'version:91.0.4472.34',
         }
       ],
     },
@@ -355,13 +355,13 @@
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
       '--impl-version=90',
     ],
-    'identifier': 'Implementation Library Skew Tests For 90.0.4430.205',
+    'identifier': 'Implementation Library Skew Tests For 90.0.4430.206',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M90',
-          'revision': 'version:90.0.4430.205',
+          'revision': 'version:90.0.4430.206',
         }
       ],
     },
@@ -403,13 +403,13 @@
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
       '--impl-version=91',
     ],
-    'identifier': 'Implementation Library Skew Tests For 91.0.4472.33',
+    'identifier': 'Implementation Library Skew Tests For 91.0.4472.34',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M91',
-          'revision': 'version:91.0.4472.33',
+          'revision': 'version:91.0.4472.34',
         }
       ],
     },
@@ -427,13 +427,13 @@
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
       '--impl-version=90',
     ],
-    'identifier': 'Implementation Library Skew Tests For 90.0.4430.205',
+    'identifier': 'Implementation Library Skew Tests For 90.0.4430.206',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M90',
-          'revision': 'version:90.0.4430.205',
+          'revision': 'version:90.0.4430.206',
         }
       ],
     },
@@ -475,13 +475,13 @@
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
       '--client-version=91',
     ],
-    'identifier': 'Client Library Skew Tests For 91.0.4472.33',
+    'identifier': 'Client Library Skew Tests For 91.0.4472.34',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M91',
-          'revision': 'version:91.0.4472.33',
+          'revision': 'version:91.0.4472.34',
         }
       ],
     },
@@ -499,13 +499,13 @@
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
       '--client-version=90',
     ],
-    'identifier': 'Client Library Skew Tests For 90.0.4430.205',
+    'identifier': 'Client Library Skew Tests For 90.0.4430.206',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M90',
-          'revision': 'version:90.0.4430.205',
+          'revision': 'version:90.0.4430.206',
         }
       ],
     },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 8eff960..9e4a626 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -4871,7 +4871,7 @@
       },
       'Cast Linux': {
         'mixins': [
-          'linux-xenial',
+          'linux-bionic',
         ],
         'additional_compile_targets': [
           'cast_shell',
@@ -4911,7 +4911,7 @@
         'browser_config': 'web-engine-shell',
         'os_type': 'linux',
         'mixins': [
-          'linux-xenial',
+          'linux-bionic',
         ],
         'swarming': {
           'dimension_sets': [
@@ -5111,9 +5111,6 @@
         ],
       },
       'linux-ozone-rel': {
-        'mixins': [
-          'linux-xenial',
-        ],
         'additional_compile_targets': [
           'chrome',
         ],
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 0da0572..2f844d3 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -2052,11 +2052,9 @@
             ],
             "experiments": [
                 {
-                    "name": "DirectIntentEnabled_20210211",
+                    "name": "EnabledWithUpdatedMenuItemString_20210325",
                     "params": {
-                        "disableOnIncognito": "true",
-                        "minAgsaVersionForDirectIntent": "12.3.8",
-                        "useDirectIntent": "true"
+                        "useSearchImageWithGoogleLensItemName": "true"
                     },
                     "enable_features": [
                         "ContextMenuSearchWithGoogleLens"
@@ -3711,6 +3709,80 @@
             ]
         }
     ],
+    "IOSDefaultBrowserFullscreenPromoCTAExperiment": [
+        {
+            "platforms": [
+                "ios"
+            ],
+            "experiments": [
+                {
+                    "name": "OpenLinks",
+                    "params": {
+                        "show_open_links_title": "true"
+                    },
+                    "enable_features": [
+                        "DefaultBrowserFullscreenPromoCTAExperiment"
+                    ]
+                },
+                {
+                    "name": "Switch",
+                    "params": {
+                        "show_switch_title": "true"
+                    },
+                    "enable_features": [
+                        "DefaultBrowserFullscreenPromoCTAExperiment"
+                    ]
+                }
+            ]
+        }
+    ],
+    "IOSDefaultBrowserNonModalPromoExperiment": [
+        {
+            "platforms": [
+                "ios"
+            ],
+            "experiments": [
+                {
+                    "name": "ShortTimeout",
+                    "params": {
+                        "timeout": "15"
+                    },
+                    "enable_features": [
+                        "DefaultPromoNonModal"
+                    ]
+                },
+                {
+                    "name": "ShortTimeoutInstructions",
+                    "params": {
+                        "instructions_enabled": "true",
+                        "timeout": "15"
+                    },
+                    "enable_features": [
+                        "DefaultPromoNonModal"
+                    ]
+                },
+                {
+                    "name": "LongTimeout",
+                    "params": {
+                        "timeout": "45"
+                    },
+                    "enable_features": [
+                        "DefaultPromoNonModal"
+                    ]
+                },
+                {
+                    "name": "LongTimeoutInstructions",
+                    "params": {
+                        "instructions_enabled": "true",
+                        "timeout": "45"
+                    },
+                    "enable_features": [
+                        "DefaultPromoNonModal"
+                    ]
+                }
+            ]
+        }
+    ],
     "IOSDiscoverFeed": [
         {
             "platforms": [
@@ -4260,6 +4332,21 @@
             ]
         }
     ],
+    "LauncherScoreNormalizer": [
+        {
+            "platforms": [
+                "chromeos"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "EnableLauncherScoreNormalizer"
+                    ]
+                }
+            ]
+        }
+    ],
     "LauncherSettingsSearch": [
         {
             "platforms": [
@@ -8112,6 +8199,22 @@
             ]
         }
     ],
+    "WebRTC-Aec3TransparentModeHmm": [
+        {
+            "platforms": [
+                "windows",
+                "mac",
+                "chromeos",
+                "chromeos_lacros",
+                "linux"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled"
+                }
+            ]
+        }
+    ],
     "WebRTC-Audio-NetEqDelayManagerConfig": [
         {
             "platforms": [
diff --git a/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc b/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc
index 40591a51..f8ebe6e 100644
--- a/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc
+++ b/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc
@@ -30,6 +30,7 @@
 
 #include "third_party/blink/renderer/bindings/core/v8/scheduled_action.h"
 
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/binding_security.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc b/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
index 7d06c07..f0c2a0e 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
@@ -15,6 +15,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/core/testing/garbage_collected_script_wrappable.h"
 #include "third_party/blink/renderer/core/testing/gc_observation.h"
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc b/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc
index 926840df..16c94c5 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc
@@ -13,6 +13,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.cc b/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.cc
index f2f92ebb..b3d7d12a 100644
--- a/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.cc
+++ b/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.cc
@@ -10,6 +10,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_window_post_message_options.h"
 #include "third_party/blink/renderer/core/frame/frame.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_fuzzer.cc b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_fuzzer.cc
index fdfdea1..834d85e 100644
--- a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_fuzzer.cc
+++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_fuzzer.cc
@@ -15,6 +15,7 @@
 #include "third_party/blink/public/platform/web_blob_info.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/messaging/message_port.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_page_popup_controller_binding.cc b/third_party/blink/renderer/bindings/core/v8/v8_page_popup_controller_binding.cc
index 3d1cf43..7f466d1d 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_page_popup_controller_binding.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_page_popup_controller_binding.cc
@@ -10,6 +10,7 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/page/page_popup_controller.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
 
diff --git a/third_party/blink/renderer/core/animation/compositor_animations.cc b/third_party/blink/renderer/core/animation/compositor_animations.cc
index 771f55fb..13b72fe 100644
--- a/third_party/blink/renderer/core/animation/compositor_animations.cc
+++ b/third_party/blink/renderer/core/animation/compositor_animations.cc
@@ -33,6 +33,7 @@
 #include <algorithm>
 #include <cmath>
 #include <memory>
+
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/core/animation/animation_effect.h"
 #include "third_party/blink/renderer/core/animation/css/compositor_keyframe_color.h"
@@ -46,6 +47,7 @@
 #include "third_party/blink/renderer/core/css/properties/computed_style_utils.h"
 #include "third_party/blink/renderer/core/dom/dom_node_ids.h"
 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/layout/layout_box.h"
 #include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
diff --git a/third_party/blink/renderer/core/app_history/app_history.cc b/third_party/blink/renderer/core/app_history/app_history.cc
index b28712e..959d06f 100644
--- a/third_party/blink/renderer/core/app_history/app_history.cc
+++ b/third_party/blink/renderer/core/app_history/app_history.cc
@@ -10,6 +10,7 @@
 #include "third_party/blink/renderer/core/app_history/app_history_navigate_event_init.h"
 #include "third_party/blink/renderer/core/app_history/app_history_navigate_options.h"
 #include "third_party/blink/renderer/core/frame/history_util.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/html/forms/form_data.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
 #include "third_party/blink/renderer/core/loader/frame_load_request.h"
diff --git a/third_party/blink/renderer/core/app_history/app_history.h b/third_party/blink/renderer/core/app_history/app_history.h
index ce191169..0bb6748 100644
--- a/third_party/blink/renderer/core/app_history/app_history.h
+++ b/third_party/blink/renderer/core/app_history/app_history.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_APP_HISTORY_APP_HISTORY_H_
 
 #include "third_party/blink/public/web/web_frame_load_type.h"
+#include "third_party/blink/public/web/web_history_item.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/events/event_target.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
diff --git a/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc b/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc
index d42c6c8..20c28bee 100644
--- a/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc
+++ b/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc
@@ -13,6 +13,7 @@
 #include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
 #include "third_party/blink/renderer/core/css/style_sheet_contents.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/html/html_html_element.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
diff --git a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
index b7f334c..8606c57 100644
--- a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
+++ b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
@@ -43,6 +43,7 @@
 #include "third_party/blink/renderer/core/frame/ad_tracker.h"
 #include "third_party/blink/renderer/core/frame/deprecation.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/html/html_element.h"
 #include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
diff --git a/third_party/blink/renderer/core/editing/commands/undo_step.cc b/third_party/blink/renderer/core/editing/commands/undo_step.cc
index 23c2c9f..8f7fca43 100644
--- a/third_party/blink/renderer/core/editing/commands/undo_step.cc
+++ b/third_party/blink/renderer/core/editing/commands/undo_step.cc
@@ -13,6 +13,7 @@
 #include "third_party/blink/renderer/core/editing/selection_template.h"
 #include "third_party/blink/renderer/core/editing/set_selection_options.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller_test.cc b/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller_test.cc
index 724fe7c2..b10e044 100644
--- a/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller_test.cc
+++ b/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller_test.cc
@@ -14,6 +14,7 @@
 #include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
 #include "third_party/blink/renderer/core/editing/visible_selection.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 
 using ui::mojom::ImeTextSpanThickness;
 using ui::mojom::ImeTextSpanUnderlineStyle;
diff --git a/third_party/blink/renderer/core/events/pointer_event.cc b/third_party/blink/renderer/core/events/pointer_event.cc
index ce3d1b4..fce2c5d 100644
--- a/third_party/blink/renderer/core/events/pointer_event.cc
+++ b/third_party/blink/renderer/core/events/pointer_event.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/core/events/pointer_event.h"
 
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_pointer_event_init.h"
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
diff --git a/third_party/blink/renderer/core/events/pointer_event_factory.cc b/third_party/blink/renderer/core/events/pointer_event_factory.cc
index 5f4181a..5c2360582 100644
--- a/third_party/blink/renderer/core/events/pointer_event_factory.cc
+++ b/third_party/blink/renderer/core/events/pointer_event_factory.cc
@@ -7,6 +7,7 @@
 #include "third_party/blink/public/common/widget/screen_info.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_pointer_event_init.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/page/chrome_client.h"
 #include "third_party/blink/renderer/core/page/page.h"
diff --git a/third_party/blink/renderer/core/events/simulated_event_util.cc b/third_party/blink/renderer/core/events/simulated_event_util.cc
index 5042c52..32f26649 100644
--- a/third_party/blink/renderer/core/events/simulated_event_util.cc
+++ b/third_party/blink/renderer/core/events/simulated_event_util.cc
@@ -18,6 +18,7 @@
 #include "third_party/blink/renderer/core/events/pointer_event.h"
 #include "third_party/blink/renderer/core/events/pointer_event_factory.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/input/input_device_capabilities.h"
 #include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
diff --git a/third_party/blink/renderer/core/events/touch_event.cc b/third_party/blink/renderer/core/events/touch_event.cc
index 0b88a9c77..b4720eb 100644
--- a/third_party/blink/renderer/core/events/touch_event.cc
+++ b/third_party/blink/renderer/core/events/touch_event.cc
@@ -36,6 +36,7 @@
 #include "third_party/blink/renderer/core/frame/frame_console.h"
 #include "third_party/blink/renderer/core/frame/intervention.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/web_feature.h"
 #include "third_party/blink/renderer/core/html/html_element.h"
diff --git a/third_party/blink/renderer/core/events/touch_event_test.cc b/third_party/blink/renderer/core/events/touch_event_test.cc
index 6df740d1..cae4c90 100644
--- a/third_party/blink/renderer/core/events/touch_event_test.cc
+++ b/third_party/blink/renderer/core/events/touch_event_test.cc
@@ -10,6 +10,7 @@
 #include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
 #include "third_party/blink/renderer/core/frame/frame_console.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/loader/empty_clients.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
diff --git a/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer_test.cc b/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer_test.cc
index b5c211c..6643798 100644
--- a/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer_test.cc
+++ b/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer_test.cc
@@ -31,9 +31,11 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h"
 
 #include <memory>
+
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 
 using testing::AnyNumber;
diff --git a/third_party/blink/renderer/core/exported/web_scoped_window_focus_allowed_indicator_test.cc b/third_party/blink/renderer/core/exported/web_scoped_window_focus_allowed_indicator_test.cc
index 2e1c14b..6400865 100644
--- a/third_party/blink/renderer/core/exported/web_scoped_window_focus_allowed_indicator_test.cc
+++ b/third_party/blink/renderer/core/exported/web_scoped_window_focus_allowed_indicator_test.cc
@@ -33,6 +33,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/web/web_document.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 
diff --git a/third_party/blink/renderer/core/fetch/blob_bytes_consumer_test.cc b/third_party/blink/renderer/core/fetch/blob_bytes_consumer_test.cc
index dfeac60..8a8707a1 100644
--- a/third_party/blink/renderer/core/fetch/blob_bytes_consumer_test.cc
+++ b/third_party/blink/renderer/core/fetch/blob_bytes_consumer_test.cc
@@ -9,6 +9,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/fetch/bytes_consumer_test_util.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/loader/threadable_loader.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/platform/blob/blob_data.h"
diff --git a/third_party/blink/renderer/core/fetch/bytes_consumer_tee_test.cc b/third_party/blink/renderer/core/fetch/bytes_consumer_tee_test.cc
index daa1ef7..6f373c7 100644
--- a/third_party/blink/renderer/core/fetch/bytes_consumer_tee_test.cc
+++ b/third_party/blink/renderer/core/fetch/bytes_consumer_tee_test.cc
@@ -8,6 +8,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/fetch/bytes_consumer_test_util.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/platform/blob/blob_data.h"
 #include "third_party/blink/renderer/platform/loader/testing/bytes_consumer_test_reader.h"
diff --git a/third_party/blink/renderer/core/fetch/form_data_bytes_consumer_test.cc b/third_party/blink/renderer/core/fetch/form_data_bytes_consumer_test.cc
index 6e8fa4cb..7654befd 100644
--- a/third_party/blink/renderer/core/fetch/form_data_bytes_consumer_test.cc
+++ b/third_party/blink/renderer/core/fetch/form_data_bytes_consumer_test.cc
@@ -15,6 +15,7 @@
 #include "third_party/blink/public/platform/web_http_body.h"
 #include "third_party/blink/renderer/core/fetch/bytes_consumer_test_util.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/html/forms/form_data.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
diff --git a/third_party/blink/renderer/core/fetch/response_test.cc b/third_party/blink/renderer/core/fetch/response_test.cc
index 5dc11b1..46108a2 100644
--- a/third_party/blink/renderer/core/fetch/response_test.cc
+++ b/third_party/blink/renderer/core/fetch/response_test.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/fetch/response.h"
 
 #include <memory>
+
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
@@ -14,6 +15,7 @@
 #include "third_party/blink/renderer/core/fetch/fetch_response_data.h"
 #include "third_party/blink/renderer/core/frame/frame.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc
index 81ff77f2..a987ecf0 100644
--- a/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc
+++ b/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc
@@ -14,6 +14,7 @@
 #include "third_party/blink/renderer/core/dom/document_init.h"
 #include "third_party/blink/renderer/core/frame/csp/csp_directive_list.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/html/html_script_element.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/core/testing/null_execution_context.h"
diff --git a/third_party/blink/renderer/core/frame/device_single_window_event_controller.cc b/third_party/blink/renderer/core/frame/device_single_window_event_controller.cc
index 82d9d99..271af57ad 100644
--- a/third_party/blink/renderer/core/frame/device_single_window_event_controller.cc
+++ b/third_party/blink/renderer/core/frame/device_single_window_event_controller.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/frame/device_single_window_event_controller.h"
 
 #include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index 3df1ac7..e274150 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -770,6 +770,10 @@
 
 LocalDOMWindow::~LocalDOMWindow() = default;
 
+LocalFrame* LocalDOMWindow::GetFrame() const {
+  return To<LocalFrame>(DOMWindow::GetFrame());
+}
+
 void LocalDOMWindow::Dispose() {
   // Oilpan: should the LocalDOMWindow be GCed along with its LocalFrame without
   // the frame having first notified its observers of imminent destruction, the
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.h b/third_party/blink/renderer/core/frame/local_dom_window.h
index 3472599..0ff09aa1 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.h
+++ b/third_party/blink/renderer/core/frame/local_dom_window.h
@@ -27,6 +27,8 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LOCAL_DOM_WINDOW_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LOCAL_DOM_WINDOW_H_
 
+#include <memory>
+
 #include "services/metrics/public/cpp/ukm_recorder.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
 #include "third_party/blink/public/common/tokens/tokens.h"
@@ -34,19 +36,20 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/core/editing/ime/input_method_controller.h"
+#include "third_party/blink/renderer/core/editing/spellcheck/spell_checker.h"
+#include "third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h"
 #include "third_party/blink/renderer/core/events/page_transition_event.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/dom_window.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/geometry/dom_rect.h"
+#include "third_party/blink/renderer/core/loader/frame_loader.h"
 #include "third_party/blink/renderer/core/scroll/scrollable_area.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/supplementable.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 
-#include <memory>
-
 namespace blink {
 
 class ApplicationCache;
@@ -63,6 +66,7 @@
 class FrameConsole;
 class History;
 class IdleRequestOptions;
+class LocalFrame;
 class MediaQueryList;
 class MessageEvent;
 class Modulator;
@@ -118,7 +122,7 @@
     return token_;
   }
 
-  LocalFrame* GetFrame() const { return To<LocalFrame>(DOMWindow::GetFrame()); }
+  LocalFrame* GetFrame() const;
 
   ScriptController& GetScriptController() const { return *script_controller_; }
 
diff --git a/third_party/blink/renderer/core/frame/local_dom_window_test.cc b/third_party/blink/renderer/core/frame/local_dom_window_test.cc
index 2eefc23..f598a010 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window_test.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window_test.cc
@@ -37,6 +37,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h"
 #include "third_party/blink/renderer/core/execution_context/agent.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
diff --git a/third_party/blink/renderer/core/frame/location.cc b/third_party/blink/renderer/core/frame/location.cc
index b28346b7..6b4e072 100644
--- a/third_party/blink/renderer/core/frame/location.cc
+++ b/third_party/blink/renderer/core/frame/location.cc
@@ -34,6 +34,7 @@
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
 #include "third_party/blink/renderer/core/frame/dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/loader/frame_load_request.h"
 #include "third_party/blink/renderer/core/loader/frame_loader.h"
 #include "third_party/blink/renderer/core/url/dom_url_utils_read_only.h"
diff --git a/third_party/blink/renderer/core/frame/platform_event_controller.cc b/third_party/blink/renderer/core/frame/platform_event_controller.cc
index 5584748..ad85afe5 100644
--- a/third_party/blink/renderer/core/frame/platform_event_controller.cc
+++ b/third_party/blink/renderer/core/frame/platform_event_controller.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/frame/platform_event_controller.h"
 
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/page/page.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/frame/reporting_context_test.cc b/third_party/blink/renderer/core/frame/reporting_context_test.cc
index 2dbe6ce..3bbd683b 100644
--- a/third_party/blink/renderer/core/frame/reporting_context_test.cc
+++ b/third_party/blink/renderer/core/frame/reporting_context_test.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/core/frame/deprecation_report_body.h"
 #include "third_party/blink/renderer/core/frame/document_policy_violation_report_body.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/permissions_policy_violation_report_body.h"
 #include "third_party/blink/renderer/core/frame/report.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
diff --git a/third_party/blink/renderer/core/frame/scheduling.cc b/third_party/blink/renderer/core/frame/scheduling.cc
index f3e644c8..0f93656 100644
--- a/third_party/blink/renderer/core/frame/scheduling.cc
+++ b/third_party/blink/renderer/core/frame/scheduling.cc
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_is_input_pending_options.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/navigator.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h"
diff --git a/third_party/blink/renderer/core/frame/smart_clip.cc b/third_party/blink/renderer/core/frame/smart_clip.cc
index 760db53..d1b605df 100644
--- a/third_party/blink/renderer/core/frame/smart_clip.cc
+++ b/third_party/blink/renderer/core/frame/smart_clip.cc
@@ -35,6 +35,7 @@
 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
 #include "third_party/blink/renderer/core/dom/node_traversal.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
diff --git a/third_party/blink/renderer/core/frame/use_counter_impl_test.cc b/third_party/blink/renderer/core/frame/use_counter_impl_test.cc
index c6fd0d6..c084886 100644
--- a/third_party/blink/renderer/core/frame/use_counter_impl_test.cc
+++ b/third_party/blink/renderer/core/frame/use_counter_impl_test.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/core/dom/shadow_root.h"
 #include "third_party/blink/renderer/core/frame/deprecation.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/html/html_html_element.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
 #include "third_party/blink/renderer/core/page/page.h"
diff --git a/third_party/blink/renderer/core/frame/user_activation.cc b/third_party/blink/renderer/core/frame/user_activation.cc
index d7919c91..53bf936c 100644
--- a/third_party/blink/renderer/core/frame/user_activation.cc
+++ b/third_party/blink/renderer/core/frame/user_activation.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/frame/user_activation.h"
 
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator_test.cc b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator_test.cc
index de0c6b13..a342786 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator_test.cc
+++ b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator_test.cc
@@ -9,6 +9,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/html/canvas/image_data.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/platform/graphics/color_correction_test_utils.h"
diff --git a/third_party/blink/renderer/core/html/conversion_measurement_parsing.cc b/third_party/blink/renderer/core/html/conversion_measurement_parsing.cc
index d819613..2b79ded 100644
--- a/third_party/blink/renderer/core/html/conversion_measurement_parsing.cc
+++ b/third_party/blink/renderer/core/html/conversion_measurement_parsing.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/core/execution_context/security_context.h"
 #include "third_party/blink/renderer/core/frame/frame.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/web_feature.h"
 #include "third_party/blink/renderer/core/html/html_anchor_element.h"
 #include "third_party/blink/renderer/core/html_names.h"
diff --git a/third_party/blink/renderer/core/html/custom/custom_element_registry_test.cc b/third_party/blink/renderer/core/html/custom/custom_element_registry_test.cc
index 2696ad7..b927a75 100644
--- a/third_party/blink/renderer/core/html/custom/custom_element_registry_test.cc
+++ b/third_party/blink/renderer/core/html/custom/custom_element_registry_test.cc
@@ -16,6 +16,7 @@
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/dom/shadow_root.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/html/custom/ce_reactions_scope.h"
 #include "third_party/blink/renderer/core/html/custom/custom_element.h"
 #include "third_party/blink/renderer/core/html/custom/custom_element_definition.h"
diff --git a/third_party/blink/renderer/core/html/custom/custom_element_test.cc b/third_party/blink/renderer/core/html/custom/custom_element_test.cc
index f82edbd6..d6a936a9 100644
--- a/third_party/blink/renderer/core/html/custom/custom_element_test.cc
+++ b/third_party/blink/renderer/core/html/custom/custom_element_test.cc
@@ -12,6 +12,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_element_definition_options.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/html/custom/custom_element_definition.h"
 #include "third_party/blink/renderer/core/html/custom/custom_element_registry.h"
 #include "third_party/blink/renderer/core/html/custom/custom_element_test_helpers.h"
diff --git a/third_party/blink/renderer/core/html/forms/password_input_type_test.cc b/third_party/blink/renderer/core/html/forms/password_input_type_test.cc
index 1c2f338..025beb3 100644
--- a/third_party/blink/renderer/core/html/forms/password_input_type_test.cc
+++ b/third_party/blink/renderer/core/html/forms/password_input_type_test.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "third_party/blink/renderer/core/html/forms/password_input_type.h"
+
 #include <memory>
 #include <utility>
 
-#include "third_party/blink/renderer/core/html/forms/password_input_type.h"
-
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
 #include "mojo/public/cpp/system/message_pipe.h"
@@ -14,6 +14,7 @@
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/mojom/insecure_input/insecure_input_service.mojom-blink.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third_party/blink/renderer/core/html/html_anchor_element.cc
index d4fec79..2bd3386 100644
--- a/third_party/blink/renderer/core/html/html_anchor_element.cc
+++ b/third_party/blink/renderer/core/html/html_anchor_element.cc
@@ -42,6 +42,7 @@
 #include "third_party/blink/renderer/core/frame/ad_tracker.h"
 #include "third_party/blink/renderer/core/frame/deprecation.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/html/anchor_element_metrics.h"
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc
index c1db5b1..edc2f7b 100644
--- a/third_party/blink/renderer/core/html/html_iframe_element.cc
+++ b/third_party/blink/renderer/core/html/html_iframe_element.cc
@@ -36,6 +36,7 @@
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/fetch/trust_token_issuance_authorization.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/html/html_document.h"
 #include "third_party/blink/renderer/core/html/trust_token_attribute_parsing.h"
 #include "third_party/blink/renderer/core/html_names.h"
diff --git a/third_party/blink/renderer/core/html/media/html_media_element_test.cc b/third_party/blink/renderer/core/html/media/html_media_element_test.cc
index f41966c36..1b034ab 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element_test.cc
+++ b/third_party/blink/renderer/core/html/media/html_media_element_test.cc
@@ -14,6 +14,7 @@
 #include "third_party/blink/public/platform/web_media_player.h"
 #include "third_party/blink/public/platform/web_media_player_source.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/html/media/html_audio_element.h"
 #include "third_party/blink/renderer/core/html/media/html_video_element.h"
diff --git a/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc b/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc
index fd500be..3a97d26 100644
--- a/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc
+++ b/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc
@@ -18,6 +18,7 @@
 #include "third_party/blink/renderer/core/css_value_keywords.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/picture_in_picture_controller.h"
 #include "third_party/blink/renderer/core/html/media/html_media_test_helper.h"
 #include "third_party/blink/renderer/core/html/media/html_video_element.h"
diff --git a/third_party/blink/renderer/core/html/portal/portal_host.cc b/third_party/blink/renderer/core/html/portal/portal_host.cc
index 69e423f..bcd2a8cd 100644
--- a/third_party/blink/renderer/core/html/portal/portal_host.cc
+++ b/third_party/blink/renderer/core/html/portal/portal_host.cc
@@ -5,12 +5,14 @@
 #include "third_party/blink/renderer/core/html/portal/portal_host.h"
 
 #include <utility>
+
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
 #include "third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_window_post_message_options.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
 #include "third_party/blink/renderer/core/html/portal/dom_window_portal_host.h"
 #include "third_party/blink/renderer/core/html/portal/portal_post_message_helper.h"
diff --git a/third_party/blink/renderer/core/input/keyboard_event_manager.cc b/third_party/blink/renderer/core/input/keyboard_event_manager.cc
index d52692e..022d224 100644
--- a/third_party/blink/renderer/core/input/keyboard_event_manager.cc
+++ b/third_party/blink/renderer/core/input/keyboard_event_manager.cc
@@ -17,6 +17,7 @@
 #include "third_party/blink/renderer/core/editing/editor.h"
 #include "third_party/blink/renderer/core/events/keyboard_event.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/html/forms/html_input_element.h"
diff --git a/third_party/blink/renderer/core/input/touch_event_manager.cc b/third_party/blink/renderer/core/input/touch_event_manager.cc
index 423a261..1f3a46d 100644
--- a/third_party/blink/renderer/core/input/touch_event_manager.cc
+++ b/third_party/blink/renderer/core/input/touch_event_manager.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/input/touch_event_manager.h"
 
 #include <memory>
+
 #include "third_party/blink/public/common/input/web_coalesced_input_event.h"
 #include "third_party/blink/public/common/input/web_touch_event.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -13,6 +14,7 @@
 #include "third_party/blink/renderer/core/frame/deprecation.h"
 #include "third_party/blink/renderer/core/frame/event_handler_registry.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
 #include "third_party/blink/renderer/core/input/event_handling_util.h"
diff --git a/third_party/blink/renderer/core/inspector/inspector_media_context_impl_unittest.cc b/third_party/blink/renderer/core/inspector/inspector_media_context_impl_unittest.cc
index e23ca6b0..e52f673 100644
--- a/third_party/blink/renderer/core/inspector/inspector_media_context_impl_unittest.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_media_context_impl_unittest.cc
@@ -3,8 +3,10 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/renderer/core/inspector/inspector_media_context_impl.h"
+
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/core/testing/null_execution_context.h"
 
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h
index 21a2c2e..66031f6 100644
--- a/third_party/blink/renderer/core/layout/layout_box.h
+++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -28,7 +28,6 @@
 #include "base/dcheck_is_on.h"
 #include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink-forward.h"
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
 #include "third_party/blink/renderer/core/layout/min_max_sizes.h"
 #include "third_party/blink/renderer/core/layout/overflow_model.h"
diff --git a/third_party/blink/renderer/core/layout/layout_inline.cc b/third_party/blink/renderer/core/layout/layout_inline.cc
index 11fe4e1..332921b 100644
--- a/third_party/blink/renderer/core/layout/layout_inline.cc
+++ b/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -1053,7 +1053,8 @@
   return PhysicalOffset();
 }
 
-PhysicalRect LayoutInline::AbsoluteBoundingBoxRectHandlingEmptyInline() const {
+PhysicalRect LayoutInline::AbsoluteBoundingBoxRectHandlingEmptyInline(
+    MapCoordinatesFlags flags) const {
   NOT_DESTROYED();
   Vector<PhysicalRect> rects = OutlineRects(
       PhysicalOffset(), NGOutlineType::kIncludeBlockVisualOverflow);
diff --git a/third_party/blink/renderer/core/layout/layout_inline.h b/third_party/blink/renderer/core/layout/layout_inline.h
index 4928d9c..e16ebf9 100644
--- a/third_party/blink/renderer/core/layout/layout_inline.h
+++ b/third_party/blink/renderer/core/layout/layout_inline.h
@@ -262,7 +262,8 @@
                           TransformState&,
                           MapCoordinatesFlags mode) const override;
 
-  PhysicalRect AbsoluteBoundingBoxRectHandlingEmptyInline() const final;
+  PhysicalRect AbsoluteBoundingBoxRectHandlingEmptyInline(
+      MapCoordinatesFlags = 0) const final;
 
   PhysicalRect VisualRectInDocument(
       VisualRectFlags = kDefaultVisualRectFlags) const override;
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index 175a8c5..1146335d 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -1575,14 +1575,24 @@
   return result;
 }
 
-PhysicalRect LayoutObject::AbsoluteBoundingBoxRectHandlingEmptyInline() const {
+PhysicalRect LayoutObject::AbsoluteBoundingBoxRectHandlingEmptyInline(
+    MapCoordinatesFlags flags) const {
   NOT_DESTROYED();
-  return PhysicalRect::EnclosingRect(AbsoluteBoundingBoxFloatRect());
+  return PhysicalRect::EnclosingRect(AbsoluteBoundingBoxFloatRect(flags));
 }
 
 PhysicalRect LayoutObject::AbsoluteBoundingBoxRectForScrollIntoView() const {
   NOT_DESTROYED();
-  PhysicalRect rect = AbsoluteBoundingBoxRectHandlingEmptyInline();
+  // Ignore sticky position offsets for the purposes of scrolling elements into
+  // view. See https://www.w3.org/TR/css-position-3/#stickypos-scroll for
+  // details
+
+  const MapCoordinatesFlags flag =
+      (RuntimeEnabledFeatures::CSSPositionStickyStaticScrollPositionEnabled())
+          ? kIgnoreStickyOffset
+          : 0;
+
+  PhysicalRect rect = AbsoluteBoundingBoxRectHandlingEmptyInline(flag);
   const auto& style = StyleRef();
   rect.ExpandEdges(LayoutUnit(style.ScrollMarginTop()),
                    LayoutUnit(style.ScrollMarginRight()),
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index 21d950d..e4bafe6 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -2449,7 +2449,8 @@
   // box of named anchors.
   // TODO(crbug.com/953479): After the bug is fixed, investigate whether we
   // can combine this with AbsoluteBoundingBoxRect().
-  virtual PhysicalRect AbsoluteBoundingBoxRectHandlingEmptyInline() const;
+  virtual PhysicalRect AbsoluteBoundingBoxRectHandlingEmptyInline(
+      MapCoordinatesFlags flags = 0) const;
   // This returns an IntRect expanded from
   // AbsoluteBoundingBoxRectHandlingEmptyInline by ScrollMargin.
   PhysicalRect AbsoluteBoundingBoxRectForScrollIntoView() const;
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
index 84d6baa..bd62956 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
@@ -51,6 +51,7 @@
 #include "third_party/blink/renderer/core/frame/frame_owner.h"
 #include "third_party/blink/renderer/core/frame/frame_types.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/navigator.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
diff --git a/third_party/blink/renderer/core/loader/link_loader_test.cc b/third_party/blink/renderer/core/loader/link_loader_test.cc
index 2a326e3a..0797429 100644
--- a/third_party/blink/renderer/core/loader/link_loader_test.cc
+++ b/third_party/blink/renderer/core/loader/link_loader_test.cc
@@ -18,6 +18,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/html/link_rel_attribute.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
diff --git a/third_party/blink/renderer/core/loader/threadable_loader_test.cc b/third_party/blink/renderer/core/loader/threadable_loader_test.cc
index a7955e2..101b5b5 100644
--- a/third_party/blink/renderer/core/loader/threadable_loader_test.cc
+++ b/third_party/blink/renderer/core/loader/threadable_loader_test.cc
@@ -18,6 +18,7 @@
 #include "third_party/blink/public/platform/web_url_response.h"
 #include "third_party/blink/public/platform/web_worker_fetch_context.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/loader/threadable_loader.h"
 #include "third_party/blink/renderer/core/loader/threadable_loader_client.h"
 #include "third_party/blink/renderer/core/loader/worker_fetch_context.h"
diff --git a/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc b/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc
index 7db652c..cb2e5b4 100644
--- a/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc
+++ b/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
 
 #include <memory>
+
 #include "base/test/scoped_feature_list.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
@@ -14,6 +15,7 @@
 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom-blink.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/html/html_head_element.h"
 #include "third_party/blink/renderer/core/html/html_meta_element.h"
diff --git a/third_party/blink/renderer/core/page/pointer_lock_controller.cc b/third_party/blink/renderer/core/page/pointer_lock_controller.cc
index 83cf68c..b6a5978 100644
--- a/third_party/blink/renderer/core/page/pointer_lock_controller.cc
+++ b/third_party/blink/renderer/core/page/pointer_lock_controller.cc
@@ -35,6 +35,7 @@
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/input/event_handler.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/core/page/chrome_client.h"
diff --git a/third_party/blink/renderer/core/paint/image_element_timing.cc b/third_party/blink/renderer/core/paint/image_element_timing.cc
index 0d98673..51157ba 100644
--- a/third_party/blink/renderer/core/paint/image_element_timing.cc
+++ b/third_party/blink/renderer/core/paint/image_element_timing.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/core/paint/image_element_timing.h"
 
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
 #include "third_party/blink/renderer/core/page/chrome_client.h"
diff --git a/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.cc b/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.cc
index 441d5c6..60ce89a3 100644
--- a/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.cc
+++ b/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.cc
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.h"
+
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
 #include "third_party/blink/renderer/core/paint/image_element_timing.h"
 
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
index dbe0fd8de..df7d5c5b 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -2341,8 +2341,16 @@
 PhysicalRect PaintLayerScrollableArea::ScrollIntoView(
     const PhysicalRect& absolute_rect,
     const mojom::blink::ScrollIntoViewParamsPtr& params) {
+  // Ignore sticky position offsets for the purposes of scrolling elements into
+  // view. See https://www.w3.org/TR/css-position-3/#stickypos-scroll for
+  // details
+  const MapCoordinatesFlags flag =
+      (RuntimeEnabledFeatures::CSSPositionStickyStaticScrollPositionEnabled())
+          ? kIgnoreStickyOffset
+          : 0;
+
   PhysicalRect local_expose_rect =
-      GetLayoutBox()->AbsoluteToLocalRect(absolute_rect);
+      GetLayoutBox()->AbsoluteToLocalRect(absolute_rect, flag);
   PhysicalOffset border_origin_to_scroll_origin(-GetLayoutBox()->BorderLeft(),
                                                 -GetLayoutBox()->BorderTop());
   // There might be scroll bar between border_origin and scroll_origin.
@@ -2404,9 +2412,10 @@
 
   if (intersect.IsEmpty() && !scroll_snapport_rect.IsEmpty() &&
       !local_expose_rect.IsEmpty()) {
-    return GetLayoutBox()->LocalToAbsoluteRect(local_expose_rect);
+    return GetLayoutBox()->LocalToAbsoluteRect(local_expose_rect, flag);
   }
-  intersect = GetLayoutBox()->LocalToAbsoluteRect(intersect);
+  intersect = GetLayoutBox()->LocalToAbsoluteRect(intersect, flag);
+
   return intersect;
 }
 
diff --git a/third_party/blink/renderer/core/permissions_policy/permissions_policy_test.cc b/third_party/blink/renderer/core/permissions_policy/permissions_policy_test.cc
index ae4ba8b0..5f66b9a5 100644
--- a/third_party/blink/renderer/core/permissions_policy/permissions_policy_test.cc
+++ b/third_party/blink/renderer/core/permissions_policy/permissions_policy_test.cc
@@ -10,11 +10,11 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom-blink.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/loader/empty_clients.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/platform/testing/histogram_tester.h"
-
 #include "url/gurl.h"
 #include "url/origin.h"
 
diff --git a/third_party/blink/renderer/core/permissions_policy/policy_test.cc b/third_party/blink/renderer/core/permissions_policy/policy_test.cc
index 295d2ed..5d45888 100644
--- a/third_party/blink/renderer/core/permissions_policy/policy_test.cc
+++ b/third_party/blink/renderer/core/permissions_policy/policy_test.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/core/permissions_policy/dom_feature_policy.h"
-#include "third_party/blink/renderer/core/permissions_policy/iframe_policy.h"
-
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/permissions_policy/dom_feature_policy.h"
+#include "third_party/blink/renderer/core/permissions_policy/iframe_policy.h"
 #include "third_party/blink/renderer/core/permissions_policy/permissions_policy_parser.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
diff --git a/third_party/blink/renderer/core/script/script_runner.cc b/third_party/blink/renderer/core/script/script_runner.cc
index c447240..2bcc20d 100644
--- a/third_party/blink/renderer/core/script/script_runner.cc
+++ b/third_party/blink/renderer/core/script/script_runner.cc
@@ -26,12 +26,14 @@
 #include "third_party/blink/renderer/core/script/script_runner.h"
 
 #include <algorithm>
+
 #include "base/feature_list.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
 #include "third_party/blink/renderer/core/script/script_loader.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
diff --git a/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc b/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
index 731b143..0f6797a 100644
--- a/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
+++ b/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.h"
 
 #include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
 #include "third_party/blink/public/platform/web_vector.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_css_style_sheet_init.h"
diff --git a/third_party/blink/renderer/core/svg/animation/smil_time_container_test.cc b/third_party/blink/renderer/core/svg/animation/smil_time_container_test.cc
index 5d3ec15..7c779d0 100644
--- a/third_party/blink/renderer/core/svg/animation/smil_time_container_test.cc
+++ b/third_party/blink/renderer/core/svg/animation/smil_time_container_test.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/core/dom/element_traversal.h"
 #include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/svg/svg_animated_length.h"
 #include "third_party/blink/renderer/core/svg/svg_document_extensions.h"
diff --git a/third_party/blink/renderer/core/timing/performance_timing.cc b/third_party/blink/renderer/core/timing/performance_timing.cc
index bbd3e120..02277d9 100644
--- a/third_party/blink/renderer/core/timing/performance_timing.cc
+++ b/third_party/blink/renderer/core/timing/performance_timing.cc
@@ -35,6 +35,7 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/document_parser_timing.h"
 #include "third_party/blink/renderer/core/dom/document_timing.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
 #include "third_party/blink/renderer/core/loader/document_load_timing.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
diff --git a/third_party/blink/renderer/core/timing/window_performance_test.cc b/third_party/blink/renderer/core/timing/window_performance_test.cc
index 41d449e..62ca695d 100644
--- a/third_party/blink/renderer/core/timing/window_performance_test.cc
+++ b/third_party/blink/renderer/core/timing/window_performance_test.cc
@@ -12,6 +12,7 @@
 #include "third_party/blink/renderer/core/dom/document_init.h"
 #include "third_party/blink/renderer/core/execution_context/security_context_init.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/performance_monitor.h"
 #include "third_party/blink/renderer/core/loader/document_load_timing.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc b/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc
index bbda1b7..7c98944 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/core/trustedtypes/trusted_html.h"
 #include "third_party/blink/renderer/core/trustedtypes/trusted_script.h"
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_test.cc b/third_party/blink/renderer/core/workers/dedicated_worker_test.cc
index a86d50d..5d50edb 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker_test.cc
+++ b/third_party/blink/renderer/core/workers/dedicated_worker_test.cc
@@ -6,6 +6,7 @@
 
 #include <bitset>
 #include <memory>
+
 #include "base/single_thread_task_runner.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -17,6 +18,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h"
 #include "third_party/blink/renderer/core/events/message_event.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/inspector/console_message_storage.h"
 #include "third_party/blink/renderer/core/inspector/thread_debugger.h"
 #include "third_party/blink/renderer/core/script/script.h"
diff --git a/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc b/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc
index d9bdbdb..21d4b4d3 100644
--- a/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc
+++ b/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc
@@ -3,11 +3,13 @@
 // found in the LICENSE file.
 
 #include <bitset>
+
 #include "base/single_thread_task_runner.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
 #include "third_party/blink/renderer/core/script/script.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
diff --git a/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc b/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc
index 089beaa..8814fb4c 100644
--- a/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc
+++ b/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc
@@ -15,6 +15,7 @@
 #include "third_party/blink/renderer/core/execution_context/security_context.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
 #include "third_party/blink/renderer/core/inspector/thread_debugger.h"
 #include "third_party/blink/renderer/core/loader/worker_fetch_context.h"
diff --git a/third_party/blink/renderer/core/workers/threaded_worklet_test.cc b/third_party/blink/renderer/core/workers/threaded_worklet_test.cc
index 17ef095b..f6c69e74 100644
--- a/third_party/blink/renderer/core/workers/threaded_worklet_test.cc
+++ b/third_party/blink/renderer/core/workers/threaded_worklet_test.cc
@@ -3,11 +3,13 @@
 // found in the LICENSE file.
 
 #include <bitset>
+
 #include "base/single_thread_task_runner.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/v8_cache_options.mojom-blink.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/inspector/console_message_storage.h"
 #include "third_party/blink/renderer/core/inspector/thread_debugger.h"
 #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
diff --git a/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc b/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
index 144138a..ce436fa 100644
--- a/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
+++ b/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
@@ -20,6 +20,7 @@
 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
 #include "third_party/blink/renderer/core/frame/frame_console.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/core/layout/layout_box.h"
 #include "third_party/blink/renderer/modules/animationworklet/css_animation_worklet.h"
diff --git a/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc b/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc
index a827c13a..b3116b3 100644
--- a/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc
+++ b/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/web_feature.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader_test.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader_test.cc
index acd74a3..fa4d8981 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader_test.cc
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader_test.cc
@@ -12,6 +12,7 @@
 #include "third_party/blink/renderer/bindings/modules/v8/v8_image_resource.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc
index 4565c87c..613f69d6 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
 #include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_cache_query_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_image_resource.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
diff --git a/third_party/blink/renderer/modules/battery/battery_manager.cc b/third_party/blink/renderer/modules/battery/battery_manager.cc
index e603880..27ebe52 100644
--- a/third_party/blink/renderer/modules/battery/battery_manager.cc
+++ b/third_party/blink/renderer/modules/battery/battery_manager.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/navigator.h"
 #include "third_party/blink/renderer/modules/battery/battery_dispatcher.h"
 
diff --git a/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc
index 780bc026..2b304da 100644
--- a/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc
+++ b/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc
@@ -12,6 +12,7 @@
 #include "third_party/blink/renderer/core/css/resolver/font_style_resolver.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/html/canvas/text_metrics.h"
 #include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
diff --git a/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc b/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc
index feb0ec4b..690cd10 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc
@@ -13,6 +13,7 @@
 #include "third_party/blink/public/platform/cross_variant_mojo_util.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/platform_event_controller.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_motion_data.h"
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc b/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc
index 1a167504..a39cb76 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.h"
 
 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink.h"
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc b/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc
index 7114fe0..4a163d2 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc
@@ -8,6 +8,7 @@
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/core/frame/deprecation.h"
 #include "third_party/blink/renderer/core/frame/frame_console.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_orientation_data.h"
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc b/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc
index 67577c4..5765c17b 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc
@@ -13,6 +13,7 @@
 #include "third_party/blink/public/platform/cross_variant_mojo_util.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/platform_event_controller.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_orientation_data.h"
diff --git a/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.cc b/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.cc
index 5d10432..d2bc8f9 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.cc
@@ -3,7 +3,9 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h"
+
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/imagecapture/image_capture.cc b/third_party/blink/renderer/modules/imagecapture/image_capture.cc
index 7fd9444..87e1653 100644
--- a/third_party/blink/renderer/modules/imagecapture/image_capture.cc
+++ b/third_party/blink/renderer/modules/imagecapture/image_capture.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/callback_helpers.h"
+#include "base/trace_event/trace_event.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/mojom/permissions/permission_status.mojom-blink.h"
diff --git a/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc b/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc
index 09dd505..d0afb76 100644
--- a/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc
+++ b/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/v8_binding.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
diff --git a/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc b/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
index 8c1d6518..208df05 100644
--- a/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
+++ b/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
@@ -48,6 +48,7 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/execution_context/navigator_base.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/modules/encryptedmedia/encrypted_media_utils.h"
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc b/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc
index eb35d37..ee41a7b 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc
@@ -12,6 +12,7 @@
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/screen.h"
 #include "third_party/blink/renderer/core/html/media/html_video_element.h"
 #include "third_party/blink/renderer/core/page/chrome_client.h"
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc b/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc
index 3807fe2..4863350 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
 #include "third_party/blink/renderer/core/html/media/html_media_element_controls_list.h"
 #include "third_party/blink/renderer/core/html/media/html_video_element.h"
diff --git a/third_party/blink/renderer/modules/mediasession/media_session_test.cc b/third_party/blink/renderer/modules/mediasession/media_session_test.cc
index b561bc2..18f8a3d 100644
--- a/third_party/blink/renderer/modules/mediasession/media_session_test.cc
+++ b/third_party/blink/renderer/modules/mediasession/media_session_test.cc
@@ -11,6 +11,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_media_position_state.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 
diff --git a/third_party/blink/renderer/modules/modalclosewatcher/modal_close_watcher.cc b/third_party/blink/renderer/modules/modalclosewatcher/modal_close_watcher.cc
index 7738508..02bf0b8 100644
--- a/third_party/blink/renderer/modules/modalclosewatcher/modal_close_watcher.cc
+++ b/third_party/blink/renderer/modules/modalclosewatcher/modal_close_watcher.cc
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/events/keyboard_event.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/modules/event_target_modules.h"
 #include "third_party/blink/renderer/platform/keyboard_codes.h"
 
diff --git a/third_party/blink/renderer/modules/netinfo/network_information.cc b/third_party/blink/renderer/modules/netinfo/network_information.cc
index fbc40d0..108c3e36 100644
--- a/third_party/blink/renderer/modules/netinfo/network_information.cc
+++ b/third_party/blink/renderer/modules/netinfo/network_information.cc
@@ -12,6 +12,7 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/execution_context/navigator_base.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/modules/event_target_modules.h"
diff --git a/third_party/blink/renderer/modules/nfc/nfc_proxy_test.cc b/third_party/blink/renderer/modules/nfc/nfc_proxy_test.cc
index 5f08d0a2..cbcd1ec 100644
--- a/third_party/blink/renderer/modules/nfc/nfc_proxy_test.cc
+++ b/third_party/blink/renderer/modules/nfc/nfc_proxy_test.cc
@@ -15,6 +15,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ndef_scan_options.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/modules/nfc/ndef_reader.h"
 #include "third_party/blink/renderer/modules/nfc/nfc_proxy.h"
diff --git a/third_party/blink/renderer/modules/notifications/notification_resources_loader_test.cc b/third_party/blink/renderer/modules/notifications/notification_resources_loader_test.cc
index 0aec612..97308c9 100644
--- a/third_party/blink/renderer/modules/notifications/notification_resources_loader_test.cc
+++ b/third_party/blink/renderer/modules/notifications/notification_resources_loader_test.cc
@@ -5,11 +5,13 @@
 #include "third_party/blink/renderer/modules/notifications/notification_resources_loader.h"
 
 #include <memory>
+
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/notifications/notification_constants.h"
 #include "third_party/blink/public/mojom/notifications/notification.mojom-blink.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
diff --git a/third_party/blink/renderer/modules/payments/goods/dom_window_digital_goods.cc b/third_party/blink/renderer/modules/payments/goods/dom_window_digital_goods.cc
index 019c2f3..b282dd9b 100644
--- a/third_party/blink/renderer/modules/payments/goods/dom_window_digital_goods.cc
+++ b/third_party/blink/renderer/modules/payments/goods/dom_window_digital_goods.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
index 18ecd04..505cc3a 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
@@ -35,6 +35,7 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/fileapi/blob.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
 #include "third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h"
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
index cf768997..7a96344 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
@@ -16,6 +16,7 @@
 #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_rtp_header_extension_capability.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_rtp_header_extension_parameters.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
 #include "third_party/blink/renderer/core/streams/readable_stream.h"
 #include "third_party/blink/renderer/core/streams/writable_stream.h"
diff --git a/third_party/blink/renderer/modules/plugins/navigator_plugins.cc b/third_party/blink/renderer/modules/plugins/navigator_plugins.cc
index f154e35..290d152 100644
--- a/third_party/blink/renderer/modules/plugins/navigator_plugins.cc
+++ b/third_party/blink/renderer/modules/plugins/navigator_plugins.cc
@@ -7,6 +7,7 @@
 #include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
 #include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
 #include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h"
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/navigator.h"
 #include "third_party/blink/renderer/modules/plugins/dom_mime_type.h"
diff --git a/third_party/blink/renderer/modules/presentation/presentation_availability.cc b/third_party/blink/renderer/modules/presentation/presentation_availability.cc
index 13a1b6a..ed39368 100644
--- a/third_party/blink/renderer/modules/presentation/presentation_availability.cc
+++ b/third_party/blink/renderer/modules/presentation/presentation_availability.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/modules/event_target_modules_names.h"
 #include "third_party/blink/renderer/modules/presentation/presentation_availability_state.h"
 #include "third_party/blink/renderer/modules/presentation/presentation_controller.h"
diff --git a/third_party/blink/renderer/modules/presentation/presentation_receiver.cc b/third_party/blink/renderer/modules/presentation/presentation_receiver.cc
index e424900..e74fdd04 100644
--- a/third_party/blink/renderer/modules/presentation/presentation_receiver.cc
+++ b/third_party/blink/renderer/modules/presentation/presentation_receiver.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/modules/presentation/presentation_connection.h"
 #include "third_party/blink/renderer/modules/presentation/presentation_connection_list.h"
 
diff --git a/third_party/blink/renderer/modules/presentation/presentation_request.cc b/third_party/blink/renderer/modules/presentation/presentation_request.cc
index 183be0a..99fd6856 100644
--- a/third_party/blink/renderer/modules/presentation/presentation_request.cc
+++ b/third_party/blink/renderer/modules/presentation/presentation_request.cc
@@ -13,6 +13,7 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/deprecation.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/loader/mixed_content_checker.h"
 #include "third_party/blink/renderer/modules/event_target_modules.h"
diff --git a/third_party/blink/renderer/modules/screen_enumeration/window_screens.cc b/third_party/blink/renderer/modules/screen_enumeration/window_screens.cc
index 387861e..80aeb17f 100644
--- a/third_party/blink/renderer/modules/screen_enumeration/window_screens.cc
+++ b/third_party/blink/renderer/modules/screen_enumeration/window_screens.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/modules/permissions/permission_utils.h"
 #include "third_party/blink/renderer/modules/screen_enumeration/screens.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
diff --git a/third_party/blink/renderer/modules/sensor/sensor.cc b/third_party/blink/renderer/modules/sensor/sensor.cc
index 4944b03..d7ce5f7 100644
--- a/third_party/blink/renderer/modules/sensor/sensor.cc
+++ b/third_party/blink/renderer/modules/sensor/sensor.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom-blink.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/core/timing/dom_window_performance.h"
 #include "third_party/blink/renderer/core/timing/window_performance.h"
diff --git a/third_party/blink/renderer/modules/sensor/sensor_test_utils.cc b/third_party/blink/renderer/modules/sensor/sensor_test_utils.cc
index 96539f7..85660f21 100644
--- a/third_party/blink/renderer/modules/sensor/sensor_test_utils.cc
+++ b/third_party/blink/renderer/modules/sensor/sensor_test_utils.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "third_party/blink/renderer/modules/sensor/sensor_test_utils.h"
+
 #include <utility>
 
 #include "base/callback.h"
@@ -10,9 +12,9 @@
 #include "third_party/blink/renderer/core/dom/events/event_target.h"
 #include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/page/focus_controller.h"
 #include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/modules/sensor/sensor_test_utils.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
diff --git a/third_party/blink/renderer/modules/serial/serial.cc b/third_party/blink/renderer/modules/serial/serial.cc
index c7d5965..5d9dfb8 100644
--- a/third_party/blink/renderer/modules/serial/serial.cc
+++ b/third_party/blink/renderer/modules/serial/serial.cc
@@ -19,6 +19,7 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/execution_context/navigator_base.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/modules/event_target_modules_names.h"
 #include "third_party/blink/renderer/modules/serial/serial_port.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc b/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc
index b1e9b67a..f9b6afc 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc
@@ -20,6 +20,7 @@
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/page/focus_controller.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/modules/service_worker/navigator_service_worker.h"
diff --git a/third_party/blink/renderer/modules/storage/storage_area.cc b/third_party/blink/renderer/modules/storage/storage_area.cc
index c302540..32373c8 100644
--- a/third_party/blink/renderer/modules/storage/storage_area.cc
+++ b/third_party/blink/renderer/modules/storage/storage_area.cc
@@ -33,6 +33,7 @@
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/modules/storage/dom_window_storage.h"
 #include "third_party/blink/renderer/modules/storage/inspector_dom_storage_agent.h"
 #include "third_party/blink/renderer/modules/storage/storage_controller.h"
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.cc
index c086291..c3de6fa 100644
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.cc
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.cc
@@ -16,6 +16,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_wake_lock_sentinel.h"
 #include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/modules/wake_lock/wake_lock_type.h"
 #include "third_party/blink/renderer/platform/bindings/v8_binding.h"
 #include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
diff --git a/third_party/blink/renderer/modules/webaudio/audio_basic_processor_handler_test.cc b/third_party/blink/renderer/modules/webaudio/audio_basic_processor_handler_test.cc
index cd671a87..a121443 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_basic_processor_handler_test.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_basic_processor_handler_test.cc
@@ -3,9 +3,12 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/renderer/modules/webaudio/audio_basic_processor_handler.h"
+
 #include <memory>
+
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/modules/webaudio/offline_audio_context.h"
 #include "third_party/blink/renderer/platform/audio/audio_processor.h"
diff --git a/third_party/blink/renderer/modules/webaudio/audio_context_test.cc b/third_party/blink/renderer/modules/webaudio/audio_context_test.cc
index 94dd84f..b7e88eb 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_context_test.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_context_test.cc
@@ -13,6 +13,7 @@
 #include "third_party/blink/renderer/core/core_initializer.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
diff --git a/third_party/blink/renderer/modules/webaudio/audio_node_input_test.cc b/third_party/blink/renderer/modules/webaudio/audio_node_input_test.cc
index eb2221d..4de4b619 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_node_input_test.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_node_input_test.cc
@@ -5,8 +5,10 @@
 #include "third_party/blink/renderer/modules/webaudio/audio_node.h"
 
 #include <memory>
+
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/modules/webaudio/audio_node_input.h"
 #include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
index 84fc507..578642f 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
@@ -22,6 +22,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
 #include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/inspector/worker_devtools_params.h"
 #include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
 #include "third_party/blink/renderer/core/messaging/message_channel.h"
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.cc
index 08cf3d4..109cf3c 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.cc
@@ -10,16 +10,17 @@
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/messaging/message_port.h"
 #include "third_party/blink/renderer/modules/webaudio/audio_worklet.h"
 #include "third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.h"
 #include "third_party/blink/renderer/modules/webaudio/audio_worklet_node.h"
 #include "third_party/blink/renderer/modules/webaudio/audio_worklet_object_proxy.h"
 #include "third_party/blink/renderer/modules/webaudio/audio_worklet_processor.h"
+#include "third_party/blink/renderer/modules/webaudio/cross_thread_audio_worklet_processor_info.h"
 #include "third_party/blink/renderer/modules/webaudio/offline_audio_worklet_thread.h"
 #include "third_party/blink/renderer/modules/webaudio/realtime_audio_worklet_thread.h"
 #include "third_party/blink/renderer/modules/webaudio/semi_realtime_audio_worklet_thread.h"
-#include "third_party/blink/renderer/modules/webaudio/cross_thread_audio_worklet_processor_info.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
index 70112b5..4d9995c 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
@@ -2,11 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h"
-#include "third_party/blink/renderer/modules/webaudio/offline_audio_worklet_thread.h"
-#include "third_party/blink/renderer/modules/webaudio/realtime_audio_worklet_thread.h"
-#include "third_party/blink/renderer/modules/webaudio/semi_realtime_audio_worklet_thread.h"
-
 #include <memory>
 #include <tuple>
 
@@ -25,6 +20,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
 #include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/core/inspector/worker_devtools_params.h"
 #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
@@ -37,6 +33,10 @@
 #include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
 #include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
 #include "third_party/blink/renderer/core/workers/worklet_module_responses_map.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h"
+#include "third_party/blink/renderer/modules/webaudio/offline_audio_worklet_thread.h"
+#include "third_party/blink/renderer/modules/webaudio/realtime_audio_worklet_thread.h"
+#include "third_party/blink/renderer/modules/webaudio/semi_realtime_audio_worklet_thread.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
diff --git a/third_party/blink/renderer/modules/webaudio/convolver_node_test.cc b/third_party/blink/renderer/modules/webaudio/convolver_node_test.cc
index efee294f..d0fe20cb6 100644
--- a/third_party/blink/renderer/modules/webaudio/convolver_node_test.cc
+++ b/third_party/blink/renderer/modules/webaudio/convolver_node_test.cc
@@ -3,9 +3,12 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/renderer/modules/webaudio/convolver_node.h"
+
 #include <memory>
+
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/modules/webaudio/audio_buffer.h"
 #include "third_party/blink/renderer/modules/webaudio/offline_audio_context.h"
diff --git a/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node_test.cc b/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node_test.cc
index 75f5272..0d89da80 100644
--- a/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node_test.cc
+++ b/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node_test.cc
@@ -3,9 +3,12 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.h"
+
 #include <memory>
+
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
 #include "third_party/blink/renderer/modules/webaudio/offline_audio_context.h"
diff --git a/third_party/blink/renderer/modules/webaudio/script_processor_node.cc b/third_party/blink/renderer/modules/webaudio/script_processor_node.cc
index 84242fc..2d79a73 100644
--- a/third_party/blink/renderer/modules/webaudio/script_processor_node.cc
+++ b/third_party/blink/renderer/modules/webaudio/script_processor_node.cc
@@ -27,6 +27,7 @@
 
 #include <memory>
 
+#include "base/trace_event/trace_event.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
diff --git a/third_party/blink/renderer/modules/webaudio/script_processor_node_test.cc b/third_party/blink/renderer/modules/webaudio/script_processor_node_test.cc
index ee700a8d8..0508e5c8 100644
--- a/third_party/blink/renderer/modules/webaudio/script_processor_node_test.cc
+++ b/third_party/blink/renderer/modules/webaudio/script_processor_node_test.cc
@@ -3,9 +3,12 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/renderer/modules/webaudio/script_processor_node.h"
+
 #include <memory>
+
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/modules/webaudio/offline_audio_context.h"
 
diff --git a/third_party/blink/renderer/modules/webaudio/stereo_panner_node_test.cc b/third_party/blink/renderer/modules/webaudio/stereo_panner_node_test.cc
index 2c0e2f0..d7de93df 100644
--- a/third_party/blink/renderer/modules/webaudio/stereo_panner_node_test.cc
+++ b/third_party/blink/renderer/modules/webaudio/stereo_panner_node_test.cc
@@ -3,9 +3,12 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/renderer/modules/webaudio/stereo_panner_node.h"
+
 #include <memory>
+
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/modules/webaudio/offline_audio_context.h"
 
diff --git a/third_party/blink/renderer/modules/webcodecs/BUILD.gn b/third_party/blink/renderer/modules/webcodecs/BUILD.gn
index 9fa2ba9..6e6acaa8 100644
--- a/third_party/blink/renderer/modules/webcodecs/BUILD.gn
+++ b/third_party/blink/renderer/modules/webcodecs/BUILD.gn
@@ -46,6 +46,8 @@
     "image_track.h",
     "image_track_list.cc",
     "image_track_list.h",
+    "parsed_read_into_options.cc",
+    "parsed_read_into_options.h",
     "plane.cc",
     "plane.h",
     "video_decoder.cc",
diff --git a/third_party/blink/renderer/modules/webcodecs/parsed_read_into_options.cc b/third_party/blink/renderer/modules/webcodecs/parsed_read_into_options.cc
new file mode 100644
index 0000000..c06ebf3
--- /dev/null
+++ b/third_party/blink/renderer/modules/webcodecs/parsed_read_into_options.cc
@@ -0,0 +1,235 @@
+// 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 "third_party/blink/renderer/modules/webcodecs/parsed_read_into_options.h"
+
+#include <algorithm>
+
+#include "base/numerics/checked_math.h"
+#include "third_party/blink/renderer/modules/webcodecs/plane_layout.h"
+#include "third_party/blink/renderer/modules/webcodecs/video_frame_read_into_options.h"
+#include "third_party/blink/renderer/modules/webcodecs/video_frame_region.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+
+namespace blink {
+
+ParsedReadIntoOptions::ParsedReadIntoOptions(VideoFrameReadIntoOptions* options,
+                                             media::VideoPixelFormat format,
+                                             const gfx::Size& coded_size,
+                                             const gfx::Rect& visible_rect,
+                                             ExceptionState& exception_state)
+    : num_planes(
+          static_cast<wtf_size_t>(media::VideoFrame::NumPlanes(format))) {
+  uint32_t coded_width = static_cast<uint32_t>(coded_size.width());
+  uint32_t coded_height = static_cast<uint32_t>(coded_size.height());
+
+  // Parse |region|
+  gfx::Rect region = visible_rect;
+  if (options->hasRegion()) {
+    uint32_t left = options->region()->left();
+    uint32_t top = options->region()->top();
+    uint32_t width = options->region()->width();
+    uint32_t height = options->region()->height();
+
+    // Implicitly checks that left <= kMaxDimension.
+    if (left >= coded_width) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kConstraintError,
+          String::Format("Invalid region.left %u with codedWidth %u.", left,
+                         coded_width));
+      return;
+    }
+
+    // If left and width are <= kMaxDimension then their sum will not overflow.
+    if (width > coded_width || left + width > coded_width) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kConstraintError,
+          String::Format("Invalid region.width %u with region.left %u and "
+                         "codedWidth %u.",
+                         width, left, coded_width));
+      return;
+    }
+
+    // Implicitly checks that top <= kMaxDimension.
+    if (top >= coded_height) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kConstraintError,
+          String::Format("Invalid region.top %u with codedHeight %u.", top,
+                         coded_height));
+      return;
+    }
+
+    // If top and height are <= kMaxDimension then their sum will not overflow.
+    if (height > coded_height || top + height > coded_height) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kConstraintError,
+          String::Format("Invalid region.height %u with region.top %u and "
+                         "codedHeight %u.",
+                         height, top, coded_height));
+      return;
+    }
+
+    region = gfx::Rect(left, top, width, height);
+  }
+
+  // Region must be non-empty.
+  if (region.IsEmpty()) {
+    exception_state.ThrowDOMException(
+        DOMExceptionCode::kConstraintError,
+        String::Format("Invalid region with width %d and height %d. Region "
+                       "must have nonzero area.",
+                       region.width(), region.height()));
+    return;
+  }
+
+  // Region must be sample-aligned.
+  // TODO(crbug.com/1205166): media::VideoFrame does not enforce that visible
+  // rects are sample-aligned, so we may have to deal with this case somehow.
+  // Options:
+  //   - Crop VideoFrame.visibleRegion to sample boundaries and use that.
+  //     (May result in differences between rendering paths.)
+  //   - Expand or contract the crop to sample boundaries, potentially
+  //     per-plane.
+  //   - Enforce this restriction on media::VideoFrame and see if anything
+  //     breaks.
+  for (wtf_size_t i = 0; i < num_planes; i++) {
+    gfx::Size sample_size = media::VideoFrame::SampleSize(format, i);
+    if (region.x() % sample_size.width() != 0) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kConstraintError,
+          String::Format("region.left %d is not sample-aligned in plane %u.",
+                         region.x(), i));
+      return;
+    } else if (region.width() % sample_size.width() != 0) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kConstraintError,
+          String::Format("region.width %d is not sample-aligned in plane %u.",
+                         region.width(), i));
+      return;
+    } else if (region.y() % sample_size.height() != 0) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kConstraintError,
+          String::Format("region.top %d is not sample-aligned in plane %u.",
+                         region.y(), i));
+      return;
+    } else if (region.height() % sample_size.height() != 0) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kConstraintError,
+          String::Format("region.height %d is not sample-aligned in plane %u.",
+                         region.height(), i));
+      return;
+    }
+  }
+
+  // Parse |layout|.
+  bool has_explicit_layout = false;
+  if (options->hasLayout()) {
+    // TODO(crbug.com/1205169): Consider treating missing planes as implied
+    // discard.
+    if (options->layout().size() != num_planes) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kConstraintError,
+          String::Format("Invalid layout. Expected %u planes, found %u.",
+                         num_planes, options->layout().size()));
+      return;
+    }
+
+    // If the first plane has an offset, assume every plane has an offset and
+    // stride.
+    has_explicit_layout = options->layout()[0]->hasOffset();
+
+    for (wtf_size_t i = 0; i < num_planes; i++) {
+      if (options->layout()[i]->hasOffset() != has_explicit_layout) {
+        exception_state.ThrowDOMException(
+            DOMExceptionCode::kConstraintError,
+            String::Format("Invalid layout, plane %u %s an offset. "
+                           "Either all planes must have an offset and stride, "
+                           "or all planes must have neither.",
+                           i, has_explicit_layout ? "does not have" : "has"));
+        return;
+      }
+      if (options->layout()[i]->hasStride() != has_explicit_layout) {
+        exception_state.ThrowDOMException(
+            DOMExceptionCode::kConstraintError,
+            String::Format("Invalid layout, plane %u %s a stride. "
+                           "Either all planes must have an offset and stride, "
+                           "or all planes must have neither.",
+                           i, has_explicit_layout ? "does not have" : "has"));
+        return;
+      }
+      if (has_explicit_layout) {
+        planes[i].offset = options->layout()[i]->offset();
+        planes[i].stride = options->layout()[i]->stride();
+      }
+    }
+  }
+
+  // Compute the resulting layout.
+  uint32_t end_offset[media::VideoFrame::kMaxPlanes] = {0};
+  for (wtf_size_t i = 0; i < num_planes; i++) {
+    gfx::Size sample_size = media::VideoFrame::SampleSize(format, i);
+    uint32_t sample_bytes = media::VideoFrame::BytesPerElement(format, i);
+
+    planes[i].top = region.y() / sample_size.height();
+    planes[i].height = region.height() / sample_size.height();
+    planes[i].left_bytes = region.x() / sample_size.width() * sample_bytes;
+    planes[i].width_bytes = region.width() / sample_size.width() * sample_bytes;
+
+    // If an explicit layout was not provided, planes and rows are tightly
+    // packed.
+    if (!has_explicit_layout) {
+      planes[i].offset = min_buffer_size;
+      planes[i].stride = planes[i].width_bytes;
+    } else {
+      if (planes[i].stride < planes[i].width_bytes) {
+        exception_state.ThrowDOMException(
+            DOMExceptionCode::kConstraintError,
+            String::Format("Invalid layout, plane %u must have stride at least "
+                           "%u, found %u.",
+                           i, planes[i].width_bytes, planes[i].stride));
+        return;
+      }
+    }
+
+    // Note: this calculation implies that the whole stride is allocated, even
+    // on the last row.
+    const auto plane_size =
+        base::CheckedNumeric<uint32_t>(planes[i].stride) * planes[i].height;
+    if (!plane_size.IsValid()) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kConstraintError,
+          String::Format("Invalid layout, plane %u with stride %u is too "
+                         "large.",
+                         i, planes[i].stride));
+      return;
+    }
+    const auto plane_end = plane_size + planes[i].offset;
+    if (!plane_end.IsValid()) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kConstraintError,
+          String::Format("Invalid layout, plane %u with offset %u and stride "
+                         "%u exceeds bounds.",
+                         i, planes[i].offset, planes[i].stride));
+      return;
+    }
+    end_offset[i] = plane_end.ValueOrDie();
+    min_buffer_size = std::max(min_buffer_size, end_offset[i]);
+
+    // Verify that planes do not overlap.
+    for (wtf_size_t j = 0; j < i; j++) {
+      // If plane A ends before plane B starts, they do not overlap.
+      if (end_offset[i] <= planes[j].offset ||
+          end_offset[j] <= planes[i].offset) {
+        continue;
+      }
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kConstraintError,
+          String::Format("Invalid layout, plane %u overlaps with plane %u.", i,
+                         j));
+      return;
+    }
+  }
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/webcodecs/parsed_read_into_options.h b/third_party/blink/renderer/modules/webcodecs/parsed_read_into_options.h
new file mode 100644
index 0000000..0be3464
--- /dev/null
+++ b/third_party/blink/renderer/modules/webcodecs/parsed_read_into_options.h
@@ -0,0 +1,50 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_PARSED_READ_INTO_OPTIONS_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_PARSED_READ_INTO_OPTIONS_H_
+
+#include <stdint.h>
+
+#include "media/base/video_frame.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
+
+namespace blink {
+
+class ExceptionState;
+class VideoFrameReadIntoOptions;
+
+struct ParsedReadIntoOptions {
+  ParsedReadIntoOptions(VideoFrameReadIntoOptions* options,
+                        media::VideoPixelFormat format,
+                        const gfx::Size& coded_size,
+                        const gfx::Rect& visible_rect,
+                        ExceptionState&);
+
+  struct Plane {
+    // Offset in destination buffer.
+    uint32_t offset = 0;
+    // Stride in destination buffer.
+    uint32_t stride = 0;
+
+    // Crop top, in samples.
+    uint32_t top = 0;
+    // Crop height, in samples.
+    uint32_t height = 0;
+    // Crop left, in bytes.
+    uint32_t left_bytes = 0;
+    // Crop width, in bytes (aka row_bytes).
+    uint32_t width_bytes = 0;
+  };
+
+  const wtf_size_t num_planes;
+  Plane planes[media::VideoFrame::kMaxPlanes] = {{0}};
+
+  // Minimum size of a destination buffer that fits all planes.
+  uint32_t min_buffer_size = 0;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_PARSED_READ_INTO_OPTIONS_H_
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame.cc b/third_party/blink/renderer/modules/webcodecs/video_frame.cc
index e6915e5..e9cd4511 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_frame.cc
+++ b/third_party/blink/renderer/modules/webcodecs/video_frame.cc
@@ -28,6 +28,8 @@
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
 #include "third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_factories.h"
+#include "third_party/blink/renderer/modules/webcodecs/parsed_read_into_options.h"
+#include "third_party/blink/renderer/modules/webcodecs/plane_layout.h"
 #include "third_party/blink/renderer/modules/webcodecs/webcodecs_logger.h"
 #include "third_party/blink/renderer/platform/graphics/image.h"
 #include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
@@ -807,9 +809,26 @@
 
 uint32_t VideoFrame::allocationSize(VideoFrameReadIntoOptions* options,
                                     ExceptionState& exception_state) {
-  exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
-                                    "allocationSize() is not implemented.");
-  return 0;
+  auto local_frame = handle_->frame();
+  if (!local_frame)
+    return 0;
+
+  // TODO(crbug.com/1176464): Determine the format readback will occur in, use
+  // that to compute the layout.
+  if (!IsSupportedPlanarFormat(*local_frame)) {
+    exception_state.ThrowDOMException(
+        DOMExceptionCode::kNotSupportedError,
+        "allocationSize() is not yet implemented when format is null.");
+    return 0;
+  }
+
+  ParsedReadIntoOptions layout(options, local_frame->format(),
+                               local_frame->coded_size(),
+                               local_frame->visible_rect(), exception_state);
+  if (exception_state.HadException())
+    return 0;
+
+  return layout.min_buffer_size;
 }
 
 ScriptPromise VideoFrame::readInto(
@@ -817,9 +836,81 @@
     const ArrayBufferOrArrayBufferView& destination,
     VideoFrameReadIntoOptions* options,
     ExceptionState& exception_state) {
-  exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
-                                    "readInto() is not implemented.");
-  return ScriptPromise();
+  auto local_frame = handle_->frame();
+  if (!local_frame) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+                                      "Cannot read closed VideoFrame.");
+    return ScriptPromise();
+  }
+
+  // TODO(crbug.com/1176464): Use async texture readback.
+  if (!IsSupportedPlanarFormat(*local_frame)) {
+    exception_state.ThrowDOMException(
+        DOMExceptionCode::kNotSupportedError,
+        "readInto() is not yet implemented when format is null.");
+    return ScriptPromise();
+  }
+
+  // Compute layout.
+  ParsedReadIntoOptions layout(options, local_frame->format(),
+                               local_frame->coded_size(),
+                               local_frame->visible_rect(), exception_state);
+  if (exception_state.HadException())
+    return ScriptPromise();
+
+  // Validate destination buffer.
+  DOMArrayPiece buffer(destination);
+  if (buffer.ByteLength() < static_cast<size_t>(layout.min_buffer_size)) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kConstraintError,
+                                      "destination is not large enough.");
+    return ScriptPromise();
+  }
+
+  // Map buffers if necessary.
+  if (!local_frame->IsMappable()) {
+    DCHECK(local_frame->HasGpuMemoryBuffer());
+    local_frame = media::ConvertToMemoryMappedFrame(local_frame);
+    if (!local_frame) {
+      exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+                                        "Failed to read VideoFrame data.");
+      return ScriptPromise();
+    }
+  }
+
+  // Copy data.
+  for (wtf_size_t i = 0; i < layout.num_planes; i++) {
+    size_t src_stride = local_frame->stride(i);
+    size_t dest_stride = layout.planes[i].stride;
+    size_t row_bytes = layout.planes[i].width_bytes;
+
+    uint8_t* src = local_frame->data(i) + layout.planes[i].top * src_stride +
+                   layout.planes[i].left_bytes;
+    uint8_t* dest = buffer.Bytes() + layout.planes[i].offset;
+
+    // TODO(crbug.com/1205176): Use libyuv::CopyPlane(). The requirements to use
+    // it are a bit strange though, it computes with ints and expects
+    // intermediate values (like stride * height) to fit.
+    for (size_t row = 0; row < layout.planes[i].height; row++) {
+      // TODO(crbug.com/1205175): Spec what happens to the gaps between
+      // |row_bytes| and |dest_stride|. Probably needs to be compatible with
+      // whatever libyuv does.
+      memcpy(dest, src, row_bytes);
+      src += src_stride;
+      dest += dest_stride;
+    }
+  }
+
+  // Convert and return |layout|.
+  HeapVector<Member<PlaneLayout>> result;
+  for (wtf_size_t i = 0; i < layout.num_planes; i++) {
+    auto* plane = MakeGarbageCollected<PlaneLayout>();
+    plane->setOffset(layout.planes[i].offset);
+    plane->setStride(layout.planes[i].stride);
+    result.push_back(plane);
+  }
+  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  resolver->Resolve(result);
+  return resolver->Promise();
 }
 
 void VideoFrame::close() {
diff --git a/third_party/blink/renderer/modules/webdatabase/database_tracker.cc b/third_party/blink/renderer/modules/webdatabase/database_tracker.cc
index 559b1bb..357c3dda 100644
--- a/third_party/blink/renderer/modules/webdatabase/database_tracker.cc
+++ b/third_party/blink/renderer/modules/webdatabase/database_tracker.cc
@@ -38,6 +38,7 @@
 #include "third_party/blink/public/platform/web_security_origin.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/modules/webdatabase/database.h"
 #include "third_party/blink/renderer/modules/webdatabase/database_client.h"
 #include "third_party/blink/renderer/modules/webdatabase/database_context.h"
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc b/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
index 951725f..ff20f17 100644
--- a/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
+++ b/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
@@ -22,6 +22,7 @@
 #include "third_party/blink/public/platform/websocket_handshake_throttle.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/loader/empty_clients.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
diff --git a/third_party/blink/renderer/modules/webusb/usb.cc b/third_party/blink/renderer/modules/webusb/usb.cc
index 01f2d5a..ed5c7684 100644
--- a/third_party/blink/renderer/modules/webusb/usb.cc
+++ b/third_party/blink/renderer/modules/webusb/usb.cc
@@ -19,6 +19,7 @@
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/execution_context/navigator_base.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/modules/event_target_modules.h"
 #include "third_party/blink/renderer/modules/webusb/usb_connection_event.h"
 #include "third_party/blink/renderer/modules/webusb/usb_device.h"
diff --git a/third_party/blink/renderer/modules/worklet/worklet_thread_test_common.cc b/third_party/blink/renderer/modules/worklet/worklet_thread_test_common.cc
index bcc6e3c..2222cb8 100644
--- a/third_party/blink/renderer/modules/worklet/worklet_thread_test_common.cc
+++ b/third_party/blink/renderer/modules/worklet/worklet_thread_test_common.cc
@@ -2,13 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <utility>
-
 #include "third_party/blink/renderer/modules/worklet/worklet_thread_test_common.h"
 
+#include <utility>
+
 #include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/inspector/worker_devtools_params.h"
 #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
diff --git a/third_party/blink/renderer/platform/heap/BUILD.gn b/third_party/blink/renderer/platform/heap/BUILD.gn
index 626e0ddc..233fda4 100644
--- a/third_party/blink/renderer/platform/heap/BUILD.gn
+++ b/third_party/blink/renderer/platform/heap/BUILD.gn
@@ -123,6 +123,7 @@
       "v8_wrapper/unified_heap_controller.h",
       "v8_wrapper/unified_heap_marking_visitor.h",
       "v8_wrapper/visitor.h",
+      "v8_wrapper/write_barrier.h",
     ]
 
     deps += [
diff --git a/third_party/blink/renderer/platform/heap/v8_wrapper/heap_allocator_impl.h b/third_party/blink/renderer/platform/heap/v8_wrapper/heap_allocator_impl.h
index 7056f40..49bfae0 100644
--- a/third_party/blink/renderer/platform/heap/v8_wrapper/heap_allocator_impl.h
+++ b/third_party/blink/renderer/platform/heap/v8_wrapper/heap_allocator_impl.h
@@ -10,6 +10,7 @@
 #include "third_party/blink/renderer/platform/heap/v8_wrapper/heap.h"
 #include "third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h"
 #include "third_party/blink/renderer/platform/heap/v8_wrapper/visitor.h"
+#include "third_party/blink/renderer/platform/heap/v8_wrapper/write_barrier.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "v8/include/cppgc/heap-consistency.h"
@@ -115,19 +116,7 @@
 
   template <typename T>
   static void BackingWriteBarrier(T** slot) {
-    HeapConsistency::WriteBarrierParams params;
-    switch (HeapConsistency::GetWriteBarrierType(slot, *slot, params)) {
-      case HeapConsistency::WriteBarrierType::kMarking:
-        HeapConsistency::DijkstraWriteBarrier(params, *slot);
-        break;
-      case HeapConsistency::WriteBarrierType::kGenerational:
-        HeapConsistency::GenerationalBarrier(params, slot);
-        break;
-      case HeapConsistency::WriteBarrierType::kNone:
-        break;
-      default:
-        break;  // TODO(1056170): Remove default case when API is stable.
-    }
+    WriteBarrier::DispatchForObject(slot);
   }
 
   template <typename T>
diff --git a/third_party/blink/renderer/platform/heap/v8_wrapper/member.h b/third_party/blink/renderer/platform/heap/v8_wrapper/member.h
index a734b37..5799b7b 100644
--- a/third_party/blink/renderer/platform/heap/v8_wrapper/member.h
+++ b/third_party/blink/renderer/platform/heap/v8_wrapper/member.h
@@ -6,6 +6,9 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_MEMBER_H_
 
 #include "third_party/blink/renderer/platform/heap/thread_state.h"
+#include "third_party/blink/renderer/platform/heap/v8_wrapper/write_barrier.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/construct_traits.h"
 #include "v8/include/cppgc/member.h"
 
 namespace blink {
@@ -46,4 +49,49 @@
 
 }  // namespace blink
 
+namespace WTF {
+
+template <typename T, typename Traits, typename Allocator>
+class MemberConstructTraits {
+  STATIC_ONLY(MemberConstructTraits);
+
+ public:
+  template <typename... Args>
+  static T* Construct(void* location, Args&&... args) {
+    return new (NotNull, location) T(std::forward<Args>(args)...);
+  }
+
+  static void NotifyNewElement(T* element) {
+    blink::WriteBarrier::DispatchForObject(element);
+  }
+
+  template <typename... Args>
+  static T* ConstructAndNotifyElement(void* location, Args&&... args) {
+    // ConstructAndNotifyElement updates an existing Member which might
+    // also be comncurrently traced while we update it. The regular ctors
+    // for Member don't use an atomic write which can lead to data races.
+    T* object = Construct(location, std::forward<Args>(args)...,
+                          typename T::AtomicInitializerTag());
+    NotifyNewElement(object);
+    return object;
+  }
+
+  static void NotifyNewElements(T* array, size_t len) {
+    while (len-- > 0) {
+      blink::WriteBarrier::DispatchForObject(array);
+      array++;
+    }
+  }
+};
+
+template <typename T, typename Traits, typename Allocator>
+class ConstructTraits<blink::Member<T>, Traits, Allocator>
+    : public MemberConstructTraits<blink::Member<T>, Traits, Allocator> {};
+
+template <typename T, typename Traits, typename Allocator>
+class ConstructTraits<blink::WeakMember<T>, Traits, Allocator>
+    : public MemberConstructTraits<blink::WeakMember<T>, Traits, Allocator> {};
+
+}  // namespace WTF
+
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_MEMBER_H_
diff --git a/third_party/blink/renderer/platform/heap/v8_wrapper/write_barrier.h b/third_party/blink/renderer/platform/heap/v8_wrapper/write_barrier.h
new file mode 100644
index 0000000..06bf198
--- /dev/null
+++ b/third_party/blink/renderer/platform/heap/v8_wrapper/write_barrier.h
@@ -0,0 +1,38 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_WRITE_BARRIER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_WRITE_BARRIER_H_
+
+#include "v8/include/cppgc/heap-consistency.h"
+
+namespace blink {
+
+class WriteBarrier {
+  STATIC_ONLY(WriteBarrier);
+
+  using HeapConsistency = cppgc::subtle::HeapConsistency;
+
+ public:
+  template <typename T>
+  static void DispatchForObject(T* element) {
+    HeapConsistency::WriteBarrierParams params;
+    switch (HeapConsistency::GetWriteBarrierType(element, *element, params)) {
+      case HeapConsistency::WriteBarrierType::kMarking:
+        HeapConsistency::DijkstraWriteBarrier(params, *element);
+        break;
+      case HeapConsistency::WriteBarrierType::kGenerational:
+        HeapConsistency::GenerationalBarrier(params, element);
+        break;
+      case HeapConsistency::WriteBarrierType::kNone:
+        break;
+      default:
+        break;  // TODO(1056170): Remove default case when API is stable.
+    }
+  }
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_WRITE_BARRIER_H_
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index b4a357c..d5b98970 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -542,7 +542,7 @@
       // @font-face descriptor size-adjust.
       // https://drafts.csswg.org/css-fonts-5/#descdef-font-face-size-adjust
       name: "CSSFontFaceSizeAdjust",
-      status: "test",
+      status: "experimental",
     },
     {
       // @font-face descriptors ascent-override, descent-override and
@@ -628,6 +628,10 @@
       depends_on: ["PictureInPictureAPI"],
     },
     {
+      name: "CSSPositionStickyStaticScrollPosition",
+      status: "experimental",
+    },
+    {
       name: "CSSPseudoDir",
       status: "experimental",
     },
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index b7e7bee..17d8eb5 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -566,7 +566,6 @@
 
 #### external/wpt/css/css-position
 crbug.com/752022 external/wpt/css/css-position/sticky/position-sticky-offset-overflow.html [ Failure ]
-crbug.com/664246 external/wpt/css/css-position/sticky/position-sticky-scrollIntoView.html [ Failure ]
 
 #### external/wpt/css/css-sizing
 crbug.com/1164135 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-025.html [ Failure ]
@@ -6880,9 +6879,6 @@
 # Sheriff 2021-03-23
 crbug.com/1182689 [ Mac ] external/wpt/editing/run/delete.html?6001-last [ Failure ]
 
-# Temporarily disable to update DevTools
-crbug.com/1202024 http/tests/devtools/resource-tree/resource-tree-events.js [ Pass Failure ]
-
 # Sheriff 2021-03-24
 crbug.com/1192215 [ Linux ] external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird.html [ Pass Failure ]
 
@@ -7003,7 +6999,6 @@
 # Sheriff 2021-04-22
 crbug.com/1191990 [ Linux ] http/tests/serviceworker/clients-openwindow.html [ Pass Failure ]
 crbug.com/1198443 virtual/plz-dedicated-worker/external/wpt/html/cross-origin-embedder-policy/none.https.html [ Pass Failure Timeout ]
-crbug.com/1201879 http/tests/inspector-protocol/issues/mixed-content-issue-creation-js-within-oopif.js [ Pass Timeout ]
 
 # Sheriff 2021-04-23
 crbug.com/1198832 [ Linux ] external/wpt/css/css-sizing/aspect-ratio/replaced-element-003.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-input-box-gets-focused-after-scroll.html b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-input-box-gets-focused-after-scroll.html
index 5b2d705e..438547d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-input-box-gets-focused-after-scroll.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-input-box-gets-focused-after-scroll.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<title>Focusing on visible sticky input box should not scroll the page.</title>
+<title>Focusing on visible sticky input box should scroll to unshifted sticky position.</title>
 <link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos" />
 <meta name="assert" content="This test checks that focusing on visible sticky
 positioned input box should not scroll the page." />
@@ -25,6 +25,6 @@
   var input = document.getElementById('input');
   window.scrollTo(0, 100);
   input.focus();
-  assert_equals(window.scrollY, 100);
-}, 'Focusing on visible sticky input box should not scroll the page.');
+  assert_equals(window.scrollY, 0);
+}, 'Focusing on visible sticky input box should reset the scroll to unshifted sticky position.');
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/sticky/sticky-after-input.html b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/sticky-after-input.html
new file mode 100644
index 0000000..9104aa3c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/sticky-after-input.html
@@ -0,0 +1,49 @@
+<!doctype html>
+<title>Sticky positioned element should reset the scroll position to unshifted position</title>
+<link rel="author" title="Seokho Song"  href="mailto:0xdevssh@gmail.com">
+<link rel="help" href="https://crbug.com/664246">
+<link rel="help" href="https://crbug.com/1178622">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<div id="scrollEl" style="height:100px; overflow-y: auto; scroll-padding:20px 20px 20px 20px;">
+    <input id="stickyEl" type="text" style="position:sticky;top:0" />
+    <div>1</div>
+    <div>2</div>
+    <div>3</div>
+    <div>4</div>
+    <div>5</div>
+    <div>6</div>
+    <div>7</div>
+    <div>8</div>
+    <div>9</div>
+    <div>10</div>
+    <div>11</div>
+    <div>12</div>
+    <div>13</div>
+    <div>14</div>
+    <div>15</div>
+    <div>16</div>
+    <div>17</div>
+</div>
+</div>
+<script>
+
+async_test(t => {
+    var scrollEl = document.getElementById("scrollEl");
+    var stickyEl = document.getElementById("stickyEl");
+    stickyEl.focus()
+    scrollEl.scrollTo(0, scrollEl.scrollHeight);
+    scrollEl.addEventListener('input', ()=> {
+        requestAnimationFrame(t.step_func(()=>{
+            assert_equals(scrollEl.scrollTop, 0,
+            "should reset the scroll to unshifted sticky position");
+            t.done()
+        }))
+    })
+    test_driver.send_keys(stickyEl, "A")
+})
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/webcodecs/videoFrame-readInto.any.js b/third_party/blink/web_tests/external/wpt/webcodecs/videoFrame-readInto.any.js
new file mode 100644
index 0000000..aaf95bf2
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webcodecs/videoFrame-readInto.any.js
@@ -0,0 +1,215 @@
+// META: global=window,dedicatedworker
+
+function makeI420_4x2() {
+  let yData = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
+  let uData = new Uint8Array([9, 10]);
+  let vData = new Uint8Array([11, 12]);
+  let planes = [{src: yData, stride: 4},
+                {src: uData, stride: 2},
+                {src: vData, stride: 2}];
+  let init = {timestamp: 0,
+              codedWidth: 4,
+              codedHeight: 2};
+  return new VideoFrame('I420', planes, init);
+}
+
+function makeRGBA_2x2() {
+  let planes = [{src: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8,
+                                      9, 10, 11, 12, 13, 14, 15, 16]),
+                 stride: 8}];
+  let init = {timestamp: 0,
+              codedWidth: 2,
+              codedHeight: 2};
+  // TODO(sandersd): Should be RGBA but that's missing in the IDL right now.
+  return new VideoFrame('ABGR', planes, init);
+}
+
+promise_test(async t => {
+  let frame = makeI420_4x2();
+  let buf = new Uint8Array(12);
+  let expected = new Uint8Array([
+      1, 2, 3, 4, 5, 6, 7, 8,  // y
+      9, 10,                   // u
+      11, 12                   // v
+  ]);
+  assert_equals(frame.allocationSize(), 12, 'allocationSize()');
+  await frame.readInto(buf);
+  assert_array_equals(buf, expected, 'destination buffer contents');
+}, 'Test I420 frame.');
+
+promise_test(async t => {
+  let frame = makeRGBA_2x2();
+  let buf = new Uint8Array(16);
+  let expected = new Uint8Array([
+      1, 2, 3, 4, 5, 6, 7, 8,
+      9, 10, 11, 12, 13, 14, 15, 16
+  ]);
+  assert_equals(frame.allocationSize(), 16, 'allocationSize()');
+  await frame.readInto(buf);
+  assert_array_equals(buf, expected, 'destination buffer contents');
+}, 'Test RGBA frame.');
+
+promise_test(async t => {
+  let frame = makeI420_4x2();
+  let buf = new Uint8Array(11);
+  let expected = new Uint8Array([
+      1, 2, 3, 4, 5, 6, 7, 8,  // y
+      9, 10,                   // u
+      11, 12                   // v
+  ]);
+  assert_equals(frame.allocationSize(), 12, 'allocationSize()');
+  await promise_rejects_dom(t, 'ConstraintError', frame.readInto(buf));
+}, 'Test undersized buffer.');
+
+promise_test(async t => {
+  let frame = makeI420_4x2();
+  let buf = new Uint8Array(12);
+  let options = {layout: [{}, {}, {}]};
+  let expected = new Uint8Array([
+      1, 2, 3, 4, 5, 6, 7, 8,  // y
+      9, 10,                   // u
+      11, 12                   // v
+  ]);
+  assert_equals(frame.allocationSize(options), 12, 'allocationSize()');
+  await frame.readInto(buf, options);
+  assert_array_equals(buf, expected, 'destination buffer contents');
+}, 'Test layout can be empty.');
+
+promise_test(async t => {
+  let frame = makeI420_4x2();
+  let buf = new Uint8Array(12);
+  let options = {layout: [{}]};
+  assert_throws_dom('ConstraintError', () => frame.allocationSize(options));
+  await promise_rejects_dom(t, 'ConstraintError', frame.readInto(buf, options));
+}, 'Test incorrect plane count.');
+
+promise_test(async t => {
+  let frame = makeI420_4x2();
+  let buf = new Uint8Array(12);
+  let options = {layout: [{offset: 4, stride: 4},
+                          {offset: 0, stride: 2},
+                          {offset: 2, stride: 2}]};
+  let expected = new Uint8Array([
+      9, 10,       // u
+      11, 12,      // v
+      1, 2, 3, 4,  // y
+      5, 6, 7, 8,
+  ]);
+  assert_equals(frame.allocationSize(options), 12, 'allocationSize()');
+  await frame.readInto(buf, options);
+  assert_array_equals(buf, expected, 'destination buffer contents');
+}, 'Test stride and offset work.');
+
+promise_test(async t => {
+  let frame = makeI420_4x2();
+  let buf = new Uint8Array(20);
+  let options = {layout: [{offset: 9, stride: 5},
+                          {offset: 1, stride: 3},
+                          {offset: 5, stride: 3}]};
+  let expected = new Uint8Array([
+      0,
+      9, 10, 0,       // u
+      0,
+      11, 12, 0,      // v
+      0,
+      1, 2, 3, 4, 0,  // y
+      5, 6, 7, 8, 0,
+      0
+  ]);
+  assert_equals(frame.allocationSize(options), 19, 'allocationSize()');
+  await frame.readInto(buf, options);
+  assert_array_equals(buf, expected, 'destination buffer contents');
+}, 'Test stride and offset with padding.');
+
+promise_test(async t => {
+  let frame = makeI420_4x2();
+  let buf = new Uint8Array(12);
+  let options = {layout: [{offset: 0, stride: 1},
+                          {offset: 8, stride: 2},
+                          {offset: 10, stride: 2}]};
+  assert_throws_dom('ConstraintError', () => frame.allocationSize(options));
+  await promise_rejects_dom(t, 'ConstraintError', frame.readInto(buf, options));
+}, 'Test invalid stride.');
+
+promise_test(async t => {
+  let frame = makeI420_4x2();
+  let buf = new Uint8Array(12);
+  let options = {layout: [{offset: 0, stride: 4},
+                          {offset: 8, stride: 2},
+                          {offset: 10}]};
+  assert_throws_dom('ConstraintError', () => frame.allocationSize(options));
+  await promise_rejects_dom(t, 'ConstraintError', frame.readInto(buf, options));
+}, 'Test missing stride.');
+
+
+promise_test(async t => {
+  let frame = makeI420_4x2();
+  let buf = new Uint8Array(12);
+  let options = {layout: [{offset: 0, stride: 4},
+                          {offset: 8, stride: 2},
+                          {stride: 2}]};
+  assert_throws_dom('ConstraintError', () => frame.allocationSize(options));
+  await promise_rejects_dom(t, 'ConstraintError', frame.readInto(buf, options));
+}, 'Test missing offset.');
+
+promise_test(async t => {
+  let frame = makeI420_4x2();
+  let buf = new Uint8Array(12);
+  let options = {layout: [{offset: 0, stride: 4},
+                          {offset: 8, stride: 2},
+                          {offset: 2 ** 32 - 2, stride: 2}]};
+  assert_throws_dom('ConstraintError', () => frame.allocationSize(options));
+  await promise_rejects_dom(t, 'ConstraintError', frame.readInto(buf, options));
+}, 'Test address overflow.');
+
+promise_test(async t => {
+  let frame = makeI420_4x2();
+  let buf = new Uint8Array(12);
+  let options = {region: frame.codedRegion};
+  let expected = new Uint8Array([
+      1, 2, 3, 4, 5, 6, 7, 8,  // y
+      9, 10,                   // u
+      11, 12                   // v
+  ]);
+  assert_equals(frame.allocationSize(options), 12, 'allocationSize()');
+  await frame.readInto(buf, options);
+  assert_array_equals(buf, expected, 'destination buffer contents');
+}, 'Test codedRegion.');
+
+promise_test(async t => {
+  let frame = makeI420_4x2();
+  let buf = new Uint8Array(12);
+  let options = {region: {left: 0, top: 0, width: 4, height: 0}};
+  assert_throws_dom('ConstraintError', () => frame.allocationSize(options));
+  await promise_rejects_dom(t, 'ConstraintError', frame.readInto(buf, options));
+}, 'Test empty region.');
+
+promise_test(async t => {
+  let frame = makeI420_4x2();
+  let buf = new Uint8Array(12);
+  let options = {region: {left: 0, top: 0, width: 4, height: 1}};
+  assert_throws_dom('ConstraintError', () => frame.allocationSize(options));
+  await promise_rejects_dom(t, 'ConstraintError', frame.readInto(buf, options));
+}, 'Test unaligned region.');
+
+promise_test(async t => {
+  let frame = makeI420_4x2();
+  let buf = new Uint8Array(6);
+  let options = {region: {left: 2, top: 0, width: 2, height: 2}};
+  let expected = new Uint8Array([
+      3, 4, 7, 8,  // y
+      10,          // u
+      12           // v
+  ]);
+  assert_equals(frame.allocationSize(options), 6, 'allocationSize()');
+  await frame.readInto(buf, options);
+  assert_array_equals(buf, expected, 'destination buffer contents');
+}, 'Test left crop.');
+
+promise_test(async t => {
+  let frame = makeI420_4x2();
+  let buf = new Uint8Array(12);
+  let options = {region: {left: 0, top: 0, width: 4, height: 4}};
+  assert_throws_dom('ConstraintError', () => frame.allocationSize(options));
+  await promise_rejects_dom(t, 'ConstraintError', frame.readInto(buf, options));
+}, 'Test invalid region.');
diff --git a/third_party/blink/web_tests/fast/css/sticky/sticky-focus-after-scroll.html b/third_party/blink/web_tests/fast/css/sticky/sticky-focus-after-scroll.html
deleted file mode 100644
index 8dfade7d..0000000
--- a/third_party/blink/web_tests/fast/css/sticky/sticky-focus-after-scroll.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!doctype html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<select id="stickyEl" style="position:sticky;top:0px" >
-    <option>foo</option>
-    <option>bar</option>
-</select>
-<div>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-test<br>test<br>test<br>test<br>test<br>test<br>test<br>
-</div>
-<script>
-'use strict';
-
-test(() => {
-  var stickyEl = document.getElementById("stickyEl");
-  window.scrollTo(0, document.body.scrollHeight);
-  assert_true(window.scrollY > 0);
-  var old_scroll_pos = window.scrollY;
-  stickyEl.focus();
-  assert_equals(window.scrollY, old_scroll_pos,
-      "should not scroll up after focusing on sticky element");
-});
-</script>
diff --git a/third_party/blink/web_tests/fast/css/sticky/sticky-input-box-position.html b/third_party/blink/web_tests/fast/css/sticky/sticky-input-box-position.html
index 637485a..d53340d2 100644
--- a/third_party/blink/web_tests/fast/css/sticky/sticky-input-box-position.html
+++ b/third_party/blink/web_tests/fast/css/sticky/sticky-input-box-position.html
@@ -1,35 +1,51 @@
 <!DOCTYPE html>
 <title>Type in an onscreen sticky positioned input box should not scroll the page.</title>
-<link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos" />
+<link rel="help" href="https://www.w3.org/TR/css-position-3/#stickypos-scroll" />
 <meta name="assert" content="This test checks that typing in an onscreen sticky positioned
-input box should not scroll the page." />
+input box should reset the scroll to unshifted position." />
 
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 
 <style>
 body {
-  height: 2000px;
+  display: inline;
 }
 
-input {
-  position: sticky;
-  top: 10px;
+#spacer {
+    height:2000px;
 }
+
 </style>
 
-<input type="text" id="input"/>
+<input type="text" style="position:sticky;" id="test"/>
+<input type="text" id="reference"/>
+<div id="spacer"></div>
 
 <script>
 test(() => {
-  var input = document.getElementById('input');
-  input.focus();
+  var test = document.getElementById('test');
+  test.focus();
   window.scrollTo(0, 100);
   assert_not_equals(window.eventSender, undefined, 'This test requires eventSender');
   eventSender.keyDown('T');
   eventSender.keyDown('E');
   eventSender.keyDown('S');
   eventSender.keyDown('T');
-  assert_equals(window.scrollY, 100);
-}, 'Type in the onscreen sticky input box should not scroll the page.');
+  const sticky_position = window.scrollY;
+
+ // The reference element is vertically in the position the sticky element would be if
+ // it were not shifted by its sticky position offset.
+ // We can use this to determine where the browser should scroll to move this unshifted
+ // input into view per spec.
+  var reference = document.getElementById('reference');
+  reference.focus();
+  window.scrollTo(0, 100);
+  eventSender.keyDown('T');
+  eventSender.keyDown('E');
+  eventSender.keyDown('S');
+  eventSender.keyDown('T');
+
+  assert_equals(sticky_position, window.scrollY);
+}, 'Type in the onscreen sticky input box should reset the scroll to unshifted position.');
 </script>
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-events.js b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-events.js
index 500736b6..39e18957 100644
--- a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-events.js
+++ b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-events.js
@@ -20,10 +20,13 @@
   function eventHandler(eventName, event) {
     switch (eventName) {
       case 'FrameAdded':
-      case 'FrameDetached':
         var frame = event.data;
         TestRunner.addResult(`    ${eventName} : ${frame.id}`);
         break;
+      case 'FrameDetached':
+        var frame = event.data.frame;
+        TestRunner.addResult(`    ${eventName} : ${frame.id}`);
+        break;
       case 'FrameNavigated':
       case 'MainFrameNavigated':
         var frame = event.data;
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/mixed-content-issue-creation-js-within-oopif.js b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/mixed-content-issue-creation-js-within-oopif.js
index cfca772d..389259c0 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/mixed-content-issue-creation-js-within-oopif.js
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/mixed-content-issue-creation-js-within-oopif.js
@@ -16,8 +16,6 @@
 
   dp.Target.onAttachedToTarget(async e => {
     const dp = session.createChild(e.params.sessionId).protocol;
-    await dp.Network.enable();
-    await dp.Audits.enable();
 
     // We expect to receive two issues, one for a speculative prefetch and another for the actual fetch.
     dp.Audits.onIssueAdded(issue => {
@@ -32,6 +30,9 @@
         eventReceived();
       }
     });
+
+    await dp.Network.enable();
+    await dp.Audits.enable();
   });
 
   await page.navigate('https://devtools.test:8443/inspector-protocol/resources/mixed-content-within-oopif.html');
diff --git a/third_party/blink/web_tests/wpt_internal/prerender/resources/background-sync.https.html b/third_party/blink/web_tests/wpt_internal/prerender/resources/background-sync.https.html
new file mode 100644
index 0000000..19463bdf
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/prerender/resources/background-sync.https.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="utils.js"></script>
+<script src="deferred-promise-utils.js"></script>
+<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
+<script>
+
+const params = new URLSearchParams(location.search);
+
+// The main test page (restriction-background-sync.https.html) loads the
+// initiator page, then the initiator page will prerender itself with the
+// `prerendering` parameter.
+const isPrerendering = params.has('prerendering');
+
+async function service_worker_install() {
+  const scope = "resources/";
+  const script = "background-sync.js";
+
+  const t = async_test("Test background sync");
+  const registration =
+      await service_worker_unregister_and_register(t, script, scope);
+  t.add_cleanup(() => registration.unregister());
+  await wait_for_state(t, registration.installing, 'activated');
+  return registration;
+}
+
+if (!isPrerendering) {
+  loadInitiatorPage();
+} else {
+  const prerenderEventCollector = new PrerenderEventCollector();
+  const promise = new Promise(async (resolve, reject) => {
+    try {
+      // TODO(crbug.com/1203619): The service worker registration is deferred in
+      // the prerendering. So, we need to test only periodicSync.register in
+      // this promise in order to test if it is deferred correctly. We will move
+      // the service worker installation out of this promise after its
+      // registration is granted.
+      const registration = await service_worker_install();
+      await registration.periodicSync.register(
+          'periodic', { minInterval: 1000 });
+      resolve();
+    } catch (e) {
+      reject(`periodicSync.register error: ${e.toString()}`);
+    }
+  });
+  prerenderEventCollector.start(promise, 'periodicSync.register');
+}
+
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/prerender/resources/background-sync.js b/third_party/blink/web_tests/wpt_internal/prerender/resources/background-sync.js
new file mode 100644
index 0000000..49ceb264
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/prerender/resources/background-sync.js
@@ -0,0 +1 @@
+// Do nothing.
diff --git a/third_party/blink/web_tests/wpt_internal/prerender/restriction-background-sync.https.html b/third_party/blink/web_tests/wpt_internal/prerender/restriction-background-sync.https.html
new file mode 100644
index 0000000..0fe1b5f
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/prerender/restriction-background-sync.https.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!--
+This file cannot be upstreamed to WPT until:
+* startPrerendering() usage is replaced with a WebDriver API
+* internals.setPermission() usage is replaced with a WebDriver API
+-->
+<title>Access to the Background Sync API is deferred</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/utils.js"></script>
+<body>
+<script>
+
+promise_test(async t => {
+  const bc = new BroadcastChannel('test-channel');
+  t.add_cleanup(_ => bc.close());
+
+  // We grant the permission here to make a more discerning test because
+  // periodicSync.register() waits until the permission is granted, which
+  // is deferred during prerendering so the test would trivially pass without
+  // the permission.
+  await internals.setPermission({name: 'periodic-background-sync'}, 'granted',
+                                location.origin, location.origin);
+
+  const gotMessage = new Promise(resolve => {
+    bc.addEventListener('message', e => {
+      resolve(e.data);
+    }, {
+      once: true
+    });
+  });
+  const url = `resources/background-sync.https.html`;
+  window.open(url, '_blank', 'noopener');
+
+  const result = await gotMessage;
+  const expected = [
+    {event: 'started waiting periodicSync.register',    prerendering: true},
+    {event: 'prerendering change',                      prerendering: false},
+    {event: 'finished waiting periodicSync.register',   prerendering: false},
+  ];
+  assert_equals(result.length, expected.length);
+  for (let i = 0; i < result.length; i++) {
+    assert_equals(result[i].event, expected[i].event, `event[${i}]`);
+    assert_equals(result[i].prerendering, expected[i].prerendering,
+      `prerendering[${i}]`);
+  }
+}, `The access to the Background Sync API should be deferred until the
+    prerendered page is activated`);
+
+</script>
+</body>
diff --git a/third_party/polymer/v3_0/BUILD.gn b/third_party/polymer/v3_0/BUILD.gn
index 05b7803..61e55085 100644
--- a/third_party/polymer/v3_0/BUILD.gn
+++ b/third_party/polymer/v3_0/BUILD.gn
@@ -72,6 +72,7 @@
 }
 
 ts_library("library") {
+  composite = true
   definitions = [
     "components-chromium/iron-a11y-announcer/iron-a11y-announcer.d.ts",
     "components-chromium/iron-a11y-keys-behavior/iron-a11y-keys-behavior.d.ts",
diff --git a/third_party/zlib/contrib/bench/zlib_bench.cc b/third_party/zlib/contrib/bench/zlib_bench.cc
index bc2f741..bd06ad3 100644
--- a/third_party/zlib/contrib/bench/zlib_bench.cc
+++ b/third_party/zlib/contrib/bench/zlib_bench.cc
@@ -15,7 +15,7 @@
  * Note this code can be compiled outside of the Chromium build system against
  * the system zlib (-lz) with g++ or clang++ as follows:
  *
- *   g++|clang++ -O3 -Wall -std=c++11 -lstdc++ -lz zlib_bench.cc
+ *   g++|clang++ -O3 -Wall -std=c++11 zlib_bench.cc -lstdc++ -lz
  */
 
 #include <algorithm>
@@ -306,11 +306,10 @@
   return *value >= 0 && *value <= 9;
 }
 
+const char* options = "gzip|zlib|raw [--compression 0:9] [--huffman|--rle]";
+
 void usage_exit(const char* program) {
-  printf(
-      "usage: %s gzip|zlib|raw [--compression 0:9] [--huffman|--rle] "
-      "files...\n",
-      program);
+  printf("usage: %s %s files...", program, options);
   exit(1);
 }
 
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 63cd69557..782904db 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -44553,8 +44553,6 @@
   <int value="-1899409297"
       label="ProcessSharingWithStrictSiteInstances:disabled"/>
   <int value="-1899342084" label="ArcGhostWindow:enabled"/>
-  <int value="-1898963163"
-      label="OmniboxKeywordSpaceTriggeringSetting:disabled"/>
   <int value="-1898386671" label="PasswordCheck:enabled"/>
   <int value="-1896871201" label="CrossOriginOpenerPolicyReporting:enabled"/>
   <int value="-1896733769" label="CheckOfflineCapability:disabled"/>
@@ -46100,7 +46098,6 @@
   <int value="-600726805" label="DeprecateMenagerieAPI:disabled"/>
   <int value="-599932554" label="DoodlesOnLocalNtp:disabled"/>
   <int value="-599005750" label="ScanningUI:disabled"/>
-  <int value="-598191408" label="OmniboxKeywordSpaceTriggeringSetting:enabled"/>
   <int value="-598050737" label="disable-es3-apis"/>
   <int value="-596822155" label="AppManagementIntentSettings:enabled"/>
   <int value="-596337171" label="disable-ash-sidebar"/>
@@ -46127,6 +46124,7 @@
   <int value="-570889908" label="CCTModuleDexLoading:enabled"/>
   <int value="-568448085" label="SharedClipboardReceiver:disabled"/>
   <int value="-567920515" label="disable-experimental-hotwording"/>
+  <int value="-567743697" label="EnableInputNoiseCancellationUi:enabled"/>
   <int value="-563980787" label="disable-webrtc"/>
   <int value="-563600258" label="PhotoPickerVideoSupport:disabled"/>
   <int value="-562771426" label="InstantStart:disabled"/>
@@ -47935,6 +47933,7 @@
   <int value="1061947013" label="OmniboxDeferredKeyboardPopup:disabled"/>
   <int value="1062357243" label="remember-cert-error-decisions"/>
   <int value="1064288458" label="OfflineRecentPages:enabled"/>
+  <int value="1065547630" label="EnableInputNoiseCancellationUi:disabled"/>
   <int value="1067618884" label="enable-experimental-input-view-features"/>
   <int value="1067990299" label="enable-ui-devtools"/>
   <int value="1069325321" label="CrostiniGpuSupport:enabled"/>
diff --git a/tools/metrics/histograms/histograms_xml/apps/histograms.xml b/tools/metrics/histograms/histograms_xml/apps/histograms.xml
index 34dd1cf..3ab37a8 100644
--- a/tools/metrics/histograms/histograms_xml/apps/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/apps/histograms.xml
@@ -21,6 +21,33 @@
 
 <histograms>
 
+<variants name="AppType">
+  <variant name="Arc" summary="Android apps"/>
+  <variant name="Borealis" summary="Borealis apps"/>
+  <variant name="BuiltIn" summary="BuiltIn apps"/>
+  <variant name="ChromeApp" summary="Chrome apps"/>
+  <variant name="ChromeBrowser" summary="Chrome browsers"/>
+  <variant name="Crostini" summary="Crostini apps"/>
+  <variant name="MacOs" summary="MacOs apps"/>
+  <variant name="PluginVm" summary="Plugin VM app"/>
+  <variant name="RemoteApp" summary="Remote apps"/>
+  <variant name="StandaloneBrowser" summary="Standalone browsers"/>
+  <variant name="SystemWebApp" summary="System web apps"/>
+  <variant name="WebApp" summary="Web apps"/>
+</variants>
+
+<histogram name="Apps.ActivatedCount.{AppType}" units="ms"
+    expires_after="2021-10-28">
+  <owner>dominickn@chromium.org</owner>
+  <owner>nancylingwang@chromium.org</owner>
+  <summary>
+    Recorded the app window activated times for {AppType} in Chrome OS. This is
+    logged when more than 24 hours pass after last log, or during the system
+    startup phase if more than 24 hours passed after last log.
+  </summary>
+  <token key="AppType" variants="AppType"/>
+</histogram>
+
 <histogram name="Apps.AppInfoDialog.CreateExtensionShortcutSuccess"
     enum="Boolean" expires_after="M95">
   <owner>dmurph@chromium.org</owner>
@@ -736,6 +763,17 @@
   </summary>
 </histogram>
 
+<histogram name="Apps.AppList.ZeroStateDriveProvider.Relevance" units="score"
+    expires_after="2021-10-04">
+  <owner>wrong@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
+  <owner>thanhdng@chromium.org</owner>
+  <summary>
+    Relevance score for a zero state Drive result in the results list. Logged
+    whenever ItemSuggest is queried, once for each zero-state result created.
+  </summary>
+</histogram>
+
 <histogram name="Apps.AppList.ZeroStateFileProvider.Latency" units="ms"
     expires_after="2021-09-19">
   <owner>wrong@chromium.org</owner>
@@ -759,6 +797,17 @@
   </summary>
 </histogram>
 
+<histogram name="Apps.AppList.ZeroStateFileProvider.Relevance" units="score"
+    expires_after="2021-10-04">
+  <owner>wrong@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
+  <owner>thanhdng@chromium.org</owner>
+  <summary>
+    Relevance score for a zero state file result in suggestion chips or the
+    results list. Logged once each time zero state is loaded.
+  </summary>
+</histogram>
+
 <histogram name="Apps.AppList.ZeroStateResults.LaunchedItemType"
     enum="ZeroStateResultType" expires_after="2021-10-17">
   <owner>wrong@chromium.org</owner>
@@ -1365,19 +1414,7 @@
     startup phase if more than 24 hours passed after last log. This histogram is
     capped at 1000; values above this go into the overflow bucket.
   </summary>
-  <token key="AppType">
-    <variant name="Arc" summary="Android apps"/>
-    <variant name="Borealis" summary="Borealis apps"/>
-    <variant name="BuiltIn" summary="BuiltIn apps"/>
-    <variant name="ChromeApp" summary="Chrome apps"/>
-    <variant name="Crostini" summary="Crostini apps"/>
-    <variant name="MacOs" summary="MacOs apps"/>
-    <variant name="PluginVm" summary="Plugin VM app"/>
-    <variant name="RemoteApp" summary="Remote apps"/>
-    <variant name="StandaloneBrowser" summary="Standalone browser"/>
-    <variant name="SystemWebApp" summary="System web apps"/>
-    <variant name="WebApp" summary="Web apps"/>
-  </token>
+  <token key="AppType" variants="AppType"/>
 </histogram>
 
 <histogram name="Apps.AppShimErrorVersion" units="units" expires_after="M78">
@@ -1979,20 +2016,7 @@
     when more than 24 hours pass after last log, or during the system startup
     phase if more than 24 hours passed after last log.
   </summary>
-  <token key="AppType">
-    <variant name="Arc" summary="Android apps"/>
-    <variant name="Borealis" summary="Borealis apps"/>
-    <variant name="BuiltIn" summary="BuiltIn apps"/>
-    <variant name="ChromeApp" summary="Chrome apps"/>
-    <variant name="ChromeBrowser" summary="Chrome browser"/>
-    <variant name="Crostini" summary="Crostini apps"/>
-    <variant name="MacOs" summary="MacOs apps"/>
-    <variant name="PluginVm" summary="Plugin VM app"/>
-    <variant name="RemoteApp" summary="Remote apps"/>
-    <variant name="StandaloneBrowser" summary="Standalone browser"/>
-    <variant name="SystemWebApp" summary="System web apps"/>
-    <variant name="WebApp" summary="Web apps"/>
-  </token>
+  <token key="AppType" variants="AppType"/>
 </histogram>
 
 <histogram name="Apps.ScrollableShelf.AnimationSmoothness" units="%"
@@ -2106,6 +2130,17 @@
   </summary>
 </histogram>
 
+<histogram name="Apps.UsageTime.{AppType}" units="ms"
+    expires_after="2021-10-28">
+  <owner>dominickn@chromium.org</owner>
+  <owner>nancylingwang@chromium.org</owner>
+  <summary>
+    Records the amount of time that {AppType} were used in the last five minutes
+    on Chrome OS. This is logged every five minutes.
+  </summary>
+  <token key="AppType" variants="AppType"/>
+</histogram>
+
 </histograms>
 
 </histogram-configuration>
diff --git a/tools/perf/benchmark.csv b/tools/perf/benchmark.csv
index 74cbbf7..4058d27 100644
--- a/tools/perf/benchmark.csv
+++ b/tools/perf/benchmark.csv
@@ -3,7 +3,6 @@
 Googlers can view additional information about internal perf infrastructure at,https://goto.google.com/chrome-benchmarking-sheet
 Benchmark name,Individual owners,Component,Documentation,Tags
 UNSCHEDULED_blink_perf.performance_apis,yoavweiss@chromium.org,Blink>PerformanceAPIs,https://bit.ly/blink-perf-benchmarks,all
-UNSCHEDULED_blink_perf.sanitizer-api,lyf@chromium.org,Blink>Security>SanitizerAPI,https://bit.ly/blink-perf-benchmarks,all
 UNSCHEDULED_blink_perf.service_worker,"shimazu@chromium.org, falken@chromium.org, ting.shao@intel.com",Blink>ServiceWorker,https://bit.ly/blink-perf-benchmarks,all
 UNSCHEDULED_loading.mbi,blink-isolation-dev@chromium.org,Blink>Internals>Modularization,https://bit.ly/loading-benchmarks,"all,many_agents"
 UNSCHEDULED_v8.loading_desktop,"mythria@chromium.org, tmrts@chromium.org, almuthanna@chromium.org",Blink>JavaScript,https://bit.ly/system-health-v8-benchmarks,"2016,2018,2019,2020,all,emerging_market,health_check,international,javascript_heavy"
@@ -20,6 +19,7 @@
 blink_perf.owp_storage,dmurph@chromium.org,Blink>Storage,https://bit.ly/blink-perf-benchmarks,all
 blink_perf.paint,"pdr@chromium.org, wangxianzhu@chromium.org",Blink>Paint,https://bit.ly/blink-perf-benchmarks,all
 blink_perf.parser,"jbroman@chromium.org, yukishiino@chromium.org, haraken@chromium.org",Blink>Bindings,https://bit.ly/blink-perf-benchmarks,all
+blink_perf.sanitizer-api,lyf@chromium.org,Blink>Security>SanitizerAPI,https://bit.ly/blink-perf-benchmarks,all
 blink_perf.shadow_dom,masonf@chromium.org,Blink>DOM>ShadowDOM,https://bit.ly/blink-perf-benchmarks,all
 blink_perf.svg,"fs@opera.com, pdr@chromium.org",Blink>SVG,https://bit.ly/blink-perf-benchmarks,all
 blink_perf.webaudio,"hongchan@chromium.org, rtoy@chromium.org",Blink>WebAudio,https://bit.ly/blink-perf-benchmarks,all
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py
index 0c4cf31..0da0ba80 100644
--- a/tools/perf/benchmarks/blink_perf.py
+++ b/tools/perf/benchmarks/blink_perf.py
@@ -650,7 +650,7 @@
 
   @classmethod
   def Name(cls):
-    return 'UNSCHEDULED_blink_perf.sanitizer-api'
+    return 'blink_perf.sanitizer-api'
 
   def SetExtraBrowserOptions(self, options):
     options.AppendExtraBrowserArgs([
diff --git a/tools/perf/core/bot_platforms.py b/tools/perf/core/bot_platforms.py
index fb23fee..5912ab92 100644
--- a/tools/perf/core/bot_platforms.py
+++ b/tools/perf/core/bot_platforms.py
@@ -222,7 +222,11 @@
 OFFICIAL_BENCHMARK_CONFIGS = PerfSuite(
     [_GetBenchmarkConfig(b.Name()) for b in OFFICIAL_BENCHMARKS])
 # power.mobile requires special hardware.
-OFFICIAL_BENCHMARK_CONFIGS = OFFICIAL_BENCHMARK_CONFIGS.Remove(['power.mobile'])
+# only run blink_perf.sanitizer-api on linux-perf.
+OFFICIAL_BENCHMARK_CONFIGS = OFFICIAL_BENCHMARK_CONFIGS.Remove([
+    'power.mobile',
+    'blink_perf.sanitizer-api',
+])
 # TODO(crbug.com/965158): Remove OFFICIAL_BENCHMARK_NAMES once sharding
 # scripts are no longer using it.
 OFFICIAL_BENCHMARK_NAMES = frozenset(
@@ -307,6 +311,8 @@
 _LINUX_BENCHMARK_CONFIGS = PerfSuite(OFFICIAL_BENCHMARK_CONFIGS).Remove([
     'blink_perf.display_locking',
     'v8.runtime_stats.top_25',
+]).Add([
+    'blink_perf.sanitizer-api',
 ])
 _LINUX_EXECUTABLE_CONFIGS = frozenset([
     # TODO(crbug.com/811766): Add views_perftests.
diff --git a/tools/perf/core/results_dashboard.py b/tools/perf/core/results_dashboard.py
index 013abc75c..7923393 100755
--- a/tools/perf/core/results_dashboard.py
+++ b/tools/perf/core/results_dashboard.py
@@ -147,11 +147,6 @@
   if max_bytes:
     add_diagnostics_args.extend(['--max_bytes', max_bytes])
 
-  stdio_url = _MakeStdioUrl(test_name, buildername, buildnumber)
-  if stdio_url:
-    add_diagnostics_args.extend(['--log_urls_k', 'Buildbot stdio'])
-    add_diagnostics_args.extend(['--log_urls_v', stdio_url])
-
   build_status_url = _MakeBuildStatusUrl(
       project, buildbucket, buildername, buildnumber)
   if build_status_url:
@@ -223,8 +218,6 @@
       # calculated revision column values so that these can be overwritten.
       result['supplemental_columns'].update(revision_columns)
       result['supplemental_columns'].update(
-          _GetStdioUriColumn(test_name, buildername, buildnumber))
-      result['supplemental_columns'].update(
           _GetBuildStatusUriColumn(project, buildbucket, buildername,
                                    buildnumber))
       result['supplemental_columns'].update(supplemental_columns)
@@ -281,8 +274,6 @@
       supplemental[key.replace('a_', '', 1)] = supplemental_dict[key]
 
   supplemental.update(
-      _GetStdioUriColumn(test_name, buildername, buildnumber))
-  supplemental.update(
       _GetBuildStatusUriColumn(project, buildbucket, buildername, buildnumber))
 
   # TODO(sullivan): The android recipe sends "test_name.reference"
@@ -304,19 +295,6 @@
   return fields
 
 
-def _MakeStdioUrl(test_name, buildername, buildnumber):
-  """Returns a string url pointing to buildbot stdio log."""
-  # TODO(780914): Link to logdog instead of buildbot.
-  if not buildername or not buildnumber:
-    return ''
-
-  return '%sbuilders/%s/builds/%s/steps/%s/logs/stdio' % (
-      _GetBuildBotUrl(),
-      six.moves.urllib.parse.quote(buildername),
-      six.moves.urllib.parse.quote(str(buildnumber)),
-      six.moves.urllib.parse.quote(test_name))
-
-
 def _MakeBuildStatusUrl(project, buildbucket, buildername, buildnumber):
   if not (buildername and buildnumber):
     return None
@@ -331,14 +309,6 @@
       six.moves.urllib.parse.quote(str(buildnumber)))
 
 
-def _GetStdioUriColumn(test_name, buildername, buildnumber):
-  """Gets a supplemental column containing buildbot stdio link."""
-  url = _MakeStdioUrl(test_name, buildername, buildnumber)
-  if not url:
-    return {}
-  return _CreateLinkColumn('stdio_uri', 'Buildbot stdio', url)
-
-
 def _GetBuildStatusUriColumn(project, buildbucket, buildername, buildnumber):
   """Gets a supplemental column containing buildbot status link."""
   url = _MakeBuildStatusUrl(project, buildbucket, buildername, buildnumber)
@@ -352,12 +322,6 @@
   return {'a_' + name: '[%s](%s)' % (label, url)}
 
 
-def _GetBuildBotUrl():
-  """Gets the buildbot URL which contains hostname and master name."""
-  return os.environ.get('BUILDBOT_BUILDBOTURL',
-                        'http://build.chromium.org/p/chromium/')
-
-
 def _GetTimestamp():
   """Get the Unix timestamp for the current time."""
   return int(calendar.timegm(datetime.datetime.utcnow().utctimetuple()))
diff --git a/tools/perf/core/shard_maps/linux-perf_map.json b/tools/perf/core/shard_maps/linux-perf_map.json
index 2dd0a051..e0dceb6 100644
--- a/tools/perf/core/shard_maps/linux-perf_map.json
+++ b/tools/perf/core/shard_maps/linux-perf_map.json
@@ -92,6 +92,9 @@
             "blink_perf.parser": {
                 "abridged": false
             },
+            "blink_perf.sanitizer-api": {
+                "abridged": false
+            },
             "blink_perf.shadow_dom": {
                 "abridged": false
             },
diff --git a/tools/perf/core/test_data/benchmarks_to_shard.json b/tools/perf/core/test_data/benchmarks_to_shard.json
index 7605a47..c3374be5 100644
--- a/tools/perf/core/test_data/benchmarks_to_shard.json
+++ b/tools/perf/core/test_data/benchmarks_to_shard.json
@@ -51,7 +51,7 @@
     "stories": [
       "sanitizer.html"
     ],
-    "name": "UNSCHEDULED_blink_perf.sanitizer-api"
+    "name": "blink_perf.sanitizer-api"
   },
   {
     "repeat": 1,
diff --git a/tools/typescript/ts_library.gni b/tools/typescript/ts_library.gni
index 9b137f28..c4749de 100644
--- a/tools/typescript/ts_library.gni
+++ b/tools/typescript/ts_library.gni
@@ -34,6 +34,11 @@
       out_dir = invoker.out_dir
     }
 
+    composite = false
+    if (defined(invoker.composite)) {
+      composite = invoker.composite
+    }
+
     if (defined(in_files)) {
       outputs += [ "$target_gen_dir/tsconfig.manifest" ]
       foreach(_source, in_files) {
@@ -41,10 +46,11 @@
         _dirname =
             rebase_path(get_path_info(_source, "gen_dir"), target_gen_dir)
         _filename = get_path_info(_source, "name")
-        outputs += [
-          "$out_dir/$_dirname/$_filename.js",
-          "$out_dir/$_dirname/$_filename.d.ts",
-        ]
+        outputs += [ "$out_dir/$_dirname/$_filename.js" ]
+
+        if (composite) {
+          outputs += [ "$out_dir/$_dirname/$_filename.d.ts" ]
+        }
       }
     }
 
@@ -86,6 +92,10 @@
       ]
     }
 
+    if (composite) {
+      args += [ "--composite" ]
+    }
+
     if (defined(extra_deps)) {
       if (!defined(deps)) {
         deps = []
diff --git a/tools/typescript/ts_library.py b/tools/typescript/ts_library.py
index 124e0ad..aab178c1 100644
--- a/tools/typescript/ts_library.py
+++ b/tools/typescript/ts_library.py
@@ -37,6 +37,7 @@
   parser.add_argument('--tsconfig_base')
   parser.add_argument('--in_files', nargs='*')
   parser.add_argument('--definitions', nargs='*')
+  parser.add_argument('--composite', action='store_true')
   args = parser.parse_args(argv)
 
   root_dir = os.path.relpath(args.root_dir, args.gen_dir)
@@ -54,6 +55,10 @@
   tsconfig['compilerOptions']['rootDir'] = root_dir
   tsconfig['compilerOptions']['outDir'] = out_dir
 
+  if args.composite:
+    tsconfig['compilerOptions']['composite'] = True
+    tsconfig['compilerOptions']['declaration'] = True
+
   tsconfig['files'] = []
   if args.in_files is not None:
     # Source .ts files are always resolved as being relative to |root_dir|.
diff --git a/tools/typescript/ts_library_test.py b/tools/typescript/ts_library_test.py
index dcda181e..c564c4b 100755
--- a/tools/typescript/ts_library_test.py
+++ b/tools/typescript/ts_library_test.py
@@ -49,6 +49,7 @@
         'foo.ts',
         '--definitions',
         'legacy_file.d.ts',
+        '--composite',
     ])
     return gen_dir
 
@@ -94,7 +95,6 @@
 
   def _assert_project2_output(self, gen_dir):
     files = [
-        'bar.d.ts',
         'bar.js',
         'tsconfig.json',
         'tsconfig.manifest',
@@ -103,6 +103,9 @@
     for f in files:
       self.assertTrue(os.path.exists(os.path.join(gen_dir, f)), f)
 
+    dts_file = 'bar.d.ts'
+    self.assertFalse(os.path.exists(os.path.join(gen_dir, dts_file)), dts_file)
+
   # Builds project3, which includes only definition files.
   def _build_project3(self):
     gen_dir = os.path.join(self._out_folder, 'project3')
@@ -116,6 +119,7 @@
         gen_dir,
         '--definitions',
         '../../tests/project3/baz.d.ts',
+        '--composite',
     ])
     return gen_dir
 
diff --git a/tools/typescript/tsconfig_base.json b/tools/typescript/tsconfig_base.json
index 89e9678..cba0a73 100644
--- a/tools/typescript/tsconfig_base.json
+++ b/tools/typescript/tsconfig_base.json
@@ -6,8 +6,7 @@
     "noEmitOnError": true,
     "pretty": true,
 
-    "composite": true,
-    "declaration": true,
+    "incremental": true,
 
     "forceConsistentCasingInFileNames": true,
     "noFallthroughCasesInSwitch": true,
diff --git a/ui/base/x/x11_util.cc b/ui/base/x/x11_util.cc
index 2efcfb9f..c4b92b7 100644
--- a/ui/base/x/x11_util.cc
+++ b/ui/base/x/x11_util.cc
@@ -719,10 +719,10 @@
     return false;
 
   std::vector<x11::Window> windows;
-  std::vector<x11::Window>::iterator iter;
   if (depth == 0) {
     XMenuList::GetInstance()->InsertMenuWindows(&windows);
     // Enumerate the menus first.
+    std::vector<x11::Window>::iterator iter;
     for (iter = windows.begin(); iter != windows.end(); iter++) {
       if (delegate->ShouldStopIterating(*iter))
         return true;
@@ -737,7 +737,8 @@
 
   // XQueryTree returns the children of |window| in bottom-to-top order, so
   // reverse-iterate the list to check the windows from top-to-bottom.
-  for (iter = windows.begin(); iter != windows.end(); iter++) {
+  std::vector<x11::Window>::reverse_iterator iter;
+  for (iter = windows.rbegin(); iter != windows.rend(); iter++) {
     if (IsWindowNamed(*iter) && delegate->ShouldStopIterating(*iter))
       return true;
   }
@@ -747,7 +748,7 @@
   // loop because the recursion and call to XQueryTree are expensive and is only
   // needed for a small number of cases.
   if (++depth <= max_depth) {
-    for (iter = windows.begin(); iter != windows.end(); iter++) {
+    for (iter = windows.rbegin(); iter != windows.rend(); iter++) {
       if (EnumerateChildren(delegate, *iter, max_depth, depth))
         return true;
     }
diff --git a/ui/file_manager/file_manager/background/js/file_operation_util.js b/ui/file_manager/file_manager/background/js/file_operation_util.js
index d6e522ce..7f90fc52 100644
--- a/ui/file_manager/file_manager/background/js/file_operation_util.js
+++ b/ui/file_manager/file_manager/background/js/file_operation_util.js
@@ -28,8 +28,8 @@
  *
  * @param {DirectoryEntry} root The root of the filesystem to search.
  * @param {string} path The path to be resolved.
- * @return {Promise} Promise fulfilled with the resolved entry, or rejected with
- *     FileError.
+ * @return {!Promise<DirectoryEntry|FileEntry>} Promise fulfilled with the
+ *     resolved entry, or rejected with FileError.
  */
 fileOperationUtil.resolvePath = (root, path) => {
   if (path === '' || path === '/') {
@@ -61,7 +61,7 @@
  *     deduplicated path on success.
  * @param {function(FileOperationError)=} opt_errorCallback
  *     Callback run on error.
- * @return {Promise} Promise fulfilled with available path.
+ * @return {!Promise<string>} Promise fulfilled with available path.
  */
 fileOperationUtil.deduplicatePath =
     (dirEntry, relativePath, opt_successCallback, opt_errorCallback) => {
@@ -524,35 +524,6 @@
     };
 
 /**
- * Thin wrapper of chrome.fileManagerPrivate.zipSelection to adapt its
- * interface similar to copyTo().
- *
- * @param {!Array<!Entry>} sources The array of entries to be archived.
- * @param {!DirectoryEntry} parent The entry of the destination directory.
- * @param {string} newName The name of the archive to be created.
- * @param {function(FileEntry)} successCallback Callback invoked when the
- *     operation is successfully done with the entry of the created archive.
- * @param {function(DOMError)} errorCallback Callback invoked when an error
- *     is found.
- */
-fileOperationUtil.zipSelection =
-    (sources, parent, newName, successCallback, errorCallback) => {
-      chrome.fileManagerPrivate.zipSelection(
-          sources, parent, newName, success => {
-            if (!success) {
-              // Failed to create a zip archive.
-              errorCallback(
-                  util.createDOMError(util.FileError.INVALID_MODIFICATION_ERR));
-              return;
-            }
-
-            // Returns the created entry via callback.
-            parent.getFile(
-                newName, {create: false}, successCallback, errorCallback);
-          });
-    };
-
-/**
  * A record of a queued copy operation.
  *
  * Multiple copy operations may be queued at any given time.  Additional
@@ -1183,31 +1154,28 @@
    * @param {function()} callback Called when the initialize is completed.
    */
   initialize(callback) {
+    this.initialize_().finally(callback);
+  }
+
+  /**
+   * @private
+   */
+  async initialize_() {
+    this.totalBytes = 0;
     const resolvedEntryMap = {};
-    const group = new AsyncUtil.Group();
-    for (let i = 0; i < this.sourceEntries.length; i++) {
-      group.add(function(index, callback) {
-        fileOperationUtil.resolveRecursively_(
-            this.sourceEntries[index], entries => {
-              for (let j = 0; j < entries.length; j++) {
-                resolvedEntryMap[entries[j].toURL()] = entries[j];
-              }
-              callback();
-            }, callback);
-      }.bind(this, i));
+
+    for (const sourceEntry of assert(this.sourceEntries)) {
+      const resolvedEntries = await new Promise(
+          (resolve, reject) => fileOperationUtil.resolveRecursively_(
+              sourceEntry, resolve, reject));
+      for (const resolvedEntry of resolvedEntries) {
+        this.totalBytes += resolvedEntry.size;
+        resolvedEntryMap[resolvedEntry.toURL()] = resolvedEntry;
+      }
     }
 
-    group.run(() => {
-      // For zip archiving, all the entries are processed at once.
-      this.processingEntries = [resolvedEntryMap];
-
-      this.totalBytes = 0;
-      for (const url in resolvedEntryMap) {
-        this.totalBytes += resolvedEntryMap[url].size;
-      }
-
-      callback();
-    });
+    // For ZIP archiving, all the entries are processed at once.
+    this.processingEntries = [resolvedEntryMap];
   }
 
   /**
@@ -1222,41 +1190,65 @@
    * @override
    */
   run(entryChangedCallback, progressCallback, successCallback, errorCallback) {
-    // TODO(hidehiko): we should localize the name.
+    // TODO(fdegros) Per-entry zip progress update with accurate byte count.
+    // For now just set processedBytes to 0 so that it is not full until
+    // the zip operation is done.
+    this.processedBytes = 0;
+    progressCallback();
+
+    this.run_().then(
+        entry => {
+          this.processedBytes = this.totalBytes;
+          entryChangedCallback(util.EntryChangedKind.CREATED, entry);
+          successCallback();
+        },
+        error => errorCallback(new FileOperationError(
+            util.FileOperationErrorType.FILESYSTEM_ERROR,
+            /** @type DOMError */ (error))));
+  }
+
+  /**
+   * Runs a zip file creation task.
+   *
+   * @return {!Promise<FileEntry>} Promise fulfilled with the created archive
+   *     entry, or rejected with a DOMError.
+   * @private
+   */
+  async run_() {
+    // TODO(fdegros) Localize the name.
     let destName = 'Archive';
+
+    // If there is only one entry to zip, use this entry's name for the ZIP
+    // filename.
     if (this.sourceEntries.length == 1) {
       const entryName = this.sourceEntries[0].name;
       const i = entryName.lastIndexOf('.');
       destName = ((i < 0) ? entryName : entryName.substr(0, i));
     }
 
-    fileOperationUtil.deduplicatePath(
-        this.targetDirEntry, destName + '.zip', destPath => {
-          // TODO: per-entry zip progress update with accurate byte count.
-          // For now just set completedBytes to 0 so that it is not full until
-          // the zip operatoin is done.
-          this.processedBytes = 0;
-          progressCallback();
+    const destPath = await fileOperationUtil.deduplicatePath(
+        this.targetDirEntry, destName + '.zip');
 
-          // The number of elements in processingEntries is 1. See also
-          // initialize().
-          const entries = [];
-          for (const url in this.processingEntries[0]) {
-            entries.push(this.processingEntries[0][url]);
-          }
+    // The number of elements in processingEntries is 1. See also
+    // initialize().
+    const entries = [];
+    for (const url in this.processingEntries[0]) {
+      entries.push(this.processingEntries[0][url]);
+    }
 
-          fileOperationUtil.zipSelection(
-              entries, this.zipBaseDirEntry, destPath,
-              entry => {
-                this.processedBytes = this.totalBytes;
-                entryChangedCallback(util.EntryChangedKind.CREATED, entry);
-                successCallback();
-              },
-              error => {
-                errorCallback(new FileOperationError(
-                    util.FileOperationErrorType.FILESYSTEM_ERROR, error));
-              });
-        }, errorCallback);
+    const success = await new Promise(
+        resolve => chrome.fileManagerPrivate.zipSelection(
+            entries, this.zipBaseDirEntry, destPath, resolve));
+
+    if (!success) {
+      // Cannot create ZIP archive.
+      throw util.createDOMError(util.FileError.INVALID_MODIFICATION_ERR);
+    }
+
+    // Get the created entry.
+    return new Promise(
+        (resolve, reject) => this.zipBaseDirEntry.getFile(
+            destPath, {create: false}, resolve, reject));
   }
 };
 
diff --git a/ui/views/animation/ink_drop.cc b/ui/views/animation/ink_drop.cc
index c4e73292..db36425 100644
--- a/ui/views/animation/ink_drop.cc
+++ b/ui/views/animation/ink_drop.cc
@@ -14,30 +14,48 @@
 
 namespace views {
 
+namespace {
+
+// TODO(pbos): Remove this by changing the constructor parameters to
+// InkDropImpl.
+std::unique_ptr<InkDrop> CreateInkDropImpl(
+    InkDropHostView* host,
+    InkDropImpl::AutoHighlightMode auto_highlight_mode,
+    bool highlight_on_hover,
+    bool highlight_on_focus) {
+  auto ink_drop = std::make_unique<InkDropImpl>(host, host->size());
+  ink_drop->SetAutoHighlightMode(auto_highlight_mode);
+  ink_drop->SetShowHighlightOnHover(highlight_on_hover);
+  ink_drop->SetShowHighlightOnFocus(highlight_on_focus);
+  return ink_drop;
+}
+
+}  // namespace
+
 InkDrop::~InkDrop() = default;
 
 std::unique_ptr<InkDrop> InkDrop::CreateInkDropForSquareRipple(
     InkDropHostView* host,
     bool highlight_on_hover,
     bool highlight_on_focus) {
-  auto ink_drop = std::make_unique<InkDropImpl>(host, host->size());
-  ink_drop->SetAutoHighlightMode(
-      InkDropImpl::AutoHighlightMode::HIDE_ON_RIPPLE);
-  ink_drop->SetShowHighlightOnHover(highlight_on_hover);
-  ink_drop->SetShowHighlightOnFocus(highlight_on_focus);
-  return ink_drop;
+  return CreateInkDropImpl(host, InkDropImpl::AutoHighlightMode::HIDE_ON_RIPPLE,
+                           highlight_on_hover, highlight_on_focus);
 }
 
 std::unique_ptr<InkDrop> InkDrop::CreateInkDropForFloodFillRipple(
     InkDropHostView* host,
     bool highlight_on_hover,
     bool highlight_on_focus) {
-  auto ink_drop = std::make_unique<InkDropImpl>(host, host->size());
-  ink_drop->SetAutoHighlightMode(
-      InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE);
-  ink_drop->SetShowHighlightOnHover(highlight_on_hover);
-  ink_drop->SetShowHighlightOnFocus(highlight_on_focus);
-  return ink_drop;
+  return CreateInkDropImpl(host, InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE,
+                           highlight_on_hover, highlight_on_focus);
+}
+
+std::unique_ptr<InkDrop> InkDrop::CreateInkDropWithoutAutoHighlight(
+    InkDropHostView* host,
+    bool highlight_on_hover,
+    bool highlight_on_focus) {
+  return CreateInkDropImpl(host, InkDropImpl::AutoHighlightMode::NONE,
+                           highlight_on_hover, highlight_on_focus);
 }
 
 void InkDrop::AddObserver(InkDropObserver* observer) {
diff --git a/ui/views/animation/ink_drop.h b/ui/views/animation/ink_drop.h
index bd8d4cf7..f892547 100644
--- a/ui/views/animation/ink_drop.h
+++ b/ui/views/animation/ink_drop.h
@@ -45,6 +45,12 @@
       bool highlight_on_hover = true,
       bool highlight_on_focus = false);
 
+  // Create an InkDrop whose highlight does not react to its ripple.
+  static std::unique_ptr<InkDrop> CreateInkDropWithoutAutoHighlight(
+      InkDropHostView* host,
+      bool highlight_on_hover = true,
+      bool highlight_on_focus = false);
+
   // Called by ink drop hosts when their size is changed.
   virtual void HostSizeChanged(const gfx::Size& new_size) = 0;
 
diff --git a/ui/views/controls/button/checkbox.cc b/ui/views/controls/button/checkbox.cc
index c39662a..c9a39c2 100644
--- a/ui/views/controls/button/checkbox.cc
+++ b/ui/views/controls/button/checkbox.cc
@@ -154,10 +154,8 @@
 }
 
 std::unique_ptr<InkDrop> Checkbox::CreateInkDrop() {
-  auto ink_drop = std::make_unique<InkDropImpl>(this, size());
-  ink_drop->SetAutoHighlightMode(InkDropImpl::AutoHighlightMode::NONE);
-  ink_drop->SetShowHighlightOnHover(false);
-  return ink_drop;
+  return views::InkDrop::CreateInkDropWithoutAutoHighlight(
+      this, /*highlight_on_hover=*/false);
 }
 
 std::unique_ptr<InkDropRipple> Checkbox::CreateInkDropRipple() const {
diff --git a/ui/views/controls/button/image_button.cc b/ui/views/controls/button/image_button.cc
index c991b5b..0505a98d 100644
--- a/ui/views/controls/button/image_button.cc
+++ b/ui/views/controls/button/image_button.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/strings/utf_string_conversions.h"
+#include "base/trace_event/trace_event.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/gfx/animation/throb_animation.h"
diff --git a/ui/views/controls/webview/webview.cc b/ui/views/controls/webview/webview.cc
index 9cb29421..2f4e77f 100644
--- a/ui/views/controls/webview/webview.cc
+++ b/ui/views/controls/webview/webview.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/no_destructor.h"
+#include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "content/public/browser/browser_accessibility_state.h"
 #include "content/public/browser/browser_context.h"
diff --git a/ui/views/window/frame_caption_button.cc b/ui/views/window/frame_caption_button.cc
index c1e83ff6..15798487 100644
--- a/ui/views/window/frame_caption_button.cc
+++ b/ui/views/window/frame_caption_button.cc
@@ -186,10 +186,8 @@
 }
 
 std::unique_ptr<views::InkDrop> FrameCaptionButton::CreateInkDrop() {
-  auto ink_drop = std::make_unique<views::InkDropImpl>(this, size());
-  ink_drop->SetAutoHighlightMode(views::InkDropImpl::AutoHighlightMode::NONE);
-  ink_drop->SetShowHighlightOnHover(false);
-  return ink_drop;
+  return views::InkDrop::CreateInkDropWithoutAutoHighlight(
+      this, /*highlight_on_hover=*/false);
 }
 
 std::unique_ptr<views::InkDropRipple> FrameCaptionButton::CreateInkDropRipple()
diff --git a/ui/webui/resources/BUILD.gn b/ui/webui/resources/BUILD.gn
index 0e6128c..727a6377 100644
--- a/ui/webui/resources/BUILD.gn
+++ b/ui/webui/resources/BUILD.gn
@@ -136,6 +136,7 @@
 ts_library("library") {
   root_dir = preprocessed_folder
   out_dir = preprocessed_folder
+  composite = true
   in_files = [
     "js/cr/world.ts",
     "js/hello_world.ts",
diff --git a/ui/wm/core/compound_event_filter.cc b/ui/wm/core/compound_event_filter.cc
index 4938b32..2ee6865 100644
--- a/ui/wm/core/compound_event_filter.cc
+++ b/ui/wm/core/compound_event_filter.cc
@@ -8,6 +8,7 @@
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
+#include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/client/drag_drop_client.h"
 #include "ui/aura/env.h"
@@ -75,6 +76,30 @@
   }
 }
 
+gfx::NativeCursor CompoundEventFilter::NoResizeCursorForWindowComponent(
+    int window_component) {
+  switch (window_component) {
+    case HTBOTTOM:
+      return ui::mojom::CursorType::kNorthSouthNoResize;
+    case HTBOTTOMLEFT:
+      return ui::mojom::CursorType::kNorthEastSouthWestNoResize;
+    case HTBOTTOMRIGHT:
+      return ui::mojom::CursorType::kNorthWestSouthEastNoResize;
+    case HTLEFT:
+      return ui::mojom::CursorType::kEastWestNoResize;
+    case HTRIGHT:
+      return ui::mojom::CursorType::kEastWestNoResize;
+    case HTTOP:
+      return ui::mojom::CursorType::kNorthSouthNoResize;
+    case HTTOPLEFT:
+      return ui::mojom::CursorType::kNorthWestSouthEastNoResize;
+    case HTTOPRIGHT:
+      return ui::mojom::CursorType::kNorthEastSouthWestNoResize;
+    default:
+      return ui::mojom::CursorType::kNull;
+  }
+}
+
 void CompoundEventFilter::AddHandler(ui::EventHandler* handler) {
   handlers_.AddObserver(handler);
 }
@@ -104,7 +129,13 @@
       if (target->delegate()) {
         int window_component =
             target->delegate()->GetNonClientComponent(event->location());
-        cursor = CursorForWindowComponent(window_component);
+
+        if ((target->GetProperty(aura::client::kResizeBehaviorKey) &
+             aura::client::kResizeBehaviorCanResize) != 0) {
+          cursor = CursorForWindowComponent(window_component);
+        } else {
+          cursor = NoResizeCursorForWindowComponent(window_component);
+        }
       } else {
         // Allow the OS to handle non client cursors if we don't have a
         // a delegate to handle the non client hittest.
diff --git a/ui/wm/core/compound_event_filter.h b/ui/wm/core/compound_event_filter.h
index e012f72..8920c3c 100644
--- a/ui/wm/core/compound_event_filter.h
+++ b/ui/wm/core/compound_event_filter.h
@@ -41,6 +41,10 @@
   // Returns the cursor for the specified component.
   static gfx::NativeCursor CursorForWindowComponent(int window_component);
 
+  // Returns the not-resizable cursor for the specified component.
+  static gfx::NativeCursor NoResizeCursorForWindowComponent(
+      int window_component);
+
   // Adds/removes additional event filters. This does not take ownership of
   // the EventHandler.
   // NOTE: These handlers are deprecated. Use env::AddPreTargetEventHandler etc.
diff --git a/weblayer/browser/download_service_factory.cc b/weblayer/browser/download_service_factory.cc
index 8526d4e..9d4a8433 100644
--- a/weblayer/browser/download_service_factory.cc
+++ b/weblayer/browser/download_service_factory.cc
@@ -99,8 +99,7 @@
   // download::BlobContextGetterFactory:
   void RetrieveBlobContextGetter(
       download::BlobContextGetterCallback callback) override {
-    std::move(callback).Run(
-        content::BrowserContext::GetBlobStorageContext(browser_context_));
+    std::move(callback).Run(browser_context_->GetBlobStorageContext());
   }
 
   content::BrowserContext* browser_context_;