diff --git a/.gitattributes b/.gitattributes
index 675b8fcc..93c5b7f1 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -50,6 +50,7 @@
 README.*   text eol=lf
 WATCHLISTS   text eol=lf
 VERSION   text eol=lf
+DIR_METADATA   text eol=lf
 
 # Skip Tricium by default on files in third_party.
 third_party/** -tricium
diff --git a/AUTHORS b/AUTHORS
index 3c47ef5..c9d76de 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1202,6 +1202,7 @@
 Neverware Inc. <*@neverware.com>
 NIKE, Inc. <*@nike.com>
 NVIDIA Corporation <*@nvidia.com>
+OpenFin Inc. <*@openfin.co>
 Opera Software ASA <*@opera.com>
 Optical Tone Ltd <*@opticaltone.com>
 Pengutronix e.K. <*@pengutronix.de>
diff --git a/DEPS b/DEPS
index bb015e2..e5fc07e 100644
--- a/DEPS
+++ b/DEPS
@@ -206,11 +206,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': '01771c17f1d64201a644ca894af0aac81b1a101d',
+  'skia_revision': 'e267464b897d6dbcc5c05ca48da0abbe6f2d0aed',
   # 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': 'd82ff002381657c44563e830ec337d103b99d565',
+  'v8_revision': 'd9ccb94fc2738d2c7bec626c287518c5e3ad14e9',
   # 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.
@@ -218,15 +218,15 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '99f9277c5bcb2f83c491c5d5bb5d9e465bf00eeb',
+  'angle_revision': '2e1091e0ef699a39662f210abcb5af69750dcb38',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '84f5eeb6dd9b225f465f93737fa76aad7de355cf',
+  'swiftshader_revision': 'df17a76102dfabb3f1bd6e51449cece9f77b45e3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'e03bf7b4af92edce27642b529982cd27b680a789',
+  'pdfium_revision': '337086da0b11e7a3c2cfac87aeeec70aa9e01e0c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -269,7 +269,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '2d615e49c1cba8191c7c8b8318741ad5490db0aa',
+  'catapult_revision': 'c3fb4c6d391580afa58452561091810e0f5d9f77',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -277,7 +277,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': 'ee87b994218e9052f0297e672af5710b53d0192e',
+  'devtools_frontend_revision': 'cab003ff2dd9ea5c06ccfeeb97e743ad971b130e',
   # 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.
@@ -313,11 +313,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_tools_revision': '6fac705e76165663544e8562537c4165d3bac190',
+  'spv_tools_revision': 'ba15b58862907e9ca5398ea4dd23b97dffc4b2b6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_headers_revision': '3fdabd0da2932c276b25b9b4a988ba134eba1aa6',
+  'spv_headers_revision': '05836bdba63e7debce9fa9feaed42f20cd43af9d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -329,7 +329,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': 'e2cbcc9565886e0a066580e3be7426b9924be72f',
+  'dawn_revision': '22505a5afe1f75b402a00a27d49e313fbd6e2181',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -368,7 +368,7 @@
   'ukey2_revision': '0275885d8e6038c39b8a8ca55e75d1d4d1727f47',
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'tint_revision': '4f79c84050287dab127ba5410e770889ed11cb05',
+  'tint_revision': '8f7c80347dc6b5c380e19ca446ed5a439ce919e3',
 
   # TODO(crbug.com/941824): The values below need to be kept in sync
   # between //DEPS and //buildtools/DEPS, so if you're updating one,
@@ -892,7 +892,7 @@
   # Tools used when building Chrome for Chrome OS. This affects both the Simple
   # Chrome workflow, as well as the chromeos-chrome ebuild.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '3169c31f1f0ea280b0aef547004aa0e729647591',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'f80cfd667638e1b2bc95ecd827fb372d1be58657',
       'condition': 'checkout_chromeos',
   },
 
@@ -912,7 +912,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'f736cabba58b374aeb96d7512813a39f30567b5a',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b3a1dbae309e45f63e963fce34f174f40822ff14',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1165,7 +1165,7 @@
   },
 
   'src/third_party/libvpx/source/libvpx':
-    Var('chromium_git') + '/webm/libvpx.git' + '@' +  '7e8ea22e4056a3da04b139fcc812a3f6937bbed7',
+    Var('chromium_git') + '/webm/libvpx.git' + '@' +  '94384b5c685ad3baac8989f19ee587eb72093a7f',
 
   'src/third_party/libwebm/source':
     Var('chromium_git') + '/webm/libwebm.git' + '@' + '51ca718c3adf0ddedacd7df25fe45f67dc5a9ce1',
@@ -1248,7 +1248,7 @@
     Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '3dd5b80bc4f172dd82925bb259cb7c82348409c5',
 
   'src/third_party/openscreen/src':
-    Var('chromium_git') + '/openscreen' + '@' + 'a8cdc94e138d9c4ce2157c30c222a9e12f08ec63',
+    Var('chromium_git') + '/openscreen' + '@' + 'd975e29d1e934b21ebfc9dd4fbaebecab167f986',
 
   'src/third_party/openxr/src': {
     'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '97cfe495bb7a3853266b646d1c79e169387f9c7a',
@@ -1265,7 +1265,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '9606cffa66d00945b91a729d98c39fb4af259074',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'c4af5cd3397ddef15ef32e09847715c1ead0118a',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1343,7 +1343,7 @@
       'packages': [
           {
               'package': 'fuchsia/third_party/aemu/linux-amd64',
-              'version': 'exAX_yeKLNYEK0NGmhD6PCExVZm6XY2aCPioGGLAHlYC'
+              'version': 'dfMpR8E7Ie1gS4Mf_DWloGOmZIegnZWNA0kcMr7jPlkC'
           },
       ],
       'condition': 'host_os == "linux" and checkout_fuchsia',
@@ -1535,7 +1535,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/linux-amd64',
-          'version': 's4io-2tGPYRC7r5NKMb_6S-dd-xm-4p7J69tDFPq8OgC',
+          'version': 'STGouE9nmPhPvUv1KVauwIovsjIba4yq1HobYOsm2moC',
         },
       ],
       'dep_type': 'cipd',
@@ -1545,7 +1545,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/windows-amd64',
-          'version': '6JFI1DhhYVfuJu5O5hIqAMI3vsd1fGoBEjuuyfrv5GAC',
+          'version': 'uchtgU5o7fKP3pU3wO7xE_MCNW7vkUEfaG4V2ehVOv4C',
         },
       ],
       'dep_type': 'cipd',
@@ -1555,7 +1555,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/mac-amd64',
-          'version': '-sWJ6Y-_28CBu5970u_9tllKY3mY-_75kBm4Ikavq24C',
+          'version': 'zglqXfuaXqShJjRK_8fR8Fo2N-hczeJASDUh4Vy2s4gC',
         },
       ],
       'dep_type': 'cipd',
@@ -1569,7 +1569,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@7b3ad4f25a179e097a130c7bf5ec4f2ca177ba4a',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8462cfcb03a53c334eb0fcde68e96bed447a086a',
     'condition': 'checkout_src_internal',
   },
 
@@ -1577,7 +1577,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 'rzh7SSCNO_IMmZv7t7OIlOy_7XIZejdnXpj-Uh3IeGwC',
+        'version': 'FPS7GXWrnoUpSm7SUEXrX5w9y54l81RKV4hoZXUW3xEC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1588,7 +1588,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'U-5IIfB8vy39NvpI83unV6yKRSTL446Zw5cBERt3kGgC',
+        'version': 'ce3CRtV0VP2yelnNkFkhuX0bCzB4BFzKPeYxeIRHf70C',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/WATCHLISTS b/WATCHLISTS
index f4af75d..7be1844b 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -97,6 +97,9 @@
     'android_tab': {
       'filepath': 'chrome/android/java/src/org/chromium/chrome/browser/Tab'
     },
+    'android_toolbar': {
+      'filepath': 'chrome/android/java/src/org/chromium/chrome/browser/toolbar/'
+    },
     'android_uma_settings': {
       'filepath': 'chrome/android/java/src/org/chromium/chrome/browser/settings/privacy/PrivacyPreferencesManager.java|'\
                   'chrome/android/java/src/org/chromium/chrome/browser/settings/privacy/PrivacyPreferences.java|'\
@@ -1651,7 +1654,8 @@
                   '|components/metrics/public/mojom/call_stack*',
     },
     'scanning': {
-      'filepath': 'chromeos/components/scanning/',
+      'filepath': 'chromeos/components/scanning/'\
+                  '|chrome/browser/chromeos/scanning/',
     },
     'screen_orientation': {
       'filepath': 'screen_orientation',
@@ -2101,6 +2105,7 @@
     'android_studio': ['wnwen+watch@chromium.org',
                        'nyquist+watch@chromium.org'],
     'android_tab': ['dtrainor+watch@chromium.org'],
+    'android_toolbar': ['jinsukkim+watch@chromium.org'],
     'android_uma_settings': ['asvitkine+watch@chromium.org',
                              'gayane+watch@chromium.org'],
     'android_webapk': ['dominickn+watch-webapk@chromium.org',
diff --git a/android_webview/browser/DEPS b/android_webview/browser/DEPS
index 730c09b..c384720 100644
--- a/android_webview/browser/DEPS
+++ b/android_webview/browser/DEPS
@@ -111,7 +111,7 @@
   # Required for the Web Speech API.
   "+third_party/blink/public/mojom/speech",
   # Required by AwSettings.
-  "+third_party/blink/public/mojom/renderer_preferences.mojom.h",
+  "+third_party/blink/public/common/renderer_preferences/renderer_preferences.h",
   "+third_party/blink/public/mojom/webpreferences/web_preferences.mojom.h",
   # For the content_browser overlay manifest
   "+third_party/blink/public/mojom/input",
diff --git a/android_webview/browser/aw_settings.cc b/android_webview/browser/aw_settings.cc
index d0c5470..53f4cf93 100644
--- a/android_webview/browser/aw_settings.cc
+++ b/android_webview/browser/aw_settings.cc
@@ -24,7 +24,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "net/http/http_util.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom.h"
 
 using base::android::ConvertJavaStringToUTF16;
@@ -239,8 +239,7 @@
     return;
 
   bool update_prefs = false;
-  blink::mojom::RendererPreferences* prefs =
-      web_contents()->GetMutableRendererPrefs();
+  blink::RendererPreferences* prefs = web_contents()->GetMutableRendererPrefs();
 
   if (!renderer_prefs_initialized_) {
     content::UpdateFontRendererPreferencesFromSystemSettings(prefs);
diff --git a/android_webview/browser/metrics/visibility_metrics_logger.cc b/android_webview/browser/metrics/visibility_metrics_logger.cc
index 30909df..854e4c5 100644
--- a/android_webview/browser/metrics/visibility_metrics_logger.cc
+++ b/android_webview/browser/metrics/visibility_metrics_logger.cc
@@ -291,19 +291,17 @@
 }
 
 void VisibilityMetricsLogger::RecordScreenPortionMetrics() {
-  int tracked_portion = static_cast<int>(current_open_web_screen_portion_);
+  for (int i = 0; i < static_cast<int>(WebViewOpenWebScreenPortion::kMaxValue);
+       i++) {
+    int32_t elapsed_seconds =
+        open_web_screen_portion_tracked_duration_[i].InSeconds();
+    if (elapsed_seconds == 0)
+      continue;
 
-  // TODO (idries@): record every bucket, not just
-  // current_open_web_screen_portion_
-  int32_t elapsed_seconds =
-      open_web_screen_portion_tracked_duration_[tracked_portion].InSeconds();
-  if (elapsed_seconds == 0)
-    return;
-
-  open_web_screen_portion_tracked_duration_[tracked_portion] -=
-      base::TimeDelta::FromSeconds(elapsed_seconds);
-  GetOpenWebVisibileScreenPortionHistogram()->AddCount(tracked_portion,
-                                                       elapsed_seconds);
+    open_web_screen_portion_tracked_duration_[i] -=
+        base::TimeDelta::FromSeconds(elapsed_seconds);
+    GetOpenWebVisibileScreenPortionHistogram()->AddCount(i, elapsed_seconds);
+  }
 }
 
 }  // namespace android_webview
\ No newline at end of file
diff --git a/android_webview/browser/metrics/visibility_metrics_logger.h b/android_webview/browser/metrics/visibility_metrics_logger.h
index bfacafa..7ee6df1 100644
--- a/android_webview/browser/metrics/visibility_metrics_logger.h
+++ b/android_webview/browser/metrics/visibility_metrics_logger.h
@@ -113,7 +113,7 @@
     base::TimeDelta no_webview_tracked_duration_ =
         base::TimeDelta::FromSeconds(0);
     // Total duration that WebViews meet the tracking criteria (i.e. if
-    // 2x WebViews meet the criteria for 1 second then increment by 2 sections)
+    // 2x WebViews meet the criteria for 1 second then increment by 2 seconds)
     base::TimeDelta per_webview_duration_ = base::TimeDelta::FromSeconds(0);
     // Total duration that WebViews exist but do not meet the tracking criteria
     base::TimeDelta per_webview_untracked_duration_ =
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
index 6fd96f59..a23418f 100644
--- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
+++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -86,7 +86,7 @@
                             + "stricter same-origin feature is enabled."),
             Flag.baseFeature(AwFeatures.WEBVIEW_MEASURE_SCREEN_COVERAGE,
                     "Measure the number of pixels occupied by one or more WebViews as a proportion "
-                            + "of the total screen size. Depending on the number of WebVieaws and "
+                            + "of the total screen size. Depending on the number of WebViews and "
                             + "the size of the screen this might be expensive so hidden behind a "
                             + "feature flag until the true runtime cost can be measured."),
             Flag.baseFeature(BlinkFeatures.WEB_COMPONENTS_V0,
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwMetricsIntegrationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwMetricsIntegrationTest.java
index c26d421..0fd60c6 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwMetricsIntegrationTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwMetricsIntegrationTest.java
@@ -334,7 +334,7 @@
 
             // Load a page to ensure the renderer process is created.
             mRule.loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
-                    embeddedTestServer.getURL("/simple_page.html"));
+                    embeddedTestServer.getURL("/android_webview/test/data/hello_world.html"));
             helper.waitForCallback(finalMetricsCollectedCount, 1);
 
             // At this point we know one of two things must be true:
@@ -353,7 +353,7 @@
             // have been copied into the browser process.
 
             mRule.loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
-                    embeddedTestServer.getURL("/simple_page.html"));
+                    embeddedTestServer.getURL("/android_webview/test/data/hello_world.html"));
             helper.waitForCallback(finalMetricsCollectedCount, 2);
 
             Assert.assertEquals(1,
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwNetworkConfigurationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwNetworkConfigurationTest.java
index 317d8c3..5d659581 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwNetworkConfigurationTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwNetworkConfigurationTest.java
@@ -196,7 +196,7 @@
         mTestServer = EmbeddedTestServer.createAndStartServer(
                 InstrumentationRegistry.getInstrumentation().getContext());
         try {
-            final String url = mTestServer.getURL("/any-http-url-will-suffice.html");
+            final String url = mTestServer.getURL("/android_webview/test/data/hello_world.html");
             mActivityTestRule.loadUrlSync(
                     mAwContents, mContentsClient.getOnPageFinishedHelper(), url);
             AwWebResourceRequest request =
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java
index f1a822f..2fb68cf 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java
@@ -230,7 +230,7 @@
                         + "}</script>");
 
         mActivityTestRule.triggerPopup(mParentContents, mParentContentsClient, mWebServer,
-                parentPageHtml, null /* 204 response */, popupPath, "tryOpenWindow()");
+                parentPageHtml, "<html></html>", popupPath, "tryOpenWindow()");
         PopupInfo popupInfo = mActivityTestRule.createPopupContents(mParentContents);
         TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
                 popupInfo.popupContentsClient.getOnPageFinishedHelper();
diff --git a/ash/bloom/OWNERS b/ash/bloom/OWNERS
new file mode 100644
index 0000000..0c730475
--- /dev/null
+++ b/ash/bloom/OWNERS
@@ -0,0 +1,3 @@
+file://chromeos/assistant/OWNERS
+
+# COMPONENT: UI>Shell>Assistant
diff --git a/ash/bloom/bloom_ui_delegate_impl.cc b/ash/bloom/bloom_ui_delegate_impl.cc
index 6a3ee59..6a493e5 100644
--- a/ash/bloom/bloom_ui_delegate_impl.cc
+++ b/ash/bloom/bloom_ui_delegate_impl.cc
@@ -26,12 +26,13 @@
   assistant_interaction_controller()->StartBloomInteraction();
 }
 
-void BloomUiDelegateImpl::OnShowResult(const std::string& html) {
+void BloomUiDelegateImpl::OnShowResult(
+    const chromeos::bloom::BloomResult& result) {
   if (!assistant_interaction_controller())
     return;
 
-  assistant_interaction_controller()->ShowBloomResult("<html><body> " + html +
-                                                      "</body></html>");
+  // TODO(jeroendh): convert the result to HTML
+  assistant_interaction_controller()->ShowBloomResult("");
 }
 
 void BloomUiDelegateImpl::OnInteractionFinished(
diff --git a/ash/bloom/bloom_ui_delegate_impl.h b/ash/bloom/bloom_ui_delegate_impl.h
index a2700bd..b59cf1c 100644
--- a/ash/bloom/bloom_ui_delegate_impl.h
+++ b/ash/bloom/bloom_ui_delegate_impl.h
@@ -21,7 +21,7 @@
   // BloomUiDelegate implementation:
   void OnInteractionStarted() override;
   void OnShowUI() override;
-  void OnShowResult(const std::string& html) override;
+  void OnShowResult(const chromeos::bloom::BloomResult& result) override;
   void OnInteractionFinished(
       chromeos::bloom::BloomInteractionResolution resolution) override;
 
diff --git a/ash/capture_mode/capture_mode_bar_view.cc b/ash/capture_mode/capture_mode_bar_view.cc
index d87d8ec..978b1ee 100644
--- a/ash/capture_mode/capture_mode_bar_view.cc
+++ b/ash/capture_mode/capture_mode_bar_view.cc
@@ -12,10 +12,12 @@
 #include "ash/capture_mode/capture_mode_source_view.h"
 #include "ash/capture_mode/capture_mode_type_view.h"
 #include "ash/style/ash_color_provider.h"
+#include "base/bind.h"
 #include "ui/aura/window.h"
 #include "ui/views/background.h"
 #include "ui/views/controls/separator.h"
 #include "ui/views/layout/box_layout.h"
+#include "ui/views/metadata/metadata_impl_macros.h"
 #include "ui/views/style/platform_style.h"
 
 namespace ash {
@@ -43,8 +45,9 @@
       capture_source_view_(
           AddChildView(std::make_unique<CaptureModeSourceView>())),
       separator_2_(AddChildView(std::make_unique<views::Separator>())),
-      close_button_(
-          AddChildView(std::make_unique<CaptureModeCloseButton>(this))) {
+      close_button_(AddChildView(std::make_unique<CaptureModeCloseButton>(
+          base::BindRepeating(&CaptureModeBarView::OnButtonPressed,
+                              base::Unretained(this))))) {
   SetPaintToLayer();
   auto* color_provider = AshColorProvider::Get();
   SkColor background_color = color_provider->GetBaseLayerColor(
@@ -90,14 +93,11 @@
   capture_type_view_->OnCaptureTypeChanged(new_type);
 }
 
-const char* CaptureModeBarView::GetClassName() const {
-  return "CaptureModeBarView";
-}
-
-void CaptureModeBarView::ButtonPressed(views::Button* sender,
-                                       const ui::Event& event) {
-  DCHECK_EQ(sender, close_button_);
+void CaptureModeBarView::OnButtonPressed() {
   CaptureModeController::Get()->Stop();
 }
 
+BEGIN_METADATA(CaptureModeBarView, views::View)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/capture_mode/capture_mode_bar_view.h b/ash/capture_mode/capture_mode_bar_view.h
index 82d5de1..9162c02 100644
--- a/ash/capture_mode/capture_mode_bar_view.h
+++ b/ash/capture_mode/capture_mode_bar_view.h
@@ -7,7 +7,8 @@
 
 #include "ash/ash_export.h"
 #include "ash/capture_mode/capture_mode_types.h"
-#include "ui/views/controls/button/button.h"
+#include "ui/views/metadata/metadata_header_macros.h"
+#include "ui/views/view.h"
 
 namespace views {
 class Separator;
@@ -38,9 +39,10 @@
 //   |
 //   CaptureModeBarView
 //
-class ASH_EXPORT CaptureModeBarView : public views::View,
-                                      public views::ButtonListener {
+class ASH_EXPORT CaptureModeBarView : public views::View {
  public:
+  METADATA_HEADER(CaptureModeBarView);
+
   CaptureModeBarView();
   CaptureModeBarView(const CaptureModeBarView&) = delete;
   CaptureModeBarView& operator=(const CaptureModeBarView&) = delete;
@@ -60,13 +62,9 @@
   void OnCaptureSourceChanged(CaptureModeSource new_source);
   void OnCaptureTypeChanged(CaptureModeType new_type);
 
-  // views::View:
-  const char* GetClassName() const override;
-
-  // views::ButtonListener:
-  void ButtonPressed(views::Button* sender, const ui::Event& event) override;
-
  private:
+  void OnButtonPressed();
+
   // Owned by the views hierarchy.
   CaptureModeTypeView* capture_type_view_;
   views::Separator* separator_1_;
diff --git a/ash/capture_mode/capture_mode_close_button.cc b/ash/capture_mode/capture_mode_close_button.cc
index 2a106cf..3f083057 100644
--- a/ash/capture_mode/capture_mode_close_button.cc
+++ b/ash/capture_mode/capture_mode_close_button.cc
@@ -9,11 +9,13 @@
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/accessibility/view_accessibility.h"
 #include "ui/views/controls/highlight_path_generator.h"
+#include "ui/views/metadata/metadata_impl_macros.h"
 
 namespace ash {
 
-CaptureModeCloseButton::CaptureModeCloseButton(views::ButtonListener* listener)
-    : ViewWithInkDrop(listener) {
+CaptureModeCloseButton::CaptureModeCloseButton(
+    views::Button::PressedCallback callback)
+    : ViewWithInkDrop(callback) {
   SetPreferredSize(capture_mode::kButtonSize);
   SetBorder(views::CreateEmptyBorder(capture_mode::kButtonPadding));
   auto* color_provider = AshColorProvider::Get();
@@ -39,8 +41,7 @@
                                              capture_mode::kButtonPadding);
 }
 
-const char* CaptureModeCloseButton::GetClassName() const {
-  return "CaptureModeCloseButton";
-}
+BEGIN_METADATA(CaptureModeCloseButton, ViewWithInkDrop<views::ImageButton>)
+END_METADATA
 
 }  // namespace ash
diff --git a/ash/capture_mode/capture_mode_close_button.h b/ash/capture_mode/capture_mode_close_button.h
index 4f32b3f..799b6d7 100644
--- a/ash/capture_mode/capture_mode_close_button.h
+++ b/ash/capture_mode/capture_mode_close_button.h
@@ -9,6 +9,7 @@
 #include "ash/capture_mode/view_with_ink_drop.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/button/image_button.h"
+#include "ui/views/metadata/metadata_header_macros.h"
 
 namespace ash {
 
@@ -16,13 +17,12 @@
 class ASH_EXPORT CaptureModeCloseButton
     : public ViewWithInkDrop<views::ImageButton> {
  public:
-  explicit CaptureModeCloseButton(views::ButtonListener* listener);
+  METADATA_HEADER(CaptureModeCloseButton);
+
+  explicit CaptureModeCloseButton(views::Button::PressedCallback callback);
   CaptureModeCloseButton(const CaptureModeCloseButton&) = delete;
   CaptureModeCloseButton& operator=(const CaptureModeCloseButton&) = delete;
   ~CaptureModeCloseButton() override = default;
-
-  // views::ImageButton:
-  const char* GetClassName() const override;
 };
 
 }  // namespace ash
diff --git a/ash/capture_mode/capture_mode_session.cc b/ash/capture_mode/capture_mode_session.cc
index ef42233..ca2fe76 100644
--- a/ash/capture_mode/capture_mode_session.cc
+++ b/ash/capture_mode/capture_mode_session.cc
@@ -243,7 +243,6 @@
 CaptureModeSession::CaptureModeSession(CaptureModeController* controller)
     : controller_(controller),
       current_root_(GetPreferredRootWindow()),
-      capture_mode_bar_view_(new CaptureModeBarView()),
       magnifier_glass_(kMagnifierParams) {
   Shell::Get()->AddPreTargetHandler(this);
 
@@ -257,8 +256,8 @@
   capture_mode_bar_widget_.Init(
       CreateWidgetParams(parent, CaptureModeBarView::GetBounds(current_root_),
                          "CaptureModeBarWidget"));
-  capture_mode_bar_widget_.SetContentsView(
-      base::WrapUnique(capture_mode_bar_view_));
+  capture_mode_bar_view_ = capture_mode_bar_widget_.SetContentsView(
+      std::make_unique<CaptureModeBarView>());
   capture_mode_bar_widget_.Show();
 
   UpdateCaptureLabelWidget();
diff --git a/ash/capture_mode/capture_mode_session.h b/ash/capture_mode/capture_mode_session.h
index e49f91fb..63360e2b 100644
--- a/ash/capture_mode/capture_mode_session.h
+++ b/ash/capture_mode/capture_mode_session.h
@@ -19,6 +19,7 @@
 #include "ui/events/event.h"
 #include "ui/events/event_handler.h"
 #include "ui/views/controls/button/button.h"
+#include "ui/views/widget/unique_widget_ptr.h"
 #include "ui/views/widget/widget.h"
 
 namespace gfx {
@@ -191,10 +192,10 @@
   views::Widget capture_mode_bar_widget_;
 
   // The content view of the above widget and owned by its views hierarchy.
-  CaptureModeBarView* capture_mode_bar_view_;
+  CaptureModeBarView* capture_mode_bar_view_ = nullptr;
 
   // Widget which displays capture region size during a region capture session.
-  std::unique_ptr<views::Widget> dimensions_label_widget_;
+  views::UniqueWidgetPtr dimensions_label_widget_;
 
   // Widget that shows an optional icon and a message in the middle of the
   // screen or in the middle of the capture region and prompts the user what to
@@ -202,7 +203,7 @@
   // and source and can be empty in some cases. And in video capture mode, when
   // starting capturing, the widget will transform into a 3-second countdown
   // timer.
-  std::unique_ptr<views::Widget> capture_label_widget_;
+  views::UniqueWidgetPtr capture_label_widget_;
 
   // Magnifier glass used during a region capture session.
   MagnifierGlass magnifier_glass_;
diff --git a/ash/capture_mode/capture_mode_source_view.cc b/ash/capture_mode/capture_mode_source_view.cc
index 897b1f2..d051914c 100644
--- a/ash/capture_mode/capture_mode_source_view.cc
+++ b/ash/capture_mode/capture_mode_source_view.cc
@@ -9,21 +9,28 @@
 #include "ash/capture_mode/capture_mode_controller.h"
 #include "ash/capture_mode/capture_mode_toggle_button.h"
 #include "ash/resources/vector_icons/vector_icons.h"
+#include "base/bind.h"
 #include "ui/views/layout/box_layout.h"
+#include "ui/views/metadata/metadata_impl_macros.h"
 
 namespace ash {
 
 CaptureModeSourceView::CaptureModeSourceView()
     : fullscreen_toggle_button_(
           AddChildView(std::make_unique<CaptureModeToggleButton>(
-              this,
+              base::BindRepeating(&CaptureModeSourceView::OnFullscreenToggle,
+                                  base::Unretained(this)),
               kCaptureModeFullscreenIcon))),
-      region_toggle_button_(AddChildView(
-          std::make_unique<CaptureModeToggleButton>(this,
-                                                    kCaptureModeRegionIcon))),
-      window_toggle_button_(AddChildView(
-          std::make_unique<CaptureModeToggleButton>(this,
-                                                    kCaptureModeWindowIcon))) {
+      region_toggle_button_(
+          AddChildView(std::make_unique<CaptureModeToggleButton>(
+              base::BindRepeating(&CaptureModeSourceView::OnRegionToggle,
+                                  base::Unretained(this)),
+              kCaptureModeRegionIcon))),
+      window_toggle_button_(
+          AddChildView(std::make_unique<CaptureModeToggleButton>(
+              base::BindRepeating(&CaptureModeSourceView::OnWindowToggle,
+                                  base::Unretained(this)),
+              kCaptureModeWindowIcon))) {
   auto* box_layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
       views::BoxLayout::Orientation::kHorizontal, gfx::Insets(),
       capture_mode::kBetweenChildSpacing));
@@ -42,21 +49,19 @@
   window_toggle_button_->SetToggled(new_source == CaptureModeSource::kWindow);
 }
 
-const char* CaptureModeSourceView::GetClassName() const {
-  return "CaptureModeSourceView";
+void CaptureModeSourceView::OnFullscreenToggle() {
+  CaptureModeController::Get()->SetSource(CaptureModeSource::kFullscreen);
 }
 
-void CaptureModeSourceView::ButtonPressed(views::Button* sender,
-                                          const ui::Event& event) {
-  auto* controller = CaptureModeController::Get();
-  if (sender == fullscreen_toggle_button_) {
-    controller->SetSource(CaptureModeSource::kFullscreen);
-  } else if (sender == region_toggle_button_) {
-    controller->SetSource(CaptureModeSource::kRegion);
-  } else {
-    DCHECK_EQ(sender, window_toggle_button_);
-    controller->SetSource(CaptureModeSource::kWindow);
-  }
+void CaptureModeSourceView::OnRegionToggle() {
+  CaptureModeController::Get()->SetSource(CaptureModeSource::kRegion);
 }
 
+void CaptureModeSourceView::OnWindowToggle() {
+  CaptureModeController::Get()->SetSource(CaptureModeSource::kWindow);
+}
+
+BEGIN_METADATA(CaptureModeSourceView, views::View)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/capture_mode/capture_mode_source_view.h b/ash/capture_mode/capture_mode_source_view.h
index a479ea0..e17d1f83 100644
--- a/ash/capture_mode/capture_mode_source_view.h
+++ b/ash/capture_mode/capture_mode_source_view.h
@@ -7,7 +7,8 @@
 
 #include "ash/ash_export.h"
 #include "ash/capture_mode/capture_mode_types.h"
-#include "ui/views/controls/button/button.h"
+#include "ui/views/metadata/metadata_header_macros.h"
+#include "ui/views/view.h"
 
 namespace ash {
 
@@ -16,9 +17,10 @@
 // A view that is part of the CaptureBar view, from which the user can toggle
 // between the three available capture sources (fullscreen, region, and window).
 // Only a single capture source can be active at any time.
-class ASH_EXPORT CaptureModeSourceView : public views::View,
-                                         public views::ButtonListener {
+class ASH_EXPORT CaptureModeSourceView : public views::View {
  public:
+  METADATA_HEADER(CaptureModeSourceView);
+
   CaptureModeSourceView();
   CaptureModeSourceView(const CaptureModeSourceView&) = delete;
   CaptureModeSourceView& operator=(const CaptureModeSourceView&) = delete;
@@ -37,13 +39,11 @@
   // Called when the capture source changes.
   void OnCaptureSourceChanged(CaptureModeSource new_source);
 
-  // views::View:
-  const char* GetClassName() const override;
-
-  // views::ButtonListener:
-  void ButtonPressed(views::Button* sender, const ui::Event& event) override;
-
  private:
+  void OnFullscreenToggle();
+  void OnRegionToggle();
+  void OnWindowToggle();
+
   // Owned by the views hierarchy.
   CaptureModeToggleButton* fullscreen_toggle_button_;
   CaptureModeToggleButton* region_toggle_button_;
diff --git a/ash/capture_mode/capture_mode_toggle_button.cc b/ash/capture_mode/capture_mode_toggle_button.cc
index 55cccf6..59c071a 100644
--- a/ash/capture_mode/capture_mode_toggle_button.cc
+++ b/ash/capture_mode/capture_mode_toggle_button.cc
@@ -10,13 +10,14 @@
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/accessibility/view_accessibility.h"
 #include "ui/views/controls/highlight_path_generator.h"
+#include "ui/views/metadata/metadata_impl_macros.h"
 
 namespace ash {
 
 CaptureModeToggleButton::CaptureModeToggleButton(
-    views::ButtonListener* listener,
+    views::Button::PressedCallback callback,
     const gfx::VectorIcon& icon)
-    : ViewWithInkDrop(listener) {
+    : ViewWithInkDrop(callback) {
   SetPreferredSize(capture_mode::kButtonSize);
   SetBorder(views::CreateEmptyBorder(capture_mode::kButtonPadding));
   SetImageHorizontalAlignment(ALIGN_CENTER);
@@ -42,10 +43,6 @@
       AshColorProvider::ControlsLayerType::kControlBackgroundColorActive);
 }
 
-const char* CaptureModeToggleButton::GetClassName() const {
-  return "CaptureModeToggleButton";
-}
-
 void CaptureModeToggleButton::OnPaintBackground(gfx::Canvas* canvas) {
   if (!GetToggled())
     return;
@@ -79,4 +76,8 @@
   SetToggledImage(views::Button::STATE_NORMAL, &toggled_icon);
 }
 
+BEGIN_METADATA(CaptureModeToggleButton,
+               ViewWithInkDrop<views::ToggleImageButton>)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/capture_mode/capture_mode_toggle_button.h b/ash/capture_mode/capture_mode_toggle_button.h
index 60cde18..a500078 100644
--- a/ash/capture_mode/capture_mode_toggle_button.h
+++ b/ash/capture_mode/capture_mode_toggle_button.h
@@ -7,7 +7,9 @@
 
 #include "ash/ash_export.h"
 #include "ash/capture_mode/view_with_ink_drop.h"
+#include "ui/views/controls/button/button.h"
 #include "ui/views/controls/button/image_button.h"
+#include "ui/views/metadata/metadata_header_macros.h"
 
 namespace gfx {
 struct VectorIcon;
@@ -21,14 +23,15 @@
 class ASH_EXPORT CaptureModeToggleButton
     : public ViewWithInkDrop<views::ToggleImageButton> {
  public:
-  CaptureModeToggleButton(views::ButtonListener* listener,
+  METADATA_HEADER(CaptureModeToggleButton);
+
+  CaptureModeToggleButton(views::Button::PressedCallback callback,
                           const gfx::VectorIcon& icon);
   CaptureModeToggleButton(const CaptureModeToggleButton&) = delete;
   CaptureModeToggleButton& operator=(const CaptureModeToggleButton&) = delete;
   ~CaptureModeToggleButton() override = default;
 
   // views::ToggleImageButton:
-  const char* GetClassName() const override;
   void OnPaintBackground(gfx::Canvas* canvas) override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
 
diff --git a/ash/capture_mode/capture_mode_type_view.cc b/ash/capture_mode/capture_mode_type_view.cc
index a2ffd7e7..c62ca8b 100644
--- a/ash/capture_mode/capture_mode_type_view.cc
+++ b/ash/capture_mode/capture_mode_type_view.cc
@@ -10,8 +10,10 @@
 #include "ash/capture_mode/capture_mode_toggle_button.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/style/ash_color_provider.h"
+#include "base/bind.h"
 #include "ui/views/background.h"
 #include "ui/views/layout/box_layout.h"
+#include "ui/views/metadata/metadata_impl_macros.h"
 
 namespace ash {
 
@@ -26,12 +28,16 @@
 }  // namespace
 
 CaptureModeTypeView::CaptureModeTypeView()
-    : image_toggle_button_(AddChildView(
-          std::make_unique<CaptureModeToggleButton>(this,
-                                                    kCaptureModeImageIcon))),
-      video_toggle_button_(AddChildView(
-          std::make_unique<CaptureModeToggleButton>(this,
-                                                    kCaptureModeVideoIcon))) {
+    : image_toggle_button_(
+          AddChildView(std::make_unique<CaptureModeToggleButton>(
+              base::BindRepeating(&CaptureModeTypeView::OnImageToggle,
+                                  base::Unretained(this)),
+              kCaptureModeImageIcon))),
+      video_toggle_button_(
+          AddChildView(std::make_unique<CaptureModeToggleButton>(
+              base::BindRepeating(&CaptureModeTypeView::OnVideoToggle,
+                                  base::Unretained(this)),
+              kCaptureModeVideoIcon))) {
   auto* color_provider = AshColorProvider::Get();
   const SkColor bg_color = color_provider->GetControlsLayerColor(
       AshColorProvider::ControlsLayerType::kControlBackgroundColorInactive);
@@ -55,19 +61,15 @@
             video_toggle_button_->GetToggled());
 }
 
-const char* CaptureModeTypeView::GetClassName() const {
-  return "CaptureModeTypeView";
+void CaptureModeTypeView::OnImageToggle() {
+  CaptureModeController::Get()->SetType(CaptureModeType::kImage);
 }
 
-void CaptureModeTypeView::ButtonPressed(views::Button* sender,
-                                        const ui::Event& event) {
-  auto* controller = CaptureModeController::Get();
-  if (sender == image_toggle_button_) {
-    controller->SetType(CaptureModeType::kImage);
-  } else {
-    DCHECK_EQ(sender, video_toggle_button_);
-    controller->SetType(CaptureModeType::kVideo);
-  }
+void CaptureModeTypeView::OnVideoToggle() {
+  CaptureModeController::Get()->SetType(CaptureModeType::kVideo);
 }
 
+BEGIN_METADATA(CaptureModeTypeView, views::View)
+END_METADATA
+
 }  // namespace ash
diff --git a/ash/capture_mode/capture_mode_type_view.h b/ash/capture_mode/capture_mode_type_view.h
index 60f139f..3188127a 100644
--- a/ash/capture_mode/capture_mode_type_view.h
+++ b/ash/capture_mode/capture_mode_type_view.h
@@ -7,7 +7,8 @@
 
 #include "ash/ash_export.h"
 #include "ash/capture_mode/capture_mode_types.h"
-#include "ui/views/controls/button/button.h"
+#include "ui/views/metadata/metadata_header_macros.h"
+#include "ui/views/view.h"
 
 namespace ash {
 
@@ -15,9 +16,10 @@
 
 // A view that is part of the CaptureBarView, from which the user can toggle
 // between the two available capture types (image, and video).
-class ASH_EXPORT CaptureModeTypeView : public views::View,
-                                       public views::ButtonListener {
+class ASH_EXPORT CaptureModeTypeView : public views::View {
  public:
+  METADATA_HEADER(CaptureModeTypeView);
+
   CaptureModeTypeView();
   CaptureModeTypeView(const CaptureModeTypeView&) = delete;
   CaptureModeTypeView& operator=(const CaptureModeTypeView&) = delete;
@@ -33,13 +35,10 @@
   // Called when the capture type changes.
   void OnCaptureTypeChanged(CaptureModeType new_type);
 
-  // views::View:
-  const char* GetClassName() const override;
-
-  // views::ButtonListener:
-  void ButtonPressed(views::Button* sender, const ui::Event& event) override;
-
  private:
+  void OnImageToggle();
+  void OnVideoToggle();
+
   // Owned by the views hierarchy.
   CaptureModeToggleButton* image_toggle_button_;
   CaptureModeToggleButton* video_toggle_button_;
diff --git a/ash/clipboard/clipboard_nudge_controller.cc b/ash/clipboard/clipboard_nudge_controller.cc
index dd9eb33..b93b2dcf 100644
--- a/ash/clipboard/clipboard_nudge_controller.cc
+++ b/ash/clipboard/clipboard_nudge_controller.cc
@@ -13,6 +13,7 @@
 #include "base/logging.h"
 #include "base/no_destructor.h"
 #include "base/util/values/values_util.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
@@ -33,11 +34,15 @@
     : clipboard_history_(clipboard_history) {
   clipboard_history_->AddObserver(this);
   ui::ClipboardMonitor::GetInstance()->AddObserver(this);
+  if (chromeos::features::IsClipboardHistoryNudgeSessionResetEnabled())
+    Shell::Get()->session_controller()->AddObserver(this);
 }
 
 ClipboardNudgeController::~ClipboardNudgeController() {
   clipboard_history_->RemoveObserver(this);
   ui::ClipboardMonitor::GetInstance()->RemoveObserver(this);
+  if (chromeos::features::IsClipboardHistoryNudgeSessionResetEnabled())
+    Shell::Get()->session_controller()->RemoveObserver(this);
 }
 
 // static
@@ -98,6 +103,14 @@
   }
 }
 
+void ClipboardNudgeController::OnActiveUserPrefServiceChanged(
+    PrefService* prefs) {
+  // Reset the nudge prefs so that the nudge can be shown again.
+  DictionaryPrefUpdate update(prefs, prefs::kMultipasteNudges);
+  update->SetIntPath(kShownCount, 0);
+  update->SetPath(kLastTimeShown, util::TimeToValue(base::Time()));
+}
+
 void ClipboardNudgeController::ShowNudge() {
   // Create and show the nudge.
   nudge_ = std::make_unique<ClipboardNudge>();
diff --git a/ash/clipboard/clipboard_nudge_controller.h b/ash/clipboard/clipboard_nudge_controller.h
index a7c12ba..27d6966e 100644
--- a/ash/clipboard/clipboard_nudge_controller.h
+++ b/ash/clipboard/clipboard_nudge_controller.h
@@ -7,6 +7,7 @@
 
 #include "ash/ash_export.h"
 #include "ash/clipboard/clipboard_history.h"
+#include "ash/public/cpp/session/session_observer.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/clock.h"
 #include "base/timer/timer.h"
@@ -31,7 +32,8 @@
 };
 
 class ASH_EXPORT ClipboardNudgeController : public ClipboardHistory::Observer,
-                                            public ui::ClipboardObserver {
+                                            public ui::ClipboardObserver,
+                                            public SessionObserver {
  public:
   ClipboardNudgeController(ClipboardHistory* clipboard_history);
   ClipboardNudgeController(const ClipboardNudgeController&) = delete;
@@ -47,6 +49,9 @@
   // ui::ClipboardObserver:
   void OnClipboardDataRead() override;
 
+  // SessionObserver:
+  void OnActiveUserPrefServiceChanged(PrefService* prefs) override;
+
   // Resets nudge state and show nudge timer.
   void HandleNudgeShown();
 
diff --git a/ash/home_screen/home_launcher_gesture_handler.cc b/ash/home_screen/home_launcher_gesture_handler.cc
index 36f06d6..82e6cab 100644
--- a/ash/home_screen/home_launcher_gesture_handler.cc
+++ b/ash/home_screen/home_launcher_gesture_handler.cc
@@ -451,7 +451,7 @@
       // end splitview if it is active as SplitViewController observes
       // overview mode ends.
       Shell::Get()->overview_controller()->EndOverview(
-          OverviewEnterExitType::kSwipeFromShelf);
+          OverviewEnterExitType::kFadeOutExit);
     } else {
       home_launcher_opacity = 0.f;
     }
diff --git a/ash/home_screen/home_launcher_gesture_handler_unittest.cc b/ash/home_screen/home_launcher_gesture_handler_unittest.cc
index 266b895..6e0d6a3 100644
--- a/ash/home_screen/home_launcher_gesture_handler_unittest.cc
+++ b/ash/home_screen/home_launcher_gesture_handler_unittest.cc
@@ -321,53 +321,6 @@
   Shell::Get()->overview_controller()->StartOverview();
 }
 
-// Tests that HomeLauncherGestureHandler works as expected when one window is
-// snapped, and overview mode is active on the other side.
-TEST_F(HomeLauncherGestureHandlerTest, SplitviewOneSnappedWindow) {
-  UpdateDisplay("400x456");
-
-  auto window1 = CreateWindowForTesting();
-  auto window2 = CreateWindowForTesting();
-
-  // Snap one window and leave overview mode open with the other window.
-  OverviewController* overview_controller = Shell::Get()->overview_controller();
-  overview_controller->StartOverview();
-  split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
-  ASSERT_TRUE(overview_controller->InOverviewSession());
-  ASSERT_TRUE(split_view_controller()->InSplitViewMode());
-
-  const int window2_initial_translation =
-      window2->transform().To2dTranslation().y();
-  DoPress(Mode::kSlideUpToShow);
-  EXPECT_EQ(window1.get(), GetGestureHandler()->GetActiveWindow());
-
-  // Tests that while scrolling the window transforms change.
-  GetGestureHandler()->OnScrollEvent(gfx::PointF(0.f, 300.f), 0.f, 1.f);
-  EXPECT_NE(window1->transform(), gfx::Transform());
-  EXPECT_NE(window2_initial_translation,
-            window2->transform().To2dTranslation().y());
-
-  // Tests that after releasing at below the halfway point, we remain in
-  // both splitview and overview mode.
-  GetGestureHandler()->OnReleaseEvent(gfx::PointF(0.f, 300.f),
-                                      /*velocity_y=*/base::nullopt);
-  EXPECT_EQ(window1->transform(), gfx::Transform());
-  EXPECT_EQ(window2_initial_translation,
-            window2->transform().To2dTranslation().y());
-  EXPECT_TRUE(overview_controller->InOverviewSession());
-  EXPECT_TRUE(split_view_controller()->InSplitViewMode());
-
-  // Tests that after releasing on the top half, overivew and splitview have
-  // both been exited, and both windows are minimized to show the home launcher.
-  DoPress(Mode::kSlideUpToShow);
-  GetGestureHandler()->OnReleaseEvent(gfx::PointF(0.f, 100.f),
-                                      /*velocity_y=*/base::nullopt);
-  EXPECT_FALSE(overview_controller->InOverviewSession());
-  EXPECT_FALSE(split_view_controller()->InSplitViewMode());
-  EXPECT_TRUE(WindowState::Get(window1.get())->IsMinimized());
-  EXPECT_TRUE(WindowState::Get(window2.get())->IsMinimized());
-}
-
 // Tests that swipe to close works as expected when there are two snapped
 // windows.
 TEST_F(HomeLauncherGestureHandlerTest, SplitviewTwoSnappedWindows) {
diff --git a/ash/home_screen/home_screen_controller.cc b/ash/home_screen/home_screen_controller.cc
index cf6bcabf..7bbb64b 100644
--- a/ash/home_screen/home_screen_controller.cc
+++ b/ash/home_screen/home_screen_controller.cc
@@ -151,7 +151,7 @@
 
     if (overview_controller->InOverviewSession()) {
       // End overview mode.
-      overview_controller->EndOverview(OverviewEnterExitType::kSlideOutExit);
+      overview_controller->EndOverview(OverviewEnterExitType::kFadeOutExit);
       return true;
     }
 
@@ -343,17 +343,10 @@
 
   const bool animate =
       IsHomeScreenVisible() &&
-      (overview_enter_type == OverviewEnterExitType::kSlideInEnter ||
-       overview_enter_type == OverviewEnterExitType::kFadeInEnter);
-  const bool use_scale_transition =
-      overview_enter_type == OverviewEnterExitType::kFadeInEnter ||
-      (features::IsDragFromShelfToHomeOrOverviewEnabled() &&
-       overview_enter_type != OverviewEnterExitType::kSlideInEnter);
-  const HomeScreenPresenter::TransitionType transition =
-      use_scale_transition ? HomeScreenPresenter::TransitionType::kScaleHomeOut
-                           : HomeScreenPresenter::TransitionType::kSlideHomeOut;
+      overview_enter_type == OverviewEnterExitType::kFadeInEnter;
 
-  home_screen_presenter_.ScheduleOverviewModeAnimation(transition, animate);
+  home_screen_presenter_.ScheduleOverviewModeAnimation(
+      HomeScreenPresenter::TransitionType::kScaleHomeOut, animate);
 }
 
 void HomeScreenController::OnOverviewModeEnding(
@@ -390,18 +383,11 @@
   }
 
   const bool animate =
-      *overview_exit_type_ == OverviewEnterExitType::kSlideOutExit ||
       *overview_exit_type_ == OverviewEnterExitType::kFadeOutExit;
-  const bool use_scale_transition =
-      *overview_exit_type_ == OverviewEnterExitType::kFadeOutExit ||
-      (features::IsDragFromShelfToHomeOrOverviewEnabled() &&
-       *overview_exit_type_ != OverviewEnterExitType::kSlideOutExit);
-  const HomeScreenPresenter::TransitionType transition =
-      use_scale_transition ? HomeScreenPresenter::TransitionType::kScaleHomeIn
-                           : HomeScreenPresenter::TransitionType::kSlideHomeIn;
   overview_exit_type_ = base::nullopt;
 
-  home_screen_presenter_.ScheduleOverviewModeAnimation(transition, animate);
+  home_screen_presenter_.ScheduleOverviewModeAnimation(
+      HomeScreenPresenter::TransitionType::kScaleHomeIn, animate);
 
   // Make sure the window visibility is updated, in case it was previously
   // hidden due to overview being shown.
diff --git a/ash/in_session_auth/auth_dialog_contents_view.cc b/ash/in_session_auth/auth_dialog_contents_view.cc
index 2f335cea..687d59b 100644
--- a/ash/in_session_auth/auth_dialog_contents_view.cc
+++ b/ash/in_session_auth/auth_dialog_contents_view.cc
@@ -413,16 +413,15 @@
   return view;
 }
 
-void AuthDialogContentsView::OnAuthSubmit(const base::string16& password) {
-  InSessionAuthDialogController::Get()->AuthenticateUserWithPasswordOrPin(
-      base::UTF16ToUTF8(password),
-      base::BindOnce(&AuthDialogContentsView::OnPasswordOrPinAuthComplete,
+void AuthDialogContentsView::OnAuthSubmit(const base::string16& pin) {
+  InSessionAuthDialogController::Get()->AuthenticateUserWithPin(
+      base::UTF16ToUTF8(pin),
+      base::BindOnce(&AuthDialogContentsView::OnPinAuthComplete,
                      weak_factory_.GetWeakPtr()));
 }
 
-// TODO(b/156258540): Clear password/PIN if auth failed and retry is allowed.
-void AuthDialogContentsView::OnPasswordOrPinAuthComplete(
-    base::Optional<bool> success) {}
+// TODO(b/156258540): Clear PIN if auth failed and retry is allowed.
+void AuthDialogContentsView::OnPinAuthComplete(base::Optional<bool> success) {}
 
 void AuthDialogContentsView::OnFingerprintAuthComplete(
     bool success,
diff --git a/ash/in_session_auth/auth_dialog_contents_view.h b/ash/in_session_auth/auth_dialog_contents_view.h
index e75244e4..4a1975b 100644
--- a/ash/in_session_auth/auth_dialog_contents_view.h
+++ b/ash/in_session_auth/auth_dialog_contents_view.h
@@ -83,8 +83,8 @@
   // Called when the user submits password or PIN.
   void OnAuthSubmit(const base::string16& password);
 
-  // Called when password/PIN authentication of the user completes.
-  void OnPasswordOrPinAuthComplete(base::Optional<bool> success);
+  // Called when PIN authentication of the user completes.
+  void OnPinAuthComplete(base::Optional<bool> success);
 
   // Called when fingerprint authentication completes.
   void OnFingerprintAuthComplete(bool success,
diff --git a/ash/in_session_auth/in_session_auth_dialog_controller_impl.cc b/ash/in_session_auth/in_session_auth_dialog_controller_impl.cc
index 500abf1..f17073e6 100644
--- a/ash/in_session_auth/in_session_auth_dialog_controller_impl.cc
+++ b/ash/in_session_auth/in_session_auth_dialog_controller_impl.cc
@@ -35,8 +35,8 @@
 
   AccountId account_id =
       Shell::Get()->session_controller()->GetActiveAccountId();
-  // Password should always be available.
-  uint32_t auth_methods = AuthDialogContentsView::kAuthPassword;
+  // GAIA password option is not offered.
+  uint32_t auth_methods = 0;
 
   if (client_->IsFingerprintAuthAvailable(account_id)) {
     client_->StartFingerprintAuthSession(
@@ -73,6 +73,14 @@
   if (pin_auth_available)
     auth_methods |= AuthDialogContentsView::kAuthPin;
 
+  if (auth_methods == 0) {
+    // If neither fingerprint nor PIN is available, we shouldn't receive the
+    // request.
+    LOG(ERROR) << "Neither fingerprint nor PIN is available.";
+    Cancel();
+    return;
+  }
+
   dialog_ = std::make_unique<InSessionAuthDialog>(auth_methods);
 }
 
@@ -87,16 +95,20 @@
   dialog_.reset();
 }
 
-void InSessionAuthDialogControllerImpl::AuthenticateUserWithPasswordOrPin(
-    const std::string& password,
+void InSessionAuthDialogControllerImpl::AuthenticateUserWithPin(
+    const std::string& pin,
     OnAuthenticateCallback callback) {
   DCHECK(client_);
 
   // TODO(b/156258540): Check that PIN is enabled / set up for this user.
-  bool authenticated_by_pin = base::ContainsOnlyChars(password, "0123456789");
+
+  if (!base::ContainsOnlyChars(pin, "0123456789")) {
+    OnAuthenticateComplete(std::move(callback), false);
+    return;
+  }
 
   client_->AuthenticateUserWithPasswordOrPin(
-      password, authenticated_by_pin,
+      pin, true,
       base::BindOnce(&InSessionAuthDialogControllerImpl::OnAuthenticateComplete,
                      weak_factory_.GetWeakPtr(), std::move(callback)));
 }
diff --git a/ash/in_session_auth/in_session_auth_dialog_controller_impl.h b/ash/in_session_auth/in_session_auth_dialog_controller_impl.h
index ab4e686..cab9c09 100644
--- a/ash/in_session_auth/in_session_auth_dialog_controller_impl.h
+++ b/ash/in_session_auth/in_session_auth_dialog_controller_impl.h
@@ -33,9 +33,8 @@
   void SetClient(InSessionAuthDialogClient* client) override;
   void ShowAuthenticationDialog(FinishCallback finish_callback) override;
   void DestroyAuthenticationDialog() override;
-  void AuthenticateUserWithPasswordOrPin(
-      const std::string& password,
-      OnAuthenticateCallback callback) override;
+  void AuthenticateUserWithPin(const std::string& pin,
+                               OnAuthenticateCallback callback) override;
   void AuthenticateUserWithFingerprint(
       base::OnceCallback<void(bool, FingerprintState)> callback) override;
   void Cancel() override;
diff --git a/ash/in_session_auth/in_session_auth_dialog_controller_impl_unittest.cc b/ash/in_session_auth/in_session_auth_dialog_controller_impl_unittest.cc
index 91c6d2f..d8b810f 100644
--- a/ash/in_session_auth/in_session_auth_dialog_controller_impl_unittest.cc
+++ b/ash/in_session_auth/in_session_auth_dialog_controller_impl_unittest.cc
@@ -17,23 +17,23 @@
 
 using InSessionAuthDialogControllerImplTest = AshTestBase;
 
-TEST_F(InSessionAuthDialogControllerImplTest, PasswordAuthSuccess) {
+TEST_F(InSessionAuthDialogControllerImplTest, PinAuthSuccess) {
   InSessionAuthDialogController* controller =
       Shell::Get()->in_session_auth_dialog_controller();
   auto client = std::make_unique<MockInSessionAuthDialogClient>();
 
-  std::string password = "password";
+  std::string pin = "123456";
 
   EXPECT_CALL(*client, AuthenticateUserWithPasswordOrPin(
-                           password, /* authenticated_by_pin = */ false, _))
-      .WillOnce([](const std::string& password, bool authenticated_by_pin,
+                           pin, /* authenticated_by_pin = */ true, _))
+      .WillOnce([](const std::string& pin, bool authenticated_by_pin,
                    base::OnceCallback<void(bool success)> controller_callback) {
         std::move(controller_callback).Run(true);
       });
 
   base::Optional<bool> view_callback_result;
-  controller->AuthenticateUserWithPasswordOrPin(
-      password,
+  controller->AuthenticateUserWithPin(
+      pin,
       /* View callback will be executed during controller callback. */
       base::BindLambdaForTesting(
           [&view_callback_result](base::Optional<bool> did_auth) {
@@ -44,23 +44,23 @@
   EXPECT_TRUE(*view_callback_result);
 }
 
-TEST_F(InSessionAuthDialogControllerImplTest, PasswordAuthFail) {
+TEST_F(InSessionAuthDialogControllerImplTest, PinAuthFail) {
   InSessionAuthDialogController* controller =
       Shell::Get()->in_session_auth_dialog_controller();
   auto client = std::make_unique<MockInSessionAuthDialogClient>();
 
-  std::string password = "password";
+  std::string pin = "123456";
 
   EXPECT_CALL(*client, AuthenticateUserWithPasswordOrPin(
-                           password, /* authenticated_by_pin = */ false, _))
-      .WillOnce([](const std::string& password, bool authenticated_by_pin,
+                           pin, /* authenticated_by_pin = */ true, _))
+      .WillOnce([](const std::string& pin, bool authenticated_by_pin,
                    base::OnceCallback<void(bool success)> controller_callback) {
         std::move(controller_callback).Run(false);
       });
 
   base::Optional<bool> view_callback_result;
-  controller->AuthenticateUserWithPasswordOrPin(
-      password,
+  controller->AuthenticateUserWithPin(
+      pin,
       /* View callback will be executed during controller callback. */
       base::BindLambdaForTesting(
           [&view_callback_result](base::Optional<bool> did_auth) {
diff --git a/ash/login/login_screen_test_api.cc b/ash/login/login_screen_test_api.cc
index 4617b4a7..8f80f0d8 100644
--- a/ash/login/login_screen_test_api.cc
+++ b/ash/login/login_screen_test_api.cc
@@ -681,6 +681,19 @@
 }
 
 // static
+base::string16 LoginScreenTestApi::GetManagementDisclosureText(
+    const AccountId& account_id) {
+  LoginBigUserView* big_user_view = GetBigUserView(account_id);
+  if (!big_user_view) {
+    ADD_FAILURE() << "Could not find user " << account_id.Serialize();
+    return base::string16();
+  }
+  LoginUserView::TestApi user_test(big_user_view->GetUserView());
+  LoginUserMenuView::TestApi user_menu_test(user_test.menu());
+  return user_menu_test.management_disclosure_label()->GetText();
+}
+
+// static
 bool LoginScreenTestApi::IsOobeDialogVisible() {
   LockScreen::TestApi lock_screen_test(LockScreen::Get());
   LockContentsView::TestApi lock_contents_test(
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc
index f834eed1..8f0263a 100644
--- a/ash/login/ui/lock_contents_view.cc
+++ b/ash/login/ui/lock_contents_view.cc
@@ -1494,10 +1494,10 @@
 void LockContentsView::ToggleManagementForUserForDebug(const AccountId& user) {
   auto replace = [](const LoginUserInfo& user_info) {
     auto changed = user_info;
-    if (user_info.user_enterprise_domain)
-      changed.user_enterprise_domain.reset();
+    if (user_info.user_account_manager)
+      changed.user_account_manager.reset();
     else
-      changed.user_enterprise_domain = "example@example.com";
+      changed.user_account_manager = "example@example.com";
     return changed;
   };
 
diff --git a/ash/login/ui/login_user_menu_view.cc b/ash/login/ui/login_user_menu_view.cc
index 9b8f609..7ecd136 100644
--- a/ash/login/ui/login_user_menu_view.cc
+++ b/ash/login/ui/login_user_menu_view.cc
@@ -99,6 +99,10 @@
   return bubble_->username_label_;
 }
 
+views::Label* LoginUserMenuView::TestApi::management_disclosure_label() {
+  return bubble_->management_disclosure_label_;
+}
+
 LoginUserMenuView::LoginUserMenuView(
     const LoginUserInfo& user,
     views::View* anchor_view,
@@ -138,16 +142,16 @@
   }
 
   // User is managed.
-  if (user.user_enterprise_domain) {
+  if (user.user_account_manager) {
     managed_user_data_ = new views::View();
     managed_user_data_->SetLayoutManager(std::make_unique<views::BoxLayout>(
         views::BoxLayout::Orientation::kVertical));
     base::string16 managed_text = l10n_util::GetStringFUTF16(
         IDS_ASH_LOGIN_MANAGED_SESSION_MONITORING_USER_WARNING,
-        base::UTF8ToUTF16(user.user_enterprise_domain.value()));
-    views::Label* managed_label = login_views_utils::CreateBubbleLabel(
+        base::UTF8ToUTF16(user.user_account_manager.value()));
+    management_disclosure_label_ = login_views_utils::CreateBubbleLabel(
         managed_text, gfx::kGoogleGrey200, this);
-    managed_user_data_->AddChildView(managed_label);
+    managed_user_data_->AddChildView(management_disclosure_label_);
     AddChildView(managed_user_data_);
   }
 
diff --git a/ash/login/ui/login_user_menu_view.h b/ash/login/ui/login_user_menu_view.h
index 238dc37..18f8bc69 100644
--- a/ash/login/ui/login_user_menu_view.h
+++ b/ash/login/ui/login_user_menu_view.h
@@ -28,6 +28,7 @@
     views::View* remove_user_confirm_data();
     views::View* managed_user_data();
     views::Label* username_label();
+    views::Label* management_disclosure_label();
 
    private:
     LoginUserMenuView* bubble_;
@@ -66,6 +67,7 @@
   views::View* remove_user_confirm_data_ = nullptr;
   RemoveUserButton* remove_user_button_ = nullptr;
   views::Label* username_label_ = nullptr;
+  views::Label* management_disclosure_label_ = nullptr;
 
   base::string16 warning_message_;
 
diff --git a/ash/login/ui/login_user_view.cc b/ash/login/ui/login_user_view.cc
index 4406f60..7082df99 100644
--- a/ash/login/ui/login_user_view.cc
+++ b/ash/login/ui/login_user_view.cc
@@ -186,7 +186,7 @@
     }
 
     bool is_managed =
-        user.user_enterprise_domain ||
+        user.user_account_manager ||
         user.basic_user_info.type == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
     enterprise_icon_->SetVisible(is_managed);
   }
@@ -597,7 +597,7 @@
 void LoginUserView::UpdateCurrentUserState() {
   base::string16 accessible_name;
   auto email = base::UTF8ToUTF16(current_user_.basic_user_info.display_email);
-  if (current_user_.user_enterprise_domain) {
+  if (current_user_.user_account_manager) {
     accessible_name = l10n_util::GetStringFUTF16(
         IDS_ASH_LOGIN_POD_MANAGED_ACCESSIBLE_NAME, email);
   } else if (current_user_.basic_user_info.type ==
diff --git a/ash/public/cpp/in_session_auth_dialog_controller.h b/ash/public/cpp/in_session_auth_dialog_controller.h
index 84796ca..4aa4512 100644
--- a/ash/public/cpp/in_session_auth_dialog_controller.h
+++ b/ash/public/cpp/in_session_auth_dialog_controller.h
@@ -34,12 +34,11 @@
   // Destroys the authentication dialog.
   virtual void DestroyAuthenticationDialog() = 0;
 
-  // Takes a password or PIN and sends it to InSessionAuthDialogClient to
+  // Takes a PIN and sends it to InSessionAuthDialogClient to
   // authenticate. The InSessionAuthDialogClient should already know the current
   // session's active user, so the user account is not provided here.
-  virtual void AuthenticateUserWithPasswordOrPin(
-      const std::string& password,
-      OnAuthenticateCallback callback) = 0;
+  virtual void AuthenticateUserWithPin(const std::string& pin,
+                                       OnAuthenticateCallback callback) = 0;
 
   // Requests ChromeOS to report fingerprint scan result through |callback|.
   virtual void AuthenticateUserWithFingerprint(
diff --git a/ash/public/cpp/login_screen_test_api.h b/ash/public/cpp/login_screen_test_api.h
index 761e3d97..a688908a 100644
--- a/ash/public/cpp/login_screen_test_api.h
+++ b/ash/public/cpp/login_screen_test_api.h
@@ -64,6 +64,8 @@
 
   static std::string GetDisplayedName(const AccountId& account_id);
   static base::string16 GetDisabledAuthMessage(const AccountId& account_id);
+  static base::string16 GetManagementDisclosureText(
+      const AccountId& account_id);
 
   static bool ExpandPublicSessionPod(const AccountId& account_id);
   static bool HidePublicSessionExpandedPod();
diff --git a/ash/public/cpp/login_types.h b/ash/public/cpp/login_types.h
index 2f925cdb..863482de 100644
--- a/ash/public/cpp/login_types.h
+++ b/ash/public/cpp/login_types.h
@@ -280,9 +280,11 @@
   // screen for this user.
   bool show_display_password_button = false;
 
-  // The domain name displayed in the login screen UI for user-level
-  // management. This is only set if the relevant user is managed.
-  base::Optional<std::string> user_enterprise_domain;
+  // The name of the entity that manages this user's account displayed in the
+  // login screen UI for user-level management. Will be either a domain name
+  // (foo.com) or the email address of the admin (some_user@foo.com).
+  // This is only set if the relevant user is managed.
+  base::Optional<std::string> user_account_manager;
 
   // Contains the public account information if user type is PUBLIC_ACCOUNT.
   base::Optional<PublicAccountInfo> public_account_info;
diff --git a/ash/shortcut_viewer/strings/shortcut_viewer_strings_iw.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_iw.xtb
index 65f3ec3..5b07e7d 100644
--- a/ash/shortcut_viewer/strings/shortcut_viewer_strings_iw.xtb
+++ b/ash/shortcut_viewer/strings/shortcut_viewer_strings_iw.xtb
@@ -74,7 +74,7 @@
 <translation id="353037708190149633">שמירת כל הדפים הפתוחים בחלון הנוכחי כסימניות בתיקייה חדשה</translation>
 <translation id="355103131818127604">פתיחת הקישור בכרטיסייה חדשה ברקע</translation>
 <translation id="3622741593887335780">התקרבות (כשמופעלת זכוכית מגדלת במצב מעוגן או במצב מסך מלא)</translation>
-<translation id="3649256019230929621">מזער את החלון</translation>
+<translation id="3649256019230929621">מזעור החלון</translation>
 <translation id="3655154169297074232">כרטיסיות וחלונות</translation>
 <translation id="3668361878347172356">ביצוע מחדש של הפעולה האחרונה</translation>
 <translation id="3710784500737332588">פתיחת מרכז העזרה</translation>
diff --git a/ash/strings/ash_strings_iw.xtb b/ash/strings/ash_strings_iw.xtb
index 8907f8bc..eb0d09af 100644
--- a/ash/strings/ash_strings_iw.xtb
+++ b/ash/strings/ash_strings_iw.xtb
@@ -98,7 +98,7 @@
 <translation id="1882897271359938046">משקף אל <ph name="DISPLAY_NAME" /></translation>
 <translation id="1885785240814121742">ביטול נעילה עם טביעת אצבע</translation>
 <translation id="1888656773939766144">‏<ph name="DISPLAY_NAME" /> לא תומך ברזולוציה של <ph name="SPECIFIED_RESOLUTION" /> ‏(<ph name="SPECIFIED_REFRESH_RATE" />Hz). הרזולוציה הוחלפה ל-<ph name="FALLBACK_RESOLUTION" /> ‏(<ph name="FALLBACK_REFRESH_RATE" />). עליך ללחוץ על 'אישור' כדי לשמור את השינויים. ההגדרות הקודמות ישוחזרו בעוד <ph name="TIMEOUT_SECONDS" />.</translation>
-<translation id="1919743966458266018">מקש הקיצור לפתיחת מנהל המשימות השתנה. השתמש ב-<ph name="NEW_SHORTCUT" /> במקום ב-<ph name="OLD_SHORTCUT" />.</translation>
+<translation id="1919743966458266018">מקש הקיצור לפתיחת מנהל המשימות השתנה. יש להשתמש ב-<ph name="NEW_SHORTCUT" /> במקום ב-<ph name="OLD_SHORTCUT" />.</translation>
 <translation id="1923539912171292317">לחיצות אוטומטיות</translation>
 <translation id="1924640696879807758">מהטלפון</translation>
 <translation id="1928739107511554905">‏כדי להתקין את העדכון, יש להשתמש במסך המגע ולהפעיל מחדש את ה-Chromebook כשהמקלדת מחוברת.</translation>
@@ -435,7 +435,7 @@
 <translation id="5260676007519551770">שולחן עבודה 4</translation>
 <translation id="5283198616748585639">הוספת דקה</translation>
 <translation id="528468243742722775">סיום</translation>
-<translation id="5286194356314741248">סורק</translation>
+<translation id="5286194356314741248">הסריקה מתבצעת</translation>
 <translation id="5297704307811127955">כבויה</translation>
 <translation id="5302048478445481009">שפה</translation>
 <translation id="5313326810920013265">‏הגדרות Bluetooth</translation>
@@ -505,7 +505,7 @@
 <translation id="5978382165065462689">שיתוף שליטה במסך דרך סיוע מרחוק.</translation>
 <translation id="5980301590375426705">יציאה מהפעלת אורח</translation>
 <translation id="598882571027504733">‏כדי להתקין את העדכון, יש להפעיל מחדש את ה-Chromebook כשהמקלדת מחוברת.</translation>
-<translation id="5992218262414051481">‏מצב ניגודיות גבוהה פועל. הקש שוב על Ctrl+Search+H כדי לכבות אותו.</translation>
+<translation id="5992218262414051481">‏מצב ניגודיות גבוהה פועל. יש להקיש שוב על Ctrl+Search+H כדי לכבות אותו.</translation>
 <translation id="6018164090099858612">יציאה ממצב שיקוף</translation>
 <translation id="602001110135236999">גלילה שמאלה</translation>
 <translation id="6025324406281560198"><ph name="SECURITY_STATUS" />,‏ <ph name="CONNECTION_STATUS" />, עוצמת האות: <ph name="SIGNAL_STRENGTH" />, הרשת מנוהלת על ידי מנהל המערכת שלך</translation>
@@ -545,11 +545,11 @@
 <translation id="6445835306623867477"><ph name="ROUTE_TITLE" /> במכשיר <ph name="RECEIVER_NAME" /></translation>
 <translation id="6452181791372256707">דחייה</translation>
 <translation id="6453179446719226835">שינוי השפה הסתיים</translation>
-<translation id="6459472438155181876">מרחיב את המסך אל <ph name="DISPLAY_NAME" /></translation>
+<translation id="6459472438155181876">הרחבת המסך אל <ph name="DISPLAY_NAME" /> מתבצעת</translation>
 <translation id="6482559668224714696">זכוכית מגדלת במסך מלא</translation>
 <translation id="6490471652906364588">‏מכשיר עם יציאת USB-C (יציאה ימנית)</translation>
 <translation id="649452524636452238">קוד האימות של הכרטיס החכם</translation>
-<translation id="6501401484702599040">מעביר את המסך אל <ph name="RECEIVER_NAME" /></translation>
+<translation id="6501401484702599040">העברת המסך אל <ph name="RECEIVER_NAME" /> מתבצעת</translation>
 <translation id="6520517963145875092">יש לבחור חלון לצילום</translation>
 <translation id="652139407789908527">במהלך העדכון, ייתכן שהתצוגה במסך תופסק לפרק זמן ארוך מהרגיל (עד דקה). אין ללחוץ על לחצן ההפעלה עד להשלמת העדכון.</translation>
 <translation id="6528179044667508675">נא לא להפריע</translation>
@@ -572,7 +572,7 @@
 <translation id="6692996468359469499">קבלת מידע בקשר לבחירה שלך</translation>
 <translation id="6696025732084565524">המקלדת הניתנת לניתוק זקוקה לעדכון קריטי</translation>
 <translation id="6700713906295497288">‏לחצן תפריט IME</translation>
-<translation id="6713285437468012787">‏מכשיר ה-Bluetooth‏ "<ph name="DEVICE_NAME" />" הותאם והוא זמין כעת לכל המשתמשים. אתה יכול להסיר את ההתאמה הזו ב'הגדרות'.</translation>
+<translation id="6713285437468012787">‏מכשיר ה-Bluetooth‏ "<ph name="DEVICE_NAME" />" הותאם והוא זמין כעת לכל המשתמשים. ניתן להסיר את ההתאמה הזו ב'הגדרות'.</translation>
 <translation id="6715542151869432661">לא נמצאו מכשירים ניידים.</translation>
 <translation id="6723839937902243910">חשמל</translation>
 <translation id="6727969043791803658">‏מחובר, ‎<ph name="BATTERY_PERCENTAGE" />%‎ סוללה</translation>
@@ -580,7 +580,7 @@
 <translation id="6751826523481687655">מעקב הביצועים פועל</translation>
 <translation id="6752912906630585008">שולחן העבודה <ph name="REMOVED_DESK" /> הוסר ושולב עם שולחן העבודה <ph name="RECEIVE_DESK" /></translation>
 <translation id="6757237461819837179">מדיה לא מופעלת</translation>
-<translation id="6777216307882431711">‏מספק חשמל למכשירים המחוברים ב-USB-C</translation>
+<translation id="6777216307882431711">‏אספקת חשמל למכשירים המחוברים ב-USB-C</translation>
 <translation id="6790428901817661496">הפעלה</translation>
 <translation id="6803622936009808957">לא ניתן היה לשקף מסכים מכיוון שלא נמצאה רזולוציה נתמכת. במקום זאת התצוגה עברה למצב שולחן עבודה מורחב.</translation>
 <translation id="6818242057446442178">מילה אחת אחורה</translation>
diff --git a/ash/system/overview/overview_button_tray.cc b/ash/system/overview/overview_button_tray.cc
index edc14e8..4806d28f 100644
--- a/ash/system/overview/overview_button_tray.cc
+++ b/ash/system/overview/overview_button_tray.cc
@@ -110,8 +110,7 @@
     const OverviewEnterExitType enter_exit_type =
         overview_controller->overview_session()->enter_exit_overview_type();
     if (mru_window_list.size() > 1u &&
-        enter_exit_type != OverviewEnterExitType::kFadeInEnter &&
-        enter_exit_type != OverviewEnterExitType::kSlideInEnter) {
+        enter_exit_type != OverviewEnterExitType::kFadeInEnter) {
       aura::Window* new_active_window = mru_window_list[1];
 
       // In tablet split view mode, quick switch will only affect the windows on
diff --git a/ash/system/phonehub/notification_opt_in_view.cc b/ash/system/phonehub/notification_opt_in_view.cc
index 188f53c..f6c0e71a 100644
--- a/ash/system/phonehub/notification_opt_in_view.cc
+++ b/ash/system/phonehub/notification_opt_in_view.cc
@@ -17,6 +17,7 @@
 #include "ash/system/unified/rounded_label_button.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chromeos/components/phonehub/notification_access_manager.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/views/border.h"
@@ -55,8 +56,11 @@
 
 }  // namespace
 
-NotificationOptInView::NotificationOptInView(TrayBubbleView* bubble_view)
-    : bubble_view_(bubble_view) {
+NotificationOptInView::NotificationOptInView(
+    TrayBubbleView* bubble_view,
+    chromeos::phonehub::NotificationAccessManager* notification_access_manager)
+    : bubble_view_(bubble_view),
+      notification_access_manager_(notification_access_manager) {
   SetID(PhoneHubViewID::kNotificationOptInView);
   InitLayout();
   LogInterstitialScreenEvent(InterstitialScreen::kNotificationOptIn,
@@ -74,6 +78,7 @@
                                  InterstitialScreenEvent::kDismiss);
       SetVisible(false);
       bubble_view_->UpdateBubble();
+      notification_access_manager_->DismissSetupRequiredUi();
       break;
     case kSetUpButtonTag:
       // Opens the notification set up dialog in settings to start the opt in
diff --git a/ash/system/phonehub/notification_opt_in_view.h b/ash/system/phonehub/notification_opt_in_view.h
index 6c70bfd0..32c3cce 100644
--- a/ash/system/phonehub/notification_opt_in_view.h
+++ b/ash/system/phonehub/notification_opt_in_view.h
@@ -16,6 +16,12 @@
 class Label;
 }  // namespace views
 
+namespace chromeos {
+namespace phonehub {
+class NotificationAccessManager;
+}  // namespace phonehub
+}  // namespace chromeos
+
 namespace ash {
 
 class TrayBubbleView;
@@ -27,7 +33,9 @@
  public:
   METADATA_HEADER(NotificationOptInView);
 
-  explicit NotificationOptInView(TrayBubbleView* bubble_view);
+  NotificationOptInView(TrayBubbleView* bubble_view,
+                        chromeos::phonehub::NotificationAccessManager*
+                            notification_access_manager);
   NotificationOptInView(const NotificationOptInView&) = delete;
   NotificationOptInView& operator=(const NotificationOptInView&) = delete;
   ~NotificationOptInView() override;
@@ -47,6 +55,7 @@
   InterstitialViewButton* dismiss_button_ = nullptr;
 
   TrayBubbleView* bubble_view_ = nullptr;
+  chromeos::phonehub::NotificationAccessManager* notification_access_manager_;
 };
 
 }  // namespace ash
diff --git a/ash/system/phonehub/phone_connected_view.cc b/ash/system/phonehub/phone_connected_view.cc
index 08522a0..af90081 100644
--- a/ash/system/phonehub/phone_connected_view.cc
+++ b/ash/system/phonehub/phone_connected_view.cc
@@ -45,11 +45,14 @@
 
   AddSeparator();
 
-  // TODO(meilinw): handle the case when the user has dismissed this opt in
-  // view once, we shouldn't show it again.
-  if (!phone_hub_manager->GetNotificationAccessManager()
-           ->HasAccessBeenGranted()) {
-    AddChildView(std::make_unique<NotificationOptInView>(bubble_view));
+  chromeos::phonehub::NotificationAccessManager* access_manager =
+      phone_hub_manager->GetNotificationAccessManager();
+  bool should_show_notification_setup_ui =
+      !access_manager->HasAccessBeenGranted() &&
+      !access_manager->HasNotificationSetupUiBeenDismissed();
+  if (should_show_notification_setup_ui) {
+    AddChildView(std::make_unique<NotificationOptInView>(
+        bubble_view, phone_hub_manager->GetNotificationAccessManager()));
   }
 
   setup_layered_view(
diff --git a/ash/system/phonehub/phone_hub_notification_controller.cc b/ash/system/phonehub/phone_hub_notification_controller.cc
index 3654a48..903a917 100644
--- a/ash/system/phonehub/phone_hub_notification_controller.cc
+++ b/ash/system/phonehub/phone_hub_notification_controller.cc
@@ -236,6 +236,7 @@
 
   message_center::RichNotificationData optional_fields;
   optional_fields.small_image = app_metadata.icon;
+  optional_fields.ignore_accent_color_for_small_image = true;
   optional_fields.timestamp = notification->timestamp();
 
   auto shared_image = notification->shared_image();
diff --git a/ash/wm/overview/overview_controller.cc b/ash/wm/overview/overview_controller.cc
index 7fbf27b..b77a355 100644
--- a/ash/wm/overview/overview_controller.cc
+++ b/ash/wm/overview/overview_controller.cc
@@ -81,22 +81,12 @@
     }
   }
 
-  // If kDragFromShelfToHomeOrOverview is enabled, overview is expected to fade
-  // in or out to home screen (when all windows are minimized).
-  if (ash::features::IsDragFromShelfToHomeOrOverviewEnabled()) {
-    return enter ? OverviewEnterExitType::kFadeInEnter
-                 : OverviewEnterExitType::kFadeOutExit;
-  }
-
-  // When kDragFromShelfToHomeOrOverview is enabled, the original type is
-  // overridden even if the list of windows is empty so home screen knows to
-  // animate in during overview exit animation (home screen controller uses
-  // different show/hide animations depending on the overview exit/enter types).
-  if (windows.empty())
-    return original_type;
-
-  return enter ? OverviewEnterExitType::kSlideInEnter
-               : OverviewEnterExitType::kSlideOutExit;
+  // The original type is overridden even if the list of windows is empty so
+  // home screen knows to animate in during overview exit animation (home screen
+  // controller uses different show/hide animations depending on the overview
+  // exit/enter types).
+  return enter ? OverviewEnterExitType::kFadeInEnter
+               : OverviewEnterExitType::kFadeOutExit;
 }
 
 }  // namespace
@@ -326,14 +316,11 @@
       OnStartingAnimationComplete(/*canceled=*/true);
     start_animations_.clear();
 
-    if (type == OverviewEnterExitType::kSlideOutExit ||
-        type == OverviewEnterExitType::kFadeOutExit ||
-        type == OverviewEnterExitType::kSwipeFromShelf) {
-      // Minimize the windows without animations. When the home launcher button
-      // is pressed, minimized widgets will get created in their place, and
-      // those widgets will be slid out of overview. Otherwise,
-      // HomeLauncherGestureHandler will handle sliding the windows out and when
-      // this function is called, we do not need to create minimized widgets.
+    if (type == OverviewEnterExitType::kFadeOutExit) {
+      // FadeOutExit is used for transition to the home launcher. Minimize the
+      // windows without animations to prevent them from getting maximized
+      // during overview exit. Minimized widgets will get created in their
+      // place, and those widgets will fade out of overview.
       std::vector<aura::Window*> windows_to_minimize(windows.size());
       auto it =
           std::copy_if(windows.begin(), windows.end(),
@@ -493,7 +480,6 @@
       split_view_controller->state() !=
           SplitViewController::State::kBothSnapped &&
       InOverviewSession() && overview_session_->IsEmpty() &&
-      type != OverviewEnterExitType::kSwipeFromShelf &&
       type != OverviewEnterExitType::kImmediateExit) {
     return false;
   }
diff --git a/ash/wm/overview/overview_controller_unittest.cc b/ash/wm/overview/overview_controller_unittest.cc
index e1586c2d..6cd1542 100644
--- a/ash/wm/overview/overview_controller_unittest.cc
+++ b/ash/wm/overview/overview_controller_unittest.cc
@@ -142,7 +142,6 @@
   AnimationState ending_animation_state() const {
     return ending_animation_state_;
   }
-  bool last_animation_was_slide() const { return last_animation_was_slide_; }
   bool last_animation_was_fade() const { return last_animation_was_fade_; }
 
  private:
@@ -151,10 +150,6 @@
     const OverviewEnterExitType enter_exit_type =
         selector->enter_exit_overview_type();
 
-    last_animation_was_slide_ =
-        enter_exit_type == OverviewEnterExitType::kSlideInEnter ||
-        enter_exit_type == OverviewEnterExitType::kSlideOutExit;
-
     last_animation_was_fade_ =
         enter_exit_type == OverviewEnterExitType::kFadeInEnter ||
         enter_exit_type == OverviewEnterExitType::kFadeOutExit;
@@ -173,7 +168,6 @@
 
   AnimationState starting_animation_state_ = UNKNOWN;
   AnimationState ending_animation_state_ = UNKNOWN;
-  bool last_animation_was_slide_ = false;
   bool last_animation_was_fade_ = false;
   // If false, skips the checks in OnOverviewMode Starting/Ending
   // AnimationComplete.
@@ -529,31 +523,25 @@
 
   Shell::Get()->overview_controller()->StartOverview();
   EXPECT_FALSE(observer.last_animation_was_fade());
-  EXPECT_FALSE(observer.last_animation_was_slide());
 
-  // Exit to home launcher using either fade out or slide out animation. This
-  // should minimize all windows.
-  const bool is_homerview_enabled =
-      ash::features::IsDragFromShelfToHomeOrOverviewEnabled();
+  // Exit to home launcher using fade out animation. This should minimize all
+  // windows.
   Shell::Get()->overview_controller()->EndOverview(
-      is_homerview_enabled ? OverviewEnterExitType::kFadeOutExit
-                           : OverviewEnterExitType::kSlideOutExit);
+      OverviewEnterExitType::kFadeOutExit);
 
-  EXPECT_EQ(is_homerview_enabled, observer.last_animation_was_fade());
-  EXPECT_EQ(!is_homerview_enabled, observer.last_animation_was_slide());
+  EXPECT_TRUE(observer.last_animation_was_fade());
 
   ASSERT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
   EXPECT_TRUE(WindowState::Get(window.get())->IsMinimized());
 
-  // All windows are minimized, so we should use the slide in or the fade in
-  // animation to enter overview.
+  // All windows are minimized, so we should use the fade in animation to enter
+  // overview.
   Shell::Get()->overview_controller()->StartOverview();
-  EXPECT_EQ(is_homerview_enabled, observer.last_animation_was_fade());
-  EXPECT_EQ(!is_homerview_enabled, observer.last_animation_was_slide());
+  EXPECT_TRUE(observer.last_animation_was_fade());
 }
 
-// Tests that the slide and fade animations are not used to enter or exit
-// overview in clamshell.
+// Tests that fade animations are not used to enter or exit overview in
+// clamshell.
 TEST_F(OverviewControllerTest, OverviewEnterExitAnimationClamshell) {
   TestOverviewObserver observer(/*should_monitor_animation_state = */ false);
 
@@ -562,19 +550,16 @@
       CreateTestWindowInShellWithBounds(bounds));
 
   Shell::Get()->overview_controller()->StartOverview();
-  EXPECT_FALSE(observer.last_animation_was_slide());
   EXPECT_FALSE(observer.last_animation_was_fade());
 
   Shell::Get()->overview_controller()->EndOverview();
-  EXPECT_FALSE(observer.last_animation_was_slide());
   EXPECT_FALSE(observer.last_animation_was_fade());
 
-  // Even with all window minimized, overview should not use slide, nor fade
-  // animation to enter.
+  // Even with all window minimized, overview should not use fade animation to
+  // enter.
   ASSERT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
   WindowState::Get(window.get())->Minimize();
   Shell::Get()->overview_controller()->StartOverview();
-  EXPECT_FALSE(observer.last_animation_was_slide());
   EXPECT_FALSE(observer.last_animation_was_fade());
 }
 
@@ -587,16 +572,12 @@
   ui::ScopedAnimationDurationScaleMode non_zero(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
 
-  const bool is_homerview_enabled =
-      ash::features::IsDragFromShelfToHomeOrOverviewEnabled();
   Shell::Get()->overview_controller()->StartOverview(
-      is_homerview_enabled ? OverviewEnterExitType::kFadeInEnter
-                           : OverviewEnterExitType::kSlideInEnter);
+      OverviewEnterExitType::kFadeInEnter);
   auto* wallpaper_widget_controller =
       Shell::GetPrimaryRootWindowController()->wallpaper_widget_controller();
-  EXPECT_EQ(is_homerview_enabled,
-            wallpaper_widget_controller->GetWallpaperProperty().blur_sigma > 0);
-  EXPECT_EQ(is_homerview_enabled, wallpaper_widget_controller->IsAnimating());
+  EXPECT_GT(wallpaper_widget_controller->GetWallpaperProperty().blur_sigma, 0);
+  EXPECT_TRUE(wallpaper_widget_controller->IsAnimating());
 }
 
 // Tests that overview session exits cleanly if exit is requested before
@@ -617,17 +598,13 @@
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
   Shell::Get()->overview_controller()->StartOverview();
 
-  // Exit to home launcher using either fade out or slide out animation. This
-  // should minimize all windows.
-  const bool is_homerview_enabled =
-      ash::features::IsDragFromShelfToHomeOrOverviewEnabled();
+  // Exit to home launcher using fade out animation. This should minimize all
+  // windows.
   TestOverviewObserver observer(/*should_monitor_animation_state = */ true);
   Shell::Get()->overview_controller()->EndOverview(
-      is_homerview_enabled ? OverviewEnterExitType::kFadeOutExit
-                           : OverviewEnterExitType::kSlideOutExit);
+      OverviewEnterExitType::kFadeOutExit);
 
-  EXPECT_EQ(is_homerview_enabled, observer.last_animation_was_fade());
-  EXPECT_EQ(!is_homerview_enabled, observer.last_animation_was_slide());
+  EXPECT_TRUE(observer.last_animation_was_fade());
 
   // Verify that the overview exits cleanly.
   observer.WaitForEndingAnimationComplete();
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc
index 0f12f1f..1711d43 100644
--- a/ash/wm/overview/overview_grid.cc
+++ b/ash/wm/overview/overview_grid.cc
@@ -1305,11 +1305,6 @@
   nudge_data_.clear();
 }
 
-void OverviewGrid::SlideWindowsIn() {
-  for (const auto& window_item : window_list_)
-    window_item->SlideWindowIn();
-}
-
 std::unique_ptr<ui::ScopedLayerAnimationSettings>
 OverviewGrid::UpdateYPositionAndOpacity(
     float new_y,
diff --git a/ash/wm/overview/overview_grid.h b/ash/wm/overview/overview_grid.h
index 955ffe2..9596e88 100644
--- a/ash/wm/overview/overview_grid.h
+++ b/ash/wm/overview/overview_grid.h
@@ -262,11 +262,6 @@
   // Clears |nudge_data_|.
   void EndNudge();
 
-  // Called after PositionWindows when entering overview from the home launcher
-  // screen. Translates all windows vertically and animates to their final
-  // locations.
-  void SlideWindowsIn();
-
   // Update the y position and opacity of the entire grid. Does this by
   // transforming the windows in |window_list_|. If |callback| is non null, the
   // transformation and opacity change should be animated. The animation
diff --git a/ash/wm/overview/overview_item.cc b/ash/wm/overview/overview_item.cc
index c9620ccd..44edee3 100644
--- a/ash/wm/overview/overview_item.cc
+++ b/ash/wm/overview/overview_item.cc
@@ -131,8 +131,7 @@
   // OverviewEnterExitType can only be set to kWindowMinimized in talbet mode.
   // Fade out the minimized window without animation if switch from tablet mode
   // to clamshell mode.
-  if (type == OverviewEnterExitType::kSlideOutExit ||
-      type == OverviewEnterExitType::kFadeOutExit) {
+  if (type == OverviewEnterExitType::kFadeOutExit) {
     return Shell::Get()->tablet_mode_controller()->InTabletMode()
                ? OVERVIEW_ANIMATION_EXIT_TO_HOME_LAUNCHER
                : OVERVIEW_ANIMATION_NONE;
@@ -247,10 +246,7 @@
     OverviewAnimationType animation_type =
         GetExitOverviewAnimationTypeForMinimizedWindow(
             enter_exit_type, should_animate_when_exiting_);
-    FadeOutWidgetAndMaybeSlideOnExit(
-        std::move(item_widget_), animation_type,
-        animation_type == OVERVIEW_ANIMATION_EXIT_TO_HOME_LAUNCHER &&
-            enter_exit_type == OverviewEnterExitType::kSlideOutExit);
+    FadeOutWidgetFromOverview(std::move(item_widget_), animation_type);
   }
 }
 
@@ -370,22 +366,15 @@
           PerformItemSpawnedAnimation(item_widget_->GetNativeWindow(),
                                       gfx::Transform{});
         } else {
-          // Items that are slide in already have their slide in animations
-          // handled in |SlideWindowIn|.
-          const bool slide_in = overview_session_->enter_exit_overview_type() ==
-                                OverviewEnterExitType::kSlideInEnter;
-          if (!slide_in) {
-            // If entering from home launcher, use the home specific (fade)
-            // animation.
-            OverviewAnimationType fade_animation =
-                animation_type == OVERVIEW_ANIMATION_ENTER_FROM_HOME_LAUNCHER
-                    ? animation_type
-                    : OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN;
+          // If entering from home launcher, use the home specific (fade)
+          // animation.
+          OverviewAnimationType fade_animation =
+              animation_type == OVERVIEW_ANIMATION_ENTER_FROM_HOME_LAUNCHER
+                  ? animation_type
+                  : OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN;
 
-            FadeInWidgetAndMaybeSlideOnEnter(item_widget_.get(), fade_animation,
-                                             /*slide=*/false,
-                                             /*observe=*/true);
-          }
+          FadeInWidgetToOverview(item_widget_.get(), fade_animation,
+                                 /*observe=*/true);
 
           // Update the item header visibility immediately if entering from home
           // launcher.
@@ -616,20 +605,6 @@
   SetBounds(scaled_bounds, animation_type);
 }
 
-void OverviewItem::SlideWindowIn() {
-  // This only gets called if we see the home launcher on enter (all windows are
-  // minimized).
-  DCHECK(transform_window_.IsMinimized());
-
-  // The mask and shadow will be shown when animation ends. Update the mask
-  // after starting the animation since starting the animation lets the
-  // controller know we are in starting animation.
-  FadeInWidgetAndMaybeSlideOnEnter(item_widget_.get(),
-                                   OVERVIEW_ANIMATION_ENTER_FROM_HOME_LAUNCHER,
-                                   /*slide=*/true, /*observe=*/true);
-  UpdateRoundedCornersAndShadow();
-}
-
 std::unique_ptr<ui::ScopedLayerAnimationSettings>
 OverviewItem::UpdateYPositionAndOpacity(
     float new_grid_y,
@@ -805,9 +780,9 @@
     overview_item_view_->SetHeaderVisibility(
         OverviewItemView::HeaderVisibility::kVisible);
   } else {
-    FadeInWidgetAndMaybeSlideOnEnter(
-        item_widget_.get(), OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN,
-        /*slide=*/false, /*observe=*/false);
+    FadeInWidgetToOverview(item_widget_.get(),
+                           OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN,
+                           /*observe=*/false);
   }
   const bool show_backdrop =
       GetWindowDimensionsType() != OverviewGridWindowFillMode::kNormal;
@@ -1091,13 +1066,6 @@
   if (!prepared_for_overview_)
     return;
 
-  // When swiping away overview mode via shelf, windows will get minimized, but
-  // we do not want show a mirrored view in this case.
-  if (overview_session_->enter_exit_overview_type() ==
-      OverviewEnterExitType::kSwipeFromShelf) {
-    return;
-  }
-
   WindowStateType new_type = window_state->GetStateType();
   if (chromeos::IsMinimizedWindowStateType(old_type) ==
       chromeos::IsMinimizedWindowStateType(new_type)) {
diff --git a/ash/wm/overview/overview_item.h b/ash/wm/overview/overview_item.h
index 2a50d99..126f388 100644
--- a/ash/wm/overview/overview_item.h
+++ b/ash/wm/overview/overview_item.h
@@ -140,10 +140,6 @@
   // Increases the bounds of the dragged item.
   void ScaleUpSelectedItem(OverviewAnimationType animation_type);
 
-  // Shift the window item up and then animates it to its original spot. Used
-  // to transition from the home launcher.
-  void SlideWindowIn();
-
   // Translate and fade the window (or minimized widget) and |item_widget_|. It
   // should remain in the same spot relative to the grids origin, which is given
   // by |new_grid_y|. Returns the settings object of the layer the caller should
diff --git a/ash/wm/overview/overview_session.cc b/ash/wm/overview/overview_session.cc
index 6679569..a217a52 100644
--- a/ash/wm/overview/overview_session.cc
+++ b/ash/wm/overview/overview_session.cc
@@ -283,16 +283,8 @@
     // grid.
     if (enter_exit_overview_type_ == OverviewEnterExitType::kImmediateEnter) {
       overview_grid->PositionWindows(/*animate=*/false);
-    } else if (enter_exit_overview_type_ ==
-               OverviewEnterExitType::kSlideInEnter) {
-      overview_grid->PositionWindows(/*animate=*/false);
-      overview_grid->SlideWindowsIn();
     } else {
       // Exit only types should not appear here:
-      DCHECK_NE(enter_exit_overview_type_,
-                OverviewEnterExitType::kSwipeFromShelf);
-      DCHECK_NE(enter_exit_overview_type_,
-                OverviewEnterExitType::kSlideOutExit);
       DCHECK_NE(enter_exit_overview_type_, OverviewEnterExitType::kFadeOutExit);
 
       overview_grid->PositionWindows(/*animate=*/true, /*ignored_items=*/{},
@@ -406,9 +398,8 @@
 
     // Fade out the no windows widget. This animation continues past the
     // lifetime of |this|.
-    FadeOutWidgetAndMaybeSlideOnExit(std::move(no_windows_widget_),
-                                     OVERVIEW_ANIMATION_RESTORE_WINDOW,
-                                     /*slide=*/false);
+    FadeOutWidgetFromOverview(std::move(no_windows_widget_),
+                              OVERVIEW_ANIMATION_RESTORE_WINDOW);
   }
 }
 
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc
index 2eae3f2..a27684de1 100644
--- a/ash/wm/overview/overview_session_unittest.cc
+++ b/ash/wm/overview/overview_session_unittest.cc
@@ -5823,23 +5823,6 @@
           SplitViewController::LEFT, /*window_for_minimum_size=*/nullptr));
 }
 
-// Verify the behavior when trying to exit overview with one snapped window
-// is as expected.
-TEST_P(SplitViewOverviewSessionTest, ExitOverviewWithOneSnapped) {
-  std::unique_ptr<aura::Window> window(CreateWindow(gfx::Rect(400, 400)));
-
-  // Tests that we cannot exit overview when there is one snapped window and no
-  // windows in overview normally.
-  ToggleOverview();
-  split_view_controller()->SnapWindow(window.get(), SplitViewController::LEFT);
-  ToggleOverview();
-  ASSERT_TRUE(InOverviewSession());
-
-  // Tests that we can exit overview if we swipe up from the shelf.
-  ToggleOverview(OverviewEnterExitType::kSwipeFromShelf);
-  EXPECT_FALSE(InOverviewSession());
-}
-
 // Test that in tablet mode, pressing tab key in overview should not crash.
 TEST_P(SplitViewOverviewSessionTest, NoCrashWhenPressTabKey) {
   std::unique_ptr<aura::Window> window(CreateWindow(gfx::Rect(400, 400)));
diff --git a/ash/wm/overview/overview_types.h b/ash/wm/overview/overview_types.h
index a55b9b2..41b6f88 100644
--- a/ash/wm/overview/overview_types.h
+++ b/ash/wm/overview/overview_types.h
@@ -58,19 +58,6 @@
   // bounds. Window(s) that are not visible to the user do not get animated.
   // This should always be the type when in clamshell mode.
   kNormal,
-  // Slide all windows in to enter overview. This can happen when going from
-  // a state which all window(s) are minimized.
-  kSlideInEnter,
-  // Slide all windows out to exit overview. This can happen when going to
-  // a state which all window(s) are minimized. This will minimize windows on
-  // exit if needed, so that we do not need to add a delayed observer to
-  // handle minimizing the windows after overview exit animations are
-  // finished.
-  kSlideOutExit,
-  // Overview can be closed by swiping up from the shelf. In this mode, the
-  // call site will handle shifting the bounds of the windows, so overview
-  // code does not need to handle any animations. This is an exit only type.
-  kSwipeFromShelf,
   // Used only when it's desired to enter overview mode immediately without
   // animations. It's used when entering overview by dragging a window from
   // the top of the screen or from the shelf, or by long pressing the overview
diff --git a/ash/wm/overview/overview_utils.cc b/ash/wm/overview/overview_utils.cc
index b796c54d..9b7b4106 100644
--- a/ash/wm/overview/overview_utils.cc
+++ b/ash/wm/overview/overview_utils.cc
@@ -45,17 +45,6 @@
 
 namespace ash {
 
-namespace {
-
-// The transform applied to an overview item when animating to or from the home
-// launcher.
-const gfx::Transform& GetShiftTransform() {
-  static const base::NoDestructor<gfx::Transform> matrix(1, 0, 0, 1, 0, -100);
-  return *matrix;
-}
-
-}  // namespace
-
 bool CanCoverAvailableWorkspace(aura::Window* window) {
   SplitViewController* split_view_controller = SplitViewController::Get(window);
   if (split_view_controller->InSplitViewMode())
@@ -97,32 +86,19 @@
   return true;
 }
 
-void FadeInWidgetAndMaybeSlideOnEnter(views::Widget* widget,
-                                      OverviewAnimationType animation_type,
-                                      bool slide,
-                                      bool observe) {
+void FadeInWidgetToOverview(views::Widget* widget,
+                            OverviewAnimationType animation_type,
+                            bool observe) {
   aura::Window* window = widget->GetNativeWindow();
-  if (window->layer()->GetTargetOpacity() == 1.f && !slide)
+  if (window->layer()->GetTargetOpacity() == 1.f)
     return;
 
   gfx::Transform original_transform = window->transform();
-  if (slide) {
-    // Translate the window up before sliding down to |original_transform|.
-    gfx::Transform new_transform = original_transform;
-    new_transform.ConcatTransform(GetShiftTransform());
-    if (window->layer()->GetTargetOpacity() == 1.f &&
-        window->layer()->GetTargetTransform() == new_transform) {
-      return;
-    }
-    window->SetTransform(new_transform);
-  }
 
   // Fade in the widget from its current opacity.
   ScopedOverviewAnimationSettings scoped_overview_animation_settings(
       animation_type, window);
   window->layer()->SetOpacity(1.0f);
-  if (slide)
-    window->SetTransform(original_transform);
 
   if (observe) {
     auto enter_observer = std::make_unique<EnterAnimationObserver>();
@@ -132,9 +108,8 @@
   }
 }
 
-void FadeOutWidgetAndMaybeSlideOnExit(std::unique_ptr<views::Widget> widget,
-                                      OverviewAnimationType animation_type,
-                                      bool slide) {
+void FadeOutWidgetFromOverview(std::unique_ptr<views::Widget> widget,
+                               OverviewAnimationType animation_type) {
   // The overview controller may be nullptr on shutdown.
   OverviewController* controller = Shell::Get()->overview_controller();
   if (!controller) {
@@ -155,12 +130,6 @@
   animation_settings.AddObserver(observer.get());
   controller->AddExitAnimationObserver(std::move(observer));
   widget_ptr->SetOpacity(0.f);
-
-  if (slide) {
-    gfx::Transform new_transform = widget_ptr->GetNativeWindow()->transform();
-    new_transform.ConcatTransform(GetShiftTransform());
-    widget_ptr->GetNativeWindow()->SetTransform(new_transform);
-  }
 }
 
 void ImmediatelyCloseWidgetOnExit(std::unique_ptr<views::Widget> widget) {
diff --git a/ash/wm/overview/overview_utils.h b/ash/wm/overview/overview_utils.h
index 55caa36..340a8457 100644
--- a/ash/wm/overview/overview_utils.h
+++ b/ash/wm/overview/overview_utils.h
@@ -35,23 +35,19 @@
 // true otherwise.
 bool ShouldAnimateWallpaper(aura::Window* root_window);
 
-// Fades |widget| to opacity one with the enter overview settings. Additionally
-// place |widget| closer to the top of screen and slide it down if |slide| is
-// true. Have OverviewController observe this animation as a enter animation if
+// Fades |widget| to opacity one with the enter overview settings.
+// Have OverviewController observe this animation as a enter animation if
 // |observe| is true.
-void FadeInWidgetAndMaybeSlideOnEnter(views::Widget* widget,
-                                      OverviewAnimationType animation_type,
-                                      bool slide,
-                                      bool observe);
+void FadeInWidgetToOverview(views::Widget* widget,
+                            OverviewAnimationType animation_type,
+                            bool observe);
 
 // Fades |widget| to opacity zero with animation settings depending on
 // |animation_type|. Used by several classes which need to be destroyed on
 // exiting overview, but have some widgets which need to continue animating.
 // |widget| is destroyed after finishing animation.
-// If |slide| is true, the |widget| will slide closer to the top of the screen.
-void FadeOutWidgetAndMaybeSlideOnExit(std::unique_ptr<views::Widget> widget,
-                                      OverviewAnimationType animation_type,
-                                      bool slide);
+void FadeOutWidgetFromOverview(std::unique_ptr<views::Widget> widget,
+                               OverviewAnimationType animation_type);
 
 // Takes ownership of |widget|, closes and destroys it without any animations.
 void ImmediatelyCloseWidgetOnExit(std::unique_ptr<views::Widget> widget);
diff --git a/ash/wm/overview/scoped_overview_animation_settings.cc b/ash/wm/overview/scoped_overview_animation_settings.cc
index 863c7d0e..7464748a 100644
--- a/ash/wm/overview/scoped_overview_animation_settings.cc
+++ b/ash/wm/overview/scoped_overview_animation_settings.cc
@@ -39,8 +39,6 @@
     base::TimeDelta::FromMilliseconds(250);
 constexpr base::TimeDelta kHomeLauncherTransition =
     base::TimeDelta::FromMilliseconds(350);
-constexpr base::TimeDelta kHomeLauncherSlideTransition =
-    base::TimeDelta::FromMilliseconds(250);
 
 // Time duration of the show animation of the drop target.
 constexpr base::TimeDelta kDropTargetFade =
@@ -72,9 +70,7 @@
       return kCloseFadeOut;
     case OVERVIEW_ANIMATION_ENTER_FROM_HOME_LAUNCHER:
     case OVERVIEW_ANIMATION_EXIT_TO_HOME_LAUNCHER:
-      return features::IsDragFromShelfToHomeOrOverviewEnabled()
-                 ? kHomeLauncherTransition
-                 : kHomeLauncherSlideTransition;
+      return kHomeLauncherTransition;
     case OVERVIEW_ANIMATION_DROP_TARGET_FADE:
       return kDropTargetFade;
     case OVERVIEW_ANIMATION_NO_RECENTS_FADE:
@@ -148,17 +144,8 @@
       animation_settings_->SetPreemptionStrategy(
           ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
       // Add animation delay when entering from home launcher.
-      // Delay transform only when using slide animation (which is used
-      // if kDragFromShelfToHomeOrOverview is not enabled), as otherwise
-      // the overview item will only fade in.
-      if (features::IsDragFromShelfToHomeOrOverviewEnabled()) {
-        animator->SchedulePauseForProperties(
-            kFromHomeLauncherDelay, ui::LayerAnimationElement::OPACITY);
-      } else {
-        animator->SchedulePauseForProperties(
-            kFromHomeLauncherDelay, ui::LayerAnimationElement::OPACITY |
-                                        ui::LayerAnimationElement::TRANSFORM);
-      }
+      animator->SchedulePauseForProperties(kFromHomeLauncherDelay,
+                                           ui::LayerAnimationElement::OPACITY);
       break;
     case OVERVIEW_ANIMATION_EXIT_TO_HOME_LAUNCHER:
       animation_settings_->SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc
index 55fd0e65..ba0e455 100644
--- a/ash/wm/splitview/split_view_controller.cc
+++ b/ash/wm/splitview/split_view_controller.cc
@@ -1357,14 +1357,6 @@
     OverviewSession* overview_session) {
   DCHECK(InSplitViewMode());
 
-  // Early exit if overview is ended while swiping up on the shelf to avoid
-  // snapping a window or showing a toast.
-  if (overview_session->enter_exit_overview_type() ==
-      OverviewEnterExitType::kSwipeFromShelf) {
-    EndSplitView();
-    return;
-  }
-
   // If overview is ended because of a window getting snapped, suppress the
   // overview exiting animation.
   if (state_ == State::kBothSnapped)
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 5f62f2e..b66dfe8 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -3926,6 +3926,7 @@
     sources = [
       "android/junit/src/org/chromium/base/ApplicationStatusTest.java",
       "android/junit/src/org/chromium/base/CallbackControllerTest.java",
+      "android/junit/src/org/chromium/base/CollectionUtilTest.java",
       "android/junit/src/org/chromium/base/DiscardableReferencePoolTest.java",
       "android/junit/src/org/chromium/base/FileUtilsTest.java",
       "android/junit/src/org/chromium/base/LifetimeAssertTest.java",
diff --git a/base/allocator/allocator_shim.h b/base/allocator/allocator_shim.h
index 724a1ac..9c819a8 100644
--- a/base/allocator/allocator_shim.h
+++ b/base/allocator/allocator_shim.h
@@ -7,6 +7,7 @@
 
 #include <stddef.h>
 
+#include "base/allocator/buildflags.h"
 #include "base/base_export.h"
 #include "build/build_config.h"
 
@@ -150,6 +151,10 @@
 BASE_EXPORT void InitializeAllocatorShim();
 #endif  // defined(OS_APPLE)
 
+#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
+BASE_EXPORT void EnablePCScanIfNeeded();
+#endif
+
 }  // namespace allocator
 }  // namespace base
 
diff --git a/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc b/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc
index 1b18beb7..cb2bcbf 100644
--- a/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc
+++ b/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc
@@ -6,6 +6,7 @@
 #include "base/allocator/allocator_shim_internals.h"
 #include "base/allocator/partition_allocator/partition_alloc.h"
 #include "base/allocator/partition_allocator/partition_alloc_constants.h"
+#include "base/allocator/partition_allocator/partition_alloc_features.h"
 #include "base/bits.h"
 #include "base/no_destructor.h"
 #include "build/build_config.h"
@@ -78,7 +79,8 @@
 
   auto* new_root = new (g_allocator_buffer) base::ThreadSafePartitionRoot(
       {base::PartitionOptions::Alignment::kRegular,
-       base::PartitionOptions::ThreadCache::kEnabled});
+       base::PartitionOptions::ThreadCache::kEnabled,
+       base::PartitionOptions::PCScan::kDisabledByDefault});
   g_root_.store(new_root, std::memory_order_release);
 
   // Semantically equivalent to base::Lock::Release().
@@ -108,8 +110,10 @@
 base::ThreadSafePartitionRoot* AlignedAllocator() {
   // Since the general-purpose allocator uses the thread cache, this one cannot.
   static base::NoDestructor<base::ThreadSafePartitionRoot> aligned_allocator(
-      base::PartitionOptions{base::PartitionOptions::Alignment::kAlignedAlloc,
-                             base::PartitionOptions::ThreadCache::kDisabled});
+      base::PartitionOptions{
+          base::PartitionOptions::Alignment::kAlignedAlloc,
+          base::PartitionOptions::ThreadCache::kDisabled,
+          base::PartitionOptions::PCScan::kDisabledByDefault});
   return aligned_allocator.get();
 }
 
@@ -186,6 +190,21 @@
 
 }  // namespace
 
+namespace base {
+namespace allocator {
+
+#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
+void EnablePCScanIfNeeded() {
+  if (!features::IsPartitionAllocPCScanEnabled())
+    return;
+  Allocator().EnablePCScan();
+  AlignedAllocator()->EnablePCScan();
+}
+#endif
+
+}  // namespace allocator
+}  // namespace base
+
 constexpr AllocatorDispatch AllocatorDispatch::default_dispatch = {
     &PartitionMalloc,          /* alloc_function */
     &PartitionMallocUnchecked, /* alloc_unchecked_function */
diff --git a/base/allocator/partition_allocator/partition_alloc.cc b/base/allocator/partition_allocator/partition_alloc.cc
index 3a06ecc..266bfd6 100644
--- a/base/allocator/partition_allocator/partition_alloc.cc
+++ b/base/allocator/partition_allocator/partition_alloc.cc
@@ -18,6 +18,7 @@
 #include "base/allocator/partition_allocator/partition_direct_map_extent.h"
 #include "base/allocator/partition_allocator/partition_oom.h"
 #include "base/allocator/partition_allocator/partition_page.h"
+#include "base/allocator/partition_allocator/partition_root.h"
 #include "base/check_op.h"
 #include "base/no_destructor.h"
 #include "base/synchronization/lock.h"
@@ -278,6 +279,7 @@
   // the beginning of the slot.
   allow_extras = (opts.alignment != PartitionOptions::Alignment::kAlignedAlloc);
 
+  scannable = (opts.pcscan != PartitionOptions::PCScan::kAlwaysDisabled);
   // Concurrent freeing in PCScan can only safely work on thread-safe
   // partitions.
   if (thread_safe && opts.pcscan == PartitionOptions::PCScan::kEnabled)
diff --git a/base/allocator/partition_allocator/partition_alloc.h b/base/allocator/partition_allocator/partition_alloc.h
index 523e03db..e0749d24 100644
--- a/base/allocator/partition_allocator/partition_alloc.h
+++ b/base/allocator/partition_allocator/partition_alloc.h
@@ -80,7 +80,6 @@
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
 #include "base/notreached.h"
-#include "base/optional.h"
 #include "base/partition_alloc_buildflags.h"
 #include "base/stl_util.h"
 #include "base/synchronization/lock.h"
diff --git a/base/allocator/partition_allocator/partition_bucket.cc b/base/allocator/partition_allocator/partition_bucket.cc
index 9bcab15..617337d 100644
--- a/base/allocator/partition_allocator/partition_bucket.cc
+++ b/base/allocator/partition_allocator/partition_bucket.cc
@@ -291,12 +291,12 @@
   char* tag_bitmap = super_page + PartitionPageSize();
   char* quarantine_bitmaps = tag_bitmap + ReservedTagBitmapSize();
   const size_t quarantine_bitmaps_size =
-      root->pcscan ? 2 * sizeof(QuarantineBitmap) : 0;
+      root->scannable ? 2 * sizeof(QuarantineBitmap) : 0;
   PA_DCHECK(quarantine_bitmaps_size % PartitionPageSize() == 0);
   char* ret = quarantine_bitmaps + quarantine_bitmaps_size;
   root->next_partition_page = ret + total_size;
   root->next_partition_page_end = root->next_super_page - PartitionPageSize();
-  PA_DCHECK(ret == SuperPagePayloadBegin(super_page, root->pcscan.has_value()));
+  PA_DCHECK(ret == SuperPagePayloadBegin(super_page, root->scannable));
   PA_DCHECK(root->next_partition_page_end == SuperPagePayloadEnd(super_page));
 
   // The first slot span is accessible. The given committed_size is equal to
diff --git a/base/allocator/partition_allocator/partition_root.h b/base/allocator/partition_allocator/partition_root.h
index 37cf9b72..955357f7 100644
--- a/base/allocator/partition_allocator/partition_root.h
+++ b/base/allocator/partition_allocator/partition_root.h
@@ -13,6 +13,7 @@
 #include "base/allocator/partition_allocator/partition_tag.h"
 #include "base/allocator/partition_allocator/pcscan.h"
 #include "base/allocator/partition_allocator/thread_cache.h"
+#include "base/optional.h"
 
 namespace base {
 
@@ -40,13 +41,20 @@
   };
 
   enum class PCScan {
-    kDisabled,
+    // Should be used for value partitions, i.e. partitions that are known to
+    // not have pointers. No metadata (quarantine bitmaps) is allocated for such
+    // partitions.
+    kAlwaysDisabled,
+    // PCScan is disabled by default, but can be enabled by calling
+    // PartitionRoot::EnablePCScan().
+    kDisabledByDefault,
+    // PCScan is always enabled.
     kEnabled,
   };
 
   Alignment alignment = Alignment::kRegular;
   ThreadCache thread_cache = ThreadCache::kDisabled;
-  PCScan pcscan = PCScan::kDisabled;
+  PCScan pcscan = PCScan::kAlwaysDisabled;
 };
 
 // Never instantiate a PartitionRoot directly, instead use
@@ -70,6 +78,7 @@
   // nothing) instead of true|false, so that we can just add or subtract the
   // size instead of having an if branch on the hot paths.
   bool allow_extras;
+  bool scannable = false;
   bool initialized = false;
 
 #if ENABLE_TAG_FOR_CHECKED_PTR2 || ENABLE_TAG_FOR_MTE_CHECKED_PTR
@@ -225,6 +234,13 @@
     return features::IsPartitionAllocGigaCageEnabled() && allow_extras;
   }
 
+  void EnablePCScan() {
+    // TODO(bikineev): Make CHECK once PCScan is enabled.
+    if (!scannable || pcscan.has_value())
+      return;
+    pcscan.emplace(this);
+  }
+
  private:
   // Allocates memory, without initializing extras.
   //
diff --git a/base/allocator/partition_allocator/pcscan.cc b/base/allocator/partition_allocator/pcscan.cc
index 3cfea47..abe05818 100644
--- a/base/allocator/partition_allocator/pcscan.cc
+++ b/base/allocator/partition_allocator/pcscan.cc
@@ -34,7 +34,7 @@
   static base::NoDestructor<ThreadSafePartitionRoot> allocator{
       PartitionOptions{PartitionOptions::Alignment::kRegular,
                        PartitionOptions::ThreadCache::kDisabled,
-                       PartitionOptions::PCScan::kDisabled}};
+                       PartitionOptions::PCScan::kAlwaysDisabled}};
   return *allocator;
 }
 
diff --git a/base/android/java/src/org/chromium/base/CallbackController.java b/base/android/java/src/org/chromium/base/CallbackController.java
index cb55ce0c..be0070a 100644
--- a/base/android/java/src/org/chromium/base/CallbackController.java
+++ b/base/android/java/src/org/chromium/base/CallbackController.java
@@ -207,9 +207,8 @@
     public void destroy() {
         try (AutoCloseableLock acl = AutoCloseableLock.lock(mReadWriteLock.writeLock())) {
             checkNotCanceled();
-            for (WeakReference<Cancelable> cancelableWeakReference : mCancelables) {
-                Cancelable cancelable = cancelableWeakReference.get();
-                if (cancelable != null) cancelable.cancel();
+            for (Cancelable cancelable : CollectionUtil.strengthen(mCancelables)) {
+                cancelable.cancel();
             }
             mCancelables = null;
         }
diff --git a/base/android/java/src/org/chromium/base/CollectionUtil.java b/base/android/java/src/org/chromium/base/CollectionUtil.java
index 7e4c5b2..fc22c006 100644
--- a/base/android/java/src/org/chromium/base/CollectionUtil.java
+++ b/base/android/java/src/org/chromium/base/CollectionUtil.java
@@ -8,10 +8,13 @@
 
 import androidx.annotation.NonNull;
 
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -80,4 +83,28 @@
             worker.onResult((Map.Entry<K, V>) entry);
         }
     }
+
+    /**
+     * Removes null entries from the given collection and then returns a list of strong references.
+     *
+     * Note: This helper is relevant if you have a List<WeakReference<T>> or a Map with weak values.
+     * For Set<WeakReference<T>>, use Collections.newSetFromMap(new WeakHashMap()) instead.
+     *
+     * @param weakRefs Collection to iterate.
+     * @return List of strong references.
+     */
+    public static <T> List<T> strengthen(Collection<WeakReference<T>> weakRefs) {
+        ArrayList<T> ret = new ArrayList<>(weakRefs.size());
+        Iterator<WeakReference<T>> it = weakRefs.iterator();
+        while (it.hasNext()) {
+            WeakReference<T> weakRef = it.next();
+            T strongRef = weakRef.get();
+            if (strongRef == null) {
+                it.remove();
+            } else {
+                ret.add(strongRef);
+            }
+        }
+        return ret;
+    }
 }
diff --git a/base/android/java/src/org/chromium/base/UnownedUserDataKey.java b/base/android/java/src/org/chromium/base/UnownedUserDataKey.java
index 6034907..38b10b3 100644
--- a/base/android/java/src/org/chromium/base/UnownedUserDataKey.java
+++ b/base/android/java/src/org/chromium/base/UnownedUserDataKey.java
@@ -8,12 +8,11 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
-import java.lang.ref.WeakReference;
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
+import java.util.Collections;
 import java.util.Objects;
 import java.util.Set;
+import java.util.WeakHashMap;
 
 /**
  * UnownedUserDataKey is used in conjunction with a particular {@link UnownedUserData} as the key
@@ -63,7 +62,9 @@
 public final class UnownedUserDataKey<T extends UnownedUserData> {
     @NonNull
     private final Class<T> mClazz;
-    private final Set<WeakReference<UnownedUserDataHost>> mHostAttachments = new HashSet<>();
+    // A Set that uses WeakReference<UnownedUserDataHost> internally.
+    private final Set<UnownedUserDataHost> mWeakHostAttachments =
+            Collections.newSetFromMap(new WeakHashMap<>());
 
     /**
      * Constructs a key to use for attaching to a particular {@link UnownedUserDataHost}.
@@ -93,7 +94,7 @@
         host.set(this, object);
 
         if (!isAttachedToHost(host)) {
-            mHostAttachments.add(new WeakReference<>(host));
+            mWeakHostAttachments.add(host);
         }
     }
 
@@ -108,7 +109,8 @@
      */
     @Nullable
     public final T retrieveDataFromHost(@NonNull UnownedUserDataHost host) {
-        for (UnownedUserDataHost attachedHost : getStrongRefs()) {
+        assertNoDestroyedAttachments();
+        for (UnownedUserDataHost attachedHost : mWeakHostAttachments) {
             if (host.equals(attachedHost)) {
                 return host.get(this);
             }
@@ -123,7 +125,8 @@
      * @param host The host to detach from.
      */
     public final void detachFromHost(@NonNull UnownedUserDataHost host) {
-        for (UnownedUserDataHost attachedHost : getStrongRefs()) {
+        assertNoDestroyedAttachments();
+        for (UnownedUserDataHost attachedHost : new ArrayList<>(mWeakHostAttachments)) {
             if (host.equals(attachedHost)) {
                 removeHostAttachment(attachedHost);
             }
@@ -135,7 +138,8 @@
      * this key. It is OK to call this for already detached objects.
      */
     public final void detachFromAllHosts(@NonNull T object) {
-        for (UnownedUserDataHost attachedHost : getStrongRefs()) {
+        assertNoDestroyedAttachments();
+        for (UnownedUserDataHost attachedHost : new ArrayList<>(mWeakHostAttachments)) {
             if (object.equals(attachedHost.get(this))) {
                 removeHostAttachment(attachedHost);
             }
@@ -162,8 +166,9 @@
 
     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
     /* package */ int getHostAttachmentCount(@NonNull T object) {
+        assertNoDestroyedAttachments();
         int ret = 0;
-        for (UnownedUserDataHost attachedHost : getStrongRefs()) {
+        for (UnownedUserDataHost attachedHost : mWeakHostAttachments) {
             if (object.equals(attachedHost.get(this))) {
                 ret++;
             }
@@ -173,32 +178,17 @@
 
     private void removeHostAttachment(UnownedUserDataHost host) {
         host.remove(this);
-        for (WeakReference<UnownedUserDataHost> hostWeakReference : mHostAttachments) {
-            if (host.equals(hostWeakReference.get())) {
-                // Modifying mHostAttachments while iterating over it is okay here because we
-                // break out of the loop right away.
-                mHostAttachments.remove(hostWeakReference);
-                return;
-            }
-        }
+        mWeakHostAttachments.remove(host);
     }
 
-    // TODO(https://crbug.com/1131047): Make a //base helper for this.
-    private Collection<UnownedUserDataHost> getStrongRefs() {
-        ArrayList<UnownedUserDataHost> ret = new ArrayList<>();
-        Set<WeakReference<UnownedUserDataHost>> hosts = new HashSet<>(mHostAttachments);
-        for (WeakReference<UnownedUserDataHost> hostWeakReference : hosts) {
-            UnownedUserDataHost hostStrongReference = hostWeakReference.get();
-            if (hostStrongReference == null) {
-                mHostAttachments.remove(hostWeakReference);
-                continue;
+    private void assertNoDestroyedAttachments() {
+        if (BuildConfig.DCHECK_IS_ON) {
+            for (UnownedUserDataHost attachedHost : mWeakHostAttachments) {
+                if (attachedHost.isDestroyed()) {
+                    assert false : "Host should have been removed already.";
+                    throw new IllegalStateException();
+                }
             }
-            if (hostStrongReference.isDestroyed()) {
-                assert false : "Host should have been removed already.";
-                throw new IllegalStateException();
-            }
-            ret.add(hostStrongReference);
         }
-        return ret;
     }
 }
diff --git a/base/android/junit/src/org/chromium/base/CollectionUtilTest.java b/base/android/junit/src/org/chromium/base/CollectionUtilTest.java
new file mode 100644
index 0000000..90a1c20
--- /dev/null
+++ b/base/android/junit/src/org/chromium/base/CollectionUtilTest.java
@@ -0,0 +1,37 @@
+// 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.
+
+package org.chromium.base;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/** Unit tests for {@link Log}. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class CollectionUtilTest {
+    /** Tests that the computed call origin is the correct one. */
+    @Test
+    public void testStrengthen() {
+        // Java never GC's small constants, so there's no risk of the weak refs becoming null.
+        ArrayList<WeakReference<Integer>> weakList = new ArrayList<>();
+        weakList.add(new WeakReference<>(0));
+        weakList.add(new WeakReference<>(1));
+        weakList.add(new WeakReference<>(2));
+
+        assertEquals(Arrays.asList(0, 1, 2), CollectionUtil.strengthen(weakList));
+
+        weakList.set(1, new WeakReference<>(null));
+        assertEquals(Arrays.asList(0, 2), CollectionUtil.strengthen(weakList));
+    }
+}
diff --git a/base/fuchsia/scoped_service_binding.h b/base/fuchsia/scoped_service_binding.h
index 9da1218..44913f76 100644
--- a/base/fuchsia/scoped_service_binding.h
+++ b/base/fuchsia/scoped_service_binding.h
@@ -73,11 +73,13 @@
  public:
   // |outgoing_directory| and |impl| must outlive the binding.
   ScopedSingleClientServiceBinding(sys::OutgoingDirectory* outgoing_directory,
-                                   Interface* impl)
+                                   Interface* impl,
+                                   std::string name = Interface::Name_)
       : binding_(impl) {
     publisher_.emplace(
         outgoing_directory,
-        fit::bind_member(this, &ScopedSingleClientServiceBinding::BindClient));
+        fit::bind_member(this, &ScopedSingleClientServiceBinding::BindClient),
+                         std::move(name));
     binding_.set_error_handler(fit::bind_member(
         this, &ScopedSingleClientServiceBinding::OnBindingEmpty));
   }
diff --git a/base/fuchsia/scoped_service_binding_unittest.cc b/base/fuchsia/scoped_service_binding_unittest.cc
index a01bae3..dd0474e 100644
--- a/base/fuchsia/scoped_service_binding_unittest.cc
+++ b/base/fuchsia/scoped_service_binding_unittest.cc
@@ -21,6 +21,19 @@
   VerifyTestInterface(&stub2, ZX_OK);
 }
 
+// Verifies that ScopedSingleClientServiceBinding allows a different name.
+TEST_F(ScopedServiceBindingTest, SingleClientConnectNewName) {
+  const std::string interface_name = "fuchsia.TestInterface2";
+  auto service_binding_new_name_ = std::make_unique<
+      ScopedSingleClientServiceBinding<testfidl::TestInterface>>(
+          outgoing_directory_.get(), &test_service_, interface_name);
+
+  testfidl::TestInterfacePtr stub;
+  public_service_directory_->Connect(interface_name,
+                                     stub.NewRequest().TakeChannel());
+  VerifyTestInterface(&stub, ZX_OK);
+}
+
 // Verify that if we connect twice to a prefer-new bound service, the existing
 // connection gets closed.
 TEST_F(ScopedServiceBindingTest, SingleClientPreferNew) {
diff --git a/base/fuchsia/scoped_service_publisher.h b/base/fuchsia/scoped_service_publisher.h
index 60eb1cf4..3c9986e7 100644
--- a/base/fuchsia/scoped_service_publisher.h
+++ b/base/fuchsia/scoped_service_publisher.h
@@ -24,24 +24,26 @@
   // Publishes a public service in the specified |outgoing_directory|.
   // |outgoing_directory| and |handler| must outlive the binding.
   ScopedServicePublisher(sys::OutgoingDirectory* outgoing_directory,
-                         fidl::InterfaceRequestHandler<Interface> handler)
+                         fidl::InterfaceRequestHandler<Interface> handler,
+                         std::string name = Interface::Name_)
       : ScopedServicePublisher(outgoing_directory->GetOrCreateDirectory("svc"),
-                               std::move(handler)) {}
+                               std::move(handler), std::move(name)) {}
 
   // Publishes a service in the specified |pseudo_dir|. |pseudo_dir| and
   // |handler| must outlive the binding.
   ScopedServicePublisher(vfs::PseudoDir* pseudo_dir,
-                         fidl::InterfaceRequestHandler<Interface> handler)
-      : pseudo_dir_(pseudo_dir) {
-    pseudo_dir_->AddEntry(Interface::Name_,
+                         fidl::InterfaceRequestHandler<Interface> handler,
+                         std::string name = Interface::Name_)
+      : pseudo_dir_(pseudo_dir), name_(std::move(name)) {
+    pseudo_dir_->AddEntry(name_,
                           std::make_unique<vfs::Service>(std::move(handler)));
   }
 
-  ~ScopedServicePublisher() { pseudo_dir_->RemoveEntry(Interface::Name_); }
+  ~ScopedServicePublisher() { pseudo_dir_->RemoveEntry(name_); }
 
  private:
   vfs::PseudoDir* const pseudo_dir_ = nullptr;
-
+  std::string name_;
   DISALLOW_COPY_AND_ASSIGN(ScopedServicePublisher);
 };
 
diff --git a/base/metrics/field_trial_params.h b/base/metrics/field_trial_params.h
index c44e719..577c341 100644
--- a/base/metrics/field_trial_params.h
+++ b/base/metrics/field_trial_params.h
@@ -121,6 +121,9 @@
 //
 // See the individual definitions below for the appropriate interfaces.
 // Attempting to use it with any other type is a compile error.
+//
+// Getting a param value from a FeatureParam<T> will have the same semantics as
+// GetFieldTrialParamValueByFeature(), see that function's comments for details.
 template <typename T, bool IsEnum = std::is_enum<T>::value>
 struct FeatureParam {
   // Prevent use of FeatureParam<> with unsupported types (e.g. void*). Uses T
@@ -134,8 +137,8 @@
 //     constexpr FeatureParam<string> kAssistantName{
 //         &kAssistantFeature, "assistant_name", "HAL"};
 //
-// If the feature is not set, or set to the empty string, then Get() will return
-// the default value.
+// If the parameter is not set, or set to the empty string, then Get() will
+// return the default value.
 template <>
 struct FeatureParam<std::string> {
   constexpr FeatureParam(const Feature* feature,
@@ -143,6 +146,8 @@
                          const char* default_value)
       : feature(feature), name(name), default_value(default_value) {}
 
+  // Calling Get() will activate the field trial associated with |feature|. See
+  // GetFieldTrialParamValueByFeature() for more details.
   BASE_EXPORT std::string Get() const;
 
   const Feature* const feature;
@@ -155,8 +160,8 @@
 //     constexpr FeatureParam<double> kAssistantTriggerThreshold{
 //         &kAssistantFeature, "trigger_threshold", 0.10};
 //
-// If the feature is not set, or set to an invalid double value, then Get() will
-// return the default value.
+// If the parameter is not set, or set to an invalid double value, then Get()
+// will return the default value.
 template <>
 struct FeatureParam<double> {
   constexpr FeatureParam(const Feature* feature,
@@ -164,6 +169,8 @@
                          double default_value)
       : feature(feature), name(name), default_value(default_value) {}
 
+  // Calling Get() will activate the field trial associated with |feature|. See
+  // GetFieldTrialParamValueByFeature() for more details.
   BASE_EXPORT double Get() const;
 
   const Feature* const feature;
@@ -176,7 +183,7 @@
 //     constexpr FeatureParam<int> kAssistantParallelism{
 //         &kAssistantFeature, "parallelism", 4};
 //
-// If the feature is not set, or set to an invalid int value, then Get() will
+// If the parameter is not set, or set to an invalid int value, then Get() will
 // return the default value.
 template <>
 struct FeatureParam<int> {
@@ -185,6 +192,8 @@
                          int default_value)
       : feature(feature), name(name), default_value(default_value) {}
 
+  // Calling Get() will activate the field trial associated with |feature|. See
+  // GetFieldTrialParamValueByFeature() for more details.
   BASE_EXPORT int Get() const;
 
   const Feature* const feature;
@@ -197,8 +206,8 @@
 //     constexpr FeatureParam<int> kAssistantIsHelpful{
 //         &kAssistantFeature, "is_helpful", true};
 //
-// If the feature is not set, or set to value other than "true" or "false", then
-// Get() will return the default value.
+// If the parameter is not set, or set to value other than "true" or "false",
+// then Get() will return the default value.
 template <>
 struct FeatureParam<bool> {
   constexpr FeatureParam(const Feature* feature,
@@ -206,6 +215,8 @@
                          bool default_value)
       : feature(feature), name(name), default_value(default_value) {}
 
+  // Calling Get() will activate the field trial associated with |feature|. See
+  // GetFieldTrialParamValueByFeature() for more details.
   BASE_EXPORT bool Get() const;
 
   const Feature* const feature;
@@ -218,7 +229,7 @@
 //     constexpr base::FeatureParam<base::TimeDelta> kPerAgentDelayMs{
 //         &kPerAgentSchedulingExperiments, "delay_ms", base::TimeDelta()};
 //
-// If the feature is not set, or set to an invalid value (as defined by
+// If the parameter is not set, or set to an invalid value (as defined by
 // base::TimeDelta::FromString()), then Get() will return the default value.
 template <>
 struct FeatureParam<base::TimeDelta> {
@@ -227,6 +238,8 @@
                          base::TimeDelta default_value)
       : feature(feature), name(name), default_value(default_value) {}
 
+  // Calling Get() will activate the field trial associated with |feature|. See
+  // GetFieldTrialParamValueByFeature() for more details.
   BASE_EXPORT base::TimeDelta Get() const;
 
   const Feature* const feature;
@@ -274,6 +287,8 @@
     static_assert(option_count >= 1, "FeatureParam<enum> has no options");
   }
 
+  // Calling Get() will activate the field trial associated with |feature|. See
+  // GetFieldTrialParamValueByFeature() for more details.
   Enum Get() const {
     std::string value = GetFieldTrialParamValueByFeature(*feature, name);
     if (value.empty())
diff --git a/base/numerics/safe_conversions_impl.h b/base/numerics/safe_conversions_impl.h
index 7c5ca68..c1f8f7c 100644
--- a/base/numerics/safe_conversions_impl.h
+++ b/base/numerics/safe_conversions_impl.h
@@ -378,9 +378,17 @@
     using SrcLimits = std::numeric_limits<Src>;
     using DstLimits = NarrowingRange<Dst, Src, Bounds>;
     using Promotion = decltype(Src() + Dst());
+    bool ge_zero = false;
+    // Converting floating-point to integer will discard fractional part, so
+    // values in (-1.0, -0.0) will truncate to 0 and fit in Dst.
+    if (std::is_floating_point<Src>::value) {
+      ge_zero = value > Src(-1);
+    } else {
+      ge_zero = value >= Src(0);
+    }
     return RangeCheck(
-        value >= Src(0) && (DstLimits::lowest() == 0 ||
-                            static_cast<Dst>(value) >= DstLimits::lowest()),
+        ge_zero && (DstLimits::lowest() == 0 ||
+                    static_cast<Dst>(value) >= DstLimits::lowest()),
         static_cast<Promotion>(SrcLimits::max()) <=
                 static_cast<Promotion>(DstLimits::max()) ||
             static_cast<Promotion>(value) <=
diff --git a/base/safe_numerics_unittest.cc b/base/safe_numerics_unittest.cc
index 7413731..8e2637b 100644
--- a/base/safe_numerics_unittest.cc
+++ b/base/safe_numerics_unittest.cc
@@ -1535,6 +1535,11 @@
   EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
       std::numeric_limits<int64_t>::lowest()));
 
+  // Converting to integer types will discard the fractional part first, so -0.9
+  // will be truncated to -0.0.
+  EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(-0.9));
+  EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1.0));
+
   EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0));
   EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1));
   EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2));
@@ -1569,6 +1574,11 @@
   EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
       std::numeric_limits<int64_t>::lowest()));
 
+  // Converting to integer types will discard the fractional part first, so -0.9
+  // will be truncated to -0.0.
+  EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(-0.9));
+  EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1.0));
+
   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0));
   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1));
   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2));
diff --git a/base/test/metrics/histogram_tester.cc b/base/test/metrics/histogram_tester.cc
index 5977a95..96a53d2 100644
--- a/base/test/metrics/histogram_tester.cc
+++ b/base/test/metrics/histogram_tester.cc
@@ -41,7 +41,7 @@
   } else {
     // No histogram means there were zero samples.
     EXPECT_EQ(0, expected_count)
-        << "Histogram \"" << name << "\" does not exist.";
+        << "Zero samples found for Histogram \"" << name << "\".";
   }
 }
 
diff --git a/base/threading/OWNERS b/base/threading/OWNERS
new file mode 100644
index 0000000..da064da
--- /dev/null
+++ b/base/threading/OWNERS
@@ -0,0 +1,4 @@
+# For HangWatcher implementation and tests:
+per-file hang_watcher*=olivierli@chromium.org
+
+# COMPONENT: Internals>Core
diff --git a/base/threading/hang_watcher_unittest.cc b/base/threading/hang_watcher_unittest.cc
index c88be8c..1ffd9a3d 100644
--- a/base/threading/hang_watcher_unittest.cc
+++ b/base/threading/hang_watcher_unittest.cc
@@ -23,6 +23,7 @@
 #include "base/threading/thread_checker.h"
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
+#include "build/build_config.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -900,9 +901,19 @@
   VerifyScopesDontBlock();
 }
 
+#if defined(OS_MAC) && defined(ARCH_CPU_ARM64)
+// Flaky hangs on arm64 Macs: https://crbug.com/1140207
+#define MAYBE_NewScopeDoesNotBlockDuringCapture \
+  DISABLED_NewScopeDoesNotBlockDuringCapture
+#else
+#define MAYBE_NewScopeDoesNotBlockDuringCapture \
+  NewScopeDoesNotBlockDuringCapture
+#endif
+
 // Test that execution does not block in ~HangWatchScopeEnabled() when the scope
 // was created after the start of a capture.
-TEST_F(HangWatchScopeEnabledBlockingTest, NewScopeDoesNotBlockDuringCapture) {
+TEST_F(HangWatchScopeEnabledBlockingTest,
+       MAYBE_NewScopeDoesNotBlockDuringCapture) {
   // Start a HangWatchScopeEnabled that expires right away. Ensures that the
   // first monitor will detect a hang.
   HangWatchScopeEnabled expires_right_away(base::TimeDelta{});
diff --git a/base/threading/sequence_bound.h b/base/threading/sequence_bound.h
index b7299ed..7a5fe8c 100644
--- a/base/threading/sequence_bound.h
+++ b/base/threading/sequence_bound.h
@@ -182,14 +182,14 @@
   // to a const lvalue reference) is not allowed.
   template <typename R, typename... Args>
   auto AsyncCall(R (T::*method)(Args...),
-                 const Location& location = Location::Current()) {
+                 const Location& location = Location::Current()) const {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     return AsyncCallBuilder<R (T::*)(Args...)>(this, &location, method);
   }
 
   template <typename R, typename... Args>
   auto AsyncCall(R (T::*method)(Args...) const,
-                 const Location& location = Location::Current()) {
+                 const Location& location = Location::Current()) const {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     return AsyncCallBuilder<R (T::*)(Args...) const>(this, &location, method);
   }
@@ -329,13 +329,14 @@
   template <typename MethodPtrType>
   class AsyncCallBuilderBase {
    protected:
-    AsyncCallBuilderBase(SequenceBound* sequence_bound,
+    AsyncCallBuilderBase(const SequenceBound* sequence_bound,
                          const Location* location,
                          MethodPtrType method)
         : sequence_bound_(sequence_bound),
           location_(location),
           method_(method) {
       // Common entry point for `AsyncCall()`, so check preconditions here.
+      DCHECK(sequence_bound_);
       DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_bound_->sequence_checker_);
       DCHECK(sequence_bound_->t_);
     }
@@ -358,7 +359,7 @@
     //   destructor will `CHECK()` if `sequence_bound_` is non-null, since that
     //   indicates `Then()` was not invoked. Similarly, note this branch should
     //   be eliminated by the optimizer if the code is free of bugs. :)
-    SequenceBound* sequence_bound_;
+    const SequenceBound* sequence_bound_;
     // Subtle: this typically points at a Location *temporary*. This is used to
     // try to detect errors resulting from lifetime extension of the async call
     // factory temporaries, since the factory destructors can perform work. If
@@ -455,7 +456,7 @@
 
     template <typename... BoundArgs>
     auto WithArgs(BoundArgs&&... bound_args) {
-      SequenceBound* const sequence_bound =
+      const SequenceBound* const sequence_bound =
           std::exchange(this->sequence_bound_, nullptr);
       return AsyncCallWithBoundArgsBuilder<ReturnType>(
           sequence_bound, this->location_,
@@ -482,12 +483,13 @@
   template <typename ReturnType>
   class AsyncCallWithBoundArgsBuilderBase {
    protected:
-    AsyncCallWithBoundArgsBuilderBase(SequenceBound* sequence_bound,
+    AsyncCallWithBoundArgsBuilderBase(const SequenceBound* sequence_bound,
                                       const Location* location,
                                       base::OnceCallback<ReturnType()> callback)
         : sequence_bound_(sequence_bound),
           location_(location),
           callback_(std::move(callback)) {
+      DCHECK(sequence_bound_);
       DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_bound_->sequence_checker_);
       DCHECK(sequence_bound_->t_);
     }
@@ -501,7 +503,7 @@
     AsyncCallWithBoundArgsBuilderBase& operator=(
         AsyncCallWithBoundArgsBuilderBase&&) noexcept = default;
 
-    SequenceBound* sequence_bound_;
+    const SequenceBound* sequence_bound_;
     const Location* const location_;
     base::OnceCallback<ReturnType()> callback_;
   };
@@ -580,7 +582,7 @@
 
   void PostTaskAndThenHelper(const Location& location,
                              OnceCallback<void()> callback,
-                             OnceClosure then_callback) {
+                             OnceClosure then_callback) const {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     impl_task_runner_->PostTaskAndReply(location, std::move(callback),
                                         std::move(then_callback));
@@ -593,7 +595,7 @@
             typename = EnableIfIsBaseCallback<CallbackType>>
   void PostTaskAndThenHelper(const Location& location,
                              OnceCallback<ReturnType()> callback,
-                             CallbackType<void(ThenArg)> then_callback) {
+                             CallbackType<void(ThenArg)> then_callback) const {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     OnceCallback<void(ThenArg)>&& once_then_callback = std::move(then_callback);
     impl_task_runner_->PostTaskAndReplyWithResult(
diff --git a/base/threading/sequence_bound_unittest.cc b/base/threading/sequence_bound_unittest.cc
index 1b75d1b..c9d9c00 100644
--- a/base/threading/sequence_bound_unittest.cc
+++ b/base/threading/sequence_bound_unittest.cc
@@ -615,6 +615,14 @@
   }
 }
 
+TEST_F(SequenceBoundTest, AsyncCallIsConstQualified) {
+  // Tests that both const and non-const methods may be called through a
+  // const-qualified SequenceBound.
+  const SequenceBound<NoArgsVoidReturn> s(task_runner_);
+  s.AsyncCall(&NoArgsVoidReturn::ConstMethod);
+  s.AsyncCall(&NoArgsVoidReturn::Method);
+}
+
 // TODO(dcheng): Maybe use the nocompile harness here instead of being
 // "clever"...
 TEST_F(SequenceBoundTest, NoCompileTests) {
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 90fb5ca..37a1c0c 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-0.20201020.3.1
+0.20201021.3.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 90fb5ca..37a1c0c 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-0.20201020.3.1
+0.20201021.3.1
diff --git a/build/mac_toolchain.py b/build/mac_toolchain.py
index 1100382..09cd980 100755
--- a/build/mac_toolchain.py
+++ b/build/mac_toolchain.py
@@ -31,9 +31,9 @@
 # To build these packages, see comments in build/xcode_binaries.yaml
 MAC_BINARIES_LABEL = 'infra_internal/ios/xcode/xcode_binaries/mac-amd64'
 MAC_BINARIES_TAG = {
-    # This contains binaries from Xcode 12.0.1, along with the 10.15 SDK (aka
-    # 12A7300).
-    'default': '89j_tSMJj0_9hMbceEg-P-VmiY_4CeYwsPE1e_zzRPcC',
+    # This contains binaries from Xcode 12.1, along with the 10.15 SDK (aka
+    # 12A7403).
+    'default': '77fpfpUrA6kBF3yEaMBEvWHOomBWqoiRT3bEJ4bXxvUC',
     # This contains binaries from Xcode 12.2 beta 3, along with the
     # 11 SDK (aka 12B5035g).
     'xcode_12_beta': 'Hbv2yK-6odRW8p2nfq7EZyaOWRpcEiMn5mvZpG9exTwC',
diff --git a/build/toolchain/mac/linker_driver.py b/build/toolchain/mac/linker_driver.py
index 453259a..66c97af8 100755
--- a/build/toolchain/mac/linker_driver.py
+++ b/build/toolchain/mac/linker_driver.py
@@ -160,7 +160,14 @@
 
   # Remove old dSYMs before invoking dsymutil.
   _RemovePath(dsym_out)
-  subprocess.check_call(DSYMUTIL_INVOKE + ['-o', dsym_out, linker_out])
+
+  tools_paths = _FindToolsPaths(full_args)
+  if os.environ.get('PATH'):
+    tools_paths.append(os.environ['PATH'])
+  dsymutil_env = os.environ.copy()
+  dsymutil_env['PATH'] = ':'.join(tools_paths)
+  subprocess.check_call(DSYMUTIL_INVOKE + ['-o', dsym_out, linker_out],
+                        env=dsymutil_env)
   return [dsym_out]
 
 
@@ -259,6 +266,19 @@
   return full_args[output_flag_index + 1]
 
 
+def _FindToolsPaths(full_args):
+  """Finds all paths where the script should look for additional tools."""
+  paths = []
+  for idx, arg in enumerate(full_args):
+    if arg in ['-B', '--prefix']:
+      paths.append(full_args[idx + 1])
+    elif arg.startswith('-B'):
+      paths.append(arg[2:])
+    elif arg.startswith('--prefix='):
+      paths.append(arg[9:])
+  return paths
+
+
 def _RemovePath(path):
   """Removes the file or directory at |path| if it exists."""
   if os.path.exists(path):
diff --git a/build/xcode_binaries.yaml b/build/xcode_binaries.yaml
index 5e56c07..ace33bd 100644
--- a/build/xcode_binaries.yaml
+++ b/build/xcode_binaries.yaml
@@ -1,11 +1,19 @@
 # This yaml file is used to package binaries from Xcode.app.
 # To use this:
-#   1) Move Xcode.app to the same directory as this file.
-#   2) Rename Xcode.app to xcode_binaries
-#   3) Call `cipd create --pkg-def build/xcode_binaries.yaml`
+#   1) Move Xcode.app to the same directory as this file,
+#      and rename Xcode.app to xcode_binaries. Or make a symlink:
+#      $ rm -rf build/xcode_binaries && \
+#        ln -s /Applications/Xcode.app build/xcode_binaries
+#   2) Call `cipd create --pkg-def build/xcode_binaries.yaml`
 # To deploy the newly created cipd package across the fleet, modify
 # mac_toolchain.py to point to the new cipd hash.
 #
+# Note that runhooks extracts the cipd file to build/mac/xcode_binaries -- your
+# build/xcode_binaries you're creating in step 1 above isn't used as part of
+# the Chromium build, build/mac_files/xcode_binaries is. So you need to
+# `runhooks` after updating the hash in mac_toolchain.py like everyone else to
+# get the new bits for your local build.
+#
 # The ACLs for this package are determined by the directory structure. The
 # nomenclature mirrors that of the hermetic toolchain to avoid ACL duplication.
 package: infra_internal/ios/xcode/xcode_binaries/mac-amd64
diff --git a/cc/paint/discardable_image_map.cc b/cc/paint/discardable_image_map.cc
index f417621..c0ed817 100644
--- a/cc/paint/discardable_image_map.cc
+++ b/cc/paint/discardable_image_map.cc
@@ -69,7 +69,7 @@
     ~ImageGatheringProvider() override = default;
 
     ScopedResult GetRasterContent(const DrawImage& draw_image) override {
-      generator_->AddImage(draw_image.paint_image(),
+      generator_->AddImage(draw_image.paint_image(), false,
                            SkRect::Make(draw_image.src_rect()), op_rect_,
                            SkMatrix::I(), draw_image.filter_quality());
       return ScopedResult();
@@ -134,7 +134,7 @@
       if (op_type == PaintOpType::DrawImage) {
         auto* image_op = static_cast<DrawImageOp*>(op);
         AddImage(
-            image_op->image,
+            image_op->image, image_op->flags.useDarkModeForImage(),
             SkRect::MakeIWH(image_op->image.width(), image_op->image.height()),
             op_rect, ctm, image_op->flags.getFilterQuality());
       } else if (op_type == PaintOpType::DrawImageRect) {
@@ -143,8 +143,9 @@
         matrix.postConcat(SkMatrix::MakeRectToRect(image_rect_op->src,
                                                    image_rect_op->dst,
                                                    SkMatrix::kFill_ScaleToFit));
-        AddImage(image_rect_op->image, image_rect_op->src, op_rect, matrix,
-                 image_rect_op->flags.getFilterQuality());
+        AddImage(image_rect_op->image,
+                 image_rect_op->flags.useDarkModeForImage(), image_rect_op->src,
+                 op_rect, matrix, image_rect_op->flags.getFilterQuality());
       } else if (op_type == PaintOpType::DrawRecord) {
         GatherDiscardableImages(
             static_cast<const DrawRecordOp*>(op)->record.get(),
@@ -156,6 +157,7 @@
   void AddImageFromFlags(const gfx::Rect& op_rect,
                          const PaintFlags& flags,
                          const SkMatrix& ctm) {
+    // TODO(prashant.n): Add dark mode support for images from shaders/filters.
     AddImageFromShader(op_rect, flags.getShader(), ctm,
                        flags.getFilterQuality());
     AddImageFromFilter(op_rect, flags.getImageFilter().get());
@@ -172,7 +174,8 @@
       const PaintImage& paint_image = shader->paint_image();
       SkMatrix matrix = ctm;
       matrix.postConcat(shader->GetLocalMatrix());
-      AddImage(paint_image,
+      // TODO(prashant.n): Add dark mode support for images from shader.
+      AddImage(paint_image, false,
                SkRect::MakeWH(paint_image.width(), paint_image.height()),
                op_rect, matrix, filter_quality);
       return;
@@ -231,6 +234,7 @@
   }
 
   void AddImage(PaintImage paint_image,
+                bool use_dark_mode,
                 const SkRect& src_rect,
                 const gfx::Rect& image_rect,
                 const SkMatrix& matrix,
@@ -293,9 +297,9 @@
     }
 
     if (add_image) {
-      image_set_.emplace_back(
-          DrawImage(std::move(paint_image), src_irect, filter_quality, matrix),
-          image_rect);
+      image_set_.emplace_back(DrawImage(std::move(paint_image), use_dark_mode,
+                                        src_irect, filter_quality, matrix),
+                              image_rect);
     }
   }
 
diff --git a/cc/paint/draw_image.cc b/cc/paint/draw_image.cc
index afa344d..8cabad4 100644
--- a/cc/paint/draw_image.cc
+++ b/cc/paint/draw_image.cc
@@ -25,13 +25,15 @@
 }  // namespace
 
 DrawImage::DrawImage()
-    : src_rect_(SkIRect::MakeXYWH(0, 0, 0, 0)),
+    : use_dark_mode_(false),
+      src_rect_(SkIRect::MakeXYWH(0, 0, 0, 0)),
       filter_quality_(kNone_SkFilterQuality),
       scale_(SkSize::Make(1.f, 1.f)),
       matrix_is_decomposable_(true) {}
 
 DrawImage::DrawImage(PaintImage image)
     : paint_image_(std::move(image)),
+      use_dark_mode_(false),
       src_rect_(
           SkIRect::MakeXYWH(0, 0, paint_image_.width(), paint_image_.height())),
       filter_quality_(kNone_SkFilterQuality),
@@ -39,6 +41,7 @@
       matrix_is_decomposable_(true) {}
 
 DrawImage::DrawImage(PaintImage image,
+                     bool use_dark_mode,
                      const SkIRect& src_rect,
                      SkFilterQuality filter_quality,
                      const SkMatrix& matrix,
@@ -46,6 +49,7 @@
                      const base::Optional<gfx::ColorSpace>& color_space,
                      float sdr_white_level)
     : paint_image_(std::move(image)),
+      use_dark_mode_(use_dark_mode),
       src_rect_(src_rect),
       filter_quality_(filter_quality),
       frame_index_(frame_index),
@@ -60,6 +64,7 @@
                      const gfx::ColorSpace& color_space,
                      float sdr_white_level)
     : paint_image_(other.paint_image_),
+      use_dark_mode_(other.use_dark_mode_),
       src_rect_(other.src_rect_),
       filter_quality_(other.filter_quality_),
       scale_(SkSize::Make(other.scale_.width() * scale_adjustment,
@@ -80,7 +85,9 @@
 DrawImage& DrawImage::operator=(const DrawImage& other) = default;
 
 bool DrawImage::operator==(const DrawImage& other) const {
-  return paint_image_ == other.paint_image_ && src_rect_ == other.src_rect_ &&
+  return paint_image_ == other.paint_image_ &&
+         use_dark_mode_ == other.use_dark_mode_ &&
+         src_rect_ == other.src_rect_ &&
          filter_quality_ == other.filter_quality_ && scale_ == other.scale_ &&
          matrix_is_decomposable_ == other.matrix_is_decomposable_ &&
          target_color_space_ == other.target_color_space_ &&
diff --git a/cc/paint/draw_image.h b/cc/paint/draw_image.h
index 984d85ad..80afc2df 100644
--- a/cc/paint/draw_image.h
+++ b/cc/paint/draw_image.h
@@ -27,6 +27,7 @@
   DrawImage();
   explicit DrawImage(PaintImage image);
   DrawImage(PaintImage image,
+            bool use_dark_mode,
             const SkIRect& src_rect,
             SkFilterQuality filter_quality,
             const SkMatrix& matrix,
@@ -50,6 +51,7 @@
   bool operator==(const DrawImage& other) const;
 
   const PaintImage& paint_image() const { return paint_image_; }
+  bool use_dark_mode() const { return use_dark_mode_; }
   const SkSize& scale() const { return scale_; }
   const SkIRect& src_rect() const { return src_rect_; }
   SkFilterQuality filter_quality() const { return filter_quality_; }
@@ -69,6 +71,7 @@
 
  private:
   PaintImage paint_image_;
+  bool use_dark_mode_;
   SkIRect src_rect_;
   SkFilterQuality filter_quality_;
   SkSize scale_;
diff --git a/cc/paint/paint_filter.cc b/cc/paint/paint_filter.cc
index cf868e21..5018eb8b 100644
--- a/cc/paint/paint_filter.cc
+++ b/cc/paint/paint_filter.cc
@@ -690,7 +690,8 @@
 
 sk_sp<PaintFilter> ImagePaintFilter::SnapshotWithImagesInternal(
     ImageProvider* image_provider) const {
-  DrawImage draw_image(image_, SkIRect::MakeWH(image_.width(), image_.height()),
+  DrawImage draw_image(image_, false,
+                       SkIRect::MakeWH(image_.width(), image_.height()),
                        filter_quality_, SkMatrix::I());
   auto scoped_result = image_provider->GetRasterContent(draw_image);
   if (!scoped_result)
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc
index a19c4cf..8b6e8e8 100644
--- a/cc/paint/paint_op_buffer.cc
+++ b/cc/paint/paint_op_buffer.cc
@@ -28,7 +28,8 @@
                           const SkMatrix& matrix) {
   if (!image)
     return DrawImage();
-  return DrawImage(image, SkIRect::MakeWH(image.width(), image.height()),
+  return DrawImage(image, flags->useDarkModeForImage(),
+                   SkIRect::MakeWH(image.width(), image.height()),
                    flags ? flags->getFilterQuality() : kLow_SkFilterQuality,
                    matrix);
 }
@@ -1437,8 +1438,9 @@
     return;
   }
 
+  // Dark mode is applied only for OOP raster during serialization.
   DrawImage draw_image(
-      op->image, SkIRect::MakeWH(op->image.width(), op->image.height()),
+      op->image, false, SkIRect::MakeWH(op->image.width(), op->image.height()),
       flags ? flags->getFilterQuality() : kNone_SkFilterQuality,
       canvas->getTotalMatrix());
   auto scoped_result = params.image_provider->GetRasterContent(draw_image);
@@ -1519,8 +1521,9 @@
   SkIRect int_src_rect;
   op->src.roundOut(&int_src_rect);
 
+  // Dark mode is applied only for OOP raster during serialization.
   DrawImage draw_image(
-      op->image, int_src_rect,
+      op->image, false, int_src_rect,
       flags ? flags->getFilterQuality() : kNone_SkFilterQuality, matrix);
   auto scoped_result = params.image_provider->GetRasterContent(draw_image);
   if (!scoped_result)
diff --git a/cc/paint/paint_op_writer.cc b/cc/paint/paint_op_writer.cc
index ccd4aba..e6b9d93 100644
--- a/cc/paint/paint_op_writer.cc
+++ b/cc/paint/paint_op_writer.cc
@@ -496,8 +496,8 @@
   WriteSimple(shader->end_degrees_);
 
   if (enable_security_constraints_) {
-    DrawImage draw_image(shader->image_, MakeSrcRect(shader->image_), quality,
-                         SkMatrix::I());
+    DrawImage draw_image(shader->image_, false, MakeSrcRect(shader->image_),
+                         quality, SkMatrix::I());
     SkSize scale_adjustment = SkSize::Make(1.f, 1.f);
     Write(draw_image, &scale_adjustment);
     DCHECK_EQ(scale_adjustment.width(), 1.f);
@@ -743,7 +743,7 @@
 
 void PaintOpWriter::Write(const ImagePaintFilter& filter) {
   DrawImage draw_image(
-      filter.image(),
+      filter.image(), false,
       SkIRect::MakeWH(filter.image().width(), filter.image().height()),
       filter.filter_quality(), SkMatrix::I());
   SkSize scale_adjustment = SkSize::Make(1.f, 1.f);
diff --git a/cc/paint/paint_shader.cc b/cc/paint/paint_shader.cc
index 43adbeb..02cdea0b 100644
--- a/cc/paint/paint_shader.cc
+++ b/cc/paint/paint_shader.cc
@@ -371,7 +371,8 @@
   SkRect src_rect = SkRect::MakeIWH(image_.width(), image_.height());
   SkIRect int_src_rect;
   src_rect.roundOut(&int_src_rect);
-  DrawImage draw_image(image_, int_src_rect, quality, total_image_matrix);
+  DrawImage draw_image(image_, false, int_src_rect, quality,
+                       total_image_matrix);
   auto decoded_draw_image = image_provider->GetRasterContent(draw_image);
   if (!decoded_draw_image)
     return nullptr;
diff --git a/cc/raster/one_copy_raster_buffer_provider.cc b/cc/raster/one_copy_raster_buffer_provider.cc
index fe15e4d..c14de08 100644
--- a/cc/raster/one_copy_raster_buffer_provider.cc
+++ b/cc/raster/one_copy_raster_buffer_provider.cc
@@ -42,11 +42,11 @@
 
 // When enabled, OneCopyRasterBufferProvider::RasterBufferImpl::Playback() runs
 // at normal thread priority.
-// TODO(https://crbug.com/1072756): Enable by default and remove the feature
-// once experiments confirm that this prevents priority inversions.
+// TODO(crbug.com/1072756): Cleanup the feature when the Stable experiment is
+// complete, on November 25, 2020.
 const base::Feature kOneCopyRasterBufferPlaybackNormalThreadPriority{
     "OneCopyRasterBufferPlaybackNormalThreadPriority",
-    base::FEATURE_DISABLED_BY_DEFAULT};
+    base::FEATURE_ENABLED_BY_DEFAULT};
 
 }  // namespace
 
diff --git a/cc/raster/playback_image_provider_unittest.cc b/cc/raster/playback_image_provider_unittest.cc
index 37d78e9..3f0fbfa 100644
--- a/cc/raster/playback_image_provider_unittest.cc
+++ b/cc/raster/playback_image_provider_unittest.cc
@@ -79,7 +79,7 @@
           .set_id(PaintImage::GetNextId())
           .set_image(CreateRasterImage(), PaintImage::GetNextContentId())
           .TakePaintImage(),
-      rect, kMedium_SkFilterQuality, matrix)));
+      false, rect, kMedium_SkFilterQuality, matrix)));
   EXPECT_EQ(cache.images_decoded(), 0);
 
   EXPECT_FALSE(provider.GetRasterContent(
@@ -102,7 +102,7 @@
   SkIRect rect = SkIRect::MakeWH(10, 10);
   SkMatrix matrix = SkMatrix::I();
   EXPECT_FALSE(provider.GetRasterContent(
-      DrawImage(skip_image, rect, kMedium_SkFilterQuality, matrix)));
+      DrawImage(skip_image, false, rect, kMedium_SkFilterQuality, matrix)));
   EXPECT_EQ(cache.images_decoded(), 0);
 }
 
@@ -145,7 +145,7 @@
 
   SkIRect rect = SkIRect::MakeWH(10, 10);
   SkMatrix matrix = SkMatrix::I();
-  DrawImage draw_image(image, rect, kMedium_SkFilterQuality, matrix);
+  DrawImage draw_image(image, false, rect, kMedium_SkFilterQuality, matrix);
   provider.GetRasterContent(draw_image);
   ASSERT_TRUE(cache.last_image().paint_image());
   ASSERT_EQ(cache.last_image().paint_image(), image);
@@ -163,8 +163,8 @@
   {
     SkIRect rect = SkIRect::MakeWH(10, 10);
     SkMatrix matrix = SkMatrix::I();
-    auto draw_image = DrawImage(CreateBitmapImage(gfx::Size(10, 10)), rect,
-                                kMedium_SkFilterQuality, matrix);
+    auto draw_image = DrawImage(CreateBitmapImage(gfx::Size(10, 10)), false,
+                                rect, kMedium_SkFilterQuality, matrix);
     auto decode = provider.GetRasterContent(draw_image);
     EXPECT_TRUE(decode);
     EXPECT_EQ(cache.refed_image_count(), 1);
@@ -184,8 +184,8 @@
   {
     SkIRect rect = SkIRect::MakeWH(10, 10);
     SkMatrix matrix = SkMatrix::I();
-    auto draw_image = DrawImage(CreateBitmapImage(gfx::Size(10, 10)), rect,
-                                kMedium_SkFilterQuality, matrix);
+    auto draw_image = DrawImage(CreateBitmapImage(gfx::Size(10, 10)), false,
+                                rect, kMedium_SkFilterQuality, matrix);
     auto decode = provider.GetRasterContent(draw_image);
     EXPECT_TRUE(decode);
     EXPECT_EQ(cache.refed_image_count(), 0);
diff --git a/cc/test/skia_common.cc b/cc/test/skia_common.cc
index 37dfa06..86d146c 100644
--- a/cc/test/skia_common.cc
+++ b/cc/test/skia_common.cc
@@ -176,7 +176,7 @@
   SkIRect irect;
   rect.roundOut(&irect);
 
-  return DrawImage(CreateDiscardablePaintImage(size, color_space), irect,
+  return DrawImage(CreateDiscardablePaintImage(size, color_space), false, irect,
                    filter_quality, matrix);
 }
 
diff --git a/cc/tiles/checker_image_tracker.cc b/cc/tiles/checker_image_tracker.cc
index 4c932e9..48c1284e 100644
--- a/cc/tiles/checker_image_tracker.cc
+++ b/cc/tiles/checker_image_tracker.cc
@@ -369,6 +369,7 @@
   decode_state->scale = SkSize::Make(
       std::max(decode_state->scale.fWidth, draw_image.scale().fWidth),
       std::max(decode_state->scale.fHeight, draw_image.scale().fHeight));
+  decode_state->use_dark_mode = draw_image.use_dark_mode();
   decode_state->filter_quality =
       std::max(decode_state->filter_quality, draw_image.filter_quality());
   decode_state->color_space = draw_image.target_color_space();
@@ -407,7 +408,8 @@
       continue;
 
     draw_image = DrawImage(
-        candidate, SkIRect::MakeWH(candidate.width(), candidate.height()),
+        candidate, it->second.use_dark_mode,
+        SkIRect::MakeWH(candidate.width(), candidate.height()),
         it->second.filter_quality,
         SkMatrix::Scale(it->second.scale.width(), it->second.scale.height()),
         it->second.frame_index, it->second.color_space);
diff --git a/cc/tiles/checker_image_tracker.h b/cc/tiles/checker_image_tracker.h
index 76286899..bc01f63c 100644
--- a/cc/tiles/checker_image_tracker.h
+++ b/cc/tiles/checker_image_tracker.h
@@ -137,6 +137,7 @@
   // queuing the image decode.
   struct DecodeState {
     DecodePolicy policy = DecodePolicy::SYNC;
+    bool use_dark_mode = false;
     SkFilterQuality filter_quality = kNone_SkFilterQuality;
     SkSize scale = SkSize::MakeEmpty();
     gfx::ColorSpace color_space;
diff --git a/cc/tiles/checker_image_tracker_unittest.cc b/cc/tiles/checker_image_tracker_unittest.cc
index 100e27a7..7bfb4af 100644
--- a/cc/tiles/checker_image_tracker_unittest.cc
+++ b/cc/tiles/checker_image_tracker_unittest.cc
@@ -123,7 +123,7 @@
                          .set_is_multipart(is_multipart)
                          .set_decoding_mode(PaintImage::DecodingMode::kAsync)
                          .TakePaintImage(),
-                     SkIRect::MakeWH(dimension, dimension),
+                     false, SkIRect::MakeWH(dimension, dimension),
                      kNone_SkFilterQuality, SkMatrix::I(),
                      PaintImage::kDefaultFrameIndex, gfx::ColorSpace());
   }
@@ -437,7 +437,7 @@
           .set_id(partial_image.paint_image().stable_id())
           .set_paint_image_generator(CreatePaintImageGenerator(image_size))
           .TakePaintImage(),
-      SkIRect::MakeWH(image_size.width(), image_size.height()),
+      false, SkIRect::MakeWH(image_size.width(), image_size.height()),
       kNone_SkFilterQuality, SkMatrix::I(), PaintImage::kDefaultFrameIndex,
       gfx::ColorSpace());
   EXPECT_FALSE(
@@ -469,9 +469,9 @@
   DrawImage scaled_image1(image, 0.5f, PaintImage::kDefaultFrameIndex,
                           gfx::ColorSpace());
   DrawImage scaled_image2 =
-      DrawImage(image.paint_image(), image.src_rect(), kHigh_SkFilterQuality,
-                SkMatrix::Scale(1.8f, 1.8f), PaintImage::kDefaultFrameIndex,
-                gfx::ColorSpace());
+      DrawImage(image.paint_image(), false, image.src_rect(),
+                kHigh_SkFilterQuality, SkMatrix::Scale(1.8f, 1.8f),
+                PaintImage::kDefaultFrameIndex, gfx::ColorSpace());
 
   std::vector<DrawImage> draw_images = {scaled_image1, scaled_image2};
   CheckerImageTracker::ImageDecodeQueue image_decode_queue =
@@ -544,7 +544,7 @@
   // Create an image with checkerable dimensions and subrect it. It should not
   // be checkered.
   DrawImage image = CreateImage(ImageType::CHECKERABLE);
-  image = DrawImage(image.paint_image(), SkIRect::MakeWH(200, 200),
+  image = DrawImage(image.paint_image(), false, SkIRect::MakeWH(200, 200),
                     image.filter_quality(), SkMatrix::I(),
                     PaintImage::kDefaultFrameIndex, image.target_color_space());
   EXPECT_FALSE(ShouldCheckerImage(image, WhichTree::PENDING_TREE));
diff --git a/cc/tiles/decoded_image_tracker.cc b/cc/tiles/decoded_image_tracker.cc
index a7aa6b4..a429db05 100644
--- a/cc/tiles/decoded_image_tracker.cc
+++ b/cc/tiles/decoded_image_tracker.cc
@@ -48,7 +48,7 @@
   // Queue the decode in the image controller, but switch out the callback for
   // our own.
   auto image_bounds = SkIRect::MakeWH(image.width(), image.height());
-  DrawImage draw_image(image, image_bounds, kNone_SkFilterQuality,
+  DrawImage draw_image(image, false, image_bounds, kNone_SkFilterQuality,
                        SkMatrix::I(), frame_index, target_color_space);
   image_controller_->QueueImageDecode(
       draw_image, base::BindOnce(&DecodedImageTracker::ImageDecodeFinished,
diff --git a/cc/tiles/decoded_image_tracker_unittest.cc b/cc/tiles/decoded_image_tracker_unittest.cc
index 8ffb481..71c34a3 100644
--- a/cc/tiles/decoded_image_tracker_unittest.cc
+++ b/cc/tiles/decoded_image_tracker_unittest.cc
@@ -110,10 +110,10 @@
   // filter quality here, since it shouldn't matter and the checks should
   // succeed anyway.
   DrawImage locked_draw_image(
-      paint_image, SkIRect::MakeWH(1, 1), kHigh_SkFilterQuality, SkMatrix::I(),
-      PaintImage::kDefaultFrameIndex, decoded_color_space);
+      paint_image, false, SkIRect::MakeWH(1, 1), kHigh_SkFilterQuality,
+      SkMatrix::I(), PaintImage::kDefaultFrameIndex, decoded_color_space);
   EXPECT_TRUE(image_controller()->IsDrawImageLocked(locked_draw_image));
-  DrawImage srgb_draw_image(paint_image, SkIRect::MakeWH(1, 1),
+  DrawImage srgb_draw_image(paint_image, false, SkIRect::MakeWH(1, 1),
                             kHigh_SkFilterQuality, SkMatrix::I(),
                             PaintImage::kDefaultFrameIndex, srgb_color_space);
   EXPECT_FALSE(image_controller()->IsDrawImageLocked(srgb_draw_image));
@@ -171,10 +171,10 @@
   EXPECT_EQ(2u, image_controller()->num_locked_images());
 
   // Create dummy draw images for each:
-  DrawImage draw_image_1(paint_image_1, SkIRect::MakeWH(1, 1),
+  DrawImage draw_image_1(paint_image_1, false, SkIRect::MakeWH(1, 1),
                          kHigh_SkFilterQuality, SkMatrix::I(), 0,
                          gfx::ColorSpace());
-  DrawImage draw_image_2(paint_image_2, SkIRect::MakeWH(1, 1),
+  DrawImage draw_image_2(paint_image_2, false, SkIRect::MakeWH(1, 1),
                          kHigh_SkFilterQuality, SkMatrix::I(), 0,
                          gfx::ColorSpace());
 
diff --git a/cc/tiles/gpu_image_decode_cache_perftest.cc b/cc/tiles/gpu_image_decode_cache_perftest.cc
index 96c16de..20725f8 100644
--- a/cc/tiles/gpu_image_decode_cache_perftest.cc
+++ b/cc/tiles/gpu_image_decode_cache_perftest.cc
@@ -115,7 +115,7 @@
             .set_id(PaintImage::GetNextId())
             .set_image(CreateImage(1024, 2048), PaintImage::GetNextContentId())
             .TakePaintImage(),
-        SkIRect::MakeWH(1024, 2048), kMedium_SkFilterQuality,
+        false, SkIRect::MakeWH(1024, 2048), kMedium_SkFilterQuality,
         CreateMatrix(SkSize::Make(1.0f, 1.0f)), 0u,
         gfx::ColorSpace::CreateXYZD50());
 
@@ -148,7 +148,7 @@
             .set_id(PaintImage::GetNextId())
             .set_image(CreateImage(1024, 2048), PaintImage::GetNextContentId())
             .TakePaintImage(),
-        SkIRect::MakeWH(1024, 2048), kMedium_SkFilterQuality,
+        false, SkIRect::MakeWH(1024, 2048), kMedium_SkFilterQuality,
         CreateMatrix(SkSize::Make(0.6f, 0.6f)), 0u, gfx::ColorSpace());
 
     DecodedDrawImage decoded_image = cache_->GetDecodedImageForDraw(image);
@@ -177,7 +177,7 @@
           .set_id(PaintImage::GetNextId())
           .set_image(CreateImage(1024, 2048), PaintImage::GetNextContentId())
           .TakePaintImage(),
-      SkIRect::MakeWH(1024, 2048), kMedium_SkFilterQuality,
+      false, SkIRect::MakeWH(1024, 2048), kMedium_SkFilterQuality,
       CreateMatrix(SkSize::Make(1.0f, 1.0f)), 0u,
       gfx::ColorSpace::CreateXYZD50());
 
diff --git a/cc/tiles/gpu_image_decode_cache_unittest.cc b/cc/tiles/gpu_image_decode_cache_unittest.cc
index 4d70c959..01268808 100644
--- a/cc/tiles/gpu_image_decode_cache_unittest.cc
+++ b/cc/tiles/gpu_image_decode_cache_unittest.cc
@@ -480,7 +480,7 @@
       cs = DefaultColorSpace();
       color_space = &cs;
     }
-    return DrawImage(paint_image, *src_rect, filter_quality, matrix,
+    return DrawImage(paint_image, false, *src_rect, filter_quality, matrix,
                      frame_index, *color_space, sdr_white_level);
   }
 
@@ -1547,7 +1547,7 @@
 TEST_P(GpuImageDecodeCacheTest, NonOverlappingSrcRectImagesAreSkipped) {
   auto cache = CreateCache();
   PaintImage image = CreatePaintImageInternal(GetNormalImageSize());
-  DrawImage draw_image(image,
+  DrawImage draw_image(image, false,
                        SkIRect::MakeXYWH(image.width() + 1, image.height() + 1,
                                          image.width(), image.height()),
                        kMedium_SkFilterQuality,
@@ -1876,7 +1876,7 @@
 
   PaintImage image2 = CreatePaintImageInternal(GetNormalImageSize());
   DrawImage draw_image2(
-      image2, SkIRect::MakeWH(image2.width(), image2.height()),
+      image2, false, SkIRect::MakeWH(image2.width(), image2.height()),
       kMedium_SkFilterQuality, CreateMatrix(SkSize::Make(1.0f, 1.0f)),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
@@ -2082,9 +2082,9 @@
   viz::ContextProvider::ScopedContextLock context_lock(context_provider());
 
   SkFilterQuality quality = kMedium_SkFilterQuality;
-  DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
-                       quality, CreateMatrix(SkSize::Make(1.0f, 1.0f)), 1u,
-                       DefaultColorSpace());
+  DrawImage draw_image(
+      image, false, SkIRect::MakeWH(image.width(), image.height()), quality,
+      CreateMatrix(SkSize::Make(1.0f, 1.0f)), 1u, DefaultColorSpace());
   auto decoded_image =
       EnsureImageBacked(cache->GetDecodedImageForDraw(draw_image));
   ASSERT_TRUE(decoded_image.image());
@@ -2110,7 +2110,7 @@
   ASSERT_LT(subset_width, test_image_size.width());
   ASSERT_LT(subset_height, test_image_size.height());
   DrawImage subset_draw_image(
-      image, SkIRect::MakeWH(subset_width, subset_height), quality,
+      image, false, SkIRect::MakeWH(subset_width, subset_height), quality,
       CreateMatrix(SkSize::Make(1.0f, 1.0f)), 3u, DefaultColorSpace());
   decoded_image =
       EnsureImageBacked(cache->GetDecodedImageForDraw(subset_draw_image));
@@ -2925,10 +2925,10 @@
     SkSize requires_decode_at_original_scale = SkSize::Make(0.8f, 0.8f);
 
     PaintImage image = CreatePaintImageInternal(GetNormalImageSize());
-    DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
-                         filter_quality,
-                         CreateMatrix(requires_decode_at_original_scale),
-                         PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+    DrawImage draw_image(
+        image, false, SkIRect::MakeWH(image.width(), image.height()),
+        filter_quality, CreateMatrix(requires_decode_at_original_scale),
+        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
     ImageDecodeCache::TaskResult result = cache->GetTaskForImageAndRef(
         draw_image, ImageDecodeCache::TracingInfo());
     EXPECT_TRUE(result.need_unref);
@@ -3017,8 +3017,8 @@
       ASSERT_TRUE(target_cs.GetPQSDRWhiteLevel(&sdr_white_level));
 
     DrawImage draw_image(
-        image, SkIRect::MakeWH(image.width(), image.height()), filter_quality,
-        CreateMatrix(requires_decode_at_original_scale),
+        image, false, SkIRect::MakeWH(image.width(), image.height()),
+        filter_quality, CreateMatrix(requires_decode_at_original_scale),
         PaintImage::kDefaultFrameIndex, target_cs, sdr_white_level);
     ImageDecodeCache::TaskResult result = cache->GetTaskForImageAndRef(
         draw_image, ImageDecodeCache::TracingInfo());
@@ -3227,7 +3227,7 @@
         gfx::Size image_size = GetNormalImageSize();
         PaintImage image = CreatePaintImageInternal(image_size);
         DrawImage draw_image(
-            image, SkIRect::MakeWH(image.width(), image.height()),
+            image, false, SkIRect::MakeWH(image.width(), image.height()),
             filter_quality, CreateMatrix(scaled_size),
             PaintImage::kDefaultFrameIndex, DefaultColorSpace());
         ImageDecodeCache::TaskResult result = cache->GetTaskForImageAndRef(
@@ -3450,7 +3450,8 @@
     const PaintImage image = CreatePaintImageForDecodeAcceleration(
         ImageType::kJPEG, subsampling_and_expected_data_size.first);
     const SkFilterQuality quality = kHigh_SkFilterQuality;
-    DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
+    DrawImage draw_image(image, false,
+                         SkIRect::MakeWH(image.width(), image.height()),
                          quality, CreateMatrix(SkSize::Make(0.75f, 0.75f)),
                          PaintImage::kDefaultFrameIndex, target_color_space);
     ImageDecodeCache::TaskResult result = cache->GetTaskForImageAndRef(
@@ -3489,8 +3490,9 @@
   ASSERT_TRUE(target_color_space.IsValid());
   const PaintImage image = CreatePaintImageForDecodeAcceleration();
   const SkFilterQuality quality = kHigh_SkFilterQuality;
-  DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
-                       quality, CreateMatrix(SkSize::Make(0.75f, 0.75f)),
+  DrawImage draw_image(image, false,
+                       SkIRect::MakeWH(image.width(), image.height()), quality,
+                       CreateMatrix(SkSize::Make(0.75f, 0.75f)),
                        PaintImage::kDefaultFrameIndex, target_color_space);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -3527,8 +3529,9 @@
   ASSERT_TRUE(target_color_space.IsValid());
   const PaintImage image = CreatePaintImageForDecodeAcceleration();
   const SkFilterQuality quality = kHigh_SkFilterQuality;
-  DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
-                       quality, CreateMatrix(SkSize::Make(0.75f, 0.75f)),
+  DrawImage draw_image(image, false,
+                       SkIRect::MakeWH(image.width(), image.height()), quality,
+                       CreateMatrix(SkSize::Make(0.75f, 0.75f)),
                        PaintImage::kDefaultFrameIndex, target_color_space);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -3574,8 +3577,9 @@
   ASSERT_TRUE(target_color_space.IsValid());
   const PaintImage image = CreatePaintImageForDecodeAcceleration();
   const SkFilterQuality quality = kHigh_SkFilterQuality;
-  DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
-                       quality, CreateMatrix(SkSize::Make(1.0f, 1.0f)),
+  DrawImage draw_image(image, false,
+                       SkIRect::MakeWH(image.width(), image.height()), quality,
+                       CreateMatrix(SkSize::Make(1.0f, 1.0f)),
                        PaintImage::kDefaultFrameIndex, target_color_space);
   ImageDecodeCache::TaskResult result =
       cache->GetOutOfRasterDecodeTaskForImageAndRef(draw_image);
@@ -3596,8 +3600,9 @@
   ASSERT_TRUE(target_color_space.IsValid());
   const PaintImage image = CreatePaintImageForDecodeAcceleration();
   const SkFilterQuality quality = kHigh_SkFilterQuality;
-  DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
-                       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f)),
+  DrawImage draw_image(image, false,
+                       SkIRect::MakeWH(image.width(), image.height()), quality,
+                       CreateMatrix(SkSize::Make(0.5f, 0.5f)),
                        PaintImage::kDefaultFrameIndex, target_color_space);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -3620,8 +3625,9 @@
   ASSERT_TRUE(target_color_space.IsValid());
   const PaintImage image = CreatePaintImageForDecodeAcceleration();
   const SkFilterQuality quality = kHigh_SkFilterQuality;
-  DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
-                       quality, CreateMatrix(SkSize::Make(0.75f, 0.75f)),
+  DrawImage draw_image(image, false,
+                       SkIRect::MakeWH(image.width(), image.height()), quality,
+                       CreateMatrix(SkSize::Make(0.75f, 0.75f)),
                        PaintImage::kDefaultFrameIndex, target_color_space);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -3669,8 +3675,9 @@
   ASSERT_TRUE(target_color_space.IsValid());
   const PaintImage image = CreatePaintImageForDecodeAcceleration();
   const SkFilterQuality quality = kHigh_SkFilterQuality;
-  DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
-                       quality, CreateMatrix(SkSize::Make(0.75f, 0.75f)),
+  DrawImage draw_image(image, false,
+                       SkIRect::MakeWH(image.width(), image.height()), quality,
+                       CreateMatrix(SkSize::Make(0.75f, 0.75f)),
                        PaintImage::kDefaultFrameIndex, target_color_space);
   ImageDecodeCache::TaskResult result =
       cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -3717,9 +3724,10 @@
   const PaintImage jpeg_image =
       CreatePaintImageForDecodeAcceleration(ImageType::kJPEG);
   DrawImage jpeg_draw_image(
-      jpeg_image, SkIRect::MakeWH(jpeg_image.width(), jpeg_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.75f, 0.75f)),
-      PaintImage::kDefaultFrameIndex, target_color_space);
+      jpeg_image, false,
+      SkIRect::MakeWH(jpeg_image.width(), jpeg_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.75f, 0.75f)), PaintImage::kDefaultFrameIndex,
+      target_color_space);
   ImageDecodeCache::TaskResult jpeg_task = cache->GetTaskForImageAndRef(
       jpeg_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(jpeg_task.need_unref);
@@ -3777,9 +3785,10 @@
   const PaintImage webp_image =
       CreatePaintImageForDecodeAcceleration(ImageType::kWEBP);
   DrawImage webp_draw_image(
-      webp_image, SkIRect::MakeWH(webp_image.width(), webp_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.75f, 0.75f)),
-      PaintImage::kDefaultFrameIndex, target_color_space);
+      webp_image, false,
+      SkIRect::MakeWH(webp_image.width(), webp_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.75f, 0.75f)), PaintImage::kDefaultFrameIndex,
+      target_color_space);
   ImageDecodeCache::TaskResult webp_task = cache->GetTaskForImageAndRef(
       webp_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(webp_task.need_unref);
@@ -3816,9 +3825,10 @@
   const PaintImage png_image =
       CreatePaintImageForDecodeAcceleration(ImageType::kPNG);
   DrawImage png_draw_image(
-      png_image, SkIRect::MakeWH(jpeg_image.width(), jpeg_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.75f, 0.75f)),
-      PaintImage::kDefaultFrameIndex, target_color_space);
+      png_image, false,
+      SkIRect::MakeWH(jpeg_image.width(), jpeg_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.75f, 0.75f)), PaintImage::kDefaultFrameIndex,
+      target_color_space);
   ImageDecodeCache::TaskResult png_task = cache->GetTaskForImageAndRef(
       png_draw_image, ImageDecodeCache::TracingInfo());
   EXPECT_TRUE(png_task.need_unref);
diff --git a/cc/tiles/image_controller_unittest.cc b/cc/tiles/image_controller_unittest.cc
index c518941..52ae3817 100644
--- a/cc/tiles/image_controller_unittest.cc
+++ b/cc/tiles/image_controller_unittest.cc
@@ -239,16 +239,17 @@
 int kDefaultTimeoutSeconds = 10;
 
 DrawImage CreateDiscardableDrawImage(gfx::Size size) {
-  return DrawImage(CreateDiscardablePaintImage(size),
+  return DrawImage(CreateDiscardablePaintImage(size), false,
                    SkIRect::MakeWH(size.width(), size.height()),
                    kNone_SkFilterQuality, SkMatrix::I(),
                    PaintImage::kDefaultFrameIndex, gfx::ColorSpace());
 }
 
 DrawImage CreateBitmapDrawImage(gfx::Size size) {
-  return DrawImage(
-      CreateBitmapImage(size), SkIRect::MakeWH(size.width(), size.height()),
-      kNone_SkFilterQuality, SkMatrix::I(), PaintImage::kDefaultFrameIndex);
+  return DrawImage(CreateBitmapImage(size), false,
+                   SkIRect::MakeWH(size.width(), size.height()),
+                   kNone_SkFilterQuality, SkMatrix::I(),
+                   PaintImage::kDefaultFrameIndex);
 }
 
 class ImageControllerTest : public testing::Test {
diff --git a/cc/tiles/software_image_decode_cache.cc b/cc/tiles/software_image_decode_cache.cc
index f2676e80..f76bc87 100644
--- a/cc/tiles/software_image_decode_cache.cc
+++ b/cc/tiles/software_image_decode_cache.cc
@@ -415,7 +415,7 @@
               ? SkIRect::MakeWH(paint_image.width(), paint_image.height())
               : gfx::RectToSkIRect(key.src_rect());
       DrawImage candidate_draw_image(
-          paint_image, src_rect, kNone_SkFilterQuality, SkMatrix::I(),
+          paint_image, false, src_rect, kNone_SkFilterQuality, SkMatrix::I(),
           key.frame_key().frame_index(), key.target_color_space());
       candidate_key.emplace(CacheKey::FromDrawImage(
           candidate_draw_image,
diff --git a/cc/tiles/software_image_decode_cache_perftest.cc b/cc/tiles/software_image_decode_cache_perftest.cc
index 5d729ac8..8fa55b4 100644
--- a/cc/tiles/software_image_decode_cache_perftest.cc
+++ b/cc/tiles/software_image_decode_cache_perftest.cc
@@ -62,7 +62,7 @@
                   .set_image(CreateImage(rect.width(), rect.height()),
                              PaintImage::GetNextContentId())
                   .TakePaintImage(),
-              subrect, quality,
+              false, subrect, quality,
               CreateMatrix(SkSize::Make(scale.first, scale.second)), 0u,
               gfx::ColorSpace());
         }
diff --git a/cc/tiles/software_image_decode_cache_unittest.cc b/cc/tiles/software_image_decode_cache_unittest.cc
index ac3e41a..45bf3a0 100644
--- a/cc/tiles/software_image_decode_cache_unittest.cc
+++ b/cc/tiles/software_image_decode_cache_unittest.cc
@@ -51,7 +51,8 @@
   PaintImage paint_image = CreatePaintImage(100, 100);
   bool is_decomposable = true;
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       kNone_SkFilterQuality,
       CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -73,7 +74,8 @@
   PaintImage paint_image = CreatePaintImage(100, 100);
   bool is_decomposable = true;
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       kLow_SkFilterQuality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -91,7 +93,8 @@
   PaintImage paint_image = CreatePaintImage(100, 100);
   bool is_decomposable = true;
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       kMedium_SkFilterQuality,
       CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -110,7 +113,8 @@
   PaintImage paint_image = CreatePaintImage(100, 100);
   bool is_decomposable = true;
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       kLow_SkFilterQuality,
       CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -129,7 +133,8 @@
   PaintImage paint_image = CreatePaintImage(100, 100);
   bool is_decomposable = true;
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       kHigh_SkFilterQuality,
       CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -148,7 +153,8 @@
   PaintImage paint_image = CreatePaintImage(100, 100);
   bool is_decomposable = true;
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       kLow_SkFilterQuality,
       CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -169,8 +175,9 @@
   SkFilterQuality quality = kMedium_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 0.4f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 0.4f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -188,8 +195,9 @@
   SkFilterQuality quality = kMedium_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -208,8 +216,9 @@
   SkFilterQuality quality = kMedium_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -229,8 +238,9 @@
   SkFilterQuality quality = kMedium_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -250,8 +260,9 @@
   SkFilterQuality quality = kMedium_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -271,8 +282,9 @@
   SkFilterQuality quality = kMedium_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -292,8 +304,9 @@
   SkFilterQuality quality = kMedium_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -312,8 +325,9 @@
   SkFilterQuality quality = kMedium_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -332,8 +346,9 @@
   SkFilterQuality quality = kMedium_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -352,8 +367,9 @@
   SkFilterQuality quality = kMedium_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -371,8 +387,9 @@
   SkFilterQuality quality = kMedium_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -390,8 +407,9 @@
   SkFilterQuality quality = kMedium_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -409,8 +427,9 @@
   SkFilterQuality quality = kMedium_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -429,8 +448,9 @@
   SkFilterQuality quality = kHigh_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 0.2f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 0.2f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -448,8 +468,9 @@
   SkFilterQuality quality = kHigh_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(2.5f, 1.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(2.5f, 1.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -471,8 +492,9 @@
   // At least one dimension should scale down, so that medium quality doesn't
   // become low.
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.45f, 0.45f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.45f, 0.45f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -491,8 +513,9 @@
   SkFilterQuality quality = kHigh_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -511,8 +534,9 @@
   SkFilterQuality quality = kHigh_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -532,8 +556,9 @@
   SkFilterQuality quality = kHigh_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -553,8 +578,9 @@
   SkFilterQuality quality = kHigh_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -587,7 +613,8 @@
   PaintImage paint_image = CreatePaintImage(97, 61);
   bool is_decomposable = true;
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       kMedium_SkFilterQuality,
       CreateMatrix(SkSize::Make(0.2f, 0.2f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -608,8 +635,9 @@
   SkFilterQuality quality = kNone_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 0.5), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 0.5), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -622,8 +650,9 @@
   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
 
   DrawImage another_draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.5f, 1.5), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(1.5f, 1.5), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   auto another_key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
@@ -644,7 +673,7 @@
   SkFilterQuality quality = kHigh_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image,
+      paint_image, false,
       SkIRect::MakeXYWH(25, 35, paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -665,7 +694,7 @@
   SkFilterQuality quality = kHigh_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image,
+      paint_image, false,
       SkIRect::MakeXYWH(20, 30, paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -687,8 +716,9 @@
   SkFilterQuality quality = kHigh_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -696,8 +726,9 @@
   EXPECT_TRUE(result.task);
 
   DrawImage another_draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
   ImageDecodeCache::TaskResult another_result = cache.GetTaskForImageAndRef(
       another_draw_image, ImageDecodeCache::TracingInfo());
@@ -717,8 +748,9 @@
   SkFilterQuality quality = kHigh_SkFilterQuality;
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -746,7 +778,8 @@
   bool is_decomposable = true;
 
   DrawImage high_quality_draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       kHigh_SkFilterQuality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -757,7 +790,8 @@
   EXPECT_TRUE(high_quality_result.task);
 
   DrawImage none_quality_draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()),
       kNone_SkFilterQuality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -782,8 +816,9 @@
   SkFilterQuality quality = kHigh_SkFilterQuality;
 
   DrawImage half_size_draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
   ImageDecodeCache::TaskResult half_size_result = cache.GetTaskForImageAndRef(
       half_size_draw_image, ImageDecodeCache::TracingInfo());
@@ -791,8 +826,9 @@
   EXPECT_TRUE(half_size_result.task);
 
   DrawImage quarter_size_draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
   ImageDecodeCache::TaskResult quarter_size_result =
       cache.GetTaskForImageAndRef(quarter_size_draw_image,
@@ -815,7 +851,7 @@
 
   PaintImage first_paint_image = CreatePaintImage(100, 100);
   DrawImage first_draw_image(
-      first_paint_image,
+      first_paint_image, false,
       SkIRect::MakeWH(first_paint_image.width(), first_paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -826,7 +862,7 @@
 
   PaintImage second_paint_image = CreatePaintImage(100, 100);
   DrawImage second_draw_image(
-      second_paint_image,
+      second_paint_image, false,
       SkIRect::MakeWH(second_paint_image.width(), second_paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -864,8 +900,9 @@
 
   PaintImage paint_image = CreatePaintImage(100, 100, color_space_a);
   DrawImage first_draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
       PaintImage::kDefaultFrameIndex, color_space_b);
   ImageDecodeCache::TaskResult first_result = cache.GetTaskForImageAndRef(
       first_draw_image, ImageDecodeCache::TracingInfo());
@@ -873,8 +910,9 @@
   EXPECT_TRUE(first_result.task);
 
   DrawImage second_draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
       PaintImage::kDefaultFrameIndex, color_space_c);
   ImageDecodeCache::TaskResult second_result = cache.GetTaskForImageAndRef(
       second_draw_image, ImageDecodeCache::TracingInfo());
@@ -883,8 +921,9 @@
   EXPECT_TRUE(first_result.task.get() != second_result.task.get());
 
   DrawImage third_draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
       PaintImage::kDefaultFrameIndex, color_space_b);
   ImageDecodeCache::TaskResult third_result = cache.GetTaskForImageAndRef(
       third_draw_image, ImageDecodeCache::TracingInfo());
@@ -907,8 +946,9 @@
 
   PaintImage paint_image = CreatePaintImage(100, 100);
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -936,8 +976,9 @@
 
   PaintImage paint_image = CreatePaintImage(100, 100);
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -971,8 +1012,9 @@
 
   PaintImage paint_image = CreatePaintImage(100, 100);
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1012,8 +1054,9 @@
 
   PaintImage paint_image = CreatePaintImage(100, 100);
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1052,8 +1095,9 @@
 
   PaintImage paint_image = CreatePaintImage(100, 100);
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
   ImageDecodeCache::TaskResult result =
       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1084,7 +1128,7 @@
 
   PaintImage paint_image = CreatePaintImage(100, 100);
   DrawImage draw_image(
-      paint_image,
+      paint_image, false,
       SkIRect::MakeXYWH(20, 30, paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -1116,8 +1160,9 @@
 
   PaintImage paint_image = CreatePaintImage(100, 100);
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   DecodedDrawImage decoded_draw_image =
@@ -1141,8 +1186,9 @@
 
   PaintImage paint_image = CreatePaintImage(100, 100);
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   DecodedDrawImage decoded_draw_image =
@@ -1171,8 +1217,9 @@
 
   PaintImage paint_image = CreatePaintImage(100, 100);
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.f, 0.f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.f, 0.f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   ImageDecodeCache::TaskResult result =
@@ -1194,7 +1241,7 @@
 
   PaintImage paint_image = CreatePaintImage(100, 100);
   DrawImage draw_image(
-      paint_image,
+      paint_image, false,
       SkIRect::MakeXYWH(150, 150, paint_image.width(), paint_image.height()),
       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -1218,8 +1265,9 @@
 
   PaintImage paint_image = CreatePaintImage(100, 100);
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   ImageDecodeCache::TaskResult result =
@@ -1246,7 +1294,8 @@
   SkFilterQuality quality = kLow_SkFilterQuality;
 
   PaintImage paint_image = CreatePaintImage(100, 100);
-  DrawImage draw_image(paint_image, SkIRect::MakeXYWH(10, 10, 80, 80), quality,
+  DrawImage draw_image(paint_image, false, SkIRect::MakeXYWH(10, 10, 80, 80),
+                       quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
                        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
@@ -1279,7 +1328,8 @@
   SkFilterQuality quality = kNone_SkFilterQuality;
 
   PaintImage paint_image = CreatePaintImage(100, 100);
-  DrawImage draw_image(paint_image, SkIRect::MakeXYWH(10, 10, 80, 80), quality,
+  DrawImage draw_image(paint_image, false, SkIRect::MakeXYWH(10, 10, 80, 80),
+                       quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
                        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
@@ -1310,8 +1360,9 @@
 
   PaintImage paint_image = CreatePaintImage(500, 200);
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   ImageDecodeCache::TaskResult result =
@@ -1341,8 +1392,9 @@
 
   PaintImage paint_image = CreatePaintImage(500, 200);
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   ImageDecodeCache::TaskResult result =
@@ -1372,8 +1424,9 @@
 
   PaintImage paint_image = CreatePaintImage(500, 200);
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   ImageDecodeCache::TaskResult result =
@@ -1403,8 +1456,9 @@
 
   PaintImage paint_image = CreatePaintImage(500, 200);
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   ImageDecodeCache::TaskResult result =
@@ -1434,8 +1488,9 @@
 
   PaintImage paint_image = CreatePaintImage(500, 200);
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   ImageDecodeCache::TaskResult result =
@@ -1465,8 +1520,9 @@
 
   PaintImage paint_image = CreatePaintImage(500, 200);
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   ImageDecodeCache::TaskResult result =
@@ -1496,8 +1552,9 @@
 
   PaintImage paint_image = CreatePaintImage(500, 200);
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   ImageDecodeCache::TaskResult result =
@@ -1527,8 +1584,9 @@
 
   PaintImage paint_image = CreatePaintImage(500, 200);
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.001f, 0.001f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.001f, 0.001f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   ImageDecodeCache::TaskResult result =
@@ -1551,12 +1609,14 @@
 
   PaintImage paint_image = CreatePaintImage(500, 200);
   DrawImage draw_image_50(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
   DrawImage draw_image_49(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   ImageDecodeCache::TaskResult result_50 = cache.GetTaskForImageAndRef(
@@ -1602,8 +1662,9 @@
   for (int i = 0; i < 10; ++i) {
     PaintImage paint_image = CreatePaintImage(100, 100);
     DrawImage draw_image(
-        paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-        quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+        paint_image, false,
+        SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
         PaintImage::kDefaultFrameIndex, DefaultColorSpace());
     ImageDecodeCache::TaskResult result = cache.GetTaskForImageAndRef(
         draw_image, ImageDecodeCache::TracingInfo());
@@ -1639,8 +1700,8 @@
 
   bool is_decomposable = true;
   SkFilterQuality quality = kHigh_SkFilterQuality;
-  DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
-                       quality,
+  DrawImage draw_image(image, false,
+                       SkIRect::MakeWH(image.width(), image.height()), quality,
                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
                        1u, DefaultColorSpace());
   auto decoded_image = cache.GetDecodedImageForDraw(draw_image);
@@ -1662,7 +1723,7 @@
 
   // Subset.
   DrawImage subset_draw_image(
-      image, SkIRect::MakeWH(5, 5), quality,
+      image, false, SkIRect::MakeWH(5, 5), quality,
       CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), 3u,
       DefaultColorSpace());
   decoded_image = cache.GetDecodedImageForDraw(subset_draw_image);
@@ -1682,7 +1743,8 @@
   auto paint_image =
       CreateDiscardablePaintImage(gfx::Size(min_dimension, min_dimension),
                                   DefaultColorSpace().ToSkColorSpace(), false);
-  DrawImage draw_image(paint_image, SkIRect::MakeXYWH(0, 0, 10, 10), quality,
+  DrawImage draw_image(paint_image, false, SkIRect::MakeXYWH(0, 0, 10, 10),
+                       quality,
                        CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
                        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
@@ -1715,7 +1777,7 @@
   // Populate the cache with an original sized decode.
   auto paint_image = CreateDiscardablePaintImage(
       gfx::Size(100, 100), DefaultColorSpace().ToSkColorSpace());
-  DrawImage draw_image(paint_image, SkIRect::MakeWH(100, 100), quality,
+  DrawImage draw_image(paint_image, false, SkIRect::MakeWH(100, 100), quality,
                        CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
                        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
   DecodedDrawImage decoded_draw_image =
@@ -1725,7 +1787,7 @@
 
   // Ask for another decode, this time with an empty subrect.
   DrawImage empty_draw_image(
-      paint_image, SkIRect::MakeEmpty(), quality,
+      paint_image, false, SkIRect::MakeEmpty(), quality,
       CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
   DecodedDrawImage empty_decoded_draw_image =
@@ -1742,8 +1804,9 @@
 
   PaintImage paint_image = CreateBitmapImage(gfx::Size(100, 100));
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
       PaintImage::kDefaultFrameIndex, target_color_space);
 
   DecodedDrawImage decoded_draw_image =
@@ -1766,8 +1829,9 @@
 
   PaintImage paint_image = CreateBitmapImage(gfx::Size(100, 100));
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
 
   // The cache should not support this image.
@@ -1791,7 +1855,7 @@
     for (int j = 0; j < 2; ++j) {
       float scale = j == 0 ? 1.f : 0.5f;
       DrawImage draw_image(
-          paint_image,
+          paint_image, false,
           SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
           CreateMatrix(SkSize::Make(scale, scale), is_decomposable),
           PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -1831,8 +1895,9 @@
   // Scale to mip level 1, there should be a single entry in the cache from
   // the direct decode.
   DrawImage draw_image1(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5, 0.5), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5, 0.5), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
   DecodedDrawImage decoded_image1 = cache.GetDecodedImageForDraw(draw_image1);
   ASSERT_TRUE(decoded_image1.image());
@@ -1848,8 +1913,9 @@
   // Scale to mip level 2, we should be using the existing entry instead of
   // re-decoding.
   DrawImage draw_image2(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.25, 0.25), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.25, 0.25), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
   DecodedDrawImage decoded_image2 = cache.GetDecodedImageForDraw(draw_image2);
   ASSERT_TRUE(decoded_image2.image());
@@ -1888,7 +1954,7 @@
 
   // Scale to mip level 1, there should be 2 entries in the cache, since the
   // subrect vetoes decode to scale.
-  DrawImage draw_image(paint_image, SkIRect::MakeWH(50, 50), quality,
+  DrawImage draw_image(paint_image, false, SkIRect::MakeWH(50, 50), quality,
                        CreateMatrix(SkSize::Make(0.5, 0.5), is_decomposable),
                        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
   DecodedDrawImage decoded_image = cache.GetDecodedImageForDraw(draw_image);
@@ -1924,8 +1990,9 @@
                                .TakePaintImage();
 
   DrawImage draw_image(
-      paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()),
-      quality, CreateMatrix(SkSize::Make(0.5, 0.5), is_decomposable),
+      paint_image, false,
+      SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
+      CreateMatrix(SkSize::Make(0.5, 0.5), is_decomposable),
       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
   DecodedDrawImage decoded_image = cache.GetDecodedImageForDraw(draw_image);
   ASSERT_TRUE(decoded_image.image());
@@ -1956,10 +2023,10 @@
                                     PaintImage::GetNextContentId())
                          .TakePaintImage();
 
-  DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
-                       kMedium_SkFilterQuality,
-                       CreateMatrix(SkSize::Make(0.5, 0.5), true),
-                       PaintImage::kDefaultFrameIndex, color_space);
+  DrawImage draw_image(
+      image, false, SkIRect::MakeWH(image.width(), image.height()),
+      kMedium_SkFilterQuality, CreateMatrix(SkSize::Make(0.5, 0.5), true),
+      PaintImage::kDefaultFrameIndex, color_space);
 
   DecodedDrawImage decoded_image = cache.GetDecodedImageForDraw(draw_image);
   EXPECT_EQ(decoded_image.image()->colorType(), kRGBA_F16_SkColorType);
@@ -1986,10 +2053,10 @@
   // Note: We use P3 here since software cache shouldn't be used when conversion
   // to SRGB is needed.
   auto raster_color_space = gfx::ColorSpace::CreateDisplayP3D65();
-  DrawImage draw_image(image, SkIRect::MakeWH(image.width(), image.height()),
-                       kMedium_SkFilterQuality,
-                       CreateMatrix(SkSize::Make(0.5, 0.5), true),
-                       PaintImage::kDefaultFrameIndex, raster_color_space);
+  DrawImage draw_image(
+      image, false, SkIRect::MakeWH(image.width(), image.height()),
+      kMedium_SkFilterQuality, CreateMatrix(SkSize::Make(0.5, 0.5), true),
+      PaintImage::kDefaultFrameIndex, raster_color_space);
 
   DecodedDrawImage decoded_image = cache.GetDecodedImageForDraw(draw_image);
   EXPECT_NE(decoded_image.image()->colorType(), kRGBA_F16_SkColorType);
diff --git a/cc/tiles/software_image_decode_cache_unittest_combinations.cc b/cc/tiles/software_image_decode_cache_unittest_combinations.cc
index 5052a2a..afbf20b 100644
--- a/cc/tiles/software_image_decode_cache_unittest_combinations.cc
+++ b/cc/tiles/software_image_decode_cache_unittest_combinations.cc
@@ -45,7 +45,7 @@
       float scale,
       const SkIRect src_rect = SkIRect::MakeEmpty()) {
     return DrawImage(
-        paint_image(),
+        paint_image(), false,
         src_rect.isEmpty()
             ? SkIRect::MakeWH(paint_image().width(), paint_image().height())
             : src_rect,
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index ac08839d..8976646b 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -7978,7 +7978,7 @@
       return;
     first_ = false;
 
-    image_ = DrawImage(CreateDiscardablePaintImage(gfx::Size(400, 400)),
+    image_ = DrawImage(CreateDiscardablePaintImage(gfx::Size(400, 400)), false,
                        SkIRect::MakeWH(400, 400), kNone_SkFilterQuality,
                        SkMatrix::I(), PaintImage::kDefaultFrameIndex,
                        gfx::ColorSpace());
diff --git a/chrome/VERSION b/chrome/VERSION
index cba10da..c3e2a01 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=88
 MINOR=0
-BUILD=4299
+BUILD=4301
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index c604cb2..15406df5 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -544,7 +544,6 @@
     "//chrome/browser:sharing_send_message_result_generated_enum",
     "//chrome/browser/notifications/scheduler/public:jni_enums",
     "//chrome/browser/supervised_user/supervised_user_error_page:enums_srcjar",
-    "//chrome/browser/updates/announcement_notification:jni_enums",
     "//components/autofill_assistant/browser:autofill_assistant_enums_java",
     "//components/browsing_data/core:browsing_data_utils_java",
     "//components/browsing_data/core:clear_browsing_data_tab_java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index e3b9dc7..3ccede3 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -908,6 +908,7 @@
   "java/src/org/chromium/chrome/browser/media/ui/ChromeMediaNotificationControllerDelegate.java",
   "java/src/org/chromium/chrome/browser/media/ui/ChromeMediaNotificationManager.java",
   "java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java",
+  "java/src/org/chromium/chrome/browser/messages/MessageContainerCoordinator.java",
   "java/src/org/chromium/chrome/browser/metrics/ActivityTabStartupMetricsTracker.java",
   "java/src/org/chromium/chrome/browser/metrics/BackgroundTaskMemoryMetricsEmitter.java",
   "java/src/org/chromium/chrome/browser/metrics/LaunchMetrics.java",
@@ -935,6 +936,7 @@
   "java/src/org/chromium/chrome/browser/native_page/NativePageNavigationDelegate.java",
   "java/src/org/chromium/chrome/browser/native_page/NativePageNavigationDelegateImpl.java",
   "java/src/org/chromium/chrome/browser/navigation_predictor/NavigationPredictorBridge.java",
+  "java/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetector.java",
   "java/src/org/chromium/chrome/browser/net/nqe/NetworkQualityObserver.java",
   "java/src/org/chromium/chrome/browser/net/nqe/NetworkQualityProvider.java",
   "java/src/org/chromium/chrome/browser/net/spdyproxy/DataReductionProxySettings.java",
@@ -1045,7 +1047,6 @@
   "java/src/org/chromium/chrome/browser/offlinepages/TaskExtrasPacker.java",
   "java/src/org/chromium/chrome/browser/offlinepages/TriggerConditions.java",
   "java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageDownloadBridge.java",
-  "java/src/org/chromium/chrome/browser/offlinepages/indicator/ConnectivityDetector.java",
   "java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineDetector.java",
   "java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorController.java",
   "java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerV2.java",
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni
index 09a67c7..45b925f 100644
--- a/chrome/android/chrome_public_apk_tmpl.gni
+++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -439,8 +439,14 @@
       if (defined(_module_desc.native_deps) && _module_desc.native_deps != []) {
         _lib_target = "//chrome/android:${_base_target_name}_${_module_desc.name}${_toolchain}"
         _chrome_module_shared_lib_deps += [ _lib_target ]
-        _lib_out_dir = get_label_info(_lib_target, "root_out_dir")
-        _chrome_module_loadable_modules += [ "${_lib_out_dir}/${_base_target_name}_${_module_desc.name}_partition.so" ]
+
+        # In component builds, native libraries from DFMs are not in partitions,
+        # so include them as normal shared libraries instead of loadable
+        # modules.
+        if (!is_component_build) {
+          _lib_out_dir = get_label_info(_lib_target, "root_out_dir")
+          _chrome_module_loadable_modules += [ "${_lib_out_dir}/${_base_target_name}_${_module_desc.name}_partition.so" ]
+        }
       }
     }
   }
@@ -535,7 +541,15 @@
           deps += [ "//chrome/android:base_module_java" ]
         }
         deps += [ ":${target_name}__all_chrome_resources" ]
-        deps += _chrome_module_shared_lib_deps
+        if (is_component_build) {
+          if (android_64bit_target_cpu && !invoker.is_64_bit_browser) {
+            secondary_abi_shared_libraries += _chrome_module_shared_lib_deps
+          } else {
+            shared_libraries += _chrome_module_shared_lib_deps
+          }
+        } else {
+          deps += _chrome_module_shared_lib_deps
+        }
         _loadable_modules_32_bit = []
         _loadable_modules_64_bit = []
         foreach(_module_desc, _module_descs) {
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index ed28326..c9776f7 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -278,6 +278,8 @@
   "javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowIntegrationTest.java",
   "javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowTestHelper.java",
   "javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsTest.java",
+  "javatests/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetectorDelegateStub.java",
+  "javatests/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetectorTest.java",
   "javatests/src/org/chromium/chrome/browser/night_mode/ChromeNightModeTestUtils.java",
   "javatests/src/org/chromium/chrome/browser/night_mode/settings/ThemeSettingsFragmentTest.java",
   "javatests/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilderTest.java",
@@ -310,8 +312,6 @@
   "javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java",
   "javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java",
   "javatests/src/org/chromium/chrome/browser/offlinepages/RequestCoordinatorBridgeTest.java",
-  "javatests/src/org/chromium/chrome/browser/offlinepages/indicator/ConnectivityDetectorDelegateStub.java",
-  "javatests/src/org/chromium/chrome/browser/offlinepages/indicator/ConnectivityDetectorTest.java",
   "javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java",
   "javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java",
   "javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchConfigurationTest.java",
diff --git a/chrome/android/expectations/lint-suppressions.xml b/chrome/android/expectations/lint-suppressions.xml
index d7d4b62ec..b4e81f2f 100644
--- a/chrome/android/expectations/lint-suppressions.xml
+++ b/chrome/android/expectations/lint-suppressions.xml
@@ -135,6 +135,10 @@
   <issue id="PrivateApi" severity="ignore"/>
   <!-- Chrome is a system app. -->
   <issue id="ProtectedPermissions" severity="ignore"/>
+  <issue id="RestrictedApi">
+    <!-- Chrome uses these GMS core APIs. -->
+    <ignore regexp="is marked as internal and should not be accessed from apps"/>
+  </issue>
   <issue id="Recycle" severity="ignore"/>
   <issue id="Registered" severity="ignore"/>
   <issue id="ResourceAsColor" severity="ignore"/>
diff --git a/chrome/android/expectations/monochrome_public_bundle.arm64.libs_and_assets.expected b/chrome/android/expectations/monochrome_public_bundle.arm64.libs_and_assets.expected
index 28ace4d..771e205 100644
--- a/chrome/android/expectations/monochrome_public_bundle.arm64.libs_and_assets.expected
+++ b/chrome/android/expectations/monochrome_public_bundle.arm64.libs_and_assets.expected
@@ -3,8 +3,13 @@
 apk_path=lib/armeabi-v7a/libarcore_sdk_c.so, compress=False, alignment=4096
 apk_path=lib/armeabi-v7a/libcrashpad_handler_trampoline.so, compress=False, alignment=4096
 apk_path=lib/armeabi-v7a/libmonochrome.so, compress=False, alignment=4096
+apk_path=lib/armeabi-v7a/libmonochrome_cablev2_authenticator_partition.so, compress=False, alignment=4096
+apk_path=lib/armeabi-v7a/libmonochrome_stack_unwinder_partition.so, compress=False, alignment=4096
+apk_path=lib/armeabi-v7a/libmonochrome_test_dummy_partition.so, compress=False, alignment=4096
+apk_path=lib/armeabi-v7a/libmonochrome_vr_partition.so, compress=False, alignment=4096
 apk_path=assets/chrome_100_percent.pak, compress=False, alignment=4
 apk_path=assets/icudtl.dat, compress=False, alignment=4
+apk_path=assets/icudtl_extra.dat, compress=False, alignment=4
 apk_path=assets/locales/af.pak, compress=False, alignment=4
 apk_path=assets/locales/am.pak, compress=False, alignment=4
 apk_path=assets/locales/ar.pak, compress=False, alignment=4
diff --git a/chrome/android/expectations/trichrome_chrome_bundle.arm64.libs_and_assets.expected b/chrome/android/expectations/trichrome_chrome_bundle.arm64.libs_and_assets.expected
index e9c8441..1f7aec2b 100644
--- a/chrome/android/expectations/trichrome_chrome_bundle.arm64.libs_and_assets.expected
+++ b/chrome/android/expectations/trichrome_chrome_bundle.arm64.libs_and_assets.expected
@@ -1,6 +1,11 @@
 apk_path=lib/armeabi-v7a/libarcore_sdk_c.so, compress=False, alignment=4096
 apk_path=lib/armeabi-v7a/libchromium_android_linker.so, compress=False, alignment=4096
+apk_path=lib/armeabi-v7a/libmonochrome_cablev2_authenticator_partition.so, compress=False, alignment=4096
+apk_path=lib/armeabi-v7a/libmonochrome_stack_unwinder_partition.so, compress=False, alignment=4096
+apk_path=lib/armeabi-v7a/libmonochrome_test_dummy_partition.so, compress=False, alignment=4096
+apk_path=lib/armeabi-v7a/libmonochrome_vr_partition.so, compress=False, alignment=4096
 apk_path=assets/chrome_100_percent.pak, compress=False, alignment=4
+apk_path=assets/icudtl_extra.dat, compress=False, alignment=4
 apk_path=assets/locales/af.pak, compress=False, alignment=4
 apk_path=assets/locales/am.pak, compress=False, alignment=4
 apk_path=assets/locales/ar.pak, compress=False, alignment=4
diff --git a/chrome/android/java/res/layout/main.xml b/chrome/android/java/res/layout/main.xml
index f9ec479..fa1214a5 100644
--- a/chrome/android/java/res/layout/main.xml
+++ b/chrome/android/java/res/layout/main.xml
@@ -21,13 +21,6 @@
             android:layout_height="match_parent"
             android:visibility="gone" />
 
-        <org.chromium.components.messages.MessageContainer
-            android:id="@+id/message_container"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:visibility="gone"
-            android:layout_gravity="start|top" />
-
         <org.chromium.chrome.browser.ui.BottomContainer
             android:id="@+id/bottom_container"
             android:layout_width="match_parent"
@@ -98,6 +91,13 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content" />
 
+        <org.chromium.components.messages.MessageContainer
+            android:id="@+id/message_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:visibility="gone"
+            android:layout_gravity="start|top" />
+
         <ViewStub
             android:id="@+id/status_indicator_stub"
             android:layout_width="match_parent"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/DEPS
index 3902dc9..642ef72 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/DEPS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/DEPS
@@ -68,9 +68,6 @@
   "CardUnmaskPrompt\.java": [
     "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
   ],
-  "BookmarkPage\.java": [
-    "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
-  ],
   "BookmarkUtils\.java": [
     "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
   ],
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/about_settings/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/about_settings/OWNERS
index b0e25901..796c7d9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/about_settings/OWNERS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/about_settings/OWNERS
@@ -3,4 +3,4 @@
 
 # COMPONENT: UI>Browser>Mobile>Settings
 # OS: Android
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/accessibility/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/accessibility/OWNERS
index 9c52fe45..25f2d41 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/accessibility/OWNERS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/accessibility/OWNERS
@@ -3,4 +3,4 @@
 
 # COMPONENT: UI>Browser>Accessibility
 # OS: Android
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/accessibility_tab_switcher/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/accessibility_tab_switcher/OWNERS
index 89135db..c5d4f5e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/accessibility_tab_switcher/OWNERS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/accessibility_tab_switcher/OWNERS
@@ -1,5 +1,5 @@
 twellington@chromium.org
 
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
 # COMPONENT: UI>Browser>Mobile>TabSwitcher
 # OS: Android
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/announcement/AnnouncementNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/announcement/AnnouncementNotificationManager.java
index 5f2c25c..1d1cb2c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/announcement/AnnouncementNotificationManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/announcement/AnnouncementNotificationManager.java
@@ -14,7 +14,6 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.IntentUtils;
 import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
@@ -73,18 +72,14 @@
                         case IntentType.UNKNOWN:
                             break;
                         case IntentType.CLICK:
-                            recordHistogram(AnnouncementNotificationEvent.CLICK);
                             openUrl(context, url);
                             break;
                         case IntentType.CLOSE:
-                            recordHistogram(AnnouncementNotificationEvent.CLOSE);
                             break;
                         case IntentType.ACK:
-                            recordHistogram(AnnouncementNotificationEvent.ACK);
                             close();
                             break;
                         case IntentType.OPEN:
-                            recordHistogram(AnnouncementNotificationEvent.OPEN);
                             openUrl(context, url);
                             close();
                             break;
@@ -118,11 +113,6 @@
                 .cancel(ANNOUNCEMENT_NOTIFICATION_TAG, ANNOUNCEMENT_NOTIFICATION_ID);
     }
 
-    private static void recordHistogram(@AnnouncementNotificationEvent int event) {
-        RecordHistogram.recordEnumeratedHistogram("Notifications.Announcement.Events", event,
-                AnnouncementNotificationEvent.MAX_VALUE + 1);
-    }
-
     @CalledByNative
     private static void showNotification(String url) {
         Context context = ContextUtils.getApplicationContext();
@@ -157,8 +147,6 @@
         NotificationUmaTracker.getInstance().onNotificationShown(
                 NotificationUmaTracker.SystemNotificationType.ANNOUNCEMENT,
                 notification.getNotification());
-
-        recordHistogram(AnnouncementNotificationEvent.SHOWN);
     }
 
     @CalledByNative
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/video_tutorials/NewTabPageVideoIPHManager.java b/chrome/android/java/src/org/chromium/chrome/browser/app/video_tutorials/NewTabPageVideoIPHManager.java
index 8fdaf1e..b20a2f7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/video_tutorials/NewTabPageVideoIPHManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/video_tutorials/NewTabPageVideoIPHManager.java
@@ -68,6 +68,8 @@
     }
 
     private void onFetchTutorials(List<Tutorial> tutorials) {
+        if (tutorials.isEmpty()) return;
+
         // Make a copy of the list before adding summary card.
         List<Tutorial> tutorialsCopy = new ArrayList<>(tutorials);
         addSyntheticSummaryTutorial(tutorialsCopy);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActivity.java
index 88b5849b6..16b04e3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActivity.java
@@ -10,6 +10,8 @@
 
 import androidx.annotation.VisibleForTesting;
 
+import org.chromium.base.IntentUtils;
+import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.SnackbarActivity;
 import org.chromium.components.bookmarks.BookmarkId;
 import org.chromium.components.embedder_support.util.UrlConstants;
@@ -28,7 +30,10 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        mBookmarkManager = new BookmarkManager(this, true, getSnackbarManager());
+        mBookmarkManager = new BookmarkManager(this,
+                IntentUtils.safeGetParcelableExtra(
+                        getIntent(), IntentHandler.EXTRA_PARENT_COMPONENT),
+                true, getSnackbarManager());
         String url = getIntent().getDataString();
         if (TextUtils.isEmpty(url)) url = UrlConstants.BOOKMARKS_URL;
         mBookmarkManager.updateForUrl(url);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
index 47476e81..cd35640 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
@@ -4,10 +4,11 @@
 
 package org.chromium.chrome.browser.bookmarks;
 
-import android.app.Activity;
 import android.app.ActivityManager;
+import android.content.ComponentName;
 import android.content.Context;
 import android.text.TextUtils;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityManager;
@@ -49,7 +50,8 @@
 
     private static boolean sPreventLoadingForTesting;
 
-    private Activity mActivity;
+    private Context mContext;
+    private ComponentName mOpenBookmarkComponentName;
     private ViewGroup mMainView;
     private BookmarkModel mBookmarkModel;
     private BookmarkUndoController mUndoController;
@@ -158,12 +160,15 @@
     /**
      * Creates an instance of {@link BookmarkManager}. It also initializes resources,
      * bookmark models and jni bridges.
-     * @param activity The activity context to use.
+     * @param context The current {@link Context} used to obtain resources or inflate views.
+     * @param openBookmarkComponentName The component to use when opening a bookmark.
      * @param isDialogUi Whether the main bookmarks UI will be shown in a dialog, not a NativePage.
      * @param snackbarManager The {@link SnackbarManager} used to display snackbars.
      */
-    public BookmarkManager(Activity activity, boolean isDialogUi, SnackbarManager snackbarManager) {
-        mActivity = activity;
+    public BookmarkManager(Context context, ComponentName openBookmarkComponentName,
+            boolean isDialogUi, SnackbarManager snackbarManager) {
+        mContext = context;
+        mOpenBookmarkComponentName = openBookmarkComponentName;
         mIsDialogUi = isDialogUi;
 
         mSelectionDelegate = new SelectionDelegate<BookmarkId>() {
@@ -180,7 +185,7 @@
         mDragStateDelegate = new BookmarkDragStateDelegate();
 
         mBookmarkModel = new BookmarkModel();
-        mMainView = (ViewGroup) mActivity.getLayoutInflater().inflate(R.layout.bookmark_main, null);
+        mMainView = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.bookmark_main, null);
 
         @SuppressWarnings("unchecked")
         SelectableListLayout<BookmarkId> selectableList =
@@ -189,7 +194,7 @@
         mSelectableListLayout.initializeEmptyView(
                 R.string.bookmarks_folder_empty, R.string.bookmark_no_result);
 
-        mAdapter = new BookmarkItemsAdapter(activity);
+        mAdapter = new BookmarkItemsAdapter(mContext);
 
         mAdapterDataObserver = new AdapterDataObserver() {
             @Override
@@ -214,7 +219,7 @@
 
         mSelectableListLayout.configureWideDisplayStyle();
 
-        mUndoController = new BookmarkUndoController(activity, mBookmarkModel, snackbarManager);
+        mUndoController = new BookmarkUndoController(mContext, mBookmarkModel, snackbarManager);
         mBookmarkModel.addObserver(mBookmarkModelObserver);
         initializeToLoadingState();
         if (!sPreventLoadingForTesting) {
@@ -400,7 +405,7 @@
         if (state.mState == BookmarkUIState.STATE_FOLDER) {
             // Loading and searching states may be pushed to the stack but should never be stored in
             // preferences.
-            BookmarkUtils.setLastUsedUrl(mActivity, state.mUrl);
+            BookmarkUtils.setLastUsedUrl(mContext, state.mUrl);
             // If a loading state is replaced by another loading state, do not notify this change.
             if (mNativePage != null) {
                 mNativePage.onStateChange(state.mUrl, false);
@@ -489,8 +494,9 @@
 
     @Override
     public void openBookmark(BookmarkId bookmark) {
-        if (BookmarkUtils.openBookmark(mBookmarkModel, mActivity, bookmark)) {
-            BookmarkUtils.finishActivityOnPhone(mActivity);
+        if (BookmarkUtils.openBookmark(
+                    mContext, mOpenBookmarkComponentName, mBookmarkModel, bookmark)) {
+            BookmarkUtils.finishActivityOnPhone(mContext);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java
index e2b6f13..e3302ed 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java
@@ -4,10 +4,12 @@
 
 package org.chromium.chrome.browser.bookmarks;
 
+import android.content.ComponentName;
+
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.app.ChromeActivity;
+import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.ui.native_page.BasicNativePage;
 import org.chromium.chrome.browser.ui.native_page.NativePageHost;
 import org.chromium.components.embedder_support.util.UrlConstants;
@@ -21,13 +23,16 @@
 
     /**
      * Create a new instance of the bookmarks page.
+     * @param componentName The current activity component, used to open bookmarks.
+     * @param snackbarManager Allows control over the app snackbar.
      * @param activity The activity to get context and manage fragments.
      * @param host A NativePageHost to load urls.
      */
-    public BookmarkPage(ChromeActivity activity, NativePageHost host) {
+    public BookmarkPage(
+            ComponentName componentName, SnackbarManager snackbarManager, NativePageHost host) {
         super(host);
 
-        mManager = new BookmarkManager(activity, false, activity.getSnackbarManager());
+        mManager = new BookmarkManager(host.getContext(), componentName, false, snackbarManager);
         mManager.setBasicNativePage(this);
         mTitle = host.getContext().getResources().getString(R.string.bookmarks);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUndoController.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUndoController.java
index 16146566..cd2474e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUndoController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUndoController.java
@@ -16,8 +16,7 @@
 import java.util.Locale;
 
 /**
- * Shows an undo bar when the user modifies bookmarks,
- * allowing them to undo their changes.
+ * Shows an undo bar when the user modifies bookmarks, allowing them to undo their changes.
  */
 public class BookmarkUndoController extends BookmarkModelObserver implements
         SnackbarManager.SnackbarController, BookmarkDeleteObserver {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java
index 76c9662..428696e2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java
@@ -15,7 +15,6 @@
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.BuildInfo;
-import org.chromium.base.IntentUtils;
 import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.metrics.RecordHistogram;
@@ -245,32 +244,22 @@
 
     /**
      * Opens a bookmark and reports UMA.
+     * @param context The current context used to launch the intent.
+     * @param openBookmarkComponentName The component to use when opening a bookmark.
      * @param model Bookmarks model to manage the bookmark.
-     * @param activity Activity requesting to open the bookmark.
      * @param bookmarkId ID of the bookmark to be opened.
      * @return Whether the bookmark was successfully opened.
      */
-    public static boolean openBookmark(
-            BookmarkModel model, Activity activity, BookmarkId bookmarkId) {
+    public static boolean openBookmark(Context context, ComponentName openBookmarkComponentName,
+            BookmarkModel model, BookmarkId bookmarkId) {
         if (model.getBookmarkById(bookmarkId) == null) return false;
 
-        String url = model.getBookmarkById(bookmarkId).getUrl();
-
         RecordUserAction.record("MobileBookmarkManagerEntryOpened");
         RecordHistogram.recordEnumeratedHistogram(
                 "Bookmarks.OpenBookmarkType", bookmarkId.getType(), BookmarkType.LAST + 1);
 
-        if (activity instanceof BookmarkActivity) {
-            // For phones, the bookmark manager is a separate activity. When the activity is
-            // launched, an intent extra is set specifying the parent component.
-            ComponentName parentComponent = IntentUtils.safeGetParcelableExtra(
-                activity.getIntent(), IntentHandler.EXTRA_PARENT_COMPONENT);
-            openUrl(activity, url, parentComponent);
-        } else {
-            // For tablets, the bookmark manager is open in a tab in the ChromeActivity. Use
-            // the ComponentName of the ChromeActivity passed into this method.
-            openUrl(activity, url, activity.getComponentName());
-        }
+        String url = model.getBookmarkById(bookmarkId).getUrl();
+        openUrl(context, url, openBookmarkComponentName);
 
         return true;
     }
@@ -291,10 +280,10 @@
         return R.color.default_icon_color_tint_list;
     }
 
-    private static void openUrl(Activity activity, String url, ComponentName componentName) {
+    private static void openUrl(Context context, String url, ComponentName componentName) {
         Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
-        intent.putExtra(Browser.EXTRA_APPLICATION_ID,
-                activity.getApplicationContext().getPackageName());
+        intent.putExtra(
+                Browser.EXTRA_APPLICATION_ID, context.getApplicationContext().getPackageName());
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         intent.putExtra(IntentHandler.EXTRA_PAGE_TRANSITION_TYPE, PageTransition.AUTO_BOOKMARK);
 
@@ -304,7 +293,7 @@
             // If the bookmark manager is shown in a tab on a phone (rather than in a separate
             // activity) the component name may be null. Send the intent through
             // ChromeLauncherActivity instead to avoid crashing. See crbug.com/615012.
-            intent.setClass(activity, ChromeLauncherActivity.class);
+            intent.setClass(context.getApplicationContext(), ChromeLauncherActivity.class);
         }
 
         IntentHandler.startActivityForTrustedIntent(intent);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/OWNERS
index 4c277795..73398330 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/OWNERS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/OWNERS
@@ -1,5 +1,5 @@
 twellington@chromium.org
 
 # COMPONENT: UI>Browser>Bookmarks
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
 # OS: Android
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/compositor/OWNERS
index ba4650d..ba2abbe 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/OWNERS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/OWNERS
@@ -2,5 +2,5 @@
 mdjones@chromium.org
 
 # COMPONENT: UI>Browser>Mobile>CompositedUI
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
 # OS: Android
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/OWNERS
index 0170aa21..a5b333f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/OWNERS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/OWNERS
@@ -2,5 +2,5 @@
 sinansahin@google.com
 
 # COMPONENT: UI>Browser>Mobile>ContextMenu
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
 # OS: Android
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java
index 7e75ea0..0dc0b2b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java
@@ -60,8 +60,6 @@
 import org.chromium.chrome.browser.tab.TrustedCdn;
 import org.chromium.chrome.browser.toolbar.ToolbarColors;
 import org.chromium.chrome.browser.toolbar.ToolbarDataProvider;
-import org.chromium.chrome.browser.toolbar.ToolbarTabController;
-import org.chromium.chrome.browser.toolbar.menu_button.MenuButtonCoordinator;
 import org.chromium.chrome.browser.toolbar.top.ToolbarActionModeCallback;
 import org.chromium.chrome.browser.toolbar.top.ToolbarLayout;
 import org.chromium.chrome.browser.toolbar.top.ToolbarPhone;
@@ -159,7 +157,6 @@
     private int mState = STATE_DOMAIN_ONLY;
     private String mFirstUrl;
 
-    protected ToolbarDataProvider mToolbarDataProvider;
     private CustomTabLocationBar mLocationBar;
 
     private Runnable mTitleAnimationStarter = new Runnable() {
@@ -191,8 +188,6 @@
         mLiteStatusView = findViewById(R.id.url_bar_lite_status);
         mLiteStatusSeparatorView = findViewById(R.id.url_bar_lite_status_separator);
         mUrlCoordinator = new UrlBarCoordinator((UrlBar) mUrlBar);
-        mLocationBar = new CustomTabLocationBar();
-        mUrlCoordinator.setDelegate(mLocationBar);
         mUrlCoordinator.setAllowFocus(false);
         mTitleBar = findViewById(R.id.title_bar);
         mLocationBarFrameLayout = findViewById(R.id.location_bar_frame_layout);
@@ -208,14 +203,6 @@
     }
 
     @Override
-    protected void initialize(ToolbarDataProvider toolbarDataProvider,
-            ToolbarTabController tabController, MenuButtonCoordinator menuButtonCoordinator) {
-        super.initialize(toolbarDataProvider, tabController, menuButtonCoordinator);
-        mLocationBar.setToolbarDataProvider(toolbarDataProvider);
-        mLocationBar.updateVisualsForState();
-    }
-
-    @Override
     public void onNativeLibraryReady() {
         super.onNativeLibraryReady();
         mLocationBar.onNativeLibraryReady();
@@ -258,6 +245,27 @@
         updateCustomActionButtonVisuals(button, drawable, description);
     }
 
+    /**
+     *
+     * @param toolbarDataProvider {@link ToolbarDataProvider} to be used for accessing Toolbar
+     *         state.
+     * @return The LocationBar implementation for this CustomTabToolbar.
+     */
+    public LocationBar createLocationBar(ToolbarDataProvider toolbarDataProvider) {
+        mLocationBar = new CustomTabLocationBar(toolbarDataProvider);
+        mUrlCoordinator.setDelegate(mLocationBar);
+        mLocationBar.updateVisualsForState();
+        return mLocationBar;
+    }
+
+    /**
+     *
+     * @param actionModeCallback The default callback for text editing action bar to use.
+     */
+    public void setDefaultTextEditActionModeCallback(ToolbarActionModeCallback actionModeCallback) {
+        mUrlCoordinator.setActionModeCallback(actionModeCallback);
+    }
+
     private void updateCustomActionButtonVisuals(
             ImageButton button, Drawable drawable, String description) {
         Resources resources = getResources();
@@ -389,7 +397,7 @@
 
     private void updateToolbarLayoutMargin() {
         // We show the Incognito logo for Incognito CCT case
-        if (mToolbarDataProvider.isIncognito()) mIncognitoButton.setVisibility(VISIBLE);
+        if (getToolbarDataProvider().isIncognito()) mIncognitoButton.setVisibility(VISIBLE);
 
         int startMargin = calculateStartMarginWhenCloseButtonVisibilityGone();
 
@@ -616,7 +624,18 @@
     /**
      * Custom tab-specific implementation of the LocationBar interface.
      */
-    public class CustomTabLocationBar implements LocationBar {
+    private class CustomTabLocationBar implements LocationBar {
+        private ToolbarDataProvider mToolbarDataProvider;
+
+        public CustomTabLocationBar(ToolbarDataProvider toolbarDataProvider) {
+            mToolbarDataProvider = toolbarDataProvider;
+        }
+
+        /** Gets the {@link ToolbarDataProvider} to be used for accessing {@link Toolbar} state. */
+        ToolbarDataProvider getToolbarDataProvider() {
+            return mToolbarDataProvider;
+        }
+
         @Override
         public void onNativeLibraryReady() {
             mSecurityButton.setOnClickListener(v -> {
@@ -756,16 +775,6 @@
             updateStatusIcon();
         }
 
-        /** Sets the {@link ToolbarDataProvider} to be used for accessing {@link Toolbar} state. */
-        public void setToolbarDataProvider(ToolbarDataProvider model) {
-            mToolbarDataProvider = model;
-        }
-
-        /** Gets the {@link ToolbarDataProvider} to be used for accessing {@link Toolbar} state. */
-        public ToolbarDataProvider getToolbarDataProvider() {
-            return mToolbarDataProvider;
-        }
-
         @Override
         public void updateVisualsForState() {
             Resources resources = getResources();
@@ -824,10 +833,6 @@
             return mSecurityButton;
         }
 
-        public void setDefaultTextEditActionModeCallback(ToolbarActionModeCallback callback) {
-            mUrlCoordinator.setActionModeCallback(callback);
-        }
-
         @Override
         public void backKeyPressed() {
             assert false : "The URL bar should never take focus in CCTs.";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/OWNERS
index b3445f9..f2b14d9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/OWNERS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/OWNERS
@@ -1,5 +1,5 @@
 jinsukkim@chromium.org
 
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
 # COMPONENT: UI>Browser>Mobile
 # OS: Android
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java b/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java
index 3b366068..7fe6a37 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.homepage;
 
+import android.content.Context;
 import android.text.TextUtils;
 
 import androidx.annotation.NonNull;
@@ -12,10 +13,14 @@
 import org.chromium.base.ObserverList;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.homepage.settings.HomepageMetricsEnums.HomepageLocationType;
+import org.chromium.chrome.browser.homepage.settings.HomepageSettings;
 import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
+import org.chromium.chrome.browser.settings.SettingsLauncher;
+import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.components.embedder_support.util.UrlConstants;
 import org.chromium.components.embedder_support.util.UrlUtilities;
 
@@ -40,12 +45,14 @@
 
     private final SharedPreferencesManager mSharedPreferencesManager;
     private final ObserverList<HomepageStateListener> mHomepageStateListeners;
+    private SettingsLauncher mSettingsLauncher;
 
     private HomepageManager() {
         mSharedPreferencesManager = SharedPreferencesManager.getInstance();
         mHomepageStateListeners = new ObserverList<>();
         HomepagePolicyManager.getInstance().addListener(this);
         PartnerBrowserCustomizations.getInstance().setPartnerHomepageListener(this);
+        mSettingsLauncher = new SettingsLauncherImpl();
     }
 
     /**
@@ -74,6 +81,19 @@
     }
 
     /**
+     * Menu click handler on home button.
+     * @param context {@link Context} used for launching a settings activity.
+     */
+    public void onMenuClick(Context context) {
+        assert ChromeFeatureList.isInitialized();
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.HOMEPAGE_SETTINGS_UI_CONVERSION)) {
+            mSettingsLauncher.launchSettingsActivity(context, HomepageSettings.class);
+        } else {
+            setPrefHomepageEnabled(false);
+        }
+    }
+
+    /**
      * Notify any listeners about a homepage state change.
      */
     public void notifyHomepageUpdated() {
@@ -295,4 +315,9 @@
     public void onHomepageUpdate() {
         notifyHomepageUpdated();
     }
+
+    @VisibleForTesting
+    public void setSettingsLauncherForTesting(SettingsLauncher launcher) {
+        mSettingsLauncher = launcher;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/messages/MessageContainerCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/messages/MessageContainerCoordinator.java
new file mode 100644
index 0000000..bfcb29a
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/messages/MessageContainerCoordinator.java
@@ -0,0 +1,69 @@
+// 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.
+
+package org.chromium.chrome.browser.messages;
+
+import android.content.res.Resources;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
+import org.chromium.chrome.browser.fullscreen.BrowserControlsManager;
+import org.chromium.components.messages.MessageContainer;
+
+/**
+ * Coordinator of {@link MessageContainer}, which can adjust margins of the message container
+ * and control the visibility of browser control when message is being shown.
+ */
+public class MessageContainerCoordinator implements BrowserControlsStateProvider.Observer {
+    private MessageContainer mContainer;
+    private BrowserControlsManager mControlsManager;
+
+    public MessageContainerCoordinator(
+            @NonNull MessageContainer container, @NonNull BrowserControlsManager controlsManager) {
+        mContainer = container;
+        mControlsManager = controlsManager;
+        mControlsManager.addObserver(this);
+    }
+
+    public void destroy() {
+        mControlsManager.removeObserver(this);
+        mContainer = null;
+        mControlsManager = null;
+    }
+
+    private void updateMargins() {
+        CoordinatorLayout.LayoutParams params =
+                (CoordinatorLayout.LayoutParams) mContainer.getLayoutParams();
+        Resources res = mContainer.getResources();
+        // TODO(crbug.com/1123947): Update dimens for PWAs.
+        params.topMargin = mControlsManager.getTopControlsHeight()
+                - res.getDimensionPixelOffset(R.dimen.message_bubble_inset)
+                - res.getDimensionPixelOffset(R.dimen.message_shadow_top_margin);
+        mContainer.setLayoutParams(params);
+    }
+
+    public void showMessageContainer() {
+        mContainer.setVisibility(View.VISIBLE);
+        updateMargins();
+    }
+
+    public void hideMessageContainer() {
+        mContainer.setVisibility(View.GONE);
+    }
+
+    @Override
+    public void onControlsOffsetChanged(int topOffset, int topControlsMinHeightOffset,
+            int bottomOffset, int bottomControlsMinHeightOffset, boolean needsAnimate) {
+        updateMargins();
+    }
+
+    @Override
+    public void onTopControlsHeightChanged(int topControlsHeight, int topControlsMinHeight) {
+        updateMargins();
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
index 8b3f231..b7752eed 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
@@ -94,7 +94,8 @@
         }
 
         protected NativePage buildBookmarksPage(Tab tab) {
-            return new BookmarkPage(mActivity, new TabShim(tab, mActivity));
+            return new BookmarkPage(mActivity.getComponentName(), mActivity.getSnackbarManager(),
+                    new TabShim(tab, mActivity));
         }
 
         protected NativePage buildDownloadsPage(Tab tab) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/ConnectivityDetector.java b/chrome/android/java/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetector.java
similarity index 97%
rename from chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/ConnectivityDetector.java
rename to chrome/android/java/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetector.java
index 814b16d2..4f45049 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/ConnectivityDetector.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetector.java
@@ -2,7 +2,7 @@
 // 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.offlinepages.indicator;
+package org.chromium.chrome.browser.net.connectivitydetector;
 
 import android.annotation.TargetApi;
 import android.content.Context;
@@ -168,7 +168,7 @@
                 if (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
                         && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                         && capabilities.hasCapability(
-                                   NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)) {
+                                NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)) {
                     return ConnectionState.VALIDATED;
                 }
                 if (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)) {
@@ -428,8 +428,7 @@
             protected void onPostExecute(Integer result) {
                 callback.onResult(result);
             }
-        }
-                .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
     private void scheduleNextConnectivityCheck() {
@@ -482,15 +481,15 @@
         setConnectionState(newConnectionState);
     }
 
-    @VisibleForTesting
-    void setConnectionState(@ConnectionState int connectionState) {
+    @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+    public void setConnectionState(@ConnectionState int connectionState) {
         if (mConnectionState == connectionState) return;
         mConnectionState = connectionState;
         if (mObserver != null) mObserver.onConnectionStateChanged(mConnectionState);
     }
 
-    @VisibleForTesting
-    static void setDelegateForTesting(Delegate delegate) {
+    @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+    public static void setDelegateForTesting(Delegate delegate) {
         sOveriddenDelegate = delegate;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/net/connectivitydetector/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/net/connectivitydetector/OWNERS
new file mode 100644
index 0000000..840e7d7
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/net/connectivitydetector/OWNERS
@@ -0,0 +1,4 @@
+file://components/offline_pages/OWNERS
+
+# TEAM: offline-dev@chromium.org
+# COMPONENT: UI>Browser>Offline
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/OWNERS
index f810f08b..5306875 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/OWNERS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/OWNERS
@@ -1,4 +1,4 @@
 twellington@chromium.org
 
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
 # COMPONENT: UI>Browser>Mobile>ThemeColors
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineDetector.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineDetector.java
index 8b534480..fe03269 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineDetector.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineDetector.java
@@ -16,7 +16,8 @@
 import org.chromium.base.Log;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
-import org.chromium.chrome.browser.offlinepages.indicator.ConnectivityDetector.ConnectionState;
+import org.chromium.chrome.browser.net.connectivitydetector.ConnectivityDetector;
+import org.chromium.chrome.browser.net.connectivitydetector.ConnectivityDetector.ConnectionState;
 import org.chromium.chrome.browser.version.ChromeVersionInfo;
 import org.chromium.components.variations.VariationsAssociatedData;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorController.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorController.java
index 82de7eb..a91b3ebd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorController.java
@@ -22,6 +22,7 @@
 import org.chromium.chrome.browser.download.DownloadOpenSource;
 import org.chromium.chrome.browser.download.DownloadUtils;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.net.connectivitydetector.ConnectivityDetector;
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/settings/OWNERS
index 5ca740f..b44338e0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/settings/OWNERS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/OWNERS
@@ -3,5 +3,5 @@
 chouinard@chromium.org
 
 # COMPONENT: UI>Browser>Mobile>Settings
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
 # OS: Android
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/status_indicator/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/status_indicator/OWNERS
index b7f5658..7c26725 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/status_indicator/OWNERS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/status_indicator/OWNERS
@@ -1,9 +1,10 @@
 # Primary:
-mdjones@chromium.org
+sinansahin@google.com
 
 # Secondary:
+mdjones@chromium.org
 twellington@chromium.org
 
-# COMPONENT: UI>Browser>Mobile
+# COMPONENT: UI>Browser>Mobile>StatusIndicator
 # OS: Android
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/OWNERS
index c29df74..c7f66ea 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/OWNERS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/OWNERS
@@ -1,4 +1,4 @@
 twellington@chromium.org
 
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
 # COMPONENT: UI>Browser>Mobile
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java
index 5f79cba..3634b07 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.toolbar;
 
 import android.content.Context;
-import android.content.res.ColorStateList;
 import android.util.AttributeSet;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
@@ -17,121 +16,51 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.core.content.ContextCompat;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.Callback;
 import org.chromium.base.TraceEvent;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ActivityTabProvider;
-import org.chromium.chrome.browser.ActivityTabProvider.ActivityTabTabObserver;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
-import org.chromium.chrome.browser.homepage.HomepageManager;
-import org.chromium.chrome.browser.homepage.HomepagePolicyManager;
-import org.chromium.chrome.browser.homepage.settings.HomepageSettings;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
-import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tasks.ReturnToChromeExperimentsUtil;
-import org.chromium.chrome.browser.toolbar.ThemeColorProvider.TintObserver;
-import org.chromium.chrome.features.start_surface.StartSurface;
-import org.chromium.chrome.features.start_surface.StartSurfaceState;
-import org.chromium.components.embedder_support.util.UrlUtilities;
 import org.chromium.ui.widget.ChromeImageButton;
 
 /**
  * The home button.
+ * TODO(crbug.com/1056422): Fix the visibility bug on NTP.
  */
 public class HomeButton extends ChromeImageButton
-        implements TintObserver, OnCreateContextMenuListener, MenuItem.OnMenuItemClickListener,
-                   HomepageManager.HomepageStateListener {
+        implements OnCreateContextMenuListener, MenuItem.OnMenuItemClickListener {
     @VisibleForTesting
     public static final int ID_REMOVE = 0;
     @VisibleForTesting
     public static final int ID_SETTINGS = 1;
 
-    /** A provider that notifies components when the theme color changes.*/
-    private ThemeColorProvider mThemeColorProvider;
-
-    /** The {@link ActivityTabTabObserver} used to know when the active page changed. */
-    private ActivityTabTabObserver mActivityTabTabObserver;
-
-    /** The {@link ActivityTabProvider} used to know if the active tab is on the NTP. */
-    private ActivityTabProvider mActivityTabProvider;
+    private Callback<Context> mOnMenuClickCallback;
+    private Supplier<Boolean> mIsManagedByPolicySupplier;
 
     // Test related members
     private static boolean sSaveContextMenuForTests;
     private ContextMenu mMenuForTests;
 
-    private SettingsLauncher mSettingsLauncher;
-
-    private ObservableSupplier<StartSurface> mStartSurfaceSupplier;
-    private Callback<StartSurface> mStartSurfaceSupplierObserver;
-    private StartSurface mStartSurface;
-    private StartSurface.StateObserver mStartSurfaceStateObserver;
-
     public HomeButton(Context context, AttributeSet attrs) {
         super(context, attrs);
 
         final int homeButtonIcon = R.drawable.btn_toolbar_home;
         setImageDrawable(ContextCompat.getDrawable(context, homeButtonIcon));
-        HomepageManager.getInstance().addListener(this);
+    }
+
+    /**
+     * Initialize home button.
+     * @param homepageVisibility Observable used to react on homepage visibility change.
+     * @param onHomepageMenuClickCallback Callback for menu click event on homepage.
+     * @param isHomepageManagedByPolicy Supplier that tells if homepage is managed by policy.
+     */
+    public void init(ObservableSupplier<Boolean> homepageVisibility,
+            Callback<Context> onMenuClickCallback, Supplier<Boolean> isHomepageManagedByPolicy) {
+        homepageVisibility.addObserver((visible) -> updateContextMenuListener());
+        mOnMenuClickCallback = onMenuClickCallback;
+        mIsManagedByPolicySupplier = isHomepageManagedByPolicy;
         updateContextMenuListener();
-
-        mSettingsLauncher = new SettingsLauncherImpl();
-    }
-
-    public void destroy() {
-        if (mThemeColorProvider != null) {
-            mThemeColorProvider.removeTintObserver(this);
-            mThemeColorProvider = null;
-        }
-
-        if (mActivityTabTabObserver != null) {
-            mActivityTabTabObserver.destroy();
-            mActivityTabTabObserver = null;
-        }
-
-        HomepageManager.getInstance().removeListener(this);
-
-        if (mStartSurfaceSupplier != null) {
-            mStartSurfaceSupplier.removeObserver(mStartSurfaceSupplierObserver);
-        }
-
-        if (mStartSurface != null) {
-            mStartSurface.removeStateChangeObserver(mStartSurfaceStateObserver);
-        }
-    }
-
-    public void setThemeColorProvider(ThemeColorProvider themeColorProvider) {
-        mThemeColorProvider = themeColorProvider;
-        mThemeColorProvider.addTintObserver(this);
-    }
-
-    public void setStartSurfaceSupplier(ObservableSupplier<StartSurface> startSurfaceSupplier) {
-        assert ReturnToChromeExperimentsUtil.shouldShowStartSurfaceAsTheHomePage();
-
-        mStartSurfaceSupplier = startSurfaceSupplier;
-        mStartSurfaceSupplierObserver = (startSurface) -> {
-            // TODO(crbug.com/1084528): Replace with OneShotSupplier when it is available.
-            assert startSurface != null;
-            assert mStartSurface == null : "The StartSurface should be set at most once.";
-
-            mStartSurface = startSurface;
-            mStartSurfaceStateObserver = (newState, shouldShowToolbar) -> {
-                if (newState == StartSurfaceState.SHOWN_HOMEPAGE) {
-                    updateButtonEnabledState(false);
-                } else {
-                    updateButtonEnabledState(null);
-                }
-            };
-            startSurface.addStateChangeObserver(mStartSurfaceStateObserver);
-        };
-        mStartSurfaceSupplier.addObserver(mStartSurfaceSupplierObserver);
-    }
-
-    @Override
-    public void onTintChanged(ColorStateList tint, boolean useLight) {
-        ApiCompatibilityUtils.setImageTintList(this, tint);
     }
 
     @Override
@@ -152,41 +81,18 @@
 
     @Override
     public boolean onMenuItemClick(MenuItem item) {
-        assert !isManagedByPolicy();
+        assert !mIsManagedByPolicySupplier.get();
         if (isHomepageSettingsUIConversionEnabled()) {
             assert item.getItemId() == ID_SETTINGS;
-            mSettingsLauncher.launchSettingsActivity(getContext(), HomepageSettings.class);
         } else {
             assert item.getItemId() == ID_REMOVE;
-            HomepageManager.getInstance().setPrefHomepageEnabled(false);
         }
+        mOnMenuClickCallback.onResult(getContext());
 
         return true;
     }
 
     @Override
-    public void onHomepageStateUpdated() {
-        updateButtonEnabledState(null);
-    }
-
-    public void setActivityTabProvider(ActivityTabProvider activityTabProvider) {
-        mActivityTabProvider = activityTabProvider;
-        mActivityTabTabObserver = new ActivityTabTabObserver(activityTabProvider) {
-            @Override
-            public void onObservingDifferentTab(Tab tab, boolean hint) {
-                if (tab == null) return;
-                updateButtonEnabledState(tab);
-            }
-
-            @Override
-            public void onUpdateUrl(Tab tab, String url) {
-                if (tab == null) return;
-                updateButtonEnabledState(tab);
-            }
-        };
-    }
-
-    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         try (TraceEvent e = TraceEvent.scoped("HomeButton.onMeasure")) {
             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@@ -200,60 +106,8 @@
         }
     }
 
-    /**
-     * Menu button is enabled when not in NTP or if in NTP and homepage is enabled and set to
-     * somewhere other than the NTP.
-     * @param tab The notifying {@link Tab} that might be selected soon, this is a hint that a tab
-     *         change is likely.
-     */
-    public void updateButtonEnabledState(Tab tab) {
-        // New tab page button takes precedence over homepage.
-        final boolean isHomepageEnabled = HomepageManager.isHomepageEnabled();
-
-        boolean isEnabled;
-        if (getActiveTab() != null) {
-            // Now tab shows a webpage, let's check if the webpage is not the NTP, or the webpage is
-            // NTP but homepage is not NTP.
-            isEnabled = !isTabNTP(getActiveTab())
-                    || (isHomepageEnabled
-                            && !UrlUtilities.isNTPUrl(HomepageManager.getHomepageUri()));
-        } else {
-            // There is no active tab, which means tab is in transition, ex tab swither view to tab
-            // view, or from one tab to another tab.
-            isEnabled = !isTabNTP(tab);
-        }
-        updateButtonEnabledState(isEnabled);
-    }
-
-    private void updateButtonEnabledState(boolean isEnabled) {
-        setEnabled(isEnabled);
-        updateContextMenuListener();
-    }
-
-    /**
-     * Check if the provided tab is NTP. The tab is a hint that
-     * @param tab The notifying {@link Tab} that might be selected soon, this is a hint that a tab
-     *         change is likely.
-     */
-    private boolean isTabNTP(Tab tab) {
-        return tab != null && UrlUtilities.isNTPUrl(tab.getUrlString());
-    }
-
-    /**
-     * Return the active tab. If no active tab is shown, return null.
-     */
-    private Tab getActiveTab() {
-        if (mActivityTabProvider == null) return null;
-
-        return mActivityTabProvider.get();
-    }
-
-    private boolean isManagedByPolicy() {
-        return HomepagePolicyManager.isHomepageManagedByPolicy();
-    }
-
     private void updateContextMenuListener() {
-        if (!isManagedByPolicy()) {
+        if (!mIsManagedByPolicySupplier.get()) {
             setOnCreateContextMenuListener(this);
         } else {
             setOnCreateContextMenuListener(null);
@@ -281,9 +135,4 @@
     public ContextMenu getMenuForTests() {
         return mMenuForTests;
     }
-
-    @VisibleForTesting
-    public void setSettingsLauncherForTests(SettingsLauncher settingsLauncher) {
-        mSettingsLauncher = settingsLauncher;
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index 0ae6a12..0563492 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -47,13 +47,13 @@
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior.OverviewModeObserver;
 import org.chromium.chrome.browser.compositor.layouts.SceneChangeObserver;
 import org.chromium.chrome.browser.customtabs.features.toolbar.CustomTabToolbar;
-import org.chromium.chrome.browser.customtabs.features.toolbar.CustomTabToolbar.CustomTabLocationBar;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.findinpage.FindToolbarManager;
 import org.chromium.chrome.browser.findinpage.FindToolbarObserver;
 import org.chromium.chrome.browser.fullscreen.FullscreenManager;
 import org.chromium.chrome.browser.fullscreen.FullscreenOptions;
 import org.chromium.chrome.browser.homepage.HomepageManager;
+import org.chromium.chrome.browser.homepage.HomepagePolicyManager;
 import org.chromium.chrome.browser.identity_disc.IdentityDiscController;
 import org.chromium.chrome.browser.ntp.FakeboxDelegate;
 import org.chromium.chrome.browser.ntp.IncognitoNewTabPage;
@@ -345,13 +345,10 @@
         mActionModeController.setTabStripHeight(mToolbar.getTabStripHeight());
 
         if (toolbarLayout instanceof CustomTabToolbar) {
-            CustomTabLocationBar customTabLocationBar =
-                    (CustomTabLocationBar) mToolbar.getLocationBar();
-            // TODO(https://crbug.com/1140188): Use a factory to wire these dependencies.
-            customTabLocationBar.setToolbarDataProvider(mLocationBarModel);
-            customTabLocationBar.setDefaultTextEditActionModeCallback(
+            CustomTabToolbar customTabToolbar = ((CustomTabToolbar) toolbarLayout);
+            mLocationBar = customTabToolbar.createLocationBar(mLocationBarModel);
+            customTabToolbar.setDefaultTextEditActionModeCallback(
                     mActionModeController.getActionModeCallback());
-            mLocationBar = customTabLocationBar;
         } else {
             LocationBarCoordinator locationBarCoordinator = new LocationBarCoordinator(
                     mActivity.findViewById(R.id.location_bar), profileSupplier, mLocationBarModel,
@@ -687,6 +684,12 @@
             identityDiscController.addObserver(
                     (canShowHint) -> mIdentityDiscStateSupplier.set(canShowHint));
         }
+        HomeButton homeButton = toolbarLayout.getHomeButton();
+        if (homeButton != null) {
+            homeButton.init(mHomeButtonVisibilitySupplier,
+                    HomepageManager.getInstance()::onMenuClick,
+                    HomepagePolicyManager::isHomepageManagedByPolicy);
+        }
         return toolbar;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
index 82fa406..3a1940a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
@@ -365,10 +365,6 @@
 
     @Override
     void destroy() {
-        if (mHomeButton != null) {
-            mHomeButton.destroy();
-            mHomeButton = null;
-        }
         if (mLocationBar != null) {
             mLocationBar.destroy();
             mLocationBar = null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java
index e1d3011..0e312bf3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java
@@ -151,10 +151,6 @@
 
     @Override
     void destroy() {
-        if (mHomeButton != null) {
-            mHomeButton.destroy();
-            mHomeButton = null;
-        }
         if (mLocationBar != null) {
             mLocationBar.destroy();
             mLocationBar = null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java
index 944aad1..eec045e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java
@@ -193,6 +193,10 @@
         TranslateBridgeJni.get().setExplicitLanguageAskPromptShown(shown);
     }
 
+    public static void setIgnoreMissingKeyForTesting(boolean ignore) {
+        TranslateBridgeJni.get().setIgnoreMissingKeyForTesting(ignore); // IN-TEST
+    }
+
     @NativeMethods
     interface Natives {
         void manualTranslateWhenReady(WebContents webContents);
@@ -213,5 +217,6 @@
         void setLanguageBlockedState(String language, boolean blocked);
         boolean getExplicitLanguageAskPromptShown();
         void setExplicitLanguageAskPromptShown(boolean shown);
+        void setIgnoreMissingKeyForTesting(boolean ignore);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
index 91c0856..6c4dd94 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
@@ -53,6 +53,7 @@
 import org.chromium.chrome.browser.image_descriptions.ImageDescriptionsController;
 import org.chromium.chrome.browser.lifecycle.Destroyable;
 import org.chromium.chrome.browser.lifecycle.InflationObserver;
+import org.chromium.chrome.browser.messages.MessageContainerCoordinator;
 import org.chromium.chrome.browser.metrics.UkmRecorder;
 import org.chromium.chrome.browser.omnibox.OmniboxFocusReason;
 import org.chromium.chrome.browser.omnibox.geo.GeolocationHeader;
@@ -86,6 +87,7 @@
 import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator;
 import org.chromium.components.feature_engagement.EventConstants;
 import org.chromium.components.messages.ManagedMessageDispatcher;
+import org.chromium.components.messages.MessageContainer;
 import org.chromium.components.messages.MessagesFactory;
 import org.chromium.content_public.browser.ActionModeCallbackHelper;
 import org.chromium.content_public.browser.LoadUrlParams;
@@ -164,6 +166,8 @@
     private final OneshotSupplier<StartSurface> mStartSurfaceSupplier;
     @Nullable
     private ManagedMessageDispatcher mMessageDispatcher;
+    @Nullable
+    private MessageContainerCoordinator mMessageContainerCoordinator;
     private LayoutManager mLayoutManager;
 
     /**
@@ -256,6 +260,11 @@
             mMessageDispatcher = null;
         }
 
+        if (mMessageContainerCoordinator != null) {
+            mMessageContainerCoordinator.destroy();
+            mMessageContainerCoordinator = null;
+        }
+
         if (mLayoutManager != null) {
             mLayoutManager.removeSceneChangeObserver(mContextualSearchSceneChangeObserver);
         }
@@ -343,8 +352,10 @@
         initFindToolbarManager();
         initializeToolbar();
         if (CachedFeatureFlags.isEnabled(ChromeFeatureList.MESSAGES_FOR_ANDROID_INFRASTRUCTURE)) {
-            mMessageDispatcher = MessagesFactory.createMessageDispatcher(
-                    mActivity.findViewById(R.id.message_container));
+            MessageContainer container = mActivity.findViewById(R.id.message_container);
+            mMessageContainerCoordinator =
+                    new MessageContainerCoordinator(container, getBrowserControlsManager());
+            mMessageDispatcher = MessagesFactory.createMessageDispatcher(container);
             MessagesFactory.attachMessageDispatcher(
                     mActivity.getWindowAndroid(), mMessageDispatcher);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/UsageStatsService.java b/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/UsageStatsService.java
index dc619dd..7439e1a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/UsageStatsService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/UsageStatsService.java
@@ -9,6 +9,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.BuildInfo;
+import org.chromium.base.CollectionUtil;
 import org.chromium.base.Log;
 import org.chromium.base.Promise;
 import org.chromium.base.ThreadUtils;
@@ -249,12 +250,9 @@
     }
 
     private void notifyObserversOfSuspensions(List<String> fqdns, boolean suspended) {
-        for (WeakReference<PageViewObserver> observerRef : mPageViewObservers) {
-            PageViewObserver observer = observerRef.get();
-            if (observer != null) {
-                for (String fqdn : fqdns) {
-                    observer.notifySiteSuspensionChanged(fqdn, suspended);
-                }
+        for (PageViewObserver observer : CollectionUtil.strengthen(mPageViewObservers)) {
+            for (String fqdn : fqdns) {
+                observer.notifySiteSuspensionChanged(fqdn, suspended);
             }
         }
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
index fc1ebaeb..d072f502 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -66,9 +66,6 @@
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.infobar.InfoBarContainer;
 import org.chromium.chrome.browser.infobar.InstallableAmbientBadgeInfoBar;
-import org.chromium.chrome.browser.init.BrowserParts;
-import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
-import org.chromium.chrome.browser.init.EmptyBrowserParts;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabUtils;
@@ -88,7 +85,10 @@
 import org.chromium.components.infobars.InfoBar;
 import org.chromium.components.infobars.InfoBarAnimationListener;
 import org.chromium.components.infobars.InfoBarUiItem;
+import org.chromium.components.signin.AccountManagerFacadeProvider;
+import org.chromium.components.signin.test.util.FakeAccountManagerFacade;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
+import org.chromium.content_public.browser.test.NativeLibraryTestUtils;
 import org.chromium.content_public.browser.test.util.Criteria;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -101,7 +101,6 @@
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Tests the app banners.
@@ -235,7 +234,8 @@
             }
         };
 
-        loadNative();
+        AccountManagerFacadeProvider.setInstanceForTests(new FakeAccountManagerFacade(null));
+        NativeLibraryTestUtils.loadNativeLibraryAndInitBrowserProcess();
 
         ThreadUtils.runOnUiThreadBlocking(() -> {
             Profile profile = Profile.getLastUsedRegularProfile();
@@ -262,22 +262,6 @@
         }
     }
 
-    private void loadNative() {
-        final AtomicBoolean mNativeLoaded = new AtomicBoolean();
-        final BrowserParts parts = new EmptyBrowserParts() {
-            @Override
-            public void finishNativeInitialization() {
-                mNativeLoaded.set(true);
-            }
-        };
-        PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> {
-            ChromeBrowserInitializer.getInstance().handlePreNativeStartup(parts);
-            ChromeBrowserInitializer.getInstance().handlePostNativeStartup(true, parts);
-        });
-        CriteriaHelper.pollUiThread(
-                () -> mNativeLoaded.get(), "Failed while waiting for starting native.");
-    }
-
     private void resetEngagementForUrl(final String url, final double engagement) {
         ThreadUtils.runOnUiThreadBlocking(() -> {
             // TODO (https://crbug.com/1063807):  Add incognito mode tests.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/OWNERS
index a86aa489c..813e9f7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/OWNERS
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/OWNERS
@@ -1,5 +1,5 @@
 file://chrome/android/java/src/org/chromium/chrome/browser/gesturenav/OWNERS
 
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
 # COMPONENT: UI>Browser>Mobile
 # OS: Android
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/ConnectivityDetectorDelegateStub.java b/chrome/android/javatests/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetectorDelegateStub.java
similarity index 94%
rename from chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/ConnectivityDetectorDelegateStub.java
rename to chrome/android/javatests/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetectorDelegateStub.java
index 388c9bd8..169db0f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/ConnectivityDetectorDelegateStub.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetectorDelegateStub.java
@@ -2,7 +2,7 @@
 // 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.offlinepages.indicator;
+package org.chromium.chrome.browser.net.connectivitydetector;
 
 /**
  * Stub of ConnectivityDetector.Delegate for testing purpose.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/ConnectivityDetectorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetectorTest.java
similarity index 99%
rename from chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/ConnectivityDetectorTest.java
rename to chrome/android/javatests/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetectorTest.java
index f1b7549..342595d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/ConnectivityDetectorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetectorTest.java
@@ -2,7 +2,7 @@
 // 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.offlinepages.indicator;
+package org.chromium.chrome.browser.net.connectivitydetector;
 
 import android.support.test.InstrumentationRegistry;
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/net/connectivitydetector/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/net/connectivitydetector/OWNERS
new file mode 100644
index 0000000..d5dbb16
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/net/connectivitydetector/OWNERS
@@ -0,0 +1,4 @@
+file://chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OWNERS
+
+# TEAM: offline-dev@chromium.org
+# COMPONENT: UI>Browser>Offline
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java
index 918a521..04d48bae 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.offlinepages;
 
+import android.content.Intent;
 import android.net.Uri;
 import android.support.test.InstrumentationRegistry;
 import android.util.Base64;
@@ -15,6 +16,7 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 
 import org.chromium.base.ApiCompatibilityUtils;
@@ -22,14 +24,20 @@
 import org.chromium.base.task.PostTask;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.DisabledTest;
+import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
+import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.incognito.IncognitoDataTestUtils;
 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge.OfflinePageModelObserver;
 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge.SavePageCallback;
 import org.chromium.chrome.browser.offlinepages.downloads.OfflinePageDownloadBridge;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.profiles.ProfileKey;
+import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
+import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.components.offlinepages.DeletePageResult;
 import org.chromium.components.offlinepages.SavePageResult;
 import org.chromium.content_public.browser.LoadUrlParams;
@@ -59,8 +67,14 @@
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class OfflinePageBridgeTest {
     @Rule
+    public TestRule mProcessor = new Features.InstrumentationProcessor();
+
+    @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
 
+    @Rule
+    public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule();
+
     private static final String TEST_PAGE = "/chrome/test/data/android/about.html";
     private static final int TIMEOUT_MS = 5000;
     private static final ClientId TEST_CLIENT_ID =
@@ -69,17 +83,13 @@
     private OfflinePageBridge mOfflinePageBridge;
     private EmbeddedTestServer mTestServer;
     private String mTestPage;
+    private Profile mProfile;
 
-    private void initializeBridgeForProfile(final boolean incognitoProfile)
-            throws InterruptedException {
+    private void initializeBridgeForProfile() throws InterruptedException {
         final Semaphore semaphore = new Semaphore(0);
         PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> {
-            Profile profile = Profile.getLastUsedRegularProfile();
-            if (incognitoProfile) {
-                profile = profile.getOffTheRecordProfile();
-            }
             // Ensure we start in an offline state.
-            mOfflinePageBridge = OfflinePageBridge.getForProfile(profile);
+            mOfflinePageBridge = OfflinePageBridge.getForProfile(mProfile);
             if (mOfflinePageBridge == null || mOfflinePageBridge.isOfflinePageModelLoaded()) {
                 semaphore.release();
                 return;
@@ -93,19 +103,13 @@
             });
         });
         Assert.assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        if (!incognitoProfile) Assert.assertNotNull(mOfflinePageBridge);
     }
 
-    private OfflinePageBridge getBridgeForProfileKey(final boolean incognitoProfile)
-            throws InterruptedException {
+    private OfflinePageBridge getBridgeForProfileKey() throws InterruptedException {
         final Semaphore semaphore = new Semaphore(0);
         AtomicReference<OfflinePageBridge> offlinePageBridgeRef = new AtomicReference<>();
         PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> {
-            Profile profile = Profile.getLastUsedRegularProfile();
-            if (incognitoProfile) {
-                profile = profile.getOffTheRecordProfile();
-            }
-            ProfileKey profileKey = profile.getProfileKey();
+            ProfileKey profileKey = mProfile.getProfileKey();
             // Ensure we start in an offline state.
             OfflinePageBridge offlinePageBridge = OfflinePageBridge.getForProfileKey(profileKey);
             offlinePageBridgeRef.set(offlinePageBridge);
@@ -122,7 +126,6 @@
             });
         });
         Assert.assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        if (!incognitoProfile) Assert.assertNotNull(offlinePageBridgeRef.get());
         return offlinePageBridgeRef.get();
     }
 
@@ -138,7 +141,10 @@
             }
         });
 
-        initializeBridgeForProfile(false);
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { mProfile = Profile.getLastUsedRegularProfile(); });
+
+        initializeBridgeForProfile();
 
         mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
         mTestPage = mTestServer.getURL(TEST_PAGE);
@@ -152,7 +158,7 @@
     @Test
     @MediumTest
     public void testProfileAndKeyMapToSameOfflinePageBridge() throws Exception {
-        OfflinePageBridge offlinePageBridgeRetrievedByKey = getBridgeForProfileKey(false);
+        OfflinePageBridge offlinePageBridgeRetrievedByKey = getBridgeForProfileKey();
         Assert.assertSame(mOfflinePageBridge, offlinePageBridgeRetrievedByKey);
     }
 
@@ -201,15 +207,50 @@
 
     @Test
     @MediumTest
-    public void testOfflinePageBridgeDisabledInIncognito() throws Exception {
-        initializeBridgeForProfile(true);
+    public void testOfflinePageBridgeDisabled_InIncognitoTabbedActivity() throws Exception {
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { mProfile = Profile.getLastUsedRegularProfile().getPrimaryOTRProfile(); });
+        initializeBridgeForProfile();
         Assert.assertEquals(null, mOfflinePageBridge);
     }
 
     @Test
     @MediumTest
-    public void testOfflinePageBridgeForProfileKeyDisabledInIncognito() throws Exception {
-        OfflinePageBridge offlinePageBridgeRetrievedByKey = getBridgeForProfileKey(true);
+    public void testOfflinePageBridgeForProfileKeyDisabled_InIncognitoTabbedActivity()
+            throws Exception {
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { mProfile = Profile.getLastUsedRegularProfile().getPrimaryOTRProfile(); });
+        OfflinePageBridge offlinePageBridgeRetrievedByKey = getBridgeForProfileKey();
+        Assert.assertNull(offlinePageBridgeRetrievedByKey);
+    }
+
+    @Test
+    @MediumTest
+    @Features.EnableFeatures({ChromeFeatureList.CCT_INCOGNITO})
+    public void testOfflinePageBridgeDisabled_InIncognitoCCT() throws Exception {
+        prepareAndLaunchIncognitoCCT();
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            Tab tab = mCustomTabActivityTestRule.getActivity().getActivityTab();
+            mProfile = Profile.fromWebContents(tab.getWebContents());
+            Assert.assertTrue(mProfile.isOffTheRecord());
+            Assert.assertFalse(mProfile.isPrimaryOTRProfile());
+        });
+        initializeBridgeForProfile();
+        Assert.assertEquals(null, mOfflinePageBridge);
+    }
+
+    @Test
+    @MediumTest
+    @Features.EnableFeatures({ChromeFeatureList.CCT_INCOGNITO})
+    public void testOfflinePageBridgeForProfileKeyDisabled_InIncognitoCCT() throws Exception {
+        prepareAndLaunchIncognitoCCT();
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            Tab tab = mCustomTabActivityTestRule.getActivity().getActivityTab();
+            mProfile = Profile.fromWebContents(tab.getWebContents());
+            Assert.assertTrue(mProfile.isOffTheRecord());
+            Assert.assertFalse(mProfile.isPrimaryOTRProfile());
+        });
+        OfflinePageBridge offlinePageBridgeRetrievedByKey = getBridgeForProfileKey();
         Assert.assertNull(offlinePageBridgeRetrievedByKey);
     }
 
@@ -550,4 +591,11 @@
             outputChannel.close();
         }
     }
+
+    private void prepareAndLaunchIncognitoCCT() throws TimeoutException {
+        Intent intent = CustomTabsTestUtils.createMinimalIncognitoCustomTabIntent(
+                InstrumentationRegistry.getContext(), "about:blank");
+        IncognitoDataTestUtils.fireAndWaitForCctWarmup();
+        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java
index 249e1b8..7e0d077b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java
@@ -23,6 +23,8 @@
 import org.chromium.chrome.browser.download.DownloadActivity;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.net.connectivitydetector.ConnectivityDetector;
+import org.chromium.chrome.browser.net.connectivitydetector.ConnectivityDetectorDelegateStub;
 import org.chromium.chrome.browser.offlinepages.ClientId;
 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/HomeButtonTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/HomeButtonTest.java
index 83f1f1b..92dd507f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/HomeButtonTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/HomeButtonTest.java
@@ -26,9 +26,11 @@
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
+import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.homepage.HomepageManager;
+import org.chromium.chrome.browser.homepage.HomepagePolicyManager;
 import org.chromium.chrome.browser.homepage.HomepageTestRule;
 import org.chromium.chrome.browser.homepage.settings.HomepageSettings;
 import org.chromium.chrome.browser.settings.SettingsLauncher;
@@ -83,8 +85,11 @@
 
             mIdHomeButton = View.generateViewId();
             mHomeButton = new HomeButton(getActivity(), null);
+            mHomeButton.init(new ObservableSupplierImpl<Boolean>(),
+                    HomepageManager.getInstance()::onMenuClick,
+                    HomepagePolicyManager::isHomepageManagedByPolicy);
             mHomeButton.setId(mIdHomeButton);
-            mHomeButton.setSettingsLauncherForTests(mSettingsLauncher);
+            HomepageManager.getInstance().setSettingsLauncherForTesting(mSettingsLauncher);
             HomeButton.setSaveContextMenuForTests(true);
 
             content.addView(mHomeButton);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateCompactInfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateCompactInfoBarTest.java
index 87b48d3..864076b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateCompactInfoBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateCompactInfoBarTest.java
@@ -17,22 +17,21 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.infobar.InfoBarContainer;
 import org.chromium.chrome.browser.infobar.TranslateCompactInfoBar;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
-import org.chromium.chrome.test.util.ChromeRestriction;
 import org.chromium.chrome.test.util.InfoBarTestAnimationListener;
 import org.chromium.chrome.test.util.InfoBarUtil;
 import org.chromium.chrome.test.util.MenuUtils;
 import org.chromium.chrome.test.util.TranslateUtil;
 import org.chromium.components.infobars.InfoBar;
-import org.chromium.net.test.EmbeddedTestServer;
+import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
 import java.util.concurrent.TimeoutException;
 
@@ -51,20 +50,30 @@
 
     private InfoBarContainer mInfoBarContainer;
     private InfoBarTestAnimationListener mListener;
-    private EmbeddedTestServer mTestServer;
 
     @Before
     public void setUp() throws Exception {
         mActivityTestRule.startMainActivityOnBlankPage();
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> TranslateBridge.setIgnoreMissingKeyForTesting(true));
         mInfoBarContainer = mActivityTestRule.getInfoBarContainer();
         mListener = new InfoBarTestAnimationListener();
         mInfoBarContainer.addAnimationListener(mListener);
-        mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
     }
 
     @After
     public void tearDown() {
-        mTestServer.stopAndDestroyServer();
+        mInfoBarContainer.removeAnimationListener(mListener);
+    }
+
+    /**
+     * Returns true if a test that requires internet access should be skipped due to an
+     * out-of-process NetworkService. When the NetworkService is run out-of-process, a fake DNS
+     * resolver is used that will fail to resolve any non-local names. crbug.com/1134812 is tracking
+     * the changes to make the translate service mockable and remove the internet requirement.
+     */
+    private boolean shouldSkipDueToNetworkService() {
+        return !ChromeFeatureList.isEnabled("NetworkServiceInProcess");
     }
 
     /**
@@ -73,10 +82,10 @@
     @Test
     @MediumTest
     @Feature({"Browser", "Main"})
-    @Restriction(ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES)
-    @DisabledTest(message = "https://crbug.com/1130712")
+    @Restriction({Restriction.RESTRICTION_TYPE_INTERNET})
     public void testTranslateCompactInfoBarAppears() throws TimeoutException {
-        mActivityTestRule.loadUrl(mTestServer.getURL(TRANSLATE_PAGE));
+        if (shouldSkipDueToNetworkService()) return;
+        mActivityTestRule.loadUrl(mActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE));
         mListener.addInfoBarAnimationFinished("InfoBar not opened.");
         InfoBar infoBar = mInfoBarContainer.getInfoBarsForTesting().get(0);
         TranslateUtil.assertCompactTranslateInfoBar(infoBar);
@@ -89,10 +98,10 @@
     @Test
     @MediumTest
     @Feature({"Browser", "Main"})
-    @Restriction(ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES)
-    @DisabledTest(message = "https://crbug.com/1130712")
+    @Restriction({Restriction.RESTRICTION_TYPE_INTERNET})
     public void testTranslateCompactInfoBarOverflowMenus() throws TimeoutException {
-        mActivityTestRule.loadUrl(mTestServer.getURL(TRANSLATE_PAGE));
+        if (shouldSkipDueToNetworkService()) return;
+        mActivityTestRule.loadUrl(mActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE));
         mListener.addInfoBarAnimationFinished("InfoBar not opened.");
         TranslateCompactInfoBar infoBar =
                 (TranslateCompactInfoBar) mInfoBarContainer.getInfoBarsForTesting().get(0);
@@ -112,10 +121,10 @@
     @Test
     @MediumTest
     @Feature({"Browser", "Main"})
-    @Restriction(ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES)
-    @DisabledTest(message = "https://crbug.com/1130712")
+    @Restriction({Restriction.RESTRICTION_TYPE_INTERNET})
     public void testTabMenuDismissedOnOrientationChange() throws Exception {
-        mActivityTestRule.loadUrl(mTestServer.getURL(TRANSLATE_PAGE));
+        if (shouldSkipDueToNetworkService()) return;
+        mActivityTestRule.loadUrl(mActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE));
         mListener.addInfoBarAnimationFinished("InfoBar not opened.");
         TranslateCompactInfoBar infoBar =
                 (TranslateCompactInfoBar) mInfoBarContainer.getInfoBarsForTesting().get(0);
@@ -142,19 +151,15 @@
     @Test
     @MediumTest
     @Feature({"Browser", "Main"})
-    @Restriction(ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES)
-    @DisabledTest(message = "https://crbug.com/1130712")
+    @Restriction({Restriction.RESTRICTION_TYPE_INTERNET})
     public void testTranslateCompactInfoBarReopenOnTarget() throws TimeoutException {
-        mActivityTestRule.loadUrl(mTestServer.getURL(TRANSLATE_PAGE));
-        mListener.addInfoBarAnimationFinished("InfoBar not opened.");
+        if (shouldSkipDueToNetworkService()) return;
+        mActivityTestRule.loadUrl(mActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE));
+
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/false);
 
         TranslateCompactInfoBar infoBar =
                 (TranslateCompactInfoBar) mInfoBarContainer.getInfoBarsForTesting().get(0);
-
-        // Only the source tab is selected.
-        Assert.assertTrue(infoBar.isSourceTabSelectedForTesting());
-        Assert.assertFalse(infoBar.isTargetTabSelectedForTesting());
-
         // Translate.
         TranslateUtil.clickTargetMenuItem(infoBar, "en");
         // Close bar.
@@ -164,11 +169,7 @@
         MenuUtils.invokeCustomMenuActionSync(InstrumentationRegistry.getInstrumentation(),
                 mActivityTestRule.getActivity(), R.id.translate_id);
 
-        infoBar = (TranslateCompactInfoBar) mInfoBarContainer.getInfoBarsForTesting().get(0);
-
-        // Only the target tab is selected.
-        Assert.assertFalse(infoBar.isSourceTabSelectedForTesting());
-        Assert.assertTrue(infoBar.isTargetTabSelectedForTesting());
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/true);
     }
 
     /**
@@ -177,25 +178,19 @@
     @Test
     @MediumTest
     @Feature({"Browser", "Main"})
-    @Restriction(ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES)
-    @DisabledTest(message = "https://crbug.com/1130712")
+    @Restriction({Restriction.RESTRICTION_TYPE_INTERNET})
     public void testStartTranslateOnManualInitiation() throws TimeoutException {
+        if (shouldSkipDueToNetworkService()) return;
         // Load a page that won't trigger the translate recommendation.
-        mActivityTestRule.loadUrl(mTestServer.getURL(NON_TRANSLATE_PAGE));
+        mActivityTestRule.loadUrl(mActivityTestRule.getTestServer().getURL(NON_TRANSLATE_PAGE));
 
         Assert.assertTrue(mInfoBarContainer.getInfoBarsForTesting().isEmpty());
 
         // Invoke bar by clicking the manual translate button.
         MenuUtils.invokeCustomMenuActionSync(InstrumentationRegistry.getInstrumentation(),
                 mActivityTestRule.getActivity(), R.id.translate_id);
-        mListener.addInfoBarAnimationFinished("InfoBar not opened.");
 
-        TranslateCompactInfoBar infoBar =
-                (TranslateCompactInfoBar) mInfoBarContainer.getInfoBarsForTesting().get(0);
-
-        // Only the target tab is selected.
-        Assert.assertFalse(infoBar.isSourceTabSelectedForTesting());
-        Assert.assertTrue(infoBar.isTargetTabSelectedForTesting());
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/true);
     }
 
     /**
@@ -204,32 +199,22 @@
     @Test
     @MediumTest
     @Feature({"Browser", "Main"})
-    @Restriction(ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES)
-    @DisabledTest(message = "https://crbug.com/1130712")
+    @Restriction({Restriction.RESTRICTION_TYPE_INTERNET})
     public void testManualInitiationWithBarOpen() throws TimeoutException {
-        mActivityTestRule.loadUrl(mTestServer.getURL(TRANSLATE_PAGE));
-        mListener.addInfoBarAnimationFinished("InfoBar not opened.");
+        if (shouldSkipDueToNetworkService()) return;
+        mActivityTestRule.loadUrl(mActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE));
 
-        TranslateCompactInfoBar infoBar =
-                (TranslateCompactInfoBar) mInfoBarContainer.getInfoBarsForTesting().get(0);
-
-        // Only the source tab is selected.
-        Assert.assertTrue(infoBar.isSourceTabSelectedForTesting());
-        Assert.assertFalse(infoBar.isTargetTabSelectedForTesting());
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/false);
 
         MenuUtils.invokeCustomMenuActionSync(InstrumentationRegistry.getInstrumentation(),
                 mActivityTestRule.getActivity(), R.id.translate_id);
 
-        // Only the target tab is selected.
-        Assert.assertFalse(infoBar.isSourceTabSelectedForTesting());
-        Assert.assertTrue(infoBar.isTargetTabSelectedForTesting());
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/true);
 
         // Verify that hitting "Translate..." again doesn't revert the translation.
         MenuUtils.invokeCustomMenuActionSync(InstrumentationRegistry.getInstrumentation(),
                 mActivityTestRule.getActivity(), R.id.translate_id);
 
-        // Only the target tab is selected.
-        Assert.assertFalse(infoBar.isSourceTabSelectedForTesting());
-        Assert.assertTrue(infoBar.isTargetTabSelectedForTesting());
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/true);
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateIntentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateIntentTest.java
index edf37afe..e1dedb09 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateIntentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateIntentTest.java
@@ -16,26 +16,22 @@
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
-import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import org.chromium.base.ContextUtils;
-import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.DisabledTest;
+import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.infobar.InfoBarContainer;
-import org.chromium.chrome.browser.infobar.TranslateCompactInfoBar;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
-import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule;
-import org.chromium.chrome.test.util.InfoBarTestAnimationListener;
+import org.chromium.chrome.test.util.TranslateUtil;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.content_public.browser.test.util.Criteria;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
@@ -50,58 +46,36 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-@Batch(Batch.PER_CLASS)
 public class TranslateIntentTest {
-    @ClassRule
-    public static final ChromeTabbedActivityTestRule sActivityTestRule =
-            new ChromeTabbedActivityTestRule();
     @Rule
-    public final BlankCTATabInitialStateRule mInitialStateRule =
-            new BlankCTATabInitialStateRule(sActivityTestRule, false);
+    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
 
     private static final String TRANSLATE_PAGE = "/chrome/test/data/translate/fr_test.html";
     private static final String NON_TRANSLATE_PAGE =
             "/chrome/test/data/translate/english_page.html";
 
     private InfoBarContainer mInfoBarContainer;
-    private InfoBarTestAnimationListener mListener;
 
     /**
      * Wait until the activity tab is translatable. This is useful in cases where we can't wait on
      * the infobar.
      */
     private void waitUntilTranslatable() {
-        CriteriaHelper.pollInstrumentationThread(() -> {
-            Tab tab = sActivityTestRule.getActivity().getActivityTab();
+        CriteriaHelper.pollUiThread(() -> {
+            Tab tab = mActivityTestRule.getActivity().getActivityTab();
             Criteria.checkThat(tab, Matchers.notNullValue());
-            boolean canManuallyTranslate = false;
-            try {
-                canManuallyTranslate = TestThreadUtils.runOnUiThreadBlocking(
-                        () -> TranslateBridge.canManuallyTranslate(tab));
-            } catch (ExecutionException e) {
-                e.printStackTrace();
-                canManuallyTranslate = false;
-            }
-            Criteria.checkThat(canManuallyTranslate, Matchers.is(true));
+            Criteria.checkThat(TranslateBridge.canManuallyTranslate(tab), Matchers.is(true));
         });
     }
 
     /**
-     * Wait until the given translate infobar is in the given state.
+     * Returns true if a test that requires internet access should be skipped due to an
+     * out-of-process NetworkService. When the NetworkService is run out-of-process, a fake DNS
+     * resolver is used that will fail to resolve any non-local names. crbug.com/1134812 is tracking
+     * the changes to make the translate service mockable and remove the internet requirement.
      */
-    private void waitForTranslateInfoBarState(boolean expectTranslated) {
-        TranslateCompactInfoBar infoBar =
-                (TranslateCompactInfoBar) mInfoBarContainer.getInfoBarsForTesting().get(0);
-
-        CriteriaHelper.pollInstrumentationThread(() -> {
-            if (expectTranslated) {
-                return !infoBar.isSourceTabSelectedForTesting()
-                        && infoBar.isTargetTabSelectedForTesting();
-            } else {
-                return infoBar.isSourceTabSelectedForTesting()
-                        && !infoBar.isTargetTabSelectedForTesting();
-            }
-        });
+    private boolean shouldSkipDueToNetworkService() {
+        return !ChromeFeatureList.isEnabled("NetworkServiceInProcess");
     }
 
     /**
@@ -118,86 +92,84 @@
         }
         IntentHandler.addTrustedIntentExtras(intent);
         TestThreadUtils.runOnUiThreadBlocking(
-                () -> sActivityTestRule.getActivity().onNewIntent(intent));
+                () -> mActivityTestRule.getActivity().onNewIntent(intent));
     }
 
     @Before
     public void setUp() {
-        mInfoBarContainer = sActivityTestRule.getInfoBarContainer();
-        mListener = new InfoBarTestAnimationListener();
-        mInfoBarContainer.addAnimationListener(mListener);
+        mActivityTestRule.startMainActivityOnBlankPage();
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> TranslateBridge.setIgnoreMissingKeyForTesting(true));
+        mInfoBarContainer = mActivityTestRule.getInfoBarContainer();
     }
 
     @After
     public void tearDown() {
-        mInfoBarContainer.removeAnimationListener(mListener);
     }
 
     @Test
     @MediumTest
-    @DisabledTest(message = "https://crbug.com/1127786 and https://crbug.com/1135682")
+    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
     @Features.DisableFeatures({ChromeFeatureList.TRANSLATE_INTENT})
-    public void
-    testTranslateIntentDisabled() throws TimeoutException {
-        final String url = sActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE);
+    public void testTranslateIntentDisabled() throws TimeoutException {
+        if (shouldSkipDueToNetworkService()) return;
+        final String url = mActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE);
         // Load a page that triggers the translate recommendation.
-        sActivityTestRule.loadUrl(url);
-        mListener.addInfoBarAnimationFinished("InfoBar not opened.");
-        waitForTranslateInfoBarState(false);
+        mActivityTestRule.loadUrl(url);
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/false);
 
         sendTranslateIntent(url, null);
 
         // No translation occurs.
-        waitForTranslateInfoBarState(false);
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/false);
     }
 
     @Test
     @MediumTest
-    @DisabledTest(message = "https://crbug.com/1127786 and https://crbug.com/1135682")
+    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
     @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT})
-    public void
-    testTranslateIntentOnTranslatePage() throws TimeoutException {
-        final String url = sActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE);
+    public void testTranslateIntentOnTranslatePage() throws TimeoutException {
+        if (shouldSkipDueToNetworkService()) return;
+        final String url = mActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE);
         // Load a page that triggers the translate recommendation.
-        sActivityTestRule.loadUrl(url);
-        mListener.addInfoBarAnimationFinished("InfoBar not opened.");
-        waitForTranslateInfoBarState(false);
+        mActivityTestRule.loadUrl(url);
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/false);
 
         sendTranslateIntent(url, null);
 
         // Only the target tab is selected.
-        waitForTranslateInfoBarState(true);
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/true);
     }
 
     @Test
     @MediumTest
-    @DisabledTest(message = "https://crbug.com/1127786 and https://crbug.com/1135682")
+    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
     @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT})
-    public void
-    testTranslateIntentOnNonTranslatePage() throws TimeoutException {
-        final String url = sActivityTestRule.getTestServer().getURL(NON_TRANSLATE_PAGE);
+    public void testTranslateIntentOnNonTranslatePage() throws TimeoutException {
+        if (shouldSkipDueToNetworkService()) return;
+        final String url = mActivityTestRule.getTestServer().getURL(NON_TRANSLATE_PAGE);
         // Load a page that doesn't trigger the translate recommendation.
-        sActivityTestRule.loadUrl(url);
+        mActivityTestRule.loadUrl(url);
 
         waitUntilTranslatable();
         Assert.assertTrue(mInfoBarContainer.getInfoBarsForTesting().isEmpty());
 
         sendTranslateIntent(url, null);
-        mListener.addInfoBarAnimationFinished("InfoBar not opened.");
 
         // Only the target tab is selected.
-        waitForTranslateInfoBarState(true);
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/true);
     }
 
     @Test
     @MediumTest
-    @DisabledTest(message = "https://crbug.com/1127786 and https://crbug.com/1135682")
+    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
     @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT})
-    public void
-    testTranslateIntentWithTargetLanguage() throws TimeoutException, ExecutionException {
-        final String url = sActivityTestRule.getTestServer().getURL(NON_TRANSLATE_PAGE);
+    public void testTranslateIntentWithTargetLanguage()
+            throws TimeoutException, ExecutionException {
+        if (shouldSkipDueToNetworkService()) return;
+        final String url = mActivityTestRule.getTestServer().getURL(NON_TRANSLATE_PAGE);
         // Load a page that doesn't trigger the translate recommendation.
-        sActivityTestRule.loadUrl(url);
+        mActivityTestRule.loadUrl(url);
 
         waitUntilTranslatable();
         Assert.assertTrue(mInfoBarContainer.getInfoBarsForTesting().isEmpty());
@@ -207,10 +179,9 @@
         Assert.assertFalse(acceptCodes.contains("de"));
 
         sendTranslateIntent(url, "de");
-        mListener.addInfoBarAnimationFinished("InfoBar not opened.");
 
         // Only the target tab is selected.
-        waitForTranslateInfoBarState(true);
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/true);
 
         // Verify that German has been added to the user's accept languages.
         acceptCodes =
@@ -220,13 +191,13 @@
 
     @Test
     @MediumTest
-    @DisabledTest(message = "https://crbug.com/1127786 and https://crbug.com/1135682")
+    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
     @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT})
-    public void
-    testTranslateIntentWithUnsupportedTargetLanguage() throws TimeoutException {
-        final String url = sActivityTestRule.getTestServer().getURL(NON_TRANSLATE_PAGE);
+    public void testTranslateIntentWithUnsupportedTargetLanguage() throws TimeoutException {
+        if (shouldSkipDueToNetworkService()) return;
+        final String url = mActivityTestRule.getTestServer().getURL(NON_TRANSLATE_PAGE);
         // Load a page that doesn't trigger the translate recommendation.
-        sActivityTestRule.loadUrl(url);
+        mActivityTestRule.loadUrl(url);
 
         waitUntilTranslatable();
         Assert.assertTrue(mInfoBarContainer.getInfoBarsForTesting().isEmpty());
@@ -238,97 +209,96 @@
 
     @Test
     @MediumTest
-    @DisabledTest(message = "https://crbug.com/1127786 and https://crbug.com/1135682")
+    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
     @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT})
-    public void
-    testTranslateIntentOnIncognito() throws TimeoutException {
-        final String url = sActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE);
+    public void testTranslateIntentOnIncognito() throws TimeoutException {
+        if (shouldSkipDueToNetworkService()) return;
+        final String url = mActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE);
         // Load a page that triggers the translate recommendation.
-        sActivityTestRule.loadUrlInNewTab(url, /*incognito=*/true);
+        mActivityTestRule.loadUrlInNewTab(url, /*incognito=*/true);
         // A new tab is opened for this test so we need to get the new container.
-        mInfoBarContainer = sActivityTestRule.getInfoBarContainer();
-        InfoBarTestAnimationListener mListener = new InfoBarTestAnimationListener();
-        mInfoBarContainer.addAnimationListener(mListener);
-        mListener.addInfoBarAnimationFinished("InfoBar not opened.");
-        waitForTranslateInfoBarState(false);
+        mInfoBarContainer = mActivityTestRule.getInfoBarContainer();
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/false);
 
         sendTranslateIntent(url, null);
 
         // No translation should happen.
-        waitForTranslateInfoBarState(false);
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/false);
+
+        // We opened a new tab for this test. Ensure that it's closed.
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { mActivityTestRule.getActivity().getTabModelSelector().closeAllTabs(); });
     }
 
     @Test
     @MediumTest
-    @DisabledTest(message = "https://crbug.com/1127786 and https://crbug.com/1135682")
+    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
     @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT})
-    public void
-    testTranslateIntentWithUrlMismatch() throws TimeoutException {
-        final String url = sActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE);
+    public void testTranslateIntentWithUrlMismatch() throws TimeoutException {
+        if (shouldSkipDueToNetworkService()) return;
+        final String url = mActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE);
         // Load a page that triggers the translate recommendation.
-        sActivityTestRule.loadUrl(url);
-        mListener.addInfoBarAnimationFinished("InfoBar not opened.");
-        waitForTranslateInfoBarState(false);
+        mActivityTestRule.loadUrl(url);
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/false);
 
         sendTranslateIntent("http://incorrect.com", null);
 
         // No translation should happen.
-        waitForTranslateInfoBarState(false);
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/false);
     }
 
     @Test
     @MediumTest
-    @DisabledTest(message = "https://crbug.com/1127786 and https://crbug.com/1135682")
+    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
     @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT})
-    public void
-    testTranslateIntentWithoutExpectedUrl() throws TimeoutException {
-        final String url = sActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE);
+    public void testTranslateIntentWithoutExpectedUrl() throws TimeoutException {
+        if (shouldSkipDueToNetworkService()) return;
+        final String url = mActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE);
         // Load a page that triggers the translate recommendation.
-        sActivityTestRule.loadUrl(url);
-        mListener.addInfoBarAnimationFinished("InfoBar not opened.");
-        waitForTranslateInfoBarState(false);
+        mActivityTestRule.loadUrl(url);
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/false);
 
         sendTranslateIntent(null, null);
 
         // No translation should happen.
-        waitForTranslateInfoBarState(false);
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/false);
     }
 
     @Test
     @MediumTest
-    @DisabledTest(message = "https://crbug.com/1127786 and https://crbug.com/1135682")
+    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
     @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT})
-    public void
-    testTranslateIntentVerifyComponent() throws TimeoutException {
-        final String url = sActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE);
+    public void testTranslateIntentVerifyComponent() throws TimeoutException {
+        if (shouldSkipDueToNetworkService()) return;
+        final String url = mActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE);
         // Load a page that triggers the translate recommendation.
-        sActivityTestRule.loadUrl(url);
-        mListener.addInfoBarAnimationFinished("InfoBar not opened.");
-        waitForTranslateInfoBarState(false);
+        mActivityTestRule.loadUrl(url);
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/false);
 
         Context context = ContextUtils.getApplicationContext();
 
         final Intent intent = new Intent(TranslateIntentHandler.ACTION_TRANSLATE_TAB);
         intent.setClassName(context, "com.google.android.apps.chrome.TranslateDispatcher");
         intent.putExtra(TranslateIntentHandler.EXTRA_EXPECTED_URL, url);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         // Send this via startActivity so we don't bypass LaunchIntentHandler.
-        TestThreadUtils.runOnUiThreadBlocking(() -> context.startActivity(intent));
+        mActivityTestRule.startActivityCompletely(intent);
+        mActivityTestRule.waitForActivityNativeInitializationComplete();
 
         // Only the target tab is selected.
-        waitForTranslateInfoBarState(true);
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/true);
     }
 
     @Test
     @MediumTest
-    @DisabledTest(message = "https://crbug.com/1127786 and https://crbug.com/1135682")
+    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
     @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT})
-    public void
-    testTranslateIntentIncorrectComponent() throws TimeoutException {
-        final String url = sActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE);
+    public void testTranslateIntentIncorrectComponent() throws TimeoutException {
+        if (shouldSkipDueToNetworkService()) return;
+        final String url = mActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE);
         // Load a page that triggers the translate recommendation.
-        sActivityTestRule.loadUrl(url);
-        mListener.addInfoBarAnimationFinished("InfoBar not opened.");
-        waitForTranslateInfoBarState(false);
+        mActivityTestRule.loadUrl(url);
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/false);
 
         Context context = ContextUtils.getApplicationContext();
 
@@ -336,10 +306,11 @@
         // Bypassing the TranslateDispatcher activity alias should reject the intent.
         intent.setClass(context, ChromeLauncherActivity.class);
         intent.putExtra(TranslateIntentHandler.EXTRA_EXPECTED_URL, url);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         TestThreadUtils.runOnUiThreadBlocking(() -> context.startActivity(intent));
 
         // No translation should happen.
-        waitForTranslateInfoBarState(false);
+        TranslateUtil.waitForTranslateInfoBarState(mInfoBarContainer, /*expectTranslated=*/false);
     }
 
     @Test
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineDetectorUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineDetectorUnitTest.java
index 1e710260..d9a5889 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineDetectorUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineDetectorUnitTest.java
@@ -26,7 +26,8 @@
 
 import org.chromium.base.ApplicationState;
 import org.chromium.base.test.BaseRobolectricTestRunner;
-import org.chromium.chrome.browser.offlinepages.indicator.ConnectivityDetector.ConnectionState;
+import org.chromium.chrome.browser.net.connectivitydetector.ConnectivityDetector;
+import org.chromium.chrome.browser.net.connectivitydetector.ConnectivityDetector.ConnectionState;
 
 /**
  * Unit tests for {@link OfflineDetector}.
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerV2UnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerV2UnitTest.java
index 8f576c6..3f453ac 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerV2UnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerV2UnitTest.java
@@ -34,7 +34,8 @@
 import org.chromium.base.supplier.Supplier;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.offlinepages.indicator.ConnectivityDetector.ConnectionState;
+import org.chromium.chrome.browser.net.connectivitydetector.ConnectivityDetector;
+import org.chromium.chrome.browser.net.connectivitydetector.ConnectivityDetector.ConnectionState;
 import org.chromium.chrome.browser.status_indicator.StatusIndicatorCoordinator;
 
 /**
diff --git a/chrome/android/modules/buildflags.gni b/chrome/android/modules/buildflags.gni
index c60310e..94c6293 100644
--- a/chrome/android/modules/buildflags.gni
+++ b/chrome/android/modules/buildflags.gni
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/android/channel.gni")
 import("//build/config/android/config.gni")
 import("//build/config/compiler/compiler.gni")
 import("//device/vr/buildflags/buildflags.gni")
@@ -10,7 +11,10 @@
   # Whether //chrome code and resources are in a DFM for Monochrome and
   # Trichrome bundles. This module will also include code and resources from all
   # other DFMs.
-  enable_chrome_module = false
+  # TODO(crbug.com/1126301): The binary size tools need to be updated to include
+  # DFM code before this can be enabled on stable.
+  enable_chrome_module =
+      android_channel == "default" || android_channel == "canary"
 }
 
 # If true, lld is used to partition feature code into separate libraries, which
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 1dd59f35..6a759cf2 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5645,16 +5645,16 @@
       <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 the shopping tasks module.">
+      <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 the shopping tasks module.">
+      <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 the shopping tasks module.">
+      <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>
-      <message name="IDS_NTP_MODULES_SHOPPING_TASKS_INFO_CLOSE" desc="Text shown on close button of the shopping tasks module.">
+      <message name="IDS_NTP_MODULES_SHOPPING_TASKS_INFO_CLOSE" desc="Text shown on close button of a task module.">
         Close
       </message>
       <!-- Extensions NTP Middle Slot Promo -->
diff --git a/chrome/app/printing_strings.grdp b/chrome/app/printing_strings.grdp
index 326292b..d6386420 100644
--- a/chrome/app/printing_strings.grdp
+++ b/chrome/app/printing_strings.grdp
@@ -16,6 +16,9 @@
     <message name="IDS_PRINT_PREVIEW_TITLE" desc="Fallback title for print preview page.">
       Print
     </message>
+    <message name="IDS_PRINT_PREVIEW_DESCRIPTION" desc="Accessibility text: title/description of the Print Preview dialog Web Contents, read by screenreaders.">
+      Print preview dialog
+    </message>
     <message name="IDS_PRINT_PREVIEW_LOADING" desc="Message to display while the print preview is still loading.">
       Loading preview
     </message>
diff --git a/chrome/app/printing_strings_grdp/IDS_PRINT_PREVIEW_DESCRIPTION.png.sha1 b/chrome/app/printing_strings_grdp/IDS_PRINT_PREVIEW_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..5035a9b
--- /dev/null
+++ b/chrome/app/printing_strings_grdp/IDS_PRINT_PREVIEW_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+4cebd4f475de4a4c1bbcd7c815aebe5efd2a204e
\ No newline at end of file
diff --git a/chrome/app/resources/chromium_strings_bn.xtb b/chrome/app/resources/chromium_strings_bn.xtb
index 07409c9..7ad3053 100644
--- a/chrome/app/resources/chromium_strings_bn.xtb
+++ b/chrome/app/resources/chromium_strings_bn.xtb
@@ -181,6 +181,7 @@
 <translation id="6863361426438995919">Google Pay (Chromium এ কপি করা হয়েছে)</translation>
 <translation id="6893813176749746474"> Chromium আপডেট করা হয়েছে৷ কিন্তু আপনি এটি অন্ততঃপক্ষে 30 দিন ব্যবহার করতে পারবেন না৷</translation>
 <translation id="6964305034639999644">Chromium ছদ্মবেশী উইন্ডোতে লিঙ্কটি খুলুন</translation>
+<translation id="6978145336957848883">দুর্বল পাসওয়ার্ড সহজেই অনুমান করা যায়। Chromium-কে <ph name="BEGIN_LINK" />আপনার জন্য শক্তিশালী পাসওয়ার্ড তৈরি করার ও সেটি মনে রাখার<ph name="END_LINK" /> অনুমতি দিন।</translation>
 <translation id="6990124437352146030">এই সাইটটির জন্য Chromium কে আপনার মাইক্রোফোনে অ্যাক্সেস দিতে হবে</translation>
 <translation id="701244094609242530">Chromium আপনার এক্সটেনশনগুলি চেক করে দেখতে পারছে না। পরে আবার চেষ্টা করুন।</translation>
 <translation id="7028347026395185822">{NUM_HOURS,plural, =1{Chromium আপনার কম্পিউটারে কোনও পরিচিত ক্ষতিকারক সফ্টওয়্যার খুঁজে পায়নি। শেষবার চেক করা হয়েছে: ১ ঘণ্টা আগে।}one{Chromium আপনার কম্পিউটারে কোনও পরিচিত ক্ষতিকারক সফ্টওয়্যার খুঁজে পায়নি। শেষবার চেক করা হয়েছে: {NUM_HOURS} ঘণ্টা আগে।}other{Chromium আপনার কম্পিউটারে কোনও পরিচিত ক্ষতিকারক সফ্টওয়্যার খুঁজে পায়নি। শেষবার চেক করা হয়েছে: {NUM_HOURS} ঘণ্টা আগে।}}</translation>
diff --git a/chrome/app/resources/chromium_strings_gu.xtb b/chrome/app/resources/chromium_strings_gu.xtb
index 69932e43..c658202b 100644
--- a/chrome/app/resources/chromium_strings_gu.xtb
+++ b/chrome/app/resources/chromium_strings_gu.xtb
@@ -11,6 +11,7 @@
 <translation id="1131805035311359397">ડેટા ઉલ્લંઘન અને અન્ય સુરક્ષાની સમસ્યાથી તમારા પાસવર્ડ સુરક્ષિત છે કે નહીં તે ચેક કરવા માટે, <ph name="BEGIN_LINK" />Chromeiumમાં સાઇન ઇન કરો<ph name="END_LINK" />.</translation>
 <translation id="1185134272377778587">Chromium વિશે</translation>
 <translation id="1315551408014407711">તમારી નવી Chromium પ્રોફાઇલ સેટઅપ કરો</translation>
+<translation id="1357932062193643861">જ્યારે Chromium ખુલ્લું હોય ત્યારે પૂછો</translation>
 <translation id="1396446129537741364">Chromium પાસવર્ડ્સ બતાવવાનો પ્રયાસ કરી રહ્યું છે.</translation>
 <translation id="1414495520565016063">તમે Chromium માં સાઇન ઇન કર્યું છે!</translation>
 <translation id="151962892725702025">Chromium OS તમારા ડેટાને સિંક કરી શક્યું નથી, કારણ કે તમારા ડોમેન માટે સિંક ઉપલબ્ધ નથી.</translation>
diff --git a/chrome/app/resources/chromium_strings_iw.xtb b/chrome/app/resources/chromium_strings_iw.xtb
index 31f9526..b05afa1 100644
--- a/chrome/app/resources/chromium_strings_iw.xtb
+++ b/chrome/app/resources/chromium_strings_iw.xtb
@@ -69,7 +69,7 @@
 <translation id="331951419404882060">‏מערכת ההפעלה של Chromium לא הצליחה לסנכרן את הנתונים שלך עקב שגיאה בתהליך הכניסה.</translation>
 <translation id="347328004046849135">‏אם מערכת Chromium תזהה שנכנסת עם סיסמה שנחשפה, היא תתריע לך על כך</translation>
 <translation id="3474745554856756813">‏פעולה זו תמחק <ph name="ITEMS_COUNT" /> פריטים מהמכשיר. כדי לשחזר את הנתונים מאוחר יותר, יש להיכנס אל Chromium עם <ph name="USER_EMAIL" />.</translation>
-<translation id="3509308970982693815">‏סגור את כל חלונות Chromium ונסה שוב.</translation>
+<translation id="3509308970982693815">‏יש לסגור את כל חלונות Chromium ולנסות שוב.</translation>
 <translation id="3527440529060401414">‏Chromium יכול לבדוק אם יש תוכנות מזיקות במחשב שלך</translation>
 <translation id="3575459661164320785">‏יש במחשב שלך תוכנה מזיקה. Chromium יכול להסיר אותה, לשחזר את ההגדרות שלך ולהשבית תוספים כדי שהדפדפן יחזור שוב לפעולה רגילה.</translation>
 <translation id="3639635944603682591">‏נתוני הגלישה של האדם הזה יימחקו מהמכשיר. כדי לשחזר את הנתונים, יש להיכנס ל-Chromium בתור <ph name="USER_EMAIL" />.</translation>
@@ -82,7 +82,7 @@
 <translation id="378917192836375108">‏Chromium מאפשר לך ללחוץ על מספר טלפון באינטרנט ולהתקשר אליו באמצעות Skype!</translation>
 <translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
 <translation id="388648406173476553">‏התאמה אישית וניהול של Chromium נחוצה פעולה שלך - יש ללחוץ לקבלת פרטים נוספים.</translation>
-<translation id="3889543394854987837">‏לחץ על השם שלך כדי לפתוח את Chromium ולהתחיל לגלוש.</translation>
+<translation id="3889543394854987837">‏יש ללחוץ על השם שלך כדי לפתוח את Chromium ולהתחיל לגלוש.</translation>
 <translation id="3945058413678539331">‏Chromium מנסה להעתיק את הסיסמאות. כדי לאפשר למערכת לעשות זאת, יש להזין את הסיסמה שלך ל-Windows.</translation>
 <translation id="4036079820698952681">‏דיווח על <ph name="BEGIN_LINK" />ההגדרות הנוכחיות<ph name="END_LINK" /> יעזור לשפר את Chromium</translation>
 <translation id="4050175100176540509">הגרסה החדשה כוללת שיפורי בטיחות חשובים ותכונות חדשות.</translation>
@@ -187,13 +187,13 @@
 <translation id="701244094609242530">‏Chromium לא יכול לבדוק את התוספים שלך. כדאי לנסות שוב מאוחר יותר.</translation>
 <translation id="7028347026395185822">{NUM_HOURS,plural, =1{‏Chromium לא גילה תוכנות מזיקות ידועות במחשב שלך. בדיקה אחרונה: לפני שעה אחת.}two{‏Chromium לא גילה תוכנות מזיקות ידועות במחשב שלך. בדיקה אחרונה: לפני שעתיים ({NUM_HOURS}).}many{‏Chromium לא גילה תוכנות מזיקות ידועות במחשב שלך. בדיקה אחרונה: לפני {NUM_HOURS} שעות.}other{‏Chromium לא גילה תוכנות מזיקות ידועות במחשב שלך. בדיקה אחרונה: לפני {NUM_HOURS} שעות.}}</translation>
 <translation id="705851970750939768">‏יש לעדכן את Chromium‏</translation>
-<translation id="7066436765290594559">‏מערכת ההפעלה של Chromium לא הצליחה לסנכרן את הנתונים שלך. עדכן את משפט הסיסמה לסנכרון.</translation>
+<translation id="7066436765290594559">‏מערכת ההפעלה של Chromium לא הצליחה לסנכרן את הנתונים שלך. יש לעדכן את משפט הסיסמה שלך לסנכרון.</translation>
 <translation id="7067091210845072982">‏אם אין לתמונה תיאור מועיל, Chromium ינסה לספק לך תיאור. כדי ליצור תיאורים, התמונות נשלחות אל Google.</translation>
 <translation id="7196312274710523067">‏לא ניתן היה להפעיל את Chromium. יש לנסות שוב.</translation>
 <translation id="7197677400338048821">‏Chromium לא יכול לבדוק את הסיסמאות שלך. יש לנסות שוב בעוד 24 שעות.</translation>
 <translation id="7205698830395646142">‏הסתרה בתפריט Chromium</translation>
 <translation id="7223968959479464213">‏מנהל המשימות - Chromium</translation>
-<translation id="731644333568559921">‏עדכן את &amp;מערכת ההפעלה של Chromium‏</translation>
+<translation id="731644333568559921">‏עדכון &amp;מערכת ההפעלה של Chromium‏</translation>
 <translation id="731795002583552498">‏מעדכן את Chromium‏</translation>
 <translation id="7318036098707714271">‏קובץ ההעדפות שלך פגום או לא חוקי. 
 
@@ -225,7 +225,7 @@
 <translation id="7857220146454061152">‏כדי לקבל עדכונים של Chromium בעתיד, נדרשת מערכת הפעלה OS X 10.11 ואילך. במחשב הזה מותקנת מערכת ההפעלה OS X 10.10.</translation>
 <translation id="7867198900892795913">‏עדכון Chromium לגרסה האחרונה לא הצליח, ולכן אין לך גישה אל תכונות חדשות ותיקוני אבטחה.</translation>
 <translation id="7898472181347242998">‏כדי לראות אם המכשיר שלך מעודכן, יש לעבור אל <ph name="LINK_BEGIN" />הגדרות Chromium OS<ph name="LINK_END" /></translation>
-<translation id="7937630085815544518">‏נכנסת ל-Chromium כ-<ph name="USER_EMAIL_ADDRESS" />. השתמש באותו חשבון כדי להיכנס שוב.</translation>
+<translation id="7937630085815544518">‏נכנסת ל-Chromium כ-<ph name="USER_EMAIL_ADDRESS" />. יש להשתמש באותו חשבון כדי להיכנס שוב.</translation>
 <translation id="7975919845073681630">‏זוהי התקנה משנית של Chromium, ולא ניתן להפוך אותו לדפדפן ברירת המחדל שלך.</translation>
 <translation id="7979877361127045932">‏הסתר בתפריט Chromium</translation>
 <translation id="8013436988911883588">‏אחרי מתן גישה ל-Chromium, אתרים יוכלו לבקש ממך גישה.</translation>
@@ -259,7 +259,7 @@
 <translation id="9019929317751753759">‏כדי לשפר את האבטחה של Chromium, השבתנו את התוסף הבא שאינו רשום ב-<ph name="IDS_EXTENSION_WEB_STORE_TITLE" /> וייתכן שנוסף ללא ידיעתך.</translation>
 <translation id="9089354809943900324">‏Chromium אינו מעודכן</translation>
 <translation id="9093206154853821181">{0,plural, =1{‏Chromium יופעל מחדש בעוד שעה}two{‏Chromium יופעל מחדש בעוד # שעות}many{‏Chromium יופעל מחדש בעוד # שעות}other{‏Chromium יופעל מחדש בעוד # שעות}}</translation>
-<translation id="91086099826398415">‏פתח את הקישור &amp;בכרטיסיית Chromium חדשה</translation>
+<translation id="91086099826398415">‏פתיחת הקישור &amp;בכרטיסיית Chromium חדשה</translation>
 <translation id="911206726377975832">למחוק גם את נתוני הגלישה שלך?</translation>
 <translation id="9158494823179993217">‏לפי הגדרת מנהל המערכת, Chromium יפתח דפדפן חלופי כדי לגשת אל <ph name="TARGET_URL_HOSTNAME" />.</translation>
 <translation id="9190841055450128916">‏Chromium ‏(mDNS-In)</translation>
diff --git a/chrome/app/resources/chromium_strings_or.xtb b/chrome/app/resources/chromium_strings_or.xtb
index a242bd0..b8c933f 100644
--- a/chrome/app/resources/chromium_strings_or.xtb
+++ b/chrome/app/resources/chromium_strings_or.xtb
@@ -11,6 +11,7 @@
 <translation id="1131805035311359397">ଆପଣଙ୍କ ପାସୱାର୍ଡଗୁଡ଼ିକ ଡାଟା ଚୋରି ଏବଂ ଅନ୍ୟ ସୁରକ୍ଷା ସମସ୍ୟାଗୁଡ଼ିକରୁ ସୁରକ୍ଷିତ ଅଛି ନା ନାହିଁ ତାହା ଯାଞ୍ଚ କରିବାକୁ, <ph name="BEGIN_LINK" />Chromiumରେ ସାଇନ୍ ଇନ୍ କରନ୍ତୁ<ph name="END_LINK" />।</translation>
 <translation id="1185134272377778587">Chromium ବିଷୟରେ</translation>
 <translation id="1315551408014407711">ଆପଣଙ୍କର ନୂଆ Chromium ପ୍ରୋଫାଇଲ୍ ସେଟ୍ ଅପ୍ କରନ୍ତୁ</translation>
+<translation id="1357932062193643861">Chromium ଖୋଲିଲେ ପଚାରନ୍ତୁ</translation>
 <translation id="1396446129537741364">ପାସ୍‌ୱର୍ଡଗୁଡ଼ିକ ଦେଖାଇବାକୁ Chromium ଚେଷ୍ଟା କରୁଛି।</translation>
 <translation id="1414495520565016063">ଆପଣ Chromium‍ରେ ସାଇନ୍-ଇନ୍ କରିଛନ୍ତି!</translation>
 <translation id="151962892725702025">Chromium OS ଆପଣଙ୍କର ଡାଟାକୁ ସିଙ୍କ୍ କରିପାରିବ ନାହିଁ, କାରଣ ଆପଣଙ୍କ ଡୋମେନ୍ ପାଇଁ ସିଙ୍କ୍ ଉପଲବ୍ଧ ନାହିଁ।</translation>
diff --git a/chrome/app/resources/chromium_strings_pa.xtb b/chrome/app/resources/chromium_strings_pa.xtb
index 9532b8dd..75f7910 100644
--- a/chrome/app/resources/chromium_strings_pa.xtb
+++ b/chrome/app/resources/chromium_strings_pa.xtb
@@ -53,7 +53,7 @@
 <translation id="2910007522516064972">&amp;Chromium ਬਾਰੇ</translation>
 <translation id="2977470724722393594">Chromium ਅੱਪ ਟੂ ਡੇਟ ਹੈ</translation>
 <translation id="2983934633046890458">Chromium ਪਾਸਵਰਡਾਂ ਦਾ ਸੰਪਾਦਨ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰ ਰਿਹਾ ਹੈ।</translation>
-<translation id="3031887101543416445">{NUM_DAYS,plural, =1{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: 1 ਦਿਨ ਪਹਿਲਾਂ।}one{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_DAYS} ਦਿਨ ਪਹਿਲਾਂ।}other{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_DAYS} ਦਿਨ ਪਹਿਲਾਂ।}}</translation>
+<translation id="3031887101543416445">{NUM_DAYS,plural, =1{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: 1 ਦਿਨ ਪਹਿਲਾਂ।}one{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_DAYS} ਦਿਨ ਪਹਿਲਾਂ।}other{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_DAYS} ਦਿਨ ਪਹਿਲਾਂ।}}</translation>
 <translation id="3032706164202344641">Chromium ਤੁਹਾਡੇ ਪਾਸਵਰਡਾਂ ਦੀ ਜਾਂਚ ਨਹੀਂ ਕਰ ਸਕਦਾ। ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</translation>
 <translation id="3032787606318309379">Chromium ਵਿੱਚ ਜੋੜ ਰਿਹਾ ਹੈ...</translation>
 <translation id="3068515742935458733">Chromium ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਵਿੱਚ ਮਦਦ ਕਰਨ ਲਈ Google ਨੂੰ ਕ੍ਰੈਸ਼ ਰਿਪੋਰਟਾਂ ਅਤੇ <ph name="UMA_LINK" /> ਭੇਜੋ</translation>
@@ -89,21 +89,21 @@
 <translation id="3945058413678539331">Chromium ਪਾਸਵਰਡਾਂ ਨੂੰ ਕਾਪੀ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰ ਰਿਹਾ ਹੈ। ਇਹ ਕਰਨ ਦੇਣ ਲਈ ਆਪਣਾ ਵਿੰਡੋ ਪਾਸਵਰਡ ਟਾਈਪ ਕਰੋ।</translation>
 <translation id="4036079820698952681"><ph name="BEGIN_LINK" />ਵਰਤਮਾਨ ਸੈਟਿੰਗਾਂ<ph name="END_LINK" /> ਦੀ ਰਿਪੋਰਟ ਕਰਕੇ Chromium ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਵਿੱਚ ਮਦਦ ਕਰੋ</translation>
 <translation id="4050175100176540509">ਮਹੱਤਵਪੂਰਣ ਸੁਰੱਖਿਆ ਸੁਧਾਰ ਅਤੇ ਨਵੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨਵੇਂ ਰੂਪ ਵਿੱਚ ਉਪਲਬਧ ਹਨ।</translation>
-<translation id="4136604564421273381">Chromium ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚੋਂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਹਟਾ ਰਿਹਾ ਹੈ...</translation>
+<translation id="4136604564421273381">Chromium ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਤੋਂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਹਟਾ ਰਿਹਾ ਹੈ...</translation>
 <translation id="419998258129752635"><ph name="PAGE_TITLE" /> - ਨੈੱਟਵਰਕ ਸਾਈਨ-ਇਨ - Chromium</translation>
 <translation id="421369550622382712">Chromium ਲਈ ਸ਼ਾਨਦਾਰ ਐਪਸ, ਗੇਮਸ, ਐਕਸਟੈਂਸ਼ਨਾਂ ਅਤੇ ਵਿਸ਼ੇ ਖੋਜੋ।</translation>
 <translation id="4216212958613226427">ਇਸ ਭਾਸ਼ਾ ਦੀ ਵਰਤੋਂ Chromium UI ਦਿਖਾਉਣ ਲਈ ਕੀਤੀ ਜਾਂਦੀ ਹੈ</translation>
 <translation id="4230135487732243613">ਕੀ ਤੁਹਾਡਾ Chromium ਡਾਟਾ ਇਸ ਖਾਤੇ ਨਾਲ ਲਿੰਕ ਕਰਨਾ ਹੈ?</translation>
 <translation id="4271805377592243930">Chromium ਬਾਰੇ ਮਦਦ ਪ੍ਰਾਪਤ ਕਰੋ</translation>
 <translation id="4285930937574705105">ਅਚਨਚੇਤ ਗੜਬੜ ਕਾਰਨ ਸਥਾਪਨਾ ਅਸਫਲ ਹੋ ਗਈ। ਜੇਕਰ ਇਸ ਵੇਲੇ Chromium ਚੱਲ ਰਿਹਾ ਹੈ, ਤਾਂ ਕਿਰਪਾ ਕਰਕੇ ਇਸਨੂੰ ਬੰਦ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</translation>
-<translation id="4352041330999353637">Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: ਕੱਲ੍ਹ।</translation>
+<translation id="4352041330999353637">Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: ਬੀਤੇ ਕੱਲ੍ਹ।</translation>
 <translation id="4407044323746248786">ਕੀ ਫਿਰ ਵੀ Chromium ਤੋਂ ਬਾਹਰ ਜਾਣਾ ਹੈ?</translation>
 <translation id="4415566066719264597">Chromium ਨੂੰ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲਣ ਦਿਓ</translation>
 <translation id="4423735387467980091">Google Chrome ਨੂੰ ਵਿਉਂਤਬੱਧ ਕਰਕੇ ਕੰਟਰੋਲ ਕਰੋ।</translation>
 <translation id="4544142686420020088">Chromium ਅੱਪਡੇਟ ਨਹੀਂ ਹੋਇਆ, ਕੋਈ ਗੜਬੜ ਹੋ ਗਈ। <ph name="BEGIN_LINK" />Chromium ਅੱਪਡੇਟ ਦੀਆਂ ਸਮੱਸਿਆਵਾਂ ਅਤੇ ਅਸਫਲ ਹੋਈਆਂ ਅੱਪਡੇਟਾਂ ਨੂੰ ਠੀਕ ਕਰੋ।<ph name="END_LINK" /></translation>
 <translation id="4567424176335768812">ਤੁਸੀਂ <ph name="USER_EMAIL_ADDRESS" /> ਦੇ ਤੌਰ 'ਤੇ ਸਾਈਨ-ਇਨ ਕੀਤਾ ਹੈ। ਹੁਣ ਤੁਸੀਂ ਆਪਣੇ ਸਾਰੇ ਸਾਈਨ-ਇਨ ਕੀਤੇ ਡੀਵਾਈਸਾਂ 'ਤੇ ਆਪਣੇ ਬੁੱਕਮਾਰਕਾਂ, ਇਤਿਹਾਸ ਅਤੇ ਹੋਰ ਸੈਟਿੰਗਾਂ ਤੱਕ ਪਹੁੰਚ ਪ੍ਰਾਪਤ ਕਰ ਸਕਦੇ ਹੋ।</translation>
 <translation id="459535195905078186">Chromium ਐਪਸ</translation>
-<translation id="4595492485953540730">{NUM_MINS,plural, =1{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: 1 ਮਿੰਟ ਪਹਿਲਾਂ।}one{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_MINS} ਮਿੰਟ ਪਹਿਲਾਂ।}other{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_MINS} ਮਿੰਟ ਪਹਿਲਾਂ।}}</translation>
+<translation id="4595492485953540730">{NUM_MINS,plural, =1{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: 1 ਮਿੰਟ ਪਹਿਲਾਂ।}one{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_MINS} ਮਿੰਟ ਪਹਿਲਾਂ।}other{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_MINS} ਮਿੰਟ ਪਹਿਲਾਂ।}}</translation>
 <translation id="4677944499843243528">ਇੰਜ ਜਾਪਦਾ ਹੈ ਕਿ ਪ੍ਰੋਫਾਈਲ ਨੂੰ ਕਿਸੇ ਹੋਰ ਕੰਪਿਊਟਰ <ph name="HOST_NAME" /> 'ਤੇ ਦੂਜੀ Chromium ਪ੍ਰਕਿਰਿਆ (<ph name="PROCESS_ID" />) ਵਿੱਚ ਵਰਤਿਆ ਜਾ ਰਿਹਾ ਹੈ। Chromium ਨੇ ਪ੍ਰੋਫਾਈਲ ਲਾਕ ਕਰ ਦਿੱਤੀ ਹੈ ਤਾਂ ਜੋ ਇਹ ਖਰਾਬ ਹੋਣ ਤੋਂ ਬੱਚ ਸਕੇ। ਜੇਕਰ ਤੁਹਾਨੂੰ ਪੱਕਾ ਪਤਾ ਹੈ ਕਿ ਕੋਈ ਹੋਰ ਪ੍ਰਕਿਰਿਆਵਾਂ ਇਹ ਪ੍ਰੋਫਾਈਲ ਨਹੀਂ ਵਰਤ ਰਹੀਆਂ, ਤਾਂ ਤੁਸੀਂ ਪ੍ਰੋਫਾਈਲ ਨੂੰ ਅਣਲਾਕ ਕਰ ਸਕਦੇ ਹੋ ਅਤੇ Chromium ਨੂੰ ਮੁੜ-ਲਾਂਚ ਕਰ ਸਕਦੇ ਹੋ।</translation>
 <translation id="469338717132742108">Chromium OS ਬਾਰੇ ਮਦਦ ਪ੍ਰਾਪਤ ਕਰੋ</translation>
 <translation id="4708774505295300557">ਕਿਸੇ ਵਿਅਕਤੀ ਨੇ ਪਹਿਲਾਂ ਹੀ <ph name="ACCOUNT_EMAIL_LAST" /> ਵਜੋਂ ਇਸ ਕੰਪਿਊਟਰ 'ਤੇ Chromium 'ਤੇ ਸਾਈਨ-ਇਨ ਕੀਤਾ ਹੋਇਆ ਹੈ। ਆਪਣੀ ਜਾਣਕਾਰੀ ਵੱਖਰੀ ਰੱਖਣ ਲਈ ਕਿਰਪਾ ਕਰਕੇ ਇੱਕ ਨਵਾਂ Chromium ਵਰਤੋਂਕਾਰ ਬਣਾਓ।</translation>
@@ -177,7 +177,7 @@
 ਸ਼ਾਇਦ ਕੁਝ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਉਪਲਬਧ ਨਾ ਹੋਣ। ਕਿਰਪਾ ਕਰਕੇ ਇੱਕ ਵੱਖ ਪ੍ਰੋਫਾਈਲ ਡਾਇਰੈਕਟਰੀ ਜਾਂ Chromium ਦਾ ਨਵਾਂ ਵਰਜਨ ਵਰਤੋ।</translation>
 <translation id="6734080038664603509">Chromium ਨੂੰ ਅੱਪਡੇਟ ਕਰੋ</translation>
 <translation id="6734291798041940871">Chromium ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਪਹਿਲਾਂ ਹੀ ਸਾਰੇ ਵਰਤੋਂਕਾਰਾਂ ਲਈ ਸਥਾਪਤ ਕੀਤਾ ਗਿਆ ਹੈ।</translation>
-<translation id="6737557815519435616">Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: ਕੁਝ ਸਮਾਂ ਪਹਿਲਾਂ।</translation>
+<translation id="6737557815519435616">Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: ਕੁਝ ਸਮਾਂ ਪਹਿਲਾਂ।</translation>
 <translation id="6762551859069255163">ਕੰਮਕਾਜੀ ਅਤੇ ਨਿੱਜੀ ਬ੍ਰਾਊਜ਼ਿੰਗ ਨੂੰ ਵੱਖ ਕਰਨ ਲਈ ਜਾਂ ਇਸ ਡੀਵਾਈਸ ਦੀ ਵਰਤੋਂ ਕਰਨ ਵਾਲੇ ਵੱਖ-ਵੱਖ ਲੋਕਾਂ ਲਈ Chromium ਵਿੱਚ ਵੱਖ-ਵੱਖ ਪ੍ਰੋਫਾਈਲ ਵਰਤੋ</translation>
 <translation id="6774082503108938489">ਤੁਹਾਡੇ ਮਾਂ-ਪਿਓ ਨੇ Chromium ਲਈ "ਸਾਈਟਾਂ, ਐਪਾਂ ਅਤੇ ਐਕਸਟੈਂਸ਼ਨਾਂ ਲਈ ਇਜਾਜ਼ਤਾਂ" ਨੂੰ ਬੰਦ ਕਰ ਦਿੱਤਾ ਹੈ। ਇਸ <ph name="EXTENSION_TYPE_PARAMETER" /> ਨੂੰ ਚਾਲੂ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ।</translation>
 <translation id="6847869444787758381">Chromium ਤੁਹਾਨੂੰ ਇਹ ਗੱਲ ਦੱਸਦਾ ਹੈ ਕਿ ਤੁਹਾਡੇ ਪਾਸਵਰਡਾਂ ਨਾਲ ਪਹਿਲਾਂ ਕਦੇ ਛੇੜਛਾੜ ਹੋਈ ਹੈ ਜਾਂ ਨਹੀਂ</translation>
@@ -188,7 +188,7 @@
 <translation id="6978145336957848883">ਕਮਜ਼ੋਰ ਪਾਸਵਰਡਾਂ ਦਾ ਅੰਦਾਜ਼ਾ ਲਗਾਉਣਾ ਆਸਾਨ ਹੁੰਦਾ ਹੈ। Chromium ਨੂੰ <ph name="BEGIN_LINK" />ਤੁਹਾਡੇ ਲਈ ਮਜ਼ਬੂਤ ਪਾਸਵਰਡ ਬਣਾਉਣ ਅਤੇ ਯਾਦ ਰੱਖਣ<ph name="END_LINK" /> ਦਿਓ।</translation>
 <translation id="6990124437352146030">Chromium ਨੂੰ ਇਸ ਸਾਈਟ ਵਾਸਤੇ ਤੁਹਾਡੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਲਈ ਇਜਾਜ਼ਤ ਦੀ ਲੋੜ ਹੈ</translation>
 <translation id="701244094609242530">Chromium ਤੁਹਾਡੀਆਂ ਐਕਸਟੈਂਸ਼ਨਾਂ ਦੀ ਜਾਂਚ ਨਹੀਂ ਕਰ ਸਕਦਾ। ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</translation>
-<translation id="7028347026395185822">{NUM_HOURS,plural, =1{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: 1 ਘੰਟਾ ਪਹਿਲਾਂ।}one{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_HOURS} ਘੰਟਾ ਪਹਿਲਾਂ।}other{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_HOURS} ਘੰਟੇ ਪਹਿਲਾਂ।}}</translation>
+<translation id="7028347026395185822">{NUM_HOURS,plural, =1{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: 1 ਘੰਟਾ ਪਹਿਲਾਂ।}one{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_HOURS} ਘੰਟਾ ਪਹਿਲਾਂ।}other{Chromium ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_HOURS} ਘੰਟੇ ਪਹਿਲਾਂ।}}</translation>
 <translation id="705851970750939768">Chromium ਨੂੰ ਅੱਪਡੇਟ ਕਰੋ</translation>
 <translation id="7066436765290594559">Chromium OS ਤੁਹਾਡਾ ਡਾਟਾ ਸਿੰਕ ਨਹੀਂ ਕਰ ਸਕਿਆ। ਕਿਰਪਾ ਕਰਕੇ ਆਪਣਾ ਸਿੰਕ ਪਾਸਫਰੇਜ਼ ਅੱਪਡੇਟ ਕਰੋ।</translation>
 <translation id="7067091210845072982">ਜੇ ਕਿਸੇ ਚਿੱਤਰ ਦਾ ਲਾਭਕਾਰੀ ਵਰਣਨ ਨਹੀਂ ਹੈ, ਤਾਂ Chromium ਤੁਹਾਡੇ ਲਈ ਇੱਕ ਵਰਣਨ ਮੁਹੱਈਆ ਕਰਵਾਉਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੇਗਾ। ਵਰਣਨ ਬਣਾਉਣ ਲਈ, ਚਿੱਤਰ Google ਨੂੰ ਭੇਜੇ ਜਾਂਦੇ ਹਨ।</translation>
diff --git a/chrome/app/resources/chromium_strings_te.xtb b/chrome/app/resources/chromium_strings_te.xtb
index 9be112a..a2f9e33e 100644
--- a/chrome/app/resources/chromium_strings_te.xtb
+++ b/chrome/app/resources/chromium_strings_te.xtb
@@ -9,6 +9,7 @@
 <translation id="1131805035311359397">డేటా ఉల్లంఘనల నుండి, ఇతర భద్రతా సమస్యల నుండి మీ పాస్‌వర్డ్‌లు సురక్షితంగా ఉన్నాయో లేదో చెక్ చేయడానికి, <ph name="BEGIN_LINK" />Chromiumకు సైన్ ఇన్ చేయండి<ph name="END_LINK" />.</translation>
 <translation id="1185134272377778587">Chromium గురించి</translation>
 <translation id="1315551408014407711">మీ కొత్త Chromium ప్రొఫైల్‍ను సెట్ అప్ చేయండి</translation>
+<translation id="1357932062193643861">Chromium తెరుచుకున్నప్పుడు అడగాలి</translation>
 <translation id="1396446129537741364">Chromium పాస్‌వర్డ్‌లను చూపడానికి ప్రయత్నిస్తోంది.</translation>
 <translation id="1414495520565016063">మీరు Chromiumకు సైన్ ఇన్ చేసారు!</translation>
 <translation id="151962892725702025">మీ డొమైన్ కోసం సింక్‌ అందుబాటులో లేనందున, Chromium OS, మీ డేటాను సింక్ చేయ‌లేక‌పోయింది.</translation>
diff --git a/chrome/app/resources/generated_resources_ar.xtb b/chrome/app/resources/generated_resources_ar.xtb
index 1397c77..8501a8a 100644
--- a/chrome/app/resources/generated_resources_ar.xtb
+++ b/chrome/app/resources/generated_resources_ar.xtb
@@ -942,7 +942,7 @@
 <translation id="2075959085554270910">تتيح لك تفعيل ميزة الضغط للنقر وميزة السحب بالنقر أو إيقافهما.</translation>
 <translation id="2076269580855484719">إخفاء هذا المكون الإضافي</translation>
 <translation id="2076672359661571384">متوسط (موصى به)</translation>
-<translation id="2077129598763517140">استخدام تسريع الأجهزة عند توفره</translation>
+<translation id="2077129598763517140">استخدام ميزة "تسريع الأجهزة" عند توفرها</translation>
 <translation id="2078019350989722914">التحذير قبل الإنهاء (<ph name="KEY_EQUIVALENT" />)</translation>
 <translation id="2079053412993822885">إذا حذفت إحدى شهاداتك، فلن تستطيع استخدامها لتعريف هويتك.</translation>
 <translation id="2079545284768500474">تراجع</translation>
diff --git a/chrome/app/resources/generated_resources_bn.xtb b/chrome/app/resources/generated_resources_bn.xtb
index 1931011..268289a 100644
--- a/chrome/app/resources/generated_resources_bn.xtb
+++ b/chrome/app/resources/generated_resources_bn.xtb
@@ -928,6 +928,7 @@
 <translation id="204914487372604757">শর্টকাট তৈরি করুন</translation>
 <translation id="2050339315714019657">প্রতিকৃতি</translation>
 <translation id="2053312383184521053">নিষ্ক্রিয় অবস্থার ডেটা</translation>
+<translation id="2054665754582400095">আপনার উপস্থিতি</translation>
 <translation id="2055585478631012616">যেকোনও খোলা ট্যাব ছাড়াও এই সব সাইটগুলি থেকে আপনি সাইন-আউট হয়ে যাবেন</translation>
 <translation id="205560151218727633">Google অ্যাসিস্ট্যান্ট লোগো</translation>
 <translation id="2058456167109518507">ডিভাইস শনাক্ত করা হয়েছে</translation>
@@ -1214,6 +1215,7 @@
 <translation id="2387052489799050037">হোম স্ক্রিনে যান</translation>
 <translation id="2387458720915042159">প্রক্সি কানেকশনের ধরণ</translation>
 <translation id="2390347491606624519">প্রক্সি সার্ভারে কানেক্ট করা যাচ্ছে না, আবার সাইন-ইন করুন</translation>
+<translation id="2390782873446084770">ওয়াই-ফাই সিঙ্ক</translation>
 <translation id="2391082728065870591">ফিডব্যাক রিপোর্ট পাঠান</translation>
 <translation id="2391419135980381625">মানক হরফ</translation>
 <translation id="2392163307141705938"><ph name="IDS_SHORT_PRODUCT_NAME" />-এর জন্য আপনার অভিভাবক যে সময়সীমা সেট করেছেন তা পার হয়ে গেছে।</translation>
@@ -1869,6 +1871,7 @@
 <translation id="3157931365184549694">পুনরুদ্ধার করুন</translation>
 <translation id="3158033540161634471">আপনার আঙ্গুলের ছাপ সেট-আপ করুন</translation>
 <translation id="3159493096109238499">বেজ</translation>
+<translation id="3159978855457658359">ডিভাইসের নাম এডিট করুন</translation>
 <translation id="3160842278951476457"><ph name="ISSUED_BY" /> [<ph name="ISSUED_TO" />] (হার্ডওয়্যার-সাহায্যপ্রাপ্ত)</translation>
 <translation id="3161522574479303604">সকল ভাষা</translation>
 <translation id="3162853326462195145">স্কুলের অ্যাকাউন্ট</translation>
@@ -3228,6 +3231,7 @@
 <translation id="4761104368405085019">আপনার মাইক্রোফোন ব্যবহার করুন</translation>
 <translation id="4762718786438001384">ডিভাইসের ডিস্কের স্থান আশংকাজনকভাবে কম</translation>
 <translation id="4763408175235639573">আপনি যখন এই পৃষ্ঠাটি দেখেছিলেন তখন নিম্নোক্ত কুকিগুলি সেট হয়েছিল</translation>
+<translation id="4764368918650455114">এটি নিশ্চিত করুন যেন উভয় ডিভাইস আনলক থাকে ও পরস্পরের কাছাকাছি থাকে। তার সাথে যেন ব্লুটুথও চালু করা থাকে। যদি আপনি কোনও Chromebook-এর সাথে শেয়ার করেন, তাহলে নিশ্চিত করে নিন সেই ডিভাইসে 'নিয়ারবাই শেয়ার' ফিচার যেন চালু করা থাকে (সময় বেছে নিয়ে 'স্ট্যাটাস এরিয়া' বিকল্প খুলুন, তারপরে 'নিয়ারবাই শেয়ার' ফিচার বেছে নিন)। <ph name="LINK_BEGIN" />আরও জানুন<ph name="LINK_END" /></translation>
 <translation id="4765582662863429759">Android Messages-কে আপনার ফোন থেকে Chromebook-এ টেক্সট রিলে করতে অনুমতি দেয়</translation>
 <translation id="476598255842811483">আপনার ডিভাইসে 'নিয়ারবাই শেয়ার' ফিচার চালু না করা পর্যন্ত কেউ আপনার ডিভাইস দেখতে পাবেন না</translation>
 <translation id="4768332406694066911">আপনার পরিচয় শনাক্ত করে এমন সংস্থাগুলি থেকে শংসাপত্র আপনার কাছে আছে</translation>
@@ -3390,6 +3394,7 @@
 <translation id="4960294539892203357"><ph name="WINDOW_TITLE" /> - <ph name="PROFILE_NAME" /></translation>
 <translation id="496185450405387901">এই অ্যাপটি আপনার অ্যাডমিনিস্ট্রেটর ইনস্টল করে দিয়েছেন।</translation>
 <translation id="4964455510556214366">সাজানোর ব্যবস্থা</translation>
+<translation id="496446150016900060">আপনার ফোনের সাথে ওয়াই-ফাই নেটওয়ার্ক সিঙ্ক করুন</translation>
 <translation id="4965808351167763748">Hangouts Meet চালাতে আপনি এই ডিভাইস সেট-আপ করতে চান?</translation>
 <translation id="496888482094675990">Google ড্রাইভ, এক্সর্টানাল স্টোরেজ অথবা আপনার Chrome OS ডিভাইসে আপনি যে ফাইলগুলি সেভ করেছেন ফাইল অ্যাপ সেগুলিতে দ্রুত অ্যাক্সেস দেয়।</translation>
 <translation id="4971412780836297815">সম্পন্ন হলে খুলুন</translation>
@@ -3696,6 +3701,7 @@
 <translation id="5341980496415249280">অনুগ্রহ করে অপেক্ষা করুন, প্যাকিং করা হচ্ছে....</translation>
 <translation id="5342091991439452114">পিন অবশ্যই কমপক্ষে <ph name="MINIMUM" /> সংখ্যার হতে হবে</translation>
 <translation id="5344036115151554031">Linux-কে ফিরিয়ে আনা হচ্ছে</translation>
+<translation id="5345916423802287046">সাইন-ইন করলেই অ্যাপ চালু হয়ে যাবে</translation>
 <translation id="5350293332385664455">Google Assistant অ্যাপ বন্ধ করুন</translation>
 <translation id="535123479159372765">অন্য ডিভাইস থেকে টেক্সট কপি করা হয়েছে</translation>
 <translation id="5352033265844765294">Time Stamping</translation>
@@ -4006,6 +4012,7 @@
 <translation id="5704875434923668958">এতে সিঙ্ক হচ্ছে</translation>
 <translation id="5705005699929844214">সর্বদা অ্যাক্সেসিবিলিটি বিকল্পগুলি দেখান</translation>
 <translation id="5705882733397021510">ফিরে যান</translation>
+<translation id="5707117624115653804">এই সেটিং কাজ করে এমন অ্যাপ ও সাইটের জন্য ক্যাপশনের সাইজ এবং স্টাইল কাস্টমাইজ করুন</translation>
 <translation id="5707185214361380026">এর থেকে এক্সটেনশন লোড করা যায়নি:</translation>
 <translation id="5708171344853220004">Microsoft Principal Name</translation>
 <translation id="5709557627224531708">Chrome-কে আপনার ডিফল্ট ব্রাউজার হিসেবে সেট করুন</translation>
@@ -4169,6 +4176,7 @@
 <translation id="5904614460720589786">কনফিগার করার সময় সমস্যা হওয়ার জন্য <ph name="APP_NAME" /> সেট-আপ করা যায়নি। আপনার অ্যাডমিনের সাথে যোগাযোগ করুন। সমস্যার কোড: <ph name="ERROR_CODE" />।</translation>
 <translation id="5906655207909574370">প্রায় আপ-টু-ডেট হয়েছে! আপডেট শেষ করতে আপনার ডিভাইস আবার চালু করুন।</translation>
 <translation id="5906732635754427568">এই অ্যাপ্লিকেশান সংশ্লিষ্ট ডেটা এই ডিভাইস থেকে সরিয়ে ফেলা হবে।</translation>
+<translation id="5908474332780919512">সাইন-ইন করলেই অ্যাপ চালু হয়ে যাবে</translation>
 <translation id="5908695239556627796">মাউসের মাধ্যমে স্ক্রল করার স্পিড</translation>
 <translation id="5908769186679515905">সাইটগুলিকে Flash চালানোর বিষয়ে অবরুদ্ধ করুন</translation>
 <translation id="5910363049092958439">এই ভাবে ছবি সেভ করুন...</translation>
@@ -4709,6 +4717,7 @@
 <translation id="6532527800157340614">সাইন-ইন করা যাচ্ছে না, কারণ আপনার অ্যাক্সেস টোকেন পুনরুদ্ধার করা সম্ভব হয়নি। আপনার নেটওয়ার্কের কানেকশন চেক করে আবার চেষ্টা করে দেখুন।</translation>
 <translation id="6532663472409656417">এন্টারপ্রাইজ এনরোল করা হয়েছে</translation>
 <translation id="6535331821390304775">এই ধরনের লিঙ্ককে এর সাথে যুক্ত অ্যাপে <ph name="ORIGIN" />-কে সবসময় খোলার অনুমতি দিন</translation>
+<translation id="6537613839935722475">নামে অক্ষর, সংখ্যা ও হাইফেন (-) থাকতে পারে</translation>
 <translation id="6538635548667167211">বর্তমান ডেটা ব্যবহারের সেটিংয়ে, মোবাইল ডেটা ব্যবহার করেই শুধুমাত্র ডেটা ট্রান্সফার করা যাবে</translation>
 <translation id="654039047105555694"><ph name="BEGIN_BOLD" />দ্রষ্টব্য:<ph name="END_BOLD" /> আপনি যদি জানেন যে আপনি কি করছেন তাহলে সক্ষম করুন বা যদি আপনাকে এমনটি করতে বলা হয়ে থাকে, তাহলে মনে রাখবেন যে ডেটা সংগ্রহ কর্মক্ষমতাকে হ্রাস করতে পারে৷</translation>
 <translation id="6541638731489116978">আপনার মোশন সেন্সর ব্যবহার করা থেকে এই সাইটকে ব্লক করা হয়েছে।</translation>
@@ -4797,6 +4806,7 @@
 <translation id="6650234781371031356">এই ডিভাইসে এবং আপনার Google অ্যাকাউন্টে <ph name="WEBSITE" />-এর পাসওয়ার্ড সেভ করা আছে। আপনি কোনটা মুছে দিতে চান?</translation>
 <translation id="665061930738760572">&amp;নতুন উইন্ডোতে খুলুন</translation>
 <translation id="6651237644330755633">ওয়েবসাইটগুলিকে শনাক্ত করার জন্য এই শংসপত্রটিকে বিশ্বাস করুন</translation>
+<translation id="6651495917527016072">আপনার ফোনের সাথে ওয়াই-ফাই নেটওয়ার্ক সিঙ্ক করুন। <ph name="LINK_BEGIN" />আরও জানুন<ph name="LINK_END" /></translation>
 <translation id="665355505818177700">Chrome <ph name="MS_AD_NAME" /> ইন্টিগ্রেশন শুধুমাত্র x86_64 প্ল্যাটফর্মে সমর্থিত। ARM অথবা x86 প্ল্যাটফর্মে তৈরি Chromebook এ এই কাজটি করা যাবে না।</translation>
 <translation id="6654509035557065241">পছন্দের নেটওয়ার্ক</translation>
 <translation id="6655190889273724601">ডেভেলপার মোড</translation>
@@ -5400,6 +5410,7 @@
 <translation id="7375235221357833624">{0,plural, =1{১ ঘণ্টার মধ্যে ডিভাইস আপডেট করুন}one{# ঘণ্টার মধ্যে ডিভাইস আপডেট করুন}other{# ঘণ্টার মধ্যে ডিভাইস আপডেট করুন}}</translation>
 <translation id="7376553024552204454">মাউস কার্সারটি যখন নড়াচড়া করে তখন একে হাইলাইট করুন</translation>
 <translation id="7377451353532943397">সেন্সর অ্যাক্সেস ব্লক করা চালিয়ে যান</translation>
+<translation id="7378611153938412599">দুর্বল পাসওয়ার্ড সহজেই অনুমান করা যায়। আপনি শক্তিশালী পাসওয়ার্ড তৈরি করছেন কিনা তা ভাল করে দেখে নিন। <ph name="BEGIN_LINK" />নিরাপত্তা সংক্রান্ত আরও পরামর্শ দেখুন।<ph name="END_LINK" /></translation>
 <translation id="73786666777299047">Chrome ওয়েব স্টোর খুলুন</translation>
 <translation id="7378812711085314936">ডেটা সংযোগ পান</translation>
 <translation id="7380622428988553498">ডিভাইসের নামে অনুপোযুক্ত অক্ষর আছে</translation>
@@ -5923,6 +5934,7 @@
 <translation id="7959074893852789871">ফাইলটিতে একাধিক শংসাপত্র রয়েছে, এর মধ্যে কয়েকটি আমদানি করা হয়নি:</translation>
 <translation id="7961015016161918242">কখনই নয়</translation>
 <translation id="7963001036288347286">টাচপ্যাড অ্যাক্সিলারেশন</translation>
+<translation id="7963608432878156675">এই নামটি অন্যান্য ডিভাইসে দেখা যাবে যাতে ব্লুটুথ ও নেটওয়ার্কের সাথে কানেক্ট করা যায়</translation>
 <translation id="7963826112438303517">আপনার অ্যাসিস্ট্যান্ট এই রেকর্ডিং ও অনুরোধের ভয়েস ব্যবহার করে আপনার একটি ভয়েস মডেল তৈরি ও আপডেট করে। আপনি Voice Match চালু করেছেন এমন ডিভাইসে এটি স্টোর হয়ে থাকে। অ্যাসিস্ট্যান্ট সেটিংসে ভয়েস অ্যাক্টিভিটি দেখুন বা রেখে দিন।</translation>
 <translation id="7966241909927244760">ছবি আইডি কপি করুন</translation>
 <translation id="7966571622054096916">{COUNT,plural, =1{বুকমার্ক তালিকাতে ১টি আইটেম আছে}one{বুকমার্ক তালিকাতে {COUNT}টি আইটেম আছে}other{বুকমার্ক তালিকাতে {COUNT}টি আইটেম আছে}}</translation>
@@ -6386,6 +6398,7 @@
 <translation id="850875081535031620">কোনও ক্ষতিকর সফ্টওয়্যার খুঁজে পাওয়া যায়নি</translation>
 <translation id="8509177919508253835">নিরাপত্তা কী ডিভাইস রিসেট করে পিন তৈরি করুন</translation>
 <translation id="8509646642152301857">বানান পরীক্ষক অভিধান ডাউনলোড করা যায়নি৷</translation>
+<translation id="8512396579636492893">{COUNT,plural, =0{কোনও দুর্বল পাসওয়ার্ড পাওয়া যায়নি}=1{{COUNT}টি দুর্বল পাসওয়ার্ড পাওয়া গেছে}one{{COUNT}টি দুর্বল পাসওয়ার্ড পাওয়া গেছে}other{{COUNT}টি দুর্বল পাসওয়ার্ড পাওয়া গেছে}}</translation>
 <translation id="8512476990829870887">প্রক্রিয়া সমাপ্ত করুন</translation>
 <translation id="851263357009351303">ছবিগুলি দেখানোর জন্য সর্বদা <ph name="HOST" />-কে অনুমতি দিন </translation>
 <translation id="8513108775083588393">অটো রোটেট</translation>
diff --git a/chrome/app/resources/generated_resources_gu.xtb b/chrome/app/resources/generated_resources_gu.xtb
index 7ee6df22..9eee8424 100644
--- a/chrome/app/resources/generated_resources_gu.xtb
+++ b/chrome/app/resources/generated_resources_gu.xtb
@@ -17,6 +17,7 @@
 <translation id="1012794136286421601">તમારી દસ્તાવેજ, શીટ, સ્લાઇડ, અને ડ્રોઇંગ્સ ફાઇલો સિંક થઈ રહી છે. ઓનલાઇન કે ઑફલાઇન તેમને વાપરવા માટે Google ડ્રાઇવ ઍપ મેમરીન ખોલો.</translation>
 <translation id="1012876632442809908">USB-C ઉપકરણ (આગળનું પોર્ટ)</translation>
 <translation id="1013707859758800957">એક અનસેન્ડબૉક્સ્ડ પ્લગિનને આ પૃષ્ઠ પર ચાલવાની મંજૂરી આપવામાં આવી હતી.</translation>
+<translation id="1015041505466489552">TrackPoint</translation>
 <translation id="1015318665228971643">ફોલ્ડરના નામમાં ફેરફાર કરો</translation>
 <translation id="1015578595646638936">{NUM_DAYS,plural, =1{<ph name="DEVICE_TYPE" /> અપડેટ કરવાનો છેલ્લો દિવસ}one{<ph name="DEVICE_TYPE" /> {NUM_DAYS} દિવસની અંદર અપડેટ કરો}other{<ph name="DEVICE_TYPE" /> {NUM_DAYS} દિવસની અંદર અપડેટ કરો}}</translation>
 <translation id="1016566241875885511">અતિરિક્ત માહિતી (વૈકલ્પિક)</translation>
diff --git a/chrome/app/resources/generated_resources_iw.xtb b/chrome/app/resources/generated_resources_iw.xtb
index 491e5f0..004a65567 100644
--- a/chrome/app/resources/generated_resources_iw.xtb
+++ b/chrome/app/resources/generated_resources_iw.xtb
@@ -30,7 +30,7 @@
 <translation id="1029317248976101138">התקרב</translation>
 <translation id="1031362278801463162">טוען תצוגה מקדימה</translation>
 <translation id="1032605640136438169">יש לקרוא את התנאים החדשים</translation>
-<translation id="103279545524624934">‏עליך לפנות שטח אחסון כדי להפעיל אפליקציות Android.</translation>
+<translation id="103279545524624934">‏עליך לפנות נפח אחסון כדי להפעיל אפליקציות Android.</translation>
 <translation id="1033780634303702874">גישה להתקנים הסיריאליים שלך</translation>
 <translation id="1034942643314881546">‏המערכת מפעילה את ADB ליצירת איור של אפליקציות</translation>
 <translation id="1036348656032585052">כיבוי</translation>
@@ -120,7 +120,7 @@
 <translation id="1128591060186966949">עריכת מנוע חיפוש</translation>
 <translation id="1129850422003387628">ניהול אפליקציות</translation>
 <translation id="1130589222747246278"><ph name="WINDOW_TITLE" /> – חלק מהקבוצה <ph name="GROUP_NAME" /></translation>
-<translation id="1134009406053225289">פתח בחלון גלישה פרטית</translation>
+<translation id="1134009406053225289">פתיחה בחלון גלישה פרטית</translation>
 <translation id="1136179794690960030"><ph name="EMOJI_NAME" />. <ph name="EMOJI_INDEX" /> מתוך <ph name="EMOJI_COUNT" />.</translation>
 <translation id="1136712381129578788">מפתח האבטחה נעול כי הזנת קוד אימות שגוי יותר מדי פעמים. כדי לבטל את הנעילה צריך לנתק ולחבר אותו מחדש.</translation>
 <translation id="1137589305610962734">נתונים זמניים</translation>
@@ -203,7 +203,7 @@
 <translation id="1221825588892235038">בחירה בלבד</translation>
 <translation id="1223484782328004593">נדרש רישיון כדי להשתמש ב-<ph name="APP_NAME" /></translation>
 <translation id="1223853788495130632">מנהל המערכת ממליץ על ערך מסוים עבור הגדרה זו.</translation>
-<translation id="1225177025209879837">מעבד את הבקשה...</translation>
+<translation id="1225177025209879837">עיבוד הבקשה מתבצע...</translation>
 <translation id="1227507814927581609">האימות נכשל בעת ההתחברות אל "<ph name="DEVICE_NAME" />".</translation>
 <translation id="1230417814058465809">מופעלת הגנה רגילה. כדי להוסיף שכבת אבטחה, יש להשתמש בהגנה המשופרת.</translation>
 <translation id="1231733316453485619">להפעיל סנכרון?</translation>
@@ -456,7 +456,7 @@
 <translation id="1515163294334130951">הפעלה</translation>
 <translation id="1515909359182093592"><ph name="INPUT_LABEL" /> – מארח</translation>
 <translation id="1520689915144573455">{COUNT,plural, =1{אפליקציה אחת}two{# אפליקציות}many{# אפליקציות}other{# אפליקציות}}</translation>
-<translation id="1521442365706402292">נהל אישורים</translation>
+<translation id="1521442365706402292">ניהול אישורים</translation>
 <translation id="1521774566618522728">סנכרון אחרון: היום</translation>
 <translation id="152234381334907219">פריטים שאף פעם לא נשמרו</translation>
 <translation id="1523170391134722817">לא תהיה תמיכה אחרי דצמבר</translation>
@@ -518,10 +518,10 @@
 <translation id="1587907146729660231">יש לגעת בלחצן ההפעלה עם האצבע</translation>
 <translation id="1588438908519853928">רגיל</translation>
 <translation id="158849752021629804">יש צורך ברשת ביתית</translation>
-<translation id="1588870296199743671">פתח קישור באמצעות...</translation>
+<translation id="1588870296199743671">פתיחת קישור באמצעות...</translation>
 <translation id="1589055389569595240">הצג איות ודקדוק</translation>
 <translation id="1591679663873027990">‏הרשאת גישה למכשירי USB באמצעות Parallels Desktop. אחרי הוצאת התקן ה-USB, הוא לא נשמר בזיכרון של Parallels Desktop.</translation>
-<translation id="1593594475886691512">מפרמט...</translation>
+<translation id="1593594475886691512">הפרמוט מתבצע...</translation>
 <translation id="159359590073980872">מטמון של תמונה</translation>
 <translation id="1593926297800505364">שמירת אמצעי התשלום</translation>
 <translation id="1595492813686795610">‏מתבצע עכשיו שדרוג של Linux</translation>
@@ -585,14 +585,14 @@
 <translation id="1653526288038954982">{NUM_PRINTER,plural, =1{‏יש להוסיף את המדפסת אל Google Cloud Print כך שניתן יהיה להדפיס מכל מקום.}two{‏יש להוסיף # מדפסות אל Google Cloud Print כך שניתן יהיה להדפיס מכל מקום.}many{‏יש להוסיף # מדפסות אל Google Cloud Print כך שניתן יהיה להדפיס מכל מקום.}other{‏יש להוסיף # מדפסות אל Google Cloud Print כך שניתן יהיה להדפיס מכל מקום.}}</translation>
 <translation id="1653575510930452864">העתקת הקישור לטקסט</translation>
 <translation id="1656528038316521561">שקיפות רקע</translation>
-<translation id="1657406563541664238">‏עזור להפוך את <ph name="PRODUCT_NAME" /> לטוב יותר, על ידי שליחה אוטומטית של נתוני שימוש ודוחות קריסה אל Google</translation>
+<translation id="1657406563541664238">‏רוצה לעזור לנו לשפר את <ph name="PRODUCT_NAME" /> על ידי שליחה אוטומטית של נתוני שימוש ודוחות קריסה אל Google?</translation>
 <translation id="1657937299377480641">כדי להיכנס מחדש לצורך גישה למקורות מידע חינוכיים, יש לבקש הרשאה מהורה</translation>
 <translation id="1658424621194652532">דף זה ניגש למיקרופון שלך.</translation>
 <translation id="1660204651932907780">מתן הרשאה לאתרים להשמיע צלילים (מומלץ)</translation>
 <translation id="1660763353352708040">בעיה במתאם המתח</translation>
 <translation id="1661156625580498328">‏אכיפה של הצפנת AES (מומלץ).</translation>
 <translation id="1661867754829461514">‏חסר PIN</translation>
-<translation id="16620462294541761">מצטערים, לא ניתן לאמת את הסיסמה שלך. נסה שוב.</translation>
+<translation id="16620462294541761">מצטערים, לא ניתן לאמת את הסיסמה שלך. יש לנסות שוב.</translation>
 <translation id="166278006618318542">אלגוריתם מפתח ציבורי של נושא</translation>
 <translation id="166439687370499867">אין אישור לשנות את תצורת הרשתות המשותפות</translation>
 <translation id="1668435968811469751">הרשמה ידנית</translation>
@@ -683,7 +683,7 @@
 <translation id="1766575458646819543">התבצעה יציאה ממסך מלא</translation>
 <translation id="1766957085594317166">‏אפשר לשמור סיסמאות בצורה בטוחה בחשבון Google, כך שלאחר מכן לא יהיה יותר צורך להקליד אותן ידנית</translation>
 <translation id="1768278914020124551">אופס! נתקלנו בבעיה ביצירת קשר עם שרת ההתחברות. בדוק את חיבור הרשת ואת שם הדומיין ולאחר מכן נסה שוב.</translation>
-<translation id="1769104665586091481">פתח קישור &amp;בחלון חדש</translation>
+<translation id="1769104665586091481">פתיחת קישור &amp;בחלון חדש</translation>
 <translation id="1773212559869067373">אישור האימות נדחה מקומית</translation>
 <translation id="177336675152937177">נתוני יישומים מתארחים</translation>
 <translation id="1776712937009046120">הוסף משתמש</translation>
@@ -757,7 +757,7 @@
 <translation id="1845727111305721124">מורשים להשמיע צלילים</translation>
 <translation id="1846308012215045257">‏כדי להפעיל את <ph name="PLUGIN_NAME" />, יש ללחוץ עליו תוך כדי הקשה על Control</translation>
 <translation id="1849186935225320012">‏לדף זה יש שליטה מלאה על מכשירי MIDI.</translation>
-<translation id="1850508293116537636">סובב &amp;בכיוון השעון</translation>
+<translation id="1850508293116537636">סיבוב &amp;בכיוון השעון</translation>
 <translation id="1852141627593563189">חיפוש תוכנה מזיקה</translation>
 <translation id="1852799913675865625">אירעה שגיאה בעת ניסיון לקרוא את הקובץ: <ph name="ERROR_TEXT" />.</translation>
 <translation id="1853692000353488670">כרטיסייה חדשה לגלישה בסתר</translation>
@@ -799,7 +799,7 @@
 <translation id="1887597546629269384">‏יש לומר שוב "Hey Google"</translation>
 <translation id="1887850431809612466">שכתוב חומרה</translation>
 <translation id="1890674179660343635">‏&lt;span&gt;מזהה: &lt;/span&gt;<ph name="EXTENSION_ID" /></translation>
-<translation id="189210018541388520">פתח מסך מלא</translation>
+<translation id="189210018541388520">פתיחת מסך מלא</translation>
 <translation id="1892341345406963517">שלום <ph name="PARENT_NAME" /></translation>
 <translation id="189358972401248634">שפות אחרות</translation>
 <translation id="1895658205118569222">כיבוי</translation>
@@ -979,7 +979,7 @@
 <translation id="2122305276694332719">חיבור אוטומטי לרשת מוסתרת מאפשר לאחרים לראות את המכשיר שלך וחלק מהגדרות הרשת. האפשרות הזו לא מומלצת.</translation>
 <translation id="2123766928840368256">בחירת קובץ אחר</translation>
 <translation id="2124930039827422115">{1,plural, =1{משתמש אחד נתן דירוג של <ph name="AVERAGE_RATING" />.}two{# משתמשים נתנו דירוג של <ph name="AVERAGE_RATING" />.}many{# משתמשים נתנו דירוג של <ph name="AVERAGE_RATING" />.}other{# משתמשים נתנו דירוג של <ph name="AVERAGE_RATING" />.}}</translation>
-<translation id="2126167708562367080">מנהל המערכת שלך השבית את הסינכרון.</translation>
+<translation id="2126167708562367080">מנהל המערכת שלך השבית את הסנכרון.</translation>
 <translation id="2127372758936585790">מטען בעל מתח נמוך</translation>
 <translation id="212862741129535676">אחוז תפוסה במצב תדירות</translation>
 <translation id="212876957201860463">בשלבי הכנה להגדרת המכשיר הסלולרי...</translation>
@@ -995,7 +995,7 @@
 <translation id="2139545522194199494">‏רשת <ph name="NETWORK_INDEX" /> מתוך <ph name="NETWORK_COUNT" />,‏ <ph name="NETWORK_NAME" />,‏ עוצמת האות: ‎<ph name="SIGNAL_STRENGTH" />%‎, הרשת מנוהלת על ידי מנהל המערכת שלך, התחברות</translation>
 <translation id="2139919072249842737">לחצן ההגדרה</translation>
 <translation id="214169863967063661">פתיחת הגדרות המראה</translation>
-<translation id="2142328300403846845">פתח קישור בתור</translation>
+<translation id="2142328300403846845">פתיחת קישור בתור</translation>
 <translation id="2143765403545170146">הצג תמיד את סרגל הכלים במצב מסך מלא</translation>
 <translation id="2143778271340628265">‏תצורת שרת proxy ידנית</translation>
 <translation id="2144536955299248197">מציג האישורים: <ph name="CERTIFICATE_NAME" /></translation>
@@ -1069,7 +1069,7 @@
 <translation id="2220529011494928058">דיווח על בעיה</translation>
 <translation id="2220572644011485463">קוד אימות או סיסמה</translation>
 <translation id="2224444042887712269">ההגדרה הזו שייכת ל-<ph name="OWNER_EMAIL" />.</translation>
-<translation id="2224551243087462610">ערוך את שם התיקייה</translation>
+<translation id="2224551243087462610">עריכת שם התיקייה</translation>
 <translation id="2225864335125757863">כדי להגן על החשבון, יש לשנות את הסיסמאות הבאות באופן מיידי:</translation>
 <translation id="2226204716217107988">לעבור לפרופיל אחר?</translation>
 <translation id="2226449515541314767">‏האפשרות לשלוט שליטה מלאה על מכשירי MIDI נחסמה עבור אתר זה.</translation>
@@ -1118,7 +1118,7 @@
 <translation id="2274840746523584236">‏יש לטעון את Chromebook</translation>
 <translation id="2276503375879033601">הוספת יישומים</translation>
 <translation id="2277255602909579701">‏כל קובצי ה-Cookie ונתוני האתר</translation>
-<translation id="2278562042389100163">פתח חלון דפדפן</translation>
+<translation id="2278562042389100163">פתיחת חלון דפדפן</translation>
 <translation id="2280486287150724112">שוליים ימניים</translation>
 <translation id="2282146716419988068">‏תהליך GPU</translation>
 <translation id="2282155092769082568">כתובת אתר של תצורה אוטומטית:</translation>
@@ -1190,7 +1190,7 @@
 <translation id="2355604387869345912">הפעלת שיתוף אינטרנט מיידי בין מכשירים</translation>
 <translation id="2356070529366658676">שאל</translation>
 <translation id="2357330829548294574">הסרה של <ph name="USER_NAME" /></translation>
-<translation id="2359345697448000899">נהל את התוספים שלך באמצעות לחיצה על 'תוספים' בתפריט כלים.</translation>
+<translation id="2359345697448000899">ניהול התוספים שלך על ידי לחיצה על 'תוספים' בתפריט כלים.</translation>
 <translation id="2359556993567737338">‏חיבור התקן Bluetooth</translation>
 <translation id="2359808026110333948">המשך</translation>
 <translation id="236117173274098341">אופטימיזציה</translation>
@@ -1199,7 +1199,7 @@
 <translation id="2365507699358342471">לאתר הזה יש גישה אל טקסט ותמונות שהועתקו אל לוח העריכה.</translation>
 <translation id="2366260648632264559">יש להציג את טקסט המערכת בשפה הזו</translation>
 <translation id="2367972762794486313">הצגת אפליקציות</translation>
-<translation id="2371076942591664043">פתח &amp;בסיום</translation>
+<translation id="2371076942591664043">פתיחה &amp;בסיום</translation>
 <translation id="2373666622366160481">התאמה לגודל הנייר</translation>
 <translation id="2375406435414127095">התחברות לטלפון</translation>
 <translation id="2377588536920405462">‏כדי לכבות את המיקום, עליך להשבית את ההגדרה הראשית של המיקום במכשיר שלך. בהגדרות המיקום אפשר גם להשבית את האפשרות להסתמך על Wi-Fi, רשתות סלולריות וחיישנים כדי לקבוע את המיקום.</translation>
@@ -1310,7 +1310,7 @@
 <translation id="2497852260688568942">מנהל המערכת שלך השבית את הסנכרון</translation>
 <translation id="2498539833203011245">מזער</translation>
 <translation id="2498765460639677199">ענק</translation>
-<translation id="2499747912851752301">מייצא סיסמאות...</translation>
+<translation id="2499747912851752301">ייצוא סיסמאות מתבצע...</translation>
 <translation id="2500471369733289700">הגישה לאתר נחסמה כדי להגן על הפרטיות שלך</translation>
 <translation id="2501173422421700905">אישור בהמתנה</translation>
 <translation id="2501278716633472235">חזרה</translation>
@@ -1509,7 +1509,7 @@
 <translation id="2730029791981212295">‏גיבוי אפליקציות וקובצי Linux</translation>
 <translation id="2730901670247399077">הצעות אמוג'י</translation>
 <translation id="273093730430620027">דף זה ניגש למצלמה שלך.</translation>
-<translation id="2731392572903530958">פתח מ&amp;חדש חלון שנסגר</translation>
+<translation id="2731392572903530958">פתיחה מ&amp;חדש של חלון שנסגר</translation>
 <translation id="2731700343119398978">יש להמתין...</translation>
 <translation id="2731710757838467317">יוצר את המשתמש בפיקוח. התהליך עשוי להימשך מספר רגעים.</translation>
 <translation id="2731971182069536520">בפעם הבאה שהמכשיר יופעל מחדש, מנהל המערכת יבצע עדכון חד-פעמי שימחק את הנתונים המקומיים.</translation>
@@ -1575,7 +1575,7 @@
 <translation id="2799223571221894425">הפעל מחדש</translation>
 <translation id="2800760947029405028">העלאת תמונה</translation>
 <translation id="2801954693771979815">גודל תצוגה במסך</translation>
-<translation id="2803313416453193357">פתח את התיקייה</translation>
+<translation id="2803313416453193357">פתיחת התיקייה</translation>
 <translation id="2803375539583399270">הזנת קוד אימות</translation>
 <translation id="2804043232879091219">לא ניתן לפתוח את הדפדפן החלופי</translation>
 <translation id="2804667941345577550">המערכת תוציא אותך מהאתר הזה, כולל בכרטיסיות הפתוחות</translation>
@@ -1626,7 +1626,7 @@
 <translation id="2864601841139725659">הגדר את תמונת הפרופיל</translation>
 <translation id="2865919525181940183">צילום מסך של התוכנות שמוצגות כרגע במסך</translation>
 <translation id="286674810810214575">מקורות החשמל בבדיקה…</translation>
-<translation id="2867768963760577682">פתח ככרטיסייה מוצמדת</translation>
+<translation id="2867768963760577682">פתיחה ככרטיסייה מוצמדת</translation>
 <translation id="2868746137289129307">תוסף זה הוא מיושן והושבת בהתאם למדיניות הארגון. ייתכן שהוא יופעל באופן אוטומטי כשתצא גרסה חדשה יותר.</translation>
 <translation id="2870560284913253234">אתר</translation>
 <translation id="2870909136778269686">מעדכן....</translation>
@@ -1649,7 +1649,7 @@
 <translation id="2885378588091291677">מנהל המשימות</translation>
 <translation id="2885729872133513017">התרחשה בעיה במהלך פענוח תגובת השרת.</translation>
 <translation id="2886771036282400576">• <ph name="PERMISSION" /></translation>
-<translation id="2889064240420137087">פתח קישור באמצעות...</translation>
+<translation id="2889064240420137087">פתיחת קישור באמצעות...</translation>
 <translation id="2889925978073739256">המשך לחסום יישומי פלאגין שאינם בארגז חול</translation>
 <translation id="2893168226686371498">דפדפן ברירת מחדל</translation>
 <translation id="2893917546370257247">{COUNT,plural, =1{קטע טקסט אחד}two{# קטעי טקסט}many{# קטעי טקסט}other{# קטעי טקסט}}</translation>
@@ -1713,7 +1713,7 @@
 <translation id="2960208947600937804">‏אירעה שגיאה במהלך ההגדרה של Linux. יש לפנות אל מנהל המערכת.</translation>
 <translation id="296026337010986570">‏סיימנו! התוכנות המזיקות הוסרו. כדי להפעיל מחדש את התוספים, צריך לעבור אל &lt;a href="chrome://extensions"&gt;תוספים&lt;/a&gt;.</translation>
 <translation id="2961090598421146107"><ph name="CERTIFICATE_NAME" /> (ניתנה הארכה)</translation>
-<translation id="2961695502793809356">לחץ כדי לעבור קדימה, לחץ והחזק כדי לראות את ההיסטוריה</translation>
+<translation id="2961695502793809356">יש ללחוץ כדי לעבור קדימה, ללחוץ ולהחזיק כדי לראות את ההיסטוריה</translation>
 <translation id="2962131322798295505">Wallpaper Picker</translation>
 <translation id="2963151496262057773">הפלאגין הבא אינו מגיב: <ph name="PLUGIN_NAME" /> האם ברצונך לכבות אותו?</translation>
 <translation id="2964193600955408481">‏השבתת Wi-Fi</translation>
@@ -1948,7 +1948,7 @@
 <translation id="3269069891205016797">כשתצא, המידע שלך יוסר מהמכשיר.</translation>
 <translation id="3269093882174072735">טעינת תמונה</translation>
 <translation id="3269612321104318480">כחול-ירקרק בהיר ולבן</translation>
-<translation id="326999365752735949">מוריד הבדלים</translation>
+<translation id="326999365752735949">הורדת ההבדלים מתבצעת</translation>
 <translation id="3270965368676314374">קריאה, שינוי ומחיקה של קובצי תמונות, מוזיקה ומדיה מסוגים נוספים מהמחשב שלך</translation>
 <translation id="327147043223061465">‏הצגה של כל קובצי ה-Cookie ונתוני האתרים</translation>
 <translation id="3271648667212143903"><ph name="ORIGIN" /> רוצה להתחבר אל</translation>
@@ -1984,7 +1984,7 @@
 <translation id="3305389145870741612">תהליך הפרמוט עשוי להימשך מספר שניות. אנא המתן.</translation>
 <translation id="3305661444342691068">‏פתח PDF בתצוגה מקדימה</translation>
 <translation id="3308116878371095290">‏לא ניתן להגדיר קובצי Cookie לדף זה.</translation>
-<translation id="3308134619352333507">לחצן 'הסתר'</translation>
+<translation id="3308134619352333507">לחצן 'הסתרה'</translation>
 <translation id="3308852433423051161">‏טעינת Google Assistant מתבצעת...</translation>
 <translation id="3310640316857623290">‏זמן האחזור של ה-DNS גבוה במידה משמעותית מהסף המותר</translation>
 <translation id="3311445899360743395">ייתכן שיוסרו מהמכשיר נתונים המשויכים לאפליקציה הזו.</translation>
@@ -2063,7 +2063,7 @@
 <translation id="340671561090997290">{NUM_EXTENSIONS,plural, =1{התוסף הזה עשוי להיות מסוכן}two{התוספים האלה עשויים להיות מסוכנים}many{התוספים האלה עשויים להיות מסוכנים}other{התוספים האלה עשויים להיות מסוכנים}}</translation>
 <translation id="3409785640040772790">מפות</translation>
 <translation id="3410832398355316179">כל הקבצים והנתונים המקומיים שמשויכים למשתמש הזה יימחקו לצמיתות אחרי שהמשתמש יוסר. <ph name="USER_EMAIL" /> יוכל עדיין להיכנס לחשבון מאוחר יותר.</translation>
-<translation id="3412265149091626468">עבור אל בחירה</translation>
+<translation id="3412265149091626468">מעבר אל בחירה</translation>
 <translation id="3413122095806433232">מנפיקי רשות אישורים: <ph name="LOCATION" /></translation>
 <translation id="3414952576877147120">גודל:</translation>
 <translation id="3416468988018290825">‏הצגה של כתובות URL מלאות בכל המקרים</translation>
@@ -2138,10 +2138,10 @@
 <translation id="3480827850068960424">נמצאו <ph name="NUM" /> כרטיסיות</translation>
 <translation id="3481268647794498892">ייפתח ב-<ph name="ALTERNATIVE_BROWSER_NAME" /> בעוד <ph name="COUNTDOWN_SECONDS" /> שניות</translation>
 <translation id="3482719661246593752">ל-<ph name="ORIGIN" /> יש אפשרות לראות את הקבצים הבאים</translation>
-<translation id="3484273680291419129">מסיר תוכנה מזיקה...</translation>
+<translation id="3484273680291419129">הסרת תוכנה מזיקה מתבצעת...</translation>
 <translation id="3484869148456018791">קבל אישור חדש</translation>
 <translation id="3487007233252413104">פונקציה אנונימית</translation>
-<translation id="348780365869651045">‏ממתין ל-AppCache...</translation>
+<translation id="348780365869651045">‏בהמתנה ל-AppCache...</translation>
 <translation id="3488065109653206955">מופעל חלקית</translation>
 <translation id="3491669675709357988">‏בחשבון של הילד או הילדה שלך לא מוגדרת בקרת הורים של Family Link. יש לך אפשרות להוסיף בקרת הורים לאחר סיום ההגדרה. באפליקציה 'מה חדש ב-Chromebook' מפורט מידע נוסף על בקרת הורים.</translation>
 <translation id="3491678231052507920">‏אתרים משתמשים בדרך כלל בנתונים ובמכשירים של מציאות מדומה כדי לאפשר כניסה לפעילויות VR</translation>
@@ -2739,7 +2739,7 @@
 <translation id="4142518881503042940">ניתן לשמור את המדפסות שזוהו בפרופיל שלך או להוסיף מדפסת חדשה. <ph name="LINK_BEGIN" />מידע נוסף<ph name="LINK_END" /></translation>
 <translation id="4144218403971135344">שיפור איכות הווידאו וחיסכון בחיי הסוללה. תוכן וידאו יופעל רק במסך התומך בהעברה.</translation>
 <translation id="4144651632048685784">{COUNT,plural, =1{מספר טלפון אחד}two{# מספרי טלפון}many{# מספרי טלפון}other{# מספרי טלפון}}</translation>
-<translation id="4146026355784316281">פתח תמיד באמצעות מציג המערכת</translation>
+<translation id="4146026355784316281">פתיחה תמיד באמצעות מציג המערכת</translation>
 <translation id="4146785383423576110">איפוס וניקוי</translation>
 <translation id="4147897805161313378">‏תמונות Google</translation>
 <translation id="4147911968024186208">אפשר לנסות שוב. אם השגיאה הזאת ממשיכה להופיע, ניתן לפנות לנציג התמיכה.</translation>
@@ -2797,7 +2797,7 @@
 <translation id="4242577469625748426">התקנת הגדרות המדיניות במכשיר: <ph name="VALIDATION_ERROR" /> נכשלה.</translation>
 <translation id="4243504193894350135">המדפסת מושהית</translation>
 <translation id="4244238649050961491">חיפוש עוד אפליקציות לשימוש בסטיילוס</translation>
-<translation id="424726838611654458">‏פתח תמיד ב-Adobe Reader</translation>
+<translation id="424726838611654458">‏פתיחה תמיד ב-Adobe Reader</translation>
 <translation id="4247901771970415646">לא ניתן לסנכרן עם <ph name="USERNAME" /></translation>
 <translation id="4248098802131000011">הגנה על הסיסמאות שלך מפני פרצות באבטחת המידע ובעיות אבטחה אחרות</translation>
 <translation id="4249248555939881673">תיכף נתחבר לרשת…</translation>
@@ -2978,14 +2978,14 @@
 <translation id="4471354919263203780">‏מתבצעת הורדה של קובצי זיהוי דיבור… ‎<ph name="PERCENT" />%‎</translation>
 <translation id="447252321002412580">‏עזרה בשיפור התכונות והביצועים של Chrome</translation>
 <translation id="4472575034687746823">תחילת העבודה</translation>
-<translation id="4474155171896946103">צור סימניה לכל הכרטיסיות...</translation>
+<translation id="4474155171896946103">יצירת סימנייה לכל הכרטיסיות...</translation>
 <translation id="4474461121892222090">הפעלת חבילת הגלישה עשויה לארוך עד 15 דקות.</translation>
 <translation id="4475552974751346499">חפש בהורדות</translation>
 <translation id="4476590490540813026">ספורטאית</translation>
 <translation id="4476659815936224889">‏כדי לסרוק את הקוד הזה, ניתן להשתמש באפליקציה של סורק קודי ה-QR בטלפון או באפליקציות מצלמה מתאימות.</translation>
 <translation id="4477015793815781985">‏צריך לכלול Ctrl, ‏Alt או ⌘</translation>
 <translation id="4478664379124702289">שמור קישו&amp;ר כ...</translation>
-<translation id="4479424953165245642">נהל יישומי קיוסק</translation>
+<translation id="4479424953165245642">ניהול יישומי קיוסק</translation>
 <translation id="4479639480957787382">אתרנט</translation>
 <translation id="4479877282574735775">המערכת מגדירה את המכונה הוירטואלית. הפעולה עשויה להימשך כמה דקות.</translation>
 <translation id="4480590691557335796">‏Chrome יכול לאתר תוכנות מזיקות במחשב ולהסיר אותן</translation>
@@ -3038,7 +3038,7 @@
 <translation id="4535127706710932914">פרופיל ברירת מחדל</translation>
 <translation id="4535767533210902251">חיישן טביעת האצבע מותקן במקש הימני העליון במקלדת. יש לגעת בו בעדינות באחת האצבעות.</translation>
 <translation id="4536140153723794651">‏אתרים שתמיד יכולים להשתמש בקובצי cookie</translation>
-<translation id="4538417792467843292">מחק מילה</translation>
+<translation id="4538417792467843292">מחיקת מילה</translation>
 <translation id="4538684596480161368">תמיד לחסום יישומי פלאגין ללא ארגז חול ב-<ph name="HOST" /></translation>
 <translation id="4538792345715658285">מותקן לפי מדיניות של ארגון.</translation>
 <translation id="4542520061254486227">קריאת הנתונים שלך באתרים <ph name="WEBSITE_1" /> ו-<ph name="WEBSITE_2" /></translation>
@@ -3170,7 +3170,7 @@
 <translation id="4670064810192446073">מציאות מדומה</translation>
 <translation id="4671265665487288124">אתרים יכולים לבקש הרשאה להוריד מספר קבצים באופן אוטומטי (מומלץ)</translation>
 <translation id="46733273239502219">המערכת תמחק גם נתונים שנשמרו במצב אופליין באפליקציות מותקנות</translation>
-<translation id="4673442866648850031">פתח את כלי הסטיילוס לאחר שליפת הסטיילוס</translation>
+<translation id="4673442866648850031">פתיחת כלי הסטיילוס לאחר שליפת הסטיילוס</translation>
 <translation id="4677772697204437347">‏זיכרון GPU</translation>
 <translation id="4680105648806843642">הצלילים הושתקו בדף הזה</translation>
 <translation id="4681453295291708042">השבתה של 'שיתוף בקרבת מקום'</translation>
@@ -3259,7 +3259,7 @@
 <translation id="4807098396393229769">שם על הכרטיס</translation>
 <translation id="4808667324955055115">חלונות קופצים חסומים</translation>
 <translation id="4809079943450490359">הוראות ממנהל המכשיר שלך:</translation>
-<translation id="480990236307250886">פתח את דף הבית</translation>
+<translation id="480990236307250886">פתיחת דף הבית</translation>
 <translation id="4811212958317149293">סריקה אוטומטית של מקלדת גישה באמצעות מתג</translation>
 <translation id="4811503964269049987">קיבוץ הכרטיסיות שנבחרו</translation>
 <translation id="4813136279048157860">התמונות שלי</translation>
@@ -3317,7 +3317,7 @@
 <translation id="4871568871368204250">כיבוי הסינכרון</translation>
 <translation id="4871719318659334896">סגירת הקבוצה</translation>
 <translation id="4873312501243535625">בודק קובצי המדיה</translation>
-<translation id="4876273079589074638">עזור למהנדסים שלנו לחקור את הקריסה הזו ולתקן אותה. מומלץ לרשום את השלבים בצורה כמה שיותר מדויקת, גם הפרטים הקטנים ביותר יכולים לעזור.</translation>
+<translation id="4876273079589074638">רוצה לעזור למהנדסים שלנו לחקור את הקריסה הזו ולתקן אותה? מומלץ לרשום את השלבים בצורה כמה שיותר מדויקת, גם הפרטים הקטנים ביותר יכולים לעזור.</translation>
 <translation id="4876895919560854374">נעילה ושחרור של המסך</translation>
 <translation id="4877276003880815204">בדיקת רכיבים</translation>
 <translation id="4878653975845355462">מנהל המערכת השבית את הרקעים המותאמים אישית</translation>
@@ -3415,7 +3415,7 @@
 <translation id="4985509611418653372">הרצה</translation>
 <translation id="4986728572522335985">הפעולה הזו תמחק את כל הנתונים במפתח האבטחה, כולל קוד האימות שלו</translation>
 <translation id="4988526792673242964">דפים</translation>
-<translation id="49896407730300355">סובב נ&amp;גד כיוון השעון</translation>
+<translation id="49896407730300355">סיבוב נ&amp;גד כיוון השעון</translation>
 <translation id="4989966318180235467">בדיקת דף ה&amp;רקע</translation>
 <translation id="4991420928586866460">התייחס למקשים בשורה העליונה כאל מקשי פונקציה</translation>
 <translation id="499165176004408815">שימוש במצב ניגודיות גבוהה</translation>
@@ -3456,7 +3456,7 @@
 <translation id="5040823038948176460">הגדרות תוכן נוספות</translation>
 <translation id="5043913660911154449">‏לחלופין, אפשר לציין את ה-PPD של המדפסת <ph name="LINK_BEGIN" />מידע נוסף<ph name="LINK_END" /></translation>
 <translation id="5045550434625856497">סיסמה שגויה</translation>
-<translation id="504561833207953641">פותח בסשן קיים של הדפדפן.</translation>
+<translation id="504561833207953641">פתיחה בסשן קיים של הדפדפן.</translation>
 <translation id="5047421709274785093">מניעת שימוש של אתרים בחיישני תנועה ואור</translation>
 <translation id="5050042263972837708">שם הקבוצה</translation>
 <translation id="5050330054928994520">TTS</translation>
@@ -3529,7 +3529,7 @@
 <translation id="5135085122826131075">‏כשאומרים "Ok Google", מתבצעת גישה ל-Assistant.</translation>
 <translation id="5135533361271311778">לא ניתן ליצור פריט סימניה.</translation>
 <translation id="5136343472380336530">‏יש לוודא ששני המכשירים אינם נעולים, שהם קרובים זה לזה ושבשניהם מופעל Bluetooth. <ph name="LINK_BEGIN" />מידע נוסף<ph name="LINK_END" /></translation>
-<translation id="5137501176474113045">מחק את הפריט הזה</translation>
+<translation id="5137501176474113045">מחיקת הפריט הזה</translation>
 <translation id="5139112070765735680"><ph name="QUERY_NAME" />, חיפוש ב-<ph name="DEFAULT_SEARCH_ENGINE_NAME" /></translation>
 <translation id="5139823398361067371">יש להזין את קוד האימות של מפתח האבטחה. אם לא ידוע לך מהו קוד האימות, יהיה עליך לאפס את מפתח האבטחה.</translation>
 <translation id="5139955368427980650">&amp;פתיחה</translation>
@@ -3538,7 +3538,7 @@
 <translation id="5142961317498132443">אימות</translation>
 <translation id="5143374789336132547">התוסף "<ph name="EXTENSION_NAME" />" שינה את הדף שמוצג בלחיצה על הלחצן 'דף הבית'.</translation>
 <translation id="5143612243342258355">הקובץ הזה מסוכן</translation>
-<translation id="5143712164865402236">עבור למסך מלא</translation>
+<translation id="5143712164865402236">מעבר למסך מלא</translation>
 <translation id="514575469079499857">‏קביעת המיקום באמצעות כתובת ה-IP (ברירת מחדל)</translation>
 <translation id="5147103632304200977">‏צריך לבקש ממני אישור כשאתר רוצה לגשת להתקני HID (מומלץ)</translation>
 <translation id="5148277445782867161">‏כדי להעריך את המיקום של המכשיר שלך, שירותי המיקום של Google מסתמכים על מקורות כמו Wi-Fi, רשתות סלולריות וחיישנים.</translation>
@@ -3567,7 +3567,7 @@
 <translation id="5181140330217080051">מוריד</translation>
 <translation id="5184063094292164363">‏קונסולת JavaScript&amp; </translation>
 <translation id="5184209580557088469">כבר קיים כרטיס עם שם המשתמש הזה</translation>
-<translation id="5184662919967270437">מעדכן את המכשיר שלך</translation>
+<translation id="5184662919967270437">עדכון המכשיר שלך מתבצע</translation>
 <translation id="5185359571430619712">בדיקת הגדרות התוספים</translation>
 <translation id="5185386675596372454">הגרסה החדשה ביותר של "<ph name="EXTENSION_NAME" />" הושבתה מכיוון שהיא דורשת הרשאות נרחבות יותר.</translation>
 <translation id="5185500136143151980">אין חיבור לאינטרנט</translation>
@@ -3612,7 +3612,7 @@
 <translation id="5241128660650683457">קריאת כל הנתונים שלך באתרים שבהם אתה מבקר</translation>
 <translation id="5242724311594467048">האם להפעיל את "<ph name="EXTENSION_NAME" />"?</translation>
 <translation id="5243522832766285132">צריך לנסות שוב בעוד כמה רגעים</translation>
-<translation id="5244474230056479698">מסנכרן ל-<ph name="EMAIL" /></translation>
+<translation id="5244474230056479698">הסנכרון ל-<ph name="EMAIL" /> מתבצע</translation>
 <translation id="5245610266855777041">תחילת העבודה עם חשבון בית ספרי</translation>
 <translation id="5246282308050205996"><ph name="APP_NAME" /> קרס. לחץ על בלון זה כדי להפעיל מחדש את היישום.</translation>
 <translation id="5247051749037287028">שם תצוגה (אופציונלי)</translation>
@@ -3650,7 +3650,7 @@
 <translation id="5283677936944177147">אופס! המערכת לא הצליחה לזהות את דגם המכשיר או את המספר הסידורי.</translation>
 <translation id="5284445933715251131">המשך הורדה</translation>
 <translation id="5285635972691565180">הצגת <ph name="DISPLAY_ID" /></translation>
-<translation id="5286194356314741248">סורק</translation>
+<translation id="5286194356314741248">הסריקה מתבצעת</translation>
 <translation id="5286252187236914003">L2TP/IPsec</translation>
 <translation id="5287425679749926365">החשבונות שלך</translation>
 <translation id="5288678174502918605">פתיחה &amp;מחדש של הכרטיסייה שנסגרה</translation>
@@ -3723,7 +3723,7 @@
 <translation id="5372529912055771682">מצב ההרשמה שסופק אינו נתמך על ידי גרסה זו של מערכת ההפעלה. ודא שאתה מפעיל את הגרסה החדשה ביותר ונסה שוב.</translation>
 <translation id="5372579129492968947">ביטול הצמדת התוסף</translation>
 <translation id="5372659122375744710">‏רשת ה-Wi-Fi לא מאובטחת</translation>
-<translation id="5376169624176189338">לחץ כדי לחזור, לחץ והחזק כדי לראות את ההיסטוריה</translation>
+<translation id="5376169624176189338">יש ללחוץ כדי לחזור, ללחוץ ולהחזיק כדי לראות את ההיסטוריה</translation>
 <translation id="5376931455988532197">הקובץ גדול מדי</translation>
 <translation id="5377721922656071359">{COUNT,plural, =1{<ph name="ATTACHMENTS" /> נשלח בהצלחה אל <ph name="DEVICE_NAME" />}two{<ph name="ATTACHMENTS" /> נשלחו בהצלחה אל <ph name="DEVICE_NAME" />}many{<ph name="ATTACHMENTS" /> נשלחו בהצלחה אל <ph name="DEVICE_NAME" />}other{<ph name="ATTACHMENTS" /> נשלחו בהצלחה אל <ph name="DEVICE_NAME" />}}</translation>
 <translation id="537813040452600081">‏דפים שתעיין בהם בחלון זה לא יופיעו בהיסטוריה של הדפדפן, והם לא ישאירו במחשב עקבות אחרים, כגון קובצי Cookie, לאחר שתצא. קבצים שתוריד וסימניות שתיצור לא יישמרו.</translation>
@@ -3771,7 +3771,7 @@
 <translation id="543338862236136125">עריכת סיסמה</translation>
 <translation id="5434065355175441495">‏הצפנת RSA של PKCS #1</translation>
 <translation id="5435779377906857208">לאשר תמיד ל-<ph name="HOST" /> גישה למיקום</translation>
-<translation id="5436492226391861498">‏ממתין ל-Proxy Tunnel...</translation>
+<translation id="5436492226391861498">‏בהמתנה ל-Proxy Tunnel...</translation>
 <translation id="5436510242972373446">חיפוש ב-<ph name="SITE_NAME" />:</translation>
 <translation id="543806387003274181">יש לשמור את הקבצים וליצור עכשיו חשבון חדש.</translation>
 <translation id="544083962418256601">יצירת קיצורי דרך...</translation>
@@ -3825,7 +3825,7 @@
 <translation id="549211519852037402">בז' ולבן</translation>
 <translation id="5493792505296048976">מסך מופעל</translation>
 <translation id="5494362494988149300">פתח &amp;בסיום</translation>
-<translation id="5495466433285976480">פעולה זו תסיר את כל המשתמשים, הקבצים והנתונים המקומיים והגדרות מקומיות אחרות לאחר שתבצע הפעלה מחדש בפעם הבאה. כל המשתמשים יצטרכו להיכנס שוב.</translation>
+<translation id="5495466433285976480">פעולה זו תסיר את כל המשתמשים, הקבצים והנתונים המקומיים והגדרות מקומיות אחרות לאחר ביצוע של הפעלה מחדש בפעם הבאה. כל המשתמשים יצטרכו להיכנס שוב.</translation>
 <translation id="5495597166260341369">אל תכבה את הצג</translation>
 <translation id="5496587651328244253">ארגון</translation>
 <translation id="5496730470963166430">לא מורשים להציג חלונות קופצים או להשתמש בהפניות אוטומטיות</translation>
@@ -4067,7 +4067,7 @@
 <translation id="5777468213129569553">‏פתח את Chrome</translation>
 <translation id="5780011244986845107">התיקייה שבחרת מכילה קבצים רגישים. האפליקציה <ph name="APP_NAME" /> תקבל הרשאת קריאה קבועה לתיקייה הזו. להמשיך?</translation>
 <translation id="5780973441651030252">עדיפות תהליך</translation>
-<translation id="5781092003150880845">סינכרון בשם <ph name="ACCOUNT_FULL_NAME" /></translation>
+<translation id="5781092003150880845">סנכרון בשם <ph name="ACCOUNT_FULL_NAME" /></translation>
 <translation id="5781865261247219930">שליחת תגובות אל <ph name="EXTENSION_NAME" /></translation>
 <translation id="5782227691023083829">מתרגם...</translation>
 <translation id="5783602409389152506">בזמן חיפוש התקנים...</translation>
@@ -4101,7 +4101,7 @@
 <translation id="5815645614496570556">‏כתובת X.400</translation>
 <translation id="5816434091619127343">אם יבוצעו שינויי המדפסת שהתבקשו, לא ניתן יהיה להשתמש בה.</translation>
 <translation id="5817918615728894473">התאם</translation>
-<translation id="5821565227679781414">צור קיצור דרך</translation>
+<translation id="5821565227679781414">יצירת קיצור דרך</translation>
 <translation id="5825412242012995131">מופעל (מומלץ)</translation>
 <translation id="5826395379250998812">יש לחבר את ה-<ph name="DEVICE_TYPE" /> לטלפון. <ph name="LINK_BEGIN" />מידע נוסף<ph name="LINK_END" /></translation>
 <translation id="5826993284769733527">שקוף למחצה</translation>
@@ -4154,7 +4154,7 @@
 <translation id="5867841422488265304">יש להזין ביטוי לחיפוש או כתובת אינטרנט</translation>
 <translation id="5869029295770560994">בסדר, הבנתי</translation>
 <translation id="5869522115854928033">סיסמאות שמורות</translation>
-<translation id="5870086504539785141">סגור את תפריט הנגישות</translation>
+<translation id="5870086504539785141">סגירת תפריט הנגישות</translation>
 <translation id="5870129979923971752">‏חסימת רכיבי handler של תשלומים</translation>
 <translation id="5870155679953074650">שגיאות חמורות</translation>
 <translation id="5876576639916258720">התכונה פעילה…</translation>
@@ -4366,7 +4366,7 @@
 <translation id="6120205520491252677">הצמדת דף זה למסך הפתיחה...</translation>
 <translation id="6122081475643980456">החיבור שלך לאינטרנט נשלט על ידי גורם כלשהו</translation>
 <translation id="6122095009389448667">המשך חסימת הגישה של האתר הזה ללוח</translation>
-<translation id="6122191549521593678">מקוון</translation>
+<translation id="6122191549521593678">אונליין</translation>
 <translation id="6122600716821516697">לשתף עם המכשיר הזה?</translation>
 <translation id="6122831415929794347">להשבית את 'גלישה בטוחה'?</translation>
 <translation id="6122875415561139701">פעולת כתיבה אסורה במכשיר: "<ph name="DEVICE_NAME" />".</translation>
@@ -4384,7 +4384,7 @@
 <translation id="6138894911715675297"><ph name="NETWORK_TYPE" />, אין רשת</translation>
 <translation id="6141988275892716286">אישור הורדה</translation>
 <translation id="6143186082490678276">קבל עזרה</translation>
-<translation id="6144938890088808325">‏עזור לנו לשפר את מחשבי Chromebook</translation>
+<translation id="6144938890088808325">‏רוצה לעזור לנו לשפר את מחשבי Chromebook?</translation>
 <translation id="6147020289383635445">התצוגה המקדימה של ההדפסה נכשלה.</translation>
 <translation id="6148576794665275391">פתיחה עכשיו</translation>
 <translation id="6149015141270619212">לא ניתן להתחבר לאינטרנט</translation>
@@ -4425,7 +4425,7 @@
 <translation id="6195693561221576702">אי אפשר להגדיר את המכשיר הזה במצב הדגמה אופליין.</translation>
 <translation id="6196640612572343990">‏חסום קובצי Cookie של צד שלישי</translation>
 <translation id="6196854373336333322">‏התוסף "<ph name="EXTENSION_NAME" />" השתלט על הגדרות שרת ה-Proxy. פירוש הדבר שהוא יכול לשנות ולקטוע לכל פעולה שביצעת באינטרנט או לצותת לה. אם לא ידוע לך בוודאות מדוע שינוי זה התרחש, סביר להניח שזהו שינוי לא רצוי.</translation>
-<translation id="6198102561359457428">צא והיכנס שוב...</translation>
+<translation id="6198102561359457428">יש לצאת ולהיכנס שוב...</translation>
 <translation id="6198252989419008588">‏שנה PIN</translation>
 <translation id="6202304368170870640">קוד האימות מאפשר להיכנס למכשיר או לבטל את נעילתו.</translation>
 <translation id="6206311232642889873">העת&amp;קת תמונה</translation>
@@ -4683,7 +4683,7 @@
 <translation id="6497457470714179223">{NUM_FILES,plural, =0{הנתונים האלה מכילים תוכן רגיש או מסוכן}=1{הקובץ הזה מכיל תוכן רגיש או מסוכן}two{הקבצים האלה מכילים תוכן רגיש או מסוכן}many{הקבצים האלה מכילים תוכן רגיש או מסוכן}other{הקבצים האלה מכילים תוכן רגיש או מסוכן}}</translation>
 <translation id="6497789971060331894">גלילה הפוכה עם העכבר</translation>
 <translation id="6498249116389603658">&amp;כל השפות שלך</translation>
-<translation id="6499143127267478107">‏מברר כתובת של שרת מארח בסקריפט של שרת Proxy...</translation>
+<translation id="6499143127267478107">‏הבירור של כתובת של שרת מארח בסקריפט של שרת Proxy מתבצע...</translation>
 <translation id="6499681088828539489">‏ביטול הרשאה של שרתי proxy לרשתות משותפות</translation>
 <translation id="650266656685499220">‏כדי ליצור אלבומים, יש לעבור לתמונות Google</translation>
 <translation id="6503077044568424649">הכי פופולריים</translation>
@@ -4723,7 +4723,7 @@
 <translation id="6545665334409411530">שיעור חזרה</translation>
 <translation id="6545864417968258051">‏סריקת Bluetooth</translation>
 <translation id="6545867563032584178">‏המיקרופון מושבת בהעדפות המערכת של Mac</translation>
-<translation id="6547354035488017500">‏עליך לפנות ‎512 MB לפחות משטח האחסון במכשיר, אחרת הוא יפסיק להגיב. כדי לפנות שטח אחסון, מחק קבצים מאחסון המכשיר.</translation>
+<translation id="6547354035488017500">‏עליך לפנות ‎512MB לפחות מנפח האחסון במכשיר, אחרת הוא יפסיק להגיב. כדי לפנות נפח אחסון, יש למחוק קבצים מאחסון המכשיר.</translation>
 <translation id="654871471440386944">להפעיל את הגלישה באמצעות סמן הטקסט?</translation>
 <translation id="6550675742724504774">אפשרויות</translation>
 <translation id="6551508934388063976">‏הפקודה לא זמינה. הקש על Control-N לפתיחת חלון חדש.</translation>
@@ -4795,7 +4795,7 @@
 <translation id="6643016212128521049">ניקוי</translation>
 <translation id="6644512095122093795">תופיע הצעה לשמור סיסמאות</translation>
 <translation id="6644513150317163574">‏פורמט כתובת URL לא חוקי יש לציין את השרת כשם מארח כאשר נעשה שימוש באימות SSO.</translation>
-<translation id="6644846457769259194">מעדכן את המכשיר שלך (<ph name="PROGRESS_PERCENT" />)</translation>
+<translation id="6644846457769259194">עדכון המכשיר שלך מתבצע (<ph name="PROGRESS_PERCENT" />)</translation>
 <translation id="6645437135153136856">‏מכשיר Google Cloud Print שבחרת כבר לא נתמך. <ph name="BR" /> אפשר לנסות להגדיר את המדפסת דרך הגדרות המערכת של המחשב.</translation>
 <translation id="6647228709620733774">‏כתובת אתר לביטול של רשות אישורי Netscape</translation>
 <translation id="6647838571840953560">עכשיו בערוץ <ph name="CHANNEL_NAME" /></translation>
@@ -4814,7 +4814,7 @@
 <translation id="6659213950629089752">בדף זה בוצע שינוי במרחק התצוגה באמצעות התוסף "<ph name="NAME" />"</translation>
 <translation id="6659594942844771486">כרטיסייה</translation>
 <translation id="6664237456442406323">‏לצערנו, המחשב שלך מוגדר עם זיהוי חומרה פגום. המצב הזה מונע ממערכת ההפעלה של Chrome להתקין את עדכוני האבטחה האחרונים, וייתכן שהמחשב שלך יהיה <ph name="BEGIN_BOLD" />חשוף להתקפות זדוניות<ph name="END_BOLD" />.</translation>
-<translation id="6664774537677393800">משהו השתבש בפתיחת הפרופיל שלך. צא ולאחר מכן היכנס מחדש.</translation>
+<translation id="6664774537677393800">משהו השתבש בפתיחת הפרופיל שלך. יש לצאת ולאחר מכן להיכנס מחדש.</translation>
 <translation id="6670142487971298264">האפליקציה <ph name="APP_NAME" /> זמינה עכשיו</translation>
 <translation id="6673391612973410118"><ph name="PRINTER_MAKE_OR_MODEL" /> (USB)</translation>
 <translation id="6675665718701918026">התקן הצבעה מחובר</translation>
@@ -4824,7 +4824,7 @@
 <translation id="6680650203439190394">קצב</translation>
 <translation id="6681668084120808868">צלם תמונה</translation>
 <translation id="6684827949542560880">המערכת מורידה את העדכון האחרון</translation>
-<translation id="668599234725812620">‏פתח את Google Play</translation>
+<translation id="668599234725812620">‏פתיחת Google Play</translation>
 <translation id="6686490380836145850">סגירת הכרטיסיות משמאל</translation>
 <translation id="6686817083349815241">שמור את הסיסמה שלך</translation>
 <translation id="6688285987813868112">‏יצירת קוד QR לתמונה הזו</translation>
@@ -4996,7 +4996,7 @@
 <translation id="6883319974225028188">אופס! המערכת לא הצליחה לשמור את תצורת המכשיר.</translation>
 <translation id="6885771755599377173">תצוגה מקדימה של מידע מערכת</translation>
 <translation id="6886476658664859389">‏מפתח אבטחה מסוג NFC</translation>
-<translation id="6886871292305414135">פתח קישור &amp;בכרטיסייה חדשה</translation>
+<translation id="6886871292305414135">פתיחת קישור &amp;בכרטיסייה חדשה</translation>
 <translation id="6892812721183419409">פתח קישור בתור <ph name="USER" /></translation>
 <translation id="6895032998810961280">‏שליחת דיווח מפורט ל-Google על תוכנה, הגדרות מערכת ותהליכים מזיקים שנמצאו במחשב שלך במהלך הניקוי הזה</translation>
 <translation id="6896758677409633944">העתק</translation>
@@ -5220,12 +5220,12 @@
 <translation id="7136694880210472378">הפוך לברירת מחדל</translation>
 <translation id="7136984461011502314">ברוך הבא ל-<ph name="PRODUCT_NAME" /></translation>
 <translation id="7136993520339022828">קרתה שגיאה. יש לנסות שוב על-ידי בחירת תמונות אחרות.</translation>
-<translation id="713888829801648570">מצטערים, לא ניתן לאמת את סיסמתך מכיוון שאתה במצב לא מקוון.</translation>
+<translation id="713888829801648570">מצטערים, לא ניתן לאמת את סיסמתך מכיוון שאין לך חיבור לאינטרנט.</translation>
 <translation id="7139627972753429585">המיקרופון בשימוש על ידי <ph name="APP_NAME" /></translation>
 <translation id="7140928199327930795">אין מכשירים זמינים נוספים.</translation>
 <translation id="7141105143012495934">הכניסה נכשלה מפני שלא ניתן היה לאחזר את פרטי החשבון. יש ליצור קשר עם מנהל המערכת או לנסות שוב.</translation>
 <translation id="7143207342074048698">מתבצע חיבור</translation>
-<translation id="7144878232160441200">נסה שוב</translation>
+<translation id="7144878232160441200">יש לנסות שוב</translation>
 <translation id="714876143603641390">‏קישוריות LAN</translation>
 <translation id="7149893636342594995">מהיום האחרון</translation>
 <translation id="715118844758971915">מדפסות קלאסיות</translation>
@@ -5235,7 +5235,7 @@
 <translation id="7165320105431587207">כשל בהגדרת התצורה של הרשת</translation>
 <translation id="716640248772308851">"<ph name="EXTENSION" />" יכול לקרוא קובצי תמונות, וידאו ואודיו במיקומים המסומנים.</translation>
 <translation id="7167486101654761064">&amp;פתח תמיד קבצים מסוג זה</translation>
-<translation id="716810439572026343">מוריד את <ph name="FILE_NAME" /></translation>
+<translation id="716810439572026343">הורדת <ph name="FILE_NAME" /> מתבצעת</translation>
 <translation id="7168109975831002660">גודל גופן מינימלי</translation>
 <translation id="7170041865419449892">מחוץ לטווח</translation>
 <translation id="7170236477717446850">תמונת פרופיל</translation>
@@ -5268,7 +5268,7 @@
 <translation id="7201118060536064622">הפריט '<ph name="DELETED_ITEM_NAME" />' נמחק</translation>
 <translation id="7201420661433230412">הצג קבצים</translation>
 <translation id="7203150201908454328">מורחב</translation>
-<translation id="7206693748120342859">מוריד את <ph name="PLUGIN_NAME" />...</translation>
+<translation id="7206693748120342859">הורדת <ph name="PLUGIN_NAME" /> מתבצעת...</translation>
 <translation id="720715819012336933">{NUM_PAGES,plural, =1{יציאה מהדף}two{יציאה מהדפים}many{יציאה מהדפים}other{יציאה מהדפים}}</translation>
 <translation id="7207457272187520234">‏שליחת מידע לגבי אופן השימוש בנתונים וניתוח הביצועים. המכשיר הזה שולח עכשיו אל Google באופן אוטומטי נתוני אבחון, נתוני מכשיר ונתוני שימוש באפליקציות. הנתונים האלה יעזרו לשמור על היציבות של המערכת ושל האפליקציות ולבצע שיפורים אחרים. חלק מהנתונים הנצברים יעזרו גם לשפר את האפליקציות של Google וכן יעזרו לשותפים של Google, כמו מפתחים של Android. ההגדרה הזו נאכפת על-ידי הבעלים. אם הופעלה ההגדרה 'פעילות באתרי אינטרנט ובאפליקציות נוספים', ייתכן שהנתונים יישמרו בחשבון Google שלך.</translation>
 <translation id="7207631048330366454">חיפוש אפליקציות</translation>
@@ -5410,7 +5410,7 @@
 <translation id="7376553024552204454">הדגש את סמן העכבר כשהסמן בתנועה</translation>
 <translation id="7377451353532943397">המשך חסימת הגישה לחיישנים</translation>
 <translation id="7378611153938412599">קל לנחש סיסמאות חלשות. חשוב להגדיר סיסמאות חזקות. <ph name="BEGIN_LINK" />לטיפים נוספים לגבי אבטחה.<ph name="END_LINK" /></translation>
-<translation id="73786666777299047">‏פתח את חנות האינטרנט של Chrome</translation>
+<translation id="73786666777299047">‏פתיחת חנות האינטרנט של Chrome</translation>
 <translation id="7378812711085314936">קבל חיבור נתונים</translation>
 <translation id="7380622428988553498">שם המכשיר מכיל תווים לא חוקיים</translation>
 <translation id="7380768571499464492"><ph name="PRINTER_NAME" /> עודכנה</translation>
@@ -5564,11 +5564,11 @@
 <translation id="7557194624273628371">‏העברה ליציאה אחרת ב-Linux</translation>
 <translation id="7559719679815339381">המתן....מתבצע עדכון של אפליקצית הקיוסק. אל תסיר את הדיסק און קי.</translation>
 <translation id="7561196759112975576">תמיד</translation>
-<translation id="756445078718366910">פתח חלון דפדפן</translation>
+<translation id="756445078718366910">פתיחת חלון דפדפן</translation>
 <translation id="7564847347806291057">סיום התהליך</translation>
 <translation id="7566118625369982896">‏ניהול קישורים של אפליקציות מ-Play</translation>
 <translation id="756809126120519699">‏נתוני Chrome נוקו</translation>
-<translation id="7568790562536448087">מעדכן</translation>
+<translation id="7568790562536448087">העדכון מתבצע</translation>
 <translation id="7569983096843329377">שחור</translation>
 <translation id="7571643774869182231">אין מספיק שטח אחסון לעדכון</translation>
 <translation id="7573172247376861652">טעינת סוללה</translation>
@@ -5689,7 +5689,7 @@
 <translation id="7702907602086592255">דומיין</translation>
 <translation id="7704305437604973648">משימה</translation>
 <translation id="7704317875155739195">השלמה אוטומטית של חיפושים וכתובות אתרים</translation>
-<translation id="7704521324619958564">‏פתח את Play Store</translation>
+<translation id="7704521324619958564">‏פתיחת Play Store</translation>
 <translation id="7705276765467986571">לא ניתן להעלות דגם סימניה.</translation>
 <translation id="7705524343798198388">VPN</translation>
 <translation id="7707108266051544351">גישת האתר הזה אל חיישני התנועה נחסמה.</translation>
@@ -5701,7 +5701,7 @@
 <translation id="7714464543167945231">אישור</translation>
 <translation id="7716648931428307506">יש לבחור היכן לשמור את הסיסמאות</translation>
 <translation id="7716781361494605745">‏כתובת אתר של מדיניות רשות אישורים של Netscape</translation>
-<translation id="7717014941119698257">מוריד: <ph name="STATUS" /></translation>
+<translation id="7717014941119698257">הורדה: <ph name="STATUS" /></translation>
 <translation id="7717134585801378441">אתרים יכולים לבקש את מיקום המכשיר (מומלץ)</translation>
 <translation id="7717845620320228976">חיפוש עדכונים</translation>
 <translation id="7719367874908701697">מרחק מתצוגה בדף</translation>
@@ -5897,7 +5897,7 @@
 <translation id="7924358170328001543">שגיאה בהעברת היציאה</translation>
 <translation id="792514962475806987">רמת זום במצב מעוגן:</translation>
 <translation id="7925247922861151263">‏בדיקת AAA נכשלה</translation>
-<translation id="7925285046818567682">ממתין ל- <ph name="HOST_NAME" />...</translation>
+<translation id="7925285046818567682">בהמתנה ל-<ph name="HOST_NAME" />...</translation>
 <translation id="7926423016278357561">זה לא הייתי אני.</translation>
 <translation id="7926975587469166629">כינוי הכרטיס</translation>
 <translation id="7928175190925744466">כבר שינית את הסיסמה הזו?</translation>
@@ -5929,7 +5929,7 @@
 <translation id="7953955868932471628">ניהול קיצורי דרך</translation>
 <translation id="7956373551960864128">מדפסות שמורות</translation>
 <translation id="7957074856830851026">הצגה של פרטי המכשיר, כמו המספר הסידורי או מזהה הנכס שלו</translation>
-<translation id="7957615753207896812">פתח את הגדרות המכשיר של המקלדת</translation>
+<translation id="7957615753207896812">פתיחת הגדרות המכשיר של המקלדת</translation>
 <translation id="7959074893852789871">הקובץ הכיל אישורים מרובים, חלקם לא יובאו:</translation>
 <translation id="7961015016161918242">אף פעם</translation>
 <translation id="7963001036288347286">האצת לוח מגע</translation>
@@ -6069,7 +6069,7 @@
 <translation id="8102139037507939978">‏הסרה של פרטים אישיים מזהים מהקובץ system_logs.txt.</translation>
 <translation id="8102159139658438129">כדי לראות אפשרויות לגבי הטלפון המחובר, אפשר לעבור אל <ph name="LINK_BEGIN" />הגדרות<ph name="LINK_END" /></translation>
 <translation id="8104696615244072556">‏בצע פעולת Powerwash במכשיר <ph name="IDS_SHORT_PRODUCT_NAME" /> שלך וחזור לגרסה הקודמת.</translation>
-<translation id="8107015733319732394">‏מתקין את חנות Google Play במכשיר <ph name="DEVICE_TYPE" />. ייתכן שההתקנה תימשך כמה דקות.</translation>
+<translation id="8107015733319732394">‏ההתקנה של חנות Google Play במכשיר <ph name="DEVICE_TYPE" /> מתבצעת. ייתכן שההתקנה תימשך כמה דקות.</translation>
 <translation id="810728361871746125">רזולוציית מסך</translation>
 <translation id="8108526232944491552">{COUNT,plural, =0{‏אין קובצי cookie של צד שלישי}=1{‏קובץ cookie אחד של צד שלישי נחסם}two{‏# קובצי cookie של צד שלישי נחסמו}many{‏# קובצי cookie של צד שלישי נחסמו}other{‏# קובצי cookie של צד שלישי נחסמו}}</translation>
 <translation id="810875025413331850">לא נמצאו מכשירים קרובים.</translation>
@@ -6082,7 +6082,7 @@
 <translation id="8118362518458010043">‏הושבת על-ידי Chrome. ייתכן שהתוסף הזה לא בטוח.</translation>
 <translation id="8118488170956489476">ה<ph name="BEGIN_LINK" />דפדפן מנוהל<ph name="END_LINK" /> על-ידי הארגון שלך</translation>
 <translation id="8118515372935001629">קצב הרענון של המסך</translation>
-<translation id="8118860139461251237">לנהל את ההורדות שלך</translation>
+<translation id="8118860139461251237">ניהול ההורדות שלך</translation>
 <translation id="811942868379260654"><ph name="RECENT_PERMISSIONS_CHANGE_SENTENCE_START" />, <ph name="RECENT_PERMISSIONS_CHANGE_1" />, <ph name="RECENT_PERMISSIONS_CHANGE_2" /> והרשאות נוספות</translation>
 <translation id="8119438628456698432">יוצר קובצי יומן...</translation>
 <translation id="811994229154425014">רווח כפול להקלדת נקודה</translation>
@@ -6187,7 +6187,7 @@
 <translation id="8251441930213048644">יש לרענן עכשיו</translation>
 <translation id="8251578425305135684">התמונה הממוזערת הוסרה.</translation>
 <translation id="825238165904109940">‏הצגה של כתובות URL מלאות בכל המקרים</translation>
-<translation id="8252569384384439529">מעלה...</translation>
+<translation id="8252569384384439529">ההעלאה מתבצעת...</translation>
 <translation id="8253198102038551905">יש ללחוץ על '+' כדי לקבל מאפייני רשת</translation>
 <translation id="8254954272268479918">‏כיבוי של Linux (בטא)</translation>
 <translation id="8255451560461371599">ללא רקע</translation>
@@ -6412,7 +6412,7 @@
 <translation id="8525306231823319788">מסך מלא</translation>
 <translation id="8526666462501866815">‏השדרוג של Linux בוטל</translation>
 <translation id="8528074251912154910">הוספת שפות</translation>
-<translation id="8528962588711550376">מבצע כניסה.</translation>
+<translation id="8528962588711550376">תהליך הכניסה מתבצע.</translation>
 <translation id="8529925957403338845">יצירת החיבור לשיתוף אינטרנט מיידי בין ניידים נכשלה</translation>
 <translation id="8534656636775144800">אופס! משהו השתבש כשניסינו לצרף את הדומיין. יש לנסות שוב.</translation>
 <translation id="8535005006684281994">‏כתובת אתר לחידוש אישור Netscape</translation>
@@ -6453,7 +6453,7 @@
 <translation id="8576249514688522074">לא מאותחלת</translation>
 <translation id="8578639784464423491">המגבלה היא 99 אותיות</translation>
 <translation id="857943718398505171">מותרת (מומלץ)</translation>
-<translation id="8581809080475256101">לחץ כדי להתקדם, תפריט הקשר כדי לראות את ההיסטוריה</translation>
+<translation id="8581809080475256101">יש ללחוץ כדי להתקדם, תפריט הקשר כדי לראות את ההיסטוריה</translation>
 <translation id="8584280235376696778">פתיחת וידאו בכרטיסייה חדשה</translation>
 <translation id="8584427708066927472">הסיסמה נמחקה מהמכשיר הזה</translation>
 <translation id="8585480574870650651">‏הסרה של Crostini</translation>
@@ -6626,7 +6626,7 @@
 <translation id="87646919272181953">‏אלבום של תמונות Google</translation>
 <translation id="8767621466733104912">‏עדכון אוטומטי של Chrome אצל כל המשתמשים</translation>
 <translation id="8770406935328356739">ספריית הבסיס של תוסף</translation>
-<translation id="8770507190024617908">נהל אנשים</translation>
+<translation id="8770507190024617908">ניהול אנשים</translation>
 <translation id="8771300903067484968">רקע דף הפתיחה עבר איפוס לרקע ברירת המחדל.</translation>
 <translation id="8773302562181397928">שמירת <ph name="PRINTER_NAME" /></translation>
 <translation id="8774379074441005279">אישור השחזור</translation>
@@ -6795,7 +6795,7 @@
 <translation id="8951465597020890363">לצאת בכל זאת ממצב אורח?</translation>
 <translation id="8952831374766033534">אפשרות ההגדרה לא נתמכת: <ph name="ERROR_LINE" /></translation>
 <translation id="8953476467359856141">בזמן טעינה</translation>
-<translation id="895347679606913382">מתחיל...</translation>
+<translation id="895347679606913382">הפעולה מתחילה...</translation>
 <translation id="895944840846194039">‏זיכרון JavaScript</translation>
 <translation id="8962083179518285172">הסתרת פרטים</translation>
 <translation id="8962918469425892674">האתר הזה משתמש בחיישני תנועה או תאורה.</translation>
@@ -6902,10 +6902,10 @@
 <translation id="9074739597929991885">Bluetooth</translation>
 <translation id="9074836595010225693">‏עכבר USB מחובר</translation>
 <translation id="9076283476770535406">ייתכן שהאתר מכיל תוכן למבוגרים בלבד</translation>
-<translation id="9076523132036239772">מצטערים, לא ניתן לאמת את האימייל או הסיסמה שלך. נסה תחילה להתחבר לרשת.</translation>
+<translation id="9076523132036239772">מצטערים, לא ניתן לאמת את האימייל או הסיסמה שלך. יש לנסות תחילה להתחבר לרשת.</translation>
 <translation id="9076977315710973122">‏שיתוף באמצעות SMB</translation>
 <translation id="9078316009970372699">השבתה של שיתוף אינטרנט מיידי בין מכשירים</translation>
-<translation id="9084064520949870008">פתח כחלון</translation>
+<translation id="9084064520949870008">פתיחה כחלון</translation>
 <translation id="9085256200913095638">שכפול הכרטיסייה שנבחרה</translation>
 <translation id="9085776959277692427"><ph name="LANGUAGE" /> לא נבחרה. כדי לבחור, יש ללחוץ על 'חיפוש' ועל מקש הרווח.</translation>
 <translation id="9087949559523851360">הוספת משתמש בעל הרשאות מוגבלות</translation>
diff --git a/chrome/app/resources/generated_resources_mk.xtb b/chrome/app/resources/generated_resources_mk.xtb
index cb80652b..5900cb68 100644
--- a/chrome/app/resources/generated_resources_mk.xtb
+++ b/chrome/app/resources/generated_resources_mk.xtb
@@ -3704,7 +3704,7 @@
 <translation id="5341980496415249280">Почекајте. Се пакува…</translation>
 <translation id="5342091991439452114">PIN-кодот мора да содржи најмалку <ph name="MINIMUM" /> цифри</translation>
 <translation id="5344036115151554031">Се враќа Linux</translation>
-<translation id="5345916423802287046">Стартувај ја апликацијата која ќе се најавам</translation>
+<translation id="5345916423802287046">Стартувај ја апликацијата кога ќе се најавам</translation>
 <translation id="5350293332385664455">Исклучување на „Помошникот на Google“</translation>
 <translation id="535123479159372765">Текст копиран од друг уред</translation>
 <translation id="5352033265844765294">Временско означување</translation>
@@ -4178,7 +4178,7 @@
 <translation id="5904614460720589786">Не можеше да се постави <ph name="APP_NAME" /> поради конфигурациски проблем. Контактирајте со администраторот. Код за грешка: <ph name="ERROR_CODE" />.</translation>
 <translation id="5906655207909574370">Речиси ажурирано! Рестартирајте го уредот за да се заврши ажурирањето.</translation>
 <translation id="5906732635754427568">Податоците поврзани со оваа апликација ќе бидат отстранети од уредов.</translation>
-<translation id="5908474332780919512">Стартувај ја апликацијата која ќе се најавам</translation>
+<translation id="5908474332780919512">Стартувај ја апликацијата кога ќе се најавам</translation>
 <translation id="5908695239556627796">Брзина на лизгање на глувчето</translation>
 <translation id="5908769186679515905">Блокирајте страниците да пуштаат Flash</translation>
 <translation id="5910363049092958439">Сни&amp;ми слика како…</translation>
diff --git a/chrome/app/resources/generated_resources_or.xtb b/chrome/app/resources/generated_resources_or.xtb
index d32c7a06..96c37ee0 100644
--- a/chrome/app/resources/generated_resources_or.xtb
+++ b/chrome/app/resources/generated_resources_or.xtb
@@ -17,6 +17,7 @@
 <translation id="1012794136286421601">ଆପଣଙ୍କର ଡକ୍, ସୀଟ୍, ସ୍ଳାଇଡ୍, ଏବଂ ଡ୍ରଇଂ ଫାଇଲ୍‌ଗୁଡ଼ିକ ସିଙ୍କ୍ କରାଯାଉଛି। Google ଡ୍ରାଇଭ୍‍ ଆପ୍‍କୁ ଅନ୍‌ଲାଇନ୍ ବା ଅଫ୍‌ଲାଇନ୍ ଆକ୍ସେସ୍ କରିବା ପାଇଁ ଖୋଲନ୍ତୁ।</translation>
 <translation id="1012876632442809908">USB-C ଡିଭାଇସ୍ (ସାମ୍‌ନା ପୋର୍ଟ)</translation>
 <translation id="1013707859758800957">ଏକ unsandboxed ପ୍ଲଗଇନ୍‍କୁ ଏହି ପୃଷ୍ଠାରେ ଚଲାଇବାକୁ ଅନୁମତି ଦିଆଯାଇଛି।</translation>
+<translation id="1015041505466489552">TrackPoint</translation>
 <translation id="1015318665228971643">ଫୋଲ୍ଡର ନାମ ଏଡିଟ୍ କରନ୍ତୁ</translation>
 <translation id="1015578595646638936">{NUM_DAYS,plural, =1{<ph name="DEVICE_TYPE" />କୁ ଅପଡେଟ୍ କରିବାର ଶେଷ ଦିନ}other{{NUM_DAYS} ଦିନ ଭିତରେ <ph name="DEVICE_TYPE" />କୁ ଅପଡେଟ୍ କରନ୍ତୁ}}</translation>
 <translation id="1016566241875885511">ଅତିରିକ୍ତ ସୂଚନା (ଇଚ୍ଛାଧୀନ)</translation>
diff --git a/chrome/app/resources/generated_resources_pa.xtb b/chrome/app/resources/generated_resources_pa.xtb
index c9959e4..7bec3d8 100644
--- a/chrome/app/resources/generated_resources_pa.xtb
+++ b/chrome/app/resources/generated_resources_pa.xtb
@@ -277,7 +277,7 @@
 <translation id="1313705515580255288">ਤੁਹਾਡੇ ਬੁੱਕਮਾਰਕ, ਇਤਿਹਾਸ ਅਤੇ ਹੋਰ ਸੈਟਿੰਗਾਂ ਨੂੰ ਤੁਹਾਡੇ Google ਖਾਤੇ 'ਤੇ ਸਿੰਕ ਕੀਤਾ ਜਾਵੇਗਾ।</translation>
 <translation id="1314565355471455267">Android VPN</translation>
 <translation id="131461803491198646">ਘਰੇਲੂ ਨੈੱਟਵਰਕ, ਰੋਮਿੰਗ ਨਹੀਂ</translation>
-<translation id="1315056510003830387">ਫਲੈਸ਼ ਦੀ ਵਰਤੋਂ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ</translation>
+<translation id="1315056510003830387">Flash ਦੀ ਵਰਤੋਂ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ</translation>
 <translation id="1316136264406804862">ਖੋਜ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ...</translation>
 <translation id="1316495628809031177">ਸਮਕਾਲੀਕਰਨ ਰੋਕਿਆ ਗਿਆ</translation>
 <translation id="1317637799698924700">ਤੁਹਾਡਾ ਡੌਕਿੰਗ ਸਟੇਸ਼ਨ USB ਪ੍ਰਕਾਰ-C ਅਨੁਰੂਪਤਾ ਮੋਡ ਵਿੱਚ ਕੰਮ ਕਰੇਗਾ।</translation>
@@ -957,7 +957,7 @@
 <translation id="2090165459409185032">ਆਪਣੀ ਖਾਤਾ ਜਾਣਕਾਰੀ ਨੂੰ ਰਿਕਵਰ ਕਰਨ ਲਈ, ਇੱਥੇ ਜਾਓ: google.com/accounts/recovery</translation>
 <translation id="2090876986345970080">ਸਿਸਟਮ ਸੁਰੱਖਿਆ ਸੈਟਿੰਗਾ</translation>
 <translation id="2091887806945687916">ਧੁਨੀ</translation>
-<translation id="209539936453343974">ਮਾਪਿਆਂ ਦੇ ਕੰਟਰੋਲ ਦਾ ਸੈੱਟਅੱਪ ਕਰਨ ਲਈ, ਬੱਚੇ ਕੋਲ ਅਜਿਹਾ Google ਖਾਤਾ ਹੋਣਾ ਲਾਜ਼ਮੀ ਹੈ ਜਿਸਦਾ ਪ੍ਰਬੰਧਨ ਮਾਂ-ਪਿਓ ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। <ph name="DEVICE_TYPE_PLURAL" /> ਮਾਪਿਆਂ ਨੂੰ Family Link ਐਪ ਨਾਲ ਸਕ੍ਰੀਨ ਸਮਾਂ ਸੀਮਾਵਾਂ ਨੂੰ ਸੈੱਟ ਕਰਨ, ਵੈੱਬਸਾਈਟਾਂ ਨੂੰ ਮਨਜ਼ੂਰ ਜਾਂ ਬਲਾਕ ਕਰਨ ਅਤੇ ਹੋਰ ਬਹੁਤ ਕੁਝ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿੰਦੀਆਂ ਹਨ। ਜੇ ਬੱਚੇ ਨੂੰ Google Classroom ਵਰਗੀਆਂ ਸਾਈਟਾਂ 'ਤੇ ਸਕੂਲ ਦਾ ਕੰਮ ਕਰਨ ਦੀ ਲੋੜ ਹੈ, ਤਾਂ ਬਾਅਦ ਵਿੱਚ ਸਕੂਲ ਖਾਤਾ ਸ਼ਾਮਲ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।</translation>
+<translation id="209539936453343974">ਮਾਪਿਆਂ ਦੇ ਕੰਟਰੋਲ ਦਾ ਸੈੱਟਅੱਪ ਕਰਨ ਲਈ, ਬੱਚੇ ਕੋਲ ਅਜਿਹਾ Google ਖਾਤਾ ਹੋਣਾ ਲਾਜ਼ਮੀ ਹੈ ਜਿਸਦਾ ਪ੍ਰਬੰਧਨ ਮਾਂ-ਪਿਓ ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੋਵੇ। <ph name="DEVICE_TYPE_PLURAL" /> ਮਾਪਿਆਂ ਨੂੰ Family Link ਐਪ ਨਾਲ ਸਕ੍ਰੀਨ ਸਮਾਂ ਸੀਮਾਵਾਂ ਨੂੰ ਸੈੱਟ ਕਰਨ, ਵੈੱਬਸਾਈਟਾਂ ਨੂੰ ਮਨਜ਼ੂਰ ਜਾਂ ਬਲਾਕ ਕਰਨ ਅਤੇ ਹੋਰ ਬਹੁਤ ਕੁਝ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿੰਦੀਆਂ ਹਨ। ਜੇ ਬੱਚੇ ਨੂੰ Google Classroom ਵਰਗੀਆਂ ਸਾਈਟਾਂ 'ਤੇ ਸਕੂਲ ਦਾ ਕੰਮ ਕਰਨ ਦੀ ਲੋੜ ਹੈ, ਤਾਂ ਬਾਅਦ ਵਿੱਚ ਸਕੂਲ ਖਾਤਾ ਸ਼ਾਮਲ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।</translation>
 <translation id="2096715839409389970">ਤੀਜੀ-ਧਿਰ ਦੀਆਂ ਕੁਕੀਜ਼ ਕਲੀਅਰ ਕਰੋ</translation>
 <translation id="2097372108957554726">ਤੁਹਾਨੂੰ ਨਵੇਂ ਡੀਵਾਈਸਾਂ ਨੂੰ ਰਜਿਸਟਰ ਕਰਨ ਲਈ Chrome 'ਤੇ ਸਾਈਨ-ਇਨ ਕਰਨ ਦੀ ਲੋੜ ਹੈ</translation>
 <translation id="2098805196501063469">ਬਾਕੀ ਬਚੇ ਪਾਸਵਰਡਾਂ ਦੀ ਜਾਂਚ ਕਰੋ</translation>
@@ -1645,7 +1645,7 @@
 <translation id="2880660355386638022">ਵਿੰਡੋ ਪਲੇਸਮੈਂਟ</translation>
 <translation id="2881076733170862447">ਜਦੋਂ ਤੁਸੀਂ ਐਕਸਟੈਂਸ਼ਨ 'ਤੇ ਕਲਿੱਕ ਕਰਦੇ ਹੋ</translation>
 <translation id="2882943222317434580"><ph name="IDS_SHORT_PRODUCT_NAME" /> ਰੀਸਟਾਰਟ ਹੋਵੇਗਾ ਅਤੇ ਅਸਥਾਈ ਤੌਰ ਤੇ ਰੀਸੈਟ ਕਰੇਗਾ।</translation>
-<translation id="288387288628762616">ਫਲੈਸ਼ ਦੀ ਵਰਤੋਂ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਹੈ</translation>
+<translation id="288387288628762616">Flash ਦੀ ਵਰਤੋਂ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਹੈ</translation>
 <translation id="2885378588091291677">ਕੰਮ ਪ੍ਰਬੰਧਕ</translation>
 <translation id="2885729872133513017">ਸਰਵਰ ਦੇ ਜਵਾਬ ਨੂੰ ਡੀਕੋਡ ਕਰਨ ਵੇਲੇ ਕੋਈ ਸਮੱਸਿਆ ਆਈ।</translation>
 <translation id="2886771036282400576">• <ph name="PERMISSION" /></translation>
@@ -3827,7 +3827,7 @@
 <translation id="5495466433285976480">ਇੰਝ ਕਰਨ ਨਾਲ ਅਗਲੀ ਵਾਰ ਸਿਸਟਮ ਮੁੜ-ਸ਼ੁਰੂ ਕਰਨ ਤੋਂ ਬਾਅਦ ਸਾਰੇ ਸਥਾਨਕ ਵਰਤੋਂਕਾਰਾਂ, ਫ਼ਾਈਲਾਂ, ਡਾਟੇ ਅਤੇ ਹੋਰ ਸੈਟਿੰਗਾਂ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ। ਸਾਰੇ ਵਰਤੋਂਕਾਰਾਂ ਨੂੰ ਦੁਬਾਰਾ ਸਾਈਨ-ਇਨ ਕਰਨ ਦੀ ਲੋੜ ਪਵੇਗੀ।</translation>
 <translation id="5495597166260341369">ਡਿਸਪਲੇ ਚਾਲੂ ਰੱਖੋ</translation>
 <translation id="5496587651328244253">ਪ੍ਰਬੰਧ ਕਰੋ</translation>
-<translation id="5496730470963166430">ਪੌਪ-ਅੱਪ ਭੇਜਣ ਜਾਂ ਰੀਡਾਇਰੈਕਟ ਵਰਤਣ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ</translation>
+<translation id="5496730470963166430">ਪੌਪ-ਅੱਪ ਭੇਜਣ ਜਾਂ ਰੀਡਾਇਰੈਕਟ ਵਰਤਣ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ</translation>
 <translation id="5497251278400702716">ਇਹ ਫ਼ਾਈਲ</translation>
 <translation id="5498967291577176373">ਤੁਹਾਡੇ ਨਾਮ, ਪਤੇ ਜਾਂ ਫ਼ੋਨ ਨੰਬਰ ਲਈ ਇਨਲਾਈਨ ਸੁਝਾਵਾਂ ਨਾਲ ਵਧੇਰੇ ਤੇਜ਼ੀ ਨਾਲ ਲਿਖੋ</translation>
 <translation id="5499313591153584299">ਇਹ ਫ਼ਾਈਲ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਹਾਨੀਕਾਰਕ ਹੋ ਸਕਦੀ ਹੈ।</translation>
@@ -4046,7 +4046,7 @@
 <translation id="5747552184818312860">ਮਿਆਦ ਸਮਾਪਤ ਹੁੰਦੀ ਹੈ</translation>
 <translation id="5747785204778348146">ਵਿਕਾਸਕਾਰ - ਅਸਥਿਰ</translation>
 <translation id="5747809636523347288"><ph name="URL" /> ਪੇਸਟ ਕਰਕੇ ਉਸ 'ਤੇ ਜਾਓ</translation>
-<translation id="5754152670305761216">ਸੁਰੱਖਿਆ ਸਮੱਗਰੀ ਚਲਾਉਣ ਦੀ ਇਜਾਜ਼ਤ ਹੈ</translation>
+<translation id="5754152670305761216">ਸੁਰੱਖਿਅਤ ਸਮੱਗਰੀ ਚਲਾਉਣ ਦੀ ਇਜਾਜ਼ਤ ਹੈ</translation>
 <translation id="5756163054456765343">ਸ&amp;ਹਾਇਤਾ ਕੇਂਦਰ</translation>
 <translation id="5759728514498647443">ਜੋ ਦਸਤਾਵੇਜ਼ ਤੁਸੀਂ ਪ੍ਰਿੰਟ ਕਰਨ ਲਈ <ph name="APP_NAME" /> ਰਾਹੀਂ ਭੇਜਦੇ ਹੋ, ਉਹ <ph name="APP_NAME" /> ਵੱਲੋਂ ਪੜ੍ਹੇ ਜਾ ਸਕਦੇ ਹਨ।</translation>
 <translation id="5763751966069581670">ਕੋਈ USB ਡੀਵਾਈਸਾਂ ਨਹੀਂ ਮਿਲੀਆਂ</translation>
@@ -6231,7 +6231,7 @@
 <translation id="8300011035382349091">ਇਸ ਟੈਬ ਦੇ ਬੁੱਕਮਾਰਕ ਦਾ ਸੰਪਾਦਨ ਕਰੋ</translation>
 <translation id="8300374739238450534">ਘਸਮੈਲਾ ਨੀਲਾ</translation>
 <translation id="8300849813060516376">OTASP ਅਸਫ਼ਲ ਹੋ ਗਿਆ</translation>
-<translation id="8304383784961451596">ਤੁਸੀਂ ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਵਰਤਣ ਲਈ ਅਧਿਕਾਰਿਤ ਨਹੀਂ ਹੋ। ਕਿਰਪਾ ਕਰਕੇ ਸਾਈਨ-ਇਨ ਇਜਾਜ਼ਤ ਲਈ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ ਜਾਂ Family Link ਵੱਲੋਂ ਨਿਗਰਾਨੀ ਵਾਲੇ ਕਿਸੇ Google ਖਾਤੇ ਨਾਲ ਸਾਈਨ-ਇਨ ਕਰੋ।</translation>
+<translation id="8304383784961451596">ਤੁਸੀਂ ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਵਰਤਣ ਲਈ ਅਧਿਕਾਰਤ ਨਹੀਂ ਹੋ। ਕਿਰਪਾ ਕਰਕੇ ਸਾਈਨ-ਇਨ ਇਜਾਜ਼ਤ ਲਈ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ ਜਾਂ Family Link ਤੋਂ ਨਿਗਰਾਨੀ ਵਾਲੇ ਕਿਸੇ Google ਖਾਤੇ ਨਾਲ ਸਾਈਨ-ਇਨ ਕਰੋ।</translation>
 <translation id="8308179586020895837">ਪੁੱਛੇ ਕਿ ਕੀ <ph name="HOST" /> ਤੁਹਾਡੇ ਕੈਮਰੇ ਤੱਕ ਪਹੁੰਚ ਪ੍ਰਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ</translation>
 <translation id="830868413617744215">ਬੀਟਾ</translation>
 <translation id="8309458809024885768">ਪ੍ਰਮਾਣ-ਪੱਤਰ ਪਹਿਲਾਂ ਤੋਂ ਮੌਜੂਦ ਹੈ</translation>
diff --git a/chrome/app/resources/generated_resources_te.xtb b/chrome/app/resources/generated_resources_te.xtb
index 22ebd18..3f79308c 100644
--- a/chrome/app/resources/generated_resources_te.xtb
+++ b/chrome/app/resources/generated_resources_te.xtb
@@ -17,6 +17,7 @@
 <translation id="1012794136286421601">మీ డాక్స్, షీట్‌లు, స్లయిడ్‌లు మరియు డ్రాయింగ్‌ల ఫైల్‌లు సమకాలీకరించబడుతున్నాయి. వీటిని ఆన్‌లైన్ లేదా ఆఫ్‌లైన్‌లో యాక్సెస్ చేయడానికి Google డిస్క్ యాప్‌ని తెరవండి.</translation>
 <translation id="1012876632442809908">USB-C పరికరం (ముందువైపు పోర్ట్)</translation>
 <translation id="1013707859758800957">ఈ పేజీలో అమలు కావడానికి శాండ్‌బాక్స్ చేయని ప్లగ్ఇన్‌ అనుమతించబడింది.</translation>
+<translation id="1015041505466489552">TrackPoint</translation>
 <translation id="1015318665228971643">ఫోల్డర్ పేరును సవరించండి</translation>
 <translation id="1015578595646638936">{NUM_DAYS,plural, =1{<ph name="DEVICE_TYPE" />ని అప్‌డేట్ చేయడానికి చివరి రోజు}other{<ph name="DEVICE_TYPE" />ని {NUM_DAYS} రోజులలోపు అప్‌డేట్ చేయండి}}</translation>
 <translation id="1016566241875885511">అదనపు సమాచారం (ఐచ్ఛికం)</translation>
diff --git a/chrome/app/resources/generated_resources_vi.xtb b/chrome/app/resources/generated_resources_vi.xtb
index 73f2ccaf..9dbb1ef 100644
--- a/chrome/app/resources/generated_resources_vi.xtb
+++ b/chrome/app/resources/generated_resources_vi.xtb
@@ -1074,7 +1074,7 @@
 <translation id="2224444042887712269">Cài đặt này thuộc về <ph name="OWNER_EMAIL" />.</translation>
 <translation id="2224551243087462610">Chỉnh sửa tên thư mục</translation>
 <translation id="2225864335125757863">Thay đổi ngay các mật khẩu sau để bảo vệ tài khoản của bạn:</translation>
-<translation id="2226204716217107988">Chuyển sang một hồ sơ khác?</translation>
+<translation id="2226204716217107988">Chuyển sang hồ sơ khác?</translation>
 <translation id="2226449515541314767">Trang web này đã bị chặn quyền kiểm soát hoàn toàn thiết bị MIDI.</translation>
 <translation id="2226907662744526012">Tự động mở khóa sau khi nhập mã PIN</translation>
 <translation id="222704500187107962">Hệ thống sẽ tự động xóa ngoại lệ này sau khi bạn thoát khỏi phiên Ẩn danh hiện tại</translation>
@@ -1144,7 +1144,7 @@
 <translation id="2307462900900812319">Định cấu hình mạng</translation>
 <translation id="230927227160767054">Trang này muốn cài đặt trình xử lý dịch vụ.</translation>
 <translation id="2309620859903500144">Trang web này đã bị chặn sử dụng cảm biến chuyển động hoặc ánh sáng của thiết bị.</translation>
-<translation id="2312219318583366810">URL trang</translation>
+<translation id="2312219318583366810">URL của trang</translation>
 <translation id="2314165183524574721">Tùy chọn hiển thị hiện tại là ẩn</translation>
 <translation id="2314774579020744484">Ngôn ngữ được dùng khi dịch trang</translation>
 <translation id="2315414688463285945">Lỗi khi định cấu hình tệp Linux. Vui lòng thử lại.</translation>
@@ -3786,7 +3786,7 @@
 <translation id="5449588825071916739">Đánh dấu trang tất cả các thẻ</translation>
 <translation id="5449716055534515760">Đóng cửa &amp;sổ</translation>
 <translation id="5452974209916053028">Phiên truy cập ẩn danh hiện tại: <ph name="RECENT_PERMISSIONS_CHANGE_SENTENCE_START" />, <ph name="RECENT_PERMISSIONS_CHANGE_1" />, <ph name="RECENT_PERMISSIONS_CHANGE_2" /></translation>
-<translation id="5454005855577728171">Đã chuyển bong bóng chú thích thành <ph name="POSITION_ON_SCREEN_FROM_LEFT" />% ngang, <ph name="POSITION_ON_SCREEN_FROM_TOP" />% dọc</translation>
+<translation id="5454005855577728171">Đã di chuyển bong bóng chú thích đến vị trí <ph name="POSITION_ON_SCREEN_FROM_LEFT" />% theo chiều ngang, <ph name="POSITION_ON_SCREEN_FROM_TOP" />% theo chiều dọc</translation>
 <translation id="5454166040603940656">với <ph name="PROVIDER" /></translation>
 <translation id="5457113250005438886">Không hợp lệ</translation>
 <translation id="5457459357461771897">Đọc và xóa ảnh, nhạc và các phương tiện khác khỏi máy tính của bạn</translation>
@@ -4122,7 +4122,7 @@
 <translation id="5841270259333717135">Định cấu hình Ethernet</translation>
 <translation id="5842497610951477805">Bật Bluetooth</translation>
 <translation id="5843706793424741864">Độ F</translation>
-<translation id="584451707753263735">Bong bóng Phụ đề trực tiếp đang hiển thị, hãy nhấn phím F6 để chuyển tiêu điểm</translation>
+<translation id="584451707753263735">Phụ đề trực tiếp đang hiển thị, hãy nhấn phím F6 để chuyển tiêu điểm</translation>
 <translation id="5844574845205796324">Đề xuất nội dung mới để khám phá</translation>
 <translation id="5846200638699387931">Lỗi cú pháp về mối quan hệ: <ph name="ERROR_LINE" /></translation>
 <translation id="5846807460505171493">Cài đặt các bản cập nhật và ứng dụng. Bằng việc tiếp tục, bạn đồng ý rằng thiết bị này cũng có thể tự động tải xuống và cài đặt các bản cập nhật cũng như ứng dụng từ Google, nhà mạng và nhà sản xuất thiết bị, có thể bằng cách sử dụng dữ liệu di động. Một vài ứng dụng có thể cung cấp tùy chọn mua hàng trong ứng dụng.</translation>
@@ -6354,7 +6354,7 @@
 <translation id="8449036207308062757">Quản lý bộ nhớ</translation>
 <translation id="8452135315243592079">Thiếu thẻ SIM</translation>
 <translation id="8455026683977728932">Không bật được hình minh họa ADB</translation>
-<translation id="8456398879271637452">Bong bóng Phụ đề trực tiếp đang hiển thị, hãy nhấn tổ hợp phím Ctrl + Lùi hoặc Ctrl + Tiến để chuyển tiêu điểm</translation>
+<translation id="8456398879271637452">Phụ đề trực tiếp đang hiển thị, hãy nhấn tổ hợp phím Ctrl + Lùi hoặc Ctrl + Tiến để chuyển tiêu điểm</translation>
 <translation id="845702320058262034">Không thể kết nối. Hãy đảm bảo bạn đã bật Bluetooth trên điện thoại.</translation>
 <translation id="8457451314607652708">Nhập dấu trang</translation>
 <translation id="8458627787104127436">Mở tất cả (<ph name="URL_COUNT" />) trong cửa sổ mới</translation>
@@ -6875,7 +6875,7 @@
 <translation id="9039014462651733343">{NUM_ATTEMPTS,plural, =1{Bạn còn một lần thử.}other{Bạn còn # lần thử.}}</translation>
 <translation id="9039663905644212491">PEAP</translation>
 <translation id="9040661932550800571">Bạn có muốn cập nhật mật khẩu cho <ph name="ORIGIN" /> không?</translation>
-<translation id="9041049756004505730">Bong bóng Phụ đề trực tiếp đang hiển thị, hãy nhấn tổ hợp phím ⌘ + Option + Mũi tên lên hoặc Mũi tên xuống để chuyển tiêu điểm</translation>
+<translation id="9041049756004505730">Phụ đề trực tiếp đang hiển thị, hãy nhấn tổ hợp phím ⌘ + Option + Mũi tên lên hoặc Mũi tên xuống để chuyển tiêu điểm</translation>
 <translation id="9041692268811217999">Quản trị viên đã vô hiệu hóa quyền truy cập vào tệp cục bộ trên máy của bạn</translation>
 <translation id="904224458472510106">Bạn không thể hủy thao tác này</translation>
 <translation id="9042893549633094279">Quyền riêng tư và bảo mật</translation>
@@ -6914,7 +6914,7 @@
 <translation id="9088446193279799727">Không thể định cấu hình Linux. Hãy kết nối Internet rồi thử lại.</translation>
 <translation id="9088917181875854783">Vui lòng xác nhận mã xác nhận này được hiển thị trên "<ph name="DEVICE_NAME" />":</translation>
 <translation id="9089416786594320554">Phương thức nhập</translation>
-<translation id="909108997331068008">Bạn đã đăng nhập vào <ph name="NEW_USER" /> bằng hồ sơ của <ph name="EXISTING_USER" /></translation>
+<translation id="909108997331068008">Hồ sơ của <ph name="EXISTING_USER" /> đã được đăng nhập vào <ph name="NEW_USER" /></translation>
 <translation id="9093429538970210897">Bạn nên sao lưu tệp để phòng trường hợp quá trình nâng cấp không hoàn tất được. Khi bắt đầu nâng cấp, Linux (Bản thử nghiệm) sẽ tắt. Vui lòng lưu các tệp đang mở trước khi tiếp tục.</translation>
 <translation id="9094033019050270033">Cập nhật mật khẩu</translation>
 <translation id="9094038138851891550">Tên người dùng không hợp lệ</translation>
diff --git a/chrome/app/resources/google_chrome_strings_bn.xtb b/chrome/app/resources/google_chrome_strings_bn.xtb
index e1c8cbb..ae6a9b8 100644
--- a/chrome/app/resources/google_chrome_strings_bn.xtb
+++ b/chrome/app/resources/google_chrome_strings_bn.xtb
@@ -77,6 +77,7 @@
 <translation id="2871893339301912279">আপনি Chrome এ প্রবেশ করেছেন৷</translation>
 <translation id="2885378588091291677">কার্য পরিচালক</translation>
 <translation id="2888126860611144412">Chrome সম্বন্ধে</translation>
+<translation id="2926676257163822632">দুর্বল পাসওয়ার্ড সহজেই অনুমান করা যায়। Chrome-কে <ph name="BEGIN_LINK" />আপনার জন্য শক্তিশালী পাসওয়ার্ড তৈরি করার ও সেটি মনে রাখার<ph name="END_LINK" /> অনুমতি দিন।</translation>
 <translation id="2929907241665500097">Chrome আপডেট করা যায়নি, কোনও সমস্যা হয়েছে। <ph name="BEGIN_LINK" />Chrome-এ আপডেট করতে না পারার সমস্যা ও আপডেট করা যায়নি এমন সমস্যার সমাধান করুন।<ph name="END_LINK" /></translation>
 <translation id="2969728957078202736"><ph name="PAGE_TITLE" /> - নেটওয়ার্ক সাইন-ইন - Chrome</translation>
 <translation id="3037838751736561277">Google Chrome পটভূমি মোডে রয়েছে।</translation>
diff --git a/chrome/app/resources/google_chrome_strings_gu.xtb b/chrome/app/resources/google_chrome_strings_gu.xtb
index 61da003c..8cb622d 100644
--- a/chrome/app/resources/google_chrome_strings_gu.xtb
+++ b/chrome/app/resources/google_chrome_strings_gu.xtb
@@ -82,6 +82,7 @@
 <translation id="2926676257163822632">નબળા પાસવર્ડનું અનુમાન કરવું સરળ હોય છે. Chromeને <ph name="BEGIN_LINK" />તમારા માટે સશક્ત પાસવર્ડ બનાવવા અને યાદ રાખવા<ph name="END_LINK" />ની મંજૂરી આપો.</translation>
 <translation id="2929907241665500097">કંઈક ખોટુ થયું હોવાને કારણે Chrome અપડેટ કરી શકાયું નથી. <ph name="BEGIN_LINK" />Chrome અપડેટ કરવામાં આવતી સમસ્યાઓ અને નિષ્ફળ થયેલા અપડેટ સુધારો.<ph name="END_LINK" /></translation>
 <translation id="2969728957078202736"><ph name="PAGE_TITLE" /> - નેટવર્ક સાઇન ઇન - Chrome</translation>
+<translation id="298099161970687941">જ્યારે Chrome ખુલ્લું હોય ત્યારે પૂછો</translation>
 <translation id="3037838751736561277">Google Chrome પૃષ્ઠભૂમિ મોડમાં છે.</translation>
 <translation id="3059710691562604940">Safe Browsingની સુવિધા બંધ છે. Chrome તેને ચાલુ રાખવાનો સુઝાવ આપે છે.</translation>
 <translation id="3065168410429928842">Chrome ટૅબ</translation>
diff --git a/chrome/app/resources/google_chrome_strings_iw.xtb b/chrome/app/resources/google_chrome_strings_iw.xtb
index f9790d74..5504091 100644
--- a/chrome/app/resources/google_chrome_strings_iw.xtb
+++ b/chrome/app/resources/google_chrome_strings_iw.xtb
@@ -12,7 +12,7 @@
 <translation id="1125124144982679672">‏מי משתמש/ת ב-Chrome?</translation>
 <translation id="1142745911746664600">‏לא ניתן לעדכן את Chrome</translation>
 <translation id="1154147086299354128">‏&amp;פתיחה ב-Chrome</translation>
-<translation id="123620459398936149">‏מערכת ההפעלה של Chrome לא הצליחה לסנכרן את הנתונים שלך. עדכן את משפט הסיסמה שלך לסנכרון.</translation>
+<translation id="123620459398936149">‏מערכת ההפעלה של Chrome לא הצליחה לסנכרן את הנתונים שלך. יש לעדכן את משפט הסיסמה שלך לסנכרון.</translation>
 <translation id="1302523850133262269">‏המתן בזמן ש-Chrome מתקין את עדכוני המערכת האחרונים.</translation>
 <translation id="1355000804395496115">‏כדאי להשתמש בפרופילים שונים ב-Chrome כדי להפריד בין גלישה בעבודה וגלישה אישית, או בין אנשים שונים שמשתמשים במכשיר הזה</translation>
 <translation id="137466361146087520">‏גרסת הבטא של Google Chrome</translation>
@@ -29,7 +29,7 @@
 <translation id="1628000112320670027">‏קבלת עזרה בנושא Chrome</translation>
 <translation id="1662639173275167396">‏הפיתוח של Chrome OS אפשרי בזכות <ph name="BEGIN_LINK_CROS_OSS" />תוכנות קוד פתוח<ph name="END_LINK_CROS_OSS" /> נוספות, כמו <ph name="BEGIN_LINK_LINUX_OSS" />Linux (בטא)<ph name="END_LINK_LINUX_OSS" />.</translation>
 <translation id="1666409074978194368">‏העדכון כמעט הושלם. יש לפתוח שוב את Google Chrome כדי לסיים את העדכון. החלונות האנונימיים לא ייפתחו מחדש.</translation>
-<translation id="1674870198290878346">‏פתח את הקישור בחלון &amp;גלישה בסתר של Chrome</translation>
+<translation id="1674870198290878346">‏פתיחת הקישור בחלון &amp;גלישה בסתר של Chrome</translation>
 <translation id="1682634494516646069">‏Google Chrome אינו יכול לקרוא ולכתוב בספריית הנתונים שלו: <ph name="USER_DATA_DIRECTORY" /></translation>
 <translation id="1698376642261615901">‏Google Chrome הוא דפדפן אינטרנט המפעיל דפי אינטרנט ואפליקציות במהירות הבזק. זהו דפדפן מהיר, יציב וקל לשימוש. תוכל לגלוש באינטרנט בצורה בטוחה יותר הודות להגנה מפני תוכנות זדוניות ופישינג, המובנית ב-Google Chrome.</translation>
 <translation id="1713301662689114961">{0,plural, =1{‏Chrome יופעל מחדש בעוד שעה}two{‏Chrome יופעל מחדש בעוד # שעות}many{‏Chrome יופעל מחדש בעוד # שעות}other{‏Chrome יופעל מחדש בעוד # שעות}}</translation>
@@ -107,7 +107,7 @@
 <translation id="3735758079232443276">‏התוסף "<ph name="EXTENSION_NAME" />" שינה את הדף שמוצג כש-Chrome מופעל.</translation>
 <translation id="3779473566290487688">‏כדי לקבל עדכונים של Google Chrome בעתיד, נדרשת מערכת הפעלה OS X 10.11 ואילך. במחשב הזה מותקנת מערכת ההפעלה OS X 10.10.</translation>
 <translation id="3780814664026482060">‏Chrome - ‏<ph name="PAGE_TITLE" /></translation>
-<translation id="386202838227397562">‏סגור את כל החלונות של Google Chrome ונסה שוב.</translation>
+<translation id="386202838227397562">‏יש לסגור את כל החלונות של Google Chrome ולנסות שוב.</translation>
 <translation id="3865754807470779944">‏מותקנת גרסה <ph name="PRODUCT_VERSION" /> של Chrome</translation>
 <translation id="3873044882194371212">‏פתח את הקישור בחלון &amp;גלישה בסתר של Chrome</translation>
 <translation id="3889417619312448367">‏הסר את Google Chrome</translation>
@@ -133,14 +133,14 @@
 <translation id="4384570495110188418">‏Chrome לא יכול לבדוק את הסיסמאות שלך כי לא נכנסת לחשבון</translation>
 <translation id="4407807842708586359">Google Chrome OS</translation>
 <translation id="4450664632294415862">‏Chrome – כניסה לרשת – <ph name="PAGE_TITLE" /></translation>
-<translation id="4458462641685292929">‏מתבצעת כרגע פעולה אחרת ב-Google Chrome. נסה שוב מאוחר יותר.</translation>
+<translation id="4458462641685292929">‏מתבצעת כרגע פעולה אחרת ב-Google Chrome. יש לנסות שוב מאוחר יותר.</translation>
 <translation id="4480040274068703980">‏מערכת ההפעלה של Chrome לא הצליחה לסנכרן את הנתונים שלך עקב שגיאה בתהליך הכניסה.</translation>
 <translation id="4521185804071812304">‏אופציונלי: שליחה אוטומטית של נתוני אבחון ושימוש אל Google תעזור לשפר את התכונות ואת הביצועים של Chrome OS.</translation>
 <translation id="4561051373932531560">‏Google Chrome מאפשר לך ללחוץ על מספר טלפון באינטרנט ולהתקשר אליו באמצעות Skype!</translation>
 <translation id="4567424176335768812">נכנסת למערכת בתור <ph name="USER_EMAIL_ADDRESS" />. כעת אתה יכול לגשת אל הסימניות, ההיסטוריה והגדרות אחרות שלך בכל המכשירים שבהם אתה מחובר לחשבון.</translation>
 <translation id="4571503333518166079">‏מעבר אל הגדרות של הודעות ב-Chrome</translation>
 <translation id="459622048091363950">‏אחרי מתן גישה ל-Chrome, אתרים יוכלו לבקש ממך גישה.</translation>
-<translation id="4600710005438004015">‏עדכון Chrome לגירסה האחרונה לא הצליח, ולכן אין לך גישה אל תכונות חדשות ותיקוני אבטחה.</translation>
+<translation id="4600710005438004015">‏עדכון Chrome לגרסה האחרונה לא הצליח, ולכן אין לך גישה אל תכונות חדשות ותיקוני אבטחה.</translation>
 <translation id="4631713731678262610">‏הסתר בתפריט Chrome</translation>
 <translation id="4633000520311261472">‏כדי לשפר את האבטחה של Chrome, השבתנו חלק מהתוספים שלא רשומים ב<ph name="IDS_EXTENSION_WEB_STORE_TITLE" /> וייתכן שנוספו ללא ידיעתך.</translation>
 <translation id="4728575227883772061">‏ההתקנה נכשלה בשל שגיאה לא צפויה. אם Google Chrome פועל כעת, סגור אותו ונסה שוב.</translation>
@@ -189,7 +189,7 @@
 <translation id="6235018212288296708">‏כלל נכנס עבור Google Chrome על מנת לאפשר תנועת mDNS.</translation>
 <translation id="6291089322031436445">‏אפליקציות לגרסת הפיתוח של Chrome</translation>
 <translation id="6291549208091401781">‏Google Chrome כבר מותקן במחשב ונגיש לכל המשתמשים.</translation>
-<translation id="6338556085225130112">‏מעדכן את Google Chrome</translation>
+<translation id="6338556085225130112">‏עדכון Google Chrome מתבצע</translation>
 <translation id="6368958679917195344">‏השימוש במערכת ההפעלה של Chrome מתאפשר באמצעות <ph name="BEGIN_LINK_CROS_OSS" />תוכנת קוד פתוח<ph name="END_LINK_CROS_OSS" /> נוספת.</translation>
 <translation id="6515495397637126556">‏<ph name="PAGE_TITLE" /> - Google Chrome בגרסת פיתוח</translation>
 <translation id="6566149418543181476">‏מעדכן את Google Chrome‏ (<ph name="PROGRESS_PERCENT" />)</translation>
@@ -231,7 +231,7 @@
 <translation id="7761834446675418963">‏אפשר ללחוץ על השם שלך כדי לפתוח את Chrome ולהתחיל לגלוש.</translation>
 <translation id="7777080907402804672">‏אם אין לתמונה תיאור מועיל, Chrome ינסה לספק לך תיאור. כדי ליצור תיאורים, התמונות נשלחות אל Google. אפשר להשבית את האפשרות הזו בכל זמן דרך ההגדרות.</translation>
 <translation id="7781002470561365167">‏גרסה חדשה של Google Chrome זמינה כעת.</translation>
-<translation id="7787950393032327779">‏נראה שהפרופיל נמצא בשימוש על ידי תהליך אחר של Google Chrome‏ (<ph name="PROCESS_ID" />) במחשב אחר (<ph name="HOST_NAME" />)‏. Chrome נעל את הפרופיל כדי שלא ייפגם. אם אתה משוכנע שאף תהליך אחר אינו משתמש בפרופיל זה, תוכל לבטל את נעילת הפרופיל ולהפעיל את Chrome מחדש.</translation>
+<translation id="7787950393032327779">‏נראה שהפרופיל נמצא בשימוש על ידי תהליך אחר של Google Chrome‏ (<ph name="PROCESS_ID" />) במחשב אחר (<ph name="HOST_NAME" />)‏. Chrome נעל את הפרופיל כדי שלא ייפגם. אם ברור לך שאף תהליך אחר אינו משתמש בפרופיל זה, באפשרותך לבטל את נעילת הפרופיל ולהפעיל את Chrome מחדש.</translation>
 <translation id="7801699035218095297">‏Google Chrome מנסה להעתיק את הסיסמאות. כדי לאפשר את הפעולה הזו, יש להקליד את הסיסמה שלך ל-Windows.</translation>
 <translation id="7808348361785373670">‏הסרה מ-Chrome...</translation>
 <translation id="7825851276765848807">‏ההתקנה נכשלה בשל שגיאה לא מזוהה. הורד שוב את Google Chrome.</translation>
diff --git a/chrome/app/resources/google_chrome_strings_or.xtb b/chrome/app/resources/google_chrome_strings_or.xtb
index c07df58..5a59699c 100644
--- a/chrome/app/resources/google_chrome_strings_or.xtb
+++ b/chrome/app/resources/google_chrome_strings_or.xtb
@@ -82,6 +82,7 @@
 <translation id="2926676257163822632">ଦୁର୍ବଳ ପାସୱାର୍ଡଗୁଡ଼ିକୁ ଅନୁମାନ କରିବା ସହଜ ଅଟେ। Chromeକୁ <ph name="BEGIN_LINK" />ଆପଣଙ୍କ ପାଇଁ ଜଟିଳ ପାସୱାର୍ଡଗୁଡ଼ିକୁ ତିଆରି କରି ମନେ ରଖିବାକୁ ଦିଅନ୍ତୁ<ph name="END_LINK" />।</translation>
 <translation id="2929907241665500097">Chrome ଅପଡେଟ୍ ହେଲା ନାହିଁ, କିଛି ତ୍ରୁଟି ହୋଇଗଲା। <ph name="BEGIN_LINK" />Chrome ଅପଡେଟ୍ ସମସ୍ୟା ଏବଂ ବିଫଳ ଅପଡେଟଗୁଡ଼ିକର ସମାଧାନ କରନ୍ତୁ।<ph name="END_LINK" /></translation>
 <translation id="2969728957078202736"><ph name="PAGE_TITLE" /> - ନେଟୱାର୍କ ସାଇନ୍-ଇନ୍ - Chrome</translation>
+<translation id="298099161970687941">Chrome ଖୋଲିଲେ ପଚାରନ୍ତୁ</translation>
 <translation id="3037838751736561277">Google Chrome ପୃଷ୍ଠପଟ ମୋଡ୍‌ରେ ଅଛି।</translation>
 <translation id="3059710691562604940">ସେଫ୍ ବ୍ରାଉଜିଂ ବନ୍ଦ ଅଛି। Chrome ଏହାକୁ ଚାଲୁ କରିବାକୁ ସୁପାରିଶ କରେ।</translation>
 <translation id="3065168410429928842">Chrome ଟାବ୍</translation>
diff --git a/chrome/app/resources/google_chrome_strings_pa.xtb b/chrome/app/resources/google_chrome_strings_pa.xtb
index 44b2567..40c785a 100644
--- a/chrome/app/resources/google_chrome_strings_pa.xtb
+++ b/chrome/app/resources/google_chrome_strings_pa.xtb
@@ -8,7 +8,7 @@
 
 ਕੁਝ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਅਣਉਪਲਬਧ ਹੋ ਸਕਦੀਆਂ ਹਨ ਅਤੇੇ ਤਰਜੀਹਾਂ ਵਿੱਚ ਕੀਤੇ ਬਦਲਾਵ ਸੁਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤੇ ਜਾਣਗੇ।</translation>
 <translation id="1088300314857992706"><ph name="USER_EMAIL_ADDRESS" /> ਵੱਲੋਂ ਪਹਿਲਾਂ Chrome ਦੀ ਵਰਤੋਂ ਕੀਤੀ ਜਾ ਰਹੀ ਸੀ</translation>
-<translation id="1088654056000736875">Chrome ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚੋਂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਹਟਾ ਰਿਹਾ ਹੈ...</translation>
+<translation id="1088654056000736875">Chrome ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਤੋਂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਹਟਾ ਰਿਹਾ ਹੈ...</translation>
 <translation id="1097330777386562916">Chrome ਨੂੰ ਬੰਦ ਕਰਨ ਵੇਲੇ ਕੁਕੀਜ਼ ਅਤੇ ਸਾਈਟ ਡਾਟੇ ਨੂੰ ਵੀ ਕਲੀਅਰ ਕਰੋ</translation>
 <translation id="110877069173485804">ਇਹ ਤੁਹਾਡਾ Chrome ਹੈ</translation>
 <translation id="1125124144982679672">Chrome ਕੌਣ ਵਰਤ ਰਿਹਾ ਹੈ?</translation>
@@ -61,7 +61,7 @@
 <translation id="2429317896000329049">Google Chrome ਤੁਹਾਡਾ ਡਾਟਾ ਸਮਕਾਲੀਕਰਨ ਨਹੀਂ ਕਰ ਸਕਿਆ ਕਿਉਂਕਿ ਸਮਕਾਲੀਕਰਨ ਤੁਹਾਡੀ ਡੋਮੇਨ ਲਈ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।</translation>
 <translation id="2467438592969358367">Google Chrome ਤੁਹਾਡੇ ਪਾਸਵਰਡ ਨਿਰਯਾਤ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ। ਇਹ ਕਰਨ ਦੇਣ ਲਈ ਆਪਣਾ Windows ਪਾਸਵਰਡ ਟਾਈਪ ਕਰੋ।</translation>
 <translation id="2485422356828889247">ਅਣਸਥਾਪਤ ਕਰੋ</translation>
-<translation id="252502352004572774">Chrome ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚੋਂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਦੀ ਜਾਂਚ ਕਰ ਰਿਹਾ ਹੈ...</translation>
+<translation id="252502352004572774">Chrome ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਲਈ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਦੀ ਜਾਂਚ ਕਰ ਰਿਹਾ ਹੈ...</translation>
 <translation id="2534507159460261402">Google Pay (Chrome 'ਤੇ ਕਾਪੀ ਕੀਤਾ ਗਿਆ)</translation>
 <translation id="2580411288591421699">ਉਹ Google Chrome ਵਰਜਨ ਸਥਾਪਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ ਜੋ ਇਸ ਵੇਲੇ ਚੱਲ ਰਿਹਾ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ Google Chrome ਬੰਦ ਕਰੋ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</translation>
 <translation id="2586406160782125153">ਇਸ ਨਾਲ ਇਸ ਡੀਵਾਈਸ ਤੋਂ ਤੁਹਾਡੇ ਬ੍ਰਾਊਜ਼ਿੰਗ ਡਾਟੇ ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ। ਬਾਅਦ ਵਿੱਚ ਆਪਣੇ ਡਾਟੇ ਨੂੰ ਮੁੜ-ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ, Chrome 'ਤੇ <ph name="USER_EMAIL" /> ਵਜੋਂ ਸਾਈਨ-ਇਨ ਕਰੋ।</translation>
@@ -117,12 +117,12 @@
 <translation id="4050175100176540509">ਮਹੱਤਵਪੂਰਣ ਸੁਰੱਖਿਆ ਸੁਧਾਰ ਅਤੇ ਨਵੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨਵੇਂ ਰੂਪ ਵਿੱਚ ਉਪਲਬਧ ਹਨ।</translation>
 <translation id="4053720452172726777">Google Chrome ਨੂੰ ਵਿਉਂਤਬੱਧ ਕਰਕੇ ਕੰਟਰੋਲ ਕਰੋ।</translation>
 <translation id="4110895483821904099">ਆਪਣੇ ਨਵੇਂ Chrome ਪ੍ਰੋਫਾਈਲ ਦਾ ਸੈੱਟਅੱਪ ਕਰੋ</translation>
-<translation id="4127976662406264741">{NUM_MINS,plural, =1{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: 1 ਮਿੰਟ ਪਹਿਲਾਂ।}one{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_MINS} ਮਿੰਟ ਪਹਿਲਾਂ।}other{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_MINS} ਮਿੰਟ ਪਹਿਲਾਂ।}}</translation>
+<translation id="4127976662406264741">{NUM_MINS,plural, =1{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: 1 ਮਿੰਟ ਪਹਿਲਾਂ।}one{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_MINS} ਮਿੰਟ ਪਹਿਲਾਂ।}other{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_MINS} ਮਿੰਟ ਪਹਿਲਾਂ।}}</translation>
 <translation id="4143243756087420366">Chrome ਨਾਮ ਅਤੇ ਤਸਵੀਰ</translation>
 <translation id="4147555960264124640">ਤੁਸੀਂ ਇੱਕ ਪ੍ਰਬੰਧਿਤ ਖਾਤੇ ਨਾਲ ਸਾਈਨ-ਇਨ ਕਰ ਰਹੇ ਹੋ ਅਤੇ ਇਸ ਪ੍ਰਬੰਧਕ ਨੂੰ ਆਪਣੀ Google Chrome ਪ੍ਰੋਫਾਈਲ 'ਤੇ ਕੰਟਰੋਲ ਪ੍ਰਦਾਨ ਕਰ ਰਹੇ ਹੋ। ਤੁਹਾਡਾ Chrome ਡਾਟਾ, ਜਿਵੇਂ ਕਿ ਤੁਹਾਡੀਆਂ ਐਪਾਂ, ਬੁੱਕਮਾਰਕਾਂ, ਇਤਿਹਾਸ, ਪਾਸਵਰਡਾਂ ਅਤੇ ਹੋਰ ਸੈਟਿੰਗਾਂ <ph name="USER_NAME" /> ਨਾਲ ਸਥਾਈ ਤੌਰ 'ਤੇ ਜੋੜੀਆਂ ਜਾਣਗੀਆਂ। ਤੁਸੀਂ ਇਸ ਡਾਟਾ ਨੂੰ Google ਖਾਤੇ ਡੈਸ਼ਬੋਰਡ ਰਾਹੀਂ ਮਿਟਾ ਸਕੋਗੇ, ਪਰੰਤੂ ਤੁਸੀਂ ਇਸ ਡਾਟਾ ਨੂੰ ਦੂਜੇ ਖਾਤੇ ਨਾਲ ਨਹੀਂ ਜੋੜ ਸਕੋਗੇ। <ph name="LEARN_MORE" /></translation>
 <translation id="4149882025268051530">ਸਥਾਪਨਾਕਾਰ ਪੁਰਾਲੇਖ ਦੇ ਨਪੀੜਨ ਨੂੰ ਵਾਪਸ ਕਰਨ ਵਿੱਚ ਅਸਫਲ ਰਿਹਾ। ਕਿਰਪਾ ਕਰਕੇ Google Chrome ਨੂੰ ਦੁਬਾਰਾ ਡਾਊਨਲੋਡ ਕਰੋ।</translation>
 <translation id="4191857738314598978">{0,plural, =1{Chrome ਨੂੰ ਇੱਕ ਦਿਨ ਦੇ ਅੰਦਰ ਮੁੜ-ਲਾਂਚ ਕਰੋ}one{Chrome ਨੂੰ # ਦਿਨ ਦੇ ਅੰਦਰ ਮੁੜ-ਲਾਂਚ ਕਰੋ}other{Chrome ਨੂੰ # ਦਿਨਾਂ ਦੇ ਅੰਦਰ ਮੁੜ-ਲਾਂਚ ਕਰੋ}}</translation>
-<translation id="4205362703535890467">Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: ਕੱਲ੍ਹ।</translation>
+<translation id="4205362703535890467">Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: ਬੀਤੇ ਕੱਲ੍ਹ।</translation>
 <translation id="4205939740494406371">Chrome ਤੁਹਾਡੇ ਪਾਸਵਰਡਾਂ ਦੀ ਜਾਂਚ ਨਹੀਂ ਕਰ ਸਕਦਾ। 24 ਘੰਟਿਆਂ ਬਾਅਦ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ ਜਾਂ <ph name="BEGIN_LINK" />ਆਪਣੇ Google ਖਾਤੇ ਵਿੱਚ ਪਾਸਵਰਡਾਂ ਦੀ ਜਾਂਚ ਕਰੋ<ph name="END_LINK" />।</translation>
 <translation id="424864128008805179">ਕੀ Chrome ਤੋਂ ਸਾਈਨ-ਆਊਟ ਹੋਣਾ ਹੈ?</translation>
 <translation id="4251615635259297716">ਕੀ ਤੁਹਾਡਾ Chrome ਡਾਟਾ ਇਸ ਖਾਤੇ ਨਾਲ ਲਿੰਕ ਕਰਨਾ ਹੈ?</translation>
@@ -151,7 +151,7 @@
 <translation id="4754614261631455953">Google Chrome Canary (mDNS-In)</translation>
 <translation id="4771048833395599659">ਇਹ ਫ਼ਾਈਲ ਖਤਰਨਾਕ ਹੋ ਸਕਦੀ ਹੈ, ਇਸ ਕਰਕੇ Chrome ਨੇ ਇਸਨੂੰ ਬਲਾਕ ਕਰ ਦਿੱਤਾ ਹੈ।</translation>
 <translation id="479167709087336770">ਇਹ Google ਖੋਜ ਵੇਲੇ ਵਰਤੇ ਜਾਣ ਵਾਲੇ ਸਪੈੱਲ-ਚੈਕਰ ਨੂੰ ਹੀ ਵਰਤਦਾ ਹੈ। ਬ੍ਰਾਊਜ਼ਰ ਵਿੱਚ ਤੁਹਾਡੇ ਵੱਲੋਂ ਟਾਈਪ ਕੀਤੀ ਜਾਣ ਵਾਲੀ ਲਿਖਤ Google ਨੂੰ ਭੇਜੀ ਜਾਵੇਗੀ। ਤੁਸੀਂ ਹਮੇਸ਼ਾਂ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਇਸ ਵਤੀਰੇ ਨੂੰ ਬਦਲ ਸਕਦੇ ਹੋ।</translation>
-<translation id="4831688036548685548">Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: ਕੁਝ ਸਮਾਂ ਪਹਿਲਾਂ।</translation>
+<translation id="4831688036548685548">Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: ਕੁਝ ਸਮਾਂ ਪਹਿਲਾਂ।</translation>
 <translation id="4891791193823137474">Google Chrome ਨੂੰ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲਣ ਦਿਓ</translation>
 <translation id="4895437082222824641">ਨਵੀਂ Chrome &amp;ਟੈਬ ਵਿੱਚ ਲਿੰਕ ਖੋਲ੍ਹੋ</translation>
 <translation id="4953650215774548573">Google Chrome ਨੂੰ ਆਪਣੇ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਬ੍ਰਾਊਜ਼ਰ ਵਜੋਂ ਸੈੱਟ ਕਰੋ</translation>
@@ -167,7 +167,7 @@
 <translation id="532046782124376502">ਚਿਤਾਵਨੀ: Google Chrome ਐਕਸਟੈਂਸ਼ਨਾਂ ਨੂੰ ਤੁਹਾਡੇ ਬ੍ਰਾਊਜ਼ਿੰਗ ਇਤਿਹਾਸ ਨੂੰ ਰਿਕਾਰਡ ਕਰਨ ਤੋਂ ਨਹੀਂ ਰੋਕ ਸਕਦਾ। ਇਨਕੋਗਨਿਟੋ ਮੋਡ ਵਿੱਚ ਇਸ ਐਕਸਟੈਂਸ਼ਨ ਨੂੰ ਬੰਦ ਕਰਨ ਲਈ, ਇਸ ਵਿਕਲਪ ਨੂੰ ਅਣਚੁਣਿਆ ਕਰੋ।</translation>
 <translation id="5386244825306882791">ਇਹ ਇਸ ਨੂੰ ਵੀ ਕੰਟਰੋਲ ਕਰਦਾ ਹੈ ਕਿ ਜਦੋਂ ਤੁਸੀਂ Chrome ਨੂੰ ਸ਼ੁਰੂ ਕਰਦੇ ਜਾਂ ਓਮਨੀਬਾਕਸ ਤੋਂ ਖੋਜ ਕਰਦੇ ਹੋ।</translation>
 <translation id="5394833366792865639">ਕੋਈ Chrome ਟੈਬ ਸਾਂਝੀ ਕਰੋ</translation>
-<translation id="5409605318138185493">{NUM_DAYS,plural, =1{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: 1 ਦਿਨ ਪਹਿਲਾਂ।}one{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_DAYS} ਦਿਨ ਪਹਿਲਾਂ।}other{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_DAYS} ਦਿਨ ਪਹਿਲਾਂ।}}</translation>
+<translation id="5409605318138185493">{NUM_DAYS,plural, =1{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: 1 ਦਿਨ ਪਹਿਲਾਂ।}one{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_DAYS} ਦਿਨ ਪਹਿਲਾਂ।}other{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_DAYS} ਦਿਨ ਪਹਿਲਾਂ।}}</translation>
 <translation id="5430073640787465221">ਤੁਹਾਡੀ ਤਰਜੀਹਾਂ ਵਾਲੀ ਫ਼ਾਈਲ ਖਰਾਬ ਜਾਂ ਅਵੈਧ ਹੈ।
 
 Google Chrome ਤੁਹਾਡੀਆਂ ਸੈਟਿੰਗਾਂ ਮੁੜ-ਹਾਸਲ ਨਹੀਂ ਕਰ ਸਕਿਆ।</translation>
@@ -285,7 +285,7 @@
 <translation id="9067395829937117663">Google Chrome ਨੂੰ Windows 7 ਜਾਂ ਇਸ ਤੋਂ ਬਾਅਦ ਵਾਲੇ ਵਰਜਨ ਦੀ ਲੋੜ ਹੈ।</translation>
 <translation id="911206726377975832">ਕੀ ਤੁਹਾਡਾ ਬ੍ਰਾਊਜ਼ਿੰਗ ਡਾਟਾ ਵੀ ਮਿਟਾਉਣਾ ਹੈ?</translation>
 <translation id="9138603949443464873">ਆਪਣੀਆਂ ਤਬਦੀਲੀਆਂ ਲਾਗੂ ਕਰਨ ਲਈ, Chrome ਨੂੰ ਮੁੜ-ਲਾਂਚ ਕਰੋ</translation>
-<translation id="9155112650704618965">{NUM_HOURS,plural, =1{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: 1 ਘੰਟਾ ਪਹਿਲਾਂ।}one{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_HOURS} ਘੰਟਾ ਪਹਿਲਾਂ।}other{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ ਵਿੱਚ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_HOURS} ਘੰਟੇ ਪਹਿਲਾਂ।}}</translation>
+<translation id="9155112650704618965">{NUM_HOURS,plural, =1{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: 1 ਘੰਟਾ ਪਹਿਲਾਂ।}one{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_HOURS} ਘੰਟਾ ਪਹਿਲਾਂ।}other{Chrome ਨੂੰ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਕੋਈ ਜਾਣੂ ਹਾਨੀਕਾਰਕ ਸਾਫ਼ਟਵੇਅਰ ਨਹੀਂ ਲੱਭਿਆ। ਪਿਛਲੀ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਗਈ: {NUM_HOURS} ਘੰਟੇ ਪਹਿਲਾਂ।}}</translation>
 <translation id="919706545465235479">ਸਮਕਾਲੀਕਰਨ ਸ਼ੁਰੂ ਕਰਨ ਲਈ Chrome ਅੱਪਡੇਟ ਕਰੋ</translation>
 <translation id="989369509083708165">Google Chrome ਤੁਹਾਡਾ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਬ੍ਰਾਊਜ਼ਰ ਹੈ</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/chrome/app/resources/google_chrome_strings_te.xtb b/chrome/app/resources/google_chrome_strings_te.xtb
index e76813f..616efac3 100644
--- a/chrome/app/resources/google_chrome_strings_te.xtb
+++ b/chrome/app/resources/google_chrome_strings_te.xtb
@@ -78,6 +78,7 @@
 <translation id="2926676257163822632">బలహీనమైన పాస్‌వర్డ్‌లను ఊహించడం చాలా సులభం. <ph name="BEGIN_LINK" />మీ కోసం శక్తివంతమైన పాస్‌వర్డ్‌లను క్రియేట్ చేయడం, గుర్తుంచుకోవడం<ph name="END_LINK" /> చేయడానికి Chromeను అనుమతించండి.</translation>
 <translation id="2929907241665500097">Chrome అప్‌డేట్ అవ్వలేదు, ఏదో తప్పు జరిగింది. <ph name="BEGIN_LINK" />Chrome అప్‌డేట్ సమస్యలు, విఫలమైన అప్‌డేట్‌లను పరిష్కరించండి.<ph name="END_LINK" /></translation>
 <translation id="2969728957078202736"><ph name="PAGE_TITLE" /> - నెట్‌వర్క్ సైన్ ఇన్ - Chrome</translation>
+<translation id="298099161970687941">Chrome తెరుచుకున్నప్పుడు అడగాలి</translation>
 <translation id="3037838751736561277">Google Chrome నేపథ్య మోడ్‌లో ఉంది.</translation>
 <translation id="3059710691562604940">సురక్షిత బ్రౌజింగ్ ఆఫ్ చేయబడింది. దాన్ని ఆన్ చేయమని Chrome సిఫార్సు చేస్తోంది.</translation>
 <translation id="3065168410429928842">Chrome ట్యాబ్</translation>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 8e70000..892fc71 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -83,6 +83,12 @@
   if (is_win) {
     flags += [ "ENABLE_SEGMENT_HEAP=$enable_segment_heap" ]
   }
+
+  if (use_allocator == "partition") {
+    flags += [ "USE_PARTITION_ALLOC_EVERYWHERE=1" ]
+  } else {
+    flags += [ "USE_PARTITION_ALLOC_EVERYWHERE=0" ]
+  }
 }
 
 # This proto library is used for non - android NTPs below.
@@ -1268,10 +1274,16 @@
     "predictors/resource_prefetch_predictor_tables.h",
     "prefetch/search_prefetch/field_trial_settings.cc",
     "prefetch/search_prefetch/field_trial_settings.h",
+    "prefetch/search_prefetch/prefetched_response_container.cc",
+    "prefetch/search_prefetch/prefetched_response_container.h",
+    "prefetch/search_prefetch/search_prefetch_from_string_url_loader.cc",
+    "prefetch/search_prefetch/search_prefetch_from_string_url_loader.h",
     "prefetch/search_prefetch/search_prefetch_service.cc",
     "prefetch/search_prefetch/search_prefetch_service.h",
     "prefetch/search_prefetch/search_prefetch_service_factory.cc",
     "prefetch/search_prefetch/search_prefetch_service_factory.h",
+    "prefetch/search_prefetch/search_prefetch_url_loader_interceptor.cc",
+    "prefetch/search_prefetch/search_prefetch_url_loader_interceptor.h",
     "prefs/browser_prefs.cc",
     "prefs/browser_prefs.h",
     "prefs/chrome_command_line_pref_store.cc",
@@ -1919,6 +1931,7 @@
     "//chrome/browser/safe_browsing",
     "//chrome/browser/safe_browsing:advanced_protection",
     "//chrome/browser/safe_browsing:url_lookup_service_factory",
+    "//chrome/browser/search/recipe_tasks:mojo_bindings",
     "//chrome/browser/search/shopping_tasks:mojo_bindings",
     "//chrome/browser/sharing:buildflags",
     "//chrome/browser/sharing/proto",
@@ -2413,8 +2426,6 @@
       "android/background_task_scheduler/chrome_background_task_factory.h",
       "android/background_task_scheduler/proxy_native_task.cc",
       "android/background_task_scheduler/proxy_native_task.h",
-      "android/battery/android_battery_metrics.cc",
-      "android/battery/android_battery_metrics.h",
       "android/bookmarks/bookmark_bridge.cc",
       "android/bookmarks/bookmark_bridge.h",
       "android/bookmarks/partner_bookmarks_reader.cc",
@@ -3186,6 +3197,7 @@
       "//components/payments/content/android",
       "//components/payments/content/android:jni_headers",
       "//components/permissions/android:native",
+      "//components/power_metrics",
       "//components/query_tiles",
       "//components/resources:android_resources",
       "//components/resources:components_resources",
@@ -3735,6 +3747,12 @@
       "search/promos/promo_service_factory.cc",
       "search/promos/promo_service_factory.h",
       "search/promos/promo_service_observer.h",
+      "search/recipe_tasks/recipe_tasks_handler.cc",
+      "search/recipe_tasks/recipe_tasks_handler.h",
+      "search/recipe_tasks/recipe_tasks_service.cc",
+      "search/recipe_tasks/recipe_tasks_service.h",
+      "search/recipe_tasks/recipe_tasks_service_factory.cc",
+      "search/recipe_tasks/recipe_tasks_service_factory.h",
       "search/search_engine_base_url_tracker.cc",
       "search/search_engine_base_url_tracker.h",
       "search/search_provider_observer.cc",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index 4f60e5a..e845988 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -216,6 +216,7 @@
   "+components/permissions",
   "+components/pdf/browser",
   "+components/policy",
+  "+components/power_metrics",
   "+components/pref_registry",
   "+components/prefs",
   "+components/prerender",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index cc0a0e3f..19c1797 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2726,10 +2726,6 @@
      flag_descriptions::kBluetoothFixA2dpPacketSizeName,
      flag_descriptions::kBluetoothFixA2dpPacketSizeDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(chromeos::features::kBluetoothFixA2dpPacketSize)},
-    {"bluetooth-next-handsfree-profile",
-     flag_descriptions::kBluetoothNextHandsfreeProfileName,
-     flag_descriptions::kBluetoothNextHandsfreeProfileDescription, kOsCrOS,
-     FEATURE_VALUE_TYPE(chromeos::features::kBluetoothNextHandsfreeProfile)},
     {"cryptauth-v2-device-activity-status",
      flag_descriptions::kCryptAuthV2DeviceActivityStatusName,
      flag_descriptions::kCryptAuthV2DeviceActivityStatusDescription, kOsCrOS,
@@ -3418,6 +3414,10 @@
     {"video-tutorials", flag_descriptions::kVideoTutorialsName,
      flag_descriptions::kVideoTutorialsDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(video_tutorials::features::kVideoTutorials)},
+    {"video-tutorials-instant-fetch",
+     flag_descriptions::kVideoTutorialsInstantFetchName,
+     flag_descriptions::kVideoTutorialsInstantFetchDescription, kOsAndroid,
+     SINGLE_VALUE_TYPE(video_tutorials::switches::kVideoTutorialsInstantFetch)},
     {"android-picture-in-picture-api",
      flag_descriptions::kAndroidPictureInPictureAPIName,
      flag_descriptions::kAndroidPictureInPictureAPIDescription, kOsAndroid,
@@ -4364,6 +4364,10 @@
      flag_descriptions::kNtpModulesDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(ntp_features::kModules)},
 
+    {"ntp-recipe-tasks-module", flag_descriptions::kNtpRecipeTasksModuleName,
+     flag_descriptions::kNtpRecipeTasksModuleDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(ntp_features::kNtpRecipeTasksModule)},
+
     {"ntp-shopping-tasks-module",
      flag_descriptions::kNtpShoppingTasksModuleName,
      flag_descriptions::kNtpShoppingTasksModuleDescription, kOsDesktop,
@@ -6185,6 +6189,11 @@
     {"enhanced_clipboard", flag_descriptions::kEnhancedClipboardName,
      flag_descriptions::kEnhancedClipboardDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(chromeos::features::kClipboardHistory)},
+    {"enhanced_clipboard_nudge_session_reset",
+     flag_descriptions::kEnhancedClipboardNudgeSessionResetName,
+     flag_descriptions::kEnhancedClipboardNudgeSessionResetDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(
+         chromeos::features::kClipboardHistoryNudgeSessionReset)},
     {"enhanced_clipboard_simple_render",
      flag_descriptions::kEnhancedClipboardSimpleRenderName,
      flag_descriptions::kEnhancedClipboardSimpleRenderDescription, kOsCrOS,
diff --git a/chrome/browser/about_flags_unittest.cc b/chrome/browser/about_flags_unittest.cc
index c8acbc28..c760888 100644
--- a/chrome/browser/about_flags_unittest.cc
+++ b/chrome/browser/about_flags_unittest.cc
@@ -151,7 +151,14 @@
   }
 };
 
-TEST_F(AboutFlagsHistogramTest, CheckHistograms) {
+// http://crbug.com/1141271
+#if defined(OS_LINUX)
+#define MAYBE_CheckHistograms DISABLED_CheckHistograms
+#else
+#define MAYBE_CheckHistograms CheckHistograms
+#endif
+
+TEST_F(AboutFlagsHistogramTest, MAYBE_CheckHistograms) {
   base::Optional<base::HistogramEnumEntryMap> login_custom_flags =
       base::ReadEnumFromEnumsXml("LoginCustomFlags");
   ASSERT_TRUE(login_custom_flags)
diff --git a/chrome/browser/android/compositor/OWNERS b/chrome/browser/android/compositor/OWNERS
index 85f91af..31a83b8c 100644
--- a/chrome/browser/android/compositor/OWNERS
+++ b/chrome/browser/android/compositor/OWNERS
@@ -5,5 +5,5 @@
 per-file *contextual_search*=twellington@chromium.org
 
 # COMPONENT: UI>Browser>Mobile>CompositedUI
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
 # OS: Android
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
index 1db984c..cab5a51 100644
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -3739,6 +3739,43 @@
             node_data.GetStringAttribute(ax::mojom::StringAttribute::kName));
 }
 
+// Validate that an inner frame within a guest WebContents correctly receives
+// focus when requested by accessibility. Previously the root
+// BrowserAccessibilityManager would not be updated due to how we were updating
+// the AXTreeData.
+IN_PROC_BROWSER_TEST_F(WebViewAccessibilityTest,
+                       FocusAccessibilityNestedFrame) {
+  LoadAppWithGuest("web_view/focus_accessibility");
+  content::WebContents* web_contents = GetFirstAppWindowWebContents();
+  content::EnableAccessibilityForWebContents(web_contents);
+  content::WebContents* guest_web_contents = GetGuestWebContents();
+  content::EnableAccessibilityForWebContents(guest_web_contents);
+
+  // Wait for focus to land on the "root web area" role, representing
+  // focus on the main document itself.
+  while (content::GetFocusedAccessibilityNodeInfo(web_contents).role !=
+         ax::mojom::Role::kRootWebArea) {
+    content::WaitForAccessibilityFocusChange();
+  }
+
+  // Now keep pressing the Tab key until focus lands on a text field.
+  // This is testing that the inner frame within the guest WebContents receives
+  // focus, and that the focus state is accurately reflected in the accessiblity
+  // state.
+  while (content::GetFocusedAccessibilityNodeInfo(web_contents).role !=
+         ax::mojom::Role::kTextField) {
+    content::SimulateKeyPress(web_contents, ui::DomKey::FromCharacter('\t'),
+                              ui::DomCode::TAB, ui::VKEY_TAB, false, false,
+                              false, false);
+    content::WaitForAccessibilityFocusChange();
+  }
+
+  ui::AXNodeData node_data =
+      content::GetFocusedAccessibilityNodeInfo(web_contents);
+  EXPECT_EQ("InnerFrameTextField",
+            node_data.GetStringAttribute(ax::mojom::StringAttribute::kName));
+}
+
 class WebContentsAccessibilityEventWatcher
     : public content::WebContentsObserver {
  public:
diff --git a/chrome/browser/apps/user_type_filter.cc b/chrome/browser/apps/user_type_filter.cc
index 6c6c2e01..0fa60466 100644
--- a/chrome/browser/apps/user_type_filter.cc
+++ b/chrome/browser/apps/user_type_filter.cc
@@ -24,7 +24,7 @@
 std::string DetermineUserType(Profile* profile) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(!profile->IsOffTheRecord());
-  if (profile->IsGuestSession())
+  if (profile->IsGuestSession() || profile->IsEphemeralGuestProfile())
     return kUserTypeGuest;
   if (profile->IsChild())
     return kUserTypeChild;
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc
index 7b14269..3f66b574 100644
--- a/chrome/browser/autofill/autofill_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -912,7 +912,13 @@
 }
 
 // Test that autofill works when the website prefills the form.
-IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, PrefillFormAndFill) {
+// TODO(crbug.com/1141208): Disabled due to flakiness on MAC
+#if defined(OS_MAC)
+#define MAYBE_PrefillFormAndFill DISABLED_PrefillFormAndFill
+#else
+#define MAYBE_PrefillFormAndFill PrefillFormAndFill
+#endif
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, MAYBE_PrefillFormAndFill) {
   const char kPrefillScript[] =
       "<script>"
       "document.getElementById('firstname').value = 'Seb';"
diff --git a/chrome/browser/battery/battery_metrics.cc b/chrome/browser/battery/battery_metrics.cc
index a53621b..3ccdafd 100644
--- a/chrome/browser/battery/battery_metrics.cc
+++ b/chrome/browser/battery/battery_metrics.cc
@@ -22,10 +22,30 @@
   return *binder;
 }
 
+#if defined(OS_ANDROID)
+bool IsAppVisible(base::android::ApplicationState state) {
+  return state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES;
+}
+#endif  // defined(OS_ANDROID)
+
 }  // namespace
 
 BatteryMetrics::BatteryMetrics() {
   StartRecording();
+
+#if defined(OS_ANDROID)
+  // On Android, also track the battery capacity drain while Chrome is the
+  // foreground activity.
+  app_state_listener_ =
+      base::android::ApplicationStatusListener::New(base::BindRepeating(
+          [](BatteryMetrics* metrics, base::android::ApplicationState state) {
+            metrics->android_metrics_.OnAppVisibilityChanged(
+                IsAppVisible(state));
+          },
+          base::Unretained(this)));
+  android_metrics_.OnAppVisibilityChanged(
+      IsAppVisible(base::android::ApplicationStatusListener::GetState()));
+#endif  // defined(OS_ANDROID)
 }
 
 BatteryMetrics::~BatteryMetrics() = default;
diff --git a/chrome/browser/battery/battery_metrics.h b/chrome/browser/battery/battery_metrics.h
index 11e216b..bdb5893 100644
--- a/chrome/browser/battery/battery_metrics.h
+++ b/chrome/browser/battery/battery_metrics.h
@@ -17,7 +17,8 @@
 #include "services/device/public/mojom/battery_status.mojom-forward.h"
 
 #if defined(OS_ANDROID)
-#include "chrome/browser/android/battery/android_battery_metrics.h"
+#include "base/android/application_status_listener.h"
+#include "components/power_metrics/android_battery_metrics.h"
 #endif  // defined(OS_ANDROID)
 
 // Records metrics around battery usage on all platforms. Connects to
@@ -55,7 +56,8 @@
   mojo::Remote<device::mojom::BatteryMonitor> battery_monitor_;
 
 #if defined(OS_ANDROID)
-  AndroidBatteryMetrics android_metrics_;
+  power_metrics::AndroidBatteryMetrics android_metrics_;
+  std::unique_ptr<base::android::ApplicationStatusListener> app_state_listener_;
 #endif  // defined(OS_ANDROID)
 
   SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chrome/browser/browser_commands_unittest.cc b/chrome/browser/browser_commands_unittest.cc
index 4ba8644..4c7dfd2a 100644
--- a/chrome/browser/browser_commands_unittest.cc
+++ b/chrome/browser/browser_commands_unittest.cc
@@ -30,7 +30,7 @@
 #include "content/public/test/test_renderer_host.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/page/page_zoom.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 
 namespace {
 
@@ -479,7 +479,7 @@
   for (int i = 0; i < tab_count; ++i) {
     WebContents* web_contents =
         browser()->tab_strip_model()->GetWebContentsAt(i);
-    blink::mojom::RendererPreferences* renderer_preferences =
+    blink::RendererPreferences* renderer_preferences =
         web_contents->GetMutableRendererPrefs();
     EXPECT_TRUE(renderer_preferences->caret_browsing_enabled);
   }
@@ -497,7 +497,7 @@
   for (int i = 0; i < tab_count; ++i) {
     WebContents* web_contents =
         browser()->tab_strip_model()->GetWebContentsAt(i);
-    blink::mojom::RendererPreferences* renderer_preferences =
+    blink::RendererPreferences* renderer_preferences =
         web_contents->GetMutableRendererPrefs();
     EXPECT_FALSE(renderer_preferences->caret_browsing_enabled);
   }
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index d081fd4..17de70e 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -873,6 +873,7 @@
   ~MockReportingService() override = default;
 
   void QueueReport(const GURL& url,
+                   const net::NetworkIsolationKey& network_isolation_key,
                    const std::string& user_agent,
                    const std::string& group,
                    const std::string& type,
@@ -882,6 +883,7 @@
   }
 
   void ProcessHeader(const GURL& url,
+                     const net::NetworkIsolationKey& network_isolation_key,
                      const std::string& header_value) override {
     NOTREACHED();
   }
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc
index 0a8a486..9a8d3d6 100644
--- a/chrome/browser/chrome_browser_interface_binders.cc
+++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -109,6 +109,7 @@
 #include "chrome/browser/payments/payment_request_factory.h"
 #include "chrome/browser/promo_browser_command/promo_browser_command.mojom.h"
 #include "chrome/browser/search/ntp_features.h"
+#include "chrome/browser/search/recipe_tasks/recipe_tasks.mojom.h"
 #include "chrome/browser/search/shopping_tasks/shopping_tasks.mojom.h"
 #include "chrome/browser/speech/speech_recognition_client_browser_interface.h"
 #include "chrome/browser/speech/speech_recognition_client_browser_interface_factory.h"
@@ -642,6 +643,11 @@
   RegisterWebUIControllerInterfaceBinder<media_feeds::mojom::MediaFeedsStore,
                                          MediaFeedsUI>(map);
 
+  if (base::FeatureList::IsEnabled(ntp_features::kNtpRecipeTasksModule)) {
+    RegisterWebUIControllerInterfaceBinder<
+        recipe_tasks::mojom::RecipeTasksHandler, NewTabPageUI>(map);
+  }
+
   if (base::FeatureList::IsEnabled(ntp_features::kNtpShoppingTasksModule)) {
     RegisterWebUIControllerInterfaceBinder<
         shopping_tasks::mojom::ShoppingTasksHandler, NewTabPageUI>(map);
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 44be095..78546ffd4 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -91,6 +91,10 @@
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/plugins/pdf_iframe_navigation_throttle.h"
 #include "chrome/browser/plugins/plugin_utils.h"
+#include "chrome/browser/prefetch/search_prefetch/field_trial_settings.h"
+#include "chrome/browser/prefetch/search_prefetch/search_prefetch_service.h"
+#include "chrome/browser/prefetch/search_prefetch/search_prefetch_service_factory.h"
+#include "chrome/browser/prefetch/search_prefetch/search_prefetch_url_loader_interceptor.h"
 #include "chrome/browser/prerender/chrome_prerender_contents_delegate.h"
 #include "chrome/browser/prerender/isolated/isolated_prerender_features.h"
 #include "chrome/browser/prerender/isolated/isolated_prerender_service.h"
@@ -350,8 +354,8 @@
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/loader/referrer_utils.h"
 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/common/switches.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "third_party/blink/public/mojom/site_engagement/site_engagement.mojom.h"
 #include "third_party/blink/public/mojom/user_agent/user_agent_metadata.mojom.h"
 #include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom.h"
@@ -2468,7 +2472,7 @@
 
 void ChromeContentBrowserClient::UpdateRendererPreferencesForWorker(
     content::BrowserContext* browser_context,
-    blink::mojom::RendererPreferences* out_prefs) {
+    blink::RendererPreferences* out_prefs) {
   DCHECK(browser_context);
   DCHECK(out_prefs);
   renderer_preferences_util::UpdateFromSystemSettings(
@@ -4770,6 +4774,11 @@
             frame_tree_node_id));
   }
 
+  if (SearchPrefetchServiceIsEnabled()) {
+    interceptors.push_back(std::make_unique<SearchPrefetchURLLoaderInterceptor>(
+        frame_tree_node_id));
+  }
+
   return interceptors;
 }
 
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 4dbca0a..ee1d227 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -232,7 +232,7 @@
   bool IsDataSaverEnabled(content::BrowserContext* context) override;
   void UpdateRendererPreferencesForWorker(
       content::BrowserContext* browser_context,
-      blink::mojom::RendererPreferences* out_prefs) override;
+      blink::RendererPreferences* out_prefs) override;
   bool AllowAppCache(const GURL& manifest_url,
 
                      const GURL& site_for_cookies,
diff --git a/chrome/browser/chrome_do_not_track_browsertest.cc b/chrome/browser/chrome_do_not_track_browsertest.cc
index 7a5065c3..7a9bf9f4 100644
--- a/chrome/browser/chrome_do_not_track_browsertest.cc
+++ b/chrome/browser/chrome_do_not_track_browsertest.cc
@@ -15,7 +15,7 @@
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 
 namespace {
 
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 315e8c9..fbfb52e 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -3853,6 +3853,8 @@
     "//chromeos/cryptohome:test_support",
     "//chromeos/dbus:lorgnette_proto",
     "//chromeos/dbus:test_support",
+    "//chromeos/dbus/attestation",
+    "//chromeos/dbus/attestation:attestation_proto",
     "//chromeos/dbus/authpolicy",
     "//chromeos/dbus/cryptohome",
     "//chromeos/dbus/cryptohome:attestation_proto",
diff --git a/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge.cc b/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge.cc
index 838f3d5..60f84aac 100644
--- a/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge.cc
+++ b/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge.cc
@@ -189,8 +189,8 @@
 
   GetNSSCertDatabaseForProfile(
       Profile::FromBrowserContext(context_),
-      base::Bind(&ArcCertStoreBridge::OnGetNSSCertDatabaseForProfile,
-                 weak_ptr_factory_.GetWeakPtr(), base::Passed(&callback)));
+      base::BindOnce(&ArcCertStoreBridge::OnGetNSSCertDatabaseForProfile,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
 void ArcCertStoreBridge::GetKeyCharacteristics(
diff --git a/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge_browsertest.cc b/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge_browsertest.cc
index 3b2a626..69953ed 100644
--- a/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge_browsertest.cc
+++ b/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge_browsertest.cc
@@ -247,8 +247,8 @@
     base::RunLoop loop;
     GetNSSCertDatabaseForProfile(
         browser()->profile(),
-        base::Bind(&ArcCertStoreBridgeTest::SetUpTestClientCerts,
-                   base::Unretained(this), loop.QuitClosure()));
+        base::BindOnce(&ArcCertStoreBridgeTest::SetUpTestClientCerts,
+                       base::Unretained(this), loop.QuitClosure()));
     loop.Run();
     // Certificates must be imported.
     ASSERT_NE(nullptr, client_cert1_);
diff --git a/chrome/browser/chromeos/attestation/attestation_policy_browsertest.cc b/chrome/browser/chromeos/attestation/attestation_policy_browsertest.cc
index 2549de0..06cbbf4 100644
--- a/chrome/browser/chromeos/attestation/attestation_policy_browsertest.cc
+++ b/chrome/browser/chromeos/attestation/attestation_policy_browsertest.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/chromeos/settings/device_settings_service.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chromeos/dbus/attestation/fake_attestation_client.h"
 #include "chromeos/dbus/cryptohome/fake_cryptohome_client.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "content/public/test/browser_test.h"
@@ -64,7 +65,8 @@
   PlatformVerificationFlow::Result SyncContentProtectionAttestation() {
     scoped_refptr<PlatformVerificationFlow> verifier(
         new PlatformVerificationFlow(
-            nullptr, nullptr, chromeos::FakeCryptohomeClient::Get(), nullptr));
+            nullptr, nullptr, chromeos::FakeCryptohomeClient::Get(),
+            chromeos::FakeAttestationClient::Get(), nullptr));
     verifier->ChallengePlatformKey(
         browser()->tab_strip_model()->GetActiveWebContents(), "fake_service_id",
         "fake_challenge",
diff --git a/chrome/browser/chromeos/attestation/platform_verification_flow.cc b/chrome/browser/chromeos/attestation/platform_verification_flow.cc
index f4260e0..bd53df4 100644
--- a/chrome/browser/chromeos/attestation/platform_verification_flow.cc
+++ b/chrome/browser/chromeos/attestation/platform_verification_flow.cc
@@ -23,6 +23,8 @@
 #include "chromeos/cryptohome/async_method_caller.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/dbus/attestation/attestation.pb.h"
+#include "chromeos/dbus/attestation/attestation_client.h"
+#include "chromeos/dbus/attestation/interface.pb.h"
 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
@@ -52,22 +54,6 @@
     "ChromeOS.PlatformVerification.Available";
 const int kOpportunisticRenewalThresholdInDays = 30;
 
-// A callback method to handle DBus errors.
-// `on_success` and `on_failure` are called mutally exclusively,
-// and `context` is moved into the chosen callback.
-template <typename ContextT>
-void DBusCallback(base::OnceCallback<void(ContextT, bool)> on_success,
-                  base::OnceCallback<void(ContextT)> on_failure,
-                  ContextT context,
-                  base::Optional<bool> result) {
-  if (result.has_value()) {
-    std::move(on_success).Run(std::move(context), result.value());
-  } else {
-    LOG(ERROR) << "PlatformVerificationFlow: DBus call failed!";
-    std::move(on_failure).Run(std::move(context));
-  }
-}
-
 // A helper to call a ChallengeCallback with an error result.
 void ReportError(
     PlatformVerificationFlow::ChallengeCallback callback,
@@ -153,6 +139,7 @@
     : attestation_flow_(NULL),
       async_caller_(cryptohome::AsyncMethodCaller::GetInstance()),
       cryptohome_client_(CryptohomeClient::Get()),
+      attestation_client_(AttestationClient::Get()),
       delegate_(NULL),
       timeout_delay_(base::TimeDelta::FromSeconds(kTimeoutInSeconds)) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -168,10 +155,12 @@
     AttestationFlow* attestation_flow,
     cryptohome::AsyncMethodCaller* async_caller,
     CryptohomeClient* cryptohome_client,
+    AttestationClient* attestation_client,
     Delegate* delegate)
     : attestation_flow_(attestation_flow),
       async_caller_(async_caller),
       cryptohome_client_(cryptohome_client),
+      attestation_client_(attestation_client),
       delegate_(delegate),
       timeout_delay_(base::TimeDelta::FromSeconds(kTimeoutInSeconds)) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -227,18 +216,23 @@
                            std::move(callback));
 
   // Check if the device has been prepared to use attestation.
-  cryptohome_client_->TpmAttestationIsPrepared(base::BindOnce(
-      &DBusCallback<ChallengeContext>,
-      base::Bind(&PlatformVerificationFlow::OnAttestationPrepared, this),
-      base::Bind([](ChallengeContext context) {
-        ReportError(std::move(context).callback, INTERNAL_ERROR);
-      }),
-      std::move(context)));
+  ::attestation::GetEnrollmentPreparationsRequest request;
+  attestation_client_->GetEnrollmentPreparations(
+      request, base::BindOnce(&PlatformVerificationFlow::OnAttestationPrepared,
+                              this, std::move(context)));
 }
 
 void PlatformVerificationFlow::OnAttestationPrepared(
     ChallengeContext context,
-    bool attestation_prepared) {
+    const ::attestation::GetEnrollmentPreparationsReply& reply) {
+  if (reply.status() != ::attestation::STATUS_SUCCESS) {
+    LOG(ERROR)
+        << "Platform verification failed to check if attestation is prepared.";
+    ReportError(std::move(context).callback, INTERNAL_ERROR);
+    return;
+  }
+  const bool attestation_prepared =
+      AttestationClient::IsAttestationPrepared(reply);
   UMA_HISTOGRAM_BOOLEAN(kAttestationAvailableHistogram, attestation_prepared);
 
   if (!attestation_prepared) {
diff --git a/chrome/browser/chromeos/attestation/platform_verification_flow.h b/chrome/browser/chromeos/attestation/platform_verification_flow.h
index 2e68bb4..a28cdfb7 100644
--- a/chrome/browser/chromeos/attestation/platform_verification_flow.h
+++ b/chrome/browser/chromeos/attestation/platform_verification_flow.h
@@ -14,6 +14,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
+#include "chromeos/dbus/attestation/interface.pb.h"
 #include "chromeos/dbus/constants/attestation_constants.h"
 #include "url/gurl.h"
 
@@ -33,6 +34,7 @@
 
 namespace chromeos {
 
+class AttestationClient;
 class CryptohomeClient;
 
 namespace attestation {
@@ -130,6 +132,7 @@
   PlatformVerificationFlow(AttestationFlow* attestation_flow,
                            cryptohome::AsyncMethodCaller* async_caller,
                            CryptohomeClient* cryptohome_client,
+                           AttestationClient* attestation_client,
                            Delegate* delegate);
 
   // Invokes an asynchronous operation to challenge a platform key.  Any user
@@ -174,10 +177,10 @@
   ~PlatformVerificationFlow();
 
   // Callback for attestation preparation. The arguments to ChallengePlatformKey
-  // are in |context|, and |attestation_prepared| specifies whether attestation
-  // has been prepared on this device.
-  void OnAttestationPrepared(ChallengeContext context,
-                             bool attestation_prepared);
+  // are in |context|, and |reply| is the result of |GetEnrollmentPreparations|.
+  void OnAttestationPrepared(
+      ChallengeContext context,
+      const ::attestation::GetEnrollmentPreparationsReply& reply);
 
   // Initiates the flow to get a platform key certificate.  The arguments to
   // ChallengePlatformKey are in |context|.  |account_id| identifies the user
@@ -193,11 +196,11 @@
   // completes.  The arguments to ChallengePlatformKey are in |context|.
   // |account_id| identifies the user for which the certificate was requested.
   // |operation_success| is true iff the certificate request operation
-  // succeeded.  |certificate_chain| holds the certificate for the platform key
-  // on success.  If the certificate request was successful, this method invokes
-  // a request to sign the challenge.  If the operation timed out prior to this
-  // method being called, this method does nothing - notably, the callback is
-  // not invoked.
+  // succeeded.  |certificate_chain| holds the certificate for the platform
+  // key on success.  If the certificate request was successful, this method
+  // invokes a request to sign the challenge.  If the operation timed out
+  // prior to this method being called, this method does nothing - notably,
+  // the callback is not invoked.
   void OnCertificateReady(
       scoped_refptr<base::RefCountedData<ChallengeContext>> context,
       const AccountId& account_id,
@@ -243,7 +246,8 @@
   AttestationFlow* attestation_flow_;
   std::unique_ptr<AttestationFlow> default_attestation_flow_;
   cryptohome::AsyncMethodCaller* async_caller_;
-  CryptohomeClient* cryptohome_client_;
+  CryptohomeClient* const cryptohome_client_;
+  AttestationClient* const attestation_client_;
   Delegate* delegate_;
   std::unique_ptr<Delegate> default_delegate_;
   base::TimeDelta timeout_delay_;
diff --git a/chrome/browser/chromeos/attestation/platform_verification_flow_unittest.cc b/chrome/browser/chromeos/attestation/platform_verification_flow_unittest.cc
index 4b8330e..79aa24fa 100644
--- a/chrome/browser/chromeos/attestation/platform_verification_flow_unittest.cc
+++ b/chrome/browser/chromeos/attestation/platform_verification_flow_unittest.cc
@@ -20,7 +20,8 @@
 #include "chromeos/attestation/mock_attestation_flow.h"
 #include "chromeos/cryptohome/mock_async_method_caller.h"
 #include "chromeos/dbus/attestation/attestation.pb.h"
-#include "chromeos/dbus/cryptohome/fake_cryptohome_client.h"
+#include "chromeos/dbus/attestation/fake_attestation_client.h"
+#include "chromeos/dbus/attestation/interface.pb.h"
 #include "chromeos/settings/cros_settings_names.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -102,14 +103,21 @@
       : certificate_status_(ATTESTATION_SUCCESS),
         fake_certificate_index_(0),
         sign_challenge_success_(true),
-        result_(PlatformVerificationFlow::INTERNAL_ERROR) {}
+        result_(PlatformVerificationFlow::INTERNAL_ERROR) {
+    ::chromeos::AttestationClient::InitializeFake();
+  }
+  ~PlatformVerificationFlowTest() override {
+    ::chromeos::AttestationClient::Shutdown();
+  }
 
   void SetUp() {
     // Create a verifier for tests to call.
-    verifier_ = new PlatformVerificationFlow(&mock_attestation_flow_,
-                                             &mock_async_caller_,
-                                             &fake_cryptohome_client_,
-                                             &fake_delegate_);
+    // We don't need cryptohome_client in unittests because it is only needed
+    // for real AttestationFlow and in unittests we uses mocked one.
+    verifier_ = new PlatformVerificationFlow(
+        &mock_attestation_flow_, &mock_async_caller_,
+        /*cryptohome_client=*/nullptr, AttestationClient::Get(),
+        &fake_delegate_);
 
     // Create callbacks for tests to use with verifier_.
     settings_helper_.ReplaceDeviceSettingsProviderWithStub();
@@ -184,7 +192,6 @@
   content::BrowserTaskEnvironment task_environment_;
   StrictMock<MockAttestationFlow> mock_attestation_flow_;
   cryptohome::MockAsyncMethodCaller mock_async_caller_;
-  chromeos::FakeCryptohomeClient fake_cryptohome_client_;
   FakeDelegate fake_delegate_;
   ScopedCrosSettingsTestHelper settings_helper_;
   scoped_refptr<PlatformVerificationFlow> verifier_;
@@ -259,7 +266,20 @@
 }
 
 TEST_F(PlatformVerificationFlowTest, DBusFailure) {
-  fake_cryptohome_client_.SetServiceIsAvailable(false);
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->ConfigureEnrollmentPreparationsStatus(::attestation::STATUS_DBUS_ERROR);
+  verifier_->ChallengePlatformKey(nullptr, kTestID, kTestChallenge,
+                                  CreateChallengeCallback());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(PlatformVerificationFlow::INTERNAL_ERROR, result_);
+}
+
+TEST_F(PlatformVerificationFlowTest, AttestationServiceInternalError) {
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->ConfigureEnrollmentPreparationsStatus(
+          ::attestation::STATUS_UNEXPECTED_DEVICE_ERROR);
   verifier_->ChallengePlatformKey(nullptr, kTestID, kTestChallenge,
                                   CreateChallengeCallback());
   base::RunLoop().RunUntilIdle();
@@ -380,8 +400,9 @@
 }
 
 TEST_F(PlatformVerificationFlowTest, AttestationNotPrepared) {
-  fake_cryptohome_client_.set_tpm_attestation_is_enrolled(false);
-  fake_cryptohome_client_.set_tpm_attestation_is_prepared(false);
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->ConfigureEnrollmentPreparations(false);
   verifier_->ChallengePlatformKey(nullptr, kTestID, kTestChallenge,
                                   CreateChallengeCallback());
   base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/chromeos/crosapi/keystore_service_ash.cc b/chrome/browser/chromeos/crosapi/keystore_service_ash.cc
index 7730897..637b40f 100644
--- a/chrome/browser/chromeos/crosapi/keystore_service_ash.cc
+++ b/chrome/browser/chromeos/crosapi/keystore_service_ash.cc
@@ -31,8 +31,8 @@
     ChallengeAttestationOnlyKeystoreCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!crosapi::mojom::IsKnownEnumValue(type)) {
-    mojom::ChallengeAttestationOnlyKeystoreResultPtr result_ptr =
-        mojom::ChallengeAttestationOnlyKeystoreResult::New();
+    crosapi::mojom::KeystoreStringResultPtr result_ptr =
+        mojom::KeystoreStringResult::New();
     result_ptr->set_error_message("unsupported keystore type");
     std::move(callback).Run(std::move(result_ptr));
     return;
@@ -110,8 +110,8 @@
     void* challenge_key_ptr,
     const chromeos::attestation::TpmChallengeKeyResult& result) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  mojom::ChallengeAttestationOnlyKeystoreResultPtr result_ptr =
-      mojom::ChallengeAttestationOnlyKeystoreResult::New();
+  crosapi::mojom::KeystoreStringResultPtr result_ptr =
+      mojom::KeystoreStringResult::New();
   if (result.IsSuccess()) {
     result_ptr->set_challenge_response(result.challenge_response);
   } else {
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc
index 667d978..46327e6 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.cc
+++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -521,13 +521,15 @@
       crostini_manager_->GetContainerSshKeys(
           container_id_,
           base::BindOnce(&CrostiniRestarter::GetContainerSshKeysFinished,
-                         weak_ptr_factory_.GetWeakPtr(), info->username));
+                         weak_ptr_factory_.GetWeakPtr(), info->username,
+                         info->homedir));
     } else {
       FinishRestart(result);
     }
   }
 
   void GetContainerSshKeysFinished(const std::string& container_username,
+                                   const base::FilePath& container_homedir,
                                    bool success,
                                    const std::string& container_public_key,
                                    const std::string& host_private_key,
@@ -551,6 +553,7 @@
     // Call to sshfs to mount.
     source_path_ = base::StringPrintf(
         "sshfs://%s@%s:", container_username.c_str(), hostname.c_str());
+    container_homedir_ = container_homedir;
     StartStage(mojom::InstallerState::kMountContainer);
     dmgr->MountPath(source_path_, "",
                     file_manager::util::GetCrostiniMountPointName(profile_),
@@ -603,7 +606,7 @@
 
     // VolumeManager is null in unittest.
     if (auto* vmgr = file_manager::VolumeManager::Get(profile_))
-      vmgr->AddSshfsCrostiniVolume(mount_path);
+      vmgr->AddSshfsCrostiniVolume(mount_path, container_homedir_);
 
     // Abort not checked until exiting this function.  On abort, do not
     // continue, but still remove observer and add volume as per above.
@@ -623,6 +626,7 @@
   base::FilePath disk_path_;
   RestartOptions options_;
   std::string source_path_;
+  base::FilePath container_homedir_;
   bool is_initial_install_ = false;
   CrostiniManager::CrostiniResultCallback completed_callback_;
   std::vector<base::OnceClosure> abort_callbacks_;
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
index 0d98b0fe..ad5aafd 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
@@ -411,6 +411,10 @@
     volume_metadata->source_path =
         std::make_unique<std::string>(volume.source_path().AsUTF8Unsafe());
   }
+  if (!volume.remote_mount_path().empty()) {
+    volume_metadata->remote_mount_path =
+        std::make_unique<std::string>(volume.remote_mount_path().value());
+  }
 
   switch (volume.source()) {
     case SOURCE_FILE:
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
index 673eec7c..c77980e 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -1091,6 +1091,7 @@
 WRAPPED_INSTANTIATE_TEST_SUITE_P(
     Trash, /* trash.js */
     FilesAppBrowserTest,
-    ::testing::Values(TestCase("trashMoveToTrash").EnableTrash()));
+    ::testing::Values(TestCase("trashMoveToTrash").EnableTrash(),
+                      TestCase("trashRestore").EnableTrash()));
 
 }  // namespace file_manager
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.cc b/chrome/browser/chromeos/file_manager/volume_manager.cc
index 2294f68..77b357b 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager.cc
+++ b/chrome/browser/chromeos/file_manager/volume_manager.cc
@@ -372,13 +372,15 @@
 
 // static
 std::unique_ptr<Volume> Volume::CreateForSshfsCrostini(
-    const base::FilePath& sshfs_mount_path) {
+    const base::FilePath& sshfs_mount_path,
+    const base::FilePath& remote_mount_path) {
   std::unique_ptr<Volume> volume(new Volume());
   volume->type_ = VOLUME_TYPE_CROSTINI;
   volume->device_type_ = chromeos::DEVICE_TYPE_UNKNOWN;
   // Keep source_path empty.
   volume->source_ = SOURCE_SYSTEM;
   volume->mount_path_ = sshfs_mount_path;
+  volume->remote_mount_path_ = remote_mount_path;
   volume->mount_condition_ = chromeos::disks::MOUNT_CONDITION_NONE;
   volume->volume_id_ = GenerateVolumeId(*volume);
   volume->watchable_ = false;
@@ -665,10 +667,11 @@
 }
 
 void VolumeManager::AddSshfsCrostiniVolume(
-    const base::FilePath& sshfs_mount_path) {
+    const base::FilePath& sshfs_mount_path,
+    const base::FilePath& remote_mount_path) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   std::unique_ptr<Volume> volume =
-      Volume::CreateForSshfsCrostini(sshfs_mount_path);
+      Volume::CreateForSshfsCrostini(sshfs_mount_path, remote_mount_path);
   // Ignore if volume already exists.
   if (mounted_volumes_.find(volume->volume_id()) != mounted_volumes_.end())
     return;
@@ -763,7 +766,7 @@
           path);
   DoMountEvent(
       success ? chromeos::MOUNT_ERROR_NONE : chromeos::MOUNT_ERROR_INVALID_PATH,
-      Volume::CreateForSshfsCrostini(path));
+      Volume::CreateForSshfsCrostini(path, base::FilePath("/home/testuser")));
   return true;
 }
 
@@ -1478,8 +1481,9 @@
       (error_code == chromeos::MOUNT_ERROR_PATH_NOT_MOUNTED)) {
     // Remove metadata associated with the mount. It will be a no-op if it
     // wasn't mounted or unmounted out of band.
-    DoUnmountEvent(chromeos::MOUNT_ERROR_NONE,
-                   *Volume::CreateForSshfsCrostini(sshfs_mount_path));
+    DoUnmountEvent(
+        chromeos::MOUNT_ERROR_NONE,
+        *Volume::CreateForSshfsCrostini(sshfs_mount_path, base::FilePath()));
     if (callback)
       std::move(callback).Run(true);
     return;
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.h b/chrome/browser/chromeos/file_manager/volume_manager.h
index 5521fc4..199bfd9f 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager.h
+++ b/chrome/browser/chromeos/file_manager/volume_manager.h
@@ -111,7 +111,8 @@
       base::FilePath mount_path,
       const std::string& root_document_id);
   static std::unique_ptr<Volume> CreateForSshfsCrostini(
-      const base::FilePath& crostini_path);
+      const base::FilePath& crostini_path,
+      const base::FilePath& remote_mount_path);
   static std::unique_ptr<Volume> CreateForAndroidFiles(
       const base::FilePath& mount_path);
   static std::unique_ptr<Volume> CreateForDocumentsProvider(
@@ -147,6 +148,7 @@
   chromeos::DeviceType device_type() const { return device_type_; }
   const base::FilePath& source_path() const { return source_path_; }
   const base::FilePath& mount_path() const { return mount_path_; }
+  const base::FilePath& remote_mount_path() const { return remote_mount_path_; }
   chromeos::disks::MountCondition mount_condition() const {
     return mount_condition_;
   }
@@ -212,6 +214,10 @@
   // - /media/archive/zip1
   base::FilePath mount_path_;
 
+  // The path on the remote host where this volume is mounted, for crostini this
+  // is the user's homedir (/home/<username>).
+  base::FilePath remote_mount_path_;
+
   // The mounting condition. See the enum for the details.
   chromeos::disks::MountCondition mount_condition_;
 
@@ -320,7 +326,8 @@
   base::WeakPtr<Volume> FindVolumeById(const std::string& volume_id);
 
   // Add sshfs crostini volume mounted at specified path.
-  void AddSshfsCrostiniVolume(const base::FilePath& sshfs_mount_path);
+  void AddSshfsCrostiniVolume(const base::FilePath& sshfs_mount_path,
+                              const base::FilePath& remote_mount_path);
 
   // Removes specified sshfs crostini mount. Runs |callback| with true if the
   // mount was removed successfully or wasn't mounted to begin with. Runs
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index 882ab2b..4f08021 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -77,6 +77,7 @@
 #include "chrome/browser/ui/webui/chromeos/login/l10n_util.h"
 #include "chrome/browser/ui/webui/chromeos/login/tpm_error_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h"
+#include "chrome/browser/ui/webui/management_ui_handler.h"
 #include "chrome/common/channel_info.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
@@ -1221,6 +1222,14 @@
   user_manager::known_user::SetIsEnterpriseManaged(user_context.GetAccountId(),
                                                    is_enterprise_managed);
 
+  if (is_enterprise_managed) {
+    std::string manager = ManagementUIHandler::GetAccountManager(profile);
+    if (!manager.empty()) {
+      user_manager::known_user::SetAccountManager(user_context.GetAccountId(),
+                                                  manager);
+    }
+  }
+
   // Inform `auth_status_consumers_` about successful login.
   // TODO(nkostylev): Pass UserContext back crbug.com/424550
   for (auto& auth_status_consumer : auth_status_consumers_)
diff --git a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
index 5aac750..0a516c98 100644
--- a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
@@ -25,12 +25,16 @@
 #include "chrome/browser/chromeos/login/existing_user_controller.h"
 #include "chrome/browser/chromeos/login/help_app_launcher.h"
 #include "chrome/browser/chromeos/login/helper.h"
+#include "chrome/browser/chromeos/login/lock/screen_locker_tester.h"
+#include "chrome/browser/chromeos/login/login_manager_test.h"
+#include "chrome/browser/chromeos/login/screens/user_selection_screen.h"
 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
 #include "chrome/browser/chromeos/login/session/user_session_manager_test_api.h"
 #include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/test/login_manager_mixin.h"
 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
+#include "chrome/browser/chromeos/login/test/user_policy_mixin.h"
 #include "chrome/browser/chromeos/login/ui/mock_login_display.h"
 #include "chrome/browser/chromeos/login/ui/mock_login_display_host.h"
 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
@@ -59,6 +63,7 @@
 #include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/settings/cros_settings_names.h"
 #include "chromeos/settings/cros_settings_provider.h"
+#include "chromeos/strings/grit/chromeos_strings.h"
 #include "components/arc/enterprise/arc_data_snapshotd_manager.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
@@ -72,6 +77,7 @@
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
+#include "components/user_manager/known_user.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
@@ -81,6 +87,7 @@
 #include "content/public/test/test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
 
 using ::testing::_;
 using ::testing::AnyNumber;
@@ -102,6 +109,10 @@
 const char kNewGaiaID[] = "11111";
 const char kExistingUser[] = "existing_test_user@gmail.com";
 const char kExistingGaiaID[] = "22222";
+const char kManagedUser[] = "user@example.com";
+const char kManagedGaiaID[] = "33333";
+const char kManager[] = "admin@example.com";
+const char kManagedDomain[] = "example.com";
 const char kUserAllowlist[] = "*@ad-domain.com";
 const char kUserNotMatchingAllowlist[] = "user@another_mail.com";
 const char kSupervisedUserID[] = "supervised_user@locally-managed.localhost";
@@ -1235,4 +1246,120 @@
   WaitForAuthErrorMessage();
 }
 
+class ExistingUserControllerProfileTest : public LoginManagerTest {
+ public:
+  ExistingUserControllerProfileTest() = default;
+
+  void SetUpInProcessBrowserTestFixture() override {
+    LoginManagerTest::SetUpInProcessBrowserTestFixture();
+    // Login as a managed user would save force-online-signin to true and
+    // invalidate the auth token into local state, which would prevent to focus
+    // during the second part of the test which happens in the login screen.
+    UserSelectionScreen::SetSkipForceOnlineSigninForTesting(true);
+  }
+
+  void TearDownInProcessBrowserTestFixture() override {
+    LoginManagerTest::TearDownInProcessBrowserTestFixture();
+    UserSelectionScreen::SetSkipForceOnlineSigninForTesting(false);
+  }
+
+ protected:
+  void SetManagedBy(std::string managed_by) {
+    std::unique_ptr<ScopedUserPolicyUpdate> scoped_user_policy_update =
+        user_policy_mixin_.RequestPolicyUpdate();
+    if (!managed_by.empty()) {
+      scoped_user_policy_update->policy_data()->set_managed_by(managed_by);
+    } else {
+      scoped_user_policy_update->policy_data()->clear_managed_by();
+    }
+  }
+
+  void Login(const LoginManagerMixin::TestUserInfo& test_user) {
+    chromeos::WizardController::SkipPostLoginScreensForTesting();
+
+    auto context = LoginManagerMixin::CreateDefaultUserContext(test_user);
+    login_manager_mixin_.LoginAndWaitForActiveSession(context);
+  }
+
+  base::string16 ConstructManagedSessionUserWarning(std::string manager) {
+    return l10n_util::GetStringFUTF16(
+        IDS_ASH_LOGIN_MANAGED_SESSION_MONITORING_USER_WARNING,
+        base::UTF8ToUTF16(manager));
+  }
+
+  const LoginManagerMixin::TestUserInfo not_managed_user_{
+      AccountId::FromUserEmailGaiaId(kNewUser, kNewGaiaID)};
+  const LoginManagerMixin::TestUserInfo managed_user_{
+      AccountId::FromUserEmailGaiaId(kManagedUser, kManagedGaiaID)};
+  UserPolicyMixin user_policy_mixin_{&mixin_host_, managed_user_.account_id};
+  LoginManagerMixin login_manager_mixin_{&mixin_host_};
+  ScreenLockerTester screen_locker_tester_;
+};
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerProfileTest,
+                       ManagedUserManagedBy) {
+  SetManagedBy(kManager);
+  Login(managed_user_);
+  EXPECT_TRUE(user_manager::known_user::GetIsEnterpriseManaged(
+      managed_user_.account_id));
+
+  // Verify that managed_by has been stored in prefs
+  std::string manager;
+  EXPECT_TRUE(user_manager::known_user::GetAccountManager(
+      managed_user_.account_id, &manager));
+  EXPECT_EQ(manager, kManager);
+
+  // Set the lock screen so that the managed warning can be queried.
+  screen_locker_tester_.Lock();
+
+  EXPECT_TRUE(ash::LoginScreenTestApi::IsManagedMessageInMenuShown(
+      managed_user_.account_id));
+
+  // Verify that the lock screen text uses the prefs value for its construction.
+  EXPECT_EQ(ash::LoginScreenTestApi::GetManagementDisclosureText(
+                managed_user_.account_id),
+            ConstructManagedSessionUserWarning(kManager));
+}
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerProfileTest, ManagedUserDomain) {
+  SetManagedBy(std::string());
+  Login(managed_user_);
+  EXPECT_TRUE(user_manager::known_user::GetIsEnterpriseManaged(
+      managed_user_.account_id));
+
+  // Verify that managed_by has been stored in prefs
+  std::string manager;
+  EXPECT_TRUE(user_manager::known_user::GetAccountManager(
+      managed_user_.account_id, &manager));
+  EXPECT_EQ(manager, kManagedDomain);
+
+  // Set the lock screen so that the managed warning can be queried.
+  screen_locker_tester_.Lock();
+
+  EXPECT_TRUE(ash::LoginScreenTestApi::IsManagedMessageInMenuShown(
+      managed_user_.account_id));
+
+  // Verify that the lock screen text uses the prefs value for its construction.
+  EXPECT_EQ(ash::LoginScreenTestApi::GetManagementDisclosureText(
+                managed_user_.account_id),
+            ConstructManagedSessionUserWarning(kManagedDomain));
+}
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerProfileTest, NotManagedUserLogin) {
+  Login(not_managed_user_);
+  EXPECT_FALSE(user_manager::known_user::GetIsEnterpriseManaged(
+      not_managed_user_.account_id));
+
+  // Verify that no value is stored in prefs for this user.
+  std::string manager;
+  EXPECT_FALSE(user_manager::known_user::GetAccountManager(
+      not_managed_user_.account_id, &manager));
+
+  screen_locker_tester_.Lock();
+
+  // Verify that no managed warning is shown for an unmanaged user.
+  EXPECT_FALSE(ash::LoginScreenTestApi::IsManagedMessageInMenuShown(
+      not_managed_user_.account_id));
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen.cc b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
index 19f794ac..4cba34d 100644
--- a/chrome/browser/chromeos/login/screens/user_selection_screen.cc
+++ b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
@@ -1102,8 +1102,14 @@
     if (user_manager::known_user::GetIsEnterpriseManaged(
             user->GetAccountId()) &&
         user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT) {
-      user_info.user_enterprise_domain =
-          gaia::ExtractDomainName(user->display_email());
+      std::string account_manager;
+      if (user_manager::known_user::GetAccountManager(user->GetAccountId(),
+                                                      &account_manager)) {
+        user_info.user_account_manager = account_manager;
+      } else {
+        user_info.user_account_manager =
+            gaia::ExtractDomainName(user->display_email());
+      }
     }
     chromeos::CrosSettings::Get()->GetBoolean(
         chromeos::kDeviceShowNumericKeyboardForPassword,
diff --git a/chrome/browser/chromeos/login/security_token_login_browsertest.cc b/chrome/browser/chromeos/login/security_token_login_browsertest.cc
index 4200a68..c12078b 100644
--- a/chrome/browser/chromeos/login/security_token_login_browsertest.cc
+++ b/chrome/browser/chromeos/login/security_token_login_browsertest.cc
@@ -67,9 +67,8 @@
 constexpr char kPinDialogInvalidPinTitle[] = "Invalid PIN.";
 constexpr char kPinDialogInvalidPin2AttemptsTitle[] =
     "Invalid PIN. 2 attempts left";
-// TODO(crbug.com/1060695): Fix the incorrect plural in the message.
 constexpr char kPinDialogInvalidPin1AttemptTitle[] =
-    "Invalid PIN. 1 attempts left";
+    "Invalid PIN. 1 attempt left";
 constexpr char kPinDialogNoAttemptsLeftTitle[] =
     "Maximum allowed attempts exceeded.";
 
diff --git a/chrome/browser/chromeos/login/session/user_session_initializer.cc b/chrome/browser/chromeos/login/session/user_session_initializer.cc
index 7acef1b..9bc9487c 100644
--- a/chrome/browser/chromeos/login/session/user_session_initializer.cc
+++ b/chrome/browser/chromeos/login/session/user_session_initializer.cc
@@ -148,7 +148,7 @@
   if (NetworkCertLoader::IsInitialized() &&
       base::SysInfo::IsRunningOnChromeOS()) {
     GetNSSCertDatabaseForProfile(profile,
-                                 base::Bind(&OnGetNSSCertDatabaseForUser));
+                                 base::BindOnce(&OnGetNSSCertDatabaseForUser));
   }
 }
 
diff --git a/chrome/browser/chromeos/login/ui/webui_login_view.cc b/chrome/browser/chromeos/login/ui/webui_login_view.cc
index df143bc1..d5c0cac 100644
--- a/chrome/browser/chromeos/login/ui/webui_login_view.cc
+++ b/chrome/browser/chromeos/login/ui/webui_login_view.cc
@@ -50,7 +50,7 @@
 #include "content/public/browser/web_ui.h"
 #include "extensions/browser/view_type_utils.h"
 #include "third_party/blink/public/common/input/web_input_event.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/views/controls/webview/web_contents_set_background_color.h"
@@ -172,8 +172,7 @@
   extensions::SetViewType(web_contents, extensions::VIEW_TYPE_COMPONENT);
   extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
       web_contents);
-  blink::mojom::RendererPreferences* prefs =
-      web_contents->GetMutableRendererPrefs();
+  blink::RendererPreferences* prefs = web_contents->GetMutableRendererPrefs();
   renderer_preferences_util::UpdateFromSystemSettings(
       prefs, ProfileHelper::GetSigninProfile());
 }
diff --git a/chrome/browser/chromeos/net/network_diagnostics/README.md b/chrome/browser/chromeos/net/network_diagnostics/README.md
index defb428..c15db705 100644
--- a/chrome/browser/chromeos/net/network_diagnostics/README.md
+++ b/chrome/browser/chromeos/net/network_diagnostics/README.md
@@ -103,7 +103,7 @@
 Tests whether the DNS latency is below an acceptable threshold.
 
 Problems:
-* `kFailedToResolveAllHosts`: Failed to resolve one or more hosts.
+* `kHostResolutionFailure`: Failed to resolve one or more hosts.
 * `kSlightlyAboveThreshold`: Average DNS latency across hosts is slightly above
    expected threshold.
 * `kSignificantlyAboveThreshold`: Average DNS latency across hosts is
diff --git a/chrome/browser/chromeos/net/network_diagnostics/dns_latency_routine.cc b/chrome/browser/chromeos/net/network_diagnostics/dns_latency_routine.cc
index e6912163..aa52ae19 100644
--- a/chrome/browser/chromeos/net/network_diagnostics/dns_latency_routine.cc
+++ b/chrome/browser/chromeos/net/network_diagnostics/dns_latency_routine.cc
@@ -108,7 +108,7 @@
   double average_latency = AverageLatency(latencies_);
   if (!successfully_resolved_all_addresses_ || average_latency == 0.0) {
     set_verdict(mojom::RoutineVerdict::kProblem);
-    problems_.emplace_back(mojom::DnsLatencyProblem::kFailedToResolveAllHosts);
+    problems_.emplace_back(mojom::DnsLatencyProblem::kHostResolutionFailure);
   } else if (average_latency > kBadLatencyMs.InMillisecondsF() &&
              average_latency <= kVeryBadLatencyMs.InMillisecondsF()) {
     set_verdict(mojom::RoutineVerdict::kProblem);
diff --git a/chrome/browser/chromeos/net/network_diagnostics/dns_latency_routine_unittest.cc b/chrome/browser/chromeos/net/network_diagnostics/dns_latency_routine_unittest.cc
index af5715d6..2a61d64 100644
--- a/chrome/browser/chromeos/net/network_diagnostics/dns_latency_routine_unittest.cc
+++ b/chrome/browser/chromeos/net/network_diagnostics/dns_latency_routine_unittest.cc
@@ -233,7 +233,7 @@
   // because a failed resolution attempt already results in a problem.
   SetUpAndRunRoutine(fake_dns_result.get(), kSuccessfulDnsResolutionDelayMs,
                      mojom::RoutineVerdict::kProblem,
-                     {mojom::DnsLatencyProblem::kFailedToResolveAllHosts});
+                     {mojom::DnsLatencyProblem::kHostResolutionFailure});
 }
 
 // This test case represents the scenario where a DNS resolution was successful;
diff --git a/chrome/browser/chromeos/platform_keys/platform_keys_service_browsertest.cc b/chrome/browser/chromeos/platform_keys/platform_keys_service_browsertest.cc
index 10547d14..2731ba5 100644
--- a/chrome/browser/chromeos/platform_keys/platform_keys_service_browsertest.cc
+++ b/chrome/browser/chromeos/platform_keys/platform_keys_service_browsertest.cc
@@ -135,8 +135,8 @@
       base::RunLoop loop;
       GetNSSCertDatabaseForProfile(
           profile_,
-          base::BindRepeating(&PlatformKeysServiceBrowserTestBase::SetUserSlot,
-                              base::Unretained(this), loop.QuitClosure()));
+          base::BindOnce(&PlatformKeysServiceBrowserTestBase::SetUserSlot,
+                         base::Unretained(this), loop.QuitClosure()));
       loop.Run();
     }
     ASSERT_TRUE(profile_);
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_command_run_routine_job.cc b/chrome/browser/chromeos/policy/remote_commands/device_command_run_routine_job.cc
index 30caf6b..319a720f 100644
--- a/chrome/browser/chromeos/policy/remote_commands/device_command_run_routine_job.cc
+++ b/chrome/browser/chromeos/policy/remote_commands/device_command_run_routine_job.cc
@@ -137,56 +137,19 @@
   switch (routine_enum_) {
     case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::
         kBatteryCapacity: {
-      constexpr char kLowMahFieldName[] = "lowMah";
-      constexpr char kHighMahFieldName[] = "highMah";
-      base::Optional<int> low_mah = params_dict_.FindIntKey(kLowMahFieldName);
-      base::Optional<int> high_mah = params_dict_.FindIntKey(kHighMahFieldName);
-      // The battery capacity routine expects two integers >= 0.
-      if (!low_mah.has_value() || !high_mah.has_value() ||
-          low_mah.value() < 0 || high_mah.value() < 0) {
-        SYSLOG(ERROR) << "Invalid parameters for BatteryCapacity routine.";
-        base::ThreadTaskRunnerHandle::Get()->PostTask(
-            FROM_HERE, base::BindOnce(std::move(failed_callback),
-                                      std::make_unique<Payload>(
-                                          MakeInvalidParametersResponse())));
-        break;
-      }
       chromeos::cros_healthd::ServiceConnection::GetInstance()
-          ->RunBatteryCapacityRoutine(
-              low_mah.value(), high_mah.value(),
-              base::BindOnce(
-                  &DeviceCommandRunRoutineJob::OnCrosHealthdResponseReceived,
-                  weak_ptr_factory_.GetWeakPtr(), std::move(succeeded_callback),
-                  std::move(failed_callback)));
+          ->RunBatteryCapacityRoutine(base::BindOnce(
+              &DeviceCommandRunRoutineJob::OnCrosHealthdResponseReceived,
+              weak_ptr_factory_.GetWeakPtr(), std::move(succeeded_callback),
+              std::move(failed_callback)));
       break;
     }
     case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kBatteryHealth: {
-      constexpr char kMaximumCycleCountFieldName[] = "maximumCycleCount";
-      constexpr char kPercentBatteryWearAllowedFieldName[] =
-          "percentBatteryWearAllowed";
-      base::Optional<int> maximum_cycle_count =
-          params_dict_.FindIntKey(kMaximumCycleCountFieldName);
-      base::Optional<int> percent_battery_wear_allowed =
-          params_dict_.FindIntKey(kPercentBatteryWearAllowedFieldName);
-      // The battery health routine expects two integers >= 0.
-      if (!maximum_cycle_count.has_value() ||
-          !percent_battery_wear_allowed.has_value() ||
-          maximum_cycle_count.value() < 0 ||
-          percent_battery_wear_allowed.value() < 0) {
-        SYSLOG(ERROR) << "Invalid parameters for BatteryHealth routine.";
-        base::ThreadTaskRunnerHandle::Get()->PostTask(
-            FROM_HERE, base::BindOnce(std::move(failed_callback),
-                                      std::make_unique<Payload>(
-                                          MakeInvalidParametersResponse())));
-        break;
-      }
       chromeos::cros_healthd::ServiceConnection::GetInstance()
-          ->RunBatteryHealthRoutine(
-              maximum_cycle_count.value(), percent_battery_wear_allowed.value(),
-              base::BindOnce(
-                  &DeviceCommandRunRoutineJob::OnCrosHealthdResponseReceived,
-                  weak_ptr_factory_.GetWeakPtr(), std::move(succeeded_callback),
-                  std::move(failed_callback)));
+          ->RunBatteryHealthRoutine(base::BindOnce(
+              &DeviceCommandRunRoutineJob::OnCrosHealthdResponseReceived,
+              weak_ptr_factory_.GetWeakPtr(), std::move(succeeded_callback),
+              std::move(failed_callback)));
       break;
     }
     case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kUrandom: {
@@ -539,6 +502,22 @@
               std::move(failed_callback)));
       break;
     }
+    case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kDnsLatency: {
+      chromeos::cros_healthd::ServiceConnection::GetInstance()
+          ->RunDnsLatencyRoutine(base::BindOnce(
+              &DeviceCommandRunRoutineJob::OnCrosHealthdResponseReceived,
+              weak_ptr_factory_.GetWeakPtr(), std::move(succeeded_callback),
+              std::move(failed_callback)));
+      break;
+    }
+    case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kDnsResolution: {
+      chromeos::cros_healthd::ServiceConnection::GetInstance()
+          ->RunDnsResolutionRoutine(base::BindOnce(
+              &DeviceCommandRunRoutineJob::OnCrosHealthdResponseReceived,
+              weak_ptr_factory_.GetWeakPtr(), std::move(succeeded_callback),
+              std::move(failed_callback)));
+      break;
+    }
   }
 }
 
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_command_run_routine_job_unittest.cc b/chrome/browser/chromeos/policy/remote_commands/device_command_run_routine_job_unittest.cc
index 89752643..8c09f49 100644
--- a/chrome/browser/chromeos/policy/remote_commands/device_command_run_routine_job_unittest.cc
+++ b/chrome/browser/chromeos/policy/remote_commands/device_command_run_routine_job_unittest.cc
@@ -38,17 +38,6 @@
 // payload.
 constexpr char kParamsFieldName[] = "params";
 
-// String constants identifying the parameter fields for the battery capacity
-// routine.
-constexpr char kLowMahFieldName[] = "lowMah";
-constexpr char kHighMahFieldName[] = "highMah";
-
-// String constants identifying the parameter fields for the battery health
-// routine.
-constexpr char kMaximumCycleCountFieldName[] = "maximumCycleCount";
-constexpr char kPercentBatteryWearAllowedFieldName[] =
-    "percentBatteryWearAllowed";
-
 // String constants identifying the parameter fields for the routine.
 constexpr char kLengthSecondsFieldName[] = "lengthSeconds";
 
@@ -279,14 +268,14 @@
   EXPECT_EQ(RemoteCommandJob::INVALID, job->status());
 }
 
+// Note that the battery capacity routine has no parameters, so it's enough to
+// ensure the routine can be run.
 TEST_F(DeviceCommandRunRoutineJobTest, RunBatteryCapacityRoutineSuccess) {
   auto run_routine_response =
       chromeos::cros_healthd::mojom::RunRoutineResponse::New(kId, kStatus);
   chromeos::cros_healthd::FakeCrosHealthdClient::Get()
       ->SetRunRoutineResponseForTesting(run_routine_response);
   base::Value params_dict(base::Value::Type::DICTIONARY);
-  params_dict.SetIntKey(kLowMahFieldName, kPositiveInt);
-  params_dict.SetIntKey(kHighMahFieldName, kPositiveInt);
   EXPECT_TRUE(RunJob(
       chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kBatteryCapacity,
       std::move(params_dict),
@@ -298,82 +287,14 @@
       })));
 }
 
-// Test that leaving out the lowMah parameter causes the battery capacity
-// routine to fail.
-TEST_F(DeviceCommandRunRoutineJobTest, RunBatteryCapacityRoutineMissingLowMah) {
-  base::Value params_dict(base::Value::Type::DICTIONARY);
-  params_dict.SetIntKey(kHighMahFieldName, kPositiveInt);
-  EXPECT_TRUE(RunJob(
-      chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kBatteryCapacity,
-      std::move(params_dict),
-      base::BindLambdaForTesting([](RemoteCommandJob* job) {
-        EXPECT_EQ(job->status(), RemoteCommandJob::FAILED);
-        std::unique_ptr<std::string> payload = job->GetResultPayload();
-        EXPECT_TRUE(payload);
-        EXPECT_EQ(CreateInvalidParametersFailurePayload(), *payload);
-      })));
-}
-
-// Test that leaving out the highMah parameter causes the battery capacity
-// routine to fail.
-TEST_F(DeviceCommandRunRoutineJobTest,
-       RunBatteryCapacityRoutineMissingHighMah) {
-  base::Value params_dict(base::Value::Type::DICTIONARY);
-  params_dict.SetIntKey(kLowMahFieldName, kPositiveInt);
-  EXPECT_TRUE(RunJob(
-      chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kBatteryCapacity,
-      std::move(params_dict),
-      base::BindLambdaForTesting([](RemoteCommandJob* job) {
-        EXPECT_EQ(job->status(), RemoteCommandJob::FAILED);
-        std::unique_ptr<std::string> payload = job->GetResultPayload();
-        EXPECT_TRUE(payload);
-        EXPECT_EQ(CreateInvalidParametersFailurePayload(), *payload);
-      })));
-}
-
-// Test that a negative lowMah parameter causes the battery capacity routine to
-// fail.
-TEST_F(DeviceCommandRunRoutineJobTest, RunBatteryCapacityRoutineInvalidLowMah) {
-  base::Value params_dict(base::Value::Type::DICTIONARY);
-  params_dict.SetIntKey(kLowMahFieldName, kNegativeInt);
-  params_dict.SetIntKey(kHighMahFieldName, kPositiveInt);
-  EXPECT_TRUE(RunJob(
-      chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kBatteryCapacity,
-      std::move(params_dict),
-      base::BindLambdaForTesting([](RemoteCommandJob* job) {
-        EXPECT_EQ(job->status(), RemoteCommandJob::FAILED);
-        std::unique_ptr<std::string> payload = job->GetResultPayload();
-        EXPECT_TRUE(payload);
-        EXPECT_EQ(CreateInvalidParametersFailurePayload(), *payload);
-      })));
-}
-
-// Test that a negative highMah parameter causes the battery capacity routine to
-// fail.
-TEST_F(DeviceCommandRunRoutineJobTest,
-       RunBatteryCapacityRoutineInvalidHighMah) {
-  base::Value params_dict(base::Value::Type::DICTIONARY);
-  params_dict.SetIntKey(kLowMahFieldName, kPositiveInt);
-  params_dict.SetIntKey(kHighMahFieldName, kNegativeInt);
-  EXPECT_TRUE(RunJob(
-      chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kBatteryCapacity,
-      std::move(params_dict),
-      base::BindLambdaForTesting([](RemoteCommandJob* job) {
-        EXPECT_EQ(job->status(), RemoteCommandJob::FAILED);
-        std::unique_ptr<std::string> payload = job->GetResultPayload();
-        EXPECT_TRUE(payload);
-        EXPECT_EQ(CreateInvalidParametersFailurePayload(), *payload);
-      })));
-}
-
+// Note that the battery health routine has no parameters, so it's enough to
+// ensure the routine can be run.
 TEST_F(DeviceCommandRunRoutineJobTest, RunBatteryHealthRoutineSuccess) {
   auto run_routine_response =
       chromeos::cros_healthd::mojom::RunRoutineResponse::New(kId, kStatus);
   chromeos::cros_healthd::FakeCrosHealthdClient::Get()
       ->SetRunRoutineResponseForTesting(run_routine_response);
   base::Value params_dict(base::Value::Type::DICTIONARY);
-  params_dict.SetIntKey(kMaximumCycleCountFieldName, kPositiveInt);
-  params_dict.SetIntKey(kPercentBatteryWearAllowedFieldName, kPositiveInt);
   EXPECT_TRUE(RunJob(
       chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kBatteryHealth,
       std::move(params_dict),
@@ -385,76 +306,6 @@
       })));
 }
 
-// Test that leaving out the maximumCycleCount parameter causes the battery
-// health routine to fail.
-TEST_F(DeviceCommandRunRoutineJobTest,
-       RunBatteryHealthRoutineMissingMaximumCycleCount) {
-  base::Value params_dict(base::Value::Type::DICTIONARY);
-  params_dict.SetIntKey(kPercentBatteryWearAllowedFieldName, kPositiveInt);
-  EXPECT_TRUE(RunJob(
-      chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kBatteryHealth,
-      std::move(params_dict),
-      base::BindLambdaForTesting([](RemoteCommandJob* job) {
-        EXPECT_EQ(job->status(), RemoteCommandJob::FAILED);
-        std::unique_ptr<std::string> payload = job->GetResultPayload();
-        EXPECT_TRUE(payload);
-        EXPECT_EQ(CreateInvalidParametersFailurePayload(), *payload);
-      })));
-}
-
-// Test that leaving out the percentBatteryWearAllowed parameter causes the
-// battery health routine to fail.
-TEST_F(DeviceCommandRunRoutineJobTest,
-       RunBatteryHealthRoutineMissingPercentBatteryWearAllowed) {
-  base::Value params_dict(base::Value::Type::DICTIONARY);
-  params_dict.SetIntKey(kMaximumCycleCountFieldName, kPositiveInt);
-  EXPECT_TRUE(RunJob(
-      chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kBatteryHealth,
-      std::move(params_dict),
-      base::BindLambdaForTesting([](RemoteCommandJob* job) {
-        EXPECT_EQ(job->status(), RemoteCommandJob::FAILED);
-        std::unique_ptr<std::string> payload = job->GetResultPayload();
-        EXPECT_TRUE(payload);
-        EXPECT_EQ(CreateInvalidParametersFailurePayload(), *payload);
-      })));
-}
-
-// Test that a negative maximumCycleCount parameter causes the battery health
-// routine to fail.
-TEST_F(DeviceCommandRunRoutineJobTest,
-       RunBatteryHealthRoutineInvalidMaximumCycleCount) {
-  base::Value params_dict(base::Value::Type::DICTIONARY);
-  params_dict.SetIntKey(kMaximumCycleCountFieldName, kNegativeInt);
-  params_dict.SetIntKey(kPercentBatteryWearAllowedFieldName, kPositiveInt);
-  EXPECT_TRUE(RunJob(
-      chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kBatteryHealth,
-      std::move(params_dict),
-      base::BindLambdaForTesting([](RemoteCommandJob* job) {
-        EXPECT_EQ(job->status(), RemoteCommandJob::FAILED);
-        std::unique_ptr<std::string> payload = job->GetResultPayload();
-        EXPECT_TRUE(payload);
-        EXPECT_EQ(CreateInvalidParametersFailurePayload(), *payload);
-      })));
-}
-
-// Test that a negative percentBatteryWearAllowed parameter causes the battery
-// health routine to fail.
-TEST_F(DeviceCommandRunRoutineJobTest,
-       RunBatteryHealthRoutineInvalidPercentBatteryWearAllowed) {
-  base::Value params_dict(base::Value::Type::DICTIONARY);
-  params_dict.SetIntKey(kMaximumCycleCountFieldName, kPositiveInt);
-  params_dict.SetIntKey(kPercentBatteryWearAllowedFieldName, kNegativeInt);
-  EXPECT_TRUE(RunJob(
-      chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kBatteryHealth,
-      std::move(params_dict),
-      base::BindLambdaForTesting([](RemoteCommandJob* job) {
-        EXPECT_EQ(job->status(), RemoteCommandJob::FAILED);
-        std::unique_ptr<std::string> payload = job->GetResultPayload();
-        EXPECT_TRUE(payload);
-        EXPECT_EQ(CreateInvalidParametersFailurePayload(), *payload);
-      })));
-}
-
 TEST_F(DeviceCommandRunRoutineJobTest, RunUrandomRoutineSuccess) {
   auto run_routine_response =
       chromeos::cros_healthd::mojom::RunRoutineResponse::New(kId, kStatus);
@@ -1390,4 +1241,42 @@
       })));
 }
 
+// Note that the DNS latency routine has no parameters, so we only need
+// to test that it can be run successfully.
+TEST_F(DeviceCommandRunRoutineJobTest, RunDnsLatencyRoutineSuccess) {
+  auto run_routine_response =
+      chromeos::cros_healthd::mojom::RunRoutineResponse::New(kId, kStatus);
+  chromeos::cros_healthd::FakeCrosHealthdClient::Get()
+      ->SetRunRoutineResponseForTesting(run_routine_response);
+  base::Value params_dict(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(
+      RunJob(chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kDnsLatency,
+             std::move(params_dict),
+             base::BindLambdaForTesting([](RemoteCommandJob* job) {
+               EXPECT_EQ(job->status(), RemoteCommandJob::SUCCEEDED);
+               std::unique_ptr<std::string> payload = job->GetResultPayload();
+               EXPECT_TRUE(payload);
+               EXPECT_EQ(CreateSuccessPayload(kId, kStatus), *payload);
+             })));
+}
+
+// Note that the DNS resolution routine has no parameters, so we only need
+// to test that it can be run successfully.
+TEST_F(DeviceCommandRunRoutineJobTest, RunDnsResolutionRoutineSuccess) {
+  auto run_routine_response =
+      chromeos::cros_healthd::mojom::RunRoutineResponse::New(kId, kStatus);
+  chromeos::cros_healthd::FakeCrosHealthdClient::Get()
+      ->SetRunRoutineResponseForTesting(run_routine_response);
+  base::Value params_dict(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(RunJob(
+      chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kDnsResolution,
+      std::move(params_dict),
+      base::BindLambdaForTesting([](RemoteCommandJob* job) {
+        EXPECT_EQ(job->status(), RemoteCommandJob::SUCCEEDED);
+        std::unique_ptr<std::string> payload = job->GetResultPayload();
+        EXPECT_TRUE(payload);
+        EXPECT_EQ(CreateSuccessPayload(kId, kStatus), *payload);
+      })));
+}
+
 }  // namespace policy
diff --git a/chrome/browser/chromeos/policy/user_network_configuration_updater.cc b/chrome/browser/chromeos/policy/user_network_configuration_updater.cc
index 94ab74b2..f1330b2c 100644
--- a/chrome/browser/chromeos/policy/user_network_configuration_updater.cc
+++ b/chrome/browser/chromeos/policy/user_network_configuration_updater.cc
@@ -130,10 +130,9 @@
   Profile* profile = content::Source<Profile>(source).ptr();
 
   GetNSSCertDatabaseForProfile(
-      profile, base::AdaptCallbackForRepeating(
-                   base::BindOnce(&UserNetworkConfigurationUpdater::
-                                      CreateAndSetClientCertificateImporter,
-                                  weak_factory_.GetWeakPtr())));
+      profile, base::BindOnce(&UserNetworkConfigurationUpdater::
+                                  CreateAndSetClientCertificateImporter,
+                              weak_factory_.GetWeakPtr()));
 }
 
 void UserNetworkConfigurationUpdater::CreateAndSetClientCertificateImporter(
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc
index b34887c..46720484 100644
--- a/chrome/browser/chromeos/preferences.cc
+++ b/chrome/browser/chromeos/preferences.cc
@@ -484,6 +484,9 @@
   registry->RegisterBooleanPref(
       chromeos::prefs::kSuggestedContentEnabled, true,
       user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
+  registry->RegisterBooleanPref(
+      chromeos::prefs::kLauncherResultEverLaunched, false,
+      user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
 }
 
 void Preferences::InitUserPrefs(sync_preferences::PrefServiceSyncable* prefs) {
diff --git a/chrome/browser/chromeos/web_applications/scanning_system_web_app_info.cc b/chrome/browser/chromeos/web_applications/scanning_system_web_app_info.cc
index 54e01d3..f01da90 100644
--- a/chrome/browser/chromeos/web_applications/scanning_system_web_app_info.cc
+++ b/chrome/browser/chromeos/web_applications/scanning_system_web_app_info.cc
@@ -22,7 +22,16 @@
   info->scope = GURL(chromeos::kChromeUIScanningAppUrl);
   info->title = l10n_util::GetStringUTF16(IDS_SCANNING_APP_TITLE);
   web_app::CreateIconInfoForSystemWebApp(
-      info->start_url, {{"app_icon_192.png", 192, IDR_SCANNING_APP_ICON}},
+      info->start_url,
+      {
+          {"scanning_app_icon_16.png", 16, IDR_SCANNING_APP_ICON_16},
+          {"scanning_app_icon_32.png", 32, IDR_SCANNING_APP_ICON_32},
+          {"scanning_app_icon_48.png", 48, IDR_SCANNING_APP_ICON_48},
+          {"scanning_app_icon_64.png", 64, IDR_SCANNING_APP_ICON_64},
+          {"scanning_app_icon_128.png", 128, IDR_SCANNING_APP_ICON_128},
+          {"scanning_app_icon_192.png", 192, IDR_SCANNING_APP_ICON_192},
+          {"scanning_app_icon_256.png", 256, IDR_SCANNING_APP_ICON_256},
+      },
       *info);
   info->theme_color = 0xFFFFFFFF;
   info->background_color = 0xFFFFFFFF;
diff --git a/chrome/browser/device/OWNERS b/chrome/browser/device/OWNERS
index cefa3cc..832af12 100644
--- a/chrome/browser/device/OWNERS
+++ b/chrome/browser/device/OWNERS
@@ -1,5 +1,5 @@
 file://chrome/android/OWNERS
 
 # COMPONENT: Internals>Flags
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
 # OS: Android
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc
index c0176c6..b1e7a06 100644
--- a/chrome/browser/devtools/devtools_ui_bindings.cc
+++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -82,7 +82,6 @@
 #include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
 #include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "third_party/blink/public/public_buildflags.h"
 #include "ui/base/page_transition_types.h"
 
diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc
index 3e85ed10..f439810d 100644
--- a/chrome/browser/devtools/devtools_window.cc
+++ b/chrome/browser/devtools/devtools_window.cc
@@ -68,7 +68,7 @@
 #include "net/base/escape.h"
 #include "third_party/blink/public/common/input/web_gesture_event.h"
 #include "third_party/blink/public/common/input/web_input_event.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/public_buildflags.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/events/keycodes/dom/keycode_converter.h"
diff --git a/chrome/browser/download/android/BUILD.gn b/chrome/browser/download/android/BUILD.gn
index 607ac29..bf9de42f3 100644
--- a/chrome/browser/download/android/BUILD.gn
+++ b/chrome/browser/download/android/BUILD.gn
@@ -145,6 +145,7 @@
   sources = [
     "java/src/org/chromium/chrome/browser/download/DownloadDialogBridgeUnitTest.java",
     "java/src/org/chromium/chrome/browser/download/DownloadLaterMetricsUnitTest.java",
+    "java/src/org/chromium/chrome/browser/download/DownloadLocationDialogMetricsUnitTest.java",
     "java/src/org/chromium/chrome/browser/download/dialogs/DownloadDialogUtilsUnitTest.java",
     "java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogHelperUnitTest.java",
   ]
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDialogBridge.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDialogBridge.java
index f2a7ab3..4abfcd4 100644
--- a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDialogBridge.java
+++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDialogBridge.java
@@ -10,6 +10,7 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.chrome.browser.download.DownloadLaterMetrics.DownloadLaterUiEvent;
+import org.chromium.chrome.browser.download.DownloadLocationDialogMetrics.DownloadLocationSuggestionEvent;
 import org.chromium.chrome.browser.download.dialogs.DownloadDateTimePickerDialog;
 import org.chromium.chrome.browser.download.dialogs.DownloadDateTimePickerDialogImpl;
 import org.chromium.chrome.browser.download.dialogs.DownloadDialogUtils;
@@ -114,6 +115,8 @@
                     && DownloadDialogUtils.shouldSuggestDownloadLocation(
                             dirs, getDownloadDefaultDirectory(), totalBytes)) {
                 suggestedDialogType = DownloadLocationDialogType.LOCATION_SUGGESTION;
+                DownloadLocationDialogMetrics.recordDownloadLocationSuggestionEvent(
+                        DownloadLocationSuggestionEvent.LOCATION_SUGGESTION_SHOWN);
             }
 
             showDialog(activity, modalDialogManager, getPrefService(), totalBytes,
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialogMetrics.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialogMetrics.java
index 5a738bf..ffe25cf 100644
--- a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialogMetrics.java
+++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialogMetrics.java
@@ -4,12 +4,30 @@
 
 package org.chromium.chrome.browser.download;
 
+import androidx.annotation.IntDef;
+
 import org.chromium.base.metrics.RecordHistogram;
 
 /**
  * Class that contains helper functions for download location download feature metrics recording.
  */
 public final class DownloadLocationDialogMetrics {
+    /**
+     * Defines events for download location suggestion feature. Used in histograms, don't reuse or
+     * remove items. Keep in sync with DownloadLocationSuggestionEvent in enums.xml.
+     */
+    @IntDef({
+            DownloadLocationSuggestionEvent.LOCATION_SUGGESTION_SHOWN,
+            DownloadLocationSuggestionEvent.NOT_ENOUGH_SPACE_SHOWN,
+    })
+
+    public @interface DownloadLocationSuggestionEvent {
+        int LOCATION_SUGGESTION_SHOWN = 0;
+        int NOT_ENOUGH_SPACE_SHOWN = 1;
+
+        int COUNT = 2;
+    }
+
     private DownloadLocationDialogMetrics() {}
 
     /**
@@ -20,4 +38,15 @@
         RecordHistogram.recordBooleanHistogram(
                 "MobileDownload.Location.Dialog.SuggestionSelected", isSelected);
     }
+
+    /**
+     * Collects download location suggestion event metrics.
+     * @param event The event to collect.
+     */
+    public static void recordDownloadLocationSuggestionEvent(
+            @DownloadLocationSuggestionEvent int event) {
+        RecordHistogram.recordEnumeratedHistogram(
+                "MobileDownload.Location.Dialog.Suggestion.Events", event,
+                DownloadLocationSuggestionEvent.COUNT);
+    }
 }
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialogMetricsUnitTest.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialogMetricsUnitTest.java
new file mode 100644
index 0000000..38d1dc3
--- /dev/null
+++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialogMetricsUnitTest.java
@@ -0,0 +1,55 @@
+// 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.
+
+package org.chromium.chrome.browser.download;
+
+import static junit.framework.Assert.assertEquals;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.metrics.test.ShadowRecordHistogram;
+import org.chromium.chrome.browser.download.DownloadLocationDialogMetrics.DownloadLocationSuggestionEvent;
+import org.chromium.testing.local.LocalRobolectricTestRunner;
+
+/**
+ * Unit test for {@link DownloadLocationDialogMetrics}.
+ */
+@RunWith(LocalRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, shadows = {ShadowRecordHistogram.class})
+public class DownloadLocationDialogMetricsUnitTest {
+    private static final String EVENT_METRIC_NAME =
+            "MobileDownload.Location.Dialog.Suggestion.Events";
+    private static final String SELECTED_METRIC_NAME =
+            "MobileDownload.Location.Dialog.SuggestionSelected";
+
+    @Before
+    public void setUp() {
+        ShadowRecordHistogram.reset();
+    }
+
+    @After
+    public void tearDown() {
+        ShadowRecordHistogram.reset();
+    }
+
+    @Test
+    public void testRecordDownloadLocationDialogSuggestionEvent() {
+        DownloadLocationDialogMetrics.recordDownloadLocationSuggestionEvent(
+                DownloadLocationSuggestionEvent.NOT_ENOUGH_SPACE_SHOWN);
+        assertEquals(1,
+                ShadowRecordHistogram.getHistogramValueCountForTesting(
+                        EVENT_METRIC_NAME, DownloadLocationSuggestionEvent.NOT_ENOUGH_SPACE_SHOWN));
+    }
+
+    @Test
+    public void testRecordDownloadLocationSuggestionChoice() {
+        DownloadLocationDialogMetrics.recordDownloadLocationSuggestionChoice(true);
+        assertEquals(
+                1, ShadowRecordHistogram.getHistogramTotalCountForTesting(SELECTED_METRIC_NAME));
+    }
+}
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLocationCustomView.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLocationCustomView.java
index 00cb0ca..55ba886 100644
--- a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLocationCustomView.java
+++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLocationCustomView.java
@@ -23,6 +23,8 @@
 
 import org.chromium.chrome.browser.download.DirectoryOption;
 import org.chromium.chrome.browser.download.DownloadDialogBridge;
+import org.chromium.chrome.browser.download.DownloadLocationDialogMetrics;
+import org.chromium.chrome.browser.download.DownloadLocationDialogMetrics.DownloadLocationSuggestionEvent;
 import org.chromium.chrome.browser.download.DownloadLocationDialogType;
 import org.chromium.chrome.browser.download.DownloadPromptStatus;
 import org.chromium.chrome.browser.download.R;
@@ -192,6 +194,9 @@
                     getContext().getText(R.string.download_location_not_enough_space));
             textColor = ContextCompat.getColor(getContext(), R.color.input_underline_error_color);
             barColor = ContextCompat.getColor(getContext(), R.color.input_underline_error_color);
+
+            DownloadLocationDialogMetrics.recordDownloadLocationSuggestionEvent(
+                    DownloadLocationSuggestionEvent.NOT_ENOUGH_SPACE_SHOWN);
         }
 
         mLocationAvailableSpace.setText(locationAvailableSpaceText);
diff --git a/chrome/browser/enterprise/reporting/profile_report_generator_unittest.cc b/chrome/browser/enterprise/reporting/profile_report_generator_unittest.cc
index 62d5b91..79f57f7 100644
--- a/chrome/browser/enterprise/reporting/profile_report_generator_unittest.cc
+++ b/chrome/browser/enterprise/reporting/profile_report_generator_unittest.cc
@@ -265,4 +265,41 @@
               report2->extension_requests(id).id());
 }
 
+TEST_F(ProfileReportGeneratorTest, ExtensionRequestOnlyReport) {
+  profile()->GetTestingPrefService()->SetManagedPref(
+      prefs::kCloudExtensionRequestEnabled,
+      std::make_unique<base::Value>(true));
+  std::vector<std::string> ids = {kExtensionId};
+  SetExtensionToPendingList(ids);
+
+  IdentityTestEnvironmentProfileAdaptor identity_test_env_adaptor(profile());
+  auto expected_info =
+      identity_test_env_adaptor.identity_test_env()->SetPrimaryAccount(
+          "test@mail.com");
+
+  auto report = generator_.MaybeGenerate(profile()->GetPath(),
+                                         profile()->GetProfileUserName(),
+                                         ReportType::kExtensionRequest);
+
+  // Extension request and profile id are included. Profile name and sign in
+  // users info are included on CrOS only.
+  EXPECT_TRUE(report);
+  EXPECT_EQ(profile()->GetPath().AsUTF8Unsafe(), report->id());
+#if defined(OS_CHROMEOS)
+  EXPECT_EQ(profile()->GetProfileUserName(), report->name());
+  EXPECT_TRUE(report->has_chrome_signed_in_user());
+#else
+  EXPECT_FALSE(report->has_name());
+  EXPECT_FALSE(report->has_chrome_signed_in_user());
+#endif
+  ASSERT_EQ(1, report->extension_requests_size());
+  EXPECT_EQ(kExtensionId, report->extension_requests(0).id());
+  EXPECT_EQ(kFakeTime, report->extension_requests(0).request_timestamp());
+
+  // Policies and extensions info should not be added.
+  EXPECT_EQ(0, report->chrome_policies_size());
+  EXPECT_EQ(0, report->extensions_size());
+  EXPECT_EQ(0, report->policy_fetched_timestamps_size());
+}
+
 }  // namespace enterprise_reporting
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_lacros.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_lacros.cc
index 493c8837..d96cc85 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_lacros.cc
+++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_lacros.cc
@@ -106,7 +106,7 @@
 
 void EnterprisePlatformKeysChallengeMachineKeyFunction::
     OnChallengeAttestationOnlyKeystore(ResultPtr result) {
-  using Result = crosapi::mojom::ChallengeAttestationOnlyKeystoreResult;
+  using Result = crosapi::mojom::KeystoreStringResult;
   switch (result->which()) {
     case Result::Tag::ERROR_MESSAGE:
       Respond(Error(result->get_error_message()));
@@ -148,7 +148,7 @@
 
 void EnterprisePlatformKeysChallengeUserKeyFunction::
     OnChallengeAttestationOnlyKeystore(ResultPtr result) {
-  using Result = crosapi::mojom::ChallengeAttestationOnlyKeystoreResult;
+  using Result = crosapi::mojom::KeystoreStringResult;
   switch (result->which()) {
     case Result::Tag::ERROR_MESSAGE:
       Respond(Error(result->get_error_message()));
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_lacros.h b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_lacros.h
index 35a0165d..8ed80d8 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_lacros.h
+++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_lacros.h
@@ -68,7 +68,7 @@
   ~EnterprisePlatformKeysChallengeMachineKeyFunction() override = default;
   ResponseAction Run() override;
 
-  using ResultPtr = crosapi::mojom::ChallengeAttestationOnlyKeystoreResultPtr;
+  using ResultPtr = crosapi::mojom::KeystoreStringResultPtr;
   void OnChallengeAttestationOnlyKeystore(ResultPtr result);
   DECLARE_EXTENSION_FUNCTION("enterprise.platformKeys.challengeMachineKey",
                              ENTERPRISE_PLATFORMKEYS_CHALLENGEMACHINEKEY)
@@ -80,7 +80,7 @@
   ~EnterprisePlatformKeysChallengeUserKeyFunction() override = default;
   ResponseAction Run() override;
 
-  using ResultPtr = crosapi::mojom::ChallengeAttestationOnlyKeystoreResultPtr;
+  using ResultPtr = crosapi::mojom::KeystoreStringResultPtr;
   void OnChallengeAttestationOnlyKeystore(ResultPtr result);
   DECLARE_EXTENSION_FUNCTION("enterprise.platformKeys.challengeUserKey",
                              ENTERPRISE_PLATFORMKEYS_CHALLENGEUSERKEY)
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc
index 4cdb396d..9410aa0 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc
+++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc
@@ -255,9 +255,8 @@
    base::RunLoop loop;
    GetNSSCertDatabaseForProfile(
        profile(),
-       base::Bind(&EnterprisePlatformKeysTest::DidGetCertDatabase,
-                  base::Unretained(this),
-                  loop.QuitClosure()));
+       base::BindOnce(&EnterprisePlatformKeysTest::DidGetCertDatabase,
+                      base::Unretained(this), loop.QuitClosure()));
    loop.Run();
   }
   policy_test_utils::SetExtensionInstallForcelistPolicy(
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
index 1a11c68..94a47e5 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
@@ -887,8 +887,7 @@
 ExtensionFunction::ResponseAction InputImeSetMenuItemsFunction::Run() {
   std::unique_ptr<SetMenuItems::Params> parent_params(
       SetMenuItems::Params::Create(*args_));
-  const SetMenuItems::Params::Parameters& params =
-      parent_params->parameters;
+  const input_ime::MenuParameters& params = parent_params->parameters;
 
   std::string error;
   InputMethodEngine* engine =
@@ -914,8 +913,7 @@
 ExtensionFunction::ResponseAction InputImeUpdateMenuItemsFunction::Run() {
   std::unique_ptr<UpdateMenuItems::Params> parent_params(
       UpdateMenuItems::Params::Create(*args_));
-  const UpdateMenuItems::Params::Parameters& params =
-      parent_params->parameters;
+  const input_ime::MenuParameters& params = parent_params->parameters;
 
   std::string error;
   InputMethodEngine* engine =
diff --git a/chrome/browser/extensions/api/omnibox/omnibox_api.cc b/chrome/browser/extensions/api/omnibox/omnibox_api.cc
index 25f0690..db7a07d 100644
--- a/chrome/browser/extensions/api/omnibox/omnibox_api.cc
+++ b/chrome/browser/extensions/api/omnibox/omnibox_api.cc
@@ -314,7 +314,7 @@
     base::string16 description = base::UTF8ToUTF16(suggestion.description);
     std::vector<int> styles(description.length(), 0);
 
-    for (const omnibox::SuggestResult::DescriptionStylesType& style :
+    for (const omnibox::MatchClassification& style :
          *suggestion.description_styles) {
       int length = style.length ? *style.length : description.length();
       size_t offset = style.offset >= 0
diff --git a/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc b/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc
index eb0feb8..270e7a77 100644
--- a/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc
+++ b/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc
@@ -387,7 +387,7 @@
   ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
 
   // Input a keyword query and wait for suggestions from the extension.
-  InputKeys(browser(), {ui::VKEY_K, ui::VKEY_W, ui::VKEY_SPACE, ui::VKEY_D});
+  InputKeys(browser(), {ui::VKEY_K, ui::VKEY_W, ui::VKEY_TAB, ui::VKEY_D});
 
   WaitForAutocompleteDone(browser());
   EXPECT_TRUE(autocomplete_controller->done());
@@ -447,6 +447,12 @@
 IN_PROC_BROWSER_TEST_F(OmniboxApiTest, ExtensionSuggestionsOnlyInKeywordMode) {
   ASSERT_TRUE(RunExtensionTest("omnibox")) << message_;
 
+  // This test covers the behavior of entering keyword mode by space, then
+  // exiting by pressing backspace.  AcceptKeywordBySpace is disabled when
+  // keyword search button is enabled, so for that case do not run this test.
+  if (OmniboxFieldTrial::IsKeywordSearchButtonEnabled())
+    return;
+
   // The results depend on the TemplateURLService being loaded. Make sure it is
   // loaded so that the autocomplete results are consistent.
   Profile* profile = browser()->profile();
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc
index 550d2b1..9aab3f2 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc
@@ -194,7 +194,7 @@
       api::passwords_private::MovePasswordToAccount::Params::Create(*args_);
   EXTENSION_FUNCTION_VALIDATE(parameters);
   GetDelegate(browser_context())
-      ->MovePasswordToAccount(parameters->id, GetSenderWebContents());
+      ->MovePasswordToAccount({parameters->id}, GetSenderWebContents());
   return RespondNow(NoArguments());
 }
 
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc
index 35e358c..29e49c1 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc
@@ -102,7 +102,7 @@
     s_test_delegate_->AddCompromisedCredential(id);
   }
 
-  base::Optional<int> last_moved_password() const {
+  const std::vector<int>& last_moved_password() const {
     return s_test_delegate_->last_moved_password();
   }
 
@@ -300,9 +300,9 @@
 }
 
 IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, MovePasswordToAccount) {
-  EXPECT_FALSE(last_moved_password().has_value());
+  EXPECT_TRUE(last_moved_password().empty());
   EXPECT_TRUE(RunPasswordsSubtest("movePasswordToAccount")) << message_;
-  EXPECT_EQ(42, last_moved_password());
+  EXPECT_EQ(42, last_moved_password()[0]);
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h
index 0cdcc30..736ca74 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h
@@ -89,12 +89,12 @@
       PlaintextPasswordCallback callback,
       content::WebContents* web_contents) = 0;
 
-  // Moves a password currently stored on the device to being stored in the
-  // signed-in, non-syncing Google Account. The result is a no-op if any of
-  // these is true: |id| is invalid; |id| corresponds to a password already
-  // stored in the account; or the user is not using the account-scoped password
-  // storage.
-  virtual void MovePasswordToAccount(int id,
+  // Moves a list of passwords currently stored on the device to being stored in
+  // the signed-in, non-syncing Google Account. The result of any password is a
+  // no-op if any of these is true: |id| is invalid; |id| corresponds to a
+  // password already stored in the account; or the user is not using the
+  // account-scoped password storage.
+  virtual void MovePasswordToAccount(const std::vector<int>& ids,
                                      content::WebContents* web_contents) = 0;
 
   // Trigger the password import procedure, allowing the user to select a file
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
index 26efafa..526152a 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
@@ -430,13 +430,16 @@
 }
 
 void PasswordsPrivateDelegateImpl::MovePasswordToAccount(
-    int id,
+    const std::vector<int>& ids,
     content::WebContents* web_contents) {
   auto* client = ChromePasswordManagerClient::FromWebContents(web_contents);
   DCHECK(client);
-  if (const std::string* sort_key = password_id_generator_.TryGetKey(id))
-    password_manager_presenter_->MovePasswordToAccountStore({*sort_key},
-                                                            client);
+  std::vector<std::string> sort_keys;
+  for (int id : ids) {
+    if (const std::string* sort_key = password_id_generator_.TryGetKey(id))
+      sort_keys.push_back(*sort_key);
+  }
+  password_manager_presenter_->MovePasswordToAccountStore(sort_keys, client);
 }
 
 void PasswordsPrivateDelegateImpl::ImportPasswords(
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h
index 45feac9..698cdc3 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h
@@ -60,7 +60,7 @@
                                 api::passwords_private::PlaintextReason reason,
                                 PlaintextPasswordCallback callback,
                                 content::WebContents* web_contents) override;
-  void MovePasswordToAccount(int id,
+  void MovePasswordToAccount(const std::vector<int>& ids,
                              content::WebContents* web_contents) override;
   void ImportPasswords(content::WebContents* web_contents) override;
   void ExportPasswords(base::OnceCallback<void(const std::string&)> accepted,
diff --git a/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc b/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc
index 1f39237..1e46394a 100644
--- a/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc
+++ b/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc
@@ -136,9 +136,9 @@
 }
 
 void TestPasswordsPrivateDelegate::MovePasswordToAccount(
-    int id,
+    const std::vector<int>& ids,
     content::WebContents* web_contents) {
-  last_moved_password_ = id;
+  last_moved_password_ = ids;
 }
 
 void TestPasswordsPrivateDelegate::ImportPasswords(
diff --git a/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h b/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h
index 2fbd5ae7..9c98acf 100644
--- a/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h
+++ b/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h
@@ -37,7 +37,7 @@
                                 api::passwords_private::PlaintextReason reason,
                                 PlaintextPasswordCallback callback,
                                 content::WebContents* web_contents) override;
-  void MovePasswordToAccount(int id,
+  void MovePasswordToAccount(const std::vector<int>& ids,
                              content::WebContents* web_contents) override;
   void ImportPasswords(content::WebContents* web_contents) override;
   void ExportPasswords(base::OnceCallback<void(const std::string&)> callback,
@@ -92,7 +92,7 @@
     start_password_check_state_ = state;
   }
 
-  base::Optional<int> last_moved_password() const {
+  const std::vector<int>& last_moved_password() const {
     return last_moved_password_;
   }
 
@@ -135,7 +135,7 @@
       password_manager::BulkLeakCheckService::State::kRunning;
 
   // Records the id of the last password that was moved.
-  base::Optional<int> last_moved_password_ = base::nullopt;
+  std::vector<int> last_moved_password_;
 };
 }  // namespace extensions
 
diff --git a/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc b/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc
index 5f8b25c..fb64498 100644
--- a/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc
+++ b/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc
@@ -76,8 +76,8 @@
       base::RunLoop loop;
       GetNSSCertDatabaseForProfile(
           profile(),
-          base::BindRepeating(&PlatformKeysTest::SetupTestCerts,
-                              base::Unretained(this), loop.QuitClosure()));
+          base::BindOnce(&PlatformKeysTest::SetupTestCerts,
+                         base::Unretained(this), loop.QuitClosure()));
       loop.Run();
     }
 
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc
index 310cffac..b4d4f56f 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -130,15 +130,16 @@
   ~ApiParameterExtractor() {}
 
   bool populate_tabs() {
-    if (params_->get_info.get() && params_->get_info->populate.get())
-      return *params_->get_info->populate;
+    if (params_->query_options.get() && params_->query_options->populate.get())
+      return *params_->query_options->populate;
     return false;
   }
 
   WindowController::TypeFilter type_filters() {
-    if (params_->get_info.get() && params_->get_info->window_types.get())
+    if (params_->query_options.get() &&
+        params_->query_options->window_types.get())
       return WindowController::GetFilterFromWindowTypes(
-          *params_->get_info->window_types);
+          *params_->query_options->window_types);
     return WindowController::kNoWindowFilter;
   }
 
diff --git a/chrome/browser/extensions/service_worker_apitest.cc b/chrome/browser/extensions/service_worker_apitest.cc
index 6139360a..2223bc5 100644
--- a/chrome/browser/extensions/service_worker_apitest.cc
+++ b/chrome/browser/extensions/service_worker_apitest.cc
@@ -420,9 +420,6 @@
   EXPECT_EQ(1, histogram_tester.GetBucketCount(
                    "Extensions.Functions.ExtensionServiceWorkerCalls",
                    functions::HistogramValue::WINDOWS_GET));
-  EXPECT_EQ(1, histogram_tester.GetBucketCount(
-                   "Extensions.Functions.ExtensionServiceWorkerCalls",
-                   functions::HistogramValue::WINDOWS_GETCURRENT));
 }
 
 // Tests chrome.webRequest APIs.
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 542a74c..4f1bc7b 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -437,11 +437,6 @@
     "expiry_milestone": 86
   },
   {
-    "name": "bluetooth-next-handsfree-profile",
-    "owners": [ "hychao" ],
-    "expiry_milestone": 85
-  },
-  {
     "name": "bypass-app-banner-engagement-checks",
     "owners": [ "dominickn" ],
     "expiry_milestone": 88
@@ -1289,7 +1284,7 @@
   },
   {
     "name": "enable-command-line-on-non-rooted-devices",
-    "owners": [ "chrome-android-app" ],
+    "owners": [ "clank-app-team@google.com" ],
     // This flag is used for debugging on Android; it causes Android Chromium
     // builds to read command-line arguments from a writable location on disk.
     "expiry_milestone": -1
@@ -2424,6 +2419,11 @@
     "expiry_milestone": 90
   },
   {
+    "name": "enhanced_clipboard_nudge_session_reset",
+    "owners":["mmourgos@chromium.org", "newcomer@chromium.org"],
+    "expiry_milestone": 90
+  },
+  {
     "name": "enhanced_clipboard_simple_render",
     "owners":["newcomer@chromium.org", "gzadina@google.com"],
     "expiry_milestone": 90
@@ -2844,12 +2844,12 @@
   },
   {
     "name": "homepage-promo-card",
-    "owners": [ "wenyufu", "chrome-android-app@chromium.org" ],
+    "owners": [ "wenyufu", "clank-app-team@google.com" ],
     "expiry_milestone": 90
   },
   {
     "name": "homepage-settings-ui-conversion",
-    "owners": [ "wenyufu", "chrome-android-app@chromium.org" ],
+    "owners": [ "wenyufu", "clank-app-team@google.com" ],
     "expiry_milestone": 86
   },
   {
@@ -3035,6 +3035,21 @@
     "expiry_milestone": -1
   },
   {
+    "name": "location-change-string",
+    "owners": [ "thegreenfrog", "bling-team" ],
+    "expiry_milestone": 91
+  },
+  {
+    "name": "location-first-run-modal",
+    "owners": [ "thegreenfrog", "bling-team" ],
+    "expiry_milestone": 91
+  },
+  {
+    "name": "location-remove-first-run",
+    "owners": [ "thegreenfrog", "bling-team" ],
+    "expiry_milestone": 91
+  },
+  {
     "name": "lock-screen-media-controls",
     "owners": [ "beccahughes", "media-dev" ],
     "expiry_milestone": 82
@@ -3270,6 +3285,11 @@
     "expiry_milestone": 88
   },
   {
+    "name": "ntp-recipe-tasks-module",
+    "owners": [ "aee", "mahmadi", "tiborg" ],
+    "expiry_milestone": 90
+  },
+  {
     "name": "ntp-repeatable-queries",
     "owners": [ "aee", "mahmadi", "ramyan", "tiborg" ],
     "expiry_milestone": 89
@@ -4708,6 +4728,11 @@
     "expiry_milestone": 90
   },
   {
+    "name": "video-tutorials-instant-fetch",
+    "owners": [ "shaktisahu"],
+    "expiry_milestone": 90
+  },
+  {
     "name": "videotoolbox-vp9-decoding",
     "owners": [ "dalecurtis", "videostack-eng" ],
     "expiry_milestone": 90
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 8e7c9e5c..651de9e 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3198,6 +3198,10 @@
 
 const char kVideoTutorialsName[] = "Enable video tutorials";
 const char kVideoTutorialsDescription[] = "Show video tutorials in Chrome";
+const char kVideoTutorialsInstantFetchName[] =
+    "Video tutorials fetch on startup";
+const char kVideoTutorialsInstantFetchDescription[] =
+    "Fetch video tutorials on startup";
 
 const char kInlineUpdateFlowName[] = "Enable Google Play inline update flow";
 const char kInlineUpdateFlowDescription[] =
@@ -3311,6 +3315,10 @@
 const char kNtpModulesName[] = "NTP Modules";
 const char kNtpModulesDescription[] = "Shows modules on the New Tab Page.";
 
+const char kNtpRecipeTasksModuleName[] = "NTP Recipe Tasks Module";
+const char kNtpRecipeTasksModuleDescription[] =
+    "Shows the recipe tasks module on the New Tab Page.";
+
 const char kNtpShoppingTasksModuleName[] = "NTP Shopping Tasks Module";
 const char kNtpShoppingTasksModuleDescription[] =
     "Shows the shopping tasks module on the New Tab Page.";
@@ -3652,12 +3660,6 @@
     "Fixes Bluetooth A2DP packet size to a smaller default value to improve "
     "audio quality and may fix audio stutter.";
 
-const char kBluetoothNextHandsfreeProfileName[] =
-    "Enable next version of Bluetooth Handsfree profile";
-const char kBluetoothNextHandsfreeProfileDescription[] =
-    "Enable next version of Bluetooth Handsfree profile 1.7 which includes "
-    "WBS(wideband speech) feature";
-
 const char kCameraSystemWebAppName[] = "Camera System Web App";
 const char kCameraSystemWebAppDescription[] =
     "Run the Chrome Camera App as a System Web App.";
@@ -3890,6 +3892,12 @@
     "history. Selecting something from the menu will result in a paste to the "
     "active window.";
 
+extern const char kEnhancedClipboardNudgeSessionResetName[] =
+    "Enable resetting enhanced clipboard nudge data";
+extern const char kEnhancedClipboardNudgeSessionResetDescription[] =
+    "When enabled, this will reset the clipboard nudge shown data on every new "
+    "user session, allowing the nudge to be shown again.";
+
 const char kEnhancedClipboardSimpleRenderName[] =
     "Only renders html in the Enhanced Clipboard if there are img or table "
     "tags";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 39cd8902..ed7dfba 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1828,6 +1828,8 @@
 
 extern const char kVideoTutorialsName[];
 extern const char kVideoTutorialsDescription[];
+extern const char kVideoTutorialsInstantFetchName[];
+extern const char kVideoTutorialsInstantFetchDescription[];
 
 extern const char kPrefetchNotificationSchedulingIntegrationName[];
 extern const char kPrefetchNotificationSchedulingIntegrationDescription[];
@@ -1899,6 +1901,9 @@
 extern const char kNtpModulesName[];
 extern const char kNtpModulesDescription[];
 
+extern const char kNtpRecipeTasksModuleName[];
+extern const char kNtpRecipeTasksModuleDescription[];
+
 extern const char kNtpShoppingTasksModuleName[];
 extern const char kNtpShoppingTasksModuleDescription[];
 
@@ -2108,9 +2113,6 @@
 extern const char kBluetoothFixA2dpPacketSizeName[];
 extern const char kBluetoothFixA2dpPacketSizeDescription[];
 
-extern const char kBluetoothNextHandsfreeProfileName[];
-extern const char kBluetoothNextHandsfreeProfileDescription[];
-
 extern const char kCameraSystemWebAppName[];
 extern const char kCameraSystemWebAppDescription[];
 
@@ -2251,6 +2253,9 @@
 extern const char kEnhancedClipboardName[];
 extern const char kEnhancedClipboardDescription[];
 
+extern const char kEnhancedClipboardNudgeSessionResetName[];
+extern const char kEnhancedClipboardNudgeSessionResetDescription[];
+
 extern const char kEnhancedClipboardSimpleRenderName[];
 extern const char kEnhancedClipboardSimpleRenderDescription[];
 
diff --git a/chrome/browser/lacros/keystore_service_lacros_browsertest.cc b/chrome/browser/lacros/keystore_service_lacros_browsertest.cc
index fac82b8..2a809c2 100644
--- a/chrome/browser/lacros/keystore_service_lacros_browsertest.cc
+++ b/chrome/browser/lacros/keystore_service_lacros_browsertest.cc
@@ -33,7 +33,7 @@
 // Tests that providing an incorrectly formatted user keystore challenge returns
 // failure.
 IN_PROC_BROWSER_TEST_F(KeystoreServiceLacrosBrowserTest, WrongFormattingUser) {
-  crosapi::mojom::ChallengeAttestationOnlyKeystoreResultPtr result;
+  crosapi::mojom::KeystoreStringResultPtr result;
   std::string challenge = "asdf";
   crosapi::mojom::KeystoreServiceAsyncWaiter async_waiter(
       keystore_service_remote().get());
diff --git a/chrome/browser/memory/OWNERS b/chrome/browser/memory/OWNERS
index 417b566..e46275d 100644
--- a/chrome/browser/memory/OWNERS
+++ b/chrome/browser/memory/OWNERS
@@ -1,4 +1,8 @@
 chrisha@chromium.org
-cylee@chromium.org
+
+# OOM and memory kills logging
+per-file memory_kills_*=vovoy@chromium.org
+per-file oom_memory_details.*=vovoy@chromium.org
+
 # COMPONENT: Blink>MemoryAllocator
 # TEAM: catan-team@chromium.org
diff --git a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
index 54f097c..d5fc5f45 100644
--- a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
+++ b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
@@ -473,6 +473,7 @@
 
   // Records whether or not the Segment heap is in use.
 #if defined(OS_WIN)
+
   if (base::win::GetVersion() >= base::win::Version::WIN10_20H1) {
     ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial("WinSegmentHeap",
 #if BUILDFLAG(ENABLE_SEGMENT_HEAP)
@@ -495,7 +496,18 @@
                                                             "Disabled"
 #endif
   );
+
 #endif  // defined(OS_WIN)
+
+  // Records whether or not PartitionAlloc is used as the default allocator.
+  ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial(
+      "PartitionAllocEverywhere",
+#if BUILDFLAG(USE_PARTITION_ALLOC_EVERYWHERE)
+      "Enabled"
+#else
+      "Disabled"
+#endif
+  );
 }
 
 void ChromeBrowserMainExtraPartsMetrics::PostBrowserStart() {
diff --git a/chrome/browser/navigation_predictor/search_engine_preconnector_browsertest.cc b/chrome/browser/navigation_predictor/search_engine_preconnector_browsertest.cc
index f846ec6..fbebfcd 100644
--- a/chrome/browser/navigation_predictor/search_engine_preconnector_browsertest.cc
+++ b/chrome/browser/navigation_predictor/search_engine_preconnector_browsertest.cc
@@ -140,8 +140,9 @@
   DISALLOW_COPY_AND_ASSIGN(SearchEnginePreconnectorNoDelaysBrowserTest);
 };
 
+// Test routinely flakes on the Mac10.11 Tests bot (https://crbug.com/1141028).
 IN_PROC_BROWSER_TEST_F(SearchEnginePreconnectorNoDelaysBrowserTest,
-                       PreconnectSearch) {
+                       DISABLED_PreconnectSearch) {
   // Put the fake search URL to be preconnected in foreground.
   NavigationPredictorKeyedServiceFactory::GetForProfile(
       Profile::FromBrowserContext(browser()->profile()))
diff --git a/chrome/browser/net/nss_context.cc b/chrome/browser/net/nss_context.cc
index 03cd9d9a..50382cc 100644
--- a/chrome/browser/net/nss_context.cc
+++ b/chrome/browser/net/nss_context.cc
@@ -32,28 +32,29 @@
 void GetCertDBOnIOThread(
     content::ResourceContext* context,
     scoped_refptr<base::SequencedTaskRunner> response_task_runner,
-    const base::RepeatingCallback<void(net::NSSCertDatabase*)>& callback) {
+    base::OnceCallback<void(net::NSSCertDatabase*)> callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // Note that the callback will be used only if the cert database hasn't yet
   // been initialized.
-  net::NSSCertDatabase* cert_db = GetNSSCertDatabaseForResourceContext(
-      context,
-      base::BindOnce(&DidGetCertDBOnIOThread, response_task_runner, callback));
+  auto completion_callback = base::AdaptCallbackForRepeating(base::BindOnce(
+      &DidGetCertDBOnIOThread, response_task_runner, std::move(callback)));
+  net::NSSCertDatabase* cert_db =
+      GetNSSCertDatabaseForResourceContext(context, completion_callback);
 
   if (cert_db)
-    DidGetCertDBOnIOThread(response_task_runner, callback, cert_db);
+    completion_callback.Run(cert_db);
 }
 
 }  // namespace
 
 void GetNSSCertDatabaseForProfile(
     Profile* profile,
-    const base::RepeatingCallback<void(net::NSSCertDatabase*)>& callback) {
+    base::OnceCallback<void(net::NSSCertDatabase*)> callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   content::GetIOThreadTaskRunner({})->PostTask(
       FROM_HERE,
       base::BindOnce(&GetCertDBOnIOThread, profile->GetResourceContext(),
-                     base::ThreadTaskRunnerHandle::Get(), callback));
+                     base::ThreadTaskRunnerHandle::Get(), std::move(callback)));
 }
diff --git a/chrome/browser/net/nss_context.h b/chrome/browser/net/nss_context.h
index 2784c14..2b3b6c6 100644
--- a/chrome/browser/net/nss_context.h
+++ b/chrome/browser/net/nss_context.h
@@ -48,6 +48,6 @@
 // It's accessing profile, so it should be called on the UI thread.
 void GetNSSCertDatabaseForProfile(
     Profile* profile,
-    const base::RepeatingCallback<void(net::NSSCertDatabase*)>& callback);
+    base::OnceCallback<void(net::NSSCertDatabase*)> callback);
 
 #endif  // CHROME_BROWSER_NET_NSS_CONTEXT_H_
diff --git a/chrome/browser/net/profile_network_context_service_browsertest.cc b/chrome/browser/net/profile_network_context_service_browsertest.cc
index dbf8be9..a0d06c18 100644
--- a/chrome/browser/net/profile_network_context_service_browsertest.cc
+++ b/chrome/browser/net/profile_network_context_service_browsertest.cc
@@ -39,6 +39,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/metrics/content/subprocess_metrics_provider.h"
 #include "components/policy/core/common/policy_map.h"
@@ -287,9 +288,13 @@
       "None scoped_feature_list_trial_group None");
 }
 
-class AmbientAuthenticationTestWithPolicy : public policy::PolicyTest {
+class AmbientAuthenticationTestWithPolicy
+    : public policy::PolicyTest,
+      public ::testing::WithParamInterface<bool> {
  public:
   AmbientAuthenticationTestWithPolicy() {
+    TestingProfile::SetScopedFeatureListForEphemeralGuestProfiles(
+        scoped_feature_list_, GetParam());
     policy::PolicyTest::SetUpInProcessBrowserTestFixture();
   }
 
@@ -316,7 +321,7 @@
 #if !defined(OS_CHROMEOS)
     EXPECT_EQ(
         AmbientAuthenticationTestHelper::IsAmbientAuthAllowedForProfile(
-            AmbientAuthenticationTestHelper::GetGuestProfile()),
+            CreateGuestBrowser()->profile()),
         AmbientAuthenticationTestHelper::IsGuestAllowedInPolicy(policy_value));
 #endif
   }
@@ -330,30 +335,35 @@
 
  private:
   policy::PolicyMap policies_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-IN_PROC_BROWSER_TEST_F(AmbientAuthenticationTestWithPolicy, RegularOnly) {
+IN_PROC_BROWSER_TEST_P(AmbientAuthenticationTestWithPolicy, RegularOnly) {
   EnablePolicyWithValue(net::AmbientAuthAllowedProfileTypes::REGULAR_ONLY);
   IsAmbientAuthAllowedForProfilesTest();
 }
 
-IN_PROC_BROWSER_TEST_F(AmbientAuthenticationTestWithPolicy,
+IN_PROC_BROWSER_TEST_P(AmbientAuthenticationTestWithPolicy,
                        IncognitoAndRegular) {
   EnablePolicyWithValue(
       net::AmbientAuthAllowedProfileTypes::INCOGNITO_AND_REGULAR);
   IsAmbientAuthAllowedForProfilesTest();
 }
 
-IN_PROC_BROWSER_TEST_F(AmbientAuthenticationTestWithPolicy, GuestAndRegular) {
+IN_PROC_BROWSER_TEST_P(AmbientAuthenticationTestWithPolicy, GuestAndRegular) {
   EnablePolicyWithValue(net::AmbientAuthAllowedProfileTypes::GUEST_AND_REGULAR);
   IsAmbientAuthAllowedForProfilesTest();
 }
 
-IN_PROC_BROWSER_TEST_F(AmbientAuthenticationTestWithPolicy, All) {
+IN_PROC_BROWSER_TEST_P(AmbientAuthenticationTestWithPolicy, All) {
   EnablePolicyWithValue(net::AmbientAuthAllowedProfileTypes::ALL);
   IsAmbientAuthAllowedForProfilesTest();
 }
 
+INSTANTIATE_TEST_SUITE_P(All,
+                         AmbientAuthenticationTestWithPolicy,
+                         /*ephemeral_guest_profile_enabled=*/testing::Bool());
+
 // Test subclass that adds switches::kDiskCacheDir and switches::kDiskCacheSize
 // to the command line, to make sure they're respected.
 class ProfileNetworkContextServiceDiskCacheBrowsertest
diff --git a/chrome/browser/net/profile_network_context_service_test_utils.cc b/chrome/browser/net/profile_network_context_service_test_utils.cc
index 3c62291..8e3211f 100644
--- a/chrome/browser/net/profile_network_context_service_test_utils.cc
+++ b/chrome/browser/net/profile_network_context_service_test_utils.cc
@@ -32,11 +32,6 @@
   return policy_value & static_cast<int>(AmbientAuthProfileBit::GUEST);
 }
 
-Profile* AmbientAuthenticationTestHelper::GetGuestProfile() {
-  Profile* guest_profile = OpenGuestBrowser()->profile();
-  return guest_profile;
-}
-
 bool AmbientAuthenticationTestHelper::IsAmbientAuthAllowedForProfile(
     Profile* profile) {
   ProfileNetworkContextService* profile_network_context_service =
@@ -51,33 +46,3 @@
              ->allow_default_credentials ==
          net::HttpAuthPreferences::ALLOW_DEFAULT_CREDENTIALS;
 }
-
-// OpenGuestBrowser method code borrowed from
-// chrome/browser/profiles/profile_window_browsertest.cc
-Browser* AmbientAuthenticationTestHelper::OpenGuestBrowser() {
-  size_t num_browsers = BrowserList::GetInstance()->size();
-
-  // Create a guest browser nicely. Using CreateProfile() and CreateBrowser()
-  // does incomplete initialization that would lead to
-  // SystemUrlRequestContextGetter being leaked.
-  profiles::SwitchToGuestProfile(ProfileManager::CreateCallback());
-  ui_test_utils::WaitForBrowserToOpen();
-
-  DCHECK_NE(static_cast<Profile*>(nullptr),
-            g_browser_process->profile_manager()->GetProfileByPath(
-                ProfileManager::GetGuestProfilePath()));
-  EXPECT_EQ(num_browsers + 1, BrowserList::GetInstance()->size());
-
-  Profile* guest = g_browser_process->profile_manager()->GetProfileByPath(
-      ProfileManager::GetGuestProfilePath());
-  Browser* browser = chrome::FindAnyBrowser(guest, true);
-  EXPECT_TRUE(browser);
-
-  // When |browser| closes a BrowsingDataRemover will be created and executed.
-  // It needs a loaded TemplateUrlService or else it hangs on to a
-  // CallbackList::Subscription forever.
-  search_test_utils::WaitForTemplateURLServiceToLoad(
-      TemplateURLServiceFactory::GetForProfile(guest));
-
-  return browser;
-}
diff --git a/chrome/browser/payments/secure_payment_confirmation_browsertest.cc b/chrome/browser/payments/secure_payment_confirmation_browsertest.cc
index 85447770..084d3323 100644
--- a/chrome/browser/payments/secure_payment_confirmation_browsertest.cc
+++ b/chrome/browser/payments/secure_payment_confirmation_browsertest.cc
@@ -316,24 +316,8 @@
   }
 };
 
-#if defined(OS_WIN)
-// TODO(kenrb): This experiment is currently only available on Mac, but this
-// test should work on all non-Android platforms. There is a Windows failure
-// that still needs to be investigated.
-#define MAYBE_CreatePaymentCredential DISABLED_CreatePaymentCredential
-#define MAYBE_LookupPaymentCredential DISABLED_LookupPaymentCredential
-#define MAYBE_ConfirmPaymentInCrossOriginIframe \
-  DISABLED_ConfirmPaymentInCrossOriginIframe
-#define MAYBE_ChallengeIsReturned DISABLED_ChallengeIsReturned
-#else
-#define MAYBE_CreatePaymentCredential CreatePaymentCredential
-#define MAYBE_LookupPaymentCredential LookupPaymentCredential
-#define MAYBE_ConfirmPaymentInCrossOriginIframe \
-  ConfirmPaymentInCrossOriginIframe
-#define MAYBE_ChallengeIsReturned ChallengeIsReturned
-#endif
 IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest,
-                       MAYBE_CreatePaymentCredential) {
+                       CreatePaymentCredential) {
   base::HistogramTester histogram_tester;
   ReplaceFidoDiscoveryFactory();
   NavigateTo("a.com", "/secure_payment_confirmation.html");
@@ -349,7 +333,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest,
-                       MAYBE_LookupPaymentCredential) {
+                       LookupPaymentCredential) {
   ReplaceFidoDiscoveryFactory();
   NavigateTo("a.com", "/secure_payment_confirmation.html");
   std::string credentialIdentifier =
@@ -379,7 +363,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest,
-                       MAYBE_ConfirmPaymentInCrossOriginIframe) {
+                       ConfirmPaymentInCrossOriginIframe) {
   NavigateTo("a.com", "/secure_payment_confirmation.html");
   ReplaceFidoDiscoveryFactory();
   std::string credentialIdentifier =
@@ -404,7 +388,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationCreationTest,
-                       MAYBE_ChallengeIsReturned) {
+                       ChallengeIsReturned) {
   NavigateTo("a.com", "/secure_payment_confirmation.html");
   ReplaceFidoDiscoveryFactory();
   std::string credentialIdentifier =
diff --git a/chrome/browser/prefetch/search_prefetch/field_trial_settings.cc b/chrome/browser/prefetch/search_prefetch/field_trial_settings.cc
index e556dc6..2ef67f6 100644
--- a/chrome/browser/prefetch/search_prefetch/field_trial_settings.cc
+++ b/chrome/browser/prefetch/search_prefetch/field_trial_settings.cc
@@ -4,9 +4,27 @@
 
 #include "chrome/browser/prefetch/search_prefetch/field_trial_settings.h"
 
-const base::Feature kSearchPrefetchService{"SearchPrefecthService",
+#include <string>
+
+#include "base/command_line.h"
+
+constexpr char kSearchPrefetchServiceCommandLineFlag[] =
+    "enable-search-prefetch-service";
+
+const base::Feature kSearchPrefetchService{"SearchPrefetchService",
                                            base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kSearchPrefetchServicePrefetching{
+    "SearchPrefetchServicePrefetching", base::FEATURE_DISABLED_BY_DEFAULT};
+
 bool SearchPrefetchServiceIsEnabled() {
-  return base::FeatureList::IsEnabled(kSearchPrefetchService);
+  return base::CommandLine::ForCurrentProcess()->HasSwitch(
+             kSearchPrefetchServiceCommandLineFlag) ||
+         base::FeatureList::IsEnabled(kSearchPrefetchService);
+}
+
+bool SearchPrefetchServicePrefetchingIsEnabled() {
+  return base::CommandLine::ForCurrentProcess()->HasSwitch(
+             kSearchPrefetchServiceCommandLineFlag) ||
+         base::FeatureList::IsEnabled(kSearchPrefetchServicePrefetching);
 }
diff --git a/chrome/browser/prefetch/search_prefetch/field_trial_settings.h b/chrome/browser/prefetch/search_prefetch/field_trial_settings.h
index b9fb4e0..3fa9e9b 100644
--- a/chrome/browser/prefetch/search_prefetch/field_trial_settings.h
+++ b/chrome/browser/prefetch/search_prefetch/field_trial_settings.h
@@ -8,7 +8,10 @@
 #include "base/feature_list.h"
 
 extern const base::Feature kSearchPrefetchService;
+extern const base::Feature kSearchPrefetchServicePrefetching;
 
 bool SearchPrefetchServiceIsEnabled();
 
+bool SearchPrefetchServicePrefetchingIsEnabled();
+
 #endif  // CHROME_BROWSER_PREFETCH_SEARCH_PREFETCH_FIELD_TRIAL_SETTINGS_H_
diff --git a/chrome/browser/prefetch/search_prefetch/prefetched_response_container.cc b/chrome/browser/prefetch/search_prefetch/prefetched_response_container.cc
new file mode 100644
index 0000000..21d16e5d
--- /dev/null
+++ b/chrome/browser/prefetch/search_prefetch/prefetched_response_container.cc
@@ -0,0 +1,28 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefetch/search_prefetch/prefetched_response_container.h"
+
+PrefetchedResponseContainer::PrefetchedResponseContainer(
+    network::mojom::URLResponseHeadPtr head,
+    std::unique_ptr<std::string> body)
+    : head_(std::move(head)), body_(std::move(body)) {}
+
+PrefetchedResponseContainer::~PrefetchedResponseContainer() = default;
+
+std::unique_ptr<PrefetchedResponseContainer>
+PrefetchedResponseContainer::Clone() const {
+  return std::make_unique<PrefetchedResponseContainer>(
+      head_->Clone(), std::make_unique<std::string>(*body_));
+}
+
+network::mojom::URLResponseHeadPtr PrefetchedResponseContainer::TakeHead() {
+  DCHECK(head_);
+  return std::move(head_);
+}
+
+std::unique_ptr<std::string> PrefetchedResponseContainer::TakeBody() {
+  DCHECK(body_);
+  return std::move(body_);
+}
diff --git a/chrome/browser/prefetch/search_prefetch/prefetched_response_container.h b/chrome/browser/prefetch/search_prefetch/prefetched_response_container.h
new file mode 100644
index 0000000..daa27e6f
--- /dev/null
+++ b/chrome/browser/prefetch/search_prefetch/prefetched_response_container.h
@@ -0,0 +1,39 @@
+// 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_PREFETCH_SEARCH_PREFETCH_PREFETCHED_RESPONSE_CONTAINER_H_
+#define CHROME_BROWSER_PREFETCH_SEARCH_PREFETCH_PREFETCHED_RESPONSE_CONTAINER_H_
+
+#include <memory>
+#include <string>
+
+#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "url/gurl.h"
+
+// This class encapsulates a whole HTTP response which can be used for caching
+// and later replaying a prefetch request.
+class PrefetchedResponseContainer {
+ public:
+  PrefetchedResponseContainer(network::mojom::URLResponseHeadPtr head,
+                              std::unique_ptr<std::string> body);
+  ~PrefetchedResponseContainer();
+
+  PrefetchedResponseContainer(const PrefetchedResponseContainer&) = delete;
+  PrefetchedResponseContainer& operator=(const PrefetchedResponseContainer&) =
+      delete;
+
+  std::unique_ptr<PrefetchedResponseContainer> Clone() const;
+
+  // Takes ownership of the response head.
+  network::mojom::URLResponseHeadPtr TakeHead();
+
+  // Take ownership of the response body.
+  std::unique_ptr<std::string> TakeBody();
+
+ private:
+  network::mojom::URLResponseHeadPtr head_;
+  std::unique_ptr<std::string> body_;
+};
+
+#endif  // CHROME_BROWSER_PREFETCH_SEARCH_PREFETCH_PREFETCHED_RESPONSE_CONTAINER_H_
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_from_string_url_loader.cc b/chrome/browser/prefetch/search_prefetch/search_prefetch_from_string_url_loader.cc
new file mode 100644
index 0000000..37c22d9
--- /dev/null
+++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_from_string_url_loader.cc
@@ -0,0 +1,155 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefetch/search_prefetch/search_prefetch_from_string_url_loader.h"
+
+#include "base/bind.h"
+#include "base/check_op.h"
+#include "base/memory/ptr_util.h"
+#include "base/notreached.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+#include "mojo/public/cpp/system/simple_watcher.h"
+#include "net/base/io_buffer.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
+
+SearchPrefetchFromStringURLLoader::SearchPrefetchFromStringURLLoader(
+    std::unique_ptr<PrefetchedResponseContainer> response,
+    const network::ResourceRequest& tentative_resource_request)
+    : head_(response->TakeHead()),
+      body_buffer_(
+          base::MakeRefCounted<net::StringIOBuffer>(response->TakeBody())),
+      bytes_of_raw_data_to_transfer_(body_buffer_->size()) {}
+
+SearchPrefetchFromStringURLLoader::~SearchPrefetchFromStringURLLoader() =
+    default;
+
+void SearchPrefetchFromStringURLLoader::FollowRedirect(
+    const std::vector<std::string>& removed_headers,
+    const net::HttpRequestHeaders& modified_headers,
+    const net::HttpRequestHeaders& modified_cors_exempt_headers,
+    const base::Optional<GURL>& new_url) {
+  NOTREACHED();
+}
+
+void SearchPrefetchFromStringURLLoader::SetPriority(
+    net::RequestPriority priority,
+    int32_t intra_priority_value) {
+  // Ignore: this class doesn't have a concept of priority.
+}
+
+void SearchPrefetchFromStringURLLoader::PauseReadingBodyFromNet() {
+  // Ignore: this class doesn't read from network.
+}
+
+void SearchPrefetchFromStringURLLoader::ResumeReadingBodyFromNet() {
+  // Ignore: this class doesn't read from network.
+}
+
+void SearchPrefetchFromStringURLLoader::TransferRawData() {
+  while (true) {
+    DCHECK_GE(bytes_of_raw_data_to_transfer_, write_position_);
+    uint32_t write_size =
+        static_cast<uint32_t>(bytes_of_raw_data_to_transfer_ - write_position_);
+    if (write_size == 0) {
+      Finish(net::OK);
+      return;
+    }
+
+    MojoResult result =
+        producer_handle_->WriteData(body_buffer_->data() + write_position_,
+                                    &write_size, MOJO_WRITE_DATA_FLAG_NONE);
+    if (result == MOJO_RESULT_SHOULD_WAIT) {
+      handle_watcher_->ArmOrNotify();
+      return;
+    }
+
+    if (result != MOJO_RESULT_OK) {
+      Finish(net::ERR_FAILED);
+      return;
+    }
+
+    // |write_position_| should only be updated when the mojo pipe has
+    // successfully been written to.
+    write_position_ += write_size;
+  }
+}
+
+SearchPrefetchFromStringURLLoader::RequestHandler
+SearchPrefetchFromStringURLLoader::ServingResponseHandler() {
+  return base::BindOnce(&SearchPrefetchFromStringURLLoader::BindAndStart,
+                        weak_ptr_factory_.GetWeakPtr());
+}
+
+void SearchPrefetchFromStringURLLoader::BindAndStart(
+    const network::ResourceRequest& request,
+    mojo::PendingReceiver<network::mojom::URLLoader> receiver,
+    mojo::PendingRemote<network::mojom::URLLoaderClient> client) {
+  DCHECK(!receiver_.is_bound());
+  receiver_.Bind(std::move(receiver));
+  receiver_.set_disconnect_handler(
+      base::BindOnce(&SearchPrefetchFromStringURLLoader::OnMojoDisconnect,
+                     weak_ptr_factory_.GetWeakPtr()));
+  client_.Bind(std::move(client));
+
+  mojo::ScopedDataPipeProducerHandle producer_handle;
+  mojo::ScopedDataPipeConsumerHandle consumer_handle;
+  MojoResult rv =
+      mojo::CreateDataPipe(nullptr, &producer_handle, &consumer_handle);
+
+  if (rv != MOJO_RESULT_OK) {
+    Finish(net::ERR_FAILED);
+    return;
+  }
+
+  client_->OnReceiveResponse(std::move(head_));
+  client_->OnStartLoadingResponseBody(std::move(consumer_handle));
+
+  producer_handle_ = std::move(producer_handle);
+
+  handle_watcher_ = std::make_unique<mojo::SimpleWatcher>(
+      FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL,
+      base::SequencedTaskRunnerHandle::Get());
+  handle_watcher_->Watch(
+      producer_handle_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
+      MOJO_WATCH_CONDITION_SATISFIED,
+      base::BindRepeating(&SearchPrefetchFromStringURLLoader::OnHandleReady,
+                          weak_ptr_factory_.GetWeakPtr()));
+
+  TransferRawData();
+}
+
+void SearchPrefetchFromStringURLLoader::OnHandleReady(
+    MojoResult result,
+    const mojo::HandleSignalsState& state) {
+  if (result != MOJO_RESULT_OK) {
+    Finish(net::ERR_FAILED);
+    return;
+  }
+  TransferRawData();
+}
+
+void SearchPrefetchFromStringURLLoader::Finish(int error) {
+  client_->OnComplete(network::URLLoaderCompletionStatus(error));
+  handle_watcher_.reset();
+  producer_handle_.reset();
+  client_.reset();
+  receiver_.reset();
+  weak_ptr_factory_.InvalidateWeakPtrs();
+  MaybeDeleteSelf();
+}
+
+void SearchPrefetchFromStringURLLoader::OnMojoDisconnect() {
+  receiver_.reset();
+  client_.reset();
+  MaybeDeleteSelf();
+}
+
+void SearchPrefetchFromStringURLLoader::MaybeDeleteSelf() {
+  if (!receiver_.is_bound() && !client_.is_bound()) {
+    delete this;
+  }
+}
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_from_string_url_loader.h b/chrome/browser/prefetch/search_prefetch/search_prefetch_from_string_url_loader.h
new file mode 100644
index 0000000..b9acd41
--- /dev/null
+++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_from_string_url_loader.h
@@ -0,0 +1,107 @@
+// 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_PREFETCH_SEARCH_PREFETCH_SEARCH_PREFETCH_FROM_STRING_URL_LOADER_H_
+#define CHROME_BROWSER_PREFETCH_SEARCH_PREFETCH_SEARCH_PREFETCH_FROM_STRING_URL_LOADER_H_
+
+#include <cstdint>
+#include <memory>
+#include <string>
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/prefetch/search_prefetch/prefetched_response_container.h"
+#include "content/public/browser/url_loader_request_interceptor.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
+
+namespace mojo {
+class SimpleWatcher;
+}
+
+namespace net {
+class StringIOBuffer;
+}
+
+class SearchPrefetchFromStringURLLoader : public network::mojom::URLLoader {
+ public:
+  using RequestHandler = base::OnceCallback<void(
+      const network::ResourceRequest& resource_request,
+      mojo::PendingReceiver<network::mojom::URLLoader> url_loader_receiver,
+      mojo::PendingRemote<network::mojom::URLLoaderClient> client)>;
+
+  SearchPrefetchFromStringURLLoader(
+      std::unique_ptr<PrefetchedResponseContainer> response,
+      const network::ResourceRequest& tentative_resource_request);
+
+  ~SearchPrefetchFromStringURLLoader() override;
+
+  SearchPrefetchFromStringURLLoader(const SearchPrefetchFromStringURLLoader&) =
+      delete;
+  SearchPrefetchFromStringURLLoader& operator=(
+      const SearchPrefetchFromStringURLLoader&) = delete;
+
+  // Called when the response should be served to the user. Returns a handler.
+  RequestHandler ServingResponseHandler();
+
+ private:
+  // network::mojom::URLLoader:
+  void FollowRedirect(
+      const std::vector<std::string>& removed_headers,
+      const net::HttpRequestHeaders& modified_headers,
+      const net::HttpRequestHeaders& modified_cors_exempt_headers,
+      const base::Optional<GURL>& new_url) override;
+  void SetPriority(net::RequestPriority priority,
+                   int32_t intra_priority_value) override;
+  void PauseReadingBodyFromNet() override;
+  void ResumeReadingBodyFromNet() override;
+
+  // Binds |this| to the mojo handlers and starts the network request using
+  // |request|. After this method is called, |this| manages its own lifetime.
+  void BindAndStart(
+      const network::ResourceRequest& request,
+      mojo::PendingReceiver<network::mojom::URLLoader> url_loader_receiver,
+      mojo::PendingRemote<network::mojom::URLLoaderClient> forwarding_client);
+
+  // Called when the mojo handle's state changes, either by being ready for more
+  // data or an error.
+  void OnHandleReady(MojoResult result, const mojo::HandleSignalsState& state);
+
+  // Finishes the request with the given net error.
+  void Finish(int error);
+
+  // Sends data on the mojo pipe.
+  void TransferRawData();
+
+  // Unbinds and deletes |this|.
+  void OnMojoDisconnect();
+
+  // Deletes |this| if it is not bound to the mojo pipes.
+  void MaybeDeleteSelf();
+
+  // The response that will be sent to mojo.
+  network::mojom::URLResponseHeadPtr head_;
+  scoped_refptr<net::StringIOBuffer> body_buffer_;
+
+  // Keeps track of the position of the data transfer.
+  int write_position_ = 0;
+
+  // The length of |body_buffer_|.
+  const int bytes_of_raw_data_to_transfer_ = 0;
+
+  // Mojo plumbing.
+  mojo::Receiver<network::mojom::URLLoader> receiver_{this};
+  mojo::Remote<network::mojom::URLLoaderClient> client_;
+  mojo::ScopedDataPipeProducerHandle producer_handle_;
+  std::unique_ptr<mojo::SimpleWatcher> handle_watcher_;
+
+  base::WeakPtrFactory<SearchPrefetchFromStringURLLoader> weak_ptr_factory_{
+      this};
+};
+
+#endif  // CHROME_BROWSER_PREFETCH_SEARCH_PREFETCH_SEARCH_PREFETCH_FROM_STRING_URL_LOADER_H_
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_service.cc b/chrome/browser/prefetch/search_prefetch/search_prefetch_service.cc
index 33a898c..6131304 100644
--- a/chrome/browser/prefetch/search_prefetch/search_prefetch_service.cc
+++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_service.cc
@@ -4,7 +4,124 @@
 
 #include "chrome/browser/prefetch/search_prefetch/search_prefetch_service.h"
 
+#include "base/bind.h"
+#include "base/callback.h"
+#include "chrome/browser/prefetch/search_prefetch/field_trial_settings.h"
+#include "chrome/browser/prefetch/search_prefetch/prefetched_response_container.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "components/search_engines/template_url_service.h"
+#include "components/variations/net/variations_http_headers.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/common/content_constants.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_status_code.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "url/origin.h"
+
+SearchPrefetchService::PrefetchRequest::PrefetchRequest(
+    const GURL& prefetch_url)
+    : prefetch_url_(prefetch_url) {}
+
+SearchPrefetchService::PrefetchRequest::~PrefetchRequest() = default;
+
+void SearchPrefetchService::PrefetchRequest::StartPrefetchRequest(
+    Profile* profile) {
+  net::NetworkTrafficAnnotationTag traffic_annotation =
+      net::DefineNetworkTrafficAnnotation("search_prefetch_service", R"(
+        semantics {
+          sender: "Search Prefetch Service"
+          description:
+            "Prefetches search results page (HTML) based on omnibox hints "
+            "provided by the user's default search engine. This allows the "
+            "prefetched content to be served when the user navigates to the "
+            "omnibox hint."
+          trigger:
+            "User typing in the omnibox and the default search provider "
+            "indicates the provided omnibox hint entry is likely to be "
+            "navigated which would result in loading a search results page for "
+            "that hint."
+          data: "Credentials if user is signed in."
+          destination: OTHER
+          destination_other: "The user's default search engine."
+        }
+        policy {
+          cookies_allowed: YES
+          cookies_store: "user"
+          setting:
+            "Users can control this feature by opting out of 'Preload pages "
+            "for faster browsing and searching'"
+          chrome_policy {
+            DefaultSearchProviderEnabled {
+              policy_options {mode: MANDATORY}
+              DefaultSearchProviderEnabled: false
+            }
+            NetworkPredictionOptions {
+              NetworkPredictionOptions: 2
+            }
+          }
+        })");
+
+  auto resource_request = std::make_unique<network::ResourceRequest>();
+  resource_request->load_flags |= net::LOAD_PREFETCH;
+  resource_request->url = prefetch_url_;
+  resource_request->credentials_mode =
+      network::mojom::CredentialsMode::kInclude;
+  variations::AppendVariationsHeaderUnknownSignedIn(
+      prefetch_url_, variations::InIncognito::kNo, resource_request.get());
+  resource_request->headers.SetHeader(content::kCorsExemptPurposeHeaderName,
+                                      "prefetch");
+  // TODO(ryansturm): Find other headers that may need to be set.
+  // https://crbug.com/1138648
+
+  simple_loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
+                                                    traffic_annotation);
+
+  auto url_loader_factory =
+      content::BrowserContext::GetDefaultStoragePartition(profile)
+          ->GetURLLoaderFactoryForBrowserProcess();
+
+  simple_loader_->DownloadToString(
+      url_loader_factory.get(),
+      base::BindOnce(&SearchPrefetchService::PrefetchRequest::LoadDone,
+                     base::Unretained(this)),
+      1024 * 1024);
+}
+
+void SearchPrefetchService::PrefetchRequest::LoadDone(
+    std::unique_ptr<std::string> response_body) {
+  bool success = simple_loader_->NetError() == net::OK;
+  int response_code = 0;
+
+  // TODO(ryansturm): Handle these errors more robustly by reporting them to the
+  // service. We need to prevent prefetches for x amount of time based on the
+  // error. https://crbug.com/1138641
+  if (!success || response_body->empty()) {
+    current_status_ = SearchPrefetchStatus::kRequestFailed;
+    return;
+  }
+  if (simple_loader_->ResponseInfo() && simple_loader_->ResponseInfo()->headers)
+    response_code = simple_loader_->ResponseInfo()->headers->response_code();
+  if (response_code != net::HTTP_OK) {
+    current_status_ = SearchPrefetchStatus::kRequestFailed;
+    return;
+  }
+  current_status_ = SearchPrefetchStatus::kSuccessfullyCompleted;
+
+  prefetch_response_container_ = std::make_unique<PrefetchedResponseContainer>(
+      simple_loader_->ResponseInfo()->Clone(), std::move(response_body));
+
+  simple_loader_.reset();
+}
+
+std::unique_ptr<PrefetchedResponseContainer>
+SearchPrefetchService::PrefetchRequest::TakePrefetchResponse() {
+  return std::move(prefetch_response_container_);
+}
 
 SearchPrefetchService::SearchPrefetchService(Profile* profile)
     : profile_(profile) {
@@ -12,3 +129,87 @@
 }
 
 SearchPrefetchService::~SearchPrefetchService() = default;
+
+bool SearchPrefetchService::MaybePrefetchURL(const GURL& url) {
+  if (!SearchPrefetchServicePrefetchingIsEnabled())
+    return false;
+
+  auto* template_url_service =
+      TemplateURLServiceFactory::GetForProfile(profile_);
+  if (!template_url_service)
+    return false;
+  base::string16 search_terms;
+
+  // Extract the terms directly to make sure this string will match the URL
+  // interception string logic.
+  template_url_service->GetDefaultSearchProvider()->ExtractSearchTermsFromURL(
+      url, template_url_service->search_terms_data(), &search_terms);
+
+  if (search_terms.size() == 0)
+    return false;
+
+  // Don't prefetch the same search terms twice within the expiry duration.
+  if (prefetches_.find(search_terms) != prefetches_.end()) {
+    return false;
+  }
+
+  prefetches_.emplace(search_terms, std::make_unique<PrefetchRequest>(url));
+  prefetches_[search_terms]->StartPrefetchRequest(profile_);
+  return true;
+  // TODO(ryansturm): Expire entries after 60 seconds. https://crbug.com/1138639
+}
+
+base::Optional<SearchPrefetchStatus>
+SearchPrefetchService::GetSearchPrefetchStatusForTesting(
+    base::string16 search_terms) {
+  if (prefetches_.find(search_terms) == prefetches_.end())
+    return base::nullopt;
+  return prefetches_[search_terms]->current_status();
+}
+
+std::unique_ptr<PrefetchedResponseContainer>
+SearchPrefetchService::TakePrefetchResponse(const GURL& url) {
+  auto* template_url_service =
+      TemplateURLServiceFactory::GetForProfile(profile_);
+  if (!template_url_service)
+    return nullptr;
+
+  base::string16 search_terms;
+  template_url_service->GetDefaultSearchProvider()->ExtractSearchTermsFromURL(
+      url, template_url_service->search_terms_data(), &search_terms);
+
+  if (search_terms.length() == 0) {
+    return nullptr;
+  }
+
+  const auto& iter = prefetches_.find(search_terms);
+
+  if (iter == prefetches_.end()) {
+    return nullptr;
+  }
+
+  // Verify that the URL is the same origin as the prefetch URL. While other
+  // checks should address this by clearing prefetches on user changes to
+  // default search, it is paramount to never serve content from one origin to
+  // another.
+  if (url::Origin::Create(url) !=
+      url::Origin::Create(iter->second->prefetch_url())) {
+    return nullptr;
+  }
+
+  if (iter->second->current_status() !=
+      SearchPrefetchStatus::kSuccessfullyCompleted) {
+    return nullptr;
+  }
+
+  std::unique_ptr<PrefetchedResponseContainer> response =
+      iter->second->TakePrefetchResponse();
+
+  // TODO(ryansturm): For metrics reporting, the prefetch request data should be
+  // moved to the correct tab helper object, for now, the object can be deleted
+  // entirely. Alternatively, the object can remain here with a new timeout in
+  // a set of currently being served requests.
+  prefetches_.erase(iter);
+
+  return response;
+}
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_service.h b/chrome/browser/prefetch/search_prefetch/search_prefetch_service.h
index ed61519..fdb7fcdf 100644
--- a/chrome/browser/prefetch/search_prefetch/search_prefetch_service.h
+++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_service.h
@@ -5,16 +5,91 @@
 #ifndef CHROME_BROWSER_PREFETCH_SEARCH_PREFETCH_SEARCH_PREFETCH_SERVICE_H_
 #define CHROME_BROWSER_PREFETCH_SEARCH_PREFETCH_SEARCH_PREFETCH_SERVICE_H_
 
+#include <map>
+
+#include "base/callback.h"
+#include "base/optional.h"
+#include "base/strings/string16.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+#include "url/gurl.h"
 
 class Profile;
+class GURL;
+class PrefetchedResponseContainer;
+
+enum class SearchPrefetchStatus {
+  // The request is on the network and may move to any other state.
+  kInFlight = 1,
+  // The request received all the data and is ready to serve.
+  kSuccessfullyCompleted = 2,
+  // The request hit an error and cannot be served.
+  kRequestFailed = 3,
+};
 
 class SearchPrefetchService : public KeyedService {
  public:
   explicit SearchPrefetchService(Profile* profile);
   ~SearchPrefetchService() override;
 
- private:
+  SearchPrefetchService(const SearchPrefetchService&) = delete;
+  SearchPrefetchService& operator=(const SearchPrefetchService&) = delete;
+
+  // Returns whether the prefetch started or not.
+  bool MaybePrefetchURL(const GURL& url);
+
+  // Takes the response from this object if |url| matches a prefetched URL.
+  std::unique_ptr<PrefetchedResponseContainer> TakePrefetchResponse(
+      const GURL& url);
+
+  // Reports the status of a prefetch for a given search term.
+  base::Optional<SearchPrefetchStatus> GetSearchPrefetchStatusForTesting(
+      base::string16 search_terms);
+
+  // Internal class to represent an ongoing or completed prefetch.
+  class PrefetchRequest {
+   public:
+    // |service| must outlive this class and be able to manage this class's
+    // lifetime.
+    explicit PrefetchRequest(const GURL& prefetch_url);
+    ~PrefetchRequest();
+
+    PrefetchRequest(const PrefetchRequest&) = delete;
+    PrefetchRequest& operator=(const PrefetchRequest&) = delete;
+
+    // Starts the network request to prefetch |prefetch_url_|.
+    void StartPrefetchRequest(Profile* profile);
+
+    SearchPrefetchStatus current_status() const { return current_status_; }
+
+    const GURL& prefetch_url() const { return prefetch_url_; }
+
+    // Takes ownership of the prefetched data.
+    std::unique_ptr<PrefetchedResponseContainer> TakePrefetchResponse();
+
+   private:
+    // Called as a callback when the prefetch request is complete. Stores the
+    // response and other metadata in |prefetch_response_container_|.
+    void LoadDone(std::unique_ptr<std::string> response_body);
+
+    SearchPrefetchStatus current_status_ = SearchPrefetchStatus::kInFlight;
+
+    // The URL to prefetch the search terms from.
+    const GURL prefetch_url_;
+
+    // The ongoing prefetch request. Null before and after the fetch.
+    std::unique_ptr<network::SimpleURLLoader> simple_loader_;
+
+    // Once a prefetch is completed successfully, the associated prefetch data
+    // and metadata about the request.
+    std::unique_ptr<PrefetchedResponseContainer> prefetch_response_container_;
+  };
+
+  // Prefetches that are started are stored using search terms as a key. Only
+  // one prefetch should be started for a given search term until the old
+  // prefetch expires.
+  std::map<base::string16, std::unique_ptr<PrefetchRequest>> prefetches_;
+
   Profile* profile_;
 };
 
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc b/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc
index 0ce8b1f..e22c5a3 100644
--- a/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc
+++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc
@@ -2,18 +2,172 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/prefetch/search_prefetch/field_trial_settings.h"
 #include "chrome/browser/prefetch/search_prefetch/search_prefetch_service.h"
 #include "chrome/browser/prefetch/search_prefetch/search_prefetch_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/search_test_utils.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "components/prefs/pref_service.h"
+#include "components/search_engines/template_url_service.h"
+#include "content/public/browser/browser_task_traits.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/http/http_status_code.h"
+#include "net/test/embedded_test_server/default_handlers.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server_connection_listener.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
+#include "url/gurl.h"
 
-class SearchPrefetchServiceDisabledBrowserTest : public InProcessBrowserTest {
+class SearchPrefetchBaseBrowserTest : public InProcessBrowserTest {
+ public:
+  SearchPrefetchBaseBrowserTest() {
+    search_server_ = std::make_unique<net::EmbeddedTestServer>(
+        net::EmbeddedTestServer::TYPE_HTTPS);
+    search_server_->ServeFilesFromSourceDirectory("chrome/test/data");
+    search_server_->RegisterRequestHandler(
+        base::BindRepeating(&SearchPrefetchBaseBrowserTest::HandleSearchRequest,
+                            base::Unretained(this)));
+    EXPECT_TRUE(search_server_->Start());
+  }
+
+  void SetUpOnMainThread() override {
+    InProcessBrowserTest::SetUpOnMainThread();
+
+    host_resolver()->AddRule("search.test", "127.0.0.1");
+
+    TemplateURLService* model =
+        TemplateURLServiceFactory::GetForProfile(browser()->profile());
+    ASSERT_TRUE(model);
+    search_test_utils::WaitForTemplateURLServiceToLoad(model);
+    ASSERT_TRUE(model->loaded());
+
+    TemplateURLData data;
+    data.SetShortName(base::ASCIIToUTF16("search.test"));
+    data.SetKeyword(data.short_name());
+    data.SetURL(GetSearchServerQueryURL("{searchTerms}").spec());
+
+    TemplateURL* template_url = model->Add(std::make_unique<TemplateURL>(data));
+    ASSERT_TRUE(template_url);
+    model->SetUserSelectedDefaultSearchProvider(template_url);
+  }
+
+  void SetUpCommandLine(base::CommandLine* cmd) override {
+    InProcessBrowserTest::SetUpCommandLine(cmd);
+    // For the proxy.
+    cmd->AppendSwitch("ignore-certificate-errors");
+    cmd->AppendSwitch("force-enable-metrics-reporting");
+  }
+
+  size_t search_server_request_count() const {
+    return search_server_request_count_;
+  }
+
+  size_t search_server_prefetch_request_count() const {
+    return search_server_prefetch_request_count_;
+  }
+
+  const std::vector<net::test_server::HttpRequest>& search_server_requests()
+      const {
+    return search_server_requests_;
+  }
+
+  GURL GetSearchServerQueryURL(const std::string& path) const {
+    return search_server_->GetURL("search.test", "/search_page.html?q=" + path);
+  }
+
+  GURL GetSearchServerQueryURLWithNoQuery(const std::string& path) const {
+    return search_server_->GetURL("search.test", path);
+  }
+
+  void WaitUntilStatusChanges(base::string16 search_terms) {
+    auto* search_prefetch_service =
+        SearchPrefetchServiceFactory::GetForProfile(browser()->profile());
+    auto status = search_prefetch_service->GetSearchPrefetchStatusForTesting(
+        search_terms);
+    while (status == search_prefetch_service->GetSearchPrefetchStatusForTesting(
+                         search_terms)) {
+      base::RunLoop run_loop;
+      run_loop.RunUntilIdle();
+    }
+  }
+
+  content::WebContents* GetWebContents() const {
+    return browser()->tab_strip_model()->GetActiveWebContents();
+  }
+
+  std::string GetDocumentInnerHTML() const {
+    return content::EvalJs(GetWebContents(),
+                           "document.documentElement.innerHTML")
+        .ExtractString();
+  }
+
+ private:
+  std::unique_ptr<net::test_server::HttpResponse> HandleSearchRequest(
+      const net::test_server::HttpRequest& request) {
+    if (request.GetURL().spec().find("favicon") != std::string::npos)
+      return nullptr;
+
+    bool is_prefetch =
+        request.headers.find("Purpose") != request.headers.end() &&
+        request.headers.find("Purpose")->second == "prefetch";
+
+    content::GetUIThreadTaskRunner({})->PostTask(
+        FROM_HERE,
+        base::BindOnce(&SearchPrefetchBaseBrowserTest::
+                           MonitorSearchResourceRequestOnUIThread,
+                       base::Unretained(this), request, is_prefetch));
+
+    if (request.GetURL().spec().find("502_on_prefetch") != std::string::npos) {
+      std::unique_ptr<net::test_server::BasicHttpResponse> resp =
+          std::make_unique<net::test_server::BasicHttpResponse>();
+      resp->set_code(is_prefetch ? net::HTTP_BAD_GATEWAY : net::HTTP_OK);
+      resp->set_content_type("text/html");
+      resp->set_content("<html><body></body></html>");
+      return resp;
+    }
+
+    std::unique_ptr<net::test_server::BasicHttpResponse> resp =
+        std::make_unique<net::test_server::BasicHttpResponse>();
+    resp->set_code(net::HTTP_OK);
+    resp->set_content_type("text/html");
+    std::string content = "<html><body> ";
+    content.append(is_prefetch ? "prefetch" : "regular");
+    content.append(" </body></html>");
+    resp->set_content(content);
+    return resp;
+  }
+
+  void MonitorSearchResourceRequestOnUIThread(
+      net::test_server::HttpRequest request,
+      bool has_prefetch_header) {
+    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+    search_server_request_count_++;
+    search_server_requests_.push_back(request);
+    if (has_prefetch_header) {
+      search_server_prefetch_request_count_++;
+    }
+  }
+
+  std::unique_ptr<net::EmbeddedTestServer> search_server_;
+
+  std::vector<net::test_server::HttpRequest> search_server_requests_;
+
+  size_t search_server_request_count_ = 0;
+  size_t search_server_prefetch_request_count_ = 0;
+};
+
+class SearchPrefetchServiceDisabledBrowserTest
+    : public SearchPrefetchBaseBrowserTest {
  public:
   SearchPrefetchServiceDisabledBrowserTest() {
     feature_list_.InitAndDisableFeature(kSearchPrefetchService);
@@ -29,10 +183,57 @@
             SearchPrefetchServiceFactory::GetForProfile(browser()->profile()));
 }
 
-class SearchPrefetchServiceEnabledBrowserTest : public InProcessBrowserTest {
+class SearchPrefetchServiceEnabledWithoutPrefetchingBrowserTest
+    : public SearchPrefetchBaseBrowserTest {
+ public:
+  SearchPrefetchServiceEnabledWithoutPrefetchingBrowserTest() {
+    feature_list_.InitWithFeatures({kSearchPrefetchService},
+                                   {kSearchPrefetchServicePrefetching});
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(
+    SearchPrefetchServiceEnabledWithoutPrefetchingBrowserTest,
+    ServiceNotCreatedWhenIncognito) {
+  EXPECT_EQ(nullptr, SearchPrefetchServiceFactory::GetForProfile(
+                         browser()->profile()->GetPrimaryOTRProfile()));
+}
+
+IN_PROC_BROWSER_TEST_F(
+    SearchPrefetchServiceEnabledWithoutPrefetchingBrowserTest,
+    ServiceCreatedWhenFeatureEnabled) {
+  EXPECT_NE(nullptr,
+            SearchPrefetchServiceFactory::GetForProfile(browser()->profile()));
+}
+
+IN_PROC_BROWSER_TEST_F(
+    SearchPrefetchServiceEnabledWithoutPrefetchingBrowserTest,
+    NoFetchWhenPrefetchDisabled) {
+  auto* search_prefetch_service =
+      SearchPrefetchServiceFactory::GetForProfile(browser()->profile());
+  EXPECT_NE(nullptr, search_prefetch_service);
+
+  std::string search_terms = "prefetch_content";
+
+  GURL prefetch_url = GetSearchServerQueryURL(search_terms);
+
+  EXPECT_FALSE(search_prefetch_service->MaybePrefetchURL(prefetch_url));
+  auto prefetch_status =
+      search_prefetch_service->GetSearchPrefetchStatusForTesting(
+          base::ASCIIToUTF16(search_terms));
+
+  EXPECT_FALSE(prefetch_status.has_value());
+}
+
+class SearchPrefetchServiceEnabledBrowserTest
+    : public SearchPrefetchBaseBrowserTest {
  public:
   SearchPrefetchServiceEnabledBrowserTest() {
-    feature_list_.InitAndEnableFeature(kSearchPrefetchService);
+    feature_list_.InitWithFeatures(
+        {kSearchPrefetchService, kSearchPrefetchServicePrefetching}, {});
   }
 
  private:
@@ -50,3 +251,175 @@
   EXPECT_NE(nullptr,
             SearchPrefetchServiceFactory::GetForProfile(browser()->profile()));
 }
+
+IN_PROC_BROWSER_TEST_F(SearchPrefetchServiceEnabledBrowserTest,
+                       BasicPrefetchFunctionality) {
+  auto* search_prefetch_service =
+      SearchPrefetchServiceFactory::GetForProfile(browser()->profile());
+  EXPECT_NE(nullptr, search_prefetch_service);
+
+  std::string search_terms = "prefetch_content";
+
+  GURL prefetch_url = GetSearchServerQueryURL(search_terms);
+
+  EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url));
+  auto prefetch_status =
+      search_prefetch_service->GetSearchPrefetchStatusForTesting(
+          base::ASCIIToUTF16(search_terms));
+  ASSERT_TRUE(prefetch_status.has_value());
+  EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value());
+
+  WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms));
+
+  EXPECT_EQ(1u, search_server_requests().size());
+  EXPECT_NE(std::string::npos,
+            search_server_requests()[0].GetURL().spec().find(search_terms));
+  EXPECT_EQ(1u, search_server_request_count());
+  EXPECT_EQ(1u, search_server_prefetch_request_count());
+
+  prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting(
+      base::ASCIIToUTF16(search_terms));
+  ASSERT_TRUE(prefetch_status.has_value());
+  EXPECT_EQ(SearchPrefetchStatus::kSuccessfullyCompleted,
+            prefetch_status.value());
+}
+
+IN_PROC_BROWSER_TEST_F(SearchPrefetchServiceEnabledBrowserTest,
+                       502PrefetchFunctionality) {
+  auto* search_prefetch_service =
+      SearchPrefetchServiceFactory::GetForProfile(browser()->profile());
+  EXPECT_NE(nullptr, search_prefetch_service);
+
+  std::string search_terms = "502_on_prefetch";
+
+  GURL prefetch_url = GetSearchServerQueryURL(search_terms);
+
+  EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url));
+  auto prefetch_status =
+      search_prefetch_service->GetSearchPrefetchStatusForTesting(
+          base::ASCIIToUTF16(search_terms));
+  ASSERT_TRUE(prefetch_status.has_value());
+  EXPECT_EQ(SearchPrefetchStatus::kInFlight, prefetch_status.value());
+
+  WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms));
+
+  EXPECT_EQ(1u, search_server_requests().size());
+  EXPECT_NE(std::string::npos,
+            search_server_requests()[0].GetURL().spec().find(search_terms));
+  EXPECT_EQ(1u, search_server_request_count());
+  EXPECT_EQ(1u, search_server_prefetch_request_count());
+
+  prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting(
+      base::ASCIIToUTF16(search_terms));
+  ASSERT_TRUE(prefetch_status.has_value());
+  EXPECT_EQ(SearchPrefetchStatus::kRequestFailed, prefetch_status.value());
+}
+
+IN_PROC_BROWSER_TEST_F(SearchPrefetchServiceEnabledBrowserTest,
+                       FetchSameTermsOnlyOnce) {
+  auto* search_prefetch_service =
+      SearchPrefetchServiceFactory::GetForProfile(browser()->profile());
+  EXPECT_NE(nullptr, search_prefetch_service);
+
+  std::string search_terms = "prefetch_content";
+
+  GURL prefetch_url = GetSearchServerQueryURL(search_terms);
+
+  EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url));
+
+  WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms));
+
+  EXPECT_FALSE(search_prefetch_service->MaybePrefetchURL(prefetch_url));
+}
+
+IN_PROC_BROWSER_TEST_F(SearchPrefetchServiceEnabledBrowserTest, BadURL) {
+  auto* search_prefetch_service =
+      SearchPrefetchServiceFactory::GetForProfile(browser()->profile());
+  EXPECT_NE(nullptr, search_prefetch_service);
+
+  std::string search_path = "/bad_path";
+
+  GURL prefetch_url = GetSearchServerQueryURLWithNoQuery(search_path);
+
+  EXPECT_FALSE(search_prefetch_service->MaybePrefetchURL(prefetch_url));
+}
+
+IN_PROC_BROWSER_TEST_F(SearchPrefetchServiceEnabledBrowserTest,
+                       BasicPrefetchServed) {
+  auto* search_prefetch_service =
+      SearchPrefetchServiceFactory::GetForProfile(browser()->profile());
+  EXPECT_NE(nullptr, search_prefetch_service);
+
+  std::string search_terms = "prefetch_content";
+
+  GURL prefetch_url = GetSearchServerQueryURL(search_terms);
+
+  EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url));
+  auto prefetch_status =
+      search_prefetch_service->GetSearchPrefetchStatusForTesting(
+          base::ASCIIToUTF16(search_terms));
+  WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms));
+
+  prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting(
+      base::ASCIIToUTF16(search_terms));
+  ASSERT_TRUE(prefetch_status.has_value());
+  EXPECT_EQ(SearchPrefetchStatus::kSuccessfullyCompleted,
+            prefetch_status.value());
+
+  ui_test_utils::NavigateToURL(browser(), prefetch_url);
+
+  auto inner_html = GetDocumentInnerHTML();
+
+  EXPECT_FALSE(base::Contains(inner_html, "regular"));
+  EXPECT_TRUE(base::Contains(inner_html, "prefetch"));
+}
+
+IN_PROC_BROWSER_TEST_F(SearchPrefetchServiceEnabledBrowserTest,
+                       RegularSearchQueryWhenNoPrefetch) {
+  auto* search_prefetch_service =
+      SearchPrefetchServiceFactory::GetForProfile(browser()->profile());
+  EXPECT_NE(nullptr, search_prefetch_service);
+
+  std::string search_terms = "prefetch_content";
+
+  GURL search_url = GetSearchServerQueryURL(search_terms);
+
+  ui_test_utils::NavigateToURL(browser(), search_url);
+
+  auto inner_html = GetDocumentInnerHTML();
+
+  EXPECT_TRUE(base::Contains(inner_html, "regular"));
+  EXPECT_FALSE(base::Contains(inner_html, "prefetch"));
+}
+
+IN_PROC_BROWSER_TEST_F(SearchPrefetchServiceEnabledBrowserTest,
+                       NonMatchingPrefetchURL) {
+  auto* search_prefetch_service =
+      SearchPrefetchServiceFactory::GetForProfile(browser()->profile());
+  EXPECT_NE(nullptr, search_prefetch_service);
+
+  std::string search_terms = "prefetch_content";
+  std::string search_terms_other = "other";
+
+  GURL prefetch_url = GetSearchServerQueryURL(search_terms);
+
+  EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url));
+  auto prefetch_status =
+      search_prefetch_service->GetSearchPrefetchStatusForTesting(
+          base::ASCIIToUTF16(search_terms));
+  WaitUntilStatusChanges(base::ASCIIToUTF16(search_terms));
+
+  prefetch_status = search_prefetch_service->GetSearchPrefetchStatusForTesting(
+      base::ASCIIToUTF16(search_terms));
+  ASSERT_TRUE(prefetch_status.has_value());
+  EXPECT_EQ(SearchPrefetchStatus::kSuccessfullyCompleted,
+            prefetch_status.value());
+
+  ui_test_utils::NavigateToURL(browser(),
+                               GetSearchServerQueryURL(search_terms_other));
+
+  auto inner_html = GetDocumentInnerHTML();
+
+  EXPECT_TRUE(base::Contains(inner_html, "regular"));
+  EXPECT_FALSE(base::Contains(inner_html, "prefetch"));
+}
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_url_loader_interceptor.cc b/chrome/browser/prefetch/search_prefetch/search_prefetch_url_loader_interceptor.cc
new file mode 100644
index 0000000..e821312
--- /dev/null
+++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_url_loader_interceptor.cc
@@ -0,0 +1,90 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefetch/search_prefetch/search_prefetch_url_loader_interceptor.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/feature_list.h"
+#include "base/metrics/histogram_macros.h"
+#include "chrome/browser/prefetch/search_prefetch/prefetched_response_container.h"
+#include "chrome/browser/prefetch/search_prefetch/search_prefetch_from_string_url_loader.h"
+#include "chrome/browser/prefetch/search_prefetch/search_prefetch_service.h"
+#include "chrome/browser/prefetch/search_prefetch/search_prefetch_service_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/prerender/browser/prerender_manager.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/browser/web_contents.h"
+
+namespace {
+
+Profile* ProfileFromFrameTreeNodeID(int frame_tree_node_id) {
+  content::WebContents* web_contents =
+      content::WebContents::FromFrameTreeNodeId(frame_tree_node_id);
+  if (!web_contents)
+    return nullptr;
+  return Profile::FromBrowserContext(web_contents->GetBrowserContext());
+}
+
+}  // namespace
+
+SearchPrefetchURLLoaderInterceptor::SearchPrefetchURLLoaderInterceptor(
+    int frame_tree_node_id)
+    : frame_tree_node_id_(frame_tree_node_id) {}
+
+SearchPrefetchURLLoaderInterceptor::~SearchPrefetchURLLoaderInterceptor() =
+    default;
+
+void SearchPrefetchURLLoaderInterceptor::MaybeCreateLoader(
+    const network::ResourceRequest& tentative_resource_request,
+    content::BrowserContext* browser_context,
+    content::URLLoaderRequestInterceptor::LoaderCallback callback) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  DCHECK(!loader_callback_);
+  loader_callback_ = std::move(callback);
+  url_ = tentative_resource_request.url;
+
+  std::unique_ptr<PrefetchedResponseContainer> prefetch =
+      GetPrefetchedResponse(url_);
+  if (!prefetch) {
+    DoNotInterceptPrefetchedNavigation();
+    return;
+  }
+
+  InterceptPrefetchedNavigation(tentative_resource_request,
+                                std::move(prefetch));
+}
+
+void SearchPrefetchURLLoaderInterceptor::InterceptPrefetchedNavigation(
+    const network::ResourceRequest& tentative_resource_request,
+    std::unique_ptr<PrefetchedResponseContainer> prefetch) {
+  std::unique_ptr<SearchPrefetchFromStringURLLoader> url_loader =
+      std::make_unique<SearchPrefetchFromStringURLLoader>(
+          std::move(prefetch), tentative_resource_request);
+  std::move(loader_callback_).Run(url_loader->ServingResponseHandler());
+  // url_loader manages its own lifetime once bound to the mojo pipes.
+  url_loader.release();
+}
+
+void SearchPrefetchURLLoaderInterceptor::DoNotInterceptPrefetchedNavigation() {
+  std::move(loader_callback_).Run({});
+}
+
+std::unique_ptr<PrefetchedResponseContainer>
+SearchPrefetchURLLoaderInterceptor::GetPrefetchedResponse(const GURL& url) {
+  auto* profile = ProfileFromFrameTreeNodeID(frame_tree_node_id_);
+  if (!profile)
+    return nullptr;
+
+  SearchPrefetchService* service =
+      SearchPrefetchServiceFactory::GetForProfile(profile);
+  if (!service)
+    return nullptr;
+
+  return service->TakePrefetchResponse(url);
+}
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_url_loader_interceptor.h b/chrome/browser/prefetch/search_prefetch/search_prefetch_url_loader_interceptor.h
new file mode 100644
index 0000000..fd954a8
--- /dev/null
+++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_url_loader_interceptor.h
@@ -0,0 +1,70 @@
+// 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_PREFETCH_SEARCH_PREFETCH_SEARCH_PREFETCH_URL_LOADER_INTERCEPTOR_H_
+#define CHROME_BROWSER_PREFETCH_SEARCH_PREFETCH_SEARCH_PREFETCH_URL_LOADER_INTERCEPTOR_H_
+
+#include <memory>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "base/sequence_checker.h"
+#include "base/time/time.h"
+#include "content/public/browser/url_loader_request_interceptor.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "url/gurl.h"
+
+namespace content {
+class BrowserContext;
+}  // namespace content
+
+class PrefetchedResponseContainer;
+
+// Intercepts search navigations that were previously prefetched.
+class SearchPrefetchURLLoaderInterceptor
+    : public content::URLLoaderRequestInterceptor {
+ public:
+  explicit SearchPrefetchURLLoaderInterceptor(int frame_tree_node_id);
+  ~SearchPrefetchURLLoaderInterceptor() override;
+
+  SearchPrefetchURLLoaderInterceptor(
+      const SearchPrefetchURLLoaderInterceptor&) = delete;
+  SearchPrefetchURLLoaderInterceptor& operator=(
+      const SearchPrefetchURLLoaderInterceptor&) = delete;
+
+  // content::URLLaoderRequestInterceptor:
+  void MaybeCreateLoader(
+      const network::ResourceRequest& tentative_resource_request,
+      content::BrowserContext* browser_context,
+      content::URLLoaderRequestInterceptor::LoaderCallback callback) override;
+
+ protected:
+  // Virtual for testing
+  virtual std::unique_ptr<PrefetchedResponseContainer> GetPrefetchedResponse(
+      const GURL& url);
+
+ private:
+  void InterceptPrefetchedNavigation(
+      const network::ResourceRequest& tentative_resource_request,
+      std::unique_ptr<PrefetchedResponseContainer>);
+  void DoNotInterceptPrefetchedNavigation();
+
+  bool MaybeInterceptNavigation(
+      const network::ResourceRequest& tentative_resource_request);
+
+  // Used to get the current WebContents/Profile.
+  const int frame_tree_node_id_;
+
+  // The url that |MaybeCreateLoader| is called with.
+  GURL url_;
+
+  // Set in |MaybeCreateLoader| and used in |On[DoNot]InterceptRequest|.
+  content::URLLoaderRequestInterceptor::LoaderCallback loader_callback_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+};
+
+#endif  // CHROME_BROWSER_PREFETCH_SEARCH_PREFETCH_SEARCH_PREFETCH_URL_LOADER_INTERCEPTOR_H_
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 5a80af8..f1f5d3c 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -68,7 +68,6 @@
 #include "chrome/browser/push_messaging/push_messaging_app_identifier.h"
 #include "chrome/browser/rlz/chrome_rlz_tracker_delegate.h"
 #include "chrome/browser/search/search.h"
-#include "chrome/browser/search/shopping_tasks/shopping_tasks_service.h"
 #include "chrome/browser/sharing/sharing_sync_preference.h"
 #include "chrome/browser/ssl/ssl_config_service_manager.h"
 #include "chrome/browser/storage/appcache_feature_prefs.h"
@@ -236,7 +235,9 @@
 #include "chrome/browser/nearby_sharing/common/nearby_share_prefs.h"
 #include "chrome/browser/search/instant_service.h"
 #include "chrome/browser/search/promos/promo_service.h"
+#include "chrome/browser/search/recipe_tasks/recipe_tasks_service.h"
 #include "chrome/browser/search/search_suggest/search_suggest_service.h"
+#include "chrome/browser/search/shopping_tasks/shopping_tasks_service.h"
 #include "chrome/browser/signin/signin_promo.h"
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
 #include "chrome/browser/ui/webui/history/foreign_session_handler.h"
@@ -899,6 +900,7 @@
   ntp_tiles::CustomLinksManagerImpl::RegisterProfilePrefs(registry);
   PinnedTabCodec::RegisterProfilePrefs(registry);
   PromoService::RegisterProfilePrefs(registry);
+  RecipeTasksService::RegisterProfilePrefs(registry);
   SearchSuggestService::RegisterProfilePrefs(registry);
   settings::SettingsUI::RegisterProfilePrefs(registry);
   send_tab_to_self::SendTabToSelfBubbleController::RegisterProfilePrefs(
diff --git a/chrome/browser/privacy_budget/privacy_budget_browsertest.cc b/chrome/browser/privacy_budget/privacy_budget_browsertest.cc
index d73fdda..0f3b44ad 100644
--- a/chrome/browser/privacy_budget/privacy_budget_browsertest.cc
+++ b/chrome/browser/privacy_budget/privacy_budget_browsertest.cc
@@ -12,6 +12,7 @@
 #include "components/variations/service/buildflags.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_utils.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -120,6 +121,50 @@
       }));
 }
 
+IN_PROC_BROWSER_TEST_F(PrivacyBudgetBrowserTest, CallsCanvasToBlob) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  content::DOMMessageQueue messages;
+  base::RunLoop run_loop;
+
+  recorder().SetOnAddEntryCallback(ukm::builders::Identifiability::kEntryName,
+                                   run_loop.QuitClosure());
+
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents(), embedded_test_server()->GetURL(
+                          "/privacy_budget/calls_canvas_to_blob.html")));
+
+  // The document calls an instrumented method and sends a message
+  // back to the test. Receipt of the message indicates that the script
+  // successfully completed. However, we must also wait for the UKM metric to be
+  // recorded, which happens on a TaskRunner.
+  std::string blob_type;
+  ASSERT_TRUE(messages.WaitForMessage(&blob_type));
+
+  // Navigating away from the test page causes the document to be unloaded. That
+  // will cause any buffered metrics to be flushed.
+  content::NavigateToURLBlockUntilNavigationsComplete(web_contents(),
+                                                      GURL("about:blank"), 1);
+
+  // Wait for the metrics to come down the pipe.
+  content::RunAllTasksUntilIdle();
+  run_loop.Run();
+
+  auto merged_entries = recorder().GetMergedEntriesByName(
+      ukm::builders::Identifiability::kEntryName);
+  // Shouldn't be more than one source here. If this changes, then we'd need to
+  // adjust this test to deal.
+  ASSERT_EQ(1u, merged_entries.size());
+
+  constexpr uint64_t input_digest = 0;
+  EXPECT_THAT(merged_entries.begin()->second->metrics,
+              IsSupersetOf({
+                  Key(blink::IdentifiableSurface::FromTypeAndToken(
+                          blink::IdentifiableSurface::Type::kCanvasReadback,
+                          input_digest)
+                          .ToUkmMetricHash()),
+              }));
+}
+
 #if BUILDFLAG(FIELDTRIAL_TESTING_ENABLED)
 
 namespace {
diff --git a/chrome/browser/profiles/profile_destroyer.cc b/chrome/browser/profiles/profile_destroyer.cc
index f083a9bd..c25d214 100644
--- a/chrome/browser/profiles/profile_destroyer.cc
+++ b/chrome/browser/profiles/profile_destroyer.cc
@@ -98,10 +98,7 @@
   // on later.
   HostSet profile_hosts = GetHostsForProfile(profile);
   void* profile_ptr = profile;
-  // TODO(https://crbug.com/1033903): Updated to cover all OTR profiles.
-  void* otr_profile_ptr = profile->HasPrimaryOTRProfile()
-                              ? profile->GetPrimaryOTRProfile()
-                              : nullptr;
+  std::vector<Profile*> otr_profiles = profile->GetAllOffTheRecordProfiles();
 #endif  // DCHECK_IS_ON()
 
   delete profile;
@@ -111,8 +108,9 @@
   // and off-the-record Profile.
   const size_t profile_hosts_count = GetHostsForProfile(profile_ptr).size();
   base::debug::Alias(&profile_hosts_count);
-  const size_t off_the_record_profile_hosts_count =
-      otr_profile_ptr ? GetHostsForProfile(otr_profile_ptr).size() : 0u;
+  size_t off_the_record_profile_hosts_count = 0;
+  for (Profile* otr : otr_profiles)
+    off_the_record_profile_hosts_count += GetHostsForProfile(otr).size();
   base::debug::Alias(&off_the_record_profile_hosts_count);
 
   // |profile| is not off-the-record, so if |profile_hosts| is not empty then
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index 6d54647..4e4ff9b 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -1886,14 +1886,18 @@
   if (profile->IsGuestSession() || profile->IsEphemeralGuestProfile())
     CleanUpGuestProfile();
 
+  ProfileAttributesEntry* entry;
+  bool background_mode =
+      GetProfileAttributesStorage().GetProfileAttributesWithPath(
+          profile->GetPath(), &entry) &&
+      entry->GetBackgroundStatus();
   if (base::FeatureList::IsEnabled(features::kDestroyProfileOnBrowserClose) &&
       !profile->IsOffTheRecord() &&
-      !profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) {
+      !profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles) &&
+      !background_mode) {
     // TODO(crbug.com/88586): Add EarlyProfileCleanup support for Guest and
     // Ephemeral profiles.
 
-    // TODO(crbug.com/88586): Make sure this works with Background Mode.
-
     // Post a task to remove the Profile, so other OnBrowserClosed() hooks and
     // the destructor for Browser can run without referencing a deleted Profile.
     content::GetUIThreadTaskRunner({})->PostTask(
diff --git a/chrome/browser/profiles/profile_window_browsertest.cc b/chrome/browser/profiles/profile_window_browsertest.cc
index 84a5530..6f647454 100644
--- a/chrome/browser/profiles/profile_window_browsertest.cc
+++ b/chrome/browser/profiles/profile_window_browsertest.cc
@@ -124,38 +124,8 @@
   ProfileWindowBrowserTest(const ProfileWindowBrowserTest&) = delete;
   ProfileWindowBrowserTest& operator=(const ProfileWindowBrowserTest&) = delete;
   ~ProfileWindowBrowserTest() override = default;
-
-  Browser* OpenGuestBrowser();
 };
 
-Browser* ProfileWindowBrowserTest::OpenGuestBrowser() {
-  size_t num_browsers = BrowserList::GetInstance()->size();
-
-  // Create a guest browser nicely. Using CreateProfile() and CreateBrowser()
-  // does incomplete initialization that would lead to
-  // SystemUrlRequestContextGetter being leaked.
-  profiles::SwitchToGuestProfile(ProfileManager::CreateCallback());
-  ui_test_utils::WaitForBrowserToOpen();
-
-  DCHECK_NE(static_cast<Profile*>(nullptr),
-            g_browser_process->profile_manager()->GetProfileByPath(
-                ProfileManager::GetGuestProfilePath()));
-  EXPECT_EQ(num_browsers + 1, BrowserList::GetInstance()->size());
-
-  Profile* guest = g_browser_process->profile_manager()->GetProfileByPath(
-      ProfileManager::GetGuestProfilePath());
-  Browser* browser = chrome::FindAnyBrowser(guest, true);
-  EXPECT_TRUE(browser);
-
-  // When |browser| closes a BrowsingDataRemover will be created and executed.
-  // It needs a loaded TemplateUrlService or else it hangs on to a
-  // CallbackList::Subscription forever.
-  search_test_utils::WaitForTemplateURLServiceToLoad(
-      TemplateURLServiceFactory::GetForProfile(guest));
-
-  return browser;
-}
-
 class ProfileWindowCountBrowserTest
     : public ProfileWindowBrowserTest,
       public testing::WithParamInterface<ProfileWindowType> {
@@ -182,7 +152,7 @@
     // |is_incognito_| is used to determine which browser type to open.
     if (!profile_) {
       new_browser = is_incognito_ ? CreateIncognitoBrowser(browser()->profile())
-                                  : OpenGuestBrowser();
+                                  : CreateGuestBrowser();
       profile_ = new_browser->profile();
     } else {
       if (profile_->IsEphemeralGuestProfile())
@@ -258,11 +228,11 @@
 };
 
 IN_PROC_BROWSER_TEST_P(GuestProfileWindowBrowserTest, OpenGuestBrowser) {
-  EXPECT_TRUE(OpenGuestBrowser());
+  EXPECT_TRUE(CreateGuestBrowser());
 }
 
 IN_PROC_BROWSER_TEST_P(GuestProfileWindowBrowserTest, GuestIsOffTheRecord) {
-  Profile* guest_profile = OpenGuestBrowser()->profile();
+  Profile* guest_profile = CreateGuestBrowser()->profile();
   if (IsEphemeral())
     EXPECT_FALSE(guest_profile->IsOffTheRecord());
   else
@@ -270,7 +240,7 @@
 }
 
 IN_PROC_BROWSER_TEST_P(GuestProfileWindowBrowserTest, GuestIgnoresHistory) {
-  Browser* guest_browser = OpenGuestBrowser();
+  Browser* guest_browser = CreateGuestBrowser();
 
   ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
       guest_browser->profile(), ServiceAccessType::EXPLICIT_ACCESS));
@@ -291,7 +261,7 @@
 }
 
 IN_PROC_BROWSER_TEST_P(GuestProfileWindowBrowserTest, GuestClearsCookies) {
-  Browser* guest_browser = OpenGuestBrowser();
+  Browser* guest_browser = CreateGuestBrowser();
   Profile* guest_profile = guest_browser->profile();
 
   ASSERT_TRUE(embedded_test_server()->Start());
@@ -315,7 +285,7 @@
 
 IN_PROC_BROWSER_TEST_P(GuestProfileWindowBrowserTest,
                        GuestClearsFindInPageCache) {
-  Browser* guest_browser = OpenGuestBrowser();
+  Browser* guest_browser = CreateGuestBrowser();
   Profile* guest_profile = guest_browser->profile();
 
   base::string16 fip_text =
@@ -353,7 +323,7 @@
   if (IsEphemeral())
     return;
 
-  Browser* guest_browser = OpenGuestBrowser();
+  Browser* guest_browser = CreateGuestBrowser();
 
   signin::IdentityManager* identity_manager =
       IdentityManagerFactory::GetForProfile(guest_browser->profile());
@@ -371,7 +341,7 @@
   EXPECT_NE(-1, model_normal_profile.GetIndexOfCommandId(IDC_BOOKMARKS_MENU));
 
   // Guest browser has no bookmark menu.
-  Browser* guest_browser = OpenGuestBrowser();
+  Browser* guest_browser = CreateGuestBrowser();
   AppMenuModel model_guest_profile(&accelerator_handler, guest_browser);
   EXPECT_EQ(-1, model_guest_profile.GetIndexOfCommandId(IDC_BOOKMARKS_MENU));
 }
diff --git a/chrome/browser/renderer_preferences_util.cc b/chrome/browser/renderer_preferences_util.cc
index ddc3c1d..438df35d 100644
--- a/chrome/browser/renderer_preferences_util.cc
+++ b/chrome/browser/renderer_preferences_util.cc
@@ -21,7 +21,7 @@
 #include "content/public/browser/renderer_preferences_util.h"
 #include "media/media_buildflags.h"
 #include "third_party/blink/public/common/peerconnection/webrtc_ip_handling_policy.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/public_buildflags.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/ui_base_features.h"
@@ -94,7 +94,7 @@
 
 namespace renderer_preferences_util {
 
-void UpdateFromSystemSettings(blink::mojom::RendererPreferences* prefs,
+void UpdateFromSystemSettings(blink::RendererPreferences* prefs,
                               Profile* profile) {
   const PrefService* pref_service = profile->GetPrefs();
   if (profile->IsOffTheRecord()) {
diff --git a/chrome/browser/renderer_preferences_util.h b/chrome/browser/renderer_preferences_util.h
index 5fb617d..5150bafd 100644
--- a/chrome/browser/renderer_preferences_util.h
+++ b/chrome/browser/renderer_preferences_util.h
@@ -8,15 +8,13 @@
 class Profile;
 
 namespace blink {
-namespace mojom {
-class RendererPreferences;
-}
+struct RendererPreferences;
 }  // namespace blink
 
 namespace renderer_preferences_util {
 
 // Copies system configuration preferences into |prefs|.
-void UpdateFromSystemSettings(blink::mojom::RendererPreferences* prefs,
+void UpdateFromSystemSettings(blink::RendererPreferences* prefs,
                               Profile* profile);
 
 }  // namespace renderer_preferences_util
diff --git a/chrome/browser/resource_coordinator/OWNERS b/chrome/browser/resource_coordinator/OWNERS
index 4f7fbe4..e31d861 100644
--- a/chrome/browser/resource_coordinator/OWNERS
+++ b/chrome/browser/resource_coordinator/OWNERS
@@ -3,7 +3,7 @@
 fdoray@chromium.org
 
 # ChromeOS tab manager related implementation.
-per-file *chromeos*=cylee@chromium.org
+per-file *chromeos*=vovoy@chromium.org
 
 per-file *.mojom=set noparent
 per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn
index 20ecd25..ecf438d 100644
--- a/chrome/browser/resources/BUILD.gn
+++ b/chrome/browser/resources/BUILD.gn
@@ -226,6 +226,7 @@
 
     deps = [
       "//chrome/browser/promo_browser_command:mojo_bindings_js",
+      "//chrome/browser/search/recipe_tasks:mojo_bindings_js",
       "//chrome/browser/search/shopping_tasks:mojo_bindings_js",
       "//chrome/browser/ui/webui/new_tab_page:mojo_bindings_js",
       "//skia/public/mojom:mojom_js",
@@ -476,21 +477,22 @@
     grit_flags = [
       "-E",
       "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
+      "-E",
+      "root_src_dir=" + rebase_path("//", root_build_dir),
     ]
 
-    if (optimize_webui) {
-      source = "chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources_vulcanized.grd"
-
-      deps = [
-        "//chrome/browser/resources/chromeos/bluetooth_pairing_dialog:build",
-      ]
-    } else {
-      source = "chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources.grd"
-
-      deps = [ "//chrome/browser/resources/chromeos/bluetooth_pairing_dialog:web_components" ]
-    }
-
     defines = chrome_grit_defines
+
+    # These arguments are needed since the grd is generated at build time.
+    enable_input_discovery_for_gn_analyze = false
+    defines += [ "SHARED_INTERMEDIATE_DIR=" +
+                 rebase_path(root_gen_dir, root_build_dir) ]
+    bluetooth_gen_dir = "$root_gen_dir/chrome/browser/resources/chromeos/bluetooth_pairing_dialog"
+    source = "$bluetooth_gen_dir/bluetooth_pairing_dialog_resources.grd"
+    deps = [
+      "//chrome/browser/resources/chromeos/bluetooth_pairing_dialog:build_grd",
+    ]
+
     outputs = [
       "grit/bluetooth_pairing_dialog_resources.h",
       "grit/bluetooth_pairing_dialog_resources_map.cc",
@@ -679,21 +681,23 @@
 
 if (is_linux || is_chromeos) {
   grit("webui_js_exception_resources") {
-    if (optimize_webui) {
-      source = "webui_js_exception/webui_js_exception_resources_vulcanized.grd"
-      deps = [ "//chrome/browser/resources/webui_js_exception:build" ]
-    } else {
-      source = "webui_js_exception/webui_js_exception_resources.grd"
-      deps =
-          [ "//chrome/browser/resources/webui_js_exception:webui_js_exception" ]
-    }
-
     grit_flags = [
       "-E",
       "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
+      "-E",
+      "root_src_dir=" + rebase_path("//", root_build_dir),
     ]
 
     defines = chrome_grit_defines
+
+    # These arguments are needed since the grd is generated at build time.
+    enable_input_discovery_for_gn_analyze = false
+    defines += [ "SHARED_INTERMEDIATE_DIR=" +
+                 rebase_path(root_gen_dir, root_build_dir) ]
+    js_gen_dir = "$root_gen_dir/chrome/browser/resources/webui_js_exception"
+    source = "$js_gen_dir/webui_js_exception_resources.grd"
+    deps = [ "//chrome/browser/resources/webui_js_exception:build_grd" ]
+
     outputs = [
       "grit/webui_js_exception_resources.h",
       "grit/webui_js_exception_resources_map.cc",
diff --git a/chrome/browser/resources/bookmarks/folder_node.html b/chrome/browser/resources/bookmarks/folder_node.html
index 3feb687..b074b3b 100644
--- a/chrome/browser/resources/bookmarks/folder_node.html
+++ b/chrome/browser/resources/bookmarks/folder_node.html
@@ -46,9 +46,9 @@
   }
 
   @media (prefers-color-scheme: dark) {
-    .drag-on .menu-label,
-    .drag-on .folder-icon,
-    .drag-on #arrow {
+    #container.drag-on .menu-label,
+    #container.drag-on .folder-icon,
+    #container.drag-on #arrow {
       color: var(--google-grey-refresh-700);
     }
   }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
index dcd16fe..80d157d 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
@@ -3255,3 +3255,56 @@
         .replay();
   });
 });
+
+TEST_F('ChromeVoxBackgroundTest', 'MarkedContent', function() {
+  const mockFeedback = this.createMockFeedback();
+  const site = `
+    <p>Start</p>
+    <span>This is </span><span role="mark">my</span><span> text.</span>
+    <br>
+    <span>This is </span><span role="mark"
+        aria-roledescription="Comment">your</span><span> text.</span>
+    <br>
+    <span>This is </span><span role="suggestion"><span
+        role="insertion">their</span></span><span> text.</span>
+    <br>
+    <span>This is </span><span role="suggestion"><span
+        role="deletion">everyone's</span></span><span> text.</span>
+  `;
+  this.runWithLoadedTree(site, function(rootNode) {
+    mockFeedback.expectSpeech('Start')
+        .call(doCmd('nextObject'))
+        .expectSpeech('This is ')
+        .call(doCmd('nextObject'))
+        .expectSpeech('my', 'Marked content')
+        .expectBraille('my Marked content')
+        .call(doCmd('nextObject'))
+        .expectSpeech(' text.', 'Exited Marked content.')
+        .expectBraille(' text. Exited Marked content.')
+        .call(doCmd('nextObject'))
+        .expectSpeech('This is ')
+        .call(doCmd('nextObject'))
+        .expectSpeech('your', 'Comment')
+        .expectBraille('your Comment')
+        .call(doCmd('nextObject'))
+        .expectSpeech(' text.', 'Exited Comment.')
+        .expectBraille(' text. Exited Comment.')
+        .call(doCmd('nextObject'))
+        .expectSpeech('This is ')
+        .call(doCmd('nextObject'))
+        .expectSpeech('their', 'Insertion', 'Suggestion')
+        .expectBraille('their Insertion Suggestion')
+        .call(doCmd('nextObject'))
+        .expectSpeech(' text.', 'Exited Suggestion.', 'Exited Insertion.')
+        .expectBraille(' text. Exited Suggestion. Exited Insertion.')
+        .call(doCmd('nextObject'))
+        .expectSpeech('This is ')
+        .call(doCmd('nextObject'))
+        .expectSpeech(`everyone's`, 'Deletion', 'Suggestion')
+        .expectBraille(`everyone's Deletion Suggestion`)
+        .call(doCmd('nextObject'))
+        .expectSpeech(' text.', 'Exited Suggestion.', 'Exited Deletion.')
+        .expectBraille(' text. Exited Suggestion. Exited Deletion.')
+        .replay();
+  });
+});
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing_test.js
index 3adaf17..f74d9c7 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing_test.js
@@ -1585,3 +1585,44 @@
     assertEquals('ab', contentEditable.value);
   });
 });
+
+TEST_F('ChromeVoxEditingTest', 'MarkedContent', function() {
+  const mockFeedback = this.createMockFeedback();
+  const site = `
+    <div contenteditable role="textbox">
+      <p>Start</p>
+      <span>This is </span><span role="mark">my</span><span> text.</span>
+      <br>
+      <span>This is </span><span role="mark"
+          aria-roledescription="Comment">your</span><span> text.</span>
+      <br>
+      <span>This is </span><span role="suggestion"><span
+          role="insertion">their</span></span><span> text.</span>
+      <br>
+      <span>This is </span><span role="suggestion"><span
+          role="deletion">everyone's</span></span><span> text.</span>
+    </div>
+  `;
+  this.runWithLoadedTree(site, function(root) {
+    const input = root.find({role: RoleType.TEXT_FIELD});
+    this.listenOnce(input, 'focus', function() {
+      mockFeedback.call(this.press(KeyCode.DOWN))
+          .expectSpeech(
+              'This is ', 'my', 'Marked content', ' text.',
+              'Exited Marked content.')
+          .call(this.press(KeyCode.DOWN))
+          .expectSpeech(
+              'This is ', 'your', 'Comment', ' text.', 'Exited Comment.')
+          .call(this.press(KeyCode.DOWN))
+          .expectSpeech(
+              'This is ', 'their', 'Insertion', 'Suggestion', ' text.',
+              'Exited Suggestion.', 'Exited Insertion.')
+          .call(this.press(KeyCode.DOWN))
+          .expectSpeech(
+              'This is ', `everyone's`, 'Deletion', 'Suggestion', ' text.',
+              'Exited Suggestion.', 'Exited Deletion.')
+          .replay();
+    });
+    input.focus();
+  });
+});
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output.js
index e7415a7..8770350 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output.js
@@ -2292,6 +2292,7 @@
       {msgId: 'role_listitem', earconId: 'LIST_ITEM', inherits: 'abstractItem'},
   log: {msgId: 'role_log', inherits: 'abstractNameFromContents'},
   main: {msgId: 'role_main', inherits: 'abstractContainer'},
+  mark: {msgId: 'role_mark', inherits: 'abstractContainer'},
   marquee: {msgId: 'role_marquee', inherits: 'abstractNameFromContents'},
   math: {msgId: 'role_math', inherits: 'abstractContainer'},
   menu: {msgId: 'role_menu', outputContextFirst: true, ignoreAncestry: true},
@@ -2411,6 +2412,12 @@
 /**
  * Rules specifying format of AutomationNodes for output.
  * @type {!Object<Object<Object<string>>>}
+ * Please see below for more information on properties.
+ * speak: The speech rule for when ChromeVox range lands exactly on the node.
+ * braille: The braille rule for when ChromeVox range lands exactly on the node.
+ * enter: The rule for when ChromeVox range enters the node's subtree.
+ *    Can contain speak and braille properties.
+ * leave: The rule for when ChromeVox range exits the node's subtree.
  */
 Output.RULES = {
   navigate: {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/msgs.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/msgs.js
index 873cde2..ea1d320 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/msgs.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/msgs.js
@@ -36,6 +36,14 @@
       return Msgs.applySubstitutions_(message, opt_subs);
     }
     message = chrome.i18n.getMessage(Msgs.NAMESPACE_ + messageId, opt_subs);
+    if ((message === undefined || message === '') &&
+        messageId.endsWith('_brl')) {
+      // Braille string entries are optional. If we couldn't find a braille-
+      // specific string, try again without the '_brl' suffix.
+      message = chrome.i18n.getMessage(
+          Msgs.NAMESPACE_ + messageId.replace('_brl', ''), opt_subs);
+    }
+
     if (message == undefined || message == '') {
       throw new Error('Invalid ChromeVox message id: ' + messageId);
     }
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_iw.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_iw.xtb
index 88c08b0..afe1dc17 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_iw.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_iw.xtb
@@ -155,7 +155,7 @@
 <translation id="2126597928985245619">אין טקסט זמין בשביל הפריט הזה</translation>
 <translation id="2127747486437921899">נטוי</translation>
 <translation id="2163782704988363449">תיקוני טעויות</translation>
-<translation id="2169714232367507776">לחץ על הפריט הנוכחי</translation>
+<translation id="2169714232367507776">יש ללחוץ על הפריט הנוכחי</translation>
 <translation id="2179452035581866348">‏ChromeVox משתמש בצליל כדי לספק לך מידע נוסף וחשוב. כדאי ללמוד את המשמעות של כל צליל כדי להשתמש בצלילים האלו לניווט מהיר יותר. אחרי שמתרגלים לצלילים, אפשר להשבית את התיאורים המילוליים ולהפעיל אותם רק כדי לקבל מידע חשוב על הדף. הנה רשימה של כל הצלילים והמשמעות שלהם.</translation>
 <translation id="2188751878842439466">{COUNT,plural, =1{סגור סוגריים}two{# סימני סגור סוגריים}many{# סימני סגור סוגריים}other{# סימני סגור סוגריים}}</translation>
 <translation id="2197863150503783129">חום אוכף</translation>
@@ -204,7 +204,7 @@
 <translation id="2592212930811759050">לחיצה פעמיים מפעילה עריכה</translation>
 <translation id="2598495320872286378">שגיאת דקדוק</translation>
 <translation id="2603828437139726540">העברת הסמן לתו הבא</translation>
-<translation id="2624431853467395961">פתח מצב למידה</translation>
+<translation id="2624431853467395961">פתיחת מצב למידה</translation>
 <translation id="2626530649491650971">clickable</translation>
 <translation id="2637227747952042642">Math</translation>
 <translation id="2638785836053527382">ההורדה של <ph name="FILE_NAME" /> נמשכת</translation>
@@ -241,7 +241,7 @@
 <translation id="2843837985843789981">הקבוצה הקודמת</translation>
 <translation id="2864481629947106776">הקישור הקודם</translation>
 <translation id="2867808975387772810">ביבליוגרפיה</translation>
-<translation id="2873259058405069099">עבור לתחילת הטבלה</translation>
+<translation id="2873259058405069099">מעבר לתחילת הטבלה</translation>
 <translation id="287383510823843610">כתום כהה</translation>
 <translation id="2879867157561757640">החלקה מטה עם שלוש אצבעות</translation>
 <translation id="288178314850623291">‏אפשר להשתמש בפקודות מעבר כדי לדלג אל סוגים ספציפיים של רכיבים. כדי לעבור קדימה בין כותרות, מקישים על מקש החיפוש ועל מקש H. כדי לעבור אחורה, מקישים יחד על מקש החיפוש, Shift ו-H.</translation>
@@ -379,7 +379,7 @@
 <translation id="3810838688059735925">וידאו</translation>
 <translation id="3813387282697781382">אלמוג בהיר</translation>
 <translation id="3816633764618089385">המדיה הבאה</translation>
-<translation id="385383972552776628">פתח את דף האפשרויות</translation>
+<translation id="385383972552776628">פתיחת דף האפשרויות</translation>
 <translation id="3856075812838139784">קריאה בלבד</translation>
 <translation id="3857141338659865495">טורקיז בינוני</translation>
 <translation id="3870295413168340326">אין כותרת קודמת מרמה 3</translation>
@@ -641,7 +641,7 @@
 <translation id="5906974869830879618">יש להזין קוד אימות</translation>
 <translation id="5921587111466148855">פרק</translation>
 <translation id="5937336320314038555">{COUNT,plural, =1{סימן שווה}two{# סימני שווה}many{# סימני שווה}other{# סימני שווה}}</translation>
-<translation id="5948123859135882163">עבור בין פירוש מבני וסמנטי של ביטויים מתמטיים</translation>
+<translation id="5948123859135882163">מעבר בין פירוש מבני וסמנטי של ביטויים מתמטיים</translation>
 <translation id="5955304353782037793">app</translation>
 <translation id="5956928062748260866">דו-שיח</translation>
 <translation id="5963413905009737549">קטע</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_pa.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_pa.xtb
index 63e4393..ed807afa6 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_pa.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_pa.xtb
@@ -68,7 +68,7 @@
 <translation id="1383876407941801731">ਖੋਜੋ</translation>
 <translation id="1396114365388024581">tablst</translation>
 <translation id="1405567553485452995">ਹਲਕਾ ਹਰਾ</translation>
-<translation id="141454040365657399">ਪੰਨਾ ਸਿਰਲੇਖ</translation>
+<translation id="141454040365657399">ਪੰਨੇ ਦਾ ਸਿਰਲੇਖ</translation>
 <translation id="1417889266572670458">ਗੂੜ੍ਹਾ ਨੀਲਾ</translation>
 <translation id="1431911867058218151">ਆਲੂਬੁਖਾਰੇ ਰੰਗਾ</translation>
 <translation id="1439316808600711881">rgn</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp b/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp
index 76e48e31..f8c4a528 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp
+++ b/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp
@@ -3032,11 +3032,14 @@
   <message desc="Describes gesture that simulates pressing the enter key. No associated UI with this string which is spoken using text-to-speech." name="IDS_CHROMEVOX_ENTER_GESTURE_DESCRIPTION" is_accessibility_with_no_ui="true">
     Enter
   </message>
-  <message desc="Describes gesture that movees to the previous important section on the screen (e.g. the Launcher, Status Tray, etc). No associated UI with this string which is spoken using text-to-speech." name="IDS_CHROMEVOX_PREVIOUS_PANE_GESTURE_DESCRIPTION" is_accessibility_with_no_ui="true">
+  <message desc="Describes gesture that moves to the previous important section on the screen (e.g. the Launcher, Status Tray, etc). No associated UI with this string which is spoken using text-to-speech." name="IDS_CHROMEVOX_PREVIOUS_PANE_GESTURE_DESCRIPTION" is_accessibility_with_no_ui="true">
     Move to previous section. Examples include the Status Tray and Launcher.
   </message>
-  <message desc="Describes gesture that movees to the next important section on the screen (e.g. the Launcher, Status Tray, etc). No associated UI with this string which is spoken using text-to-speech." name="IDS_CHROMEVOX_NEXT_PANE_GESTURE_DESCRIPTION" is_accessibility_with_no_ui="true">
+  <message desc="Describes gesture that moves to the next important section on the screen (e.g. the Launcher, Status Tray, etc). No associated UI with this string which is spoken using text-to-speech." name="IDS_CHROMEVOX_NEXT_PANE_GESTURE_DESCRIPTION" is_accessibility_with_no_ui="true">
     Move to next section. Examples include the Status Tray and Launcher.
   </message>
+  <message desc="Describes an element with the ARIA role mark. We use 'marked content' since it's more descriptive than 'mark'." name="IDS_CHROMEVOX_ROLE_MARK" is_accessibility_with_no_ui="true">
+    Marked content
+  </message>
 
 </grit-part>
diff --git a/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn b/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn
index 2ac6228..f7aa78a3 100644
--- a/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn
+++ b/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn
@@ -4,54 +4,55 @@
 
 import("//chrome/common/features.gni")
 import("//third_party/closure_compiler/compile_js.gni")
-import("//tools/grit/grit_rule.gni")
+import("//tools/grit/preprocess_grit.gni")
 import("//tools/polymer/html_to_js.gni")
-import("//tools/polymer/polymer.gni")
-import("//ui/webui/resources/tools/js_modulizer.gni")
+import("//ui/webui/resources/tools/generate_grd.gni")
 import("../../optimize_webui.gni")
 
+preprocess_folder = "preprocessed"
+preprocess_gen_manifest = "preprocessed_gen_manifest.json"
+
 if (optimize_webui) {
-  bluetooth_dialog_pak_file = "bluetooth_pairing_dialog_resources.pak"
-  unpak_folder = "bluetooth_pairing_dialog_resources.unpak"
+  build_manifest = "build_manifest.json"
 
   optimize_webui("build") {
     host = "bluetooth-pairing"
     js_out_files = [ "bluetooth_pairing_dialog.rollup.js" ]
     js_module_in_files = [ "bluetooth_pairing_dialog.js" ]
-    input = rebase_path("$target_gen_dir/$unpak_folder", root_build_dir)
+    input = rebase_path("$target_gen_dir/$preprocess_folder", root_build_dir)
+    out_manifest = "$target_gen_dir/$build_manifest"
 
     deps = [
-      ":unpak",
+      ":preprocess_generated",
       "../../../../../ui/webui/resources:preprocess",
     ]
 
     excludes = [ "chrome://resources/js/cr.m.js" ]
   }
+}
 
-  unpak("unpak") {
-    pak_file = bluetooth_dialog_pak_file
-    out_folder = unpak_folder
-
-    deps = [ ":flattened_resources" ]
+generate_grd("build_grd") {
+  input_files = [ "bluetooth_pairing_dialog_container.html" ]
+  input_files_base_dir = rebase_path(".", "//")
+  if (optimize_webui) {
+    deps = [ ":build" ]
+    resource_path_rewrites =
+        [ "bluetooth_pairing_dialog.rollup.js|bluetooth_pairing_dialog.js" ]
+    manifest_files = [ "$target_gen_dir/$build_manifest" ]
+  } else {
+    deps = [ ":preprocess_generated" ]
+    manifest_files = [ "$target_gen_dir/$preprocess_gen_manifest" ]
   }
+  grd_prefix = "bluetooth_pairing_dialog"
+  out_grd = "$target_gen_dir/${grd_prefix}_resources.grd"
+}
 
-  grit("flattened_resources") {
-    source = "bluetooth_pairing_dialog_resources.grd"
-
-    deps = [ ":web_components" ]
-    defines = chrome_grit_defines
-    grit_flags = [
-      "-E",
-      "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
-    ]
-    outputs = [
-      "grit/bluetooth_pairing_dialog_resources.h",
-      "grit/bluetooth_pairing_dialog_resources_map.cc",
-      "grit/bluetooth_pairing_dialog_resources_map.h",
-      bluetooth_dialog_pak_file,
-    ]
-    output_dir = "$root_gen_dir/chrome/browser/resources/chromeos/bluetooth_pairing_dialog"
-  }
+preprocess_grit("preprocess_generated") {
+  deps = [ ":web_components" ]
+  in_folder = target_gen_dir
+  out_folder = "$target_gen_dir/$preprocess_folder"
+  out_manifest = "$target_gen_dir/$preprocess_gen_manifest"
+  in_files = [ "bluetooth_pairing_dialog.js" ]
 }
 
 js_type_check("closure_compile") {
diff --git a/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources.grd b/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources.grd
deleted file mode 100644
index c345ebb..0000000
--- a/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources.grd
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
-  <outputs>
-    <output filename="grit/bluetooth_pairing_dialog_resources.h" type="rc_header">
-      <emit emit_type='prepend'></emit>
-    </output>
-    <output filename="grit/bluetooth_pairing_dialog_resources_map.cc"
-            type="resource_file_map_source" />
-    <output filename="grit/bluetooth_pairing_dialog_resources_map.h"
-            type="resource_map_header" />
-    <output filename="bluetooth_pairing_dialog_resources.pak" type="data_package" />
-  </outputs>
-  <release seq="1">
-    <includes>
-      <include name="IDR_BLUETOOTH_PAIRING_DIALOG_JS"
-               file="${root_gen_dir}/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog.js"
-               use_base_dir="false"
-               compress="false"
-               type="chrome_html" />
-    </includes>
-  <structures>
-    <structure name="IDR_BLUETOOTH_PAIRING_DIALOG_CONTAINER_HTML"
-               file="bluetooth_pairing_dialog_container.html"
-               compress="false"
-               type="chrome_html" />
-  </structures>
-  </release>
-</grit>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources_vulcanized.grd b/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources_vulcanized.grd
deleted file mode 100644
index 8816618..0000000
--- a/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources_vulcanized.grd
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
-  <outputs>
-    <output filename="grit/bluetooth_pairing_dialog_resources.h" type="rc_header">
-      <emit emit_type='prepend'></emit>
-    </output>
-    <output filename="grit/bluetooth_pairing_dialog_resources_map.cc"
-            type="resource_map_source" />
-    <output filename="grit/bluetooth_pairing_dialog_resources_map.h"
-            type="resource_map_header" />
-    <output filename="bluetooth_pairing_dialog_resources.pak" type="data_package" />
-  </outputs>
-  <release seq="1">
-    <includes>
-      <include name="IDR_BLUETOOTH_PAIRING_DIALOG_CONTAINER_HTML"
-               file="bluetooth_pairing_dialog_container.html"
-               type="chrome_html" />
-      <include name="IDR_BLUETOOTH_PAIRING_DIALOG_ROLLUP_JS"
-               file="${root_gen_dir}\chrome\browser\resources\chromeos\bluetooth_pairing_dialog\bluetooth_pairing_dialog.rollup.js"
-               use_base_dir="false"
-               preprocess="true"
-               type="chrome_html" />
-    </includes>
-  </release>
-</grit>
diff --git a/chrome/browser/resources/new_tab_page/BUILD.gn b/chrome/browser/resources/new_tab_page/BUILD.gn
index f0f69845..98976a9 100644
--- a/chrome/browser/resources/new_tab_page/BUILD.gn
+++ b/chrome/browser/resources/new_tab_page/BUILD.gn
@@ -338,6 +338,7 @@
       "new_tab_page.mojom-lite.js",
       "omnibox.mojom-lite.js",
       "promo_browser_command.mojom-lite.js",
+      "modules/recipe_tasks/recipe_tasks.mojom-lite.js",
       "modules/shopping_tasks/shopping_tasks.mojom-lite.js",
       "foo.mojom-lite.js",
     ]
diff --git a/chrome/browser/resources/new_tab_page/modules/BUILD.gn b/chrome/browser/resources/new_tab_page/modules/BUILD.gn
index 6aa84cb..f514641 100644
--- a/chrome/browser/resources/new_tab_page/modules/BUILD.gn
+++ b/chrome/browser/resources/new_tab_page/modules/BUILD.gn
@@ -15,6 +15,7 @@
   deps = [
     ":module_registry",
     "kaleidoscope:module",
+    "recipe_tasks:module",
     "shopping_tasks:module",
   ]
   if (!is_official_build) {
@@ -44,6 +45,7 @@
   public_deps = [
     ":web_components_local",
     "dummy:web_components",
+    "recipe_tasks:web_components",
     "shopping_tasks:web_components",
   ]
 }
@@ -63,6 +65,7 @@
       "module_descriptor.js",
       "modules.js",
       "module_registry.js",
+      "recipe_tasks/recipe_tasks_handler_proxy.js",
       "shopping_tasks/shopping_tasks_handler_proxy.js",
     ]
     if (!is_official_build) {
@@ -78,6 +81,7 @@
     in_files = [
       "module_wrapper.js",
       "dummy/module.js",
+      "recipe_tasks/module.js",
       "shopping_tasks/module.js",
     ]
   }
diff --git a/chrome/browser/resources/new_tab_page/modules/modules.js b/chrome/browser/resources/new_tab_page/modules/modules.js
index 718f724a..22051578 100644
--- a/chrome/browser/resources/new_tab_page/modules/modules.js
+++ b/chrome/browser/resources/new_tab_page/modules/modules.js
@@ -14,11 +14,16 @@
 import {kaleidoscopeDescriptor} from './kaleidoscope/module.js';
 import {ModuleDescriptor} from './module_descriptor.js';
 import {ModuleRegistry} from './module_registry.js';
+import {recipeTasksDescriptor} from './recipe_tasks/module.js';
 import {shoppingTasksDescriptor} from './shopping_tasks/module.js';
 
 /** @type {!Array<!ModuleDescriptor>} */
 const descriptors = [];
 
+if (loadTimeData.getBoolean('recipeTasksModuleEnabled')) {
+  descriptors.push(recipeTasksDescriptor);
+}
+
 if (loadTimeData.getBoolean('shoppingTasksModuleEnabled')) {
   descriptors.push(shoppingTasksDescriptor);
 }
diff --git a/chrome/browser/resources/new_tab_page/modules/modules_resources.grdp b/chrome/browser/resources/new_tab_page/modules/modules_resources.grdp
index 9df82cc..b471e0f 100644
--- a/chrome/browser/resources/new_tab_page/modules/modules_resources.grdp
+++ b/chrome/browser/resources/new_tab_page/modules/modules_resources.grdp
@@ -19,6 +19,11 @@
   <include name="IDR_NEW_TAB_PAGE_MODULE_WRAPPER_JS"
       file="${root_gen_dir}/chrome/browser/resources/new_tab_page/modules/module_wrapper.js"
       use_base_dir="false" type="BINDATA" compress="false" />
+  <include name="IDR_NEW_TAB_PAGE_MODULES_RECIPE_TASKS_MODULE_JS"
+      file="${root_gen_dir}/chrome/browser/resources/new_tab_page/modules/recipe_tasks/module.js"
+      use_base_dir="false" type="BINDATA" compress="false" />
+  <include name="IDR_NEW_TAB_PAGE_MODULES_RECIPE_TASKS_RECIPE_TASKS_HANDLER_PROXY_JS"
+      file="modules/recipe_tasks/recipe_tasks_handler_proxy.js" type="BINDATA" compress="false" />
   <include name="IDR_NEW_TAB_PAGE_MODULES_SHOPPING_TASKS_MODULE_JS"
       file="${root_gen_dir}/chrome/browser/resources/new_tab_page/modules/shopping_tasks/module.js"
       use_base_dir="false" type="BINDATA" compress="false" />
diff --git a/chrome/browser/resources/new_tab_page/modules/recipe_tasks/BUILD.gn b/chrome/browser/resources/new_tab_page/modules/recipe_tasks/BUILD.gn
new file mode 100644
index 0000000..7976e4d
--- /dev/null
+++ b/chrome/browser/resources/new_tab_page/modules/recipe_tasks/BUILD.gn
@@ -0,0 +1,28 @@
+# 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.
+
+import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/html_to_js.gni")
+
+js_library("module") {
+  deps = [
+    ":recipe_tasks_handler_proxy",
+    "..:module_descriptor",
+    "../..:img",
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/cr_elements/cr_grid",
+    "//ui/webui/resources/js:load_time_data.m",
+  ]
+}
+
+js_library("recipe_tasks_handler_proxy") {
+  deps = [
+    "//chrome/browser/search/recipe_tasks:mojo_bindings_js_library_for_compile",
+    "//ui/webui/resources/js:cr.m",
+  ]
+}
+
+html_to_js("web_components") {
+  js_files = [ "module.js" ]
+}
diff --git a/chrome/browser/resources/new_tab_page/modules/recipe_tasks/module.html b/chrome/browser/resources/new_tab_page/modules/recipe_tasks/module.html
new file mode 100644
index 0000000..a922a6b
--- /dev/null
+++ b/chrome/browser/resources/new_tab_page/modules/recipe_tasks/module.html
@@ -0,0 +1,168 @@
+<style>
+  :host {
+    box-sizing: border-box;
+    display: block;
+    height: 100%;
+    padding-inline-end: 15px;
+    padding-inline-start: 15px;
+    width: 100%;
+  }
+
+  #recipes {
+    display: flex;
+    flex-direction: row;
+  }
+
+  .recipe {
+    border-radius: 4px;
+    display: flex;
+    flex-direction: column;
+    outline: none;
+    text-decoration: none;
+    width: 120px;
+  }
+
+  :host-context(.focus-outline-visible) .recipe:focus {
+    box-shadow: var(--ntp-focus-shadow);
+  }
+
+  .recipe + .recipe {
+    margin-inline-start: 16px;
+  }
+
+  .image {
+    background: var(--google-grey-50);
+    border-radius: 4px;
+    box-sizing: border-box;
+    height: 100px;
+    margin-bottom: 8px;
+    width: 120px;
+  }
+
+  img {
+    border-radius: 4px;
+    height: 100%;
+    object-fit: cover;
+    width: 100%;
+  }
+
+  .price {
+    color: var(--cr-primary-text-color);
+    font-size: 13px;
+    font-weight: bold;
+    height: 14px;
+    line-height: 15px;
+    margin-bottom: 8px;
+  }
+
+  .name {
+    color: var(--cr-primary-text-color);
+    font-size: 12px;
+    line-height: 20px;
+    margin-bottom: 4px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+
+  .info {
+    color: var(--cr-secondary-text-color);
+    font-size: 11px;
+    height: 13px;
+    text-overflow: ellipsis;
+  }
+
+  #relatedSearches {
+    display: flex;
+    flex-direction: row;
+    margin-top: 16px;
+  }
+
+  .pill {
+    align-items: center;
+    border: solid var(--ntp-border-color) 1px;
+    border-radius: 16px;
+    box-sizing: border-box;
+    display: flex;
+    flex-direction: row;
+    flex-shrink: 0;
+    height: 32px;
+    outline: none;
+    text-decoration: none;
+  }
+
+  :host-context(.focus-outline-visible) .pill:focus {
+    box-shadow: var(--ntp-focus-shadow);
+  }
+
+  .pill + .pill {
+    margin-inline-start: 8px;
+  }
+
+  .loupe {
+    -webkit-mask-image: url(search.svg);
+    -webkit-mask-repeat: no-repeat;
+    -webkit-mask-size: 100%;
+    background-color: var(--cr-secondary-text-color);
+    height: 16px;
+    margin-inline-start: 12px;
+    width: 16px;
+  }
+
+  .search-text {
+    color: var(--cr-primary-text-color);
+    font-size: 13px;
+    margin-inline-end: 12px;
+    margin-inline-start: 8px;
+  }
+
+  cr-dialog::part(dialog) {
+    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>
+<div id="recipes">
+  <template is="dom-repeat" id="recipesRepeat"
+      items="[[recipeTask.recipes]]" on-dom-change="onDomChange_">
+    <a class="recipe" href="[[item.targetUrl.url]]" on-click="onRecipeClick_"
+        on-auxclick="onRecipeClick_">
+      <div class="image">
+        <img is="ntp-img" auto-src="[[item.imageUrl.url]]"></img>
+      </div>
+      <div class="name"  title="[[item.name]]">[[item.name]]</div>
+      <div class="info">[[item.info]]</div>
+    </a>
+  </template>
+</div>
+<div id="relatedSearches">
+  <template is="dom-repeat" id="relatedSearchesRepeat"
+      items="[[recipeTask.relatedSearches]]" on-dom-change="onDomChange_">
+    <a class="pill" href="[[item.targetUrl.url]]" on-click="onPillClick_"
+        on-auxclick="onPillClick_">
+      <div class="loupe"></div>
+      <div class="search-text">[[item.text]]</div>
+    </a>
+  </template>
+</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>
diff --git a/chrome/browser/resources/new_tab_page/modules/recipe_tasks/module.js b/chrome/browser/resources/new_tab_page/modules/recipe_tasks/module.js
new file mode 100644
index 0000000..727dbdd
--- /dev/null
+++ b/chrome/browser/resources/new_tab_page/modules/recipe_tasks/module.js
@@ -0,0 +1,121 @@
+// 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.
+
+import '../../img.js';
+
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {ModuleDescriptor} from '../module_descriptor.js';
+import {RecipeTasksHandlerProxy} from './recipe_tasks_handler_proxy.js';
+
+/**
+ * @fileoverview Implements the UI of the recipes module. This module shows
+ * recently view and related recipes
+ */
+
+class RecipeTasksModuleElement extends PolymerElement {
+  static get is() {
+    return 'ntp-recipe-tasks-module';
+  }
+
+  static get template() {
+    return html`{__html_template__}`;
+  }
+
+  static get properties() {
+    return {
+      /** @type {recipeTasks.mojom.RecipeTask} */
+      recipeTask: Object,
+
+      /** @type {boolean} */
+      showInfoDialog: Boolean,
+    };
+  }
+
+  /** @override */
+  ready() {
+    super.ready();
+    /** @type {IntersectionObserver} */
+    this.intersectionObserver_ = null;
+  }
+
+  /**
+   * @param {!Event} e
+   * @private
+   */
+  onRecipeClick_(e) {
+    const index = this.$.recipesRepeat.indexForElement(e.target);
+    RecipeTasksHandlerProxy.getInstance().handler.onRecipeClicked(index);
+    this.dispatchEvent(new Event('usage', {bubbles: true, composed: true}));
+  }
+
+  /**
+   * @param {!Event} e
+   * @private
+   */
+  onPillClick_(e) {
+    const index = this.$.relatedSearchesRepeat.indexForElement(e.target);
+    RecipeTasksHandlerProxy.getInstance().handler.onRelatedSearchClicked(index);
+    this.dispatchEvent(new Event('usage', {bubbles: true, composed: true}));
+  }
+
+  /** @private */
+  onCloseClick_() {
+    this.showInfoDialog = false;
+  }
+
+  /** @private */
+  onDomChange_() {
+    if (!this.intersectionObserver_) {
+      this.intersectionObserver_ = new IntersectionObserver(entries => {
+        entries.forEach(({intersectionRatio, target}) => {
+          target.style.visibility =
+              intersectionRatio < 1 ? 'hidden' : 'visible';
+        });
+        this.dispatchEvent(new Event('visibility-update'));
+      }, {root: this, threshold: 1});
+    } else {
+      this.intersectionObserver_.disconnect();
+    }
+    this.shadowRoot.querySelectorAll('.recipe, .pill')
+        .forEach(el => this.intersectionObserver_.observe(el));
+  }
+}
+
+customElements.define(RecipeTasksModuleElement.is, RecipeTasksModuleElement);
+
+/** @return {!Promise<?{element: !HTMLElement, title: string}>} */
+async function createModule() {
+  const {recipeTask} = await RecipeTasksHandlerProxy.getInstance()
+                           .handler.getPrimaryRecipeTask();
+  if (!recipeTask) {
+    return null;
+  }
+  const element = new RecipeTasksModuleElement();
+  element.recipeTask = recipeTask;
+  return {
+    element: element,
+    title: recipeTask.title,
+    actions: {
+      info: () => {
+        element.showInfoDialog = true;
+      },
+      dismiss: () => {
+        RecipeTasksHandlerProxy.getInstance().handler.dismissRecipeTask(
+            recipeTask.name);
+        return loadTimeData.getStringF(
+            'dismissModuleToastMessage', recipeTask.name);
+      },
+      restore: () => {
+        RecipeTasksHandlerProxy.getInstance().handler.restoreRecipeTask(
+            recipeTask.name);
+      },
+    },
+  };
+}
+
+/** @type {!ModuleDescriptor} */
+export const recipeTasksDescriptor = new ModuleDescriptor(
+    /*id=*/ 'recipe_tasks',
+    /*heightPx=*/ 206, createModule);
diff --git a/chrome/browser/resources/new_tab_page/modules/recipe_tasks/recipe_tasks_handler_proxy.js b/chrome/browser/resources/new_tab_page/modules/recipe_tasks/recipe_tasks_handler_proxy.js
new file mode 100644
index 0000000..4ec43cc1
--- /dev/null
+++ b/chrome/browser/resources/new_tab_page/modules/recipe_tasks/recipe_tasks_handler_proxy.js
@@ -0,0 +1,21 @@
+// 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.
+
+import './recipe_tasks.mojom-lite.js';
+
+import {addSingletonGetter} from 'chrome://resources/js/cr.m.js';
+
+/**
+ * @fileoverview This file provides a class that exposes the Mojo handler
+ * interface used for retrieving the recipe task for the recipe task module.
+ */
+
+export class RecipeTasksHandlerProxy {
+  constructor() {
+    /** @type {!recipeTasks.mojom.RecipeTasksHandlerRemote} */
+    this.handler = recipeTasks.mojom.RecipeTasksHandler.getRemote();
+  }
+}
+
+addSingletonGetter(RecipeTasksHandlerProxy);
diff --git a/chrome/browser/resources/new_tab_page/modules/shopping_tasks/module.html b/chrome/browser/resources/new_tab_page/modules/shopping_tasks/module.html
index 39538f0f..b6d06ea 100644
--- a/chrome/browser/resources/new_tab_page/modules/shopping_tasks/module.html
+++ b/chrome/browser/resources/new_tab_page/modules/shopping_tasks/module.html
@@ -157,14 +157,14 @@
 </div>
 <template is="dom-if" if="[[showInfoDialog]]" restamp>
   <cr-dialog show-on-attach>
-    <div slot="title">$i18n{modulesShoppingTasksInfoTitle}</div>
+    <div slot="title">$i18n{modulesTasksInfoTitle}</div>
     <div slot="body">
-      <div>$i18nRaw{modulesShoppingTasksInfo1}</div>
-      <div>$i18nRaw{modulesShoppingTasksInfo2}</div>
+      <div>$i18nRaw{modulesTasksInfo1}</div>
+      <div>$i18nRaw{modulesTasksInfo2}</div>
     </div>
     <div slot="button-container">
       <cr-button class="action-button" on-click="onCloseClick_">
-        $i18n{modulesShoppingTasksInfoClose}
+        $i18n{modulesTasksInfoClose}
       </cr-button>
     </div>
   </cr-dialog>
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 d5a9d27..7d4d673 100644
--- a/chrome/browser/resources/new_tab_page/new_tab_page.js
+++ b/chrome/browser/resources/new_tab_page/new_tab_page.js
@@ -23,6 +23,8 @@
 export {kaleidoscopeDescriptor} from './modules/kaleidoscope/module.js';
 export {ModuleDescriptor} from './modules/module_descriptor.js';
 export {ModuleRegistry} from './modules/module_registry.js';
+export {recipeTasksDescriptor} from './modules/recipe_tasks/module.js';
+export {RecipeTasksHandlerProxy} from './modules/recipe_tasks/recipe_tasks_handler_proxy.js';
 export {shoppingTasksDescriptor} from './modules/shopping_tasks/module.js';
 export {ShoppingTasksHandlerProxy} from './modules/shopping_tasks/shopping_tasks_handler_proxy.js';
 export {PromoBrowserCommandProxy} from './promo_browser_command_proxy.js';
diff --git a/chrome/browser/resources/new_tab_page/new_tab_page_resources_common.grdp b/chrome/browser/resources/new_tab_page/new_tab_page_resources_common.grdp
index cd163f0..bab35c5 100644
--- a/chrome/browser/resources/new_tab_page/new_tab_page_resources_common.grdp
+++ b/chrome/browser/resources/new_tab_page/new_tab_page_resources_common.grdp
@@ -70,6 +70,9 @@
       file="one_google_bar_api.js" type="BINDATA" compress="false" />
   <include name="IDR_NEW_TAB_PAGE_PROMO_BROWSER_COMMAND_PROXY_JS"
       file="promo_browser_command_proxy.js" type="BINDATA" compress="false" />
+  <include name="IDR_NEW_TAB_PAGE_MODULES_RECIPE_TASKS_RECIPE_TASKS_MOJO_LITE_JS"
+      file="${root_gen_dir}/chrome/browser/search/recipe_tasks/recipe_tasks.mojom-lite.js"
+      use_base_dir="false" type="BINDATA" />
   <include name="IDR_NEW_TAB_PAGE_MODULES_SHOPPING_TASKS_SHOPPING_TASKS_MOJO_LITE_JS"
       file="${root_gen_dir}/chrome/browser/search/shopping_tasks/shopping_tasks.mojom-lite.js"
       use_base_dir="false" type="BINDATA" />
diff --git a/chrome/browser/resources/pdf/elements/viewer-thumbnail-bar.js b/chrome/browser/resources/pdf/elements/viewer-thumbnail-bar.js
index 850169d..d6a24ae 100644
--- a/chrome/browser/resources/pdf/elements/viewer-thumbnail-bar.js
+++ b/chrome/browser/resources/pdf/elements/viewer-thumbnail-bar.js
@@ -84,7 +84,7 @@
    */
   activePageChanged_() {
     if (this.shadowRoot.activeElement) {
-      this.getThumbnailForPage_(this.activePage).focusAndScroll();
+      this.getThumbnailForPage(this.activePage).focusAndScroll();
     }
   }
 
@@ -97,7 +97,16 @@
       return;
     }
 
-    this.getThumbnailForPage_(pageNumber).getClickTarget().click();
+    this.getThumbnailForPage(pageNumber).getClickTarget().click();
+  }
+
+  /**
+   * @param {number} pageNumber
+   * @return {?ViewerThumbnailElement}
+   */
+  getThumbnailForPage(pageNumber) {
+    return /** @type {ViewerThumbnailElement} */ (this.shadowRoot.querySelector(
+        `viewer-thumbnail:nth-child(${pageNumber})`));
   }
 
   /**
@@ -118,16 +127,6 @@
   }
 
   /**
-   * @param {number} pageNumber
-   * @return {ViewerThumbnailElement}
-   * @private
-   */
-  getThumbnailForPage_(pageNumber) {
-    return /** @type {ViewerThumbnailElement} */ (this.shadowRoot.querySelector(
-        `viewer-thumbnail:nth-child(${pageNumber})`));
-  }
-
-  /**
    * @param {number} page
    * @return {boolean} Whether the page is the current page.
    * @private
diff --git a/chrome/browser/resources/print_preview/print_preview.html b/chrome/browser/resources/print_preview/print_preview.html
index b5c0168..68ecb3a 100644
--- a/chrome/browser/resources/print_preview/print_preview.html
+++ b/chrome/browser/resources/print_preview/print_preview.html
@@ -1,7 +1,7 @@
 <!doctype html>
 <html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading">
 <head>
-  <title>$i18n{title}</title>
+  <title>$i18n{pageDescription}</title>
   <meta charset="utf-8">
   <base href="chrome://print">
   <style>
diff --git a/chrome/browser/resources/settings/chromeos/device_page/device_page.html b/chrome/browser/resources/settings/chromeos/device_page/device_page.html
index 2867f9c..e4e9c2a 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/device_page.html
+++ b/chrome/browser/resources/settings/chromeos/device_page/device_page.html
@@ -64,7 +64,8 @@
         <settings-subpage
             associated-control="[[$$('#keyboardRow')]]"
             page-title="$i18n{keyboardTitle}">
-          <settings-keyboard prefs="{{prefs}}"></settings-keyboard>
+          <settings-keyboard prefs="{{prefs}}" focus-config="[[focusConfig_]]">
+          </settings-keyboard>
         </settings-subpage>
       </template>
       <template is="dom-if" route-path="/stylus" no-search="[[!hasStylus_]]">
diff --git a/chrome/browser/resources/settings/chromeos/device_page/keyboard.html b/chrome/browser/resources/settings/chromeos/device_page/keyboard.html
index 7ad4fc5..ba0f678e 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/keyboard.html
+++ b/chrome/browser/resources/settings/chromeos/device_page/keyboard.html
@@ -142,17 +142,19 @@
         label="$i18n{showKeyboardShortcutViewer}" external
         deep-link-focus-id$="[[Setting.kKeyboardShortcuts]]"></cr-link-row>
     <template is="dom-if" if="[[!languageSettingsV2Enabled_]]">
-      <cr-link-row class="hr" on-click="onShowLanguageInputTap_"
+      <cr-link-row id="showLanguagesDetails"
+          class="hr" on-click="onShowLanguageInputTap_"
           label="$i18n{keyboardShowLanguageAndInput}"
           role-description="$i18n{subpageArrowRoleDescription}">
       </cr-link-row>
     </template>
     <template is="dom-if" if="[[languageSettingsV2Enabled_]]">
-      <cr-link-row class="hr" on-click="onShowInputSettingsTap_"
+      <cr-link-row id="showLanguagesInput"
+          class="hr" on-click="onShowInputSettingsTap_"
           label="$i18n{keyboardShowInputSettings}"
           role-description="$i18n{subpageArrowRoleDescription}">
       </cr-link-row>
-    </template>     
+    </template>
   </template>
   <script src="keyboard.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/chromeos/device_page/keyboard.js b/chrome/browser/resources/settings/chromeos/device_page/keyboard.js
index c7251f3f..23235df 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/keyboard.js
+++ b/chrome/browser/resources/settings/chromeos/device_page/keyboard.js
@@ -35,6 +35,12 @@
         notify: true,
       },
 
+      /** @private {!Map<string, (string|Function)>} */
+      focusConfig: {
+        type: Object,
+        observer: 'onFocusConfigChange_',
+      },
+
       /** @private Whether to show Caps Lock options. */
       showCapsLock_: Boolean,
 
@@ -174,6 +180,24 @@
       ];
     },
 
+    /** @private */
+    onFocusConfigChange_() {
+      let path, id;
+      if (this.languageSettingsV2Enabled_) {
+        path = settings.routes.OS_LANGUAGES_INPUT.path;
+        id = '#showLanguagesInput';
+      } else {
+        path = settings.routes.OS_LANGUAGES_DETAILS.path;
+        id = '#showLanguageDetails';
+      }
+
+      this.focusConfig.set(path, () => {
+        Polymer.RenderStatus.afterNextRender(this, () => {
+          cr.ui.focusWithoutInk(assert(this.$$(id)));
+        });
+      });
+    },
+
     /**
      * Handler for updating which keys to show.
      * @param {Object} keyboardParams
diff --git a/chrome/browser/resources/tab_search_merge/.gitignore b/chrome/browser/resources/tab_search_merge/.gitignore
new file mode 100644
index 0000000..43ed81d8
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/.gitignore
@@ -0,0 +1,78 @@
+*.bak
+*.mk
+*.ncb
+*.opensdf
+*.orig
+*.pdb
+*.props
+*.pyc
+*.pyproj
+*.rules
+*.sdf
+*.sln
+*.sublime-project
+*.sublime-workspace
+*.suo
+*.targets
+*.user
+*.vc.opendb
+*.vcproj
+*.vcxproj
+*.vcxproj.filters
+*.vpj
+*.vpw
+*.vpwhistu
+*.vtg
+*.xcodeproj
+*.xcworkspace
+*.VC.db
+*_proto.xml
+*_proto_cpp.xml
+*~
+!Android.mk
+.*.sw?
+.DS_Store
+.android
+.ccls-cache
+.cipd
+.classpath
+.code-coverage
+.cproject
+.emulator_sdk
+.gdb_history
+.gdbinit
+.landmines
+.metadata
+.project
+.pydevproject
+.checkstyle
+*.class
+compile_commands.json
+cscope.*
+GPATH
+GRTAGS
+GSYMS
+GTAGS
+Session.vim
+tags
+Thumbs.db
+v8.log
+vs-chromium-project.txt
+/.cache/
+/.clangd/
+/.clangd-index/
+# Settings directories for eclipse
+/.externalToolBuilders/
+/.settings/
+/.vs/
+# Visual Studio Code
+.vscode/
+/_out
+/android_emulator_sdk
+/ash/ash_unittests_run.xml
+/base/base_unittests_run.xml
+/.cache/
+# Ignore IntelliJ files.
+.idea/
+# Ignore cache folder created by clangd
+.cache
diff --git a/chrome/browser/resources/tab_search_merge/BUILD.gn b/chrome/browser/resources/tab_search_merge/BUILD.gn
new file mode 100644
index 0000000..b2aaabe
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/BUILD.gn
@@ -0,0 +1,82 @@
+# 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.
+
+import("//chrome/browser/resources/optimize_webui.gni")
+import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/grit/grit_rule.gni")
+import("//tools/polymer/html_to_js.gni")
+import("//ui/webui/webui_features.gni")
+
+js_type_check("closure_compile") {
+  is_polymer3 = true
+  deps = [
+    ":app",
+    ":fuzzy_search",
+    ":tab_data",
+    ":tab_search_api_proxy",
+    ":tab_search_item",
+    ":tab_search_search_field",
+  ]
+}
+
+js_library("app") {
+  deps = [
+    ":fuzzy_search",
+    ":tab_data",
+    ":tab_search_api_proxy",
+    ":tab_search_item",
+    ":tab_search_search_field",
+    "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer",
+    "//third_party/polymer/v3_0/components-chromium/iron-selector:iron-selector",
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/js:cr.m",
+    "//ui/webui/resources/js:load_time_data.m",
+    "//ui/webui/resources/js:util.m",
+  ]
+  externs_list = [ "$externs_path/metrics_private.js" ]
+}
+
+js_library("fuzzy_search") {
+  deps = [
+    ":tab_data",
+    "//ui/webui/resources/js:util.m",
+  ]
+}
+
+js_library("tab_data") {
+  deps = []
+}
+
+js_library("tab_search_api_proxy") {
+  deps = [
+    "//chrome/browser/ui/webui/tab_search:mojo_bindings_js_library_for_compile",
+    "//ui/webui/resources/js:cr.m",
+  ]
+  externs_list = [ "$externs_path/metrics_private.js" ]
+}
+
+js_library("tab_search_item") {
+  deps = [
+    ":tab_data",
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/cr_elements/cr_icon_button:cr_icon_button.m",
+    "//ui/webui/resources/js:icon.m",
+    "//ui/webui/resources/js:load_time_data.m",
+  ]
+}
+
+js_library("tab_search_search_field") {
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/cr_elements/cr_search_field:cr_search_field_behavior.m",
+  ]
+}
+
+html_to_js("web_components") {
+  js_files = [
+    "app.js",
+    "tab_search_item.js",
+    "tab_search_search_field.js",
+  ]
+}
diff --git a/chrome/browser/resources/tab_search_merge/OWNERS b/chrome/browser/resources/tab_search_merge/OWNERS
new file mode 100644
index 0000000..380c76c
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/OWNERS
@@ -0,0 +1,5 @@
+robliao@chromium.org
+tluk@chromium.org
+yuhengh@chromium.org
+
+# COMPONENT: UI>Browser>TabSearch
diff --git a/chrome/browser/resources/tab_search_merge/app.html b/chrome/browser/resources/tab_search_merge/app.html
new file mode 100644
index 0000000..cdaa154
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/app.html
@@ -0,0 +1,89 @@
+<style include="mwb-shared-style">
+  #tabs {
+    max-height: 280px;
+    overflow-x: hidden;
+    overflow-y: auto;
+    position: relative;
+  }
+
+  #tabsContainer {
+    height: calc(var(--mwb-item-height) * var(--item-count, 0));
+  }
+
+  #no-results {
+    color: var(--cr-primary-text-color);
+    font-size: var(--mwb-primary-text-font-size);
+    padding: 12px;
+    text-align: center;
+  }
+
+  #feedback-text {
+    color: var(--cr-primary-text-color);
+    font-size: var(--mwb-primary-text-font-size);
+    margin-inline-start: var(--mwb-list-item-horizontal-margin);
+    user-select: none;
+  }
+
+  #feedback-footer {
+    border: none;
+    border-top: 1px solid var(--google-grey-refresh-500);
+    height: 40px;
+    width: 100%;
+  }
+
+  #feedback-footer:focus {
+    background-color: var(--mwb-list-item-selected-background-color);
+    outline: none;
+  }
+
+  #feedback-icon {
+    --iron-icon-fill-color: var(--google-grey-refresh-700);
+    height: var(--mwb-icon-size);
+    width: var(--mwb-icon-size);
+  }
+
+  @media (prefers-color-scheme: dark) {
+    #feedback-icon {
+      --iron-icon-fill-color: var(--google-blue-refresh-300);
+    }
+  }
+</style>
+<iron-iconset-svg name="ts" size="24">
+  <svg>
+    <defs>
+      <g id="feedback">
+        <path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 12h-2v-2h2v2zm0-4h-2V6h2v4z">
+        </path>
+      </g>
+    </defs>
+  </svg>
+</iron-iconset-svg>
+<tab-search-search-field id="searchField" autofocus clear-label="$i18n{clearSearch}"
+    label="$i18n{searchTabs} [[getKeyboardShortcut_()]]" on-focus="onSearchFocus_"
+    on-keydown="onSearchKeyDown_" on-search-changed="onSearchChanged_">
+</tab-search-search-field>
+<div id="tabs">
+  <div id="tabsContainer">
+    <iron-selector id="selector" on-keydown="onItemKeyDown_"
+        selected="{{selectedIndex_}}" selected-class="selected" role="listbox">
+      <template id="tabsList" is="dom-repeat" items="[[filteredOpenTabs_]]"
+          initial-count="[[chunkingItemCount_]]">
+        <tab-search-item id="[[item.tab.tabId]]" aria-label="[[ariaLabel_(item)]]"
+            class="mwb-list-item" data="[[item]]"
+            on-click="onItemClick_" on-close="onItemClose_"
+            on-focus="onItemFocus_" tabindex="0" role="option">
+        </tab-search-item>
+      </template>
+    </iron-selector>
+  </div>
+</div>
+<div id="no-results" hidden="[[filteredOpenTabs_.length]]">
+  $i18n{noResultsFound}
+</div>
+<template is="dom-if" if="[[feedbackButtonEnabled_]]">
+  <button id="feedback-footer" class="mwb-list-item" on-click="onFeedbackClick_"
+      on-focus="onFeedbackFocus_">
+    <iron-icon id="feedback-icon" icon="ts:feedback"></iron-icon>
+    <div id="feedback-text">$i18n{submitFeedback}</div>
+  </button>
+</template>
diff --git a/chrome/browser/resources/tab_search_merge/app.js b/chrome/browser/resources/tab_search_merge/app.js
new file mode 100644
index 0000000..6f8d8f06
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/app.js
@@ -0,0 +1,490 @@
+// 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.
+
+import 'chrome://resources/cr_elements/icons.m.js';
+import 'chrome://resources/cr_elements/shared_vars_css.m.js';
+import 'chrome://resources/cr_elements/mwb_shared_style.js';
+import 'chrome://resources/cr_elements/mwb_shared_vars.js';
+import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
+import 'chrome://resources/polymer/v3_0/iron-iconset-svg/iron-iconset-svg.js';
+import 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js';
+import './tab_search_item.js';
+import './tab_search_search_field.js'
+import './strings.js';
+
+import {assert} from 'chrome://resources/js/assert.m.js';
+import {isMac} from 'chrome://resources/js/cr.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {listenOnce} from 'chrome://resources/js/util.m.js';
+import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js';
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {fuzzySearch} from './fuzzy_search.js';
+import {TabData} from './tab_data.js';
+import {TabSearchApiProxy, TabSearchApiProxyImpl} from './tab_search_api_proxy.js';
+
+const selectorNavigationKeys = ['ArrowUp', 'ArrowDown', 'Home', 'End'];
+
+export class TabSearchAppElement extends PolymerElement {
+  static get is() {
+    return 'tab-search-app';
+  }
+
+  static get template() {
+    return html`{__html_template__}`;
+  }
+
+  static get properties() {
+    return {
+      /** @private {string} */
+      searchText_: {
+        type: String,
+        value: '',
+      },
+
+      /** @private {?Array<!tabSearch.mojom.WindowTabs>} */
+      openTabs_: {
+        type: Array,
+        observer: 'openTabsChanged_',
+      },
+
+      /** @private {!Array<!TabData>} */
+      filteredOpenTabs_: {
+        type: Array,
+        value: [],
+      },
+
+      /**
+       * Controls the number of tab search list items initially rendered in
+       * dom-repeat's chunked rendering mode.
+       * @private {number}
+       */
+      chunkingItemCount_: {
+        type: Number,
+        value: 10,
+      },
+
+      /**
+       * Options for fuzzy search.
+       * @private {!Object}
+       */
+      fuzzySearchOptions_: {
+        type: Object,
+        value: {
+          includeScore: true,
+          includeMatches: true,
+          ignoreLocation: true,
+          threshold: 0.0,
+          distance: 200,
+          keys: [
+            {
+              name: 'tab.title',
+              weight: 2,
+            },
+            {
+              name: 'hostname',
+              weight: 1,
+            }
+          ],
+        },
+      },
+
+      /** @private {boolean} */
+      feedbackButtonEnabled_: {
+        type: Boolean,
+        value: () => loadTimeData.getBoolean('submitFeedbackEnabled'),
+      },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @private {!TabSearchApiProxy} */
+    this.apiProxy_ = TabSearchApiProxyImpl.getInstance();
+
+    /** @private {!Array<number>} */
+    this.listenerIds_ = [];
+  }
+
+  /** @override */
+  ready() {
+    super.ready();
+    this.addEventListener(
+        'keydown',
+        (e) => {this.onKeyDown_(/** @type {!KeyboardEvent} **/ (e))});
+
+    // Update option values for fuzzy search from feature params.
+    this.fuzzySearchOptions_ = Object.assign({}, this.fuzzySearchOptions_, {
+      ignoreLocation: loadTimeData.getBoolean('searchIgnoreLocation'),
+      threshold: loadTimeData.getValue('searchThreshold'),
+      distance: loadTimeData.getInteger('searchDistance'),
+      keys: [
+        {
+          name: 'tab.title',
+          weight: loadTimeData.getValue('searchTitleToHostnameWeightRatio'),
+        },
+        {
+          name: 'hostname',
+          weight: 1,
+        }
+      ],
+    });
+
+    // TODO(tluk): The listener should provide the data needed to update the
+    // WebUI without having to make another round trip request to the Browser.
+    const callbackRouter = this.apiProxy_.getCallbackRouter();
+    this.listenerIds_.push(
+        callbackRouter.tabsChanged.addListener(() => this.updateTabs_()),
+        callbackRouter.tabUpdated.addListener(tab => this.onTabUpdated_(tab)));
+    this.updateTabs_();
+  }
+
+  /** @override */
+  disconnectedCallback() {
+    this.listenerIds_.forEach(
+        id => this.apiProxy_.getCallbackRouter().removeListener(id));
+  }
+
+  /** @private */
+  updateTabs_() {
+    const getTabsStartTimestamp = Date.now();
+    this.apiProxy_.getProfileTabs().then(({profileTabs}) => {
+      chrome.metricsPrivate.recordTime(
+          'Tabs.TabSearch.WebUI.TabListDataReceived',
+          Math.round(Date.now() - getTabsStartTimestamp));
+
+      // Prior to the first load |this.openTabs_| has not been set. Record the
+      // time it takes for the initial list of tabs to render.
+      if (!this.openTabs_) {
+        listenOnce(this.$.tabsList, 'rendered-item-count-changed', e => {
+          const event = /** @type {!CustomEvent<!{value: number}>} */ (e);
+          // The initial rendered tab list must be non-zero.
+          assert(event.detail.value > 0);
+
+          // Chunking is used to bound the time to interactive for users
+          // irrespective of the number of tabs they have open. This is no longer
+          // needed after the initial list render and can cause flickering on
+          // updates so disable it here.
+          // TODO(tluk): Investigate a more efficient way to handle this.
+          this.chunkingItemCount_ = 0;
+
+          // Push showUI() to the event loop to allow reflow to occur following
+          // the DOM update.
+          setTimeout(() => {
+            this.apiProxy_.showUI();
+            chrome.metricsPrivate.recordTime(
+              'Tabs.TabSearch.WebUI.InitialTabsRenderTime',
+              Math.round(window.performance.now()));
+          }, 0);
+        });
+      }
+      this.openTabs_ = profileTabs.windows;
+    });
+  }
+
+  /**
+   * @param {!tabSearch.mojom.Tab} updatedTab
+   * @private
+   */
+  onTabUpdated_(updatedTab) {
+    const updatedTabId = updatedTab.tabId;
+    const windows = this.openTabs_;
+    if (windows) {
+      for (const window of windows) {
+        const {tabs} = window;
+        for (let i = 0; i < tabs.length; ++i) {
+          // Replace the tab with the same tabId and trigger rerender.
+          if (tabs[i].tabId === updatedTabId) {
+            tabs[i] = updatedTab;
+            this.openTabs_ = windows.concat();
+            return;
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * The seleted item's index, or -1 if no item selected.
+   * @return {number}
+   */
+  getSelectedIndex() {
+    const selector = /** @type {!IronSelectorElement} */ (this.$.selector);
+    return selector.selected !== undefined ?
+        /** @type {number} */ (selector.selected) :
+        -1;
+  }
+
+  /**
+   * @param {!CustomEvent<string>} e
+   * @private
+   */
+  onSearchChanged_(e) {
+    this.searchText_ = e.detail;
+
+    this.updateFilteredTabs_(this.openTabs_ || []);
+    // Reset the selected item whenever a search query is provided.
+    this.$.selector.selected =
+        this.filteredOpenTabs_.length > 0 ? 0 : undefined;
+    this.$.tabs.scrollTop = 0;
+
+    const length = this.filteredOpenTabs_.length;
+    let text;
+    if (this.searchText_.length > 0) {
+      text = loadTimeData.getStringF(
+          length == 1 ? 'a11yFoundTabFor' : 'a11yFoundTabsFor', length,
+          this.searchText_);
+    } else {
+      text = loadTimeData.getStringF(
+          length == 1 ? 'a11yFoundTab' : 'a11yFoundTabs', length);
+    }
+    this.announceA11y_(text);
+  }
+
+  /** @private */
+  onFeedbackClick_() {
+    this.apiProxy_.showFeedbackPage();
+  }
+
+  /** @private */
+  onFeedbackFocus_() {
+    this.$.selector.selected = undefined;
+  }
+
+  /**
+   * @param {!Event} e
+   * @private
+   */
+  onItemClick_(e) {
+    const tabId = Number.parseInt(e.currentTarget.id, 10);
+    this.apiProxy_.switchToTab({tabId}, !!this.searchText_);
+  }
+
+  /**
+   * @param {!Event} e
+   * @private
+   */
+  onItemClose_(e) {
+    const tabId = Number.parseInt(e.currentTarget.id, 10);
+    this.apiProxy_.closeTab(tabId);
+    this.announceA11y_(loadTimeData.getString('a11yTabClosed'));
+  }
+
+  /**
+   * @param {!Array<!tabSearch.mojom.WindowTabs>} newOpenTabs
+   * @private
+   */
+  openTabsChanged_(newOpenTabs) {
+    this.updateFilteredTabs_(newOpenTabs);
+
+    // If there was no previously selected index, set the first item as
+    // selected; else retain the currently selected index. If the list
+    // shrunk above the selected index, select the last index in the list.
+    // If there are no matching results, set the selected index value to none.
+    this.$.selector.selectIndex(Math.min(
+        Math.max(this.getSelectedIndex(), 0),
+        this.filteredOpenTabs_.length - 1));
+  }
+
+  /**
+   * @param {!Event} e
+   * @private
+   */
+  onItemFocus_(e) {
+    this.$.selector.selected =
+        e.currentTarget.parentNode.indexOf(e.currentTarget);
+    this.updateScrollView_();
+  }
+
+  /**
+   * @param {string} key Keyboard event key value.
+   * @private
+   */
+  selectorNavigate_(key) {
+    const selector = /** @type {!IronSelectorElement} */ (this.$.selector);
+    switch (key) {
+      case 'ArrowUp':
+        selector.selectPrevious();
+        break;
+      case 'ArrowDown':
+        selector.selectNext();
+        break;
+      case 'Home':
+        selector.selected = 0;
+        break;
+      case 'End':
+        selector.selected = this.filteredOpenTabs_.length - 1;
+        break;
+    }
+  }
+
+  /**
+   * Handles key events when list item elements have focus.
+   * @param {!KeyboardEvent} e
+   * @private
+   */
+  onItemKeyDown_(e) {
+    if (e.shiftKey) {
+      return;
+    }
+
+    if (this.getSelectedIndex() === -1) {
+      // No tabs matching the search text criteria.
+      return;
+    }
+
+    if (selectorNavigationKeys.includes(e.key)) {
+      this.selectorNavigate_(e.key);
+      /** @type {!HTMLElement} */ (this.$.selector.selectedItem).focus({
+        preventScroll: true
+      });
+      e.stopPropagation();
+      e.preventDefault();
+    } else if (e.key === 'Enter' || e.key === ' ') {
+      this.apiProxy_.switchToTab(
+          {tabId: this.getSelectedTab_().tabId}, !!this.searchText_);
+      e.stopPropagation();
+    }
+  }
+
+  /** @private */
+  onSearchFocus_() {
+    if (this.$.selector.selected === undefined &&
+        this.filteredOpenTabs_.length > 0) {
+      this.$.selector.selectIndex(0);
+    }
+  }
+
+  /**
+   * @param {!KeyboardEvent} e
+   * @private
+   */
+  onKeyDown_(e) {
+    if (e.key === 'Escape') {
+      e.stopPropagation();
+      e.preventDefault();
+      this.apiProxy_.closeUI();
+    }
+  }
+
+  /**
+   * Handles key events when the search field has focus.
+   * @param {!KeyboardEvent} e
+   * @private
+   */
+  onSearchKeyDown_(e) {
+    // Do not interfere with the search field's management of text selection.
+    if (e.shiftKey) {
+      return;
+    }
+
+    if (this.getSelectedIndex() === -1) {
+      // No tabs matching the search text criteria.
+      return;
+    }
+
+    if (selectorNavigationKeys.includes(e.key)) {
+      this.selectorNavigate_(e.key);
+      this.updateScrollView_();
+      e.stopPropagation();
+      e.preventDefault();
+
+      // For some reasons setting combobox/aria-activedescendant on tab-search-search-field
+      // has no effect, so manually announce a11y message here.
+      this.announceA11y_(this.ariaLabel_(this.getSelectedTab_()));
+    } else if (e.key === 'Enter') {
+      this.apiProxy_.switchToTab(
+          {tabId: this.getSelectedTab_().tabId}, !!this.searchText_);
+      e.stopPropagation();
+    }
+  }
+
+  /** @param {string} text */
+  announceA11y_(text) {
+    IronA11yAnnouncer.requestAvailability();
+    this.dispatchEvent(new CustomEvent(
+        'iron-announce', {bubbles: true, composed: true, detail: {text}}));
+  }
+
+  /**
+   * @return {string}
+   * @private
+   */
+  ariaLabel_(item) {
+    return `${item.title} ${item.hostname}`;
+  }
+
+  /**
+   * @return {string}
+   * @private
+   */
+  getKeyboardShortcut_() {
+    return (isMac ? 'Cmd' : 'Ctrl') + '+Shift+A';
+  }
+
+  /**
+   * @param {!Array<!tabSearch.mojom.WindowTabs>} windowTabs
+   * @private
+   */
+  updateFilteredTabs_(windowTabs) {
+    const result = [];
+    windowTabs.forEach(window => {
+      window.tabs.forEach(tab => {
+        const hostname = new URL(tab.url).hostname;
+        result.push({hostname, tab});
+      });
+    });
+    result.sort(
+        (a, b) => (b.tab.lastActiveTimeTicks && a.tab.lastActiveTimeTicks) ?
+            b.tab.lastActiveTimeTicks.internalValue -
+                a.tab.lastActiveTimeTicks.internalValue :
+            0);
+    this.filteredOpenTabs_ =
+        fuzzySearch(this.searchText_, result, this.fuzzySearchOptions_);
+
+    // Update the item count in css so that the css rule can calculate the final
+    // height of the tabsContainer. This prevents the scrolling height from
+    // changing as list items are added to the dom incrementally via chunking
+    // mode.
+    this.$.tabsContainer.style
+      .setProperty("--item-count", this.filteredOpenTabs_.length.toString());
+  }
+
+  /**
+   * Ensure the scroll view can fully display a preceding or following tab item
+   * if existing.
+   * @private
+   */
+  updateScrollView_() {
+    const selectedIndex = this.getSelectedIndex();
+    if (selectedIndex === 0 ||
+        selectedIndex === this.filteredOpenTabs_.length - 1) {
+      /** @type {!Element} */ (this.$.selector.selectedItem).scrollIntoView({
+        behavior: 'smooth'
+      });
+    } else {
+      const previousItem = this.$.selector.items[this.$.selector.selected - 1];
+      if (previousItem.offsetTop < this.$.tabs.scrollTop) {
+        /** @type {!Element} */ (previousItem)
+            .scrollIntoView({behavior: 'smooth', block: 'nearest'});
+        return;
+      }
+
+      const nextItem = this.$.selector.items[this.$.selector.selected + 1];
+      if (nextItem.offsetTop + nextItem.offsetHeight >
+          this.$.tabs.scrollTop + this.$.tabs.offsetHeight) {
+        /** @type {!Element} */ (nextItem).scrollIntoView(
+            {behavior: 'smooth', block: 'nearest'});
+      }
+    }
+  }
+
+  /** return {!tabSearch.mojom.Tab} */
+  getSelectedTab_() {
+    return this.filteredOpenTabs_[this.getSelectedIndex()].tab;
+  }
+}
+
+customElements.define(TabSearchAppElement.is, TabSearchAppElement);
diff --git a/chrome/browser/resources/tab_search_merge/fuzzy_search.js b/chrome/browser/resources/tab_search_merge/fuzzy_search.js
new file mode 100644
index 0000000..ec1ef3e
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/fuzzy_search.js
@@ -0,0 +1,206 @@
+// 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.
+
+import {quoteString} from 'chrome://resources/js/util.m.js';
+
+import Fuse from './fuse.js';
+import {TabData} from './tab_data.js';
+
+/**
+ * @param {string} input
+ * @param {!Array<!TabData>} records
+ * @param {!Object} options
+ * @return {!Array<!TabData>}
+ */
+export function fuzzySearch(input, records, options) {
+  if (input.length === 0) {
+    return records;
+  }
+  // Fuse does not handle exact match searches well. It indiscriminately
+  // searches for direct matches that appear anywhere in the string. This
+  // results in a bad search experience as users expect matches at the beginning
+  // of the title / hostname, or at the beginning of words to receive
+  // preferential treatment. Matched ranges returned by Fuse also fail to
+  // highlight only the matching text, but instead match to any character
+  // present in the input string.
+  // To address these shortcomings we use the exactSearch implementation below
+  // if the options indicate an exact matching algorithm should be used.
+  if (options.threshold === 0.0) {
+    return exactSearch(input, records, options);
+  } else {
+    return new Fuse(records, options).search(input).map(result => {
+      const titleMatch = result.matches.find(e => e.key === 'tab.title');
+      const hostnameMatch = result.matches.find(e => e.key === 'hostname');
+      const item = Object.assign({}, result.item);
+      if (titleMatch) {
+        item.titleHighlightRanges = convertToRanges(titleMatch.indices);
+      }
+      if (hostnameMatch) {
+        item.hostnameHighlightRanges = convertToRanges(hostnameMatch.indices);
+      }
+      return item;
+    });
+  }
+}
+
+/**
+ * Convert fuse.js matches [start1, end1], [start2, end2] ... to
+ * ranges {start:start1, length:length1}, {start:start2, length:length2} ...
+ * to be used by search_highlight_utils.js
+ * @param {!Array<!Array<number>>} matches
+ * @return {!Array<!{start: number, length: number}>}
+ */
+function convertToRanges(matches) {
+  return matches.map(
+      ([start, end]) => ({start: start, length: end - start + 1}));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Exact Match Implementation :
+
+/**
+ * The exact match algorithm returns records ranked according to the following
+ * priorities (highest to lowest priority):
+ * 1. All items with |title| or |hostname| matching the searchText at the
+ *    beginning of the string.
+ * 2. All items with |title| or |hostname| matching the searchText at the
+ *    beginning of a word in the string.
+ * 3. All remaining items with |title| or |hostname| matching the searchText
+ *    elsewhere in the string.
+ * @param {string} searchText
+ * @param {!Array<!TabData>} records
+ * @param {!Object} options
+ * @return {!Array<!TabData>}
+ */
+function exactSearch(searchText, records, options) {
+  if (searchText.length === 0) {
+    return records;
+  }
+
+  // Controls how heavily weighted the tab's title is relative to the hostname
+  // in the scoring function.
+  const key =
+      options.keys ? options.keys.find(e => e.name === 'tab.title') : undefined;
+  const titleToHostnameWeightRatio = key ? key.weight : 1;
+  // Default distance to calculate score for title/hostname based on match
+  // position.
+  const defaultDistance = 200;
+  const distance = options.distance || defaultDistance;
+
+  // Perform an exact match search with range discovery.
+  const exactMatches = [];
+  for (let tab of records) {
+    const titleHighlightRanges = getRanges(tab.tab.title, searchText);
+    const hostnameHighlightRanges = getRanges(tab.hostname, searchText);
+    if (!titleHighlightRanges.length && !hostnameHighlightRanges.length) {
+      continue;
+    }
+    const matchedTab = /** @type {!TabData} */ (Object.assign({}, tab));
+    if (titleHighlightRanges.length) {
+      matchedTab.titleHighlightRanges = titleHighlightRanges;
+    }
+    if (hostnameHighlightRanges.length) {
+      matchedTab.hostnameHighlightRanges = hostnameHighlightRanges;
+    }
+    exactMatches.push({
+      tab: matchedTab,
+      score: scoringFunction(matchedTab, distance, titleToHostnameWeightRatio)
+    });
+  }
+
+  // Sort by score.
+  exactMatches.sort((a, b) => (b.score - a.score));
+
+  // Prioritize items.
+  const itemsMatchingStringStart = [];
+  const itemsMatchingWordStart = [];
+  const others = [];
+  const wordStartRegexp = new RegExp(`\\b${quoteString(searchText)}`, 'i');
+  for (let {tab} of exactMatches) {
+    // Find matches that occur at the beginning of the string.
+    if (hasMatchStringStart(tab)) {
+      itemsMatchingStringStart.push(tab);
+    } else if (hasRegexMatch(tab, wordStartRegexp)) {
+      itemsMatchingWordStart.push(tab);
+    } else {
+      others.push(tab);
+    }
+  }
+  return itemsMatchingStringStart.concat(itemsMatchingWordStart, others);
+}
+
+/**
+ * Determines whether the given tab has a title or hostname with identified
+ * matches at the beginning of the string.
+ * @param {!TabData} tab
+ * @return {boolean}
+ */
+function hasMatchStringStart(tab) {
+  return (tab.titleHighlightRanges !== undefined &&
+          tab.titleHighlightRanges[0].start === 0) ||
+      (tab.hostnameHighlightRanges !== undefined &&
+       tab.hostnameHighlightRanges[0].start === 0);
+}
+
+/**
+ * Determines whether the given tab has a match for the given regexp in its
+ * title or hostname.
+ * @param {!TabData} tab
+ * @param {RegExp} regexp
+ * @return {boolean}
+ */
+function hasRegexMatch(tab, regexp) {
+  return (tab.titleHighlightRanges !== undefined &&
+          tab.tab.title.search(regexp) !== -1) ||
+      (tab.hostnameHighlightRanges !== undefined &&
+       tab.hostname.search(regexp) !== -1);
+}
+
+/**
+ * Returns an array of matches that indicate where in the target string the
+ * searchText appears. If there are no identified matches an empty array is
+ * returned.
+ * @param {string} target
+ * @param {string} searchText
+ * @return {!Array<!{start: number, length: number}>}
+ */
+function getRanges(target, searchText) {
+  const escapedText = quoteString(searchText);
+  let ranges = [];
+  let match = null;
+  for (const re = new RegExp(escapedText, 'gi'); match = re.exec(target);) {
+    ranges.push({
+      start : match.index,
+      length : searchText.length,
+    });
+  }
+  return ranges;
+}
+
+/**
+ * A scoring function based on match indices of title and hostname.
+ * Matches near the beginning of the string will have a higher score than
+ * matches near the end of the string. Multiple matches will have a higher score
+ * than single matches.
+ * @param {!TabData} tab
+ * @param {number} distance
+ * @param {number} titleToHostnameWeightRatio
+ */
+function scoringFunction(tab, distance, titleToHostnameWeightRatio) {
+  let score = 0;
+  // For every match, map the match index in [0, distance] to a scalar value in
+  // [1, 0].
+  if (tab.titleHighlightRanges) {
+    for (const {start} of tab.titleHighlightRanges) {
+      score += Math.max((distance - start) / distance, 0) *
+          titleToHostnameWeightRatio;
+    }
+  }
+  if (tab.hostnameHighlightRanges) {
+    for (const {start} of tab.hostnameHighlightRanges) {
+      score += Math.max((distance - start) / distance, 0);
+    }
+  }
+  return score;
+}
diff --git a/chrome/browser/resources/tab_search_merge/tab_data.js b/chrome/browser/resources/tab_search_merge/tab_data.js
new file mode 100644
index 0000000..a9f8f854
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/tab_data.js
@@ -0,0 +1,24 @@
+// 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.
+
+/**
+ * TabData contains tabSearch.mojom.Tab and data derived from it.
+ * It makes tabSearch.mojom.Tab immutable and works well for closure compiler
+ * type checking.
+ */
+export class TabData {
+  constructor() {
+    /** @type {!tabSearch.mojom.Tab} */
+    this.tab;
+
+    /** @type {string} */
+    this.hostname;
+
+    /** @type {!Array<!{start: number, length: number}>|undefined} */
+    this.titleHighlightRanges;
+
+    /** @type {!Array<!{start: number, length: number}>|undefined} */
+    this.hostnameHighlightRanges;
+  }
+}
\ No newline at end of file
diff --git a/chrome/browser/resources/tab_search_merge/tab_search_api_proxy.js b/chrome/browser/resources/tab_search_merge/tab_search_api_proxy.js
new file mode 100644
index 0000000..a5c66a8d
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/tab_search_api_proxy.js
@@ -0,0 +1,101 @@
+// 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.
+
+import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
+import 'chrome://resources/mojo/mojo/public/mojom/base/time.mojom-lite.js';
+import './tab_search.mojom-lite.js';
+
+import {addSingletonGetter} from 'chrome://resources/js/cr.m.js';
+
+/**
+ * These values are persisted to logs and should not be renumbered or re-used.
+ * See tools/metrics/histograms/enums.xml.
+ * @enum {number}
+ */
+export const TabSwitchAction = {
+  WITHOUT_SEARCH : 0,
+  WITH_SEARCH : 1,
+};
+
+/** @interface */
+export class TabSearchApiProxy {
+  /** @param {number} tabId */
+  closeTab(tabId) {}
+
+  /** @return {Promise<{profileTabs: tabSearch.mojom.ProfileTabs}>} */
+  getProfileTabs() {}
+
+  showFeedbackPage() {}
+
+  /**
+   * @param {!tabSearch.mojom.SwitchToTabInfo} info
+   * @param {boolean} withSearch
+   */
+  switchToTab(info, withSearch) {}
+
+  /** @return {!tabSearch.mojom.PageCallbackRouter} */
+  getCallbackRouter() {}
+
+  showUI() {}
+
+  closeUI() {}
+}
+
+/** @implements {TabSearchApiProxy} */
+export class TabSearchApiProxyImpl {
+  constructor() {
+    /** @type {!tabSearch.mojom.PageCallbackRouter} */
+    this.callbackRouter = new tabSearch.mojom.PageCallbackRouter();
+
+    /** @type {!tabSearch.mojom.PageHandlerRemote} */
+    this.handler = new tabSearch.mojom.PageHandlerRemote();
+
+    const factory = tabSearch.mojom.PageHandlerFactory.getRemote();
+    factory.createPageHandler(
+        this.callbackRouter.$.bindNewPipeAndPassRemote(),
+        this.handler.$.bindNewPipeAndPassReceiver());
+  }
+
+  /** @override */
+  closeTab(tabId) {
+    this.handler.closeTab(tabId);
+  }
+
+  /** @override */
+  getProfileTabs() {
+    return this.handler.getProfileTabs();
+  }
+
+  /** @override */
+  showFeedbackPage() {
+    this.handler.showFeedbackPage();
+  }
+
+  /** @override */
+  switchToTab(info, withSearch) {
+    chrome.metricsPrivate.recordEnumerationValue(
+        'Tabs.TabSearch.WebUI.TabSwitchAction',
+        withSearch ? TabSwitchAction.WITH_SEARCH
+                   : TabSwitchAction.WITHOUT_SEARCH,
+        Object.keys(TabSwitchAction).length);
+    this.handler.switchToTab(info);
+  }
+
+  /** @override */
+  getCallbackRouter() {
+    return this.callbackRouter;
+  }
+
+  /** @override */
+  showUI() {
+    this.handler.showUI();
+  }
+
+  /** @override */
+  closeUI() {
+    this.handler.closeUI();
+  }
+}
+
+addSingletonGetter(TabSearchApiProxyImpl);
diff --git a/chrome/browser/resources/tab_search_merge/tab_search_item.html b/chrome/browser/resources/tab_search_merge/tab_search_item.html
new file mode 100644
index 0000000..1f1c9cb
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/tab_search_item.html
@@ -0,0 +1,89 @@
+<style>
+  :host(:focus) {
+    outline-color: rgba(var(--mwb-background-color), 0.24);
+  }
+
+  :host(:hover, .selected) .button-container cr-icon-button {
+    --cr-icon-button-fill-color: var(--google-grey-refresh-700);
+  }
+
+  @media (prefers-color-scheme: dark) {
+    :host(:hover, .selected) .button-container cr-icon-button {
+      --cr-icon-button-fill-color: var(--google-grey-refresh-300);
+    }
+  }
+
+  .button-container cr-icon-button {
+    --cr-icon-button-fill-color: transparent;
+    border-radius: 50%;
+  }
+
+  .button-container cr-icon-button:hover {
+    background-color: rgba(var(--google-grey-900-rgb), 0.1);
+  }
+
+  @media (prefers-color-scheme: dark) {
+    .button-container cr-icon-button:hover {
+      background-color: rgba(var(--white-rgb), 0.1);
+    }
+  }
+
+  .button-container cr-icon-button:focus {
+    border: 2px solid rgba(var(--google-blue-600-rgb), 0.4);
+  }
+
+  .favicon {
+    background-repeat: no-repeat;
+    background-size: var(--mwb-icon-size);
+    flex-shrink: 0;
+    height: var(--mwb-icon-size);
+    margin-inline-end: var(--mwb-list-item-horizontal-margin);
+    width: var(--mwb-icon-size);
+  }
+
+  .text-container {
+    flex-grow: 1;
+    overflow: hidden;
+  }
+
+  #primaryText,
+  #secondaryText {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    user-select: none;
+    white-space: nowrap;
+  }
+
+  #primaryText {
+    color: var(--cr-primary-text-color);
+    font-size: var(--mwb-primary-text-font-size);
+    margin-bottom: 3px;
+  }
+
+  #secondaryText {
+    color: var(--cr-secondary-text-color);
+    font-size: var(--mwb-secondary-text-font-size);
+  }
+
+  cr-icon-button {
+    --cr-icon-button-margin-end: calc(var(--mwb-icon-size) / 4);
+    --cr-icon-button-margin-start: calc(var(--mwb-icon-size) / 4);
+    --cr-icon-button-size: var(--mwb-icon-size);
+  }
+
+  .search-highlight-hit {
+    font-weight: bold;
+  }
+</style>
+
+<div class="favicon" style="background-image:[[faviconUrl_(data.tab)]]"></div>
+<div class="text-container">
+  <div id="primaryText" title="[[data.tab.title]]"></div>
+  <div id="secondaryText"></div>
+</div>
+<div class="button-container">
+  <cr-icon-button id="closeButton" aria-label="[[ariaLabel_(data.tab.title)]]"
+      iron-icon="mwb16:close" noink on-click="onItemClose_"
+      title="$i18n{closeTab}">
+  </cr-icon-button>
+</div>
diff --git a/chrome/browser/resources/tab_search_merge/tab_search_item.js b/chrome/browser/resources/tab_search_merge/tab_search_item.js
new file mode 100644
index 0000000..4f66ee2b
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/tab_search_item.js
@@ -0,0 +1,101 @@
+// 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.
+
+import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
+import 'chrome://resources/cr_elements/cr_icons_css.m.js';
+import 'chrome://resources/cr_elements/mwb_shared_icons.js';
+import 'chrome://resources/cr_elements/mwb_shared_vars.js';
+import 'chrome://resources/cr_elements/shared_vars_css.m.js';
+
+import {getFaviconForPageURL} from 'chrome://resources/js/icon.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {highlight} from 'chrome://resources/js/search_highlight_utils.m.js';
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {TabData} from './tab_data.js';
+import './strings.js';
+
+export class TabSearchItem extends PolymerElement {
+  static get is() {
+    return 'tab-search-item';
+  }
+
+  static get template() {
+    return html`{__html_template__}`;
+  }
+
+  static get properties() {
+    return {
+      /** @type {!TabData} */
+      data: {
+        type: Object,
+        observer: 'dataChanged_',
+      },
+    };
+  }
+
+  /**
+   * @param {!Event} e
+   * @private
+   */
+  onItemClose_(e) {
+    this.dispatchEvent(new CustomEvent('close'));
+    e.stopPropagation();
+  }
+
+  /**
+   * @param {!tabSearch.mojom.Tab} tab
+   * @return {string}
+   * @private
+   */
+  faviconUrl_(tab) {
+    return tab.faviconUrl ?
+        `url("${tab.faviconUrl}")` :
+        getFaviconForPageURL(
+            tab.isDefaultFavicon ? 'chrome://newtab' : tab.url, false);
+  }
+
+  /**
+   * @private
+   */
+  dataChanged_() {
+    this.highlightText_(
+        /** @type {!HTMLElement} */ (this.$.primaryText), this.data.tab.title,
+        this.data.titleHighlightRanges);
+    this.highlightText_(
+        /** @type {!HTMLElement} */ (this.$.secondaryText), this.data.hostname,
+        this.data.hostnameHighlightRanges);
+
+    // Show chrome:// if it's a chrome internal url
+    if (new URL(this.data.tab.url).protocol === 'chrome:') {
+      /** @type {!HTMLElement} */ (this.$.secondaryText)
+          .prepend(document.createTextNode('chrome://'));
+    }
+  }
+
+  /**
+   *
+   * @param {!HTMLElement} container
+   * @param {string} text
+   * @param {!Array<!{start:number, length:number}>|undefined} ranges
+   */
+  highlightText_(container, text, ranges) {
+    container.textContent = '';
+    const node = document.createTextNode(text);
+    container.appendChild(node);
+    if (ranges) {
+      const result = highlight(node, ranges, true);
+      // Delete default highlight style.
+      result.querySelectorAll('.search-highlight-hit').forEach(e => {
+        e.style = '';
+      });
+    }
+  }
+
+  ariaLabel_(title) {
+    return `${loadTimeData.getString('closeTab')} ${title}`;
+  }
+}
+
+customElements.define(TabSearchItem.is, TabSearchItem);
diff --git a/chrome/browser/resources/tab_search_merge/tab_search_page.html b/chrome/browser/resources/tab_search_merge/tab_search_page.html
new file mode 100644
index 0000000..7c489fa
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/tab_search_page.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Tab Search</title>
+  <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
+  <style>
+    html {
+      --white-rgb: 255, 255, 255;
+    }
+
+    html,
+    body {
+      width: 320px;
+    }
+
+    body {
+      /* Using a var here for the background color is not currently an issue for
+         Tab Search UI as it is shown asynchronously after the onload handler of
+         the main frame has completed. */
+      background-color: var(--mwb-background-color);
+      margin: 0;
+    }
+  </style>
+</head>
+<body>
+  <tab-search-app></tab-search-app>
+  <script type="module" src="app.js"></script>
+  <script type="module" src="chrome://resources/cr_elements/mwb_shared_vars.js">
+  </script>
+</body>
+</html>
diff --git a/chrome/browser/resources/tab_search_merge/tab_search_resources.grd b/chrome/browser/resources/tab_search_merge/tab_search_resources.grd
new file mode 100644
index 0000000..aa4978ea
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/tab_search_resources.grd
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
+  <outputs>
+    <output filename="grit/tab_search_resources.h" type="rc_header">
+      <emit emit_type='prepend'></emit>
+    </output>
+    <output filename="grit/tab_search_resources_map.cc"
+            type="resource_file_map_source" />
+    <output filename="grit/tab_search_resources_map.h"
+            type="resource_map_header" />
+    <output filename="tab_search_resources.pak" type="data_package" />
+  </outputs>
+  <release seq="1">
+    <includes>
+      <include name="IDR_APP_JS"
+               file="${root_gen_dir}/chrome/browser/resources/tab_search/app.js"
+               type="BINDATA"
+               use_base_dir="false" />
+      <include name="IDR_FUSE_JS"
+               file="../../../../third_party/fusejs/dist/fuse.basic.esm.min.js"
+               type="BINDATA"/>
+      <include name="IDR_FUZZY_SEARCH_JS"
+               file="fuzzy_search.js"
+               type="BINDATA"/>
+      <include name="IDR_TAB_DATA_JS"
+               file="tab_data.js"
+               type="BINDATA" />
+      <include name="IDR_TAB_SEARCH_API_PROXY_JS"
+               file="tab_search_api_proxy.js"
+               type="BINDATA" />
+      <include name="IDR_TAB_SEARCH_ITEM_JS"
+               file="${root_gen_dir}/chrome/browser/resources/tab_search/tab_search_item.js"
+               type="BINDATA"
+               use_base_dir="false"/>
+      <include name="IDR_TAB_SEARCH_MOJO_LITE_JS"
+               file="${root_gen_dir}/chrome/browser/ui/webui/tab_search/tab_search.mojom-lite.js"
+               type="BINDATA"
+               use_base_dir="false"/>
+      <include name="IDR_TAB_SEARCH_PAGE_HTML"
+               file="tab_search_page.html"
+               type="BINDATA" />
+      <include name="IDR_TAB_SEARCH_SEARCH_FIELD_JS"
+               file="${root_gen_dir}/chrome/browser/resources/tab_search/tab_search_search_field.js"
+               type="BINDATA"
+               use_base_dir="false" />
+    </includes>
+  </release>
+</grit>
diff --git a/chrome/browser/resources/tab_search_merge/tab_search_search_field.html b/chrome/browser/resources/tab_search_merge/tab_search_search_field.html
new file mode 100644
index 0000000..983f9b77
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/tab_search_search_field.html
@@ -0,0 +1,43 @@
+<style include="cr-icons">
+  :host {
+    align-items: center;
+    background-color: var(--mwb-background-color);
+    display: flex;
+    height: var(--mwb-item-height);
+    padding: 0 var(--mwb-list-item-horizontal-margin);
+    user-select: none;
+  }
+
+  #searchIcon {
+    height: var(--mwb-icon-size);
+    padding-inline-end: var(--mwb-list-item-horizontal-margin);
+    width: var(--mwb-icon-size);
+  }
+
+  #searchInput {
+    padding: 0;
+  }
+
+  @media (prefers-color-scheme: dark) {
+    #searchIcon {
+      color: var(--google-blue-refresh-300);
+    }
+  }
+
+  input {
+    align-self: stretch;
+    background-color: transparent;
+    border: none;
+    border-radius: 0;
+    color: var(--cr-primary-text-color);
+    flex: 1;
+    font-size: var(--mwb-primary-text-font-size);
+    outline: none;
+    text-overflow: ellipsis;
+  }
+</style>
+<iron-icon id="searchIcon" icon="mwb16:search"></iron-icon>
+<input id="searchInput" on-search="onSearchTermSearch"
+    on-input="onSearchTermInput" aria-label$="[[label]]" type="search"
+    autofocus="[[autofocus]]" placeholder="[[label]]" autocomplete="off"
+    spellcheck="false" />
diff --git a/chrome/browser/resources/tab_search_merge/tab_search_search_field.js b/chrome/browser/resources/tab_search_merge/tab_search_search_field.js
new file mode 100644
index 0000000..a7ca9ff
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/tab_search_search_field.js
@@ -0,0 +1,50 @@
+// 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.
+
+import 'chrome://resources/cr_elements/mwb_shared_icons.js';
+import 'chrome://resources/cr_elements/mwb_shared_vars.js';
+import 'chrome://resources/cr_elements/shared_vars_css.m.js';
+import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
+
+import {CrSearchFieldBehavior, CrSearchFieldBehaviorInterface} from 'chrome://resources/cr_elements/cr_search_field/cr_search_field_behavior.m.js';
+import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+/**
+ * @constructor
+ * @extends {PolymerElement}
+ * @implements {CrSearchFieldBehaviorInterface}
+ */
+const TabSearchSearchFieldBase =
+    mixinBehaviors([ CrSearchFieldBehavior ], PolymerElement);
+
+/** @polymer */
+export class TabSearchSearchField extends TabSearchSearchFieldBase {
+
+  static get is() {
+    return 'tab-search-search-field';
+  }
+
+  static get template() {
+    return html`{__html_template__}`;
+  }
+
+  static get properties() {
+    return {
+      /**
+       * Controls autofocus for the search field.
+       */
+      autofocus: {
+        type: Boolean,
+        value: false,
+      },
+    };
+  }
+
+  /** @return {!HTMLInputElement} */
+  getSearchInput() {
+    return /** @type {!HTMLInputElement} */ (this.$.searchInput);
+  }
+}
+
+customElements.define(TabSearchSearchField.is, TabSearchSearchField);
diff --git a/chrome/browser/resources/tab_search_merge/test/BUILD.gn b/chrome/browser/resources/tab_search_merge/test/BUILD.gn
new file mode 100644
index 0000000..f0f059c
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/test/BUILD.gn
@@ -0,0 +1,62 @@
+# 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.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_type_check("closure_compile") {
+  is_polymer3 = true
+  closure_flags = default_closure_args + [
+                    "browser_resolver_prefix_replacements=\"chrome://tab-search/=../../chrome/browser/resources/tab-search/\"",
+                    "js_module_root=../../chrome/test/data/webui/",
+                    "js_module_root=./gen/chrome/test/data/webui/",
+                  ]
+  deps = [
+    ":fuzzy_search_test",
+    ":tab_search_app_focus_test",
+    ":tab_search_app_test",
+    ":tab_search_item_test",
+  ]
+}
+
+js_library("fuzzy_search_test") {
+  deps = [
+    ":test_tab_search_api_proxy",
+    "../..:chai_assert",
+  ]
+  externs_list = [ "$externs_path/mocha-2.5.js" ]
+}
+
+js_library("tab_search_app_test") {
+  deps = [
+    ":test_tab_search_api_proxy",
+    "../..:chai_assert",
+    "//chrome/browser/resources/tab_search:app",
+  ]
+  externs_list = [ "$externs_path/mocha-2.5.js" ]
+}
+
+js_library("tab_search_app_focus_test") {
+  deps = [
+    ":test_tab_search_api_proxy",
+    "../..:chai_assert",
+    "//chrome/browser/resources/tab_search:app",
+  ]
+  externs_list = [ "$externs_path/mocha-2.5.js" ]
+}
+
+js_library("test_tab_search_api_proxy") {
+  deps = [
+    "//chrome/browser/resources/tab_search:tab_search_api_proxy",
+    "//chrome/browser/ui/webui/tab_search:mojo_bindings_js_library_for_compile",
+    "//chrome/test/data/webui:test_browser_proxy.m",
+  ]
+}
+
+js_library("tab_search_item_test") {
+  deps = [
+    "../..:chai_assert",
+    "//chrome/browser/resources/tab_search:tab_search_item",
+  ]
+  externs_list = [ "$externs_path/mocha-2.5.js" ]
+}
diff --git a/chrome/browser/resources/tab_search_merge/test/fuzzy_search_test.js b/chrome/browser/resources/tab_search_merge/test/fuzzy_search_test.js
new file mode 100644
index 0000000..c442681
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/test/fuzzy_search_test.js
@@ -0,0 +1,278 @@
+// 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.
+
+import {fuzzySearch} from 'chrome://tab-search/fuzzy_search.js';
+import {TabData} from 'chrome://tab-search/tab_data.js';
+import {assertDeepEquals, assertEquals} from '../../chai_assert.js';
+
+/**
+ * Assert search results return in specific order.
+ * @param {string} input
+ * @param {!Array<!TabData>} items
+ * @param {!Object} options
+ * @param {!Array<number>} expectedIndices
+ */
+function assertSearchOrders(input, items, options, expectedIndices) {
+  const results = fuzzySearch(input, items, options);
+  assertEquals(results.length, expectedIndices.length);
+  for (let i = 0; i < results.length; ++i) {
+    const expectedItem = items[expectedIndices[i]];
+    const actualItem = results[i];
+    assertEquals(expectedItem.tab.title, actualItem.tab.title);
+    assertEquals(expectedItem.hostname, actualItem.hostname);
+  }
+}
+
+suite('FuzzySearchTest', () => {
+  test('fuzzySearch', () => {
+    const records = [
+      {
+        tab: {
+          title: 'OpenGL',
+        },
+        hostname: 'www.opengl.org',
+      },
+      {
+        tab: {
+          title: 'Google',
+        },
+        hostname: 'www.google.com',
+      },
+    ];
+
+    const matchedRecords = [
+      {
+        tab: {
+          title: 'Google',
+        },
+        hostname: 'www.google.com',
+        titleHighlightRanges: [{start: 0, length: 1}, {start: 3, length: 3}],
+        hostnameHighlightRanges: [{start: 4, length: 1}, {start: 7, length: 3}]
+      },
+      {
+        tab: {
+          title: 'OpenGL',
+        },
+        hostname: 'www.opengl.org',
+        titleHighlightRanges: [{start: 2, length: 1}, {start: 4, length: 2}],
+        hostnameHighlightRanges: [
+          {start: 6, length: 1}, {start: 8, length: 2}, {start: 13, length: 1}
+        ],
+      },
+    ];
+
+    const options = {
+      includeScore: true,
+      ignoreLocation: true,
+      includeMatches: true,
+      keys: [
+        {
+          name: 'tab.title',
+          weight: 2,
+        },
+        {
+          name: 'hostname',
+          weight: 1,
+        }
+      ]
+    };
+
+    assertDeepEquals(matchedRecords, fuzzySearch('gle', records, options));
+    assertDeepEquals(records, fuzzySearch('', records, options));
+    assertDeepEquals([], fuzzySearch('z', records, options));
+  });
+
+  test('Test the exact match ranking order.', () => {
+    // Set threshold to 0.0 to assert an exact match search.
+    const options = {
+      threshold: 0.0,
+    };
+
+    // Initial pre-search item list.
+    const records = [
+      {
+        tab: {
+          title: 'Code Search',
+        },
+        hostname: 'search.chromium.search',
+      },
+      {tab: {title: 'Marching band'}, hostname: 'en.marching.band.com'},
+      {
+        tab: {title: 'Chrome Desktop Architecture'},
+        hostname: 'drive.google.com',
+      },
+      {
+        tab: {title: 'Arch Linux'},
+        hostname: 'www.archlinux.org',
+      },
+      {
+        tab: {title: 'Arches National Park'},
+        hostname: 'www.nps.gov',
+      },
+      {
+        tab: {title: 'Search Engine Land - Search Engines'},
+        hostname: 'searchengineland.com'
+      },
+    ];
+
+    // Resuts for 'arch'.
+    const archMatchedRecords = [
+      {
+        tab: {title: 'Arch Linux'},
+        hostname: 'www.archlinux.org',
+        titleHighlightRanges: [{start: 0, length: 4}],
+        hostnameHighlightRanges: [{start: 4, length: 4}],
+      },
+      {
+        tab: {title: 'Arches National Park'},
+        hostname: 'www.nps.gov',
+        titleHighlightRanges: [{start: 0, length: 4}],
+      },
+      {
+        tab: {title: 'Chrome Desktop Architecture'},
+        hostname: 'drive.google.com',
+        titleHighlightRanges: [{start: 15, length: 4}],
+      },
+      {
+        tab: {title: 'Code Search'},
+        hostname: 'search.chromium.search',
+        titleHighlightRanges: [{start: 7, length: 4}],
+        hostnameHighlightRanges:
+            [{start: 2, length: 4}, {start: 18, length: 4}],
+      },
+      {
+        tab: {title: 'Search Engine Land - Search Engines'},
+        hostname: 'searchengineland.com',
+        titleHighlightRanges: [{start: 2, length: 4}, {start: 23, length: 4}],
+        hostnameHighlightRanges: [{start: 2, length: 4}]
+      },
+      {
+        tab: {title: 'Marching band'},
+        hostname: 'en.marching.band.com',
+        titleHighlightRanges: [{start: 1, length: 4}],
+        hostnameHighlightRanges: [{start: 4, length: 4}]
+      },
+    ];
+
+    // Results for 'search'.
+    const searchMatchedRecords = [
+      {
+        tab: {title: 'Code Search'},
+        hostname: 'search.chromium.search',
+        titleHighlightRanges: [{start: 5, length: 6}],
+        hostnameHighlightRanges:
+            [{start: 0, length: 6}, {start: 16, length: 6}],
+      },
+      {
+        tab: {title: 'Search Engine Land - Search Engines'},
+        hostname: 'searchengineland.com',
+        titleHighlightRanges: [{start: 0, length: 6}, {start: 21, length: 6}],
+        hostnameHighlightRanges: [{start: 0, length: 6}]
+      },
+    ];
+
+    // Empty search should return the full list.
+    assertDeepEquals(records, fuzzySearch('', records, options));
+
+    assertDeepEquals(archMatchedRecords, fuzzySearch('arch', records, options));
+    assertDeepEquals(searchMatchedRecords,
+                     fuzzySearch('search', records, options));
+
+    // No matches should return an empty list.
+    assertDeepEquals([], fuzzySearch('archh', records, options));
+  });
+
+  test('Test exact search with escaped characters.', () => {
+    // Set threshold to 0.0 to assert an exact match search.
+    const options = {
+      threshold: 0.0,
+    };
+
+    // Initial pre-search item list.
+    const records = [{
+      tab: {title: '\'beginning\\test\\end'},
+      hostname: 'beginning\\test\"end',
+    }];
+
+    // Expected results for '\test'.
+    const backslashMatchedRecords = [
+      {
+        tab: {title: '\'beginning\\test\\end'},
+        hostname: 'beginning\\test\"end',
+        titleHighlightRanges: [{start: 10, length: 5}],
+        hostnameHighlightRanges: [{start: 9, length: 5}]
+      },
+    ];
+
+    // Expected results for '"end'.
+    const quoteMatchedRecords = [
+      {
+        tab: {title: '\'beginning\\test\\end'},
+        hostname: 'beginning\\test\"end',
+        hostnameHighlightRanges: [{start: 14, length: 4}],
+      },
+    ];
+
+    assertDeepEquals(backslashMatchedRecords,
+                     fuzzySearch('\\test', records, options));
+    assertDeepEquals(quoteMatchedRecords,
+                     fuzzySearch('\"end', records, options));
+  });
+
+  test('Test exact match result scoring accounts for match position.', () => {
+    const options = {
+      threshold: 0.0,
+    };
+    assertSearchOrders(
+        'two',
+        [
+          {tab: {title: 'three one two'}}, {tab: {title: 'three two one'}},
+          {tab: {title: 'one two three'}}
+        ],
+        options, [2, 1, 0]);
+  });
+
+  test(
+      'Test exact match result scoring takes into account the number of matches per item.',
+      () => {
+        const options = {
+          threshold: 0.0,
+        };
+        assertSearchOrders(
+            'one',
+            [
+              {tab: {title: 'one two three'}}, {tab: {title: 'one one three'}},
+              {tab: {title: 'one one one'}}
+            ],
+            options, [2, 1, 0]);
+      });
+
+  test(
+      'Test exact match result scoring abides by the titleToHostnameWeightRatio.',
+      () => {
+        const options = {
+          threshold: 0.0,
+          keys: [
+            {
+              name: 'tab.title',
+              weight: 2,
+            },
+            {
+              name: 'hostname',
+              weight: 1,
+            }
+          ]
+        };
+        assertSearchOrders(
+            'search',
+            [
+              {tab: {title: 'New tab'}, hostname: 'chrome://tab-search'},
+              {tab: {title: 'chrome://tab-search'}}, {
+                tab: {title: 'chrome://tab-search'},
+                hostname: 'chrome://tab-search'
+              }
+            ],
+            options, [2, 1, 0]);
+      });
+});
diff --git a/chrome/browser/resources/tab_search_merge/test/tab_search_app_focus_test.js b/chrome/browser/resources/tab_search_merge/test/tab_search_app_focus_test.js
new file mode 100644
index 0000000..4e3f4eed
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/test/tab_search_app_focus_test.js
@@ -0,0 +1,123 @@
+// 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.
+
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {getDeepActiveElement} from 'chrome://resources/js/util.m.js';
+import {keyDownOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
+import {TabSearchAppElement} from 'chrome://tab-search/app.js';
+import {TabSearchApiProxy, TabSearchApiProxyImpl} from 'chrome://tab-search/tab_search_api_proxy.js'
+import {TabSearchItem} from 'chrome://tab-search/tab_search_item.js';
+import {TabSearchSearchField} from 'chrome://tab-search/tab_search_search_field.js';
+
+import {assertEquals, assertGT} from '../../chai_assert.js';
+import {flushTasks} from '../../test_util.m.js';
+
+import {generateSampleDataFromSiteNames, sampleData, sampleSiteNames} from './tab_search_test_data.js';
+import {assertTabItemAndNeighborsInViewBounds, disableScrollIntoViewAnimations} from './tab_search_test_helper.js';
+import {TestTabSearchApiProxy} from './test_tab_search_api_proxy.js';
+
+suite('TabSearchAppFocusTest', () => {
+  /** @type {!TabSearchAppElement} */
+  let tabSearchApp;
+  /** @type {!TestTabSearchApiProxy} */
+  let testProxy;
+
+  disableScrollIntoViewAnimations(TabSearchItem);
+
+  /**
+   * @param {tabSearch.mojom.ProfileTabs} sampleData
+   * @param {Object=} loadTimeOverridenData
+   */
+  async function setupTest(sampleData, loadTimeOverridenData) {
+    testProxy = new TestTabSearchApiProxy();
+    testProxy.setProfileTabs(sampleData);
+    TabSearchApiProxyImpl.instance_ = testProxy;
+
+    if (loadTimeOverridenData) {
+      loadTimeData.overrideValues(loadTimeOverridenData);
+    }
+
+    tabSearchApp = /** @type {!TabSearchAppElement} */
+        (document.createElement('tab-search-app'));
+
+    document.body.innerHTML = '';
+    document.body.appendChild(tabSearchApp);
+    await flushTasks();
+  }
+
+  test('KeyNavigation', async () => {
+    await setupTest(sampleData(), {'submitFeedbackEnabled': true});
+
+    // Initially, the search input should have focus.
+    const searchField = /** @type {!TabSearchSearchField} */
+        (tabSearchApp.shadowRoot.querySelector('#searchField'));
+    const searchInput = /** @type {!HTMLInputElement} */
+        (searchField.shadowRoot.querySelector('#searchInput'))
+    assertEquals(searchInput, getDeepActiveElement());
+
+    const tabSearchItems = /** @type {!NodeList<!HTMLElement>} */
+        (tabSearchApp.shadowRoot.querySelectorAll('tab-search-item'));
+
+    tabSearchItems[0].focus();
+    // Once an item is focused, arrow keys should change focus too.
+    keyDownOn(tabSearchItems[0], 0, [], 'ArrowDown');
+    assertEquals(tabSearchItems[1], getDeepActiveElement());
+
+    keyDownOn(tabSearchItems[1], 0, [], 'ArrowUp');
+    assertEquals(tabSearchItems[0], getDeepActiveElement());
+
+    keyDownOn(tabSearchItems[1], 0, [], 'End');
+    assertEquals(
+        tabSearchItems[tabSearchItems.length - 1], getDeepActiveElement());
+
+    keyDownOn(tabSearchItems[tabSearchItems.length - 1], 0, [], 'Home');
+    assertEquals(tabSearchItems[0], getDeepActiveElement());
+
+    // Once the feedback button is focused, no list item should be selected.
+    const feedbackButton = /** @type {!HTMLElement} */ (
+        tabSearchApp.shadowRoot.querySelector('#feedback-footer'));
+    feedbackButton.focus();
+    assertEquals(-1, tabSearchApp.getSelectedIndex());
+
+    // On restoring focus to the search field, a list item should be selected if
+    // available.
+    searchInput.focus();
+    assertEquals(0, tabSearchApp.getSelectedIndex());
+  });
+
+  test('KeyPress', async () => {
+    await setupTest(sampleData());
+
+    const tabSearchItem = /** @type {!HTMLElement} */
+        (tabSearchApp.shadowRoot.querySelector('tab-search-item'));
+    tabSearchItem.focus();
+
+    keyDownOn(tabSearchItem, 0, [], 'Enter');
+    keyDownOn(tabSearchItem, 0, [], ' ');
+    assertEquals(2, testProxy.getCallCount('switchToTab'));
+
+    const closeButton = /** @type {!HTMLElement} */ (
+        tabSearchItem.shadowRoot.querySelector('#closeButton'));
+    keyDownOn(closeButton, 0, [], 'Enter');
+    assertEquals(1, testProxy.getCallCount('closeTab'));
+  });
+
+  test('ViewScrolling', async () => {
+    await setupTest(generateSampleDataFromSiteNames(sampleSiteNames()));
+
+    const tabsDiv = /** @type {!HTMLElement} */
+        (tabSearchApp.shadowRoot.querySelector('#tabs'));
+    // Assert that the tabs are in a overflowing state.
+    assertGT(tabsDiv.scrollHeight, tabsDiv.clientHeight);
+
+    const tabItems = /** @type {!NodeList<HTMLElement>} */
+        (tabSearchApp.shadowRoot.querySelectorAll('tab-search-item'));
+    for (let i = 0; i < tabItems.length; i++) {
+      tabItems[i].focus();
+
+      assertEquals(i, tabSearchApp.getSelectedIndex());
+      assertTabItemAndNeighborsInViewBounds(tabsDiv, tabItems, i);
+    }
+  });
+});
diff --git a/chrome/browser/resources/tab_search_merge/test/tab_search_app_test.js b/chrome/browser/resources/tab_search_merge/test/tab_search_app_test.js
new file mode 100644
index 0000000..8ad57cb
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/test/tab_search_app_test.js
@@ -0,0 +1,431 @@
+// 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.
+
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {keyDownOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
+import {TabSearchAppElement} from 'chrome://tab-search/app.js';
+import {TabSearchApiProxy, TabSearchApiProxyImpl} from 'chrome://tab-search/tab_search_api_proxy.js'
+import {TabSearchItem} from 'chrome://tab-search/tab_search_item.js';
+import {TabSearchSearchField} from 'chrome://tab-search/tab_search_search_field.js';
+
+import {assertEquals, assertFalse, assertGT, assertNotEquals, assertTrue} from '../../chai_assert.js';
+import {flushTasks, waitAfterNextRender} from '../../test_util.m.js';
+
+import {generateSampleDataFromSiteNames, sampleData, sampleSiteNames} from './tab_search_test_data.js';
+import {assertTabItemAndNeighborsInViewBounds, assertTabItemInViewBounds, disableScrollIntoViewAnimations} from './tab_search_test_helper.js';
+import {TestTabSearchApiProxy} from './test_tab_search_api_proxy.js';
+
+suite('TabSearchAppTest', () => {
+  /** @type {!TabSearchAppElement} */
+  let tabSearchApp;
+  /** @type {!TestTabSearchApiProxy} */
+  let testProxy;
+
+  disableScrollIntoViewAnimations(TabSearchItem);
+
+  /**
+   * @param {!NodeList<!Element>} rows
+   * @param {!Array<number>} ids
+   */
+  function verifyTabIds(rows, ids) {
+    assertEquals(ids.length, rows.length);
+    rows.forEach((row, index) => {
+      assertEquals(ids[index].toString(), row.getAttribute('id'));
+    });
+  }
+
+  /**
+   * @return {!NodeList<!Element>}
+   */
+  function queryRows() {
+    return tabSearchApp.shadowRoot.querySelectorAll('tab-search-item');
+  }
+
+  /**
+   * @param {tabSearch.mojom.ProfileTabs} sampleData
+   * @param {Object=} loadTimeOverridenData
+   */
+  async function setupTest(sampleData, loadTimeOverridenData) {
+    testProxy = new TestTabSearchApiProxy();
+    testProxy.setProfileTabs(sampleData);
+    TabSearchApiProxyImpl.instance_ = testProxy;
+
+    if (loadTimeOverridenData) {
+      loadTimeData.overrideValues(loadTimeOverridenData);
+    }
+
+    tabSearchApp = /** @type {!TabSearchAppElement} */
+        (document.createElement('tab-search-app'));
+
+    document.body.innerHTML = '';
+    document.body.appendChild(tabSearchApp);
+    await flushTasks();
+  }
+
+  test('return all tabs', async () => {
+    await setupTest(sampleData());
+    verifyTabIds(queryRows(), [1, 5, 6, 2, 3, 4]);
+  });
+
+  test('Default tab selection when data is present', async () => {
+    await setupTest(sampleData());
+    assertNotEquals(-1, tabSearchApp.getSelectedIndex(),
+        'No default selection in the presence of data');
+  });
+
+  test('Search text changes tab items', async () => {
+    await setupTest(sampleData());
+    const searchField = /** @type {!TabSearchSearchField} */
+      (tabSearchApp.shadowRoot.querySelector("#searchField"));
+    searchField.setValue('bing');
+    await flushTasks();
+    verifyTabIds(queryRows(), [2]);
+    assertEquals(0, tabSearchApp.getSelectedIndex());
+  });
+
+  test('No tab selected when there are no search matches', async () => {
+    await setupTest(sampleData());
+    const searchField = /** @type {!TabSearchSearchField} */
+        (tabSearchApp.shadowRoot.querySelector('#searchField'));
+    searchField.setValue('Twitter');
+    await flushTasks();
+    assertEquals(0, queryRows().length);
+    assertEquals(-1, tabSearchApp.getSelectedIndex());
+  });
+
+  test('Click on tab item triggers actions', async () => {
+    const tabData = {
+      index: 0,
+      tabId: 1,
+      title: 'Google',
+      url: 'https://www.google.com',
+    };
+    await setupTest({windows: [{active: true, tabs: [tabData]}]});
+
+    const tabSearchItem = /** @type {!HTMLElement} */
+        (tabSearchApp.shadowRoot.querySelector('tab-search-item'));
+    tabSearchItem.click();
+    const [tabInfo] = await testProxy.whenCalled('switchToTab');
+    assertEquals(tabData.tabId, tabInfo.tabId);
+
+    const tabSearchItemCloseButton = /** @type {!HTMLElement} */ (
+        tabSearchItem.shadowRoot.querySelector('cr-icon-button'));
+    tabSearchItemCloseButton.click();
+    const tabId = await testProxy.whenCalled('closeTab');
+    assertEquals(tabData.tabId, tabId);
+  });
+
+  test('Keyboard navigation on an empty list', async () => {
+    await setupTest({windows: [{active: true, tabs: []}]});
+
+    const searchField = /** @type {!TabSearchSearchField} */
+        (tabSearchApp.shadowRoot.querySelector("#searchField"));
+
+    keyDownOn(searchField, 0, [], 'ArrowUp');
+    assertEquals(-1, tabSearchApp.getSelectedIndex());
+
+    keyDownOn(searchField, 0, [], 'ArrowDown');
+    assertEquals(-1, tabSearchApp.getSelectedIndex());
+
+    keyDownOn(searchField, 0, [], 'Home');
+    assertEquals(-1, tabSearchApp.getSelectedIndex());
+
+    keyDownOn(searchField, 0, [], 'End');
+    assertEquals(-1, tabSearchApp.getSelectedIndex());
+  });
+
+  test('Keyboard navigation abides by item list range boundaries', async () => {
+    const testData = sampleData();
+    await setupTest(testData);
+
+    const numTabs =
+        testData.windows.reduce((total, w) => total + w.tabs.length, 0);
+    const searchField = /** @type {!TabSearchSearchField} */
+        (tabSearchApp.shadowRoot.querySelector("#searchField"));
+
+    keyDownOn(searchField, 0, [], 'ArrowUp');
+    assertEquals(numTabs - 1, tabSearchApp.getSelectedIndex());
+
+    keyDownOn(searchField, 0, [], 'ArrowDown');
+    assertEquals(0, tabSearchApp.getSelectedIndex());
+
+    keyDownOn(searchField, 0, [], 'ArrowDown');
+    assertEquals(1, tabSearchApp.getSelectedIndex());
+
+    keyDownOn(searchField, 0, [], 'ArrowUp');
+    assertEquals(0, tabSearchApp.getSelectedIndex());
+
+    keyDownOn(searchField, 0, [], 'End');
+    assertEquals(numTabs - 1, tabSearchApp.getSelectedIndex());
+
+    keyDownOn(searchField, 0, [], 'Home');
+    assertEquals(0, tabSearchApp.getSelectedIndex());
+  });
+
+  test('Key with modifiers should not affect selected item', async () => {
+    await setupTest(sampleData());
+
+    const searchField = /** @type {!TabSearchSearchField} */
+        (tabSearchApp.shadowRoot.querySelector('#searchField'));
+
+    for (const key of ['ArrowUp', 'ArrowDown', 'Home', 'End']) {
+      keyDownOn(searchField, 0, ['shift'], key);
+      assertEquals(0, tabSearchApp.getSelectedIndex());
+    }
+  });
+
+  test('refresh on tabs changed', async () => {
+    await setupTest(sampleData());
+    verifyTabIds(queryRows(), [1, 5, 6, 2, 3, 4]);
+    testProxy.setProfileTabs({windows: []});
+    testProxy.getCallbackRouterRemote().tabsChanged();
+    await flushTasks();
+    verifyTabIds(queryRows(), []);
+    assertEquals(-1, tabSearchApp.getSelectedIndex());
+  });
+
+  test('On tabs changed, tab item selection preserved or updated', async () => {
+    const testData = sampleData();
+    await setupTest(testData);
+
+    const searchField = /** @type {!TabSearchSearchField} */
+        (tabSearchApp.shadowRoot.querySelector('#searchField'));
+    keyDownOn(searchField, 0, [], 'ArrowDown');
+    assertEquals(1, tabSearchApp.getSelectedIndex());
+
+    testProxy.setProfileTabs({windows: [testData.windows[0]]});
+    testProxy.getCallbackRouterRemote().tabsChanged();
+    await flushTasks();
+    assertEquals(1, tabSearchApp.getSelectedIndex());
+
+    testProxy.setProfileTabs(
+        {windows: [{active: true, tabs: [testData.windows[0].tabs[0]]}]});
+    testProxy.getCallbackRouterRemote().tabsChanged();
+    await flushTasks();
+    assertEquals(0, tabSearchApp.getSelectedIndex());
+  });
+
+  test('refresh on tab updated', async () => {
+    await setupTest(sampleData());
+    verifyTabIds(queryRows(), [1, 5, 6, 2, 3, 4]);
+    let tabSearchItem = /** @type {!HTMLElement} */
+        (tabSearchApp.shadowRoot.querySelector('tab-search-item[id="1"]'));
+    assertEquals('Google', tabSearchItem.data.tab.title);
+    assertEquals('https://www.google.com', tabSearchItem.data.tab.url);
+    const updatedTab = /** @type {!tabSearch.mojom.Tab} */ ({
+      index: 0,
+      tabId: 1,
+      title: 'Example',
+      url: 'https://example.com',
+      lastActiveTimeTicks: { internalValue: 1 },
+    });
+    testProxy.getCallbackRouterRemote().tabUpdated(updatedTab);
+    await flushTasks();
+    // tabIds are not changed after tab updated.
+    verifyTabIds(queryRows(), [1, 5, 6, 2, 3, 4]);
+    tabSearchItem = /** @type {!HTMLElement} */
+        (tabSearchApp.shadowRoot.querySelector('tab-search-item[id="1"]'));
+    assertEquals(updatedTab.title, tabSearchItem.data.tab.title);
+    assertEquals(updatedTab.url, tabSearchItem.data.tab.url);
+    assertEquals('example.com', tabSearchItem.data.hostname);
+  });
+
+  test('Verify initial tab render time is logged correctly', async () => {
+    // |metricNames| tracks thow many times recordTime() has been called for
+    // a metric.
+    const metricNames = {};
+    chrome.metricsPrivate.recordTime = (...args) => {
+      if ( args[0] in metricNames ) {
+        metricNames[args[0]] += 1;
+      } else {
+        metricNames[args[0]] = 1;
+      }
+    };
+
+    await setupTest(sampleData());
+    await waitAfterNextRender(tabSearchApp);
+
+    // Make sure that tab data has been recieved.
+    verifyTabIds(queryRows(), [ 1, 5, 6, 2, 3, 4 ]);
+
+    // Ensure that |chrome.metricsPrivate.recordTime()| has been called
+    // once for InitialTabsRenderTime after initial tab data has been
+    // recieved.
+    assertEquals(1, metricNames['Tabs.TabSearch.WebUI.InitialTabsRenderTime']);
+
+    // Force a change to filtered tab data that would result in a
+    // re-render.
+    const searchField = /** @type {!TabSearchSearchField} */
+        (tabSearchApp.shadowRoot.querySelector('#searchField'));
+    searchField.setValue('bing');
+    await flushTasks();
+    await waitAfterNextRender(tabSearchApp);
+    verifyTabIds(queryRows(), [ 2 ]);
+
+    // |chrome.metricsPrivate.recordTime()| should still have only been
+    // called once for InitialTabsRenderTime.
+    assertEquals(1, metricNames['Tabs.TabSearch.WebUI.InitialTabsRenderTime']);
+  });
+
+  test('Verify tab switch is logged correctly', async () => {
+    await setupTest(sampleData());
+    // Make sure that tab data has been recieved.
+    verifyTabIds(queryRows(), [ 1, 5, 6, 2, 3, 4 ]);
+
+    // Click the first element with tabId 1.
+    let tabSearchItem = /** @type {!HTMLElement} */
+        (tabSearchApp.shadowRoot.querySelector('tab-search-item[id="1"]'));
+    tabSearchItem.click();
+
+    // Assert switchToTab() was called appropriately for an unfiltered tab list.
+    await testProxy.whenCalled('switchToTab')
+        .then(([ tabInfo, withSearch ]) => {
+          assertEquals(1, tabInfo.tabId);
+          assertFalse(withSearch);
+        });
+
+    // Force a change to filtered tab data that would result in a
+    // re-render.
+    const searchField = /** @type {!TabSearchSearchField} */
+        (tabSearchApp.shadowRoot.querySelector('#searchField'));
+    searchField.setValue('bing');
+    await flushTasks();
+    verifyTabIds(queryRows(), [ 2 ]);
+
+    testProxy.reset();
+    // Click the only remaining element with tabId 2.
+    tabSearchItem = /** @type {!HTMLElement} */
+        (tabSearchApp.shadowRoot.querySelector('tab-search-item[id="2"]'));
+    tabSearchItem.click();
+
+    // Assert switchToTab() was called appropriately for a tab list fitlered by
+    // the search query.
+    await testProxy.whenCalled('switchToTab')
+        .then(([ tabInfo, withSearch ]) => {
+          assertEquals(2, tabInfo.tabId);
+          assertTrue(withSearch);
+        });
+  });
+
+  test('Verify showUI() is called correctly', async () => {
+    assertEquals(0, testProxy.getCallCount('showUI'));
+
+    await setupTest(sampleData());
+    await waitAfterNextRender(tabSearchApp);
+
+    // Make sure that tab data has been received.
+    verifyTabIds(queryRows(), [ 1, 5, 6, 2, 3, 4 ]);
+
+    // Ensure that showUI() has been called once after initial data has been
+    // rendered.
+    assertEquals(1, testProxy.getCallCount('showUI'));
+
+    // Force a change to filtered tab data that would result in a
+    // re-render.
+    const searchField = /** @type {!TabSearchSearchField} */
+        (tabSearchApp.shadowRoot.querySelector('#searchField'));
+    searchField.setValue('bing');
+    await flushTasks();
+    await waitAfterNextRender(tabSearchApp);
+    verifyTabIds(queryRows(), [ 2 ]);
+
+    // |showUI()| should still have only been called once.
+    assertEquals(1, testProxy.getCallCount('showUI'));
+  });
+
+  test('Submit feeedback footer disabled by default', async () => {
+    await setupTest(sampleData());
+    assertTrue(
+        tabSearchApp.shadowRoot.querySelector('#feedback-footer') === null);
+  });
+
+  test('Click on Sumit Feedback footer triggers action', async () => {
+    await setupTest(sampleData(), {'submitFeedbackEnabled': true});
+
+    const feedbackButton = /** @type {!HTMLButtonElement} */
+        (tabSearchApp.shadowRoot.querySelector('#feedback-footer'));
+    feedbackButton.click();
+    await testProxy.whenCalled('showFeedbackPage');
+  });
+
+  test('Sort by most recent active tabs', async () => {
+    const tabs = [
+    {
+      index: 0,
+      tabId: 1,
+      title: 'Google',
+      url: 'https://www.google.com',
+      lastActiveTimeTicks: { internalValue: 2 },
+    },
+    {
+      index: 1,
+      tabId: 2,
+      title: 'Bing',
+      url: 'https://www.bing.com',
+      lastActiveTimeTicks: { internalValue: 4 },
+    },
+    {
+      index: 2,
+      tabId: 3,
+      title: 'Yahoo',
+      url: 'https://www.yahoo.com',
+      lastActiveTimeTicks: { internalValue: 3 },
+    }];
+
+    await setupTest({windows: [{active: true, tabs}]});
+    verifyTabIds(queryRows(), [2, 3, 1]);
+  });
+
+  test('Escape key triggers close UI API', async () => {
+    await setupTest(sampleData(), {'submitFeedbackEnabled': true});
+
+    const elements = [
+      tabSearchApp.shadowRoot.querySelector('#searchField'),
+      tabSearchApp.shadowRoot.querySelector('#tabs'),
+      tabSearchApp.shadowRoot.querySelector('tab-search-item'),
+      tabSearchApp.shadowRoot.querySelector('#feedback-footer'),
+    ];
+
+    for (const element of elements) {
+      keyDownOn(element, 0, [], 'Escape');
+    }
+
+    assertEquals(4, testProxy.getCallCount('closeUI'));
+  });
+
+  test('Scrollbar updates show previous and following list items', async () => {
+    await setupTest(generateSampleDataFromSiteNames(sampleSiteNames()));
+
+    const tabsDiv = /** @type {!HTMLElement} */
+        (tabSearchApp.shadowRoot.querySelector('#tabs'));
+    // Assert that the tabs are in a overflowing state.
+    assertGT(tabsDiv.scrollHeight, tabsDiv.clientHeight);
+
+    const tabItems = /** @type {!NodeList<!HTMLElement>}*/ (queryRows());
+    const searchField = /** @type {!TabSearchSearchField} */
+        (tabSearchApp.shadowRoot.querySelector('#searchField'));
+
+    for (let i = 0; i < tabItems.length; i++) {
+      keyDownOn(searchField, 0, [], 'ArrowDown');
+      const selectedIndex = ((i + 1) % tabItems.length);
+
+      assertEquals(selectedIndex, tabSearchApp.getSelectedIndex());
+      assertTabItemAndNeighborsInViewBounds(tabsDiv, tabItems, selectedIndex);
+    }
+
+    keyDownOn(searchField, 0, [], 'End');
+    assertTabItemInViewBounds(tabsDiv, tabItems[tabItems.length - 1]);
+
+    for (let i = tabItems.length - 1; i >= 0; i--) {
+      keyDownOn(searchField, 0, [], 'ArrowUp');
+      const selectedIndex = (i - 1 + tabItems.length) % tabItems.length;
+
+      assertEquals(selectedIndex, tabSearchApp.getSelectedIndex());
+      assertTabItemAndNeighborsInViewBounds(tabsDiv, tabItems, selectedIndex);
+    }
+
+    keyDownOn(searchField, 0, [], 'Home');
+    assertTabItemInViewBounds(tabsDiv, tabItems[0]);
+  });
+});
diff --git a/chrome/browser/resources/tab_search_merge/test/tab_search_browsertest.js b/chrome/browser/resources/tab_search_merge/test/tab_search_browsertest.js
new file mode 100644
index 0000000..44a560e
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/test/tab_search_browsertest.js
@@ -0,0 +1,69 @@
+// 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.
+
+/** @fileoverview Test suite for the WebUI tab search. */
+
+GEN_INCLUDE(['//chrome/test/data/webui/polymer_browser_test_base.js']);
+GEN('#include "chrome/browser/ui/ui_features.h"');
+GEN('#include "content/public/test/browser_test.h"');
+GEN('#include "services/network/public/cpp/features.h"');
+
+class TabSearchBrowserTest extends PolymerTest {
+  /** @override */
+  get browsePreload() {
+    throw 'this is abstract and should be overriden by subclasses';
+  }
+
+  get extraLibraries() {
+    return [
+      '//third_party/mocha/mocha.js',
+      '//chrome/test/data/webui/mocha_adapter.js',
+    ];
+  }
+
+  /** @override */
+  get featureList() {
+    return {
+      enabled: [
+        'features::kTabSearch',
+      ]
+    };
+  }
+}
+
+// eslint-disable-next-line no-var
+var TabSearchAppTest = class extends TabSearchBrowserTest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://tab-search/test_loader.html?module=tab_search/test/tab_search_app_test.js';
+  }
+};
+
+TEST_F('TabSearchAppTest', 'All', function() {
+  mocha.run();
+});
+
+// eslint-disable-next-line no-var
+var FuzzySearchTest = class extends TabSearchBrowserTest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://tab-search/test_loader.html?module=tab_search/test/fuzzy_search_test.js';
+  }
+};
+
+TEST_F('FuzzySearchTest', 'All', function() {
+  mocha.run();
+});
+
+// eslint-disable-next-line no-var
+var TabSearchItemTest = class extends TabSearchBrowserTest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://tab-search/test_loader.html?module=tab_search/test/tab_search_item_test.js';
+  }
+};
+
+TEST_F('TabSearchItemTest', 'All', function() {
+  mocha.run();
+});
\ No newline at end of file
diff --git a/chrome/browser/resources/tab_search_merge/test/tab_search_interactive_ui_tests.js b/chrome/browser/resources/tab_search_merge/test/tab_search_interactive_ui_tests.js
new file mode 100644
index 0000000..8bcca59
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/test/tab_search_interactive_ui_tests.js
@@ -0,0 +1,39 @@
+// 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.
+
+/** @fileoverview Test suite for the WebUI tab search. */
+
+GEN_INCLUDE(['//chrome/test/data/webui/polymer_interactive_ui_test.js']);
+
+GEN('#include "content/public/test/browser_test.h"');
+GEN('#include "chrome/browser/ui/ui_features.h"');
+GEN('#include "services/network/public/cpp/features.h"');
+
+// eslint-disable-next-line no-var
+var TabSearchInteractiveUITest = class extends PolymerInteractiveUITest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://tab-search/test_loader.html?module=tab_search/test/tab_search_app_focus_test.js';
+  }
+
+  get extraLibraries() {
+    return [
+      '//third_party/mocha/mocha.js',
+      '//chrome/test/data/webui/mocha_adapter.js',
+    ];
+  }
+
+  /** @override */
+  get featureList() {
+    return {
+      enabled: [
+        'features::kTabSearch',
+      ]
+    };
+  }
+}
+
+TEST_F('TabSearchInteractiveUITest', 'All', function() {
+  mocha.run();
+});
diff --git a/chrome/browser/resources/tab_search_merge/test/tab_search_item_test.js b/chrome/browser/resources/tab_search_merge/test/tab_search_item_test.js
new file mode 100644
index 0000000..8e80890
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/test/tab_search_item_test.js
@@ -0,0 +1,72 @@
+// 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.
+
+import {TabData} from 'chrome://tab-search/tab_data.js';
+import {TabSearchItem} from 'chrome://tab-search/tab_search_item.js';
+
+import {assertDeepEquals} from '../../chai_assert.js';
+import {flushTasks} from '../../test_util.m.js';
+
+suite('TabSearchItemTest', () => {
+  /**
+   * @param {string} text
+   * @param {?Array<{start:number, length:number}>} highlightRanges
+   * @param {!Array<string>} expected
+   */
+  async function assertTabSearchItemHighlights(
+      text, highlightRanges, expected) {
+    const tabSearchItem = /** @type {!TabSearchItem} */ (
+        document.createElement('tab-search-item'));
+    const data = /** @type {!TabData} */ ({
+      titleHighlightRanges: highlightRanges,
+      hostname: text,
+      hostnameHighlightRanges: highlightRanges,
+      tab: {
+        active: true,
+        index: 0,
+        isDefaultFavicon: true,
+        lastActiveTimeTicks: {internalValue: 0},
+        pinned: false,
+        showIcon: true,
+        tabId: 0,
+        url: 'https://example.com',
+        title: text,
+      }
+    });
+    tabSearchItem.data = data;
+    document.body.innerHTML = '';
+    document.body.appendChild(tabSearchItem);
+    await flushTasks();
+    assertHighlight(
+        /** @type {!HTMLElement} */ (tabSearchItem.$['primaryText']), expected);
+    assertHighlight(
+        /** @type {!HTMLElement} */ (tabSearchItem.$['secondaryText']),
+        expected);
+  }
+
+  /**
+   * @param {!HTMLElement} node
+   * @param {!Array<string>} expected
+   */
+  function assertHighlight(node, expected) {
+    assertDeepEquals(
+        expected,
+        [].slice.call(node.querySelectorAll('.search-highlight-hit'))
+            .map(e => e ? e.textContent : ''));
+  }
+
+  test('highlight', async () => {
+    const text = 'Make work better';
+    await assertTabSearchItemHighlights(text, null, []);
+    await assertTabSearchItemHighlights(
+        text, [{start: 0, length: text.length}], ['Make work better']);
+    await assertTabSearchItemHighlights(
+        text, [{start: 0, length: 4}], ['Make']);
+    await assertTabSearchItemHighlights(
+        text, [{start: 0, length: 4}, {start: 10, length: 6}],
+        ['Make', 'better']);
+    await assertTabSearchItemHighlights(
+        text, [{start: 5, length: 4}], ['work']);
+  });
+});
\ No newline at end of file
diff --git a/chrome/browser/resources/tab_search_merge/test/tab_search_test_data.js b/chrome/browser/resources/tab_search_merge/test/tab_search_test_data.js
new file mode 100644
index 0000000..01c3575
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/test/tab_search_test_data.js
@@ -0,0 +1,90 @@
+// 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.
+
+export function sampleData() {
+  const profileTabs = {
+    windows: [
+      {
+        active: true,
+        tabs: [
+          {
+            index: 0,
+            tabId: 1,
+            title: 'Google',
+            url: 'https://www.google.com',
+          },
+          {
+            index: 1,
+            tabId: 5,
+            title: 'Amazon',
+            url: 'https://www.amazon.com',
+          },
+          {
+            index: 2,
+            tabId: 6,
+            title: 'Apple',
+            url: 'https://www.apple.com',
+          },
+        ],
+      },
+      {
+        active: false,
+        tabs: [
+          {
+            index: 0,
+            tabId: 2,
+            title: 'Bing',
+            url: 'https://www.bing.com/',
+          },
+          {
+            index: 1,
+            tabId: 3,
+            title: 'Yahoo',
+            url: 'https://www.yahoo.com',
+          },
+          {
+            index: 2,
+            tabId: 4,
+            title: 'Apple',
+            url: 'https://www.apple.com/',
+          },
+        ],
+      }
+    ]
+  };
+
+  return profileTabs;
+}
+
+export function sampleSiteNames() {
+  return [
+    'Google',
+    'Amazon',
+    'Apple',
+    'Bing',
+    'Yahoo',
+    'PayPal',
+    'Square',
+    'Youtube',
+    'Facebook',
+    'Twitter',
+  ];
+}
+
+/**
+ * Generates profile data for a window with a series of tabs.
+ * @param {!Array} siteNames
+ */
+export function generateSampleDataFromSiteNames(siteNames) {
+  const tabs = siteNames.map((siteName, i) => {
+    return {
+      index: i,
+      tabId: i + 1,
+      title: siteName,
+      url: 'https://www.' + siteName.toLowerCase() + '.com',
+    };
+  });
+
+  return {windows: [{active: true, tabs: tabs}]};
+}
diff --git a/chrome/browser/resources/tab_search_merge/test/tab_search_test_helper.js b/chrome/browser/resources/tab_search_merge/test/tab_search_test_helper.js
new file mode 100644
index 0000000..a453f27
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/test/tab_search_test_helper.js
@@ -0,0 +1,57 @@
+// 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.
+
+import {assertGE, assertLE} from '../../chai_assert.js';
+
+/**
+ * Override the scrollIntoView function and parameters of the given class to
+ * avoid smooth scroll animations that delay the scrollTop property updates.
+ * @param {!Object} klass
+ */
+export function disableScrollIntoViewAnimations(klass) {
+  const originalScrollFunc = klass.prototype.scrollIntoView;
+  klass.prototype.scrollIntoView = function(options) {
+    const args = [];
+    if (typeof options === 'object' && options !== null) {
+      let noAnimationOptions = Object.assign({}, options);
+      delete noAnimationOptions.behavior;
+
+      args.push(noAnimationOptions);
+    }
+    originalScrollFunc.apply(this, args);
+  };
+}
+
+/**
+ * Assert that the tabItem HTML element is fully visible within the current
+ * scroll view.
+ * @param {!HTMLElement} tabsDiv
+ * @param {!HTMLElement} tabItem
+ */
+export function assertTabItemInViewBounds(tabsDiv, tabItem) {
+  assertGE(tabItem.offsetTop, tabsDiv.scrollTop);
+
+  assertLE(
+      tabItem.offsetTop + tabItem.offsetHeight,
+      tabsDiv.scrollTop + tabsDiv.offsetHeight);
+}
+
+/**
+ * @param {!HTMLElement} tabsDiv The HTML element containing a list of tab
+ *     items.
+ * @param {!NodeList<!HTMLElement>} tabItems A list of tab items.
+ * @param {number} index The tab item's index in the list of tab items.
+ */
+export function assertTabItemAndNeighborsInViewBounds(
+    tabsDiv, tabItems, index) {
+  if (index > 0) {
+    assertTabItemInViewBounds(tabsDiv, tabItems[index - 1]);
+  }
+
+  assertTabItemInViewBounds(tabsDiv, tabItems[index]);
+
+  if (index < tabItems.length - 1) {
+    assertTabItemInViewBounds(tabsDiv, tabItems[index + 1]);
+  }
+}
diff --git a/chrome/browser/resources/tab_search_merge/test/test_tab_search_api_proxy.js b/chrome/browser/resources/tab_search_merge/test/test_tab_search_api_proxy.js
new file mode 100644
index 0000000..5d30c2fa9
--- /dev/null
+++ b/chrome/browser/resources/tab_search_merge/test/test_tab_search_api_proxy.js
@@ -0,0 +1,76 @@
+// 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.
+
+import {TabSearchApiProxy} from 'chrome://tab-search/tab_search_api_proxy.js';
+import {TestBrowserProxy} from '../../test_browser_proxy.m.js';
+
+/** @implements {TabSearchApiProxy} */
+export class TestTabSearchApiProxy extends TestBrowserProxy {
+  constructor() {
+    super([
+      'closeTab',
+      'getProfileTabs',
+      'showFeedbackPage',
+      'switchToTab',
+      'showUI',
+      'closeUI',
+    ]);
+
+    /** @type {!tabSearch.mojom.PageCallbackRouter} */
+    this.callbackRouter = new tabSearch.mojom.PageCallbackRouter();
+
+    /** @type {!tabSearch.mojom.PageRemote} */
+    this.callbackRouterRemote =
+        this.callbackRouter.$.bindNewPipeAndPassRemote();
+
+    /** @private {tabSearch.mojom.ProfileTabs} */
+    this.profileTabs_;
+  }
+
+  /** @override */
+  closeTab(tabId) {
+    this.methodCalled('closeTab', tabId);
+  }
+
+  /** @override */
+  getProfileTabs() {
+    this.methodCalled('getProfileTabs');
+    return Promise.resolve({profileTabs: this.profileTabs_});
+  }
+
+  /** @override */
+  showFeedbackPage() {
+    this.methodCalled('showFeedbackPage');
+  }
+
+  /** @override */
+  switchToTab(tabInfo, withSearch) {
+    this.methodCalled('switchToTab', [ tabInfo, withSearch ]);
+  }
+
+  /** @override */
+  showUI() {
+    this.methodCalled('showUI');
+  }
+
+  /** @override */
+  closeUI() {
+    this.methodCalled('closeUI');
+  }
+
+  /** @override */
+  getCallbackRouter() {
+    return this.callbackRouter;
+  }
+
+  /** return {!tabSearch.mojom.PageRemote} */
+  getCallbackRouterRemote() {
+    return this.callbackRouterRemote;
+  }
+
+  /** @param {tabSearch.mojom.ProfileTabs} profileTabs */
+  setProfileTabs(profileTabs) {
+    this.profileTabs_ = profileTabs;
+  }
+}
diff --git a/chrome/browser/resources/usb_internals/BUILD.gn b/chrome/browser/resources/usb_internals/BUILD.gn
index 30f5807..dc93eac 100644
--- a/chrome/browser/resources/usb_internals/BUILD.gn
+++ b/chrome/browser/resources/usb_internals/BUILD.gn
@@ -4,19 +4,21 @@
 
 import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/grit/grit_rule.gni")
+import("//tools/polymer/html_to_js.gni")
 
 js_type_check("closure_compile") {
   deps = [
+    ":app",
     ":descriptor_panel",
     ":devices_page",
-    ":usb_internals",
   ]
 }
 
-js_library("usb_internals") {
+js_library("app") {
   deps = [
     ":devices_page",
     "//chrome/browser/ui/webui/usb_internals:mojo_bindings_js_library_for_compile",
+    "//ui/webui/resources/js:assert",
     "//ui/webui/resources/js:cr",
     "//ui/webui/resources/js:util",
     "//ui/webui/resources/js/cr/ui:tabs",
@@ -28,6 +30,7 @@
   deps = [
     ":descriptor_panel",
     "//chrome/browser/ui/webui/usb_internals:mojo_bindings_js_library_for_compile",
+    "//ui/webui/resources/js:assert",
     "//ui/webui/resources/js:cr",
   ]
 }
@@ -50,5 +53,12 @@
     "-E",
     "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
   ]
-  deps = [ "//chrome/browser/ui/webui/usb_internals:mojo_bindings_js" ]
+  deps = [
+    ":web_components",
+    "//chrome/browser/ui/webui/usb_internals:mojo_bindings_js",
+  ]
+}
+
+html_to_js("web_components") {
+  js_files = [ "app.js" ]
 }
diff --git a/chrome/browser/resources/usb_internals/app.html b/chrome/browser/resources/usb_internals/app.html
new file mode 100644
index 0000000..b663026
--- /dev/null
+++ b/chrome/browser/resources/usb_internals/app.html
@@ -0,0 +1,219 @@
+<link rel="stylesheet" href="chrome://resources/css/tabs.css">
+<link rel="stylesheet" href="chrome://resources/css/tree.css">
+<link rel="stylesheet" href="usb_internals.css">
+<tabbox>
+  <tabs>
+    <tab>Test Devices</tab>
+    <tab>Devices</tab>
+  </tabs>
+  <tabpanels>
+    <tabpanel>
+      <!-- Test Devices -->
+      <h2>Test Devices</h2>
+      <p>
+        <table class="styled-table">
+          <thead>
+            <tr>
+              <th>Name</th>
+              <th>Serial number</th>
+              <th>Landing page</th>
+              <th>
+            </tr>
+          </thead>
+          <tbody id="test-device-list">
+          </tbody>
+
+          <template id="test-device-row">
+            <tr>
+              <td></td>
+              <td></td>
+              <td></td>
+              <td><button>Remove</button></td>
+            </tr>
+          </template>
+
+        </table>
+      </p>
+      <div class="page-section">
+        <strong>Add a test device:</strong>
+        <form id="add-test-device-form" action="">
+          <p>
+            <label>
+              Name: <input id="test-device-name" type="text" size="40">
+            </label>
+          </p>
+          <p>
+            <label>
+              Serial number:
+              <input id="test-device-serial" type="text" size="40">
+            </label>
+          </p>
+          <p>
+            <label>
+              Landing page:
+              <input id="test-device-landing-page" type="text" size="40">
+            </label>
+          </p>
+          <button type="submit">Add</button>
+          <span id="add-test-device-result"></span>
+        </form>
+      </div>
+    </tabpanel>
+
+    <tabpanel>
+      <!-- Devices -->
+      <h2>Devices</h2>
+      <table class="styled-table">
+        <thead>
+          <tr>
+            <th>Bus Number</th>
+            <th>Port Number</th>
+            <th>Vendor Id</th>
+            <th>Product Id</th>
+            <th>Manufacturer Name</th>
+            <th>Product Name</th>
+            <th>Serial Number</th>
+            <th>
+          </tr>
+        </thead>
+        <tbody id="device-list"></tbody>
+
+        <template id="device-row">
+          <tr>
+            <td></td>
+            <td></td>
+            <td></td>
+            <td></td>
+            <td></td>
+            <td></td>
+            <td></td>
+            <td><button>Inspect</button></td>
+          </tr>
+        </template>
+
+      </table>
+    </tabpanel>
+  </tabpanels>
+</tabbox>
+
+
+<template id="tab-template">
+  <tab></tab>
+</template>
+
+<template id="device-tabpanel-template">
+  <tabpanel>
+    <tree class="tree-view"></tree>
+    <div class="descriptor-button">
+      <button class="device-descriptor-button">Get Device Descriptor</button>
+    </div>
+    <div class="device-descriptor-panel" hidden></div>
+    <div class="descriptor-button">
+      <button class="configuration-descriptor-button">
+        Get Configuration Descriptor
+      </button>
+    </div>
+    <div class="configuration-descriptor-panel" hidden></div>
+    <div class="descriptor-button">
+      <button class="string-descriptor-button">Get String Descriptor</button>
+    </div>
+    <div class="string-descriptor-panel" hidden>
+      String Descriptor Index:
+      <input id="index-input" type="number" min="1" list="indexes">
+      <datalist id="indexes"></datalist>
+      Language Code:
+      <input id="language-code-input" list="languages">
+      <datalist id="languages"></datalist>
+      <button>GET</button>
+    </div>
+    <div class="descriptor-button">
+      <button class="bos-descriptor-button">
+        Get WebUSB & Microsoft OS 2.0 Descriptors
+      </button>
+    </div>
+    <div class="bos-descriptor-panel" hidden></div>
+    <div class="descriptor-button">
+      <button class="testing-tool-button">Testing Tool Panel</button>
+    </div>
+    <div class="testing-tool-panel" hidden>
+      <select id="input-type">
+        <option label="Decimal with Dropdown Menu"></option>
+        <option label="Hex Bytes"></option>
+      </select>
+      <table class="styled-table">
+        <thead>
+          <tr>
+            <th>bmRequestType</th>
+            <th>bRequest</th>
+            <th>wValue</th>
+            <th>wIndex</th>
+            <th>wLength</th>
+          </tr>
+        </thead>
+        <tbody id="testing-tool">
+          <tr>
+            <td>
+              <select id="transfer-direction">
+                <option label="Host-to-Device" value="Host-to-Device">
+                </option>
+                <option label="Device-to-Host" value="Device-to-Host">
+                </option>
+              </select>
+              <select id="transfer-type">
+                <option label="Standard" value="STANDARD"></option>
+                <option label="Class" value="CLASS"></option>
+                <option label="Vendor" value="VENDOR"></option>
+              </select>
+              <select id="transfer-recipient">
+                <option label="Device" value="DEVICE"></option>
+                <option label="Interface" value="INTERFACE"></option>
+                <option label="Endpoint" value="ENDPOINT"></option>
+                <option label="Other" value="OTHER"></option>
+              </select>
+            </td>
+            <td><input id="query-request" type="number" placeholder="0"></td>
+            <td><input id="query-value" type="number" placeholder="0"></td>
+            <td><input id="query-index" type="number" placeholder="0"></td>
+            <td><input id="query-length" type="number" placeholder="0"></td>
+            <td><button>Send</button></td>
+          </tr>
+          <tr hidden>
+            <td>0x<input id="query-request-type" placeholder="00"></td>
+            <td>0x<input id="query-request" placeholder="00"></td>
+            <td>0x<input id="query-value" placeholder="0000"></td>
+            <td>0x<input id="query-index" placeholder="0000"></td>
+            <td>0x<input id="query-length" placeholder="0000"></td>
+            <td><button>Send</button></td>
+          </tr>
+        </tbody>
+      </table>
+      <div id="data-input-area">
+        Data (in Hex):
+        <textarea cols="31"></textarea>
+      </div>
+    </div>
+  </tabpanel>
+</template>
+
+<template id="descriptor-panel-template">
+  <descriptorpanel>
+    <tree class="raw-data-tree-view"></tree>
+    <div class="raw-data-byte-view"></div>
+  </descriptorpanel>
+</template>
+
+<template id="raw-data-byte-container-template">
+  <div></div>
+</template>
+
+<template id="raw-data-byte-template">
+  <span></span>
+</template>
+
+<template id="raw-data-tree-button">
+  <button>GET</button>
+</template>
+
+<template id="descriptor-panel-title">
+  <descriptorpaneltitle></descriptorpaneltitle>
+</template>
diff --git a/chrome/browser/resources/usb_internals/usb_internals.js b/chrome/browser/resources/usb_internals/app.js
similarity index 65%
rename from chrome/browser/resources/usb_internals/usb_internals.js
rename to chrome/browser/resources/usb_internals/app.js
index e9d42969..06a94c2 100644
--- a/chrome/browser/resources/usb_internals/usb_internals.js
+++ b/chrome/browser/resources/usb_internals/app.js
@@ -5,11 +5,34 @@
 /**
  * Javascript for usb_internals.html, served from chrome://usb-internals/.
  */
-cr.define('usb_internals', function() {
-  class UsbInternals {
-    constructor() {}
 
-    async initializeViews() {
+window.setupFn = window.setupFn || function() {
+  return Promise.resolve();
+};
+
+  class UsbInternalsAppElement extends HTMLElement {
+    static get template() {
+      return `{__html_template__}`;
+    }
+
+    constructor() {
+      super();
+
+      this.attachShadow({mode: 'open'});
+      const template = document.createElement('template');
+      template.innerHTML = this.constructor.template || '';
+      this.shadowRoot.appendChild(template.content.cloneNode(true));
+    }
+
+    /**
+     * @param {string} query
+     * @return {?Element}
+     */
+    $(query) {
+      return this.shadowRoot.querySelector(query);
+    }
+
+    async connectedCallback() {
       // window.setupFn() provides a hook for the test suite to perform setup
       // actions after the page is loaded but before any script is run.
       await window.setupFn();
@@ -24,28 +47,29 @@
           usbManager.$.bindNewPipeAndPassReceiver());
 
       /** @private {devices_page.DevicesPage} */
-      this.devicesPage_ = new devices_page.DevicesPage(usbManager);
+      this.devicesPage_ = new devices_page.DevicesPage(
+          usbManager, assert(this.shadowRoot));
 
       /** @private {device.mojom.UsbDeviceManagerTestRemote} */
       this.usbManagerTest_ = new device.mojom.UsbDeviceManagerTestRemote;
       await pageHandler.bindTestInterface(
           this.usbManagerTest_.$.bindNewPipeAndPassReceiver());
 
-      $('add-test-device-form').addEventListener('submit', (event) => {
+      this.$('#add-test-device-form').addEventListener('submit', (event) => {
         this.addTestDevice(event);
       });
       this.refreshTestDeviceList();
 
-      cr.ui.decorate('tabbox', cr.ui.TabBox);
+      cr.ui.decorate(assert(this.$('tabbox')), cr.ui.TabBox);
     }
 
     async refreshTestDeviceList() {
       const response = await this.usbManagerTest_.getTestDevices();
 
-      const tableBody = $('test-device-list');
+      const tableBody = this.$('#test-device-list');
       tableBody.innerHTML = trustedTypes.emptyHTML;
 
-      const rowTemplate = document.querySelector('#test-device-row');
+      const rowTemplate = this.$('#test-device-row');
       const td = rowTemplate.content.querySelectorAll('td');
 
       for (const device of response.devices) {
@@ -69,28 +93,16 @@
       event.preventDefault();
 
       const response = await this.usbManagerTest_.addDeviceForTesting(
-          $('test-device-name').value, $('test-device-serial').value,
-          $('test-device-landing-page').value);
+          this.$('#test-device-name').value, this.$('#test-device-serial').value,
+          this.$('#test-device-landing-page').value);
       if (response.success) {
         this.refreshTestDeviceList();
       }
 
-      $('add-test-device-result').textContent = response.message;
-      $('add-test-device-result').className =
+      this.$('#add-test-device-result').textContent = response.message;
+      this.$('#add-test-device-result').className =
           response.success ? 'action-success' : 'action-failure';
     }
   }
+  customElements.define('usb-internals-app', UsbInternalsAppElement);
 
-  return {
-    UsbInternals,
-  };
-});
-
-window.setupFn = window.setupFn || function() {
-  return Promise.resolve();
-};
-
-document.addEventListener('DOMContentLoaded', () => {
-  const usbInternalsPage = new usb_internals.UsbInternals();
-  usbInternalsPage.initializeViews();
-});
diff --git a/chrome/browser/resources/usb_internals/descriptor_panel.js b/chrome/browser/resources/usb_internals/descriptor_panel.js
index 6c0bfa8..08ca109 100644
--- a/chrome/browser/resources/usb_internals/descriptor_panel.js
+++ b/chrome/browser/resources/usb_internals/descriptor_panel.js
@@ -166,7 +166,9 @@
           this.stringDescriptorPanel_.stringDescriptorIndexes.add(index);
         }
 
-        const buttonTemplate = queryRequiredElement('#raw-data-tree-button');
+        const buttonTemplate = queryRequiredElement(
+            '#raw-data-tree-button',
+            /** @type {!DocumentFragment} */ (this.rootElement_.getRootNode()));
         const button = document.importNode(buttonTemplate.content, true)
                            .querySelector('button');
         item.labelElement.appendChild(button);
@@ -200,7 +202,9 @@
     renderUrlDescriptorIndexItem_(rawData, offset, item, fieldLabel) {
       const index = rawData[offset];
       if (index > 0) {
-        const buttonTemplate = queryRequiredElement('#raw-data-tree-button');
+        const buttonTemplate = queryRequiredElement(
+            '#raw-data-tree-button',
+            /** @type {!DocumentFragment} */ (this.rootElement_.getRootNode()));
         const button = document.importNode(buttonTemplate.content, true)
                            .querySelector('button');
         item.labelElement.appendChild(button);
@@ -238,7 +242,9 @@
       const msOs20DescriptorSetLength =
           data.getUint16(MS_OS_20_SET_TOTAL_LENGTH_OFFSET, true);
 
-      const buttonTemplate = queryRequiredElement('#raw-data-tree-button');
+      const buttonTemplate = queryRequiredElement(
+          '#raw-data-tree-button',
+          /** @type {!DocumentFragment} */ (this.rootElement_.getRootNode()));
       const button = document.importNode(buttonTemplate.content, true)
                          .querySelector('button');
       item.labelElement.appendChild(button);
@@ -277,7 +283,9 @@
       if (altEnumCode !== 0) {
         const vendorCode = rawData[offset + MS_OS_20_VENDOR_CODE_ITEM_OFFSET];
 
-        const buttonTemplate = queryRequiredElement('#raw-data-tree-button');
+        const buttonTemplate = queryRequiredElement(
+            '#raw-data-tree-button',
+            /** @type {!DocumentFragment} */ (this.rootElement_.getRootNode()));
         const button = document.importNode(buttonTemplate.content, true)
                            .querySelector('button');
         item.labelElement.appendChild(button);
@@ -2648,8 +2656,9 @@
    */
   function addNewDescriptorDisplayElement(
       rootElement, descriptorPanelTitle = undefined) {
-    const descriptorPanelTemplate =
-        queryRequiredElement('#descriptor-panel-template');
+    const descriptorPanelTemplate = queryRequiredElement(
+        '#descriptor-panel-template',
+        /** @type {!DocumentFragment} */ (rootElement.getRootNode()));
 
     const descriptorPanelClone = /** @type {!HTMLElement} */
         (document.importNode(descriptorPanelTemplate.content, true));
@@ -2665,8 +2674,9 @@
     rawDataTreeRoot.detail = {payload: {}, children: {}};
 
     if (descriptorPanelTitle) {
-      const descriptorPanelTitleTemplate =
-          queryRequiredElement('#descriptor-panel-title');
+      const descriptorPanelTitleTemplate = queryRequiredElement(
+          '#descriptor-panel-title',
+          /** @type {!DocumentFragment} */ (rootElement.getRootNode()));
       const clone =
           document.importNode(descriptorPanelTitleTemplate.content, true)
               .querySelector('descriptorpaneltitle');
@@ -2857,14 +2867,17 @@
    * @param {!Uint8Array} rawData
    */
   function renderRawDataBytes(rawDataByteElement, rawData) {
-    const rawDataByteContainerTemplate =
-        queryRequiredElement('#raw-data-byte-container-template');
+    const rawDataByteContainerTemplate = queryRequiredElement(
+        '#raw-data-byte-container-template',
+        /** @type {!DocumentFragment} */ (rawDataByteElement.getRootNode()));
     const rawDataByteContainerClone =
         document.importNode(rawDataByteContainerTemplate.content, true);
     const rawDataByteContainerElement =
         rawDataByteContainerClone.querySelector('div');
 
-    const rawDataByteTemplate = queryRequiredElement('#raw-data-byte-template');
+    const rawDataByteTemplate = queryRequiredElement(
+        '#raw-data-byte-template',
+        /** @type {!DocumentFragment} */ (rawDataByteElement.getRootNode()));
     for (const value of rawData) {
       const rawDataByteClone =
           document.importNode(rawDataByteTemplate.content, true);
diff --git a/chrome/browser/resources/usb_internals/devices_page.js b/chrome/browser/resources/usb_internals/devices_page.js
index 16d61da..f3fb293 100644
--- a/chrome/browser/resources/usb_internals/devices_page.js
+++ b/chrome/browser/resources/usb_internals/devices_page.js
@@ -16,10 +16,12 @@
   class DevicesPage {
     /**
      * @param {!device.mojom.UsbDeviceManagerRemote} usbManager
+     * @param {!ShadowRoot} root
      */
-    constructor(usbManager) {
+    constructor(usbManager, root) {
       /** @private {!device.mojom.UsbDeviceManagerRemote} */
       this.usbManager_ = usbManager;
+      this.root = root;
       this.renderDeviceList_();
     }
 
@@ -33,10 +35,10 @@
       /** @type {!Array<!device.mojom.UsbDeviceInfo>} */
       const devices = response.results;
 
-      const tableBody = $('device-list');
+      const tableBody = this.root.querySelector('#device-list');
       tableBody.innerHTML = trustedTypes.emptyHTML;
 
-      const rowTemplate = document.querySelector('#device-row');
+      const rowTemplate = this.root.querySelector('#device-row');
 
       for (const device of devices) {
         /** @type {DocumentFragment|Node} */
@@ -78,10 +80,10 @@
     switchToTab_(device) {
       const tabId = device.guid;
 
-      if (null == $(tabId)) {
-        const devicePage = new DevicePage(this.usbManager_, device);
+      if (null == this.root.getElementById(tabId)) {
+        const devicePage = new DevicePage(this.usbManager_, device, this.root);
       }
-      $(tabId).selected = true;
+      this.root.getElementById(tabId).selected = true;
     }
   }
 
@@ -93,9 +95,11 @@
     /**
      * @param {!device.mojom.UsbDeviceManagerRemote} usbManager
      * @param {!device.mojom.UsbDeviceInfo} device
+     * @param {!ShadowRoot} root
      */
-    constructor(usbManager, device) {
+    constructor(usbManager, device, root) {
       this.usbManager_ = usbManager;
+      this.root = root;
       this.renderTab_(device);
     }
 
@@ -105,9 +109,9 @@
      * @private
      */
     renderTab_(device) {
-      const tabs = queryRequiredElement('tabs');
+      const tabs = queryRequiredElement('tabs', this.root);
 
-      const tabTemplate = queryRequiredElement('#tab-template');
+      const tabTemplate = queryRequiredElement('#tab-template', this.root);
       /** @type {DocumentFragment|Node} */
       const tabClone = document.importNode(tabTemplate.content, true);
 
@@ -122,11 +126,11 @@
       tab.id = device.guid;
 
       tabs.appendChild(tabClone);
-      cr.ui.decorate('tab', cr.ui.Tab);
+      cr.ui.decorate(tab, cr.ui.Tab);
 
-      const tabPanels = queryRequiredElement('tabpanels');
+      const tabPanels = queryRequiredElement('tabpanels', this.root);
       const tabPanelTemplate =
-          queryRequiredElement('#device-tabpanel-template');
+          queryRequiredElement('#device-tabpanel-template', this.root);
       /** @type {DocumentFragment|Node} */
       const tabPanelClone = document.importNode(tabPanelTemplate.content, true);
 
@@ -368,8 +372,8 @@
     const button = queryRequiredElement(`.${panelType}-button`, tabPanel);
     const displayElement =
         queryRequiredElement(`.${panelType}-panel`, tabPanel);
-    const descriptorPanel =
-        new descriptor_panel.DescriptorPanel(usbDevice, displayElement);
+    const descriptorPanel = new descriptor_panel.DescriptorPanel(
+        usbDevice, /** @type {!HTMLElement} */ (displayElement));
     switch (panelType) {
       case 'string-descriptor':
         descriptorPanel.initialStringDescriptorPanel(guid);
diff --git a/chrome/browser/resources/usb_internals/resources.grd b/chrome/browser/resources/usb_internals/resources.grd
index 68f7a92..88f82ed 100644
--- a/chrome/browser/resources/usb_internals/resources.grd
+++ b/chrome/browser/resources/usb_internals/resources.grd
@@ -24,13 +24,14 @@
                flattenhtml="true"
                allowexternalscript="true"
                type="BINDATA" />
-      <include name="IDR_USB_INTERNALS_JS"
-               file="usb_internals.js"
-               type="BINDATA" />
       <include name="IDR_USB_INTERNALS_MOJOM_LITE_JS"
                file="${root_gen_dir}\chrome\browser\ui\webui\usb_internals\usb_internals.mojom-lite.js"
                use_base_dir="false"
                type="BINDATA" />
+      <include name="IDR_USB_INTERNALS_APP_JS"
+               file="${root_gen_dir}\chrome\browser\resources\usb_internals\app.js"
+               use_base_dir="false"
+               type="BINDATA" />
     </includes>
   </release>
 </grit>
diff --git a/chrome/browser/resources/usb_internals/usb_internals.html b/chrome/browser/resources/usb_internals/usb_internals.html
index f709b1255..23f40d9 100644
--- a/chrome/browser/resources/usb_internals/usb_internals.html
+++ b/chrome/browser/resources/usb_internals/usb_internals.html
@@ -5,9 +5,6 @@
   <meta charset="utf-8">
   <title>USB Internals</title>
   <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
-  <link rel="stylesheet" href="chrome://resources/css/tabs.css">
-  <link rel="stylesheet" href="chrome://resources/css/tree.css">
-  <link rel="stylesheet" href="usb_internals.css">
 
   <script src="chrome://resources/js/assert.js"></script>
   <script src="chrome://resources/js/cr.js"></script>
@@ -35,224 +32,8 @@
 </head>
 
 <body>
-  <tabbox>
-    <tabs>
-      <tab>Test Devices</tab>
-      <tab>Devices</tab>
-    </tabs>
-    <tabpanels>
-      <tabpanel>
-        <!-- Test Devices -->
-        <h2>Test Devices</h2>
-        <p>
-          <table class="styled-table">
-            <thead>
-              <tr>
-                <th>Name</th>
-                <th>Serial number</th>
-                <th>Landing page</th>
-                <th>
-              </tr>
-            </thead>
-            <tbody id="test-device-list">
-            </tbody>
-
-            <template id="test-device-row">
-              <tr>
-                <td></td>
-                <td></td>
-                <td></td>
-                <td><button>Remove</button></td>
-              </tr>
-            </template>
-
-          </table>
-        </p>
-        <div class="page-section">
-          <strong>Add a test device:</strong>
-          <form id="add-test-device-form" action="">
-            <p>
-              <label>
-                Name: <input id="test-device-name" type="text" size="40">
-              </label>
-            </p>
-            <p>
-              <label>
-                Serial number:
-                <input id="test-device-serial" type="text" size="40">
-              </label>
-            </p>
-            <p>
-              <label>
-                Landing page:
-                <input id="test-device-landing-page" type="text" size="40">
-              </label>
-            </p>
-            <button type="submit">Add</button>
-            <span id="add-test-device-result"></span>
-          </form>
-        </div>
-      </tabpanel>
-
-      <tabpanel>
-        <!-- Devices -->
-        <h2>Devices</h2>
-        <table class="styled-table">
-          <thead>
-            <tr>
-              <th>Bus Number</th>
-              <th>Port Number</th>
-              <th>Vendor Id</th>
-              <th>Product Id</th>
-              <th>Manufacturer Name</th>
-              <th>Product Name</th>
-              <th>Serial Number</th>
-              <th>
-            </tr>
-          </thead>
-          <tbody id="device-list"></tbody>
-
-          <template id="device-row">
-            <tr>
-              <td></td>
-              <td></td>
-              <td></td>
-              <td></td>
-              <td></td>
-              <td></td>
-              <td></td>
-              <td><button>Inspect</button></td>
-            </tr>
-          </template>
-
-        </table>
-      </tabpanel>
-    </tabpanels>
-  </tabbox>
-
-
-  <template id="tab-template">
-    <tab></tab>
-  </template>
-
-  <template id="device-tabpanel-template">
-    <tabpanel>
-      <tree class="tree-view"></tree>
-      <div class="descriptor-button">
-        <button class="device-descriptor-button">Get Device Descriptor</button>
-      </div>
-      <div class="device-descriptor-panel" hidden></div>
-      <div class="descriptor-button">
-        <button class="configuration-descriptor-button">
-          Get Configuration Descriptor
-        </button>
-      </div>
-      <div class="configuration-descriptor-panel" hidden></div>
-      <div class="descriptor-button">
-        <button class="string-descriptor-button">Get String Descriptor</button>
-      </div>
-      <div class="string-descriptor-panel" hidden>
-        String Descriptor Index:
-        <input id="index-input" type="number" min="1" list="indexes">
-        <datalist id="indexes"></datalist>
-        Language Code:
-        <input id="language-code-input" list="languages">
-        <datalist id="languages"></datalist>
-        <button>GET</button>
-      </div>
-      <div class="descriptor-button">
-        <button class="bos-descriptor-button">
-          Get WebUSB & Microsoft OS 2.0 Descriptors
-        </button>
-      </div>
-      <div class="bos-descriptor-panel" hidden></div>
-      <div class="descriptor-button">
-        <button class="testing-tool-button">Testing Tool Panel</button>
-      </div>
-      <div class="testing-tool-panel" hidden>
-        <select id="input-type">
-          <option label="Decimal with Dropdown Menu"></option>
-          <option label="Hex Bytes"></option>
-        </select>
-        <table class="styled-table">
-          <thead>
-            <tr>
-              <th>bmRequestType</th>
-              <th>bRequest</th>
-              <th>wValue</th>
-              <th>wIndex</th>
-              <th>wLength</th>
-            </tr>
-          </thead>
-          <tbody id="testing-tool">
-            <tr>
-              <td>
-                <select id="transfer-direction">
-                  <option label="Host-to-Device" value="Host-to-Device">
-                  </option>
-                  <option label="Device-to-Host" value="Device-to-Host">
-                  </option>
-                </select>
-                <select id="transfer-type">
-                  <option label="Standard" value="STANDARD"></option>
-                  <option label="Class" value="CLASS"></option>
-                  <option label="Vendor" value="VENDOR"></option>
-                </select>
-                <select id="transfer-recipient">
-                  <option label="Device" value="DEVICE"></option>
-                  <option label="Interface" value="INTERFACE"></option>
-                  <option label="Endpoint" value="ENDPOINT"></option>
-                  <option label="Other" value="OTHER"></option>
-                </select>
-              </td>
-              <td><input id="query-request" type="number" placeholder="0"></td>
-              <td><input id="query-value" type="number" placeholder="0"></td>
-              <td><input id="query-index" type="number" placeholder="0"></td>
-              <td><input id="query-length" type="number" placeholder="0"></td>
-              <td><button>Send</button></td>
-            </tr>
-            <tr hidden>
-              <td>0x<input id="query-request-type" placeholder="00"></td>
-              <td>0x<input id="query-request" placeholder="00"></td>
-              <td>0x<input id="query-value" placeholder="0000"></td>
-              <td>0x<input id="query-index" placeholder="0000"></td>
-              <td>0x<input id="query-length" placeholder="0000"></td>
-              <td><button>Send</button></td>
-            </tr>
-          </tbody>
-        </table>
-        <div id="data-input-area">
-          Data (in Hex):
-          <textarea cols="31"></textarea>
-        </div>
-      </div>
-    </tabpanel>
-  </template>
-
-  <template id="descriptor-panel-template">
-    <descriptorpanel>
-      <tree class="raw-data-tree-view"></tree>
-      <div class="raw-data-byte-view"></div>
-    </descriptorpanel>
-  </template>
-
-  <template id="raw-data-byte-container-template">
-    <div></div>
-  </template>
-
-  <template id="raw-data-byte-template">
-    <span></span>
-  </template>
-
-  <template id="raw-data-tree-button">
-    <button>GET</button>
-  </template>
-
-  <template id="descriptor-panel-title">
-    <descriptorpaneltitle></descriptorpaneltitle>
-  </template>
-
-  <script src="usb_internals.js"></script>
+  <usb-internals-app></usb-internals-app>
+  <script src="app.js"></script>
 </body>
 
 </html>
diff --git a/chrome/browser/resources/webui_js_exception/BUILD.gn b/chrome/browser/resources/webui_js_exception/BUILD.gn
index c62fa2f..75d48c7 100644
--- a/chrome/browser/resources/webui_js_exception/BUILD.gn
+++ b/chrome/browser/resources/webui_js_exception/BUILD.gn
@@ -4,51 +4,52 @@
 
 import("//chrome/browser/resources/optimize_webui.gni")
 import("//third_party/closure_compiler/compile_js.gni")
-import("//tools/grit/grit_rule.gni")
+import("//tools/grit/preprocess_grit.gni")
+import("//ui/webui/resources/tools/generate_grd.gni")
 import("//ui/webui/webui_features.gni")
 
-js_library("webui_js_exception") {
-}
+preprocess_folder = "preprocessed"
+preprocess_manifest = "preprocessed_manifest.json"
 
 if (optimize_webui) {
-  grit("flattened_resources") {
-    source = "webui_js_exception_resources.grd"
-
-    deps = [ ":webui_js_exception" ]
-
-    grit_flags = [
-      "-E",
-      "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
-    ]
-
-    outputs = [
-      "grit/webui_js_exception_resources.h",
-      "grit/webui_js_exception_resources_map.cc",
-      "grit/webui_js_exception_resources_map.h",
-      "webui_js_exception_resources.pak",
-    ]
-    output_dir = "$root_gen_dir/chrome/browser/resources/webui_js_exception"
-  }
-
-  unpak("unpak") {
-    pak_file = "webui_js_exception_resources.pak"
-    out_folder = "unpak"
-    deps = [ ":flattened_resources" ]
-  }
+  build_manifest = "build_manifest.json"
 
   optimize_webui("build") {
     host = "webui_js_exception"
-    input = rebase_path("$target_gen_dir/unpak", root_build_dir)
-    deps = [
-      ":unpak",
-      "//ui/webui/resources:modulize",
-    ]
+    input = rebase_path("$target_gen_dir/$preprocess_folder", root_build_dir)
+    deps = [ ":preprocess" ]
     js_module_in_files = [ "webui_js_exception.js" ]
     js_out_files = [ "webui_js_exception.rollup.js" ]
-    excludes = [ "chrome://resources/js/cr.m.js" ]
+    out_manifest = "$target_gen_dir/$build_manifest"
   }
 }
 
+preprocess_grit("preprocess") {
+  in_folder = "./"
+  out_folder = "$target_gen_dir/$preprocess_folder"
+  out_manifest = "$target_gen_dir/$preprocess_manifest"
+  in_files = [ "webui_js_exception.js" ]
+}
+
+generate_grd("build_grd") {
+  input_files = [ "webui_js_exception.html" ]
+  input_files_base_dir = rebase_path(".", "//")
+  if (optimize_webui) {
+    deps = [ ":build" ]
+    resource_path_rewrites =
+        [ "webui_js_exception.rollup.js|webui_js_exception.js" ]
+    manifest_files = [ "$target_gen_dir/$build_manifest" ]
+  } else {
+    deps = [ ":preprocess" ]
+    manifest_files = [ "$target_gen_dir/$preprocess_manifest" ]
+  }
+  grd_prefix = "webui_js_exception"
+  out_grd = "$target_gen_dir/${grd_prefix}_resources.grd"
+}
+
 js_type_check("closure_compile") {
   deps = [ ":webui_js_exception" ]
 }
+
+js_library("webui_js_exception") {
+}
diff --git a/chrome/browser/resources/webui_js_exception/webui_js_exception_resources.grd b/chrome/browser/resources/webui_js_exception/webui_js_exception_resources.grd
deleted file mode 100644
index 9946d94..0000000
--- a/chrome/browser/resources/webui_js_exception/webui_js_exception_resources.grd
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
-  <outputs>
-    <output filename="grit/webui_js_exception_resources.h" type="rc_header">
-      <emit emit_type='prepend'></emit>
-    </output>
-    <output filename="grit/webui_js_exception_resources_map.cc"
-            type="resource_file_map_source" />
-    <output filename="grit/webui_js_exception_resources_map.h"
-            type="resource_map_header" />
-    <output filename="webui_js_exception_resources.pak" type="data_package" />
-  </outputs>
-  <release seq="1">
-    <structures>
-      <structure name="IDR_WEBUI_JS_EXCEPTION_UI_WEBUI_JS_EXCEPTION_JS"
-          file="webui_js_exception.js" type="chrome_html" compress="false" />
-      <structure name="IDR_WEBUI_JS_EXCEPTION_UI_WEBUI_JS_EXCEPTION_HTML"
-          file="webui_js_exception.html" type="chrome_html" compress="false" />
-    </structures>
-  </release>
-</grit>
diff --git a/chrome/browser/resources/webui_js_exception/webui_js_exception_resources_vulcanized.grd b/chrome/browser/resources/webui_js_exception/webui_js_exception_resources_vulcanized.grd
deleted file mode 100644
index e410c66..0000000
--- a/chrome/browser/resources/webui_js_exception/webui_js_exception_resources_vulcanized.grd
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
-  <outputs>
-    <output filename="grit/webui_js_exception_resources.h" type="rc_header">
-      <emit emit_type='prepend'></emit>
-    </output>
-    <output filename="grit/webui_js_exception_resources_map.cc"
-            type="resource_map_source" />
-    <output filename="grit/webui_js_exception_resources_map.h"
-            type="resource_map_header" />
-    <output filename="webui_js_exception_resources.pak" type="data_package" />
-  </outputs>
-  <release seq="1">
-    <includes>
-      <include name="IDR_WEBUI_JS_EXCEPTION_UI_WEBUI_JS_EXCEPTION_ROLLUP_JS"
-          file="${root_gen_dir}/chrome/browser/resources/webui_js_exception/webui_js_exception.rollup.js"
-          use_base_dir="false" type="BINDATA" />
-      <include name="IDR_WEBUI_JS_EXCEPTION_UI_WEBUI_JS_EXCEPTION_HTML"
-          file="webui_js_exception.html" preprocess="true" type="BINDATA" />
-    </includes>
-  </release>
-</grit>
diff --git a/chrome/browser/search/ntp_features.cc b/chrome/browser/search/ntp_features.cc
index a0b7618..2a95996 100644
--- a/chrome/browser/search/ntp_features.cc
+++ b/chrome/browser/search/ntp_features.cc
@@ -66,6 +66,10 @@
 // If enabled, modules will be shown.
 const base::Feature kModules{"NtpModules", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// If enabled, recipe tasks module will be shown.
+const base::Feature kNtpRecipeTasksModule{"NtpRecipeTasksModule",
+                                          base::FEATURE_DISABLED_BY_DEFAULT};
+
 // If enabled, shopping tasks module will be shown.
 const base::Feature kNtpShoppingTasksModule{"NtpShoppingTasksModule",
                                             base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/search/ntp_features.h b/chrome/browser/search/ntp_features.h
index 6c14d897..553f1c60 100644
--- a/chrome/browser/search/ntp_features.h
+++ b/chrome/browser/search/ntp_features.h
@@ -26,6 +26,7 @@
 extern const base::Feature kWebUI;
 extern const base::Feature kWebUIThemeModeDoodles;
 extern const base::Feature kModules;
+extern const base::Feature kNtpRecipeTasksModule;
 extern const base::Feature kNtpShoppingTasksModule;
 
 extern const base::Feature kSearchSuggestChips;
diff --git a/chrome/browser/search/recipe_tasks/BUILD.gn b/chrome/browser/search/recipe_tasks/BUILD.gn
new file mode 100644
index 0000000..8fbb688
--- /dev/null
+++ b/chrome/browser/search/recipe_tasks/BUILD.gn
@@ -0,0 +1,10 @@
+# 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.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("mojo_bindings") {
+  sources = [ "recipe_tasks.mojom" ]
+  public_deps = [ "//url/mojom:url_mojom_gurl" ]
+}
diff --git a/chrome/browser/search/recipe_tasks/OWNERS b/chrome/browser/search/recipe_tasks/OWNERS
new file mode 100644
index 0000000..08850f4
--- /dev/null
+++ b/chrome/browser/search/recipe_tasks/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/browser/search/recipe_tasks/recipe_tasks.mojom b/chrome/browser/search/recipe_tasks/recipe_tasks.mojom
new file mode 100644
index 0000000..deb05ee
--- /dev/null
+++ b/chrome/browser/search/recipe_tasks/recipe_tasks.mojom
@@ -0,0 +1,54 @@
+// 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.
+
+module recipe_tasks.mojom;
+
+import "url/mojom/url.mojom";
+
+// A recipe of a recipe task.
+struct Recipe {
+  // Human-readable recipe name.
+  string name;
+  // URL to image of the recipe.
+  url.mojom.Url image_url;
+  // Human-readable recipe info.
+  string info;
+  // URL of the recipe target page.
+  url.mojom.Url target_url;
+};
+
+// A related search query.
+struct RelatedSearch {
+  // Text of the search query.
+  string text;
+  // URL of the query target page.
+  url.mojom.Url target_url;
+};
+
+// A recipe search journey that is currently active for the user.
+struct RecipeTask {
+  // Human-readable title.
+  string title;
+  // Human-readable name.
+  string name;
+  // Recipes associated with the task.
+  array<Recipe> recipes;
+  // Searches related to the task.
+  array<RelatedSearch> related_searches;
+};
+
+// Interface for handling requests from the recipe tasks module's JS code.
+// Bound to the NTP WebUI handler.
+interface RecipeTasksHandler {
+  // Returns the primary recipe task if available.
+  GetPrimaryRecipeTask() => (RecipeTask? recipe_task);
+  // Dismisses the task with the given name and remembers that setting.
+  DismissRecipeTask(string task_name);
+  // Restores the task with the given name and remembers that setting.
+  RestoreRecipeTask(string task_name);
+  // Logs that the recipe at position |index| has been clicked.
+  OnRecipeClicked(uint32 index);
+  // Logs that the related search pill at position |index| has been clicked.
+  OnRelatedSearchClicked(uint32 index);
+};
diff --git a/chrome/browser/search/recipe_tasks/recipe_tasks_handler.cc b/chrome/browser/search/recipe_tasks/recipe_tasks_handler.cc
new file mode 100644
index 0000000..1a8429b
--- /dev/null
+++ b/chrome/browser/search/recipe_tasks/recipe_tasks_handler.cc
@@ -0,0 +1,43 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/search/recipe_tasks/recipe_tasks_handler.h"
+
+#include "base/metrics/histogram_functions.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search/recipe_tasks/recipe_tasks_service.h"
+#include "chrome/browser/search/recipe_tasks/recipe_tasks_service_factory.h"
+
+RecipeTasksHandler::RecipeTasksHandler(
+    mojo::PendingReceiver<recipe_tasks::mojom::RecipeTasksHandler>
+        pending_receiver,
+    Profile* profile)
+    : receiver_(this, std::move(pending_receiver)), profile_(profile) {}
+
+RecipeTasksHandler::~RecipeTasksHandler() = default;
+
+void RecipeTasksHandler::GetPrimaryRecipeTask(
+    GetPrimaryRecipeTaskCallback callback) {
+  RecipeTasksServiceFactory::GetForProfile(profile_)->GetPrimaryRecipeTask(
+      std::move(callback));
+}
+
+void RecipeTasksHandler::DismissRecipeTask(const std::string& task_name) {
+  RecipeTasksServiceFactory::GetForProfile(profile_)->DismissRecipeTask(
+      task_name);
+}
+
+void RecipeTasksHandler::RestoreRecipeTask(const std::string& task_name) {
+  RecipeTasksServiceFactory::GetForProfile(profile_)->RestoreRecipeTask(
+      task_name);
+}
+
+void RecipeTasksHandler::OnRecipeClicked(uint32_t index) {
+  base::UmaHistogramCounts100("NewTabPage.RecipeTasks.RecipeClick", index);
+}
+
+void RecipeTasksHandler::OnRelatedSearchClicked(uint32_t index) {
+  base::UmaHistogramCounts100("NewTabPage.RecipeTasks.RelatedSearchClick",
+                              index);
+}
diff --git a/chrome/browser/search/recipe_tasks/recipe_tasks_handler.h b/chrome/browser/search/recipe_tasks/recipe_tasks_handler.h
new file mode 100644
index 0000000..3962f7c
--- /dev/null
+++ b/chrome/browser/search/recipe_tasks/recipe_tasks_handler.h
@@ -0,0 +1,37 @@
+// 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_SEARCH_RECIPE_TASKS_RECIPE_TASKS_HANDLER_H_
+#define CHROME_BROWSER_SEARCH_RECIPE_TASKS_RECIPE_TASKS_HANDLER_H_
+
+#include "chrome/browser/search/recipe_tasks/recipe_tasks.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+
+class Profile;
+
+// Implementation of the RecipeTasksHandler mojo interface that requests
+// recipe tasks from the RecipeTasksService. Instantiated by the NTP upon a
+// connection request by the recipe tasks module.
+class RecipeTasksHandler : public recipe_tasks::mojom::RecipeTasksHandler {
+ public:
+  RecipeTasksHandler(
+      mojo::PendingReceiver<recipe_tasks::mojom::RecipeTasksHandler>
+          pending_receiver,
+      Profile* profile);
+  ~RecipeTasksHandler() override;
+
+  // recipe_tasks::mojom::RecipeTasksHandler:
+  void GetPrimaryRecipeTask(GetPrimaryRecipeTaskCallback callback) override;
+  void DismissRecipeTask(const std::string& task_name) override;
+  void RestoreRecipeTask(const std::string& task_name) override;
+  void OnRecipeClicked(uint32_t index) override;
+  void OnRelatedSearchClicked(uint32_t index) override;
+
+ private:
+  mojo::Receiver<recipe_tasks::mojom::RecipeTasksHandler> receiver_;
+  Profile* profile_;
+};
+
+#endif  // CHROME_BROWSER_SEARCH_RECIPE_TASKS_RECIPE_TASKS_HANDLER_H_
diff --git a/chrome/browser/search/recipe_tasks/recipe_tasks_service.cc b/chrome/browser/search/recipe_tasks/recipe_tasks_service.cc
new file mode 100644
index 0000000..11b3283
--- /dev/null
+++ b/chrome/browser/search/recipe_tasks/recipe_tasks_service.cc
@@ -0,0 +1,216 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/search/recipe_tasks/recipe_tasks_service.h"
+
+#include "base/stl_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/webui_url_constants.h"
+#include "components/google/core/common/google_util.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/scoped_user_pref_update.h"
+#include "components/variations/net/variations_http_headers.h"
+#include "net/base/url_util.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+
+namespace {
+const char kNewTabRecipeTasksApiPath[] = "/async/newtab_recipe_tasks";
+const char kXSSIResponsePreamble[] = ")]}'";
+const char kDismissedTasksPrefName[] = "NewTabPage.DismissedRecipeTasks";
+
+GURL GetApiUrl(const std::string& application_locale) {
+  GURL google_base_url = google_util::CommandLineGoogleBaseURL();
+  if (!google_base_url.is_valid()) {
+    google_base_url = GURL(google_util::kGoogleHomepageURL);
+  }
+  return net::AppendQueryParameter(
+      google_base_url.Resolve(kNewTabRecipeTasksApiPath), "hl",
+      application_locale);
+}
+}  // namespace
+
+RecipeTasksService::RecipeTasksService(
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+    Profile* profile,
+    const std::string& application_locale)
+    : profile_(profile),
+      url_loader_factory_(url_loader_factory),
+      application_locale_(application_locale) {}
+
+RecipeTasksService::~RecipeTasksService() = default;
+
+// static
+void RecipeTasksService::RegisterProfilePrefs(PrefRegistrySimple* registry) {
+  registry->RegisterListPref(kDismissedTasksPrefName);
+}
+
+void RecipeTasksService::Shutdown() {}
+
+void RecipeTasksService::GetPrimaryRecipeTask(RecipeTaskCallback callback) {
+  net::NetworkTrafficAnnotationTag traffic_annotation =
+      net::DefineNetworkTrafficAnnotation("recipe_tasks_service", R"(
+        semantics {
+          sender: "Recipe Tasks Service"
+          description: "This service downloads recipe tasks, which is "
+            "information related to the user's currently active recipe "
+            "search journeys such as visisted and recommended recipes. "
+            "Recipe tasks will be displayed on the new tab page to help the "
+            "user to continue their search journey. Recipe tasks are queried "
+            "on every new tab page load."
+          trigger:
+            "Displaying the new tab page on Desktop, if Google is the "
+            "configured search provider and the user is signed in."
+          data: "Credentials if user is signed in."
+          destination: GOOGLE_OWNED_SERVICE
+        }
+        policy {
+          cookies_allowed: YES
+          cookies_store: "user"
+          setting:
+            "Users can control this feature via selecting a non-Google default "
+            "search engine in Chrome settings under 'Search Engine' or by "
+            "signing out."
+          chrome_policy {
+            DefaultSearchProviderEnabled {
+              policy_options {mode: MANDATORY}
+              DefaultSearchProviderEnabled: false
+            }
+            BrowserSignin {
+              policy_options {mode: MANDATORY}
+              BrowserSignin: 0
+            }
+          }
+        })");
+
+  auto resource_request = std::make_unique<network::ResourceRequest>();
+  resource_request->url = GetApiUrl(application_locale_);
+  resource_request->credentials_mode =
+      network::mojom::CredentialsMode::kInclude;
+  resource_request->request_initiator =
+      url::Origin::Create(GURL(chrome::kChromeUINewTabURL));
+  variations::AppendVariationsHeaderUnknownSignedIn(
+      resource_request->url,
+      /* Modules are only shown in non-incognito. */
+      variations::InIncognito::kNo, resource_request.get());
+
+  loaders_.push_back(network::SimpleURLLoader::Create(
+      std::move(resource_request), traffic_annotation));
+  loaders_.back()->DownloadToString(
+      url_loader_factory_.get(),
+      base::BindOnce(&RecipeTasksService::OnDataLoaded,
+                     weak_ptr_factory_.GetWeakPtr(), loaders_.back().get(),
+                     std::move(callback)),
+      network::SimpleURLLoader::kMaxBoundedStringDownloadSize);
+}
+
+void RecipeTasksService::DismissRecipeTask(const std::string& task_name) {
+  ListPrefUpdate update(profile_->GetPrefs(), kDismissedTasksPrefName);
+  update->AppendIfNotPresent(std::make_unique<base::Value>(task_name));
+}
+
+void RecipeTasksService::RestoreRecipeTask(const std::string& task_name) {
+  ListPrefUpdate update(profile_->GetPrefs(), kDismissedTasksPrefName);
+  update->EraseListValue(base::Value(task_name));
+}
+
+void RecipeTasksService::OnDataLoaded(network::SimpleURLLoader* loader,
+                                      RecipeTaskCallback callback,
+                                      std::unique_ptr<std::string> response) {
+  auto net_error = loader->NetError();
+  base::EraseIf(loaders_, [loader](const auto& target) {
+    return loader == target.get();
+  });
+
+  if (net_error != net::OK || !response) {
+    std::move(callback).Run(nullptr);
+    return;
+  }
+
+  if (base::StartsWith(*response, kXSSIResponsePreamble,
+                       base::CompareCase::SENSITIVE)) {
+    *response = response->substr(strlen(kXSSIResponsePreamble));
+  }
+
+  data_decoder::DataDecoder::ParseJsonIsolated(
+      *response,
+      base::BindOnce(&RecipeTasksService::OnJsonParsed,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void RecipeTasksService::OnJsonParsed(
+    RecipeTaskCallback callback,
+    data_decoder::DataDecoder::ValueOrError result) {
+  if (!result.value) {
+    std::move(callback).Run(nullptr);
+    return;
+  }
+  // We receive a list of recipe tasks ordered from highest to lowest
+  // priority. We only support showing a single task though. Therefore, pick the
+  // first task.
+  auto* recipe_tasks = result.value->FindListPath("update.recipe_tasks");
+  if (!recipe_tasks || recipe_tasks->GetList().size() == 0) {
+    std::move(callback).Run(nullptr);
+    return;
+  }
+  for (const auto& recipe_task : recipe_tasks->GetList()) {
+    auto* title = recipe_task.FindStringPath("title");
+    auto* task_name = recipe_task.FindStringPath("task_name");
+    auto* recipes = recipe_task.FindListPath("recipes");
+    auto* related_searches = recipe_task.FindListPath("related_searches");
+    if (!title || !task_name || !recipes || !related_searches ||
+        recipes->GetList().size() == 0) {
+      continue;
+    }
+    if (IsRecipeTaskDismissed(*task_name)) {
+      continue;
+    }
+    std::vector<recipe_tasks::mojom::RecipePtr> mojo_recipes;
+    for (const auto& recipe : recipes->GetList()) {
+      auto* name = recipe.FindStringPath("name");
+      auto* image_url = recipe.FindStringPath("image_url");
+      auto* info = recipe.FindStringPath("info");
+      auto* target_url = recipe.FindStringPath("target_url");
+      if (!name || !image_url || !info || !target_url) {
+        continue;
+      }
+      auto mojo_recipe = recipe_tasks::mojom::Recipe::New();
+      mojo_recipe->name = *name;
+      mojo_recipe->image_url = GURL(*image_url);
+      mojo_recipe->info = *info;
+      mojo_recipe->target_url = GURL(*target_url);
+      mojo_recipes.push_back(std::move(mojo_recipe));
+    }
+    std::vector<recipe_tasks::mojom::RelatedSearchPtr> mojo_related_searches;
+    for (const auto& related_search : related_searches->GetList()) {
+      auto* text = related_search.FindStringPath("text");
+      auto* target_url = related_search.FindStringPath("target_url");
+      if (!text || !target_url) {
+        continue;
+      }
+      auto mojo_related_search = recipe_tasks::mojom::RelatedSearch::New();
+      mojo_related_search->text = *text;
+      mojo_related_search->target_url = GURL(*target_url);
+      mojo_related_searches.push_back(std::move(mojo_related_search));
+    }
+    auto mojo_recipe_task = recipe_tasks::mojom::RecipeTask::New();
+    mojo_recipe_task->title = *title;
+    mojo_recipe_task->name = *task_name;
+    mojo_recipe_task->recipes = std::move(mojo_recipes);
+    mojo_recipe_task->related_searches = std::move(mojo_related_searches);
+    std::move(callback).Run(std::move(mojo_recipe_task));
+    return;
+  }
+  std::move(callback).Run(nullptr);
+}
+
+bool RecipeTasksService::IsRecipeTaskDismissed(const std::string& task_name) {
+  const base::ListValue* dismissed_tasks =
+      profile_->GetPrefs()->GetList(kDismissedTasksPrefName);
+  DCHECK(dismissed_tasks);
+  return dismissed_tasks->Find(base::Value(task_name)) !=
+         dismissed_tasks->end();
+}
diff --git a/chrome/browser/search/recipe_tasks/recipe_tasks_service.h b/chrome/browser/search/recipe_tasks/recipe_tasks_service.h
new file mode 100644
index 0000000..1aad32b
--- /dev/null
+++ b/chrome/browser/search/recipe_tasks/recipe_tasks_service.h
@@ -0,0 +1,70 @@
+// 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_SEARCH_RECIPE_TASKS_RECIPE_TASKS_SERVICE_H_
+#define CHROME_BROWSER_SEARCH_RECIPE_TASKS_RECIPE_TASKS_SERVICE_H_
+
+#include <list>
+#include <memory>
+
+#include "base/callback.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/search/recipe_tasks/recipe_tasks.mojom.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "services/data_decoder/public/cpp/data_decoder.h"
+
+class PrefRegistrySimple;
+class Profile;
+namespace network {
+class SharedURLLoaderFactory;
+class SimpleURLLoader;
+}  // namespace network
+
+// Downloads recipe tasks for current user from GWS.
+class RecipeTasksService : public KeyedService {
+ public:
+  RecipeTasksService(
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+      Profile* profile,
+      const std::string& application_locale);
+  RecipeTasksService(const RecipeTasksService&) = delete;
+  ~RecipeTasksService() override;
+
+  static void RegisterProfilePrefs(PrefRegistrySimple* registry);
+
+  // KeyedService:
+  void Shutdown() override;
+
+  using RecipeTaskCallback =
+      base::OnceCallback<void(recipe_tasks::mojom::RecipeTaskPtr recipe_task)>;
+  // Downloads and parses recipe tasks and calls |callback| when done.
+  // On success |callback| is called with a populated |RecipeTasksData| object
+  // of the first recipe task which has not been dismissed. On failure, it is
+  // called with nullptr.
+  void GetPrimaryRecipeTask(RecipeTaskCallback callback);
+  // Dismisses the task with the given name and remembers that setting.
+  void DismissRecipeTask(const std::string& task_name);
+  // Restores the task with the given name and remembers that setting.
+  void RestoreRecipeTask(const std::string& task_name);
+
+ private:
+  void OnDataLoaded(network::SimpleURLLoader* loader,
+                    RecipeTaskCallback callback,
+                    std::unique_ptr<std::string> response);
+  void OnJsonParsed(RecipeTaskCallback callback,
+                    data_decoder::DataDecoder::ValueOrError result);
+
+  // Returns whether a task with the given name has been dismissed.
+  bool IsRecipeTaskDismissed(const std::string& task_name);
+
+  Profile* profile_;
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+  std::list<std::unique_ptr<network::SimpleURLLoader>> loaders_;
+  std::string application_locale_;
+
+  base::WeakPtrFactory<RecipeTasksService> weak_ptr_factory_{this};
+};
+
+#endif  // CHROME_BROWSER_SEARCH_RECIPE_TASKS_RECIPE_TASKS_SERVICE_H_
diff --git a/chrome/browser/search/recipe_tasks/recipe_tasks_service_factory.cc b/chrome/browser/search/recipe_tasks/recipe_tasks_service_factory.cc
new file mode 100644
index 0000000..2b3f6243
--- /dev/null
+++ b/chrome/browser/search/recipe_tasks/recipe_tasks_service_factory.cc
@@ -0,0 +1,43 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/search/recipe_tasks/recipe_tasks_service_factory.h"
+
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/content_settings/cookie_settings_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search/recipe_tasks/recipe_tasks_service.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/storage_partition.h"
+
+// static
+RecipeTasksService* RecipeTasksServiceFactory::GetForProfile(Profile* profile) {
+  return static_cast<RecipeTasksService*>(
+      GetInstance()->GetServiceForBrowserContext(profile, true));
+}
+
+// static
+RecipeTasksServiceFactory* RecipeTasksServiceFactory::GetInstance() {
+  return base::Singleton<RecipeTasksServiceFactory>::get();
+}
+
+RecipeTasksServiceFactory::RecipeTasksServiceFactory()
+    : BrowserContextKeyedServiceFactory(
+          "RecipeTasksService",
+          BrowserContextDependencyManager::GetInstance()) {
+  DependsOn(CookieSettingsFactory::GetInstance());
+}
+
+RecipeTasksServiceFactory::~RecipeTasksServiceFactory() = default;
+
+KeyedService* RecipeTasksServiceFactory::BuildServiceInstanceFor(
+    content::BrowserContext* context) const {
+  auto url_loader_factory =
+      content::BrowserContext::GetDefaultStoragePartition(context)
+          ->GetURLLoaderFactoryForBrowserProcess();
+  return new RecipeTasksService(url_loader_factory,
+                                Profile::FromBrowserContext(context),
+                                g_browser_process->GetApplicationLocale());
+}
diff --git a/chrome/browser/search/recipe_tasks/recipe_tasks_service_factory.h b/chrome/browser/search/recipe_tasks/recipe_tasks_service_factory.h
new file mode 100644
index 0000000..ff15a3b
--- /dev/null
+++ b/chrome/browser/search/recipe_tasks/recipe_tasks_service_factory.h
@@ -0,0 +1,33 @@
+// 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_SEARCH_RECIPE_TASKS_RECIPE_TASKS_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_SEARCH_RECIPE_TASKS_RECIPE_TASKS_SERVICE_FACTORY_H_
+
+#include "base/memory/singleton.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+
+class Profile;
+class RecipeTasksService;
+
+// Factory to access the recipe task service for the current profile.
+class RecipeTasksServiceFactory : public BrowserContextKeyedServiceFactory {
+ public:
+  static RecipeTasksService* GetForProfile(Profile* profile);
+  static RecipeTasksServiceFactory* GetInstance();
+
+  RecipeTasksServiceFactory(const RecipeTasksServiceFactory&) = delete;
+
+ private:
+  friend struct base::DefaultSingletonTraits<RecipeTasksServiceFactory>;
+
+  RecipeTasksServiceFactory();
+  ~RecipeTasksServiceFactory() override;
+
+  // BrowserContextKeyedServiceFactory:
+  KeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* profile) const override;
+};
+
+#endif  // CHROME_BROWSER_SEARCH_RECIPE_TASKS_RECIPE_TASKS_SERVICE_FACTORY_H_
diff --git a/chrome/browser/search/recipe_tasks/recipe_tasks_service_unittest.cc b/chrome/browser/search/recipe_tasks/recipe_tasks_service_unittest.cc
new file mode 100644
index 0000000..adfe25e
--- /dev/null
+++ b/chrome/browser/search/recipe_tasks/recipe_tasks_service_unittest.cc
@@ -0,0 +1,377 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+
+#include "base/memory/scoped_refptr.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/mock_callback.h"
+#include "chrome/browser/search/recipe_tasks/recipe_tasks_service.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/browser_task_environment.h"
+#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class RecipeTasksServiceTest : public testing::Test {
+ public:
+  RecipeTasksServiceTest()
+      : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP) {}
+
+  void SetUp() override {
+    testing::Test::SetUp();
+
+    service_ = std::make_unique<RecipeTasksService>(
+        base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+            &test_url_loader_factory_),
+        &profile_, "en-US");
+  }
+
+  void TearDown() override {
+    service_.reset();
+    test_url_loader_factory_.ClearResponses();
+  }
+
+ protected:
+  // Required to run tests from UI thread.
+  content::BrowserTaskEnvironment task_environment_;
+  TestingProfile profile_;
+  network::TestURLLoaderFactory test_url_loader_factory_;
+  data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
+  scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
+  std::unique_ptr<RecipeTasksService> service_;
+};
+
+// Verifies correct parsing of well-formed JSON.
+TEST_F(RecipeTasksServiceTest, GoodResponse) {
+  test_url_loader_factory_.AddResponse(
+      "https://www.google.com/async/newtab_recipe_tasks?hl=en-US",
+      R"()]}'
+{
+  "update": {
+    "recipe_tasks": [
+      {
+        "title": "hello world",
+        "task_name": "hello world",
+        "recipes": [
+          {
+            "name": "foo",
+            "image_url": "https://foo.com",
+            "info": "visited 5 days ago",
+            "target_url": "https://google.com/foo"
+          },{
+            "name": "bar",
+            "image_url": "https://bar.com",
+            "info": "visited 1 day ago",
+            "target_url": "https://google.com/bar"
+          }
+        ],
+        "related_searches": [
+          {
+            "text": "baz",
+            "target_url": "https://google.com/baz"
+          },
+          {
+            "text": "blub",
+            "target_url": "https://google.com/blub"
+          }
+        ]
+      }
+    ]
+  }
+})");
+
+  recipe_tasks::mojom::RecipeTaskPtr result;
+  base::MockCallback<RecipeTasksService::RecipeTaskCallback> callback;
+  EXPECT_CALL(callback, Run(testing::_))
+      .Times(1)
+      .WillOnce(
+          testing::Invoke([&result](recipe_tasks::mojom::RecipeTaskPtr arg) {
+            result = std::move(arg);
+          }));
+
+  service_->GetPrimaryRecipeTask(callback.Get());
+  base::RunLoop().RunUntilIdle();
+
+  ASSERT_TRUE(result);
+  EXPECT_EQ("hello world", result->title);
+  EXPECT_EQ(2ul, result->recipes.size());
+  EXPECT_EQ(2ul, result->related_searches.size());
+  EXPECT_EQ("foo", result->recipes[0]->name);
+  EXPECT_EQ("https://foo.com/", result->recipes[0]->image_url.spec());
+  EXPECT_EQ("visited 5 days ago", result->recipes[0]->info);
+  EXPECT_EQ("https://google.com/bar", result->recipes[1]->target_url.spec());
+  EXPECT_EQ("bar", result->recipes[1]->name);
+  EXPECT_EQ("https://bar.com/", result->recipes[1]->image_url.spec());
+  EXPECT_EQ("visited 1 day ago", result->recipes[1]->info);
+  EXPECT_EQ("https://google.com/bar", result->recipes[1]->target_url.spec());
+  EXPECT_EQ("baz", result->related_searches[0]->text);
+  EXPECT_EQ("https://google.com/baz",
+            result->related_searches[0]->target_url.spec());
+  EXPECT_EQ("blub", result->related_searches[1]->text);
+  EXPECT_EQ("https://google.com/blub",
+            result->related_searches[1]->target_url.spec());
+}
+
+// Verifies service can handle multiple in flight requests.
+TEST_F(RecipeTasksServiceTest, MultiRequest) {
+  test_url_loader_factory_.AddResponse(
+      "https://www.google.com/async/newtab_recipe_tasks?hl=en-US",
+      R"()]}'
+{
+  "update": {
+    "recipe_tasks": [
+      {
+        "title": "hello world",
+        "task_name": "hello world",
+        "recipes": [
+          {
+            "name": "foo",
+            "image_url": "https://foo.com",
+            "info": "visited 5 days ago",
+            "target_url": "https://google.com/foo"
+          }
+        ],
+        "related_searches": [
+          {
+            "text": "baz",
+            "target_url": "https://google.com/baz"
+          }
+        ]
+      }
+    ]
+  }
+})");
+
+  recipe_tasks::mojom::RecipeTaskPtr result1;
+  base::MockCallback<RecipeTasksService::RecipeTaskCallback> callback1;
+  EXPECT_CALL(callback1, Run(testing::_))
+      .Times(1)
+      .WillOnce(
+          testing::Invoke([&result1](recipe_tasks::mojom::RecipeTaskPtr arg) {
+            result1 = std::move(arg);
+          }));
+  service_->GetPrimaryRecipeTask(callback1.Get());
+
+  recipe_tasks::mojom::RecipeTaskPtr result2;
+  base::MockCallback<RecipeTasksService::RecipeTaskCallback> callback2;
+  EXPECT_CALL(callback2, Run(testing::_))
+      .Times(1)
+      .WillOnce(
+          testing::Invoke([&result2](recipe_tasks::mojom::RecipeTaskPtr arg) {
+            result2 = std::move(arg);
+          }));
+  service_->GetPrimaryRecipeTask(callback2.Get());
+
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_TRUE(result1);
+  EXPECT_TRUE(result2);
+}
+
+// Verifies error if JSON is malformed.
+TEST_F(RecipeTasksServiceTest, BadResponse) {
+  test_url_loader_factory_.AddResponse(
+      "https://www.google.com/async/newtab_recipe_tasks?hl=en-US",
+      ")]}'{\"update\":{\"promotions\":{}}}");
+
+  recipe_tasks::mojom::RecipeTaskPtr result;
+  base::MockCallback<RecipeTasksService::RecipeTaskCallback> callback;
+  EXPECT_CALL(callback, Run(testing::_))
+      .Times(1)
+      .WillOnce(
+          testing::Invoke([&result](recipe_tasks::mojom::RecipeTaskPtr arg) {
+            result = std::move(arg);
+          }));
+
+  service_->GetPrimaryRecipeTask(callback.Get());
+  base::RunLoop().RunUntilIdle();
+
+  ASSERT_FALSE(result);
+}
+
+// Verifies error if no recipes.
+TEST_F(RecipeTasksServiceTest, NoRecipes) {
+  test_url_loader_factory_.AddResponse(
+      "https://www.google.com/async/newtab_recipe_tasks?hl=en-US",
+      R"()]}'
+{
+  "update": {
+    "recipe_tasks": [
+      {
+        "title": "hello world",
+        "task_name": "hello world",
+        "recipes": [],
+        "related_searches": [
+          {
+            "text": "baz",
+            "target_url": "https://google.com/baz"
+          }
+        ]
+      }
+    ]
+  }
+})");
+
+  recipe_tasks::mojom::RecipeTaskPtr result;
+  base::MockCallback<RecipeTasksService::RecipeTaskCallback> callback;
+  EXPECT_CALL(callback, Run(testing::_))
+      .Times(1)
+      .WillOnce(
+          testing::Invoke([&result](recipe_tasks::mojom::RecipeTaskPtr arg) {
+            result = std::move(arg);
+          }));
+
+  service_->GetPrimaryRecipeTask(callback.Get());
+  base::RunLoop().RunUntilIdle();
+
+  ASSERT_FALSE(result);
+}
+
+// Verifies error if download fails.
+TEST_F(RecipeTasksServiceTest, ErrorResponse) {
+  test_url_loader_factory_.AddResponse(
+      GURL("https://www.google.com/async/newtab_recipe_tasks?hl=en-US"),
+      network::mojom::URLResponseHead::New(), std::string(),
+      network::URLLoaderCompletionStatus(net::HTTP_NOT_FOUND));
+
+  recipe_tasks::mojom::RecipeTaskPtr result;
+  base::MockCallback<RecipeTasksService::RecipeTaskCallback> callback;
+  EXPECT_CALL(callback, Run(testing::_))
+      .Times(1)
+      .WillOnce(
+          testing::Invoke([&result](recipe_tasks::mojom::RecipeTaskPtr arg) {
+            result = std::move(arg);
+          }));
+
+  service_->GetPrimaryRecipeTask(callback.Get());
+  base::RunLoop().RunUntilIdle();
+
+  ASSERT_FALSE(result);
+}
+
+// Verifies recipe tasks can be dismissed and restored and that the service
+// remembers not to return dismissed tasks.
+TEST_F(RecipeTasksServiceTest, DismissTasks) {
+  test_url_loader_factory_.AddResponse(
+      "https://www.google.com/async/newtab_recipe_tasks?hl=en-US",
+      R"()]}'
+{
+  "update": {
+    "recipe_tasks": [
+      {
+        "title": "task 1 title",
+        "task_name": "task 1 name",
+        "recipes": [
+          {
+            "name": "foo",
+            "image_url": "https://foo.com",
+            "info": "visited 5 days ago",
+            "target_url": "https://google.com/foo"
+          }
+        ],
+        "related_searches": [
+          {
+            "text": "baz",
+            "target_url": "https://google.com/baz"
+          }
+        ]
+      },
+      {
+        "title": "task 2 title",
+        "task_name": "task 2 name",
+        "recipes": [
+          {
+            "name": "foo",
+            "image_url": "https://foo.com",
+            "info": "visited 5 days ago",
+            "target_url": "https://google.com/foo"
+          }
+        ],
+        "related_searches": [
+          {
+            "text": "baz",
+            "target_url": "https://google.com/baz"
+          }
+        ]
+      }
+    ]
+  }
+})");
+
+  recipe_tasks::mojom::RecipeTaskPtr result1;
+  base::MockCallback<RecipeTasksService::RecipeTaskCallback> callback1;
+  EXPECT_CALL(callback1, Run(testing::_))
+      .Times(1)
+      .WillOnce(
+          testing::Invoke([&result1](recipe_tasks::mojom::RecipeTaskPtr arg) {
+            result1 = std::move(arg);
+          }));
+  service_->GetPrimaryRecipeTask(callback1.Get());
+  base::RunLoop().RunUntilIdle();
+  ASSERT_TRUE(result1);
+  EXPECT_EQ("task 1 name", result1->name);
+
+  service_->DismissRecipeTask("task 1 name");
+
+  recipe_tasks::mojom::RecipeTaskPtr result2;
+  base::MockCallback<RecipeTasksService::RecipeTaskCallback> callback2;
+  EXPECT_CALL(callback2, Run(testing::_))
+      .Times(1)
+      .WillOnce(
+          testing::Invoke([&result2](recipe_tasks::mojom::RecipeTaskPtr arg) {
+            result2 = std::move(arg);
+          }));
+  service_->GetPrimaryRecipeTask(callback2.Get());
+  base::RunLoop().RunUntilIdle();
+  ASSERT_TRUE(result2);
+  EXPECT_EQ("task 2 name", result2->name);
+
+  service_->DismissRecipeTask("task 2 name");
+
+  recipe_tasks::mojom::RecipeTaskPtr result3;
+  base::MockCallback<RecipeTasksService::RecipeTaskCallback> callback3;
+  EXPECT_CALL(callback3, Run(testing::_))
+      .Times(1)
+      .WillOnce(
+          testing::Invoke([&result3](recipe_tasks::mojom::RecipeTaskPtr arg) {
+            result3 = std::move(arg);
+          }));
+  service_->GetPrimaryRecipeTask(callback3.Get());
+  base::RunLoop().RunUntilIdle();
+  ASSERT_FALSE(result3);
+
+  service_->RestoreRecipeTask("task 2 name");
+
+  recipe_tasks::mojom::RecipeTaskPtr result4;
+  base::MockCallback<RecipeTasksService::RecipeTaskCallback> callback4;
+  EXPECT_CALL(callback4, Run(testing::_))
+      .Times(1)
+      .WillOnce(
+          testing::Invoke([&result4](recipe_tasks::mojom::RecipeTaskPtr arg) {
+            result4 = std::move(arg);
+          }));
+  service_->GetPrimaryRecipeTask(callback4.Get());
+  base::RunLoop().RunUntilIdle();
+  ASSERT_TRUE(result4);
+  EXPECT_EQ("task 2 name", result4->name);
+
+  service_->RestoreRecipeTask("task 1 name");
+
+  recipe_tasks::mojom::RecipeTaskPtr result5;
+  base::MockCallback<RecipeTasksService::RecipeTaskCallback> callback5;
+  EXPECT_CALL(callback5, Run(testing::_))
+      .Times(1)
+      .WillOnce(
+          testing::Invoke([&result5](recipe_tasks::mojom::RecipeTaskPtr arg) {
+            result5 = std::move(arg);
+          }));
+  service_->GetPrimaryRecipeTask(callback5.Get());
+  base::RunLoop().RunUntilIdle();
+  ASSERT_TRUE(result5);
+  EXPECT_EQ("task 1 name", result5->name);
+}
diff --git a/chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml b/chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml
index 22e4d758..c3b41a1 100644
--- a/chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml
+++ b/chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml
@@ -12,15 +12,6 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-    <!-- TODO (crbug.com/1034733) Fix that this button is being 
-    partially covered by the iamgeview -->
-        <org.chromium.ui.widget.ChromeImageButton
-            android:id="@+id/close_button"
-            style="@style/ToolbarButton"
-            android:src="@drawable/btn_close"
-            android:contentDescription="@string/close"
-            app:tint="@color/default_icon_color_tint_list" />
-
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="match_parent"
@@ -99,6 +90,13 @@
 
         </LinearLayout>
 
+        <org.chromium.ui.widget.ChromeImageButton
+            android:id="@+id/close_button"
+            style="@style/ToolbarButton"
+            android:src="@drawable/btn_close"
+            android:contentDescription="@string/close"
+            app:tint="@color/default_icon_color_tint_list" />
+
     </RelativeLayout>
 
 </org.chromium.chrome.browser.share.screenshot.ScreenshotShareSheetView>
diff --git a/chrome/browser/ssl/chrome_security_blocking_page_factory.cc b/chrome/browser/ssl/chrome_security_blocking_page_factory.cc
index 5726307..a7444ff 100644
--- a/chrome/browser/ssl/chrome_security_blocking_page_factory.cc
+++ b/chrome/browser/ssl/chrome_security_blocking_page_factory.cc
@@ -25,7 +25,6 @@
 #include "components/security_interstitials/core/controller_client.h"
 #include "components/security_interstitials/core/metrics_helper.h"
 #include "content/public/browser/web_contents.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 
 #if defined(OS_WIN)
 #include "base/enterprise_util.h"
diff --git a/chrome/browser/ssl/security_state_tab_helper_browsertest.cc b/chrome/browser/ssl/security_state_tab_helper_browsertest.cc
index 00a0bfc..60c9232 100644
--- a/chrome/browser/ssl/security_state_tab_helper_browsertest.cc
+++ b/chrome/browser/ssl/security_state_tab_helper_browsertest.cc
@@ -2262,8 +2262,8 @@
   ASSERT_TRUE(broken_https_server.Start());
 
   // Make the form target the expired certificate server.
-  net::HostPortPair host_port_pair =
-      net::HostPortPair::FromURL(broken_https_server.GetURL("/google.html"));
+  net::HostPortPair host_port_pair = net::HostPortPair::FromURL(
+      broken_https_server.GetURL("/ssl/google.html"));
   std::string replacement_path = GetFilePathWithHostAndPortReplacement(
       "/ssl/page_with_form_targeting_insecure_url.html", host_port_pair);
   ui_test_utils::NavigateToURL(browser(),
@@ -2301,7 +2301,7 @@
     // Use a different host for targeting the form so that a Safety Tip doesn't
     // trigger on the form submission navigation.
     net::HostPortPair host_port_pair = net::HostPortPair::FromURL(
-        form_server.GetURL("example.test", "/google.html"));
+        form_server.GetURL("example.test", "/ssl/google.html"));
     std::string replacement_path = GetFilePathWithHostAndPortReplacement(
         "/ssl/page_with_form_targeting_http_url.html", host_port_pair);
     ui_test_utils::NavigateToURL(browser(), server.GetURL(replacement_path));
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc
index d4dd23ae..3bb9db1f 100644
--- a/chrome/browser/ssl/ssl_browsertest.cc
+++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -1998,8 +1998,8 @@
     base::RunLoop loop;
     GetNSSCertDatabaseForProfile(
         browser()->profile(),
-        base::Bind(&SSLUITestWithClientCert::DidGetCertDatabase,
-                   base::Unretained(this), &loop));
+        base::BindOnce(&SSLUITestWithClientCert::DidGetCertDatabase,
+                       base::Unretained(this), &loop));
     loop.Run();
   }
 
@@ -5873,8 +5873,8 @@
       base::RunLoop loop;
       GetNSSCertDatabaseForProfile(
           profile_1_,
-          base::Bind(&SSLUITestCustomCACerts::DidGetCertDatabase,
-                     base::Unretained(this), &loop, &profile_1_cert_db_));
+          base::BindOnce(&SSLUITestCustomCACerts::DidGetCertDatabase,
+                         base::Unretained(this), &loop, &profile_1_cert_db_));
       loop.Run();
     }
 
@@ -5882,8 +5882,8 @@
       base::RunLoop loop;
       GetNSSCertDatabaseForProfile(
           profile_2_,
-          base::Bind(&SSLUITestCustomCACerts::DidGetCertDatabase,
-                     base::Unretained(this), &loop, &profile_2_cert_db_));
+          base::BindOnce(&SSLUITestCustomCACerts::DidGetCertDatabase,
+                         base::Unretained(this), &loop, &profile_2_cert_db_));
       loop.Run();
     }
 
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
index 5c04ba85..31314b8 100644
--- a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
+++ b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
@@ -604,7 +604,7 @@
   BlockHost(kExampleHost);
 
   GURL blocked_url = embedded_test_server()->GetURL(
-      kExampleHost, "/supervised_user/with_frames.html");
+      kExampleHost, "/supervised_user/with_iframes.html");
   ui_test_utils::NavigateToURL(browser(), blocked_url);
   EXPECT_TRUE(IsInterstitialBeingShownInMainFrame(browser()));
 
@@ -623,7 +623,7 @@
 
   // Navigate to another allowed url.
   GURL allowed_url = embedded_test_server()->GetURL(
-      kExampleHost2, "/supervised_user/with_frames.html");
+      kExampleHost2, "/supervised_user/with_iframes.html");
   ui_test_utils::NavigateToURL(browser(), allowed_url);
   EXPECT_FALSE(IsInterstitialBeingShownInMainFrame(browser()));
 
diff --git a/chrome/browser/tabmodel/OWNERS b/chrome/browser/tabmodel/OWNERS
index 1e5cc4c4..c3390b8 100644
--- a/chrome/browser/tabmodel/OWNERS
+++ b/chrome/browser/tabmodel/OWNERS
@@ -2,7 +2,7 @@
 hnakashima@chromium.org
 meiliang@chromium.org
 
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
 # COMPONENT: UI>Browser>Mobile>TabModel
 # OS: Android
 
diff --git a/chrome/browser/tabpersistence/OWNERS b/chrome/browser/tabpersistence/OWNERS
index 4f2f509b..efa7ebfb 100644
--- a/chrome/browser/tabpersistence/OWNERS
+++ b/chrome/browser/tabpersistence/OWNERS
@@ -1,5 +1,5 @@
 file://chrome/android/OWNERS
 
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
 # COMPONENT: UI>Browser>Mobile
 # OS: Android
diff --git a/chrome/browser/task_manager/task_manager_browsertest.cc b/chrome/browser/task_manager/task_manager_browsertest.cc
index 13b2cb8..36a0187 100644
--- a/chrome/browser/task_manager/task_manager_browsertest.cc
+++ b/chrome/browser/task_manager/task_manager_browsertest.cc
@@ -762,8 +762,18 @@
             model()->GetColumnValue(ColumnSpecifier::TOTAL_NETWORK_USE, 0));
 }
 
-// Checks that task manager counts idle wakeups.
-IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, IdleWakeups) {
+// Checks that task manager counts idle wakeups. Since this test relies on
+// forcing actual system-level idle wakeups to happen, it is inherently
+// dependent on the load of the rest of the system, details of the OS scheduler,
+// and so on, which makes it very prone to flakes.
+#if defined(OS_MAC)
+// This test is too flaky to be useable on Mac, because of the reasons given
+// above.
+#define MAYBE_IdleWakeups DISABLED_IdleWakeups
+#else
+#define MAYBE_IdleWakeups IdleWakeups
+#endif
+IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, MAYBE_IdleWakeups) {
   ShowTaskManager();
   model()->ToggleColumnVisibility(ColumnSpecifier::IDLE_WAKEUPS);
 
@@ -783,12 +793,7 @@
 
 // The script above should trigger a lot of idle wakeups - up to 1000 per
 // second. Let's make sure we get at least 100 (in case the test runs slow).
-// On Mac, set a lower threshold because Chrome Mac generates fewer wakes.
-#if defined(OS_MAC)
-  const int kMinExpectedWakeCount = 50;
-#else
   const int kMinExpectedWakeCount = 100;
-#endif  // defined(OS_MAC)
   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerStatToExceed(
       MatchTab("title1.html"), ColumnSpecifier::IDLE_WAKEUPS,
       kMinExpectedWakeCount));
diff --git a/chrome/browser/translate/android/translate_bridge.cc b/chrome/browser/translate/android/translate_bridge.cc
index bf55e34..fd63af304 100644
--- a/chrome/browser/translate/android/translate_bridge.cc
+++ b/chrome/browser/translate/android/translate_bridge.cc
@@ -412,3 +412,10 @@
       ChromeTranslateClient::CreateTranslatePrefs(GetPrefService());
   translate_prefs->SetExplicitLanguageAskPromptShown(shown);
 }
+
+static void JNI_TranslateBridge_SetIgnoreMissingKeyForTesting(  // IN-TEST
+    JNIEnv* env,
+    jboolean ignore) {
+  translate::TranslateManager::SetIgnoreMissingKeyForTesting(  // IN-TEST
+      ignore);
+}
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index c7ff81d7..8ec60090 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1504,6 +1504,7 @@
       "//chrome/browser/resource_coordinator:tab_metrics_event_proto",
       "//chrome/browser/resource_coordinator/tab_ranker",
       "//chrome/browser/safe_browsing:advanced_protection",
+      "//chrome/browser/search/recipe_tasks:mojo_bindings",
       "//chrome/browser/search/shopping_tasks:mojo_bindings",
       "//chrome/browser/ui/color:color_headers",
       "//chrome/browser/ui/color:mixers",
diff --git a/chrome/browser/ui/android/appmenu/OWNERS b/chrome/browser/ui/android/appmenu/OWNERS
index 8e0277c4..285a2a8 100644
--- a/chrome/browser/ui/android/appmenu/OWNERS
+++ b/chrome/browser/ui/android/appmenu/OWNERS
@@ -1,5 +1,5 @@
 twellington@chromium.org
 
 # COMPONENT: UI>Browser>Mobile>AppMenu
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
 # OS: Android
diff --git a/chrome/browser/ui/android/default_browser_promo/OWNERS b/chrome/browser/ui/android/default_browser_promo/OWNERS
index b74b4df..87541d3 100644
--- a/chrome/browser/ui/android/default_browser_promo/OWNERS
+++ b/chrome/browser/ui/android/default_browser_promo/OWNERS
@@ -1,6 +1,6 @@
 lazzzis@google.com
 twellington@chromium.org
 
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
 # COMPONENT: UI>Browser>Mobile>Messages
 # OS: Android
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_gu.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_gu.xtb
index 709e7cc..06ec5dda 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_gu.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_gu.xtb
@@ -300,6 +300,7 @@
 <translation id="3211426585530211793"><ph name="ITEM_TITLE" /> કાઢી નાખી</translation>
 <translation id="3211503082155944789">વાંચ્યા વગરના <ph name="READING_LIST_COUNT" /> પેજ</translation>
 <translation id="321773570071367578">જો તમે તમારો પાસફ્રેઝ ભૂલી ગયાં હોવ અથવા આ સેટિંગ બદલવા માંગતા હોવ, તો <ph name="BEGIN_LINK" />સમન્વયનને ફરીથી સેટ કરો<ph name="END_LINK" /></translation>
+<translation id="3227557059438308877">સિક્યુરિટી કી તરીકે Google Chrome</translation>
 <translation id="3232754137068452469">વેબ ઍપ</translation>
 <translation id="3236059992281584593">1 મિનિટ બાકી</translation>
 <translation id="3244271242291266297">MM</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_iw.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_iw.xtb
index af12f8df..3527216 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_iw.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_iw.xtb
@@ -260,7 +260,7 @@
 <translation id="2892647708214602204">כשהקובץ הזה יהיה מוכן תופיע הודעה</translation>
 <translation id="2893180576842394309">‏Google עשויה להשתמש בהיסטוריית הגלישה שלך לצורך התאמה אישית של החיפוש ושירותי Google אחרים</translation>
 <translation id="2898264748040935573">עריכת הסיסמה השמורה</translation>
-<translation id="2900528713135656174">צור אירוע</translation>
+<translation id="2900528713135656174">יצירת אירוע</translation>
 <translation id="2901411048554510387">מוצגות הצעות הקשורות לדף <ph name="WEBSITE_TITLE" /></translation>
 <translation id="2904414404539560095">רשימת המכשירים שאפשר לשתף איתם כרטיסייה נפתחה בגובה המלא של המסך.</translation>
 <translation id="2905036901251765993">‏כדי לשתף עם אנשים בקרבת מקום, יש לתת להם לסרוק את קוד ה-QR הזה</translation>
@@ -295,7 +295,7 @@
 <translation id="3169472444629675720">Discover</translation>
 <translation id="3181954750937456830">גלישה בטוחה (מגנה עליך ועל המכשיר מפני אתרים מסוכנים)</translation>
 <translation id="3205824638308738187">כמעט סיימת!</translation>
-<translation id="3207960819495026254">מסומן בסימניה</translation>
+<translation id="3207960819495026254">מסומן בסימנייה</translation>
 <translation id="3208584281581115441">בדיקה עכשיו</translation>
 <translation id="3211426585530211793">מועד המחיקה: <ph name="ITEM_TITLE" /></translation>
 <translation id="3211503082155944789"><ph name="READING_LIST_COUNT" /> דפים שלא נקראו</translation>
@@ -311,7 +311,7 @@
 <translation id="3269956123044984603">‏כדי לקבל את הכרטיסיות מהמכשירים האחרים שלך, הפעל את האפשרות 'סנכרון אוטומטי של נתונים' בהגדרות של חשבון Android.</translation>
 <translation id="3282568296779691940">‏כניסה ל-Chrome</translation>
 <translation id="3285080554353377245">‏סרטוני הסבר על השימוש ב-Chrome</translation>
-<translation id="3288003805934695103">לטעון מחדש את הדף</translation>
+<translation id="3288003805934695103">הדף נטען מחדש</translation>
 <translation id="32895400574683172">יש הרשאה להצגת הודעות</translation>
 <translation id="3295530008794733555">יותר מהירות. פחות נתונים.</translation>
 <translation id="3298243779924642547">‏מצב Lite</translation>
@@ -514,7 +514,7 @@
 <translation id="4824958205181053313">לבטל את הסנכרון?</translation>
 <translation id="4831037795716408498">הורדת תוכן</translation>
 <translation id="4835385943915508971">‏ל-Chrome אין גישה למשאב המבוקש.</translation>
-<translation id="4837753911714442426">פתח אפשרויות להדפסת דפים</translation>
+<translation id="4837753911714442426">פתיחת אפשרויות להדפסת דפים</translation>
 <translation id="4842092870884894799">מציג את החלון הקופץ של יצירת סיסמה</translation>
 <translation id="4860895144060829044">תרימו טלפון</translation>
 <translation id="4864369630010738180">מתבצעת כניסה...</translation>
@@ -625,7 +625,7 @@
 <translation id="5648166631817621825">מהשבוע האחרון</translation>
 <translation id="5655963694829536461">חיפוש ההורדות שלך</translation>
 <translation id="5659593005791499971">אימייל</translation>
-<translation id="5665379678064389456">צור אירוע ב-<ph name="APP_NAME" /></translation>
+<translation id="5665379678064389456">יצירת אירוע ב-<ph name="APP_NAME" /></translation>
 <translation id="5668404140385795438">להתעלם מבקשה של אתר שנועדה למנוע את שינוי הזום</translation>
 <translation id="5683547024293500885">‏מערכת Chrome לא יכולה לבדוק אם יש עדכונים</translation>
 <translation id="5686790454216892815">שם הקובץ ארוך מדי</translation>
@@ -700,7 +700,7 @@
 <translation id="60923314841986378">נותרו <ph name="HOURS" /> שעות</translation>
 <translation id="6108923351542677676">ההגדרה מתבצעת…</translation>
 <translation id="6111020039983847643">צרכת בפועל</translation>
-<translation id="6112702117600201073">מרענן את הדף</translation>
+<translation id="6112702117600201073">רענון הדף מתבצע</translation>
 <translation id="6122831415929794347">להשבית את 'גלישה בטוחה'?</translation>
 <translation id="6127379762771434464">הפריט הוסר</translation>
 <translation id="6137022273846704445">השפה ב-<ph name="APP_NAME" /></translation>
@@ -778,7 +778,7 @@
 <translation id="6566259936974865419">‏Chrome חסך לך ‎<ph name="GIGABYTES" /> GB</translation>
 <translation id="6573096386450695060">אני רוצה לאפשר תמיד</translation>
 <translation id="6573431926118603307">‏כרטיסיות שפתחת ב-Chrome במכשירים האחרים שלך יופיעו כאן.</translation>
-<translation id="6583199322650523874">סמן את הדף הנוכחי בסימנייה</translation>
+<translation id="6583199322650523874">סימון הדף הנוכחי בסימנייה</translation>
 <translation id="6588043302623806746">‏שימוש ב-DNS מאובטח</translation>
 <translation id="6590471736817333463">חיסכון של עד 60% בשימוש בחבילת הגלישה</translation>
 <translation id="6590680911007613645">יש לוודא שהסיסמה שנשמרת זהה לסיסמה שלך עבור <ph name="SITE" /></translation>
@@ -809,7 +809,7 @@
 <translation id="670498945988402717">התבצעה בדיקה אתמול</translation>
 <translation id="6710213216561001401">הקודם</translation>
 <translation id="671481426037969117">זמן השימוש באפליקציה <ph name="FQDN" /> הסתיים. הטיימר יופעל מחדש מחר ואז אפשר יהיה להשתמש שוב באפליקציה.</translation>
-<translation id="6738867403308150051">מוריד...</translation>
+<translation id="6738867403308150051">ההורדה מתבצעת...</translation>
 <translation id="6767294960381293877">רשימת המכשירים שאפשר לשתף איתם כרטיסייה נפתחה בחצי גובה המסך.</translation>
 <translation id="6783942555455976443">שמירת הדף לקריאה במועד מאוחר יותר והגדרת תזכורת</translation>
 <translation id="6811034713472274749">הדף מוכן להצגה</translation>
@@ -835,7 +835,7 @@
 <translation id="6942665639005891494">ניתן תמיד לשנות את מיקום ברירת המחדל להורדות דרך האפשרות 'הגדרות' בתפריט</translation>
 <translation id="6945221475159498467">בחירה</translation>
 <translation id="6955535239952325894">ההגדרה הזו מושבתת בדפדפנים מנוהלים</translation>
-<translation id="6963766334940102469">מחק סימניות</translation>
+<translation id="6963766334940102469">מחיקת סימניות</translation>
 <translation id="6979737339423435258">משחר ההיסטוריה</translation>
 <translation id="6981982820502123353">נגישות</translation>
 <translation id="6989267951144302301">ההורדה נכשלה</translation>
@@ -915,12 +915,12 @@
 <translation id="753225086557513863">ההורדה תוזמנה למועד מאוחר יותר</translation>
 <translation id="7542481630195938534">לא ניתן לקבל הצעות</translation>
 <translation id="7559975015014302720">מצב הטעינה המהירה מושבת</translation>
-<translation id="7562080006725997899">מנקה נתוני גלישה</translation>
+<translation id="7562080006725997899">ניקוי נתוני הגלישה מתבצע</translation>
 <translation id="756809126120519699">‏נתוני Chrome נוקו</translation>
 <translation id="7577900504646297215">ניהול תחומי עניין</translation>
 <translation id="757855969265046257">{FILES,plural, =1{הורדת קובץ אחד (<ph name="FILES_DOWNLOADED_ONE" />)}two{הורדת <ph name="FILES_DOWNLOADED_MANY" /> קבצים}many{הורדת <ph name="FILES_DOWNLOADED_MANY" /> קבצים}other{הורדת <ph name="FILES_DOWNLOADED_MANY" /> קבצים}}</translation>
 <translation id="7588219262685291874">עיצוב כהה מופעל כשהמכשיר עובר לחיסכון בסוללה</translation>
-<translation id="7593557518625677601">‏פתח את הגדרות Android והפעל מחדש את הסנכרון של מערכת Android כדי להתחיל בסנכרון של Chrome</translation>
+<translation id="7593557518625677601">‏פתיחת הגדרות Android והפעלה מחדש של הסנכרון של מערכת Android כדי להתחיל בסנכרון של Chrome</translation>
 <translation id="7596558890252710462">מערכת הפעלה</translation>
 <translation id="7605594153474022051">הסנכרון לא עובד</translation>
 <translation id="7606077192958116810">מצב הטעינה המהירה מופעל. אפשר לנהל אותו דרך ההגדרות.</translation>
@@ -952,7 +952,7 @@
 <translation id="7778840695157240389">בהמשך יהיו פה סיפורים חדשים</translation>
 <translation id="7791543448312431591">הוספה</translation>
 <translation id="780301667611848630">לא תודה</translation>
-<translation id="7810647596859435254">פתח באמצעות...</translation>
+<translation id="7810647596859435254">פתיחה באמצעות...</translation>
 <translation id="7821588508402923572">ערכי החיסכון בנתונים יופיעו כאן</translation>
 <translation id="7844171778363018843">אין נתונים שנבחרו לסנכרון</translation>
 <translation id="7846296061357476882">‏שירותי Google</translation>
@@ -1008,7 +1008,7 @@
 <translation id="8186512483418048923">נותרו עוד <ph name="FILES" /> קבצים</translation>
 <translation id="8190358571722158785">נותר יום אחד</translation>
 <translation id="8200772114523450471">חידוש</translation>
-<translation id="8209050860603202033">פתח את התמונה</translation>
+<translation id="8209050860603202033">פתיחת התמונה</translation>
 <translation id="8216351761227087153">צפה</translation>
 <translation id="8218052821161047641">דף מהיר</translation>
 <translation id="8218622182176210845">ניהול החשבון</translation>
@@ -1045,8 +1045,8 @@
 <translation id="8466613982764129868">יש לוודא ש-<ph name="TARGET_DEVICE_NAME" /> מחובר לאינטרנט</translation>
 <translation id="8485434340281759656"><ph name="FILE_SIZE" /> <ph name="SEPARATOR" /> <ph name="DESCRIPTION" /></translation>
 <translation id="8487700953926739672">זמין במצב לא מקוון</translation>
-<translation id="8489271220582375723">פתח את דף ההיסטוריה</translation>
-<translation id="8493948351860045254">פנה שטח אחסון</translation>
+<translation id="8489271220582375723">פתיחת דף ההיסטוריה</translation>
+<translation id="8493948351860045254">פינוי נפח אחסון</translation>
 <translation id="8497726226069778601">אין מה לראות כאן… בינתיים</translation>
 <translation id="8503559462189395349">‏סיסמאות Chrome</translation>
 <translation id="8503813439785031346">שם משתמש</translation>
@@ -1055,7 +1055,7 @@
 <translation id="8516012719330875537">עורך תמונות</translation>
 <translation id="8523928698583292556">מחק את הסיסמה השמורה</translation>
 <translation id="8540136935098276800">‏יש להזין כתובת URL בפורמט חוקי</translation>
-<translation id="854522910157234410">פתח דף זה</translation>
+<translation id="854522910157234410">פתיחת דף זה</translation>
 <translation id="8555836665334561807">‏ב-Wi-Fi</translation>
 <translation id="8559990750235505898">הצעה לתרגם דפים בשפות אחרות</translation>
 <translation id="8560602726703398413">ניתן למצוא את רשימת הקריאה בקטע 'סימניות'</translation>
@@ -1069,7 +1069,7 @@
 <translation id="8616006591992756292">‏ייתכן שלחשבון Google שלך יהיו צורות אחרות של היסטוריית גלישה בכתובת <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
 <translation id="8617240290563765734">האם לעבור אל כתובת האתר שצוינה כהצעה בתוכן שהורדת?</translation>
 <translation id="8636825310635137004">כדי לקבל את הכרטיסיות מהמכשירים האחרים שלך, הפעל את הסנכרון.</translation>
-<translation id="8641930654639604085">נסה לחסום אתרים שמכילים תוכן למבוגרים</translation>
+<translation id="8641930654639604085">יש לנסות לחסום אתרים שמכילים תוכן למבוגרים</translation>
 <translation id="8655129584991699539">‏אפשר לנקות את הנתונים דרך הגדרות Chrome.</translation>
 <translation id="8656747343598256512">‏יש להיכנס לאתר זה ול-Chrome באמצעות חשבון Google שלך. אפשר להפעיל את הסנכרון מאוחר יותר.</translation>
 <translation id="8659579665266920523">‏איך לחפש באמצעות Chrome</translation>
@@ -1122,7 +1122,7 @@
 <translation id="9069543557624799859">ההורדה תתחיל בשעה <ph name="TIME" />.</translation>
 <translation id="9070377983101773829">התחל חיפוש קולי</translation>
 <translation id="9074336505530349563">‏כדי לקבל מ-Google הצעות לתוכן מותאם אישית, יש להיכנס ולהפעיל את הסנכרון</translation>
-<translation id="9086302186042011942">מסנכרן</translation>
+<translation id="9086302186042011942">הסנכרון מתבצע</translation>
 <translation id="9086455579313502267">אין אפשרות לגשת לרשת</translation>
 <translation id="9100505651305367705">יש להציע הצגת מאמרים בתצוגה פשוטה, כשהאפשרות נתמכת</translation>
 <translation id="9100610230175265781">יש להזין ביטוי סיסמה</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_or.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_or.xtb
index 2c7aa4a7..d0ab41f 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_or.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_or.xtb
@@ -300,6 +300,7 @@
 <translation id="3211426585530211793"><ph name="ITEM_TITLE" />କୁ ଡିଲିଟ୍ କରାଗଲା।</translation>
 <translation id="3211503082155944789"><ph name="READING_LIST_COUNT" />ଟି ଅପଠିତ ପୃଷ୍ଠା</translation>
 <translation id="321773570071367578">ଯଦି ଆପଣ ନିଜର ପାସ୍‌ଫ୍ରେଜ୍ ଭୁଲିଯାଇଛନ୍ତି କିମ୍ବା ଏହି ସେଟିଂ ପରିବର୍ତ୍ତନ କରିବାକୁ ଚାହୁଁଛନ୍ତି, ତେବେ <ph name="BEGIN_LINK" />ସିଙ୍କ୍ ରିସେଟ୍ କରନ୍ତୁ<ph name="END_LINK" />।</translation>
+<translation id="3227557059438308877">ଏକ ସୁରକ୍ଷା କୀ ଭାବେ Google Chromeର ବ୍ୟବହାର</translation>
 <translation id="3232754137068452469">ୱେବ୍ ଆପ୍</translation>
 <translation id="3236059992281584593">ଅବଶିଷ୍ଟ 1 ମିନଟ୍‌ ଅଛି</translation>
 <translation id="3244271242291266297">ମାସ</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pa.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pa.xtb
index 7065fac..10ff007 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pa.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pa.xtb
@@ -261,7 +261,7 @@
 <translation id="2893180576842394309">Google ਖੋਜ ਅਤੇ ਹੋਰਾਂ Google ਸੇਵਾਵਾਂ ਨੂੰ ਵਿਅਕਤੀਗਤ ਬਣਾਉਣ ਲਈ ਤੁਹਾਡੇ ਇਤਿਹਾਸ ਦੀ ਵਰਤੋਂ ਕਰ ਸਕਦਾ ਹੈ</translation>
 <translation id="2898264748040935573">ਸਟੋਰ ਕੀਤੇ ਪਾਸਵਰਡ ਦਾ ਸੰਪਾਦਨ ਕਰੋ</translation>
 <translation id="2900528713135656174">ਵਰਤਾਰਾ ਬਣਾਓ</translation>
-<translation id="2901411048554510387"><ph name="WEBSITE_TITLE" /> ਦੇ ਸੁਝਾਅ ਦਿਖਾਏ ਜਾ ਰਹੇ ਹਨ</translation>
+<translation id="2901411048554510387"><ph name="WEBSITE_TITLE" /> ਲਈ ਸੁਝਾਅ ਦਿਖਾਏ ਜਾ ਰਹੇ ਹਨ</translation>
 <translation id="2904414404539560095">ਕਿਸੇ ਟੈਬ ਨੂੰ ਸਾਂਝਾ ਕਰਨ ਵਾਲੇ ਡੀਵਾਈਸਾਂ ਦੀ ਸੂਚੀ ਪੂਰੀ ਉਚਾਈ 'ਤੇ ਖੁੱਲ੍ਹੀ ਹੋਈ ਹੈ।</translation>
 <translation id="2905036901251765993">ਨਜ਼ਦੀਕੀ ਲੋਕਾਂ ਨਾਲ ਸਾਂਝਾ ਕਰਨ ਲਈ, ਉਹਨਾਂ ਨੂੰ ਇਹ QR ਕੋਡ ਸਕੈਨ ਕਰਨ ਦਿਓ</translation>
 <translation id="2909615210195135082">Google ਸੂਚਨਾਵਾਂ ਪਲੇਟਫਾਰਮ</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_te.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_te.xtb
index 40329a3f..123199c7 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_te.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_te.xtb
@@ -300,6 +300,7 @@
 <translation id="3211426585530211793"><ph name="ITEM_TITLE" /> తొలగించబడింది</translation>
 <translation id="3211503082155944789"><ph name="READING_LIST_COUNT" /> చదవని పేజీలు</translation>
 <translation id="321773570071367578">మీరు మీ రహస్య పదబంధాన్ని మర్చిపోతే లేదా ఈ సెట్టింగ్‌ను మార్చాలనుకుంటే, <ph name="BEGIN_LINK" />సింక్‌ను రీసెట్ చేయండి<ph name="END_LINK" /></translation>
+<translation id="3227557059438308877">'సెక్యూరిటీ కీ'గా Google Chrome</translation>
 <translation id="3232754137068452469">వెబ్ యాప్‌</translation>
 <translation id="3236059992281584593">1 నిమిషం మిగిలి ఉంది</translation>
 <translation id="3244271242291266297">MM</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_vi.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_vi.xtb
index 9b48a07c..5d79e34 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_vi.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_vi.xtb
@@ -16,7 +16,7 @@
 <translation id="1105960400813249514">Chụp ảnh màn hình</translation>
 <translation id="1111673857033749125">Dấu trang được lưu trên thiết bị khác của bạn sẽ xuất hiện tại đây.</translation>
 <translation id="1113597929977215864">Hiển thị chế độ xem đơn giản</translation>
-<translation id="1123070903960493543">Cách bạn tương tác với Chrome, các tùy chọn cài đặt bạn đã chọn, thông tin chi tiết về sự cố mà Chrome gặp phải</translation>
+<translation id="1123070903960493543">Cách bạn tương tác với Chrome, các tùy chọn cài đặt bạn đã chọn, thông tin chi tiết về sự cố của Chrome</translation>
 <translation id="1126809382673880764">Không bảo vệ bạn trước các trang web, tệp đã tải xuống và tiện ích nguy hiểm. Bạn sẽ vẫn được bảo vệ bằng tính năng Duyệt web an toàn (nếu có) ở các dịch vụ khác của Google, chẳng hạn như Gmail và Tìm kiếm.</translation>
 <translation id="1129510026454351943">Chi tiết: <ph name="ERROR_DESCRIPTION" /></translation>
 <translation id="1141800923049248244">{FILE_COUNT,plural, =1{1 tệp đang chờ tải xuống.}other{# tệp đang chờ tải xuống.}}</translation>
@@ -169,7 +169,7 @@
 <translation id="2175927920773552910">Mã QR</translation>
 <translation id="218608176142494674">Chia sẻ</translation>
 <translation id="2195339740518523951">Tận dụng mức bảo mật mạnh nhất của Chrome</translation>
-<translation id="2200113223741723867">Quản lý tùy chọn chia sẻ dữ liệu sử dụng</translation>
+<translation id="2200113223741723867">Quản lý cách chia sẻ dữ liệu sử dụng</translation>
 <translation id="2227444325776770048">Tiếp tục bằng <ph name="USER_FULL_NAME" /></translation>
 <translation id="2234876718134438132">Đồng bộ hóa và các dịch vụ của Google</translation>
 <translation id="2239812875700136898">Kiểm soát các tin bài của bạn bằng các Tùy chọn của nút Khám phá</translation>
diff --git a/chrome/browser/ui/app_list/app_service/app_service_app_model_builder.cc b/chrome/browser/ui/app_list/app_service/app_service_app_model_builder.cc
index 192bdcec..da3cd89 100644
--- a/chrome/browser/ui/app_list/app_service/app_service_app_model_builder.cc
+++ b/chrome/browser/ui/app_list/app_service/app_service_app_model_builder.cc
@@ -50,15 +50,12 @@
   void OnAppListItemAdded(ChromeAppListItem* item) override {
     if (item->id() != crostini::kCrostiniFolderId)
       return;
-    // Persistence is not recorded by the sync, so we always set it.
-    item->SetIsPersistent(true);
 
-    // Either the name and position will be in the sync, or we set them
-    // manually.
-    if (parent_->GetSyncItem(crostini::kCrostiniFolderId,
-                             sync_pb::AppListSpecifics::TYPE_FOLDER)) {
-      return;
-    }
+    // We reset the state of the folder whether it's in the sync service or not
+    // to ensure the "Linux apps" string is translated into the current
+    // language, even if that's a different language then the folder was created
+    // with.
+    item->SetIsPersistent(true);
     item->SetName(
         l10n_util::GetStringUTF8(IDS_APP_LIST_CROSTINI_DEFAULT_FOLDER_NAME));
     item->SetDefaultPositionIfApplicable(parent_->model_updater());
diff --git a/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.cc b/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.cc
index 65308eb..62c520c7 100644
--- a/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.cc
+++ b/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.cc
@@ -19,8 +19,11 @@
 #include "base/task/thread_pool.h"
 #include "base/task_runner_util.h"
 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
+#include "chromeos/constants/chromeos_pref_names.h"
 #include "components/drive/file_errors.h"
+#include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
@@ -79,8 +82,16 @@
   // Warm the results cache if or when drivefs is mounted by fetching from the
   // Drive QuickAccess API. This is necessary only if the suggested files
   // experiment is enabled, so that results are ready for display in the
-  // suggested chips on the first launcher open after login.
-  if (suggested_files_enabled_ && drive_service_) {
+  // suggested chips on the first launcher open after login. To prevent
+  // unnecessary queries to ItemSuggest, only warm the cache if the launcher has
+  // been used before.
+  const bool launcher_used = profile->GetPrefs()->GetBoolean(
+      chromeos::prefs::kLauncherResultEverLaunched);
+  const bool gate_on_use = base::GetFieldTrialParamByFeatureAsBool(
+      app_list_features::kEnableSuggestedFiles, "gate_warm_on_launcher_use",
+      true);
+  const bool should_warm = !gate_on_use || launcher_used;
+  if (suggested_files_enabled_ && drive_service_ && should_warm) {
     if (drive_service_->IsMounted()) {
       // Drivefs is mounted, so we can fetch results immediately.
       OnFileSystemMounted();
diff --git a/chrome/browser/ui/app_list/search/search_controller.cc b/chrome/browser/ui/app_list/search/search_controller.cc
index b5118be7a..2abda4bd 100644
--- a/chrome/browser/ui/app_list/search/search_controller.cc
+++ b/chrome/browser/ui/app_list/search/search_controller.cc
@@ -29,7 +29,9 @@
 #include "chrome/browser/ui/app_list/search/search_result_ranker/histogram_util.h"
 #include "chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.h"
 #include "chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker.h"
+#include "chromeos/constants/chromeos_pref_names.h"
 #include "components/metrics/structured/structured_events.h"
+#include "components/prefs/pref_service.h"
 
 namespace app_list {
 
@@ -246,6 +248,9 @@
     }
   }
 
+  profile_->GetPrefs()->SetBoolean(chromeos::prefs::kLauncherResultEverLaunched,
+                                   true);
+
   // CrOS action recorder.
   CrOSActionRecorder::GetCrosActionRecorder()->RecordAction(
       {base::StrCat(
diff --git a/chrome/browser/ui/ash/assistant/assistant_web_view_impl.cc b/chrome/browser/ui/ash/assistant/assistant_web_view_impl.cc
index 7fa09d2..672d5d41 100644
--- a/chrome/browser/ui/ash/assistant/assistant_web_view_impl.cc
+++ b/chrome/browser/ui/ash/assistant/assistant_web_view_impl.cc
@@ -10,7 +10,7 @@
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "ui/aura/window.h"
 #include "ui/views/controls/webview/web_contents_set_background_color.h"
 #include "ui/views/controls/webview/webview.h"
diff --git a/chrome/browser/ui/ash/in_session_auth_dialog_client.cc b/chrome/browser/ui/ash/in_session_auth_dialog_client.cc
index d610aa57..2a575bb8 100644
--- a/chrome/browser/ui/ash/in_session_auth_dialog_client.cc
+++ b/chrome/browser/ui/ash/in_session_auth_dialog_client.cc
@@ -119,7 +119,6 @@
         user_context.GetAccountId(), *user_context.GetKey(),
         base::BindOnce(&InSessionAuthDialogClient::OnPinAttemptDone,
                        weak_factory_.GetWeakPtr(), user_context));
-    // OnPinAttemptDone will call AuthenticateWithPassword if attempt fails.
     return;
   }
 
@@ -143,8 +142,11 @@
     }
     OnAuthSuccess(user_context);
   } else {
-    // PIN authentication has failed; try submitting as a normal password.
-    AuthenticateWithPassword(user_context);
+    // Do not try submitting as password.
+    if (pending_auth_state_) {
+      std::move(pending_auth_state_->callback).Run(false);
+      pending_auth_state_.reset();
+    }
   }
 }
 
diff --git a/chrome/browser/ui/ash/in_session_auth_dialog_client_unittest.cc b/chrome/browser/ui/ash/in_session_auth_dialog_client_unittest.cc
index 79fcb07..6d3a7443 100644
--- a/chrome/browser/ui/ash/in_session_auth_dialog_client_unittest.cc
+++ b/chrome/browser/ui/ash/in_session_auth_dialog_client_unittest.cc
@@ -42,9 +42,8 @@
   void SetClient(ash::InSessionAuthDialogClient* client) override {}
   void ShowAuthenticationDialog(FinishCallback callback) override {}
   void DestroyAuthenticationDialog() override {}
-  void AuthenticateUserWithPasswordOrPin(
-      const std::string& password,
-      OnAuthenticateCallback callback) override {}
+  void AuthenticateUserWithPin(const std::string& pin,
+                               OnAuthenticateCallback callback) override {}
   void AuthenticateUserWithFingerprint(
       base::OnceCallback<void(bool, ash::FingerprintState)> callback) override {
   }
diff --git a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
index 2aa3f3f..6376220f 100644
--- a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
+++ b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
@@ -453,7 +453,8 @@
       embedded_test_server()->GetURL("/popup_blocker/popup-on-unload.html"));
   ui_test_utils::NavigateToURL(browser(), url);
 
-  GURL url2(embedded_test_server()->GetURL("/popup_blocker/"));
+  GURL url2(
+      embedded_test_server()->GetURL("/popup_blocker/popup-success.html"));
   ui_test_utils::NavigateToURL(browser(), url2);
 
   // Expect no popup.
@@ -520,8 +521,9 @@
   DisableProactiveBrowsingInstanceSwapFor(
       browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame());
 
-  NavigateAndCheckPopupShown(embedded_test_server()->GetURL("/popup_blocker/"),
-                             kExpectPopup);
+  NavigateAndCheckPopupShown(
+      embedded_test_server()->GetURL("/popup_blocker/popup-success.html"),
+      kExpectPopup);
 }
 
 // Verify that when you unblock popup, the popup shows in history and omnibox.
diff --git a/chrome/browser/ui/bookmarks/bookmark_bubble_sign_in_delegate.h b/chrome/browser/ui/bookmarks/bookmark_bubble_sign_in_delegate.h
index f556694..f20edac2 100644
--- a/chrome/browser/ui/bookmarks/bookmark_bubble_sign_in_delegate.h
+++ b/chrome/browser/ui/bookmarks/bookmark_bubble_sign_in_delegate.h
@@ -19,8 +19,6 @@
                                      public BrowserListObserver {
  public:
   explicit BookmarkBubbleSignInDelegate(Browser* browser);
-
- private:
   ~BookmarkBubbleSignInDelegate() override;
 
   // BubbleSyncPromoDelegate:
@@ -29,6 +27,7 @@
   // BrowserListObserver:
   void OnBrowserRemoved(Browser* browser) override;
 
+ private:
   // Makes sure |browser_| points to a valid browser.
   void EnsureBrowser();
 
diff --git a/chrome/browser/ui/extensions/hosted_app_browser_controller.cc b/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
index 46cf9f2f..ec3184ea 100644
--- a/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
+++ b/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
@@ -36,7 +36,6 @@
 #include "extensions/common/extension.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "ui/gfx/image/image_skia.h"
 #include "url/gurl.h"
 
diff --git a/chrome/browser/ui/extensions/hosted_app_browsertest.cc b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
index 6f37d81..893f2dc 100644
--- a/chrome/browser/ui/extensions/hosted_app_browsertest.cc
+++ b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
@@ -81,8 +81,8 @@
 #include "testing/gtest/include/gtest/gtest-param-test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 
 using content::RenderFrameHost;
 using content::WebContents;
@@ -129,14 +129,12 @@
 }
 
 void CheckWebContentsHasAppPrefs(content::WebContents* web_contents) {
-  blink::mojom::RendererPreferences* prefs =
-      web_contents->GetMutableRendererPrefs();
+  blink::RendererPreferences* prefs = web_contents->GetMutableRendererPrefs();
   EXPECT_FALSE(prefs->can_accept_load_drops);
 }
 
 void CheckWebContentsDoesNotHaveAppPrefs(content::WebContents* web_contents) {
-  blink::mojom::RendererPreferences* prefs =
-      web_contents->GetMutableRendererPrefs();
+  blink::RendererPreferences* prefs = web_contents->GetMutableRendererPrefs();
   EXPECT_TRUE(prefs->can_accept_load_drops);
 }
 
diff --git a/chrome/browser/ui/login/login_handler.h b/chrome/browser/ui/login/login_handler.h
index 0b30e950..0c2ae0a 100644
--- a/chrome/browser/ui/login/login_handler.h
+++ b/chrome/browser/ui/login/login_handler.h
@@ -16,6 +16,7 @@
 #include "base/optional.h"
 #include "base/synchronization/lock.h"
 #include "components/password_manager/core/browser/http_auth_manager.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/global_request_id.h"
 #include "content/public/browser/login_delegate.h"
@@ -45,10 +46,10 @@
   // the constructor DCHECKs that |login_model| is not null.
   struct LoginModelData {
     LoginModelData(password_manager::HttpAuthManager* login_model,
-                   const autofill::PasswordForm& observed_form);
+                   const password_manager::PasswordForm& observed_form);
 
     password_manager::HttpAuthManager* const model;
-    const autofill::PasswordForm& form;
+    const password_manager::PasswordForm& form;
   };
 
   ~LoginHandler() override;
@@ -166,7 +167,7 @@
 
   // Helper to create a PasswordForm for PasswordManager to start looking for
   // saved credentials.
-  static autofill::PasswordForm MakeInputForPasswordManager(
+  static password_manager::PasswordForm MakeInputForPasswordManager(
       const GURL& url,
       const net::AuthChallengeInfo& auth_info);
 
@@ -201,7 +202,7 @@
   // The PasswordForm sent to the PasswordManager. This is so we can refer to it
   // when later notifying the password manager if the credentials were accepted
   // or rejected.  This should only be accessed on the UI loop.
-  autofill::PasswordForm password_form_;
+  password_manager::PasswordForm password_form_;
 
   // Observes other login handlers so this login handler can respond.
   content::NotificationRegistrar registrar_;
diff --git a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
index 30b53de..e3d4081 100644
--- a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
+++ b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
@@ -895,7 +895,11 @@
 #define MAYBE_AcceptKeywordBySpace AcceptKeywordBySpace
 #endif
 IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_AcceptKeywordBySpace) {
-  OmniboxView* omnibox_view = NULL;
+  // AcceptKeywordBySpace is disabled when keyword search button is enabled.
+  if (OmniboxFieldTrial::IsKeywordSearchButtonEnabled())
+    return;
+
+  OmniboxView* omnibox_view = nullptr;
   ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
 
   base::string16 search_keyword(ASCIIToUTF16(kSearchKeyword));
diff --git a/chrome/browser/ui/passwords/passwords_model_delegate_mock.h b/chrome/browser/ui/passwords/passwords_model_delegate_mock.h
index fec611ef..11e4207 100644
--- a/chrome/browser/ui/passwords/passwords_model_delegate_mock.h
+++ b/chrome/browser/ui/passwords/passwords_model_delegate_mock.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ui/passwords/passwords_model_delegate.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 class PasswordsModelDelegateMock
diff --git a/chrome/browser/ui/prefs/pref_watcher.cc b/chrome/browser/ui/prefs/pref_watcher.cc
index af8ceaa..53c49e2 100644
--- a/chrome/browser/ui/prefs/pref_watcher.cc
+++ b/chrome/browser/ui/prefs/pref_watcher.cc
@@ -14,7 +14,7 @@
 #include "chrome/common/pref_names.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/language/core/browser/pref_names.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 
 #if defined(OS_CHROMEOS)
 #include "ash/public/cpp/ash_pref_names.h"
@@ -140,10 +140,10 @@
   for (auto* helper : tab_helpers_)
     helper->UpdateRendererPreferences();
 
-  blink::mojom::RendererPreferences prefs;
+  blink::RendererPreferences prefs;
   renderer_preferences_util::UpdateFromSystemSettings(&prefs, profile_);
   for (auto& watcher : renderer_preference_watchers_)
-    watcher->NotifyUpdate(prefs.Clone());
+    watcher->NotifyUpdate(prefs);
 }
 
 void PrefWatcher::OnWebPrefChanged(const std::string& pref_name) {
diff --git a/chrome/browser/ui/prefs/pref_watcher.h b/chrome/browser/ui/prefs/pref_watcher.h
index a439b2ce..78d5b76 100644
--- a/chrome/browser/ui/prefs/pref_watcher.h
+++ b/chrome/browser/ui/prefs/pref_watcher.h
@@ -15,8 +15,8 @@
 class Profile;
 class PrefsTabHelper;
 
-// Watches updates in WebKitPreferences and blink::mojom::RendererPreferences,
-// and notifies tab helpers and registered watchers of those updates.
+// Watches updates in WebKitPreferences and blink::RendererPreferences, and
+// notifies tab helpers and registered watchers of those updates.
 class PrefWatcher : public KeyedService {
  public:
   explicit PrefWatcher(Profile* profile);
@@ -42,11 +42,11 @@
   PrefChangeRegistrar local_state_pref_change_registrar_;
 
   // |tab_helpers_| observe changes in WebKitPreferences and
-  // blink::mojom::RendererPreferences.
+  // blink::RendererPreferences.
   std::set<PrefsTabHelper*> tab_helpers_;
 
   // |renderer_preference_watchers_| observe changes in
-  // blink::mojom::RendererPreferences. If the consumer also wants to WebKit
+  // blink::RendererPreferences. If the consumer also wants to WebKit
   // preference changes, use |tab_helpers_|.
   mojo::RemoteSet<blink::mojom::RendererPreferenceWatcher>
       renderer_preference_watchers_;
diff --git a/chrome/browser/ui/prefs/prefs_tab_helper.cc b/chrome/browser/ui/prefs/prefs_tab_helper.cc
index 97d147c..4a60728 100644
--- a/chrome/browser/ui/prefs/prefs_tab_helper.cc
+++ b/chrome/browser/ui/prefs/prefs_tab_helper.cc
@@ -43,8 +43,8 @@
 #include "extensions/buildflags/buildflags.h"
 #include "media/media_buildflags.h"
 #include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "third_party/icu/source/common/unicode/uchar.h"
 #include "third_party/icu/source/common/unicode/uscript.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -314,7 +314,7 @@
     PrefWatcher::Get(profile_)->RegisterHelper(this);
   }
 
-  blink::mojom::RendererPreferences* render_prefs =
+  blink::RendererPreferences* render_prefs =
       web_contents_->GetMutableRendererPrefs();
   renderer_preferences_util::UpdateFromSystemSettings(render_prefs, profile_);
 
@@ -448,8 +448,7 @@
 }
 
 void PrefsTabHelper::UpdateRendererPreferences() {
-  blink::mojom::RendererPreferences* prefs =
-      web_contents_->GetMutableRendererPrefs();
+  blink::RendererPreferences* prefs = web_contents_->GetMutableRendererPrefs();
   renderer_preferences_util::UpdateFromSystemSettings(prefs, profile_);
   web_contents_->SyncRendererPrefs();
 }
diff --git a/chrome/browser/ui/prefs/prefs_tab_helper.h b/chrome/browser/ui/prefs/prefs_tab_helper.h
index 8e28476..9bedc7c 100644
--- a/chrome/browser/ui/prefs/prefs_tab_helper.h
+++ b/chrome/browser/ui/prefs/prefs_tab_helper.h
@@ -51,7 +51,7 @@
                const content::NotificationSource& source,
                const content::NotificationDetails& details) override;
 
-  // Update the WebContents's blink::mojom::RendererPreferences.
+  // Update the WebContents's blink::RendererPreferences.
   void UpdateRendererPreferences();
 
   void OnFontFamilyPrefChanged(const std::string& pref_name);
diff --git a/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc b/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc
index 248ee1f..59a83bafe 100644
--- a/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc
+++ b/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc
@@ -79,6 +79,14 @@
   return http_response;
 }
 
+std::unique_ptr<net::test_server::BasicHttpResponse> CreateNonEmptyResponse(
+    net::HttpStatusCode code) {
+  auto http_response = std::make_unique<net::test_server::BasicHttpResponse>();
+  http_response->set_code(code);
+  http_response->set_content("<html>");
+  return http_response;
+}
+
 std::unique_ptr<net::test_server::HttpResponse> HandleReauthURL(
     const GURL& base_url,
     const net::test_server::HttpRequest& request) {
@@ -101,8 +109,10 @@
   }
 
   if (parameter == "unexpected") {
-    // Returns a response that isn't expected by Chrome.
-    return CreateEmptyResponse(net::HTTP_NOT_IMPLEMENTED);
+    // Returns a response that isn't expected by Chrome. Note that we shouldn't
+    // return an empty response here because that will result in an error page
+    // being committed for the navigation.
+    return CreateNonEmptyResponse(net::HTTP_NOT_IMPLEMENTED);
   }
 
   NOTREACHED();
diff --git a/chrome/browser/ui/views/accessibility/caret_browsing_dialog_delegate.cc b/chrome/browser/ui/views/accessibility/caret_browsing_dialog_delegate.cc
index 770273e..22ae9f5 100644
--- a/chrome/browser/ui/views/accessibility/caret_browsing_dialog_delegate.cc
+++ b/chrome/browser/ui/views/accessibility/caret_browsing_dialog_delegate.cc
@@ -81,17 +81,10 @@
         base::UserMetricsAction("Accessibility.CaretBrowsing.CancelDialog"));
   };
   SetCancelCallback(base::BindOnce(on_cancel));
+
+  SetModalType(ui::MODAL_TYPE_WINDOW);
+  set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric(
+      views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH));
 }
 
-CaretBrowsingDialogDelegate::~CaretBrowsingDialogDelegate() {}
-
-ui::ModalType CaretBrowsingDialogDelegate::GetModalType() const {
-  return ui::MODAL_TYPE_WINDOW;
-}
-
-gfx::Size CaretBrowsingDialogDelegate::CalculatePreferredSize() const {
-  const int width = ChromeLayoutProvider::Get()->GetDistanceMetric(
-                        views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH) -
-                    margins().width();
-  return gfx::Size(width, GetHeightForWidth(width));
-}
+CaretBrowsingDialogDelegate::~CaretBrowsingDialogDelegate() = default;
diff --git a/chrome/browser/ui/views/accessibility/caret_browsing_dialog_delegate.h b/chrome/browser/ui/views/accessibility/caret_browsing_dialog_delegate.h
index a0a07a42..7f9c8d4 100644
--- a/chrome/browser/ui/views/accessibility/caret_browsing_dialog_delegate.h
+++ b/chrome/browser/ui/views/accessibility/caret_browsing_dialog_delegate.h
@@ -26,11 +26,7 @@
       delete;
   ~CaretBrowsingDialogDelegate() override;
 
-  // DialogDelegateView.
-  ui::ModalType GetModalType() const override;
-  gfx::Size CalculatePreferredSize() const override;
-
-  PrefService* pref_service_;
+  PrefService* const pref_service_;
 
   // Checkbox where the user can say they don't want to be asked when they
   // toggle caret browsing next time.
diff --git a/chrome/browser/ui/views/arc_app_dialog_view.cc b/chrome/browser/ui/views/arc_app_dialog_view.cc
index 81e5a86..a250fd72 100644
--- a/chrome/browser/ui/views/arc_app_dialog_view.cc
+++ b/chrome/browser/ui/views/arc_app_dialog_view.cc
@@ -56,14 +56,6 @@
   void ConfirmOrCancelForTest(bool confirm);
 
  private:
-  // views::WidgetDelegate:
-  base::string16 GetWindowTitle() const override;
-  ui::ModalType GetModalType() const override;
-  bool ShouldShowCloseButton() const override;
-
-  // views::View:
-  gfx::Size CalculatePreferredSize() const override;
-
   // AppIconLoaderDelegate:
   void OnAppImageUpdated(const std::string& app_id,
                          const gfx::ImageSkia& image) override;
@@ -80,7 +72,6 @@
   Profile* const profile_;
 
   const std::string app_id_;
-  const base::string16 window_title_;
   ArcAppConfirmCallback confirm_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(ArcAppDialogView);
@@ -100,8 +91,8 @@
                                    ArcAppConfirmCallback confirm_callback)
     : profile_(profile),
       app_id_(app_id),
-      window_title_(window_title),
       confirm_callback_(std::move(confirm_callback)) {
+  SetTitle(window_title);
   SetButtonLabel(ui::DIALOG_BUTTON_OK, confirm_button_text);
   SetButtonLabel(ui::DIALOG_BUTTON_CANCEL, cancel_button_text);
   SetAcceptCallback(base::BindOnce(&ArcAppDialogView::OnDialogAccepted,
@@ -116,6 +107,11 @@
       provider->GetDialogInsetsForContentType(views::TEXT, views::TEXT),
       provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL)));
 
+  SetModalType(ui::MODAL_TYPE_WINDOW);
+  SetShowCloseButton(false);
+  set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric(
+      views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH));
+
   auto icon_view = std::make_unique<views::ImageView>();
   icon_view->SetPreferredSize(gfx::Size(kArcAppIconSize, kArcAppIconSize));
   icon_view_ = AddChildView(std::move(icon_view));
@@ -170,18 +166,6 @@
   }
 }
 
-base::string16 ArcAppDialogView::GetWindowTitle() const {
-  return window_title_;
-}
-
-ui::ModalType ArcAppDialogView::GetModalType() const {
-  return ui::MODAL_TYPE_WINDOW;
-}
-
-bool ArcAppDialogView::ShouldShowCloseButton() const {
-  return false;
-}
-
 void ArcAppDialogView::OnDialogAccepted() {
   // The dialog can either be accepted or cancelled, but never both.
   DCHECK(confirm_callback_);
@@ -194,12 +178,6 @@
   std::move(confirm_callback_).Run(false);
 }
 
-gfx::Size ArcAppDialogView::CalculatePreferredSize() const {
-  const int default_width = views::LayoutProvider::Get()->GetDistanceMetric(
-      views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH);
-  return gfx::Size(default_width, GetHeightForWidth(default_width));
-}
-
 void ArcAppDialogView::OnAppImageUpdated(const std::string& app_id,
                                          const gfx::ImageSkia& image) {
   DCHECK_EQ(app_id, app_id_);
diff --git a/chrome/browser/ui/views/arc_data_removal_dialog_view.cc b/chrome/browser/ui/views/arc_data_removal_dialog_view.cc
index 68c0b6e..5a5d54c 100644
--- a/chrome/browser/ui/views/arc_data_removal_dialog_view.cc
+++ b/chrome/browser/ui/views/arc_data_removal_dialog_view.cc
@@ -46,13 +46,6 @@
       DataRemovalConfirmationCallback confirm_data_removal);
   ~DataRemovalConfirmationDialog() override;
 
-  // views::WidgetDelegate:
-  base::string16 GetWindowTitle() const override;
-  ui::ModalType GetModalType() const override;
-
-  // views::View:
-  gfx::Size CalculatePreferredSize() const override;
-
   // AppIconLoaderDelegate:
   void OnAppImageUpdated(const std::string& app_id,
                          const gfx::ImageSkia& image) override;
@@ -79,6 +72,7 @@
     Profile* profile,
     DataRemovalConfirmationCallback confirm_callback)
     : profile_(profile), confirm_callback_(std::move(confirm_callback)) {
+  SetTitle(l10n_util::GetStringUTF16(IDS_ARC_DATA_REMOVAL_CONFIRMATION_TITLE));
   SetButtonLabel(
       ui::DIALOG_BUTTON_OK,
       l10n_util::GetStringUTF16(IDS_ARC_DATA_REMOVAL_CONFIRMATION_OK_BUTTON));
@@ -90,6 +84,10 @@
   SetCancelCallback(
       base::BindOnce(run_callback, base::Unretained(this), false));
 
+  SetModalType(ui::MODAL_TYPE_WINDOW);
+  set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric(
+      views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH));
+
   ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
 
   std::unique_ptr<views::BoxLayout> layout = std::make_unique<views::BoxLayout>(
@@ -130,20 +128,6 @@
   g_current_data_removal_confirmation = nullptr;
 }
 
-base::string16 DataRemovalConfirmationDialog::GetWindowTitle() const {
-  return l10n_util::GetStringUTF16(IDS_ARC_DATA_REMOVAL_CONFIRMATION_TITLE);
-}
-
-ui::ModalType DataRemovalConfirmationDialog::GetModalType() const {
-  return ui::MODAL_TYPE_WINDOW;
-}
-
-gfx::Size DataRemovalConfirmationDialog::CalculatePreferredSize() const {
-  const int default_width = views::LayoutProvider::Get()->GetDistanceMetric(
-      views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH);
-  return gfx::Size(default_width, GetHeightForWidth(default_width));
-}
-
 void DataRemovalConfirmationDialog::OnAppImageUpdated(
     const std::string& app_id,
     const gfx::ImageSkia& image) {
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc b/chrome/browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc
index 91d8b107..d1e6a1ac 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc
@@ -131,8 +131,8 @@
 
   int starting_tab_count = extra_browser->tab_strip_model()->count();
 
-  std::unique_ptr<BubbleSyncPromoDelegate> delegate;
-  delegate.reset(new BookmarkBubbleSignInDelegate(browser()));
+  std::unique_ptr<BubbleSyncPromoDelegate> delegate =
+      std::make_unique<BookmarkBubbleSignInDelegate>(browser());
 
   BrowserList::SetLastActive(extra_browser);
 
diff --git a/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc b/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc
index 7a23e7d..6f6f4c0 100644
--- a/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc
+++ b/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc
@@ -283,8 +283,7 @@
   WebContentsObserver::Observe(web_contents_);
   zoom::ZoomController::CreateForWebContents(web_contents_);
   web_contents_->SetDelegate(override_tab_delegate_.get());
-  blink::mojom::RendererPreferences* prefs =
-      web_contents_->GetMutableRendererPrefs();
+  blink::RendererPreferences* prefs = web_contents_->GetMutableRendererPrefs();
   renderer_preferences_util::UpdateFromSystemSettings(
       prefs, Profile::FromBrowserContext(browser_context));
 
diff --git a/chrome/browser/ui/views/folder_upload_confirmation_view.cc b/chrome/browser/ui/views/folder_upload_confirmation_view.cc
index fcc2153c..ce5a4927 100644
--- a/chrome/browser/ui/views/folder_upload_confirmation_view.cc
+++ b/chrome/browser/ui/views/folder_upload_confirmation_view.cc
@@ -22,6 +22,10 @@
     std::vector<ui::SelectedFileInfo> selected_files)
     : callback_(std::move(callback)),
       selected_files_(std::move(selected_files)) {
+  SetTitle(l10n_util::GetPluralStringFUTF16(
+      IDS_CONFIRM_FILE_UPLOAD_TITLE,
+      base::saturated_cast<int>(selected_files_.size())));
+
   SetButtonLabel(ui::DIALOG_BUTTON_OK,
                  l10n_util::GetStringUTF16(IDS_CONFIRM_FILE_UPLOAD_OK_BUTTON));
 
@@ -41,6 +45,11 @@
       },
       base::Unretained(this)));
 
+  SetModalType(ui::MODAL_TYPE_CHILD);
+  SetShowCloseButton(false);
+  set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric(
+      views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH));
+
   SetLayoutManager(std::make_unique<views::FillLayout>());
   auto label = std::make_unique<views::Label>(
       l10n_util::GetStringFUTF16(IDS_CONFIRM_FILE_UPLOAD_TEXT,
@@ -71,31 +80,10 @@
                                                      web_contents);
 }
 
-base::string16 FolderUploadConfirmationView::GetWindowTitle() const {
-  return l10n_util::GetPluralStringFUTF16(
-      IDS_CONFIRM_FILE_UPLOAD_TITLE,
-      base::saturated_cast<int>(selected_files_.size()));
-}
-
 views::View* FolderUploadConfirmationView::GetInitiallyFocusedView() {
   return GetCancelButton();
 }
 
-bool FolderUploadConfirmationView::ShouldShowCloseButton() const {
-  return false;
-}
-
-gfx::Size FolderUploadConfirmationView::CalculatePreferredSize() const {
-  const int width = ChromeLayoutProvider::Get()->GetDistanceMetric(
-                        views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH) -
-                    margins().width();
-  return gfx::Size(width, GetHeightForWidth(width));
-}
-
-ui::ModalType FolderUploadConfirmationView::GetModalType() const {
-  return ui::MODAL_TYPE_CHILD;
-}
-
 void ShowFolderUploadConfirmationDialog(
     const base::FilePath& path,
     base::OnceCallback<void(const std::vector<ui::SelectedFileInfo>&)> callback,
diff --git a/chrome/browser/ui/views/folder_upload_confirmation_view.h b/chrome/browser/ui/views/folder_upload_confirmation_view.h
index 54c2abe..8c7f6f7 100644
--- a/chrome/browser/ui/views/folder_upload_confirmation_view.h
+++ b/chrome/browser/ui/views/folder_upload_confirmation_view.h
@@ -44,20 +44,11 @@
       std::vector<ui::SelectedFileInfo> selected_files,
       content::WebContents* web_contents);
 
-  // views::DialogDelegateView:
-  base::string16 GetWindowTitle() const override;
-
   // It's really important that this dialog *does not* accept by default /
   // when a user presses enter without looking as we're looking for explicit
   // approval to share this many files with the site.
   views::View* GetInitiallyFocusedView() override;
 
-  bool ShouldShowCloseButton() const override;
-
-  gfx::Size CalculatePreferredSize() const override;
-
-  ui::ModalType GetModalType() const override;
-
  private:
   base::OnceCallback<void(const std::vector<ui::SelectedFileInfo>&)> callback_;
   std::vector<ui::SelectedFileInfo> selected_files_;
diff --git a/chrome/browser/ui/views/frame/tab_strip_region_view.cc b/chrome/browser/ui/views/frame/tab_strip_region_view.cc
index 6e75cdd..e169e6af4 100644
--- a/chrome/browser/ui/views/frame/tab_strip_region_view.cc
+++ b/chrome/browser/ui/views/frame/tab_strip_region_view.cc
@@ -44,6 +44,17 @@
   scroll_button->SetInkDropMode(views::Button::InkDropMode::ON);
   return scroll_button;
 }
+
+class FrameGrabHandle : public views::View {
+ public:
+  gfx::Size GetMinimumSize() const override {
+    // Reserve some space for the frame to be grabbed by, even if the tabstrip
+    // is full.
+    // TODO(tbergquist): Define this relative to the NTB insets again.
+    return gfx::Size(42, 0);
+  }
+};
+
 }  // namespace
 
 TabStripRegionView::TabStripRegionView(std::unique_ptr<TabStrip> tab_strip) {
@@ -96,11 +107,8 @@
                                       tab_strip_container_flex_spec);
   }
 
-  reserved_grab_handle_space_ = AddChildView(std::make_unique<views::View>());
-  // TODO(tbergquist): Give |reserved_grab_handle_space_| a minimum size. For
-  // now, this space is reserved by the tabstrip itself, and we're just using
-  // this view to eat up flex space so that |tab_search_button| can be end-
-  // aligned.
+  reserved_grab_handle_space_ =
+      AddChildView(std::make_unique<FrameGrabHandle>());
   reserved_grab_handle_space_->SetProperty(
       views::kFlexBehaviorKey,
       views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToMinimum,
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
index f8511346..91b7291c8 100644
--- a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
+++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
@@ -215,7 +215,7 @@
                                  Profile* profile)
     : BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
       service_(service),
-      profile_(profile),
+      profile_(profile->GetOriginalProfile()),
       active_sessions_view_(
           AddChildView(std::make_unique<MediaNotificationListView>())) {
   SetButtons(ui::DIALOG_BUTTON_NONE);
diff --git a/chrome/browser/ui/views/location_bar/selected_keyword_view_interactive_uitest.cc b/chrome/browser/ui/views/location_bar/selected_keyword_view_interactive_uitest.cc
index 64516d36..ae66093e 100644
--- a/chrome/browser/ui/views/location_bar/selected_keyword_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/location_bar/selected_keyword_view_interactive_uitest.cc
@@ -45,7 +45,7 @@
   ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
 
   // Activate the extension's omnibox keyword.
-  InputKeys(browser(), {ui::VKEY_K, ui::VKEY_E, ui::VKEY_Y, ui::VKEY_SPACE});
+  InputKeys(browser(), {ui::VKEY_K, ui::VKEY_E, ui::VKEY_Y, ui::VKEY_TAB});
 
   BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
   SelectedKeywordView* selected_keyword_view =
diff --git a/chrome/browser/ui/views/profiles/OWNERS b/chrome/browser/ui/views/profiles/OWNERS
index 9ca9a47..1aff80d1 100644
--- a/chrome/browser/ui/views/profiles/OWNERS
+++ b/chrome/browser/ui/views/profiles/OWNERS
@@ -1,5 +1,5 @@
 droger@chromium.org
-pbos@chromium.org
+jkrcal@chromium.org
 rhalavati@chromium.org
 
 # COMPONENT: UI>Browser>Toolbar
diff --git a/chrome/browser/ui/views/settings_reset_prompt_dialog.cc b/chrome/browser/ui/views/settings_reset_prompt_dialog.cc
index 7051231d..75278747 100644
--- a/chrome/browser/ui/views/settings_reset_prompt_dialog.cc
+++ b/chrome/browser/ui/views/settings_reset_prompt_dialog.cc
@@ -28,17 +28,20 @@
 void ShowSettingsResetPrompt(
     Browser* browser,
     safe_browsing::SettingsResetPromptController* controller) {
-  SettingsResetPromptDialog* dialog = new SettingsResetPromptDialog(controller);
+  SettingsResetPromptDialog* dialog =
+      new SettingsResetPromptDialog(browser, controller);
   // The dialog will delete itself, as implemented in
   // |DialogDelegateView::DeleteDelegate()|, when its widget is closed.
-  dialog->Show(browser);
+  dialog->Show();
 }
 
 }  // namespace chrome
 
 SettingsResetPromptDialog::SettingsResetPromptDialog(
+    Browser* browser,
     safe_browsing::SettingsResetPromptController* controller)
-    : browser_(nullptr), controller_(controller) {
+    : browser_(browser), controller_(controller) {
+  DCHECK(browser_);
   DCHECK(controller_);
 
   SetShowIcon(false);
@@ -64,11 +67,16 @@
       },
       base::Unretained(this)));
 
+  SetModalType(ui::MODAL_TYPE_WINDOW);
+  SetShowCloseButton(false);
+  set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric(
+      views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH));
+
   set_margins(ChromeLayoutProvider::Get()->GetDialogInsetsForContentType(
       views::TEXT, views::TEXT));
   SetLayoutManager(std::make_unique<views::FillLayout>());
 
-  views::StyledLabel* dialog_label =
+  views::StyledLabel* const dialog_label =
       AddChildView(std::make_unique<views::StyledLabel>());
   dialog_label->SetText(controller_->GetMainText());
   dialog_label->SetTextContext(views::style::CONTEXT_DIALOG_BODY_TEXT);
@@ -85,37 +93,16 @@
     controller_->Close();
 }
 
-void SettingsResetPromptDialog::Show(Browser* browser) {
-  DCHECK(browser);
+void SettingsResetPromptDialog::Show() {
   DCHECK(controller_);
-
-  browser_ = browser;
-  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
+  BrowserView* const browser_view =
+      BrowserView::GetBrowserViewForBrowser(browser_);
   constrained_window::CreateBrowserModalDialogViews(
       this, browser_view->GetNativeWindow())
       ->Show();
   controller_->DialogShown();
 }
 
-// WidgetDelegate overrides.
-
-ui::ModalType SettingsResetPromptDialog::GetModalType() const {
-  return ui::MODAL_TYPE_WINDOW;
-}
-
-bool SettingsResetPromptDialog::ShouldShowCloseButton() const {
-  return false;
-}
-
 base::string16 SettingsResetPromptDialog::GetWindowTitle() const {
   return controller_ ? controller_->GetWindowTitle() : base::string16();
 }
-
-// View overrides.
-
-gfx::Size SettingsResetPromptDialog::CalculatePreferredSize() const {
-  const int width = ChromeLayoutProvider::Get()->GetDistanceMetric(
-                        views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH) -
-                    margins().width();
-  return gfx::Size(width, GetHeightForWidth(width));
-}
diff --git a/chrome/browser/ui/views/settings_reset_prompt_dialog.h b/chrome/browser/ui/views/settings_reset_prompt_dialog.h
index 8ef7ba3..b439fd55 100644
--- a/chrome/browser/ui/views/settings_reset_prompt_dialog.h
+++ b/chrome/browser/ui/views/settings_reset_prompt_dialog.h
@@ -17,10 +17,6 @@
 class SettingsResetPromptController;
 }
 
-namespace views {
-class View;
-}
-
 // A dialog intended for prompting users to reset some of their settings to
 // their original default values. The dialog has two sections:
 // 1. Main section with an explanation text
@@ -28,22 +24,18 @@
 //    operation.
 class SettingsResetPromptDialog : public views::DialogDelegateView {
  public:
-  explicit SettingsResetPromptDialog(
+  SettingsResetPromptDialog(
+      Browser* browser,
       safe_browsing::SettingsResetPromptController* controller);
   ~SettingsResetPromptDialog() override;
 
-  void Show(Browser* browser);
+  void Show();
 
-  // views::WidgetDelegate overrides.
-  ui::ModalType GetModalType() const override;
+  // views::DialogDelegateView:
   base::string16 GetWindowTitle() const override;
-  bool ShouldShowCloseButton() const override;
-
-  // views::View overrides.
-  gfx::Size CalculatePreferredSize() const override;
 
  private:
-  Browser* browser_;
+  Browser* const browser_;
   safe_browsing::SettingsResetPromptController* controller_;
 
   DISALLOW_COPY_AND_ASSIGN(SettingsResetPromptDialog);
diff --git a/chrome/browser/ui/views/settings_reset_prompt_dialog_browsertest.cc b/chrome/browser/ui/views/settings_reset_prompt_dialog_browsertest.cc
index 2a907d8..e390b61 100644
--- a/chrome/browser/ui/views/settings_reset_prompt_dialog_browsertest.cc
+++ b/chrome/browser/ui/views/settings_reset_prompt_dialog_browsertest.cc
@@ -180,9 +180,10 @@
         ModelParams{SettingType::DEFAULT_SEARCH_ENGINE, 0});
 
     dialog_ = new SettingsResetPromptDialog(
+        browser(),
         new safe_browsing::SettingsResetPromptController(
             std::move(model), std::make_unique<BrandcodedDefaultSettings>()));
-    dialog_->Show(browser());
+    dialog_->Show();
   }
   void DismissUi() override { dialog_->Close(); }
 
diff --git a/chrome/browser/ui/views/tabs/tab_drag_context.h b/chrome/browser/ui/views/tabs/tab_drag_context.h
index 8d339c0..6fe3a660 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_context.h
+++ b/chrome/browser/ui/views/tabs/tab_drag_context.h
@@ -68,10 +68,6 @@
   // Returns the width of the active tab.
   virtual int GetActiveTabWidth() const = 0;
 
-  // Returns the width of the area that contains tabs. This does not include
-  // the width of the new tab button.
-  virtual int GetTabAreaWidth() const = 0;
-
   // Returns the width of the region in which dragged tabs are allowed to exist.
   virtual int GetTabDragAreaWidth() const = 0;
 
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
index 51d32b6..0fef576 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -567,7 +567,7 @@
         did_restore_window_ = true;
         // When all tabs in a maximized browser are dragged the browser gets
         // restored during the drag and maximized back when the drag ends.
-        const int tab_area_width = attached_context_->GetTabAreaWidth();
+        const int tab_area_width = attached_context_->GetTabDragAreaWidth();
         std::vector<gfx::Rect> drag_bounds =
             attached_context_->CalculateBoundsForDraggedViews(attached_views_);
         OffsetX(GetAttachedDragPoint(point_in_screen).x(), &drag_bounds);
@@ -1340,7 +1340,7 @@
     return;
   }
 
-  const int tab_area_width = attached_context_->GetTabAreaWidth();
+  const int tab_area_width = attached_context_->GetTabDragAreaWidth();
   std::vector<gfx::Rect> drag_bounds =
       attached_context_->CalculateBoundsForDraggedViews(attached_views_);
   OffsetX(GetAttachedDragPoint(point_in_screen).x(), &drag_bounds);
@@ -1976,9 +1976,9 @@
     gfx::Vector2d* drag_offset,
     std::vector<gfx::Rect>* drag_bounds) {
   attached_context_->ForceLayout();
-  const int dragged_context_width = attached_context_->GetTabAreaWidth();
+  const int dragged_context_width = attached_context_->GetTabDragAreaWidth();
 
-  // If the new tabstrip is smaller than the old resize the tabs.
+  // If the new tabstrip region is smaller than the old, resize the tabs.
   if (dragged_context_width < tab_area_width) {
     const float leading_ratio =
         drag_bounds->front().x() / float{tab_area_width};
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index faa4045..2df6fa0 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -558,18 +558,19 @@
     return tab_strip_->GetActiveTabWidth();
   }
 
-  int GetTabAreaWidth() const override { return tab_strip_->GetTabAreaWidth(); }
-
   int GetTabDragAreaWidth() const override {
     // There are two cases here (with tab scrolling enabled):
     // 1) If the tab strip is not wider than the tab strip region (and thus
     // not scrollable), returning the available width for tabs rather than the
     // actual width for tabs allows tabs to be dragged past the current bounds
     // of the tabstrip, anywhere along the tab strip region.
+    // N.B. The available width for tabs in this case needs to ignore tab
+    // closing mode.
     // 2) If the tabstrip is wider than the tab strip region (and thus is
     // scrollable), returning the tab area width allows tabs to be dragged
     // anywhere within the tabstrip, not just in the leftmost region of it.
-    return std::max(tab_strip_->CalculateAvailableWidthForTabs(),
+    return std::max(tab_strip_->GetAvailableWidthForTabStrip() -
+                        tab_strip_->GetRightSideReservedWidth(),
                     tab_strip_->GetTabAreaWidth());
   }
 
@@ -780,7 +781,7 @@
     // Immediately hide the new tab button if the last tab is being dragged.
     const Tab* last_visible_tab = tab_strip_->GetLastVisibleTab();
     if (last_visible_tab && last_visible_tab->dragging())
-      SetNewTabButtonVisible(true);
+      SetNewTabButtonVisible(false);
 
     std::vector<gfx::Rect> bounds = CalculateBoundsForDraggedViews(views);
     DCHECK_EQ(views.size(), bounds.size());
@@ -1370,7 +1371,8 @@
         group.value(), ToggleTabGroupCollapsedStateOrigin::kImplicitAction);
   }
 
-  ExitTabClosingMode();
+  if (group.has_value())
+    ExitTabClosingMode();
 }
 
 void TabStrip::OnGroupCreated(const tab_groups::TabGroupId& group) {
@@ -2719,13 +2721,6 @@
   return -TabStyle::GetTabInternalPadding().right();
 }
 
-int TabStrip::FrameGrabWidth() const {
-  // The grab area is adjacent to the new tab button.  Treat the padding in the
-  // new tab button as part of the grab area.
-  constexpr int kApparentWidth = 50;
-  return kApparentWidth - new_tab_button_->GetInsets().right();
-}
-
 bool TabStrip::TitlebarBackgroundIsTransparent() const {
 #if defined(OS_WIN)
   // Windows 8+ uses transparent window contents (because the titlebar area is
@@ -2796,8 +2791,7 @@
 }
 
 int TabStrip::GetRightSideReservedWidth() const {
-  return new_tab_button_ideal_bounds_.width() + TabToNewTabButtonSpacing() +
-         FrameGrabWidth();
+  return new_tab_button_ideal_bounds_.width() + TabToNewTabButtonSpacing();
 }
 
 const Tab* TabStrip::GetLastVisibleTab() const {
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h
index 60d266e..1fda6e6 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.h
+++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -461,10 +461,6 @@
   // edge of the new tab button.
   int TabToNewTabButtonSpacing() const;
 
-  // Returns the space to reserve after the tabs to guarantee the user can grab
-  // part of the window frame (to move the window with).
-  int FrameGrabWidth() const;
-
   // Returns whether the window background behind the tabstrip is transparent.
   bool TitlebarBackgroundIsTransparent() const;
 
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index bcad336..aaec20f0 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -442,7 +442,7 @@
   std::unique_ptr<BubbleSyncPromoDelegate> delegate;
 #if !defined(OS_CHROMEOS)
   // ChromeOS does not show the signin promo.
-  delegate.reset(new BookmarkBubbleSignInDelegate(browser_));
+  delegate = std::make_unique<BookmarkBubbleSignInDelegate>(browser_);
 #endif
   BookmarkBubbleView::ShowBubble(anchor_view, bookmark_star_icon, observer,
                                  std::move(delegate), browser_->profile(), url,
diff --git a/chrome/browser/ui/web_applications/web_app_launch_manager.cc b/chrome/browser/ui/web_applications/web_app_launch_manager.cc
index 3befff5..e07789f 100644
--- a/chrome/browser/ui/web_applications/web_app_launch_manager.cc
+++ b/chrome/browser/ui/web_applications/web_app_launch_manager.cc
@@ -45,7 +45,6 @@
 #include "content/public/common/referrer.h"
 #include "extensions/common/constants.h"
 #include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/base/window_open_disposition.h"
 #include "ui/display/scoped_display_for_new_windows.h"
diff --git a/chrome/browser/ui/web_applications/web_app_launch_utils.cc b/chrome/browser/ui/web_applications/web_app_launch_utils.cc
index cd1862e8..b7af783 100644
--- a/chrome/browser/ui/web_applications/web_app_launch_utils.cc
+++ b/chrome/browser/ui/web_applications/web_app_launch_utils.cc
@@ -22,7 +22,7 @@
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/web_contents.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "url/gurl.h"
 
 namespace {
diff --git a/chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.cc b/chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.cc
index 425a4bcc..f899f69 100644
--- a/chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.cc
+++ b/chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.cc
@@ -23,14 +23,6 @@
 
 namespace {
 
-#if !BUILDFLAG(OPTIMIZE_WEBUI)
-namespace {
-const char kGeneratedPath[] =
-    "@out_folder@/gen/chrome/browser/resources/chromeos/"
-    "bluetooth_pairing_dialog/";
-}
-#endif
-
 constexpr int kBluetoothPairingDialogHeight = 375;
 
 void AddBluetoothStrings(content::WebUIDataSource* html_source) {
@@ -114,18 +106,12 @@
 
   AddBluetoothStrings(source);
   source->AddLocalizedString("title", IDS_SETTINGS_BLUETOOTH_PAIR_DEVICE_TITLE);
-#if BUILDFLAG(OPTIMIZE_WEBUI)
-  webui::SetupBundledWebUIDataSource(
-      source, "bluetooth_pairing_dialog.js",
-      IDR_BLUETOOTH_PAIRING_DIALOG_ROLLUP_JS,
-      IDR_BLUETOOTH_PAIRING_DIALOG_CONTAINER_HTML);
-#else
   webui::SetupWebUIDataSource(
       source,
       base::make_span(kBluetoothPairingDialogResources,
                       kBluetoothPairingDialogResourcesSize),
-      kGeneratedPath, IDR_BLUETOOTH_PAIRING_DIALOG_CONTAINER_HTML);
-#endif
+      std::string(),
+      IDR_BLUETOOTH_PAIRING_DIALOG_BLUETOOTH_PAIRING_DIALOG_CONTAINER_HTML);
   content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/onc_import_message_handler.cc b/chrome/browser/ui/webui/chromeos/onc_import_message_handler.cc
index 27cd401..8509b2e 100644
--- a/chrome/browser/ui/webui/chromeos/onc_import_message_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/onc_import_message_handler.cc
@@ -48,8 +48,8 @@
   AllowJavascript();
   GetNSSCertDatabaseForProfile(
       Profile::FromWebUI(web_ui()),
-      base::Bind(&OncImportMessageHandler::ImportONCToNSSDB,
-                 weak_factory_.GetWeakPtr(), callback_id, onc_blob));
+      base::BindOnce(&OncImportMessageHandler::ImportONCToNSSDB,
+                     weak_factory_.GetWeakPtr(), callback_id, onc_blob));
 }
 
 void OncImportMessageHandler::ImportONCToNSSDB(const std::string& callback_id,
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 4a8876a..cf022e0 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
@@ -15,6 +15,7 @@
 #include "chrome/browser/search/instant_service.h"
 #include "chrome/browser/search/instant_service_factory.h"
 #include "chrome/browser/search/ntp_features.h"
+#include "chrome/browser/search/recipe_tasks/recipe_tasks_handler.h"
 #include "chrome/browser/search/shopping_tasks/shopping_tasks_handler.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/search/ntp_user_data_logger.h"
@@ -191,18 +192,16 @@
       {"modulesDummyTitle", IDS_NTP_MODULES_DUMMY_TITLE},
       {"modulesDummy2Title", IDS_NTP_MODULES_DUMMY2_TITLE},
       {"modulesKaleidoscopeTitle", IDS_NTP_MODULES_KALEIDOSCOPE_TITLE},
-      {"modulesShoppingTasksInfoTitle",
-       IDS_NTP_MODULES_SHOPPING_TASKS_INFO_TITLE},
-      {"modulesShoppingTasksInfoClose",
-       IDS_NTP_MODULES_SHOPPING_TASKS_INFO_CLOSE},
+      {"modulesTasksInfoTitle", IDS_NTP_MODULES_SHOPPING_TASKS_INFO_TITLE},
+      {"modulesTasksInfoClose", IDS_NTP_MODULES_SHOPPING_TASKS_INFO_CLOSE},
   };
   AddLocalizedStringsBulk(source, kStrings);
 
-  source->AddString("modulesShoppingTasksInfo1",
+  source->AddString("modulesTasksInfo1",
                     l10n_util::GetStringFUTF16(
                         IDS_NTP_MODULES_SHOPPING_TASKS_INFO_1,
                         base::UTF8ToUTF16("https://myactivity.google.com/")));
-  source->AddString("modulesShoppingTasksInfo2",
+  source->AddString("modulesTasksInfo2",
                     l10n_util::GetStringFUTF16(
                         IDS_NTP_MODULES_SHOPPING_TASKS_INFO_2,
                         base::UTF8ToUTF16("https://policies.google.com/")));
@@ -238,6 +237,9 @@
   source->AddBoolean("kaleidoscopeModuleEnabled", false);
 #endif  // BUILDFLAG(ENABLE_KALEIDOSCOPE)
   source->AddBoolean(
+      "recipeTasksModuleEnabled",
+      base::FeatureList::IsEnabled(ntp_features::kNtpRecipeTasksModule));
+  source->AddBoolean(
       "shoppingTasksModuleEnabled",
       base::FeatureList::IsEnabled(ntp_features::kNtpShoppingTasksModule));
 
@@ -248,6 +250,9 @@
   source->AddResourcePath("promo_browser_command.mojom-lite.js",
                           IDR_NEW_TAB_PAGE_PROMO_BROWSER_COMMAND_MOJO_LITE_JS);
   source->AddResourcePath(
+      "modules/recipe_tasks/recipe_tasks.mojom-lite.js",
+      IDR_NEW_TAB_PAGE_MODULES_RECIPE_TASKS_RECIPE_TASKS_MOJO_LITE_JS);
+  source->AddResourcePath(
       "modules/shopping_tasks/shopping_tasks.mojom-lite.js",
       IDR_NEW_TAB_PAGE_MODULES_SHOPPING_TASKS_SHOPPING_TASKS_MOJO_LITE_JS);
 #if !defined(OFFICIAL_BUILD)
@@ -371,6 +376,13 @@
 }
 
 void NewTabPageUI::BindInterface(
+    mojo::PendingReceiver<recipe_tasks::mojom::RecipeTasksHandler>
+        pending_receiver) {
+  recipe_tasks_handler_ = std::make_unique<RecipeTasksHandler>(
+      std::move(pending_receiver), profile_);
+}
+
+void NewTabPageUI::BindInterface(
     mojo::PendingReceiver<shopping_tasks::mojom::ShoppingTasksHandler>
         pending_receiver) {
   shopping_tasks_handler_ = std::make_unique<ShoppingTasksHandler>(
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h
index 295e83b..5bd1d8e 100644
--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h
+++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h
@@ -9,6 +9,7 @@
 #include "chrome/browser/media/kaleidoscope/mojom/kaleidoscope.mojom.h"
 #include "chrome/browser/promo_browser_command/promo_browser_command.mojom-forward.h"
 #include "chrome/browser/search/instant_service_observer.h"
+#include "chrome/browser/search/recipe_tasks/recipe_tasks.mojom.h"
 #include "chrome/browser/search/shopping_tasks/shopping_tasks.mojom.h"
 #if !defined(OFFICIAL_BUILD)
 #include "chrome/browser/ui/webui/new_tab_page/foo/foo.mojom.h"  // nogncheck crbug.com/1125897
@@ -37,6 +38,7 @@
 class NewTabPageHandler;
 class Profile;
 class PromoBrowserCommandHandler;
+class RecipeTasksHandler;
 class ShoppingTasksHandler;
 
 class NewTabPageUI
@@ -79,6 +81,13 @@
           pending_receiver);
 
   // Instantiates the implementor of the
+  // recipe_tasks::mojom::RecipeTasksHandler mojo interface passing the
+  // pending receiver that will be internally bound.
+  void BindInterface(
+      mojo::PendingReceiver<recipe_tasks::mojom::RecipeTasksHandler>
+          pending_receiver);
+
+  // Instantiates the implementor of the
   // shopping_tasks::mojom::ShoppingTasksHandler mojo interface passing the
   // pending receiver that will be internally bound.
   void BindInterface(
@@ -138,6 +147,7 @@
 
   // Mojo implementations for modules:
   std::unique_ptr<KaleidoscopeDataProviderImpl> kaleidoscope_data_provider_;
+  std::unique_ptr<RecipeTasksHandler> recipe_tasks_handler_;
   std::unique_ptr<ShoppingTasksHandler> shopping_tasks_handler_;
 
   WEB_UI_CONTROLLER_TYPE_DECL();
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
index b885f0b9..f90b3975 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -271,6 +271,7 @@
     {"optionShortEdge", IDS_PRINT_PREVIEW_OPTION_SHORT_EDGE},
     {"optionTwoSided", IDS_PRINT_PREVIEW_OPTION_TWO_SIDED},
     {"optionsLabel", IDS_PRINT_PREVIEW_OPTIONS_LABEL},
+    {"pageDescription", IDS_PRINT_PREVIEW_DESCRIPTION},
     {"pageRangeLimitInstructionWithValue",
      IDS_PRINT_PREVIEW_PAGE_RANGE_LIMIT_INSTRUCTION_WITH_VALUE},
     {"pageRangeSyntaxInstruction",
diff --git a/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_browsertest.cc b/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_browsertest.cc
index 15988e9..466b9de 100644
--- a/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_browsertest.cc
+++ b/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_browsertest.cc
@@ -79,7 +79,7 @@
 };
 
 IN_PROC_BROWSER_TEST_F(ClearBrowsingDataHandlerBrowserTest, GetInstalledApps) {
-  GURL url(https_server()->GetURL("/"));
+  GURL url(https_server()->GetURL("/title1.html"));
   InstallAndLaunchApp(url);
   base::ListValue args;
   args.AppendString(kWebUiFunctionName);
diff --git a/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc b/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc
index 4be6d11..cfe8ea0 100644
--- a/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc
+++ b/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc
@@ -12,7 +12,6 @@
 #include "chrome/grit/browser_resources.h"
 #include "chrome/grit/usb_internals_resources.h"
 #include "content/public/browser/web_ui_data_source.h"
-#include "services/network/public/mojom/content_security_policy.mojom.h"
 
 UsbInternalsUI::UsbInternalsUI(content::WebUI* web_ui)
     : ui::MojoWebUIController(web_ui) {
@@ -21,8 +20,8 @@
       content::WebUIDataSource::Create(chrome::kChromeUIUsbInternalsHost);
 
   static constexpr webui::ResourcePath kPaths[] = {
+      {"app.js", IDR_USB_INTERNALS_APP_JS},
       {"usb_internals.css", IDR_USB_INTERNALS_CSS},
-      {"usb_internals.js", IDR_USB_INTERNALS_JS},
       {"usb_internals.mojom-lite.js", IDR_USB_INTERNALS_MOJOM_LITE_JS},
       {"descriptor_panel.js", IDR_USB_INTERNALS_DESCRIPTOR_PANEL_JS},
       {"devices_page.js", IDR_USB_INTERNALS_DEVICES_PAGE_JS},
@@ -38,9 +37,7 @@
   webui::AddResourcePathsBulk(source, kPaths);
 
   source->SetDefaultResource(IDR_USB_INTERNALS_HTML);
-  source->OverrideContentSecurityPolicy(
-      network::mojom::CSPDirectiveName::TrustedTypes,
-      "trusted-types cr-ui-tree-js-static;");
+  source->DisableTrustedTypesCSP();
 
   content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
 }
diff --git a/chrome/browser/ui/webui/webui_js_exception/webui_js_exception_ui.cc b/chrome/browser/ui/webui/webui_js_exception/webui_js_exception_ui.cc
index d06afb9..97ae8b7 100644
--- a/chrome/browser/ui/webui/webui_js_exception/webui_js_exception_ui.cc
+++ b/chrome/browser/ui/webui/webui_js_exception/webui_js_exception_ui.cc
@@ -9,7 +9,6 @@
 #include "base/feature_list.h"
 #include "base/logging.h"
 #include "build/build_config.h"
-#include "build/buildflag.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/webui_util.h"
 #include "chrome/common/buildflags.h"
@@ -19,13 +18,6 @@
 #include "content/public/browser/web_ui_data_source.h"
 #include "content/public/common/content_features.h"
 
-#if !BUILDFLAG(OPTIMIZE_WEBUI)
-namespace {
-constexpr char kGeneratedPath[] =
-    "@out_folder@/gen/chrome/browser/resources/webui_js_exception/";
-}  // namespace
-#endif  // !BUILDFLAG(OPTIMIZE_WEBUI)
-
 WebUIJsExceptionUI::WebUIJsExceptionUI(content::WebUI* web_ui)
     : content::WebUIController(web_ui) {
 #if !defined(OS_WIN) && !defined(OS_FUCHSIA)
@@ -41,18 +33,11 @@
 
   content::WebUIDataSource* source =
       content::WebUIDataSource::Create(chrome::kChromeUIWebUIJsExceptionHost);
-#if BUILDFLAG(OPTIMIZE_WEBUI)
-  webui::SetupBundledWebUIDataSource(
-      source, "webui_js_exception.js",
-      IDR_WEBUI_JS_EXCEPTION_UI_WEBUI_JS_EXCEPTION_ROLLUP_JS,
-      IDR_WEBUI_JS_EXCEPTION_UI_WEBUI_JS_EXCEPTION_HTML);
-#else   // if !BUILDFLAG(OPTIMIZE_WEBUI)
-  webui::SetupWebUIDataSource(
-      source,
-      base::make_span(kWebuiJsExceptionResources,
-                      kWebuiJsExceptionResourcesSize),
-      kGeneratedPath, IDR_WEBUI_JS_EXCEPTION_UI_WEBUI_JS_EXCEPTION_HTML);
-#endif  // !BUILDFLAG(OPTIMIZE_WEBUI)
+  webui::SetupWebUIDataSource(source,
+                              base::make_span(kWebuiJsExceptionResources,
+                                              kWebuiJsExceptionResourcesSize),
+                              std::string(),
+                              IDR_WEBUI_JS_EXCEPTION_WEBUI_JS_EXCEPTION_HTML);
   Profile* profile = Profile::FromWebUI(web_ui);
   content::WebUIDataSource::Add(profile, source);
 }
diff --git a/chrome/browser/updates/announcement_notification/BUILD.gn b/chrome/browser/updates/announcement_notification/BUILD.gn
index 40d7bf1c..c9fc53c6 100644
--- a/chrome/browser/updates/announcement_notification/BUILD.gn
+++ b/chrome/browser/updates/announcement_notification/BUILD.gn
@@ -8,8 +8,6 @@
 
 source_set("announcement_notification") {
   sources = [
-    "announcement_notification_metrics.cc",
-    "announcement_notification_metrics.h",
     "announcement_notification_service.cc",
     "announcement_notification_service.h",
     "announcement_notification_service_factory.cc",
@@ -34,7 +32,6 @@
       "announcement_notification_delegate_android.cc",
       "announcement_notification_delegate_android.h",
     ]
-    deps += [ "//chrome/android:chrome_jni_headers" ]
   } else {
     sources += [
       "announcement_notification_delegate.cc",
@@ -47,12 +44,6 @@
   }
 }
 
-if (is_android) {
-  java_cpp_enum("jni_enums") {
-    sources = [ "announcement_notification_metrics.h" ]
-  }
-}
-
 source_set("unit_tests") {
   testonly = true
   sources = [ "announcement_notification_service_unittest.cc" ]
diff --git a/chrome/browser/updates/announcement_notification/announcement_notification_handler.cc b/chrome/browser/updates/announcement_notification/announcement_notification_handler.cc
index db8a3ab..929e07f 100644
--- a/chrome/browser/updates/announcement_notification/announcement_notification_handler.cc
+++ b/chrome/browser/updates/announcement_notification/announcement_notification_handler.cc
@@ -11,7 +11,6 @@
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/updates/announcement_notification/announcement_notification_delegate.h"
-#include "chrome/browser/updates/announcement_notification/announcement_notification_metrics.h"
 
 namespace {
 
@@ -26,7 +25,6 @@
 void AnnouncementNotificationHandler::OnShow(
     Profile* profile,
     const std::string& notification_id) {
-  RecordAnnouncementHistogram(AnnouncementNotificationEvent::kShown);
 }
 
 void AnnouncementNotificationHandler::OnClose(
@@ -35,7 +33,6 @@
     const std::string& notification_id,
     bool by_user,
     base::OnceClosure completed_closure) {
-  RecordAnnouncementHistogram(AnnouncementNotificationEvent::kClose);
   std::move(completed_closure).Run();
 }
 
@@ -51,16 +48,12 @@
   // Open the announcement link when the user clicks the notification or clicks
   // the button to open.
   if (button_index == kReviewButtonIndex || !action_index.has_value()) {
-    RecordAnnouncementHistogram(action_index.has_value()
-                                    ? AnnouncementNotificationEvent::kOpen
-                                    : AnnouncementNotificationEvent::kClick);
     OpenAnnouncement(profile);
     std::move(completed_closure).Run();
     return;
   }
 
   // Otherwise, close the notification.
-  RecordAnnouncementHistogram(AnnouncementNotificationEvent::kAck);
   NotificationDisplayServiceFactory::GetInstance()
       ->GetForProfile(profile)
       ->Close(NotificationHandler::Type::ANNOUNCEMENT,
diff --git a/chrome/browser/updates/announcement_notification/announcement_notification_metrics.cc b/chrome/browser/updates/announcement_notification/announcement_notification_metrics.cc
deleted file mode 100644
index 7a2166d0..0000000
--- a/chrome/browser/updates/announcement_notification/announcement_notification_metrics.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/updates/announcement_notification/announcement_notification_metrics.h"
-
-#include "base/metrics/histogram_macros.h"
-
-void RecordAnnouncementHistogram(AnnouncementNotificationEvent event) {
-  UMA_HISTOGRAM_ENUMERATION("Notifications.Announcement.Events", event);
-}
diff --git a/chrome/browser/updates/announcement_notification/announcement_notification_metrics.h b/chrome/browser/updates/announcement_notification/announcement_notification_metrics.h
deleted file mode 100644
index 8ba830d2..0000000
--- a/chrome/browser/updates/announcement_notification/announcement_notification_metrics.h
+++ /dev/null
@@ -1,32 +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_UPDATES_ANNOUNCEMENT_NOTIFICATION_ANNOUNCEMENT_NOTIFICATION_METRICS_H_
-#define CHROME_BROWSER_UPDATES_ANNOUNCEMENT_NOTIFICATION_ANNOUNCEMENT_NOTIFICATION_METRICS_H_
-
-// Used to record histograms, must match AnnouncementNotificationEvent in
-// enums.xml. Cannot reuse or delete values.
-// A Java counterpart will be generated for this enum.
-// GENERATED_JAVA_ENUM_PACKAGE: (
-//   org.chromium.chrome.browser.announcement)
-enum class AnnouncementNotificationEvent {
-  // Starts to check whether to show announcement notification.
-  kStart = 0,
-  // Notification is shown.
-  kShown = 1,
-  // Notification is clicked.
-  kClick = 2,
-  // Notification is closed.
-  kClose = 3,
-  // The acknowledge button is clicked.
-  kAck = 4,
-  // The open button is clicked.
-  kOpen = 5,
-  kMaxValue = kOpen,
-};
-
-// Records announcement notification event.
-void RecordAnnouncementHistogram(AnnouncementNotificationEvent event);
-
-#endif  // CHROME_BROWSER_UPDATES_ANNOUNCEMENT_NOTIFICATION_ANNOUNCEMENT_NOTIFICATION_METRICS_H_
diff --git a/chrome/browser/updates/announcement_notification/announcement_notification_service.cc b/chrome/browser/updates/announcement_notification/announcement_notification_service.cc
index 9d938c7b..21fde01 100644
--- a/chrome/browser/updates/announcement_notification/announcement_notification_service.cc
+++ b/chrome/browser/updates/announcement_notification/announcement_notification_service.cc
@@ -14,7 +14,6 @@
 #include "chrome/browser/profiles/profile_attributes_entry.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/updates/announcement_notification/announcement_notification_metrics.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
@@ -90,8 +89,6 @@
     if (!IsFeatureEnabled())
       return;
 
-    RecordAnnouncementHistogram(AnnouncementNotificationEvent::kStart);
-
     // No valid version Finch parameter.
     if (!IsVersionValid(remote_version_))
       return;
diff --git a/chrome/browser/version/OWNERS b/chrome/browser/version/OWNERS
index 60448b82..7567e7d 100644
--- a/chrome/browser/version/OWNERS
+++ b/chrome/browser/version/OWNERS
@@ -1,5 +1,5 @@
 file://chrome/android/OWNERS
 
 # COMPONENT: Build
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
 # OS: Android
diff --git a/chrome/browser/video_tutorials/internal/tutorial_service_impl.cc b/chrome/browser/video_tutorials/internal/tutorial_service_impl.cc
index 6caca4f..bcbbbf0 100644
--- a/chrome/browser/video_tutorials/internal/tutorial_service_impl.cc
+++ b/chrome/browser/video_tutorials/internal/tutorial_service_impl.cc
@@ -8,9 +8,11 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/command_line.h"
 #include "chrome/browser/video_tutorials/internal/config.h"
 #include "chrome/browser/video_tutorials/internal/proto_conversions.h"
 #include "chrome/browser/video_tutorials/prefs.h"
+#include "chrome/browser/video_tutorials/switches.h"
 
 namespace video_tutorials {
 
@@ -53,6 +55,8 @@
 void TutorialServiceImpl::StartFetchIfNecessary() {
   base::Time last_update_time = pref_service_->GetTime(kLastUpdatedTimeKey);
   bool needs_update =
+      base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kVideoTutorialsInstantFetch) ||
       ((base::Time::Now() - last_update_time) > Config::GetFetchFrequency());
   if (needs_update) {
     tutorial_fetcher_->StartFetchForTutorials(base::BindOnce(
diff --git a/chrome/browser/video_tutorials/switches.cc b/chrome/browser/video_tutorials/switches.cc
index 930d98a..99f54694 100644
--- a/chrome/browser/video_tutorials/switches.cc
+++ b/chrome/browser/video_tutorials/switches.cc
@@ -11,4 +11,11 @@
                                     base::FEATURE_DISABLED_BY_DEFAULT};
 
 }  // namespace features
+
+namespace switches {
+
+const char kVideoTutorialsInstantFetch[] = "video-tutorials-instant-fetch";
+
+}  // namespace switches
+
 }  // namespace video_tutorials
diff --git a/chrome/browser/video_tutorials/switches.h b/chrome/browser/video_tutorials/switches.h
index 86f3720..f2d7fb7 100644
--- a/chrome/browser/video_tutorials/switches.h
+++ b/chrome/browser/video_tutorials/switches.h
@@ -14,6 +14,14 @@
 extern const base::Feature kVideoTutorials;
 
 }  // namespace features
+
+namespace switches {
+
+// If set, the video tutorials will be fetched on startup.
+extern const char kVideoTutorialsInstantFetch[];
+
+}  // namespace switches
+
 }  // namespace video_tutorials
 
 #endif  // CHROME_BROWSER_VIDEO_TUTORIALS_SWITCHES_H_
diff --git a/chrome/browser/web_applications/components/web_app_url_loader_browsertest.cc b/chrome/browser/web_applications/components/web_app_url_loader_browsertest.cc
index a79314f..92e2a58 100644
--- a/chrome/browser/web_applications/components/web_app_url_loader_browsertest.cc
+++ b/chrome/browser/web_applications/components/web_app_url_loader_browsertest.cc
@@ -44,14 +44,18 @@
 }
 
 // Run |handler| on requests that exactly match the |relative_url|.
-std::unique_ptr<net::test_server::HttpResponse> HandleMatchingRequest(
+std::unique_ptr<net::test_server::HttpResponse>
+HandleMatchingRequestOrReturnEmptyPage(
     const std::string& relative_url,
     const net::EmbeddedTestServer::HandleRequestCallback& handler,
     const net::test_server::HttpRequest& request) {
   GURL match = request.GetURL().Resolve(relative_url);
   if (request.GetURL() == match)
     return handler.Run(request);
-  return nullptr;
+
+  auto http_response = std::make_unique<net::test_server::BasicHttpResponse>();
+  http_response->set_code(net::HTTP_OK);
+  return http_response;
 }
 
 class WebAppUrlLoaderTest : public InProcessBrowserTest {
@@ -100,9 +104,9 @@
   // Set up a server redirect from |src_relative| (a relative URL) to |dest|.
   // Must be called before the server is started.
   void SetupRedirect(const std::string& src_relative, const std::string& dest) {
-    embedded_test_server()->RegisterRequestHandler(
-        base::BindRepeating(&HandleMatchingRequest, src_relative,
-                            base::BindRepeating(&HandleServerRedirect, dest)));
+    embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
+        &HandleMatchingRequestOrReturnEmptyPage, src_relative,
+        base::BindRepeating(&HandleServerRedirect, dest)));
   }
 
  private:
diff --git a/chrome/browser/webshare/win/fake_storage_file_statics.cc b/chrome/browser/webshare/win/fake_storage_file_statics.cc
new file mode 100644
index 0000000..f295a288
--- /dev/null
+++ b/chrome/browser/webshare/win/fake_storage_file_statics.cc
@@ -0,0 +1,339 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/webshare/win/fake_storage_file_statics.h"
+
+#include <windows.foundation.h>
+#include <windows.storage.streams.h>
+#include <wrl/module.h>
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/fake_iasync_operation_win.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/win/scoped_hstring.h"
+#include "chrome/browser/webshare/win/fake_random_access_stream.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ABI::Windows::Foundation::DateTime;
+using ABI::Windows::Foundation::IAsyncAction;
+using ABI::Windows::Foundation::IAsyncOperation;
+using ABI::Windows::Foundation::IUriRuntimeClass;
+using ABI::Windows::Storage::FileAccessMode;
+using ABI::Windows::Storage::FileAttributes;
+using ABI::Windows::Storage::IStorageFile;
+using ABI::Windows::Storage::IStorageFolder;
+using ABI::Windows::Storage::IStorageItem;
+using ABI::Windows::Storage::IStreamedFileDataRequestedHandler;
+using ABI::Windows::Storage::NameCollisionOption;
+using ABI::Windows::Storage::StorageDeleteOption;
+using ABI::Windows::Storage::StorageFile;
+using ABI::Windows::Storage::StorageItemTypes;
+using ABI::Windows::Storage::StorageStreamTransaction;
+using ABI::Windows::Storage::FileProperties::BasicProperties;
+using ABI::Windows::Storage::Streams::IOutputStream;
+using ABI::Windows::Storage::Streams::IRandomAccessStream;
+using ABI::Windows::Storage::Streams::IRandomAccessStreamReference;
+using Microsoft::WRL::ComPtr;
+using Microsoft::WRL::Make;
+using Microsoft::WRL::RuntimeClass;
+using Microsoft::WRL::RuntimeClassFlags;
+using Microsoft::WRL::WinRtClassicComMix;
+
+namespace webshare {
+namespace {
+
+class FakeStorageFile final
+    : public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>,
+                          IStorageFile,
+                          IStorageItem> {
+ public:
+  FakeStorageFile(HSTRING display_name_with_extension,
+                  IStreamedFileDataRequestedHandler* data_requested,
+                  IRandomAccessStreamReference* thumbnail)
+      : streamed_file_data_requested_handler_(data_requested) {
+    // ScopedHString takes ownership of the HSTRING provided to it, but taking
+    // ownership is not an expected behavior when passing an HSTRING to a system
+    // API, so we use a temporary ScopedHString to make a copy we can safely own
+    // and release ownership of the original 'back' to the caller.
+    base::win::ScopedHString holder(display_name_with_extension);
+    display_name_with_extension_ =
+        base::win::ScopedHString::Create(holder.Get());
+    (void)holder.release();
+  }
+  FakeStorageFile(const FakeStorageFile&) = delete;
+  FakeStorageFile& operator=(const FakeStorageFile&) = delete;
+  ~FakeStorageFile() final {
+    EXPECT_FALSE(open_async_in_progress_)
+        << "FakeStorageFile destroyed while open operation is in progress.";
+  }
+
+  // ABI::Windows::Storage::IStorageFile
+  IFACEMETHODIMP get_FileType(HSTRING* value) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP get_ContentType(HSTRING* value) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP OpenAsync(
+      FileAccessMode access_mode,
+      IAsyncOperation<IRandomAccessStream*>** operation) final {
+    if (open_async_in_progress_) {
+      ADD_FAILURE()
+          << "OpenAsync called while an open operation is in progress.";
+      return E_ILLEGAL_METHOD_CALL;
+    }
+
+    auto fake_iasync_operation =
+        Make<base::win::FakeIAsyncOperation<IRandomAccessStream*>>();
+    HRESULT hr = fake_iasync_operation->QueryInterface(IID_PPV_ARGS(operation));
+    if (FAILED(hr)) {
+      EXPECT_HRESULT_SUCCEEDED(hr);
+      return hr;
+    }
+
+    bool success = base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&FakeStorageFile::OnOpenAsync,
+                       weak_factory_.GetWeakPtr(), fake_iasync_operation));
+    if (!success) {
+      EXPECT_TRUE(success);
+      return E_ASYNC_OPERATION_NOT_STARTED;
+    }
+
+    open_async_in_progress_ = true;
+    return S_OK;
+  }
+  IFACEMETHODIMP OpenTransactedWriteAsync(
+      IAsyncOperation<StorageStreamTransaction*>** operation) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP CopyOverloadDefaultNameAndOptions(
+      IStorageFolder* destination_folder,
+      IAsyncOperation<StorageFile*>** operation) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP CopyOverloadDefaultOptions(
+      IStorageFolder* destination_folder,
+      HSTRING desired_new_name,
+      IAsyncOperation<StorageFile*>** operation) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP CopyOverload(IStorageFolder* destination_folder,
+                              HSTRING desired_new_name,
+                              NameCollisionOption option,
+                              IAsyncOperation<StorageFile*>** operation) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP
+  CopyAndReplaceAsync(IStorageFile* file_to_replace,
+                      IAsyncAction** operation) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP MoveOverloadDefaultNameAndOptions(
+      IStorageFolder* destination_folder,
+      IAsyncAction** operation) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP MoveOverloadDefaultOptions(IStorageFolder* destination_folder,
+                                            HSTRING desired_new_name,
+                                            IAsyncAction** operation) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP
+  MoveOverload(IStorageFolder* destination_folder,
+               HSTRING desired_new_name,
+               NameCollisionOption option,
+               IAsyncAction** operation) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP
+  MoveAndReplaceAsync(IStorageFile* file_to_replace,
+                      IAsyncAction** operation) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+
+  // ABI::Windows::Storage::IStorageItem
+  IFACEMETHODIMP RenameAsyncOverloadDefaultOptions(
+      HSTRING desired_name,
+      IAsyncAction** operation) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP
+  RenameAsync(HSTRING desired_name,
+              NameCollisionOption option,
+              IAsyncAction** operation) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP DeleteAsyncOverloadDefaultOptions(
+      IAsyncAction** operation) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP
+  DeleteAsync(StorageDeleteOption option, IAsyncAction** operation) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP GetBasicPropertiesAsync(
+      IAsyncOperation<BasicProperties*>** operation) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP get_Name(HSTRING* value) final {
+    auto copy =
+        base::win::ScopedHString::Create(display_name_with_extension_.Get());
+    *value = copy.release();
+    return S_OK;
+  }
+  IFACEMETHODIMP get_Path(HSTRING* value) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP
+  get_Attributes(FileAttributes* value) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP
+  get_DateCreated(DateTime* value) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP
+  IsOfType(StorageItemTypes type, boolean* value) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+
+ private:
+  void OnOpenAsync(ComPtr<base::win::FakeIAsyncOperation<IRandomAccessStream*>>
+                       fake_iasync_operation) {
+    ASSERT_TRUE(open_async_in_progress_);
+    open_async_in_progress_ = false;
+
+    auto fake_stream = Make<FakeRandomAccessStream>();
+
+    ComPtr<IOutputStream> output_stream;
+    ASSERT_HRESULT_SUCCEEDED(fake_stream->GetOutputStreamAt(0, &output_stream));
+    ComPtr<FakeRandomAccessStream> fake_output_stream =
+        static_cast<FakeRandomAccessStream*>(output_stream.Get());
+    ASSERT_TRUE(fake_output_stream);
+
+    fake_output_stream->OnClose(
+        base::BindLambdaForTesting([fake_stream, fake_iasync_operation]() {
+          ComPtr<IRandomAccessStream> random_access_stream;
+          ASSERT_HRESULT_SUCCEEDED(fake_stream.As(&random_access_stream));
+          fake_iasync_operation->CompleteWithResults(random_access_stream);
+        }));
+
+    ASSERT_HRESULT_SUCCEEDED(
+        streamed_file_data_requested_handler_->Invoke(output_stream.Get()));
+  }
+
+  base::win::ScopedHString display_name_with_extension_ =
+      base::win::ScopedHString::Create("");
+  bool open_async_in_progress_ = false;
+  ComPtr<IStreamedFileDataRequestedHandler>
+      streamed_file_data_requested_handler_;
+  base::WeakPtrFactory<FakeStorageFile> weak_factory_{this};
+};
+
+}  // namespace
+
+FakeStorageFileStatics::FakeStorageFileStatics() = default;
+FakeStorageFileStatics::~FakeStorageFileStatics() = default;
+
+IFACEMETHODIMP FakeStorageFileStatics::GetFileFromPathAsync(
+    HSTRING path,
+    IAsyncOperation<StorageFile*>** operation) {
+  NOTREACHED();
+  return E_NOTIMPL;
+}
+
+IFACEMETHODIMP FakeStorageFileStatics::GetFileFromApplicationUriAsync(
+    IUriRuntimeClass* uri,
+    IAsyncOperation<StorageFile*>** operation) {
+  NOTREACHED();
+  return E_NOTIMPL;
+}
+
+IFACEMETHODIMP FakeStorageFileStatics::CreateStreamedFileAsync(
+    HSTRING display_name_with_extension,
+    IStreamedFileDataRequestedHandler* data_requested,
+    IRandomAccessStreamReference* thumbnail,
+    IAsyncOperation<StorageFile*>** operation) {
+  if (!base::win::ScopedHString::ResolveCoreWinRTStringDelayload()) {
+    ADD_FAILURE() << "Attempted to use FakeStorageFileStatics in an "
+                     "environment that doesn't support ScopedHStrings.";
+    return E_UNEXPECTED;
+  }
+
+  auto fake_iasync_operation =
+      Make<base::win::FakeIAsyncOperation<StorageFile*>>();
+  HRESULT hr = fake_iasync_operation->QueryInterface(IID_PPV_ARGS(operation));
+  if (FAILED(hr)) {
+    EXPECT_HRESULT_SUCCEEDED(hr);
+    return hr;
+  }
+
+  auto fake_storage_file = Make<FakeStorageFile>(display_name_with_extension,
+                                                 data_requested, thumbnail);
+  bool success = base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindLambdaForTesting([fake_iasync_operation, fake_storage_file]() {
+        fake_iasync_operation->CompleteWithResults(fake_storage_file);
+      }));
+  if (!success) {
+    EXPECT_TRUE(success);
+    return E_ASYNC_OPERATION_NOT_STARTED;
+  }
+
+  return S_OK;
+}
+
+IFACEMETHODIMP FakeStorageFileStatics::ReplaceWithStreamedFileAsync(
+    IStorageFile* file_to_replace,
+    IStreamedFileDataRequestedHandler* data_requested,
+    IRandomAccessStreamReference* thumbnail,
+    IAsyncOperation<StorageFile*>** operation) {
+  NOTREACHED();
+  return E_NOTIMPL;
+}
+
+IFACEMETHODIMP FakeStorageFileStatics::CreateStreamedFileFromUriAsync(
+    HSTRING display_name_with_extension,
+    IUriRuntimeClass* uri,
+    IRandomAccessStreamReference* thumbnail,
+    IAsyncOperation<StorageFile*>** operation) {
+  NOTREACHED();
+  return E_NOTIMPL;
+}
+
+IFACEMETHODIMP FakeStorageFileStatics::ReplaceWithStreamedFileFromUriAsync(
+    IStorageFile* file_to_replace,
+    IUriRuntimeClass* uri,
+    IRandomAccessStreamReference* thumbnail,
+    IAsyncOperation<StorageFile*>** operation) {
+  NOTREACHED();
+  return E_NOTIMPL;
+}
+
+}  // namespace webshare
diff --git a/chrome/browser/webshare/win/fake_storage_file_statics.h b/chrome/browser/webshare/win/fake_storage_file_statics.h
new file mode 100644
index 0000000..68a1a2a
--- /dev/null
+++ b/chrome/browser/webshare/win/fake_storage_file_statics.h
@@ -0,0 +1,62 @@
+// 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_WEBSHARE_WIN_FAKE_STORAGE_FILE_STATICS_H_
+#define CHROME_BROWSER_WEBSHARE_WIN_FAKE_STORAGE_FILE_STATICS_H_
+
+#include <windows.storage.h>
+#include <wrl/implements.h>
+
+namespace webshare {
+
+// Provides an implementation of IStorageFileStatics for use in GTests.
+class __declspec(uuid("70A03B12-27C0-499A-B8AE-18E6060BDEDD"))
+    FakeStorageFileStatics
+    : public Microsoft::WRL::RuntimeClass<
+          Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRtClassicComMix>,
+          ABI::Windows::Storage::IStorageFileStatics> {
+ public:
+  FakeStorageFileStatics();
+  FakeStorageFileStatics(const FakeStorageFileStatics&) = delete;
+  FakeStorageFileStatics& operator=(const FakeStorageFileStatics&) = delete;
+  ~FakeStorageFileStatics() final;
+
+  // ABI::Windows::Storage::IStorageFileStatics:
+  IFACEMETHODIMP GetFileFromPathAsync(
+      HSTRING path,
+      ABI::Windows::Foundation::IAsyncOperation<
+          ABI::Windows::Storage::StorageFile*>** operation) final;
+  IFACEMETHODIMP GetFileFromApplicationUriAsync(
+      ABI::Windows::Foundation::IUriRuntimeClass* uri,
+      ABI::Windows::Foundation::IAsyncOperation<
+          ABI::Windows::Storage::StorageFile*>** operation) final;
+  IFACEMETHODIMP CreateStreamedFileAsync(
+      HSTRING display_name_with_extension,
+      ABI::Windows::Storage::IStreamedFileDataRequestedHandler* data_requested,
+      ABI::Windows::Storage::Streams::IRandomAccessStreamReference* thumbnail,
+      ABI::Windows::Foundation::IAsyncOperation<
+          ABI::Windows::Storage::StorageFile*>** operation) final;
+  IFACEMETHODIMP ReplaceWithStreamedFileAsync(
+      ABI::Windows::Storage::IStorageFile* file_to_replace,
+      ABI::Windows::Storage::IStreamedFileDataRequestedHandler* data_requested,
+      ABI::Windows::Storage::Streams::IRandomAccessStreamReference* thumbnail,
+      ABI::Windows::Foundation::IAsyncOperation<
+          ABI::Windows::Storage::StorageFile*>** operation) final;
+  IFACEMETHODIMP CreateStreamedFileFromUriAsync(
+      HSTRING display_name_with_extension,
+      ABI::Windows::Foundation::IUriRuntimeClass* uri,
+      ABI::Windows::Storage::Streams::IRandomAccessStreamReference* thumbnail,
+      ABI::Windows::Foundation::IAsyncOperation<
+          ABI::Windows::Storage::StorageFile*>** operation) final;
+  IFACEMETHODIMP ReplaceWithStreamedFileFromUriAsync(
+      ABI::Windows::Storage::IStorageFile* file_to_replace,
+      ABI::Windows::Foundation::IUriRuntimeClass* uri,
+      ABI::Windows::Storage::Streams::IRandomAccessStreamReference* thumbnail,
+      ABI::Windows::Foundation::IAsyncOperation<
+          ABI::Windows::Storage::StorageFile*>** operation) final;
+};
+
+}  // namespace webshare
+
+#endif  // CHROME_BROWSER_WEBSHARE_WIN_FAKE_STORAGE_FILE_STATICS_H_
diff --git a/chrome/browser/webshare/win/fake_storage_file_statics_unittest.cc b/chrome/browser/webshare/win/fake_storage_file_statics_unittest.cc
new file mode 100644
index 0000000..79ccdaf
--- /dev/null
+++ b/chrome/browser/webshare/win/fake_storage_file_statics_unittest.cc
@@ -0,0 +1,199 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/webshare/win/fake_storage_file_statics.h"
+
+#include <wrl/event.h>
+#include <wrl/implements.h>
+
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "base/win/scoped_hstring.h"
+#include "chrome/browser/webshare/win/fake_buffer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ABI::Windows::Foundation::IAsyncOperation;
+using ABI::Windows::Foundation::IAsyncOperationCompletedHandler;
+using ABI::Windows::Foundation::IAsyncOperationWithProgress;
+using ABI::Windows::Foundation::IAsyncOperationWithProgressCompletedHandler;
+using ABI::Windows::Foundation::IClosable;
+using ABI::Windows::Storage::FileAccessMode;
+using ABI::Windows::Storage::IStorageFile;
+using ABI::Windows::Storage::IStorageItem;
+using ABI::Windows::Storage::IStreamedFileDataRequestedHandler;
+using ABI::Windows::Storage::StorageFile;
+using ABI::Windows::Storage::Streams::IBuffer;
+using ABI::Windows::Storage::Streams::IInputStream;
+using ABI::Windows::Storage::Streams::InputStreamOptions;
+using ABI::Windows::Storage::Streams::IOutputStream;
+using ABI::Windows::Storage::Streams::IRandomAccessStream;
+using Microsoft::WRL::Callback;
+using Microsoft::WRL::ComPtr;
+using Microsoft::WRL::Make;
+
+namespace webshare {
+
+TEST(FakeStorageFileStaticsTest, CreateStreamedFileAsync) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  if (!base::win::ScopedHString::ResolveCoreWinRTStringDelayload())
+    return;
+
+  auto file_statics = Make<FakeStorageFileStatics>();
+
+  // Create a streamed file, populated on-demand by the provided callback.
+  ComPtr<IStorageFile> storage_file;
+  {
+    base::RunLoop run_loop;
+    auto file_name = base::win::ScopedHString::Create("MyTestFile.abc");
+    ComPtr<IAsyncOperation<StorageFile*>> create_operation;
+    file_statics->CreateStreamedFileAsync(
+        file_name.get(),
+        Callback<IStreamedFileDataRequestedHandler>([](IOutputStream* stream) {
+          // Create a small buffer of bytes to write to the stream
+          auto buffer = Make<FakeBuffer>(4);
+          EXPECT_HRESULT_SUCCEEDED(buffer->put_Length(4));
+          byte* raw_buffer;
+          EXPECT_HRESULT_SUCCEEDED(buffer->Buffer(&raw_buffer));
+          raw_buffer[0] = 'f';
+          raw_buffer[1] = 'i';
+          raw_buffer[2] = 's';
+          raw_buffer[3] = 'h';
+
+          // Write the bytes to the stream
+          ComPtr<IAsyncOperationWithProgress<UINT32, UINT32>> write_operation;
+          EXPECT_HRESULT_SUCCEEDED(
+              stream->WriteAsync(buffer.Get(), &write_operation));
+          ComPtr<IOutputStream> captured_output_stream = stream;
+          write_operation->put_Completed(
+              Callback<
+                  IAsyncOperationWithProgressCompletedHandler<UINT32, UINT32>>(
+                  [captured_output_stream](
+                      IAsyncOperationWithProgress<UINT32, UINT32>*
+                          async_operation,
+                      AsyncStatus async_status) {
+                    // Verify the write operation completed successfully
+                    EXPECT_EQ(async_status, AsyncStatus::Completed);
+                    UINT32 result;
+                    EXPECT_HRESULT_SUCCEEDED(
+                        async_operation->GetResults(&result));
+                    EXPECT_EQ(result, 4u);
+
+                    // Flush the stream
+                    ComPtr<IAsyncOperation<bool>> flush_operation;
+                    EXPECT_HRESULT_SUCCEEDED(
+                        captured_output_stream->FlushAsync(&flush_operation));
+                    flush_operation->put_Completed(
+                        Callback<IAsyncOperationCompletedHandler<bool>>(
+                            [captured_output_stream](
+                                IAsyncOperation<bool>* async_operation,
+                                AsyncStatus async_status) {
+                              // Verify the flush operation completed
+                              // successfully
+                              EXPECT_EQ(async_status, AsyncStatus::Completed);
+                              boolean result;
+                              EXPECT_HRESULT_SUCCEEDED(
+                                  async_operation->GetResults(&result));
+                              EXPECT_EQ(result, TRUE);
+
+                              // Close the stream
+                              ComPtr<IClosable> closable;
+                              EXPECT_HRESULT_SUCCEEDED(
+                                  captured_output_stream.As(&closable));
+                              EXPECT_HRESULT_SUCCEEDED(closable->Close());
+                              return S_OK;
+                            })
+                            .Get());
+                    return S_OK;
+                  })
+                  .Get());
+          return S_OK;
+        }).Get(),
+        /*thumbnail*/ nullptr, &create_operation);
+    ASSERT_HRESULT_SUCCEEDED(create_operation->put_Completed(
+        Callback<IAsyncOperationCompletedHandler<StorageFile*>>(
+            [&run_loop, &storage_file](
+                IAsyncOperation<StorageFile*>* async_operation,
+                AsyncStatus async_status) {
+              EXPECT_EQ(async_status, AsyncStatus::Completed);
+              EXPECT_HRESULT_SUCCEEDED(
+                  async_operation->GetResults(&storage_file));
+              run_loop.Quit();
+              return S_OK;
+            })
+            .Get()));
+    run_loop.Run();
+  }
+
+  // Verify the created streamed file has the expected name
+  ComPtr<IStorageItem> storage_item;
+  ASSERT_HRESULT_SUCCEEDED(storage_file.As(&storage_item));
+  HSTRING name;
+  ASSERT_HRESULT_SUCCEEDED(storage_item->get_Name(&name));
+  ASSERT_EQ(base::win::ScopedHString(name).GetAsUTF8(), "MyTestFile.abc");
+
+  // Open the streamed file
+  ComPtr<IRandomAccessStream> opened_stream;
+  {
+    base::RunLoop run_loop;
+    ComPtr<IAsyncOperation<IRandomAccessStream*>> open_operation;
+    ASSERT_HRESULT_SUCCEEDED(storage_file->OpenAsync(
+        FileAccessMode::FileAccessMode_Read, &open_operation));
+    ASSERT_HRESULT_SUCCEEDED(open_operation->put_Completed(
+        Callback<IAsyncOperationCompletedHandler<IRandomAccessStream*>>(
+            [&run_loop, &opened_stream](
+                IAsyncOperation<IRandomAccessStream*>* async_operation,
+                AsyncStatus async_status) {
+              EXPECT_EQ(async_status, AsyncStatus::Completed);
+              EXPECT_HRESULT_SUCCEEDED(
+                  async_operation->GetResults(&opened_stream));
+              run_loop.Quit();
+              return S_OK;
+            })
+            .Get()));
+    run_loop.Run();
+  }
+
+  ComPtr<IInputStream> input_stream;
+  ASSERT_HRESULT_SUCCEEDED(opened_stream->GetInputStreamAt(0, &input_stream));
+  UINT64 size;
+  ASSERT_HRESULT_SUCCEEDED(opened_stream->get_Size(&size));
+
+  // Read the opened stream
+  auto buffer = Make<FakeBuffer>(size);
+  {
+    base::RunLoop run_loop;
+    ComPtr<IAsyncOperationWithProgress<IBuffer*, UINT32>> read_operation;
+    ASSERT_HRESULT_SUCCEEDED(input_stream->ReadAsync(
+        buffer.Get(), size, InputStreamOptions::InputStreamOptions_None,
+        &read_operation));
+    ASSERT_HRESULT_SUCCEEDED(read_operation->put_Completed(
+        Callback<IAsyncOperationWithProgressCompletedHandler<IBuffer*, UINT32>>(
+            [&run_loop, &buffer](
+                IAsyncOperationWithProgress<IBuffer*, UINT32>* async_operation,
+                AsyncStatus async_status) {
+              EXPECT_EQ(async_status, AsyncStatus::Completed);
+              ComPtr<IBuffer> result;
+              EXPECT_HRESULT_SUCCEEDED(async_operation->GetResults(&result));
+              EXPECT_EQ(result.Get(), buffer.Get());
+              run_loop.Quit();
+              return S_OK;
+            })
+            .Get()));
+    run_loop.Run();
+  }
+
+  // Verify the stream read from the file has content matching what our
+  // DataRequested callback provided
+  UINT32 length;
+  ASSERT_HRESULT_SUCCEEDED(buffer->get_Length(&length));
+  ASSERT_EQ(length, size);
+  byte* raw_buffer;
+  ASSERT_HRESULT_SUCCEEDED(buffer->Buffer(&raw_buffer));
+  ASSERT_EQ(raw_buffer[0], 'f');
+  ASSERT_EQ(raw_buffer[1], 'i');
+  ASSERT_EQ(raw_buffer[2], 's');
+  ASSERT_EQ(raw_buffer[3], 'h');
+}
+
+}  // namespace webshare
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 0c55698..b616f29 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-master-1603281470-f96bc0fcebd9344c6ef9fb677ad5905993ab5142.profdata
+chrome-linux-master-1603322998-a2bfaa167e3697b2b14734e406c0399abff8eaf1.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index cf88274..3cdbe71 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-master-1603031994-5f3b6fcba7bce636145481c18ca09ca6363425d3.profdata
+chrome-win32-master-1603227551-27f8a1799a335df211e237de1f87f7621bc18d2f.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 915c179..3907efc 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-master-1602665973-82a3b15c2fe4da417cf5b287fae1d2a3020f8e39.profdata
+chrome-win64-master-1603291852-8226e53db1ad923442028152d5859381e4c42533.profdata
diff --git a/chrome/common/extensions/api/action.json b/chrome/common/extensions/api/action.json
index 49c4b2e8..3f88b616 100644
--- a/chrome/common/extensions/api/action.json
+++ b/chrome/common/extensions/api/action.json
@@ -9,6 +9,15 @@
     "compiler_options": {
       "implemented_in": "chrome/browser/extensions/api/extension_action/extension_action_api.h"
     },
+    "types": [
+      {
+        "id": "TabDetails",
+        "type": "object",
+        "properties": {
+          "tabId": { "type": "integer", "optional": true, "minimum": 0, "description": "The ID of the tab to query state for. If no tab is specified, the non-tab-specific state is returned." }
+        }
+      }
+    ],
     "functions": [{
       "name": "setTitle",
       "type": "function",
@@ -40,15 +49,7 @@
       "description": "Gets the title of the action.",
       "parameters": [{
         "name": "details",
-        "type": "object",
-        "properties": {
-          "tabId": {
-            "type": "integer",
-            "optional": true,
-            "minimum": 0,
-            "description": "Specify the tab to get the title from. If no tab is specified, the non-tab-specific title is returned."
-          }
-        }
+        "$ref": "TabDetails"
       }, {
         "type": "function",
         "name": "callback",
@@ -132,15 +133,7 @@
       "parameters": [
         {
           "name": "details",
-          "type": "object",
-          "properties": {
-            "tabId": {
-              "type": "integer",
-              "optional": true,
-              "minimum": 0,
-              "description": "Specify the tab to get the popup from. If no tab is specified, the non-tab-specific popup is returned."
-            }
-          }
+          "$ref": "TabDetails"
         },
         {
           "type": "function",
@@ -184,15 +177,7 @@
       "description": "Gets the badge text of the action. If no tab is specified, the non-tab-specific badge text is returned.",
       "parameters": [{
         "name": "details",
-        "type": "object",
-        "properties": {
-          "tabId": {
-            "type": "integer",
-            "optional": true,
-            "minimum": 0,
-            "description": "Specify the tab to get the badge text from. If no tab is specified, the non-tab-specific badge text is returned."
-          }
-        }
+        "$ref": "TabDetails"
       }, {
         "type": "function",
         "name": "callback",
@@ -235,15 +220,7 @@
       "description": "Gets the background color of the action.",
       "parameters": [{
         "name": "details",
-        "type": "object",
-        "properties": {
-          "tabId": {
-            "type": "integer",
-            "optional": true,
-            "minimum": 0,
-            "description": "Specify the tab to get the badge background color from. If no tab is specified, the non-tab-specific badge background color is returned."
-          }
-        }
+        "$ref": "TabDetails"
       }, {
         "type": "function",
         "name": "callback",
diff --git a/chrome/common/extensions/api/browser_action.json b/chrome/common/extensions/api/browser_action.json
index ed622ad9..f4c1d12e 100644
--- a/chrome/common/extensions/api/browser_action.json
+++ b/chrome/common/extensions/api/browser_action.json
@@ -27,6 +27,13 @@
         "isInstanceOf": "ImageData",
         "additionalProperties": { "type": "any" },
         "description": "Pixel data for an image. Must be an ImageData object; for example, from a <code>canvas</code> element."
+      },
+      {
+        "id": "TabDetails",
+        "type": "object",
+        "properties": {
+          "tabId": { "type": "integer", "optional": true, "minimum": 0, "description": "The ID of the tab to query state for. If no tab is specified, the non-tab-specific state is returned." }
+        }
       }
     ],
     "functions": [
@@ -60,14 +67,7 @@
         "parameters": [
           {
             "name": "details",
-            "type": "object",
-            "properties": {
-              "tabId": {
-                "type": "integer",
-                "optional": true,
-                "description": "The tab to get the title from. If no tab is specified, the default title is returned."
-              }
-            }
+            "$ref": "TabDetails"
           },
           {
             "type": "function",
@@ -158,14 +158,7 @@
         "parameters": [
           {
             "name": "details",
-            "type": "object",
-            "properties": {
-              "tabId": {
-                "type": "integer",
-                "optional": true,
-                "description": "The tab to get the popup from. If no tab is specified, the non-tab-specific popup is returned."
-              }
-            }
+            "$ref": "TabDetails"
           },
           {
             "type": "function",
@@ -210,14 +203,7 @@
         "parameters": [
           {
             "name": "details",
-            "type": "object",
-            "properties": {
-              "tabId": {
-                "type": "integer",
-                "optional": true,
-                "description": "The tab to get the badge text from. If no tab is specified, the non-tab-specific badge text is returned."
-              }
-            }
+            "$ref": "TabDetails"
           },
           {
             "type": "function",
@@ -264,14 +250,7 @@
         "parameters": [
           {
             "name": "details",
-            "type": "object",
-            "properties": {
-              "tabId": {
-                "type": "integer",
-                "optional": true,
-                "description": "The tab to get the badge background color from. If no tab is specified, the non-tab-specific badge background color is returned."
-              }
-            }
+            "$ref": "TabDetails"
           },
           {
             "type": "function",
diff --git a/chrome/common/extensions/api/cookies.json b/chrome/common/extensions/api/cookies.json
index 544d75c..55255d2 100644
--- a/chrome/common/extensions/api/cookies.json
+++ b/chrome/common/extensions/api/cookies.json
@@ -45,6 +45,16 @@
         "type": "string",
         "enum": ["evicted", "expired", "explicit", "expired_overwrite", "overwrite"],
         "description": "The underlying reason behind the cookie's change. If a cookie was inserted, or removed via an explicit call to \"chrome.cookies.remove\", \"cause\" will be \"explicit\". If a cookie was automatically removed due to expiry, \"cause\" will be \"expired\". If a cookie was removed due to being overwritten with an already-expired expiration date, \"cause\" will be set to \"expired_overwrite\".  If a cookie was automatically removed due to garbage collection, \"cause\" will be \"evicted\".  If a cookie was automatically removed due to a \"set\" call that overwrote it, \"cause\" will be \"overwrite\". Plan your response accordingly."
+      },
+      {
+        "id": "CookieDetails",
+        "type": "object",
+        "description": "Details to identify the cookie.",
+        "properties": {
+          "url": {"type": "string", "description": "The URL with which the cookie to access is associated. This argument may be a full URL, in which case any data following the URL path (e.g. the query string) is simply ignored. If host permissions for this URL are not specified in the manifest file, the API call will fail."},
+          "name": {"type": "string", "description": "The name of the cookie to access."},
+          "storeId": {"type": "string", "optional": true, "description": "The ID of the cookie store in which to look for the cookie. By default, the current execution context's cookie store will be used."}
+        }
       }
     ],
     "functions": [
@@ -54,14 +64,8 @@
         "description": "Retrieves information about a single cookie. If more than one cookie of the same name exists for the given URL, the one with the longest path will be returned. For cookies with the same path length, the cookie with the earliest creation time will be returned.",
         "parameters": [
           {
-            "type": "object",
             "name": "details",
-            "description": "Details to identify the cookie being retrieved.",
-            "properties": {
-              "url": {"type": "string", "description": "The URL with which the cookie to retrieve is associated. This argument may be a full URL, in which case any data following the URL path (e.g. the query string) is simply ignored. If host permissions for this URL are not specified in the manifest file, the API call will fail."},
-              "name": {"type": "string", "description": "The name of the cookie to retrieve."},
-              "storeId": {"type": "string", "optional": true, "description": "The ID of the cookie store in which to look for the cookie. By default, the current execution context's cookie store will be used."}
-            }
+            "$ref": "CookieDetails"
           },
           {
             "type": "function",
@@ -145,14 +149,8 @@
         "description": "Deletes a cookie by name.",
         "parameters": [
           {
-            "type": "object",
             "name": "details",
-            "description": "Information to identify the cookie to remove.",
-            "properties": {
-              "url": {"type": "string", "description": "The URL associated with the cookie. If host permissions for this URL are not specified in the manifest file, the API call will fail."},
-              "name": {"type": "string", "description": "The name of the cookie to remove."},
-              "storeId": {"type": "string", "optional": true, "description": "The ID of the cookie store to look in for the cookie. If unspecified, the cookie is looked for by default in the current execution context's cookie store."}
-            }
+            "$ref": "CookieDetails"
           },
           {
             "type": "function",
diff --git a/chrome/common/extensions/api/file_manager_private.idl b/chrome/common/extensions/api/file_manager_private.idl
index bed4bd8..9d5acf1f8 100644
--- a/chrome/common/extensions/api/file_manager_private.idl
+++ b/chrome/common/extensions/api/file_manager_private.idl
@@ -487,6 +487,10 @@
   // Drive label of the volume. Removable partitions that belong to the
   // same physical removable device share the same drive label.
   DOMString? driveLabel;
+
+  // The path on the remote host where this volume is mounted, for crostini this
+  // is the user's homedir (/home/<username>).
+  DOMString? remoteMountPath;
 };
 
 // Payload data for mount event.
diff --git a/chrome/common/extensions/api/history.json b/chrome/common/extensions/api/history.json
index 2eb7044ad..f75d0f7 100644
--- a/chrome/common/extensions/api/history.json
+++ b/chrome/common/extensions/api/history.json
@@ -40,6 +40,13 @@
             "description": "The <a href='#transition_types'>transition type</a> for this visit from its referrer."
           }
         }
+      },
+      {
+        "id": "UrlDetails",
+        "type": "object",
+        "properties": {
+          "url": {"type": "string", "description": "The URL for the operation. It must be in the format as returned from a call to history.search."}
+        }
       }
     ],
     "functions": [
@@ -74,10 +81,7 @@
         "parameters": [
           {
             "name": "details",
-            "type": "object",
-            "properties": {
-              "url": {"type": "string", "description": "The URL for which to retrieve visit information.  It must be in the format as returned from a call to history.search."}
-            }
+            "$ref": "UrlDetails"
           },
           {
             "name": "callback",
@@ -95,10 +99,7 @@
         "parameters": [
           {
             "name": "details",
-            "type": "object",
-            "properties": {
-              "url": {"type": "string", "description": "The URL to add."}
-            }
+            "$ref": "UrlDetails"
           },
           {
             "name": "callback",
@@ -115,10 +116,7 @@
         "parameters": [
           {
             "name": "details",
-            "type": "object",
-            "properties": {
-              "url": {"type": "string", "description": "The URL to remove."}
-            }
+            "$ref": "UrlDetails"
           },
           {
             "name": "callback",
diff --git a/chrome/common/extensions/api/input_ime.json b/chrome/common/extensions/api/input_ime.json
index 5f15e5e..bdde0826 100644
--- a/chrome/common/extensions/api/input_ime.json
+++ b/chrome/common/extensions/api/input_ime.json
@@ -138,6 +138,23 @@
           "undo",
           "addToDictionary"
         ]
+      },
+      {
+        "id": "MenuParameters",
+        "type": "object",
+        "properties": {
+          "engineID": {
+            "description": "ID of the engine to use.",
+            "type": "string"
+          },
+          "items": {
+            "description": "MenuItems to add or update. They will be added in the order they exist in the array.",
+            "type": "array",
+            "items": {
+              "$ref": "MenuItem"
+            }
+          }
+        }
       }
     ],
     "functions": [
@@ -565,20 +582,7 @@
         "parameters": [
           {
             "name": "parameters",
-            "type": "object",
-            "properties": {
-              "engineID": {
-                "description": "ID of the engine to use",
-                "type": "string"
-              },
-              "items": {
-                "description": "MenuItems to add. They will be added in the order they exist in the array.",
-                "type": "array",
-                "items": {
-                  "$ref": "MenuItem"
-                }
-              }
-            }
+            "$ref": "MenuParameters"
           },
           {
             "type": "function",
@@ -597,20 +601,7 @@
         "parameters": [
           {
             "name": "parameters",
-            "type": "object",
-            "properties": {
-              "engineID": {
-                "description": "ID of the engine to use",
-                "type": "string"
-              },
-              "items": {
-                "description": "Array of MenuItems to update",
-                "type": "array",
-                "items": {
-                  "$ref": "MenuItem"
-                }
-              }
-            }
+            "$ref": "MenuParameters"
           },
           {
             "type": "function",
diff --git a/chrome/common/extensions/api/omnibox.json b/chrome/common/extensions/api/omnibox.json
index faeb8cc..59cb7aa 100644
--- a/chrome/common/extensions/api/omnibox.json
+++ b/chrome/common/extensions/api/omnibox.json
@@ -20,6 +20,27 @@
         "description": "The window disposition for the omnibox query. This is the recommended context to display results. For example, if the omnibox command is to navigate to a certain URL, a disposition of 'newForegroundTab' means the navigation should take place in a new selected tab."
       },
       {
+        "id": "MatchClassification",
+        "nodoc": true,
+        "type": "object",
+        "description": "The style ranges for the description, as provided by the extension.",
+        "properties": {
+          "offset": { "type": "integer" },
+          "type": { "description": "The style type", "$ref": "DescriptionStyleType"},
+          "length": { "type": "integer", "optional": true }
+        }
+      },
+      {
+        "id": "MatchClassificationRaw",
+        "nodoc": true,
+        "type": "object",
+        "description": "The style ranges for the description, as provided by ToValue().",
+        "properties": {
+          "offset": { "type": "integer" },
+          "type": { "type": "integer" }
+        }
+      },
+      {
         "id": "SuggestResult",
         "type": "object",
         "description": "A suggest result.",
@@ -45,14 +66,8 @@
             "type": "array",
             "description": "An array of style ranges for the description, as provided by the extension.",
             "items": {
-              "type": "object",
               "name": "matchClassification",
-              "description": "The style ranges for the description, as provided by the extension.",
-              "properties": {
-                "offset": { "type": "integer" },
-                "type": { "description": "The style type", "$ref": "DescriptionStyleType"},
-                "length": { "type": "integer", "optional": true }
-              }
+              "$ref": "MatchClassification"
             }
           },
           "descriptionStylesRaw": {
@@ -61,13 +76,8 @@
             "type": "array",
             "description": "An array of style ranges for the description, as provided by ToValue().",
             "items": {
-              "type": "object",
-              "name": "matchClassification",
-              "description": "The style ranges for the description, as provided by ToValue().",
-              "properties": {
-                "offset": { "type": "integer" },
-                "type": { "type": "integer" }
-              }
+              "name": "matchClassificationRaw",
+              "$ref": "MatchClassificationRaw"
             }
           }
         }
@@ -89,14 +99,8 @@
             "type": "array",
             "description": "An array of style ranges for the description, as provided by the extension.",
             "items": {
-              "type": "object",
               "name": "matchClassification",
-              "description": "The style ranges for the description, as provided by the extension.",
-              "properties": {
-                "offset": { "type": "integer" },
-                "type": { "description": "The style type", "$ref": "DescriptionStyleType"},
-                "length": { "type": "integer", "optional": true }
-              }
+              "$ref": "MatchClassification"
             }
           },
           "descriptionStylesRaw": {
@@ -105,13 +109,8 @@
             "type": "array",
             "description": "An array of style ranges for the description, as provided by ToValue().",
             "items": {
-              "type": "object",
-              "name": "matchClassification",
-              "description": "The style ranges for the description, as provided by ToValue().",
-              "properties": {
-                "offset": { "type": "integer" },
-                "type": { "type": "integer" }
-              }
+              "name": "matchClassificationRaw",
+              "$ref": "MatchClassificationRaw"
             }
           }
         }
diff --git a/chrome/common/extensions/api/page_action.json b/chrome/common/extensions/api/page_action.json
index a6695ba..32c4f1f 100644
--- a/chrome/common/extensions/api/page_action.json
+++ b/chrome/common/extensions/api/page_action.json
@@ -16,6 +16,13 @@
         "isInstanceOf": "ImageData",
         "additionalProperties": { "type": "any" },
         "description": "Pixel data for an image. Must be an ImageData object (for example, from a <code>canvas</code> element)."
+      },
+      {
+        "id": "TabDetails",
+        "type": "object",
+        "properties": {
+          "tabId": { "type": "integer", "optional": true, "minimum": 0, "description": "The ID of the tab to query state for. If no tab is specified, the non-tab-specific state is returned." }
+        }
       }
     ],
     "functions": [
@@ -60,13 +67,7 @@
         "parameters": [
           {
             "name": "details",
-            "type": "object",
-            "properties": {
-              "tabId": {
-                "type": "integer",
-                "description": "Specify the tab to get the title from."
-              }
-            }
+            "$ref": "TabDetails"
           },
           {
             "type": "function",
@@ -154,13 +155,7 @@
         "parameters": [
           {
             "name": "details",
-            "type": "object",
-            "properties": {
-              "tabId": {
-                "type": "integer",
-                "description": "Specify the tab to get the popup from."
-              }
-            }
+            "$ref": "TabDetails"
           },
           {
             "type": "function",
diff --git a/chrome/common/extensions/api/windows.json b/chrome/common/extensions/api/windows.json
index fe1ac869..e82006a 100644
--- a/chrome/common/extensions/api/windows.json
+++ b/chrome/common/extensions/api/windows.json
@@ -89,6 +89,14 @@
         "type": "string",
         "description": "Specifies what type of browser window to create. 'panel' is deprecated and is available only to existing whitelisted extensions on Chrome OS.",
         "enum": ["normal", "popup", "panel"]
+      },
+      {
+        "id": "QueryOptions",
+        "type": "object",
+        "properties": {
+          "populate": {"type": "boolean", "optional": true, "description": "If true, the $(ref:windows.Window) object has a <var>tabs</var> property that contains a list of the $(ref:tabs.Tab) objects. The <code>Tab</code> objects only contain the <code>url</code>, <code>pendingUrl</code>, <code>title</code>, and <code>favIconUrl</code> properties if the extension's manifest file includes the <code>\"tabs\"</code> permission." },
+          "windowTypes": {"type": "array", "items": { "$ref": "WindowType" }, "optional": true, "description": "If set, the $(ref:windows.Window) returned is filtered based on its type. If unset, the default filter is set to <code>['normal', 'popup']</code>."}
+        }
       }
     ],
     "properties": {
@@ -109,14 +117,9 @@
         "parameters": [
           {"type": "integer", "name": "windowId", "minimum": -2},
           {
-            "type": "object",
-            "name": "getInfo",
-            "optional": true,
-            "description": "",
-            "properties": {
-              "populate": {"type": "boolean", "optional": true, "description": "If true, the $(ref:windows.Window) object has a <var>tabs</var> property that contains a list of the $(ref:tabs.Tab) objects. The <code>Tab</code> objects only contain the <code>url</code>, <code>pendingUrl</code>, <code>title</code>, and <code>favIconUrl</code> properties if the extension's manifest file includes the <code>\"tabs\"</code> permission." },
-              "windowTypes": {"type": "array", "items": { "$ref": "WindowType" }, "optional": true, "description": "If set, the $(ref:windows.Window) returned is filtered based on its type. If unset, the default filter is set to <code>['normal', 'popup']</code>."}
-            }
+            "name": "queryOptions",
+            "$ref": "QueryOptions",
+            "optional": true
           },
           {
             "type": "function",
@@ -135,14 +138,9 @@
         "description": "Gets the <a href='#current-window'>current window</a>.",
         "parameters": [
           {
-            "type": "object",
-            "name": "getInfo",
-            "optional": true,
-            "description": "",
-            "properties": {
-              "populate": {"type": "boolean", "optional": true, "description": "If true, the $(ref:windows.Window) object has a <var>tabs</var> property that contains a list of the $(ref:tabs.Tab) objects. The <code>Tab</code> objects only contain the <code>url</code>, <code>pendingUrl</code>, <code>title</code>, and <code>favIconUrl</code> properties if the extension's manifest file includes the <code>\"tabs\"</code> permission." },
-              "windowTypes": {"type": "array", "items": { "$ref": "WindowType" }, "optional": true, "description": "If set, the $(ref:windows.Window) returned is filtered based on its type. If unset, the default filter is set to <code>['normal', 'popup']</code>."}
-            }
+            "name": "queryOptions",
+            "$ref": "QueryOptions",
+            "optional": true
           },
           {
             "type": "function",
@@ -161,14 +159,9 @@
         "description": "Gets the window that was most recently focused &mdash; typically the window 'on top'.",
         "parameters": [
           {
-            "type": "object",
-            "name": "getInfo",
-            "optional": true,
-            "description": "",
-            "properties": {
-              "populate": {"type": "boolean", "optional": true, "description": "If true, the $(ref:windows.Window) object has a <var>tabs</var> property that contains a list of the $(ref:tabs.Tab) objects. The <code>Tab</code> objects only contain the <code>url</code>, <code>pendingUrl</code>, <code>title</code>, and <code>favIconUrl</code> properties if the extension's manifest file includes the <code>\"tabs\"</code> permission." },
-              "windowTypes": {"type": "array", "items": { "$ref": "WindowType" }, "optional": true, "description": "If set, the $(ref:windows.Window) returned is filtered based on its type. If unset, the default filter is set to <code>['normal', 'popup']</code>."}
-            }
+            "name": "queryOptions",
+            "$ref": "QueryOptions",
+            "optional": true
           },
           {
             "type": "function",
@@ -187,14 +180,9 @@
         "description": "Gets all windows.",
         "parameters": [
           {
-            "type": "object",
-            "name": "getInfo",
-            "optional": true,
-            "description": "",
-            "properties": {
-              "populate": {"type": "boolean", "optional": true, "description": "If true, each $(ref:windows.Window) object has a <var>tabs</var> property that contains a list of the $(ref:tabs.Tab) objects for that window. The <code>Tab</code> objects only contain the <code>url</code>, <code>pendingUrl</code>, <code>title</code>, and <code>favIconUrl</code> properties if the extension's manifest file includes the <code>\"tabs\"</code> permission." },
-              "windowTypes": {"type": "array", "items": { "$ref": "WindowType" }, "optional": true, "description": "If set, the $(ref:windows.Window) returned is filtered based on its type. If unset, the default filter is set to <code>['normal', 'popup']</code>."}
-            }
+            "name": "queryOptions",
+            "$ref": "QueryOptions",
+            "optional": true
           },
           {
             "type": "function",
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 213b1ac..d83c95f 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1276,7 +1276,7 @@
 // use of Clear Key key sytems, which is always allowed as required by the spec.
 // TODO(crbug.com/784675): This pref was used as a WebPreference which is why
 // the string is prefixed with "webkit.webprefs". Now this is used in
-// blink::mojom::RendererPreferences and we should migrate the pref to use a new
+// blink::RendererPreferences and we should migrate the pref to use a new
 // non-webkit-prefixed string.
 const char kEnableEncryptedMedia[] = "webkit.webprefs.encrypted_media_enabled";
 
diff --git a/chrome/credential_provider/extension/task_manager_unittests.cc b/chrome/credential_provider/extension/task_manager_unittests.cc
index b40e384..490168da 100644
--- a/chrome/credential_provider/extension/task_manager_unittests.cc
+++ b/chrome/credential_provider/extension/task_manager_unittests.cc
@@ -7,6 +7,7 @@
 #include <atlcomcli.h>
 #include <windows.h>
 
+#include "base/guid.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_run_loop_timeout.h"
@@ -121,10 +122,10 @@
   GoogleRegistrationDataForTesting g_registration_data(serial_number);
   base::string16 machine_guid = L"machine_guid";
   SetMachineGuidForTesting(machine_guid);
-  ASSERT_EQ(S_OK, SetDmTokenForTesting("dmtoken"));
-  std::string dm_token;
-  // DM token gets Base64 encoded so get the encoded value here.
-  ASSERT_EQ(S_OK, GetDmToken(&dm_token));
+
+  FakeTokenGenerator fake_token_generator;
+  fake_token_generator.SetTokensForTesting(
+      {base::GenerateGUID(), base::GenerateGUID()});
 
   // Create a fake user associated to a gaia id.
   CComBSTR sid1;
@@ -136,6 +137,11 @@
   ASSERT_EQ(S_OK, SetUserProperty(OLE2W(sid1), L"device_resource_id",
                                   device_resource_id1));
 
+  ASSERT_EQ(S_OK, GenerateGCPWDmToken((BSTR)sid1));
+
+  base::string16 dm_token1;
+  ASSERT_EQ(S_OK, GetGCPWDmToken((BSTR)sid1, &dm_token1));
+
   ASSERT_EQ(
       GetGlobalFlagOrDefault(
           credential_provider::extension::kLastPeriodicSyncTimeRegKey, L""),
@@ -151,8 +157,7 @@
   ASSERT_EQ(FakeTask::number_of_times_executed_, 2);
   ASSERT_EQ(FakeTask::user_device_context_.size(), (size_t)1);
   extension::UserDeviceContext c1 = {device_resource_id1, serial_number,
-                                     machine_guid, OLE2W(sid1),
-                                     base::UTF8ToUTF16(dm_token)};
+                                     machine_guid, OLE2W(sid1), dm_token1};
   ASSERT_TRUE(FakeTask::user_device_context_[0] == c1);
 
   ASSERT_NE(
@@ -169,14 +174,18 @@
   ASSERT_EQ(S_OK, SetUserProperty(OLE2W(sid2), L"device_resource_id",
                                   device_resource_id2));
 
+  ASSERT_EQ(S_OK, GenerateGCPWDmToken((BSTR)sid2));
+
+  base::string16 dm_token2;
+  ASSERT_EQ(S_OK, GetGCPWDmToken((BSTR)sid2, &dm_token2));
+
   task_environment()->FastForwardBy(base::TimeDelta::FromHours(2));
 
   ASSERT_EQ(FakeTask::number_of_times_executed_, 3);
   ASSERT_EQ(FakeTask::user_device_context_.size(), (size_t)2);
 
   extension::UserDeviceContext c2 = {device_resource_id2, serial_number,
-                                     machine_guid, OLE2W(sid2),
-                                     base::UTF8ToUTF16(dm_token)};
+                                     machine_guid, OLE2W(sid2), dm_token2};
   ASSERT_TRUE(FakeTask::user_device_context_[0] == c1);
   ASSERT_TRUE(FakeTask::user_device_context_[1] == c2);
 }
diff --git a/chrome/credential_provider/extension/user_context_enumerator.cc b/chrome/credential_provider/extension/user_context_enumerator.cc
index dd4d1f78..e377e58 100644
--- a/chrome/credential_provider/extension/user_context_enumerator.cc
+++ b/chrome/credential_provider/extension/user_context_enumerator.cc
@@ -41,11 +41,6 @@
   if (FAILED(hr))
     LOGFN(ERROR) << "GetMachineGuid failed hr=" << putHR(hr);
 
-  std::string dm_token = "";
-  hr = GetDmToken(&dm_token);
-  if (FAILED(hr))
-    LOGFN(WARNING) << "GetDmToken failed hr=" << putHR(hr);
-
   std::map<base::string16, UserTokenHandleInfo> sid_to_gaia_id;
   hr = GetUserTokenHandles(&sid_to_gaia_id);
   if (FAILED(hr))
@@ -53,9 +48,13 @@
 
   std::vector<UserDeviceContext> context_info;
   for (auto const& entry : sid_to_gaia_id) {
+    base::string16 dm_token = L"";
+    hr = credential_provider::GetGCPWDmToken(entry.first, &dm_token);
+    if (FAILED(hr))
+      LOGFN(WARNING) << "GetGCPWDmToken failed hr=" << putHR(hr);
+
     context_info.push_back({GetUserDeviceResourceId(entry.first), serial_number,
-                            machine_guid, entry.first,
-                            base::UTF8ToUTF16(dm_token)});
+                            machine_guid, entry.first, dm_token});
   }
 
   hr = task.SetContext(context_info);
diff --git a/chrome/credential_provider/gaiacp/BUILD.gn b/chrome/credential_provider/gaiacp/BUILD.gn
index 82623d75..cc861f73 100644
--- a/chrome/credential_provider/gaiacp/BUILD.gn
+++ b/chrome/credential_provider/gaiacp/BUILD.gn
@@ -85,6 +85,8 @@
     "reg_utils.h",
     "scoped_lsa_policy.cc",
     "scoped_lsa_policy.h",
+    "token_generator.cc",
+    "token_generator.h",
   ]
   public_configs = [ ":util_config" ]
   public_deps = [ "//chrome/credential_provider/common:common_constants" ]
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_base.cc b/chrome/credential_provider/gaiacp/gaia_credential_base.cc
index 61d930b..1141a3a3 100644
--- a/chrome/credential_provider/gaiacp/gaia_credential_base.cc
+++ b/chrome/credential_provider/gaiacp/gaia_credential_base.cc
@@ -2060,6 +2060,11 @@
   if (FAILED(hr) && hr != E_NOTIMPL)
     LOGFN(ERROR) << "StoreWindowsPasswordIfNeeded hr=" << putHR(hr);
 
+  hr = GenerateGCPWDmToken(sid);
+  if (FAILED(hr)) {
+    LOGFN(ERROR) << "GenerateGCPWDmToken hr=" << putHR(hr);
+  }
+
   // Upload device details to gem database.
   hr = GemDeviceDetailsManager::Get()->UploadDeviceDetails(access_token, sid,
                                                            username, domain);
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc b/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc
index 058cf5f..98f59a6 100644
--- a/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc
+++ b/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc
@@ -12,6 +12,7 @@
 #include "base/base64.h"
 #include "base/base_paths_win.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/guid.h"
 #include "base/json/json_writer.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
@@ -20,7 +21,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_path_override.h"
 #include "base/time/time_override.h"
-
 #include "chrome/browser/ui/startup/credential_provider_signin_dialog_win_test_data.h"
 #include "chrome/credential_provider/common/gcp_strings.h"
 #include "chrome/credential_provider/gaiacp/gaia_credential_base.h"
@@ -3156,9 +3156,7 @@
   GoogleRegistrationDataForTesting g_registration_data(serial_number);
   base::string16 domain = L"domain";
   base::string16 machine_guid = L"machine_guid";
-  std::string dm_token = "dm_token";
   SetMachineGuidForTesting(machine_guid);
-  SetDmTokenForTesting(dm_token);
 
   std::vector<std::string> mac_addresses;
   mac_addresses.push_back("mac_address_1");
@@ -3173,6 +3171,10 @@
                       base::UTF8ToUTF16(kDefaultGaiaId), base::string16(),
                       domain, &sid));
 
+  std::string dm_token = base::GenerateGUID();
+  FakeTokenGenerator fake_token_generator;
+  fake_token_generator.SetTokensForTesting({dm_token});
+
   // Change token response to an invalid one.
   SetDefaultTokenHandleResponse(kDefaultValidTokenHandleResponse);
 
@@ -3255,9 +3257,7 @@
   ASSERT_TRUE(request_dict.FindBoolKey("is_ad_joined_user").has_value());
   ASSERT_EQ(request_dict.FindBoolKey("is_ad_joined_user").value(), true);
   ASSERT_TRUE(request_dict.FindKey("wlan_mac_addr")->is_list());
-  std::string encoded_dm_token;
-  base::Base64Encode(dm_token, &encoded_dm_token);
-  ASSERT_EQ(*request_dict.FindStringKey("dm_token"), encoded_dm_token);
+  ASSERT_EQ(*request_dict.FindStringKey("dm_token"), dm_token);
 
   std::vector<std::string> actual_mac_address_list;
   for (const base::Value& value :
diff --git a/chrome/credential_provider/gaiacp/gcp_utils.cc b/chrome/credential_provider/gaiacp/gcp_utils.cc
index 695255c3..a69883c 100644
--- a/chrome/credential_provider/gaiacp/gcp_utils.cc
+++ b/chrome/credential_provider/gaiacp/gcp_utils.cc
@@ -52,6 +52,7 @@
 #include "chrome/credential_provider/gaiacp/gaia_resources.h"
 #include "chrome/credential_provider/gaiacp/logging.h"
 #include "chrome/credential_provider/gaiacp/reg_utils.h"
+#include "chrome/credential_provider/gaiacp/token_generator.h"
 #include "chrome/installer/launcher_support/chrome_launcher_support.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "google_apis/gaia/gaia_switches.h"
@@ -91,6 +92,9 @@
 constexpr char kSentinelFilename[] = "gcpw_startup.sentinel";
 constexpr int64_t kMaxConsecutiveCrashCount = 5;
 
+// L$ prefix means this secret can only be accessed locally.
+const wchar_t kLsaKeyDMTokenPrefix[] = L"L$GCPW-DM-Token-";
+
 constexpr base::win::i18n::LanguageSelector::LangToOffset
     kLanguageOffsetPairs[] = {
 #define HANDLE_LANGUAGE(l_, o_) {L## #l_, o_},
@@ -169,6 +173,57 @@
     LOGFN(ERROR) << "Could not delete version " << version_path.BaseName();
 }
 
+// Reads the dm token for |sid| from lsa store and writes into |token| output
+// parameter. If |refresh| is true, token is re-generated before returning.
+HRESULT GetGCPWDmTokenInternal(const base::string16& sid,
+                               base::string16* token,
+                               bool refresh) {
+  DCHECK(token);
+
+  base::string16 store_key = kLsaKeyDMTokenPrefix + sid;
+
+  auto policy = ScopedLsaPolicy::Create(POLICY_ALL_ACCESS);
+
+  if (!policy) {
+    HRESULT hr = HRESULT_FROM_WIN32(::GetLastError());
+    LOGFN(ERROR) << "ScopedLsaPolicy::Create hr=" << putHR(hr);
+    return hr;
+  }
+
+  if (refresh) {
+    if (policy->PrivateDataExists(store_key.c_str())) {
+      HRESULT hr = policy->RemovePrivateData(store_key.c_str());
+      if (FAILED(hr)) {
+        LOGFN(ERROR) << "ScopedLsaPolicy::RemovePrivateData hr=" << putHR(hr);
+        return hr;
+      }
+    }
+
+    base::string16 new_token =
+        base::UTF8ToUTF16(TokenGenerator::Get()->GenerateToken());
+
+    HRESULT hr = policy->StorePrivateData(store_key.c_str(), new_token.c_str());
+    if (FAILED(hr)) {
+      LOGFN(ERROR) << "ScopedLsaPolicy::StorePrivateData hr=" << putHR(hr);
+      return hr;
+    }
+
+    *token = new_token;
+  } else {
+    wchar_t dm_token_lsa_data[1024];
+    HRESULT hr = policy->RetrievePrivateData(
+        store_key.c_str(), dm_token_lsa_data, base::size(dm_token_lsa_data));
+    if (FAILED(hr)) {
+      LOGFN(ERROR) << "ScopedLsaPolicy::RetrievePrivateData hr=" << putHR(hr);
+      return hr;
+    }
+
+    *token = dm_token_lsa_data;
+  }
+
+  return S_OK;
+}
+
 }  // namespace
 
 // GoogleRegistrationDataForTesting //////////////////////////////////////////
@@ -1155,6 +1210,15 @@
       chrome_launcher_support::SYSTEM_LEVEL_INSTALLATION, false);
 }
 
+HRESULT GenerateGCPWDmToken(const base::string16& sid) {
+  base::string16 dm_token;
+  return GetGCPWDmTokenInternal(sid, &dm_token, true);
+}
+
+HRESULT GetGCPWDmToken(const base::string16& sid, base::string16* token) {
+  return GetGCPWDmTokenInternal(sid, token, false);
+}
+
 FakesForTesting::FakesForTesting() {}
 
 FakesForTesting::~FakesForTesting() {}
diff --git a/chrome/credential_provider/gaiacp/gcp_utils.h b/chrome/credential_provider/gaiacp/gcp_utils.h
index dd061c76..c4d0ec3 100644
--- a/chrome/credential_provider/gaiacp/gcp_utils.h
+++ b/chrome/credential_provider/gaiacp/gcp_utils.h
@@ -372,6 +372,15 @@
 // Returns the file path to system installed chrome.exe.
 base::FilePath GetSystemChromePath();
 
+// Generates gcpw dm token for the given |sid|. If any of the lsa operations
+// fail, function returns a result other than S_OK.
+HRESULT GenerateGCPWDmToken(const base::string16& sid);
+
+// Reads the gcpw dm token from lsa store for the given |sid| and writes it back
+// in |token| output parameter.  If any of the lsa operations fail, function
+// returns a result other than S_OK.
+HRESULT GetGCPWDmToken(const base::string16& sid, base::string16* token);
+
 }  // namespace credential_provider
 
 #endif  // CHROME_CREDENTIAL_PROVIDER_GAIACP_GCP_UTILS_H_
diff --git a/chrome/credential_provider/gaiacp/gem_device_details_manager.cc b/chrome/credential_provider/gaiacp/gem_device_details_manager.cc
index e38819eeb..f3e5c14 100644
--- a/chrome/credential_provider/gaiacp/gem_device_details_manager.cc
+++ b/chrome/credential_provider/gaiacp/gem_device_details_manager.cc
@@ -128,8 +128,8 @@
   for (const std::string& mac_address : mac_addresses)
     mac_address_value_list.Append(base::Value(mac_address));
 
-  std::string dm_token;
-  hr = GetDmToken(&dm_token);
+  base::string16 dm_token;
+  hr = GetGCPWDmToken(sid, &dm_token);
   if (FAILED(hr)) {
     LOGFN(WARNING) << "DM token is required to execute periodic tasks hr="
                  << putHR(hr);
@@ -157,7 +157,7 @@
   request_dict_->SetStringKey(kBuiltInAdminNameParameterName,
                               built_in_admin_name);
   request_dict_->SetStringKey(kAdminGroupNameParameterName, admin_group_name);
-  request_dict_->SetStringKey(kDmToken, dm_token);
+  request_dict_->SetStringKey(kDmToken, base::UTF16ToUTF8(dm_token));
 
   base::string16 known_resource_id = GetUserDeviceResourceId(sid);
   if (!known_resource_id.empty()) {
diff --git a/chrome/credential_provider/gaiacp/token_generator.cc b/chrome/credential_provider/gaiacp/token_generator.cc
new file mode 100644
index 0000000..ee38215
--- /dev/null
+++ b/chrome/credential_provider/gaiacp/token_generator.cc
@@ -0,0 +1,31 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/credential_provider/gaiacp/token_generator.h"
+
+#include "base/unguessable_token.h"
+
+namespace credential_provider {
+
+std::string TokenGenerator::GenerateToken() {
+  return base::UnguessableToken::Create().ToString();
+}
+
+// static
+TokenGenerator* TokenGenerator::Get() {
+  return *GetInstanceStorage();
+}
+
+// static
+TokenGenerator** TokenGenerator::GetInstanceStorage() {
+  static TokenGenerator instance;
+  static TokenGenerator* instance_storage = &instance;
+  return &instance_storage;
+}
+
+TokenGenerator::TokenGenerator() {}
+
+TokenGenerator::~TokenGenerator() = default;
+
+}  // namespace credential_provider
diff --git a/chrome/credential_provider/gaiacp/token_generator.h b/chrome/credential_provider/gaiacp/token_generator.h
new file mode 100644
index 0000000..994d0e47
--- /dev/null
+++ b/chrome/credential_provider/gaiacp/token_generator.h
@@ -0,0 +1,29 @@
+// 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_CREDENTIAL_PROVIDER_GAIACP_TOKEN_GENERATOR_H_
+#define CHROME_CREDENTIAL_PROVIDER_GAIACP_TOKEN_GENERATOR_H_
+
+#include <string>
+
+namespace credential_provider {
+
+class TokenGenerator {
+ public:
+  // Returns the storage used for the instance pointer.
+  static TokenGenerator** GetInstanceStorage();
+
+  static TokenGenerator* Get();
+
+  // Generates a 128-bit token from a cryptographically strong random source.
+  virtual std::string GenerateToken();
+
+ protected:
+  TokenGenerator();
+  virtual ~TokenGenerator();
+};
+
+}  // namespace credential_provider
+
+#endif  // CHROME_CREDENTIAL_PROVIDER_GAIACP_TOKEN_GENERATOR_H_
diff --git a/chrome/credential_provider/test/gcp_fakes.cc b/chrome/credential_provider/test/gcp_fakes.cc
index 19ec31b..df92fd2 100644
--- a/chrome/credential_provider/test/gcp_fakes.cc
+++ b/chrome/credential_provider/test/gcp_fakes.cc
@@ -1397,4 +1397,26 @@
   TaskManager::RunTasksInternal();
 }
 
+///////////////////////////////////////////////////////////////////////////////
+
+FakeTokenGenerator::FakeTokenGenerator()
+    : token_generator_(*GetInstanceStorage()) {
+  *GetInstanceStorage() = this;
+}
+
+FakeTokenGenerator::~FakeTokenGenerator() {
+  *GetInstanceStorage() = token_generator_;
+}
+
+std::string FakeTokenGenerator::GenerateToken() {
+  auto token = test_tokens_.front();
+  test_tokens_.erase(test_tokens_.begin());
+  return token;
+}
+
+void FakeTokenGenerator::SetTokensForTesting(
+    const std::vector<std::string>& test_tokens) {
+  test_tokens_ = test_tokens;
+}
+
 }  // namespace credential_provider
diff --git a/chrome/credential_provider/test/gcp_fakes.h b/chrome/credential_provider/test/gcp_fakes.h
index bc2a645c..45d99aa6 100644
--- a/chrome/credential_provider/test/gcp_fakes.h
+++ b/chrome/credential_provider/test/gcp_fakes.h
@@ -31,6 +31,7 @@
 #include "chrome/credential_provider/gaiacp/password_recovery_manager.h"
 #include "chrome/credential_provider/gaiacp/scoped_lsa_policy.h"
 #include "chrome/credential_provider/gaiacp/scoped_user_profile.h"
+#include "chrome/credential_provider/gaiacp/token_generator.h"
 #include "chrome/credential_provider/gaiacp/user_policies_manager.h"
 #include "chrome/credential_provider/gaiacp/win_http_url_fetcher.h"
 #include "chrome/credential_provider/setup/gcpw_files.h"
@@ -599,7 +600,7 @@
 
 class FakeUserPoliciesManager : public UserPoliciesManager {
  public:
-  explicit FakeUserPoliciesManager();
+  FakeUserPoliciesManager();
   explicit FakeUserPoliciesManager(bool cloud_policies_enabled);
   ~FakeUserPoliciesManager() override;
 
@@ -729,6 +730,22 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+class FakeTokenGenerator : public TokenGenerator {
+ public:
+  FakeTokenGenerator();
+  ~FakeTokenGenerator() override;
+
+  std::string GenerateToken() override;
+
+  void SetTokensForTesting(const std::vector<std::string>& test_tokens);
+
+ private:
+  TokenGenerator* token_generator_ = nullptr;
+  std::vector<std::string> test_tokens_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
 }  // namespace credential_provider
 
 #endif  // CHROME_CREDENTIAL_PROVIDER_TEST_GCP_FAKES_H_
diff --git a/chrome/installer/mac/signing/README.md b/chrome/installer/mac/signing/README.md
index 658d408..157f8ed3 100644
--- a/chrome/installer/mac/signing/README.md
+++ b/chrome/installer/mac/signing/README.md
@@ -16,7 +16,7 @@
 The scripts are invoked using the driver located at
 `//chrome/installer/mac/sign_chrome.py`. In order to sign a binary, a signing
 identity is required. Googlers can use the [internal development
-identity](https://goto.google.com/macoscerts); otherwise you must supply your
+identity](https://goto.google.com/ioscerts); otherwise you must supply your
 own. Note that a
 [self-signed](https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Procedures/Procedures.html)
 identity is incompatible with the _library validation_ signing option that
@@ -32,6 +32,30 @@
 bundle. The `--development` flag skips over code signing requirements and checks
 that do not work without the official Google signing identity.
 
+## The Installer Identity
+
+The above section speaks of the `--identity` parameter to `sign_chrome.py`, and
+how the normal development identity will do, and how a self-signed identity will
+not work. However, the identity used for Installer (.pkg) files is different.
+
+Installer files require a special Installer Package Signing Certificate, which
+is different than a normal certificate in that it has a special Extended Key
+Usage extension.
+
+For the normal identity, Apple provides both a development and a deployment
+certificate, and while the deployment certificate can be (and should be)
+carefully guarded, the development certificate can be more widely used by the
+development team. However, Apple provides _only_ a deployment installer
+certificate. For development purposes, you must self-sign your own.
+
+Directions on how to create a self-signed certificate with the special Extended
+Key Usage extension for installer use can be found on
+[security.stackexchange](https://security.stackexchange.com/a/47908).
+
+You will need to explicitly mark the certificate in Keychain Access as trusted.
+Be sure that `security -v find-identity` lists this new certificate as a valid
+identity.
+
 ## Chromium
 
 There are slight differences between the official Google Chrome signed build and
diff --git a/chrome/installer/mini_installer/mini_installer.cc b/chrome/installer/mini_installer/mini_installer.cc
index d01bb78c..a854348 100644
--- a/chrome/installer/mini_installer/mini_installer.cc
+++ b/chrome/installer/mini_installer/mini_installer.cc
@@ -736,115 +736,6 @@
          CreateWorkDir(base_path.get(), work_dir, exit_code);
 }
 
-// Returns true for ".." and "." directories.
-bool IsCurrentOrParentDirectory(const wchar_t* dir) {
-  return dir && dir[0] == L'.' &&
-         (dir[1] == L'\0' || (dir[1] == L'.' && dir[2] == L'\0'));
-}
-
-// Best effort directory tree deletion including the directory specified
-// by |path|, which must not end in a separator.
-// The |path| argument is writable so that each recursion can use the same
-// buffer as was originally allocated for the path.  The path will be unchanged
-// upon return.
-void RecursivelyDeleteDirectory(PathString* path) {
-  // |path| will never have a trailing backslash.
-  size_t end = path->length();
-  if (!path->append(L"\\*.*"))
-    return;
-
-  WIN32_FIND_DATA find_data = {0};
-  HANDLE find = ::FindFirstFile(path->get(), &find_data);
-  if (find != INVALID_HANDLE_VALUE) {
-    do {
-      // Chrome never creates files/directories with reparse points (i.e.,
-      // mounted folders, links, etc), so never try to delete them.
-      if (find_data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
-        continue;
-
-      // Use the short name if available to make the most of our buffer.
-      const wchar_t* name = find_data.cAlternateFileName[0]
-                                ? find_data.cAlternateFileName
-                                : find_data.cFileName;
-      if (IsCurrentOrParentDirectory(name))
-        continue;
-
-      path->truncate_at(end + 1);  // Keep the trailing backslash.
-      if (!path->append(name))
-        continue;  // Continue in spite of too long names.
-
-      if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-        RecursivelyDeleteDirectory(path);
-      else
-        ::DeleteFile(path->get());
-    } while (::FindNextFile(find, &find_data));
-    ::FindClose(find);
-  }
-
-  // Restore the path and delete the directory before we return.
-  path->truncate_at(end);
-  ::RemoveDirectory(path->get());
-}
-
-// Enumerates subdirectories of |parent_dir| and deletes all subdirectories
-// that match with a given |prefix|.  |parent_dir| must have a trailing
-// backslash.
-// The process is done on a best effort basis, so conceivably there might
-// still be matches left when the function returns.
-void DeleteDirectoriesWithPrefix(const wchar_t* parent_dir,
-                                 const wchar_t* prefix) {
-  // |parent_dir| is guaranteed to always have a trailing backslash.
-  PathString spec;
-  if (!spec.assign(parent_dir) || !spec.append(prefix) || !spec.append(L"*.*"))
-    return;
-
-  WIN32_FIND_DATA find_data = {0};
-  HANDLE find = ::FindFirstFileEx(spec.get(), FindExInfoStandard, &find_data,
-                                  FindExSearchLimitToDirectories, nullptr, 0);
-  if (find == INVALID_HANDLE_VALUE)
-    return;
-
-  PathString path;
-  do {
-    // Chrome never creates files/directories with reparse points (i.e., mounted
-    // folders, links, etc), so never try to delete them.
-    if (find_data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
-      continue;
-
-    if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-      // Use the short name if available to make the most of our buffer.
-      const wchar_t* name = find_data.cAlternateFileName[0]
-                                ? find_data.cAlternateFileName
-                                : find_data.cFileName;
-      if (IsCurrentOrParentDirectory(name))
-        continue;
-      if (path.assign(parent_dir) && path.append(name))
-        RecursivelyDeleteDirectory(&path);
-    }
-  } while (::FindNextFile(find, &find_data));
-  ::FindClose(find);
-}
-
-// Attempts to free up space by deleting temp directories that previous
-// installer runs have failed to clean up.
-void DeleteOldChromeTempDirectories() {
-  static const wchar_t* const kDirectoryPrefixes[] = {
-      kTempPrefix,
-      L"chrome_"  // Previous installers created directories with this prefix
-                  // and there are still some lying around.
-  };
-
-  ProcessExitResult ignore(SUCCESS_EXIT_CODE);
-  PathString temp;
-  // GetTempDir always returns a path with a trailing backslash.
-  if (!GetTempDir(&temp, &ignore))
-    return;
-
-  for (size_t i = 0; i < _countof(kDirectoryPrefixes); ++i) {
-    DeleteDirectoriesWithPrefix(temp.get(), kDirectoryPrefixes[i]);
-  }
-}
-
 // Checks the command line for specific mini installer flags.
 // If the function returns true, the command line has been processed and all
 // required actions taken.  The installer must exit and return the returned
@@ -864,12 +755,6 @@
 }
 
 ProcessExitResult WMain(HMODULE module) {
-  // Always start with deleting potential leftovers from previous installations.
-  // This can make the difference between success and failure.  We've seen
-  // many installations out in the field fail due to out of disk space problems
-  // so this could buy us some space.
-  DeleteOldChromeTempDirectories();
-
   ProcessExitResult exit_code = ProcessExitResult(SUCCESS_EXIT_CODE);
 
   // Parse configuration from the command line and resources.
diff --git a/chrome/renderer/lite_video/OWNERS b/chrome/renderer/lite_video/OWNERS
index d5e2286..9bcf864 100644
--- a/chrome/renderer/lite_video/OWNERS
+++ b/chrome/renderer/lite_video/OWNERS
@@ -1,3 +1,3 @@
 file://components/data_reduction_proxy/OWNERS
 
-# COMPONENT: Internal>Network>DataUse
+# COMPONENT: Internals>Network>DataUse
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 7eb948d..3facfa1 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -330,6 +330,8 @@
       "../browser/webshare/win/fake_iasync_operation_with_progress.h",
       "../browser/webshare/win/fake_random_access_stream.cc",
       "../browser/webshare/win/fake_random_access_stream.h",
+      "../browser/webshare/win/fake_storage_file_statics.cc",
+      "../browser/webshare/win/fake_storage_file_statics.h",
       "../browser/webshare/win/scoped_fake_data_transfer_manager_interop.cc",
       "../browser/webshare/win/scoped_fake_data_transfer_manager_interop.h",
       "//chrome/app/chrome_crash_reporter_client_win.cc",
@@ -4646,6 +4648,7 @@
 
       # NTP is in native code on Android.
       "../browser/search/ntp_features_unittest.cc",
+      "../browser/search/recipe_tasks/recipe_tasks_service_unittest.cc",
       "../browser/search/shopping_tasks/shopping_tasks_service_unittest.cc",
     ]
     if (is_posix || is_fuchsia) {
@@ -5818,6 +5821,7 @@
       "../browser/webshare/win/fake_data_transfer_manager_interop_unittest.cc",
       "../browser/webshare/win/fake_data_transfer_manager_unittest.cc",
       "../browser/webshare/win/fake_random_access_stream_unittest.cc",
+      "../browser/webshare/win/fake_storage_file_statics_unittest.cc",
       "../browser/webshare/win/show_share_ui_for_window_operation_unittest.cc",
     ]
     deps += [
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/TranslateUtil.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/TranslateUtil.java
index 18dc546..5776bd4 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/TranslateUtil.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/TranslateUtil.java
@@ -10,6 +10,7 @@
 import org.junit.Assert;
 
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.infobar.InfoBarContainer;
 import org.chromium.chrome.browser.infobar.TranslateCompactInfoBar;
 import org.chromium.components.infobars.InfoBar;
 import org.chromium.components.infobars.InfoBarCompactLayout;
@@ -18,6 +19,9 @@
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
+import java.util.ArrayList;
+import java.util.concurrent.TimeoutException;
+
 /**
  * Utility functions for dealing with Translate InfoBars.
  */
@@ -100,4 +104,27 @@
             final TranslateCompactInfoBar infoBar, final String code) {
         TestThreadUtils.runOnUiThreadBlocking(() -> { infoBar.onTargetMenuItemClicked(code); });
     }
+
+    /**
+     * Wait until the translate infobar is present in the given InfoBarContainer and is in the given
+     * state. Throws a TimeoutException if the given state is never reached.
+     */
+    public static void waitForTranslateInfoBarState(
+            InfoBarContainer container, boolean expectTranslated) throws TimeoutException {
+        CriteriaHelper.pollUiThread(() -> {
+            ArrayList<InfoBar> infoBars = container.getInfoBarsForTesting();
+            if (infoBars.isEmpty()) {
+                return false;
+            }
+            assertCompactTranslateInfoBar(infoBars.get(0));
+            TranslateCompactInfoBar infoBar = (TranslateCompactInfoBar) infoBars.get(0);
+            if (expectTranslated) {
+                return !infoBar.isSourceTabSelectedForTesting()
+                        && infoBar.isTargetTabSelectedForTesting();
+            } else {
+                return infoBar.isSourceTabSelectedForTesting()
+                        && !infoBar.isTargetTabSelectedForTesting();
+            }
+        });
+    }
 }
diff --git a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/windows_basic/service_worker_background.js b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/windows_basic/service_worker_background.js
index b0096962..db8d0b4 100644
--- a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/windows_basic/service_worker_background.js
+++ b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/windows_basic/service_worker_background.js
@@ -27,14 +27,6 @@
   }
 }
 
-var getCurrentWindowUtil = function(getCurrentCallback) {
-  try {
-    chrome.windows.getCurrent(getCurrentCallback);
-  } catch (e) {
-    chrome.test.fail(e);
-  }
-}
-
 chrome.test.runTests([
   // Get the window that was automatically created.
   function testWindowGetAllBeforeCreate() {
@@ -63,12 +55,6 @@
         chrome.test.assertEq(400, windowData.height);
         chrome.test.succeed();
       });
-      // Check that the created window is the current window.
-      getCurrentWindowUtil(function(currentWindowData) {
-        chrome.test.assertEq(createdWindowId, currentWindowData.id);
-        chrome.test.succeed();
-      });
-      chrome.test.succeed();
     });
   },
   ]);
diff --git a/chrome/test/data/extensions/platform_apps/web_view/focus_accessibility/main.js b/chrome/test/data/extensions/platform_apps/web_view/focus_accessibility/main.js
index 9fe2ee195..76f62075 100644
--- a/chrome/test/data/extensions/platform_apps/web_view/focus_accessibility/main.js
+++ b/chrome/test/data/extensions/platform_apps/web_view/focus_accessibility/main.js
@@ -18,7 +18,11 @@
     webview.removeEventListener('loadabort', onLoadAbort);
   };
   webview.src = 'data:text/html,' +
-      '<html><body><button>Guest button</button></body></html>';
+      '<html><body><button>Guest button</button>' +
+      '<iframe src="data:text/html,' +
+      '<html><body><input type=text aria-label=InnerFrameTextField></input>' +
+      '</body></html>"></iframe>' +
+      '</body></html>';
   return webview;
 }
 
diff --git a/chrome/test/data/pdf/BUILD.gn b/chrome/test/data/pdf/BUILD.gn
index ef4ed71..728e86d 100644
--- a/chrome/test/data/pdf/BUILD.gn
+++ b/chrome/test/data/pdf/BUILD.gn
@@ -193,9 +193,13 @@
 
 js_library("viewer_thumbnail_bar_test") {
   deps = [
+    ":test_util",
+    "../webui:test_util.m",
     "//chrome/browser/resources/pdf/elements:viewer-thumbnail",
     "//chrome/browser/resources/pdf/elements:viewer-thumbnail-bar",
+    "//third_party/polymer/v3_0/components-chromium/iron-test-helpers:mock-interactions",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/js/cr/ui:focus_outline_manager.m",
   ]
   externs_list = [ "$externs_path/test.js" ]
 }
diff --git a/chrome/test/data/pdf/viewer_thumbnail_bar_test.js b/chrome/test/data/pdf/viewer_thumbnail_bar_test.js
index 61863951..f5940d8e 100644
--- a/chrome/test/data/pdf/viewer_thumbnail_bar_test.js
+++ b/chrome/test/data/pdf/viewer_thumbnail_bar_test.js
@@ -5,6 +5,8 @@
 import {eventToPromise} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/_test_resources/webui/test_util.m.js';
 import {ViewerThumbnailBarElement} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/elements/viewer-thumbnail-bar.js';
 import {ViewerThumbnailElement} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/elements/viewer-thumbnail.js';
+import {FocusOutlineManager} from 'chrome://resources/js/cr/ui/focus_outline_manager.m.js';
+import {keyDownOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {testAsync} from './test_util.js';
@@ -30,6 +32,14 @@
   return thumbnailBarHeight;
 }
 
+/**
+ * @param {!HTMLElement} element
+ * @param {string} key
+ */
+function keydown(element, key) {
+  keyDownOn(element, 0, [], key);
+}
+
 // Unit tests for the viewer-thumbnail-bar element.
 const tests = [
   // Test that the thumbnail bar has the correct number of thumbnails and
@@ -55,7 +65,7 @@
        */
       function testNavigateThumbnail(thumbnail, expectedPageIndex) {
         const whenChanged = eventToPromise('change-page', thumbnailBar);
-        thumbnail.shadowRoot.querySelector('#thumbnail').click();
+        thumbnail.getClickTarget().click();
         return whenChanged.then(e => {
           chrome.test.assertEq(expectedPageIndex, e.detail.page);
           chrome.test.assertEq('thumbnail', e.detail.origin);
@@ -156,6 +166,129 @@
       }
     });
   },
+  function testThumbnailForwardFocus() {
+    const testDocLength = 10;
+    const thumbnailBar = createThumbnailBar();
+    thumbnailBar.docLength = testDocLength;
+
+    flush();
+
+    testAsync(async () => {
+      /**
+       * @param {number} pageNumber
+       * @return {!Promise}
+       */
+      function waitForwardFocus(pageNumber) {
+        // Reset focus.
+        thumbnailBar.blur();
+
+        const toThumbnail = /** @type {!ViewerThumbnailElement} */ (
+            thumbnailBar.getThumbnailForPage(pageNumber));
+        const whenActiveThumbnailFocused = eventToPromise('focus', toThumbnail);
+
+        // Calling focus() on `thumbnailBar` in this test doesn't trigger the
+        // event listener, but manually dispatching an event does.
+        thumbnailBar.dispatchEvent(new FocusEvent('focus'));
+        return whenActiveThumbnailFocused;
+      }
+
+      // When there's no active page, focus should forward to the first
+      // thumbnail.
+      await waitForwardFocus(1);
+
+      // When there's an active page, focus should forward to the thumbnail of
+      // the active page.
+      let activePage = 3;
+      thumbnailBar.activePage = activePage;
+      await waitForwardFocus(activePage);
+
+      activePage = 10;
+      thumbnailBar.activePage = activePage;
+      await waitForwardFocus(activePage);
+    });
+  },
+  function testThumbnailUpDownFocus() {
+    const testDocLength = 3;
+    const thumbnailBar = createThumbnailBar();
+    thumbnailBar.docLength = testDocLength;
+
+    flush();
+
+    testAsync(async () => {
+      /**
+       * @param {!ViewerThumbnailElement} fromThumbnail
+       * @param {boolean} up
+       */
+      async function pressUpDownArrow(fromThumbnail, up) {
+        const fromPageNumber = fromThumbnail.pageNumber;
+        const toPageNumber = up ? fromPageNumber - 1 : fromPageNumber + 1;
+        const toThumbnail = /** @type {!ViewerThumbnailElement} */ (
+            thumbnailBar.getThumbnailForPage(toPageNumber));
+
+        const whenToThumbnailFocused = eventToPromise('focus', toThumbnail);
+        keydown(fromThumbnail, up ? 'ArrowUp' : 'ArrowDown');
+        await whenToThumbnailFocused;
+      }
+
+      const thumbnails =
+          /** @type {!NodeList<!ViewerThumbnailElement>} */ (
+              thumbnailBar.shadowRoot.querySelectorAll('viewer-thumbnail'));
+
+      // Start focus on the second of three thumbnails.
+      // Simulate this focus by mouse so `ViewerThumbnailElement.onFocus_()`
+      // doesn't forward the focus.
+      FocusOutlineManager.forDocument(document).visible = false;
+      let focusedIndex = 1;
+      thumbnails[focusedIndex].focus();
+
+      await pressUpDownArrow(thumbnails[focusedIndex], /*up=*/ true);
+      focusedIndex -= 1;
+      chrome.test.assertEq(
+          thumbnails[focusedIndex], thumbnailBar.shadowRoot.activeElement);
+
+      await pressUpDownArrow(thumbnails[focusedIndex], /*up=*/ false);
+      focusedIndex += 1;
+      chrome.test.assertEq(
+          thumbnails[focusedIndex], thumbnailBar.shadowRoot.activeElement);
+
+      await pressUpDownArrow(thumbnails[focusedIndex], /*up=*/ false);
+      focusedIndex += 1;
+      chrome.test.assertEq(
+          thumbnails[focusedIndex], thumbnailBar.shadowRoot.activeElement);
+
+      await pressUpDownArrow(thumbnails[focusedIndex], /*up=*/ true);
+      focusedIndex -= 1;
+      chrome.test.assertEq(
+          thumbnails[focusedIndex], thumbnailBar.shadowRoot.activeElement);
+    });
+  },
+  function testThumbnailLeftRightSelect() {
+    const testDocLength = 2;
+    const thumbnailBar = createThumbnailBar();
+    thumbnailBar.docLength = testDocLength;
+
+    flush();
+
+    thumbnailBar.activePage = 1;
+    let whenChanged = eventToPromise('change-page', thumbnailBar);
+    keydown(thumbnailBar, 'ArrowRight');
+    return whenChanged
+        .then(e => {
+          // The event contains the zero-based page index.
+          chrome.test.assertEq(1, e.detail.page);
+
+          thumbnailBar.activePage = 2;
+          whenChanged = eventToPromise('change-page', thumbnailBar);
+          keydown(thumbnailBar, 'ArrowLeft');
+          return whenChanged;
+        })
+        .then(e => {
+          // The event contains the zero-based page index.
+          chrome.test.assertEq(0, e.detail.page);
+
+          chrome.test.succeed();
+        });
+  }
 ];
 
 chrome.test.runTests(tests);
diff --git a/chrome/test/data/privacy_budget/calls_canvas_to_blob.html b/chrome/test/data/privacy_budget/calls_canvas_to_blob.html
new file mode 100644
index 0000000..81d1737
--- /dev/null
+++ b/chrome/test/data/privacy_budget/calls_canvas_to_blob.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Privacy Budget: Test page that calls Canvas.toBlob.</title>
+<script src="test_utils.js"></script>
+<script src="canvas_to_blob.js"></script>
diff --git a/chrome/test/data/privacy_budget/canvas_to_blob.js b/chrome/test/data/privacy_budget/canvas_to_blob.js
new file mode 100644
index 0000000..5b78eb5
--- /dev/null
+++ b/chrome/test/data/privacy_budget/canvas_to_blob.js
@@ -0,0 +1,13 @@
+// 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.
+//
+// Gets an image blob from a HTMLCanvasElement and sends it back to the test
+// via `sendValueToTest`.
+window.addEventListener('load', () => {
+  document.createElement('canvas').toBlob(function(blob) {
+    sendValueToTest(JSON.stringify({
+      'type': blob.type,
+    }));
+  });
+});
diff --git a/chrome/test/data/ssl/page_with_form_targeting_http_url.html b/chrome/test/data/ssl/page_with_form_targeting_http_url.html
index 4e3a86f..92ba15d 100644
--- a/chrome/test/data/ssl/page_with_form_targeting_http_url.html
+++ b/chrome/test/data/ssl/page_with_form_targeting_http_url.html
@@ -2,7 +2,7 @@
 <head><title>Page with form that targets an http URL</title>
 </head>
 <body>
-  <form action='http://REPLACE_WITH_HOST_AND_PORT/google.html' id='theform' method='post'>
+  <form action='http://REPLACE_WITH_HOST_AND_PORT/ssl/google.html' id='theform' method='post'>
     <input type='text' id='textfield' name='fieldname' value='fieldvalue'>
     <input type='submit' id='submit' value='submit'>
   </form>
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index d3007180..293499d0 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -441,7 +441,7 @@
     "./cr_components:modulize",
     "./cr_components/chromeos:modulize",
     "./cr_elements:modulize",
-    "./js/cr/ui:modulize",
+    "./js/cr:modulize",
     "./resources:modulize",
     "./settings:modulize",
   ]
@@ -454,6 +454,7 @@
 js_modulizer("modulize_local") {
   input_files = [
     "cr_focus_row_behavior_test.js",
+    "cr_test.js",
     "fake_chrome_event.js",
     "mock_controller.js",
     "mock_timer.js",
@@ -461,7 +462,8 @@
     "test_store.js",
     "test_util.js",
   ]
-  namespace_rewrites = test_namespace_rewrites
+  namespace_rewrites =
+      test_namespace_rewrites + [ "cr.addSingletonGetter|addSingletonGetter" ]
 }
 
 group("closure_compile") {
diff --git a/chrome/test/data/webui/cr_test.js b/chrome/test/data/webui/cr_test.js
index 6a01e35e..e8166c4 100644
--- a/chrome/test/data/webui/cr_test.js
+++ b/chrome/test/data/webui/cr_test.js
@@ -2,10 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-var EventTarget;
+// #import {addSingletonGetter} from 'chrome://resources/js/cr.m.js';
+
+/* #ignore */ var EventTarget;
 
 function setUp() {
-  EventTarget = cr.EventTarget;
+  /* #ignore */ EventTarget = cr.EventTarget;
 }
 
 function testDefineProperty() {
@@ -218,7 +220,7 @@
   assertTrue(hit);
 }
 
-function testAddSingletonGetter() {
+/* #export */ function testAddSingletonGetter() {
   function Foo() {}
   cr.addSingletonGetter(Foo);
 
@@ -242,7 +244,7 @@
       x, z, 'Should return a different object after clearing for testing');
 }
 
-function testDefineWithGetter() {
+/* #export */ function testDefineWithGetter() {
   var v = 0;
   cr.define('foo', function() {
     return {
@@ -257,3 +259,6 @@
   v = 1;
   assertEquals(1, foo.v);
 }
+
+window.setUp = setUp;
+window.testAddSingletonGetter = testAddSingletonGetter;
diff --git a/chrome/test/data/webui/js/cr/BUILD.gn b/chrome/test/data/webui/js/cr/BUILD.gn
new file mode 100644
index 0000000..56fb8493
--- /dev/null
+++ b/chrome/test/data/webui/js/cr/BUILD.gn
@@ -0,0 +1,17 @@
+# 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.
+
+import("//third_party/closure_compiler/compile_js.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+
+group("modulize") {
+  deps = [
+    ":modulize_local",
+    "./ui:modulize",
+  ]
+}
+
+js_modulizer("modulize_local") {
+  input_files = [ "event_target_test.js" ]
+}
diff --git a/chrome/test/data/webui/js/cr/event_target_test.js b/chrome/test/data/webui/js/cr/event_target_test.js
index 31e97df..65fcde4 100644
--- a/chrome/test/data/webui/js/cr/event_target_test.js
+++ b/chrome/test/data/webui/js/cr/event_target_test.js
@@ -2,13 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-/* @const */ var EventTarget;
+// clang-format off
+// #import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js';
+// clang-format on
 
-function setUp() {
-  EventTarget = cr.EventTarget;
+/* #ignore */ /* @const */ var EventTarget;
+
+/* #export */ function setUp() {
+  /* #ignore */ EventTarget = cr.EventTarget;
 }
 
-function testFunctionListener() {
+/* #export */ function testFunctionListener() {
   var fi = 0;
   function f(e) {
     fi++;
@@ -37,7 +41,7 @@
   assertEquals(1, gi, 'Should have been called once');
 }
 
-function testHandleEvent() {
+/* #export */ function testHandleEvent() {
   var fi = 0;
   var f = {
     handleEvent: function(e) {
@@ -70,7 +74,7 @@
   assertEquals(1, gi, 'Should have been called once');
 }
 
-function testPreventDefault() {
+/* #export */ function testPreventDefault() {
   var i = 0;
   function prevent(e) {
     i++;
@@ -95,3 +99,8 @@
   assertEquals(2, j);
   assertEquals(1, i);
 }
+
+window.setUp = setUp;
+window.testFunctionListener = testFunctionListener;
+window.testHandleEvent = testHandleEvent;
+window.testPreventDefault = testPreventDefault;
diff --git a/chrome/test/data/webui/js/cr/ui/BUILD.gn b/chrome/test/data/webui/js/cr/ui/BUILD.gn
index 6d5b8b9..e6a76361 100644
--- a/chrome/test/data/webui/js/cr/ui/BUILD.gn
+++ b/chrome/test/data/webui/js/cr/ui/BUILD.gn
@@ -2,18 +2,17 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//third_party/closure_compiler/compile_js.gni")
+import("//ui/webui/resources/js/cr.gni")
 import("//ui/webui/resources/tools/js_modulizer.gni")
 
-group("modulize") {
-  deps = [ ":modulize_local" ]
-}
-
-js_modulizer("modulize_local") {
-  input_files = [ "grid_test.js" ]
-
-  namespace_rewrites = [
-    "cr.ui.Grid|Grid",
-    "cr.ui.ArrayDataModel|ArrayDataModel",
+js_modulizer("modulize") {
+  input_files = [
+    "grid_test.js",
+    "array_data_model_test.js",
+    "command_test.js",
+    "context_menu_handler_test.js",
+    "list_test.js",
   ]
+
+  namespace_rewrites = cr_namespace_rewrites
 }
diff --git a/chrome/test/data/webui/js/cr/ui/array_data_model_test.js b/chrome/test/data/webui/js/cr/ui/array_data_model_test.js
index eaa3087..50feb78 100644
--- a/chrome/test/data/webui/js/cr/ui/array_data_model_test.js
+++ b/chrome/test/data/webui/js/cr/ui/array_data_model_test.js
@@ -2,14 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-function testSlice() {
+// clang-format off
+// #import {ArrayDataModel} from 'chrome://resources/js/cr/ui/array_data_model.m.js';
+// clang-format on
+
+/* #export */ function testSlice() {
   var m = new cr.ui.ArrayDataModel([0, 1, 2]);
   assertArrayEquals([0, 1, 2], m.slice());
   assertArrayEquals([1, 2], m.slice(1));
   assertArrayEquals([1], m.slice(1, 2));
 }
 
-function testPush() {
+/* #export */ function testPush() {
   var m = new cr.ui.ArrayDataModel([0, 1, 2]);
 
   var count = 0;
@@ -27,7 +31,7 @@
   assertEquals(1, count, 'The splice event should only fire once');
 }
 
-function testSplice() {
+/* #export */ function testSplice() {
   function compare(array, args) {
     var m = new cr.ui.ArrayDataModel(array.slice());
     var expected = array.slice();
@@ -46,7 +50,7 @@
   compare([1, 2, 3], [5, 3, 1, 2, 3]);
 }
 
-function testPermutation() {
+/* #export */ function testPermutation() {
   function doTest(sourceArray, spliceArgs) {
     var m = new cr.ui.ArrayDataModel(sourceArray.slice());
     var permutation;
@@ -73,7 +77,7 @@
   doTest([1, 2, 3], [0, 3, 1, 2, 3]);
 }
 
-function testUpdateIndexes() {
+/* #export */ function testUpdateIndexes() {
   var m = new cr.ui.ArrayDataModel([1, 2, 3]);
   var changedIndexes = [];
   m.addEventListener('change', function(event) {
@@ -83,7 +87,7 @@
   assertArrayEquals([0, 1, 2], changedIndexes);
 }
 
-function testReplaceItem() {
+/* #export */ function testReplaceItem() {
   var m = new cr.ui.ArrayDataModel([1, 2, 3]);
   var permutation = null;
   var changeIndex;
@@ -97,3 +101,10 @@
   assertEquals(null, permutation);
   assertEquals(1, changeIndex);
 }
+
+window.testSlice = testSlice;
+window.testPush = testPush;
+window.testSplice = testSplice;
+window.testPermutation = testPermutation;
+window.testUpdateIndexes = testUpdateIndexes;
+window.testReplaceItem = testReplaceItem;
diff --git a/chrome/test/data/webui/js/cr/ui/command_test.html b/chrome/test/data/webui/js/cr/ui/command_test.html
index f199ceac..d0fac4c 100644
--- a/chrome/test/data/webui/js/cr/ui/command_test.html
+++ b/chrome/test/data/webui/js/cr/ui/command_test.html
@@ -4,7 +4,6 @@
 <title>cr.ui.Command test</title>
 </head>
 <body>
-<command shortcut="n|Ctrl"></command>
 <script src="chrome://resources/js/assert.js"></script>
 <script src="chrome://resources/js/cr.js"></script>
 <script src="chrome://resources/js/cr/ui.js"></script>
diff --git a/chrome/test/data/webui/js/cr/ui/command_test.js b/chrome/test/data/webui/js/cr/ui/command_test.js
index 5e52afa..22f02af 100644
--- a/chrome/test/data/webui/js/cr/ui/command_test.js
+++ b/chrome/test/data/webui/js/cr/ui/command_test.js
@@ -2,7 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-function testCommandDefaultPrevented() {
+// #import {Command} from 'chrome://resources/js/cr/ui/command.m.js';
+// #import {decorate} from 'chrome://resources/js/cr/ui.m.js';
+
+/* #export */ function setUp() {
+  const cmd = document.createElement('command');
+  cmd.setAttribute('shortcut', 'n|Ctrl');
+  document.body.appendChild(cmd);
+}
+
+/* #export */ function testCommandDefaultPrevented() {
   var calls = 0;
   document.addEventListener('canExecute', function(e) {
     ++calls;
@@ -28,7 +37,7 @@
   };
 }
 
-function testShortcuts() {
+/* #export */ function testShortcuts() {
   cr.ui.decorate('command', cr.ui.Command);
   const cmd = document.querySelector('command');
   // US keyboard - qwerty-N should work.
@@ -40,3 +49,7 @@
   // RU keyboard - qwerty-N (Cyrillic Te) should work.
   assertTrue(cmd.matchesEvent(createEvent('т', 'KeyN', 0x4e)));
 }
+
+window.setUp = setUp;
+window.testCommandDefaultPrevented = testCommandDefaultPrevented;
+window.testShortcuts = testShortcuts;
diff --git a/chrome/test/data/webui/js/cr/ui/context_menu_handler_test.js b/chrome/test/data/webui/js/cr/ui/context_menu_handler_test.js
index e6122a7..aa78e007 100644
--- a/chrome/test/data/webui/js/cr/ui/context_menu_handler_test.js
+++ b/chrome/test/data/webui/js/cr/ui/context_menu_handler_test.js
@@ -2,7 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-function testShowAndHideEvents() {
+// clang-format off
+// #import {contextMenuHandler} from 'chrome://resources/js/cr/ui/context_menu_handler.m.js';
+// #import {decorate} from 'chrome://resources/js/cr/ui.m.js';
+// #import {Menu} from 'chrome://resources/js/cr/ui/menu.m.js';
+// clang-format on
+
+/* #export */ function testShowAndHideEvents() {
   // Keep original Date.now not to affect other code.
   var originalDateNow = Date.now;
 
@@ -64,3 +70,5 @@
 
   Date.now = originalDateNow;
 }
+
+window.testShowAndHideEvents = testShowAndHideEvents;
diff --git a/chrome/test/data/webui/js/cr/ui/list_test.js b/chrome/test/data/webui/js/cr/ui/list_test.js
index 7f0dec9..f941e2e 100644
--- a/chrome/test/data/webui/js/cr/ui/list_test.js
+++ b/chrome/test/data/webui/js/cr/ui/list_test.js
@@ -2,7 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-function testClearPinnedItem() {
+// clang-format off
+// #import {List} from 'chrome://resources/js/cr/ui/list.m.js';
+// #import {ArrayDataModel} from 'chrome://resources/js/cr/ui/array_data_model.m.js';
+// clang-format on
+
+/* #export */ function testClearPinnedItem() {
   var list = document.createElement('ul');
   list.style.position = 'absolute';
   list.style.width = '800px';
@@ -24,7 +29,7 @@
   assertEquals('Item B', list.querySelectorAll('li')[0].textContent);
 }
 
-function testClickOutsideListItem() {
+/* #export */ function testClickOutsideListItem() {
   const list = document.createElement('ul');
   list.style.position = 'absolute';
   list.style.width = '800px';
@@ -57,3 +62,6 @@
   assertEquals(item, list.getListItemAncestor(item));
   assertEquals(item, list.getListItemAncestor(span));
 }
+
+window.testClearPinnedItem = testClearPinnedItem;
+window.testClickOutsideListItem = testClickOutsideListItem;
diff --git a/chrome/test/data/webui/new_tab_page/modules/recipe_tasks/module_test.js b/chrome/test/data/webui/new_tab_page/modules/recipe_tasks/module_test.js
new file mode 100644
index 0000000..0df140b
--- /dev/null
+++ b/chrome/test/data/webui/new_tab_page/modules/recipe_tasks/module_test.js
@@ -0,0 +1,197 @@
+// 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.
+
+import {recipeTasksDescriptor, RecipeTasksHandlerProxy} from 'chrome://new-tab-page/new_tab_page.js';
+import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.m.js';
+import {eventToPromise} from 'chrome://test/test_util.m.js';
+
+suite('NewTabPageModulesRecipeTasksModuleTest', () => {
+  /**
+   * @implements {RecipeTasksHandlerProxy}
+   * @extends {TestBrowserProxy}
+   */
+  let testProxy;
+
+  setup(() => {
+    PolymerTest.clearBody();
+
+    testProxy = TestBrowserProxy.fromClass(RecipeTasksHandlerProxy);
+    testProxy.handler =
+        TestBrowserProxy.fromClass(recipeTasks.mojom.RecipeTasksHandlerRemote);
+    RecipeTasksHandlerProxy.instance_ = testProxy;
+  });
+
+  test('creates no module if no task', async () => {
+    // Arrange.
+    testProxy.handler.setResultFor(
+        'getPrimaryRecipeTask', Promise.resolve({recipeTask: null}));
+
+    // Act.
+    await recipeTasksDescriptor.initialize();
+
+    // Assert.
+    assertEquals(1, testProxy.handler.getCallCount('getPrimaryRecipeTask'));
+    assertEquals(null, recipeTasksDescriptor.element);
+  });
+
+  test('creates module if task', async () => {
+    // Arrange.
+    const recipeTask = {
+      title: 'Hello world',
+      recipes: [
+        {
+          name: 'foo',
+          imageUrl: {url: 'https://foo.com/img.png'},
+          info: 'foo info',
+          targetUrl: {url: 'https://foo.com'},
+        },
+        {
+          name: 'bar',
+          imageUrl: {url: 'https://bar.com/img.png'},
+          info: 'bar info',
+          targetUrl: {url: 'https://bar.com'},
+        },
+      ],
+      relatedSearches: [
+        {
+          text: 'baz',
+          targetUrl: {url: 'https://baz.com'},
+        },
+        {
+          text: 'blub',
+          targetUrl: {url: 'https://blub.com'},
+        },
+      ],
+    };
+    testProxy.handler.setResultFor(
+        'getPrimaryRecipeTask', Promise.resolve({recipeTask}));
+
+    // Act.
+    await recipeTasksDescriptor.initialize();
+    const module = recipeTasksDescriptor.element;
+    document.body.append(module);
+    module.$.recipesRepeat.render();
+    module.$.relatedSearchesRepeat.render();
+
+    // Assert.
+    const recipes = Array.from(module.shadowRoot.querySelectorAll('.recipe'));
+    const pills = Array.from(module.shadowRoot.querySelectorAll('.pill'));
+    assertEquals(1, testProxy.handler.getCallCount('getPrimaryRecipeTask'));
+    assertEquals(2, recipes.length);
+    assertEquals(2, pills.length);
+    assertEquals('https://foo.com/', recipes[0].href);
+    assertEquals(
+        'https://foo.com/img.png', recipes[0].querySelector('img').autoSrc);
+    assertEquals('foo', recipes[0].querySelector('.name').innerText);
+    assertEquals('foo', recipes[0].querySelector('.name').title);
+    assertEquals('foo info', recipes[0].querySelector('.info').innerText);
+    assertEquals('https://bar.com/', recipes[1].href);
+    assertEquals(
+        'https://bar.com/img.png', recipes[1].querySelector('img').autoSrc);
+    assertEquals('bar', recipes[1].querySelector('.name').innerText);
+    assertEquals('bar', recipes[1].querySelector('.name').title);
+    assertEquals('bar info', recipes[1].querySelector('.info').innerText);
+    assertEquals('https://baz.com/', pills[0].href);
+    assertEquals('baz', pills[0].querySelector('.search-text').innerText);
+    assertEquals('https://blub.com/', pills[1].href);
+    assertEquals('blub', pills[1].querySelector('.search-text').innerText);
+  });
+
+  test('recipes and pills are hidden when cutoff', async () => {
+    const repeat = (n, fn) => Array(n).fill(0).map(fn);
+    testProxy.handler.setResultFor('getPrimaryRecipeTask', Promise.resolve({
+      recipeTask: {
+        title: 'Hello world',
+        recipes: repeat(20, () => ({
+                              name: 'foo',
+                              imageUrl: {url: 'https://foo.com/img.png'},
+                              info: 'foo info',
+                              targetUrl: {url: 'https://foo.com'},
+                            })),
+        relatedSearches: repeat(20, () => ({
+                                      text: 'baz',
+                                      targetUrl: {url: 'https://baz.com'},
+                                    })),
+      }
+    }));
+    await recipeTasksDescriptor.initialize();
+    const moduleElement = recipeTasksDescriptor.element;
+    document.body.append(moduleElement);
+    moduleElement.$.recipesRepeat.render();
+    moduleElement.$.relatedSearchesRepeat.render();
+    const getElements = () =>
+        Array.from(moduleElement.shadowRoot.querySelectorAll('.recipe, .pill'));
+    assertEquals(40, getElements().length);
+    const hiddenCount = () =>
+        getElements().filter(el => el.style.visibility === 'hidden').length;
+    const checkHidden = async (width, count) => {
+      const waitForVisibilityUpdate =
+          eventToPromise('visibility-update', moduleElement);
+      moduleElement.style.width = width;
+      await waitForVisibilityUpdate;
+      assertEquals(count, hiddenCount());
+    };
+    await checkHidden('500px', 31);
+    await checkHidden('300px', 35);
+    await checkHidden('700px', 26);
+    await checkHidden('500px', 31);
+  });
+
+  test('Backend is notified when module is dismissed or restored', async () => {
+    // Arrange.
+    const recipeTask = {
+      title: 'Continue searching for Hello world',
+      name: 'Hello world',
+      recipes: [
+        {
+          name: 'foo',
+          imageUrl: {url: 'https://foo.com/img.png'},
+          info: 'foo info',
+          targetUrl: {url: 'https://foo.com'},
+        },
+        {
+          name: 'bar',
+          imageUrl: {url: 'https://bar.com/img.png'},
+          info: 'bar info',
+          targetUrl: {url: 'https://bar.com'},
+        },
+      ],
+      relatedSearches: [
+        {
+          text: 'baz',
+          targetUrl: {url: 'https://baz.com'},
+        },
+        {
+          text: 'blub',
+          targetUrl: {url: 'https://blub.com'},
+        },
+      ],
+    };
+    testProxy.handler.setResultFor(
+        'getPrimaryRecipeTask', Promise.resolve({recipeTask}));
+
+
+    // Act.
+    await recipeTasksDescriptor.initialize();
+
+    // Assert.
+    assertEquals('function', typeof recipeTasksDescriptor.actions.dismiss);
+    assertEquals('function', typeof recipeTasksDescriptor.actions.restore);
+
+    // Act.
+    const toastMessage = recipeTasksDescriptor.actions.dismiss();
+
+    // Assert.
+    assertEquals('Removed Hello world', toastMessage);
+    assertEquals(
+        'Hello world', await testProxy.handler.whenCalled('dismissRecipeTask'));
+
+    // Act.
+    recipeTasksDescriptor.actions.restore();
+
+    // Assert.
+    assertEquals(
+        'Hello world', await testProxy.handler.whenCalled('restoreRecipeTask'));
+  });
+});
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 6748e19..57bc79a 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
@@ -245,6 +245,19 @@
 });
 
 // eslint-disable-next-line no-var
+var NewTabPageModulesRecipeTasksModuleTest =
+    class extends NewTabPageBrowserTest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://new-tab-page/test_loader.html?module=new_tab_page/modules/recipe_tasks/module_test.js';
+  }
+};
+
+TEST_F('NewTabPageModulesRecipeTasksModuleTest', 'All', function() {
+  mocha.run();
+});
+
+// eslint-disable-next-line no-var
 var NewTabPageModulesShoppingTasksModuleTest =
     class extends NewTabPageBrowserTest {
   /** @override */
diff --git a/chrome/test/data/webui/usb_internals_test.js b/chrome/test/data/webui/usb_internals_test.js
index e5ddcd67..85b3fa2b 100644
--- a/chrome/test/data/webui/usb_internals_test.js
+++ b/chrome/test/data/webui/usb_internals_test.js
@@ -252,7 +252,11 @@
 
 
 suite('UsbInternalsUITest', function() {
+  let app = null;
+
   suiteSetup(function() {
+    app = document.querySelector('usb-internals-app');
+
     // Before tests are run, make sure setup completes.
     return setupResolver.promise.then(function() {
       return Promise.all([
@@ -270,17 +274,17 @@
     const EXPECT_DEVICES_NUM = 2;
 
     // Totally 2 tables: 'TestDevice' table and 'Device' table.
-    const tables = document.querySelectorAll('table');
+    const tables = app.shadowRoot.querySelectorAll('table');
     expectEquals(2, tables.length);
 
     // Only 2 tabs after loading page.
-    const tabs = document.querySelectorAll('tab');
+    const tabs = app.shadowRoot.querySelectorAll('tab');
     expectEquals(2, tabs.length);
-    const tabPanels = document.querySelectorAll('tabpanel');
+    const tabPanels = app.shadowRoot.querySelectorAll('tabpanel');
     expectEquals(2, tabPanels.length);
 
     // The second is the devices table, which has 8 columns.
-    const devicesTable = document.querySelectorAll('table')[1];
+    const devicesTable = app.shadowRoot.querySelectorAll('table')[1];
     const columns = devicesTable.querySelector('thead')
                         .querySelector('tr')
                         .querySelectorAll('th');
@@ -292,29 +296,29 @@
   });
 
   test('DeviceTabAdded', function() {
-    const devicesTable = document.querySelector('#device-list');
+    const devicesTable = app.$('#device-list');
     // Click the inspect button to open information about the first device.
     // The device info is opened as a third tab panel.
     devicesTable.querySelectorAll('button')[0].click();
-    assertEquals(3, document.querySelectorAll('tab').length);
-    assertEquals(3, document.querySelectorAll('tabpanel').length);
-    expectTrue(document.querySelectorAll('tabpanel')[2].selected);
+    assertEquals(3, app.shadowRoot.querySelectorAll('tab').length);
+    assertEquals(3, app.shadowRoot.querySelectorAll('tabpanel').length);
+    expectTrue(app.shadowRoot.querySelectorAll('tabpanel')[2].selected);
 
     // Check that clicking the inspect button for another device will open a
     // new tabpanel.
     devicesTable.querySelectorAll('button')[1].click();
-    assertEquals(4, document.querySelectorAll('tab').length);
-    assertEquals(4, document.querySelectorAll('tabpanel').length);
-    expectTrue(document.querySelectorAll('tabpanel')[3].selected);
-    expectFalse(document.querySelectorAll('tabpanel')[2].selected);
+    assertEquals(4, app.shadowRoot.querySelectorAll('tab').length);
+    assertEquals(4, app.shadowRoot.querySelectorAll('tabpanel').length);
+    expectTrue(app.shadowRoot.querySelectorAll('tabpanel')[3].selected);
+    expectFalse(app.shadowRoot.querySelectorAll('tabpanel')[2].selected);
 
     // Check that clicking the inspect button for the same device a second
     // time will open the same tabpanel.
     devicesTable.querySelectorAll('button')[0].click();
-    assertEquals(4, document.querySelectorAll('tab').length);
-    assertEquals(4, document.querySelectorAll('tabpanel').length);
-    expectTrue(document.querySelectorAll('tabpanel')[2].selected);
-    expectFalse(document.querySelectorAll('tabpanel')[3].selected);
+    assertEquals(4, app.shadowRoot.querySelectorAll('tab').length);
+    assertEquals(4, app.shadowRoot.querySelectorAll('tabpanel').length);
+    expectTrue(app.shadowRoot.querySelectorAll('tabpanel')[2].selected);
+    expectFalse(app.shadowRoot.querySelectorAll('tabpanel')[3].selected);
   });
 
   test('RenderDeviceInfoTree', function() {
@@ -322,7 +326,7 @@
     // showing WebUSB information. Check the tree displays correct data.
     // The tab panel of the first device is opened in previous test as the
     // third tab panel.
-    const deviceTab = document.querySelectorAll('tabpanel')[2];
+    const deviceTab = app.shadowRoot.querySelectorAll('tabpanel')[2];
     const tree = deviceTab.querySelector('tree');
     const treeItems = tree.querySelectorAll('.tree-item');
     assertEquals(11, treeItems.length);
@@ -347,7 +351,7 @@
     await deviceTabInitializedResolver.promise;
     // The tab panel of the first device is opened in previous test as the
     // third tab panel. This device has correct device descriptor.
-    const deviceTab = document.querySelectorAll('tabpanel')[2];
+    const deviceTab = app.shadowRoot.querySelectorAll('tabpanel')[2];
     deviceTab.querySelector('.device-descriptor-button').click();
 
     await deviceDescriptorRenderResolver.promise;
@@ -413,11 +417,11 @@
 
   test('RenderShortDeviceDescriptor', async function() {
     await deviceManagerGetDevicesResolver.promise;
-    const devicesTable = document.querySelector('#device-list');
+    const devicesTable = app.$('#device-list');
     // Inspect the second device, which has short device descriptor.
     devicesTable.querySelectorAll('button')[1].click();
     // The fourth is the device tab (a third tab was opened in a previous test).
-    const deviceTab = document.querySelectorAll('tabpanel')[3];
+    const deviceTab = app.shadowRoot.querySelectorAll('tabpanel')[3];
 
     await deviceTabInitializedResolver.promise;
     deviceDescriptorRenderResolver = new PromiseResolver();
diff --git a/chrome/test/data/webui/webui_resource_browsertest.cc b/chrome/test/data/webui/webui_resource_browsertest.cc
index 38049fa..5d1c1754 100644
--- a/chrome/test/data/webui/webui_resource_browsertest.cc
+++ b/chrome/test/data/webui/webui_resource_browsertest.cc
@@ -51,10 +51,20 @@
   LoadTestUrl("js/cr/ui/array_data_model_test.html");
 }
 
+#if defined(OS_CHROMEOS)
+IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, ArrayDataModelModuleTest) {
+  LoadTestUrl("?module=js/cr/ui/array_data_model_test.m.js");
+}
+#endif
+
 IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, CrTest) {
   LoadTestUrl("cr_test.html");
 }
 
+IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, CrModuleTest) {
+  LoadTestUrl("?module=cr_test.m.js");
+}
+
 IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, CrReloadTest) {
   LoadTestUrl("cr_reload_test.html");
 }
@@ -63,6 +73,10 @@
   LoadTestUrl("js/cr/event_target_test.html");
 }
 
+IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, EventTargetModuleTest) {
+  LoadTestUrl("?module=js/cr/event_target_test.m.js");
+}
+
 IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, I18nProcessCssTest) {
   LoadTestUrl("i18n_process_css_test.html");
 }
@@ -122,6 +136,10 @@
 }
 
 #if defined(OS_CHROMEOS)
+IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, ListModuleTest) {
+  LoadTestUrl("?module=js/cr/ui/list_test.m.js");
+}
+
 IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, GridTest) {
   LoadTestUrl("js/cr/ui/grid_test.html");
 }
@@ -159,10 +177,22 @@
   LoadTestUrl("js/cr/ui/command_test.html");
 }
 
+#if defined(OS_CHROMEOS)
+IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, CommandModuleTest) {
+  LoadTestUrl("?module=js/cr/ui/command_test.m.js");
+}
+#endif
+
 IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, ContextMenuHandlerTest) {
   LoadTestUrl("js/cr/ui/context_menu_handler_test.html");
 }
 
+#if defined(OS_CHROMEOS)
+IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, ContextMenuHandlerModuleTest) {
+  LoadTestUrl("?module=js/cr/ui/context_menu_handler_test.m.js");
+}
+#endif
+
 IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, MenuButtonTest) {
   LoadTestUrl("js/cr/ui/menu_button_test.html");
 }
diff --git a/chrome/updater/app/app_install.cc b/chrome/updater/app/app_install.cc
index c8711f5..04fb05d8 100644
--- a/chrome/updater/app/app_install.cc
+++ b/chrome/updater/app/app_install.cc
@@ -91,6 +91,21 @@
   splash_screen_ = splash_screen_maker_.Run();
   splash_screen_->Show();
 
+  // Capture `update_service` to manage the object lifetime.
+  scoped_refptr<UpdateService> update_service = CreateUpdateService();
+  update_service->GetVersion(
+      base::BindOnce(&AppInstall::GetVersionDone, this, update_service));
+}
+
+void AppInstall::GetVersionDone(scoped_refptr<UpdateService>,
+                                const base::Version& version) {
+  VLOG_IF(1, (version.IsValid()))
+      << "Found active version: " << version.GetString();
+  if (version.IsValid() && version >= base::Version(UPDATER_VERSION_STRING)) {
+    splash_screen_->Dismiss(base::BindOnce(&AppInstall::MaybeInstallApp, this));
+    return;
+  }
+
   InstallCandidate(
       false,
       base::BindOnce(
diff --git a/chrome/updater/app/app_install.h b/chrome/updater/app/app_install.h
index 05584d33..b10fe7f2 100644
--- a/chrome/updater/app/app_install.h
+++ b/chrome/updater/app/app_install.h
@@ -16,11 +16,13 @@
 
 namespace base {
 class TaskRunner;
+class Version;
 }
 
 namespace updater {
 
 struct RegistrationResponse;
+class UpdateService;
 
 // This class defines an interface for installing an application. The interface
 // is intended to be implemented for scenerios where UI and RPC calls to
@@ -54,6 +56,10 @@
   void Initialize() override;
   void FirstTaskRun() override;
 
+  // Called after the version of the active updater has been retrieved.
+  void GetVersionDone(scoped_refptr<UpdateService>,
+                      const base::Version& version);
+
   void InstallCandidateDone(int result);
 
   void WakeCandidate();
diff --git a/chrome/updater/win/update_service_out_of_process.cc b/chrome/updater/win/update_service_out_of_process.cc
index 15dd0bfe..a1c03833 100644
--- a/chrome/updater/win/update_service_out_of_process.cc
+++ b/chrome/updater/win/update_service_out_of_process.cc
@@ -292,7 +292,6 @@
               [](scoped_refptr<base::SequencedTaskRunner> taskrunner,
                  base::OnceCallback<void(const base::Version&)> callback,
                  const base::Version& version) {
-                DCHECK(version.IsValid());
                 taskrunner->PostTask(
                     FROM_HERE, base::BindOnce(std::move(callback), version));
               },
diff --git a/chromecast/browser/extensions/api/tabs/tabs_api.cc b/chromecast/browser/extensions/api/tabs/tabs_api.cc
index 68c51ed9..9dd1d1c 100644
--- a/chromecast/browser/extensions/api/tabs/tabs_api.cc
+++ b/chromecast/browser/extensions/api/tabs/tabs_api.cc
@@ -84,8 +84,8 @@
   ~ApiParameterExtractor() {}
 
   bool populate_tabs() {
-    if (params_->get_info.get() && params_->get_info->populate.get())
-      return *params_->get_info->populate;
+    if (params_->query_options.get() && params_->query_options->populate.get())
+      return *params_->query_options->populate;
     return false;
   }
 
diff --git a/chromecast/browser/webview/cast_app_rpc_instance.cc b/chromecast/browser/webview/cast_app_rpc_instance.cc
index 2c0b7f6..27b4392 100644
--- a/chromecast/browser/webview/cast_app_rpc_instance.cc
+++ b/chromecast/browser/webview/cast_app_rpc_instance.cc
@@ -21,7 +21,7 @@
     grpc::ServerCompletionQueue* cq,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     WebviewWindowManager* window_manager,
-    WebContentsProvider* web_contents_provider)
+    base::WeakPtr<WebContentsProvider> web_contents_provider)
     : PlatformViewsRpcInstance(cq, task_runner, window_manager),
       service_(service),
       web_contents_provider_(web_contents_provider) {
@@ -51,8 +51,12 @@
 
 void CastAppRpcInstance::CreateCastAppWindowLink(int platform_view_id,
                                                  int app_window_id) {
-  app_id_ = platform_view_id;
+  if (!web_contents_provider_) {
+    OnError("web_contents_provider_ is null");
+    return;
+  }
 
+  app_id_ = platform_view_id;
   content::WebContents* web_contents =
       web_contents_provider_->GetWebContents(app_window_id);
   if (!web_contents) {
diff --git a/chromecast/browser/webview/cast_app_rpc_instance.h b/chromecast/browser/webview/cast_app_rpc_instance.h
index 0530111..af78e42 100644
--- a/chromecast/browser/webview/cast_app_rpc_instance.h
+++ b/chromecast/browser/webview/cast_app_rpc_instance.h
@@ -7,6 +7,7 @@
 
 #include "chromecast/browser/webview/platform_views_rpc_instance.h"
 
+#include "base/memory/weak_ptr.h"
 #include "content/public/browser/web_contents_observer.h"
 
 namespace chromecast {
@@ -19,7 +20,7 @@
                      grpc::ServerCompletionQueue* cq,
                      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
                      WebviewWindowManager* window_manager,
-                     WebContentsProvider* web_contents_provider);
+                     base::WeakPtr<WebContentsProvider> web_contents_provider);
   ~CastAppRpcInstance() override;
 
  protected:
@@ -30,7 +31,7 @@
   void CreateCastAppWindowLink(int platform_view_id, int app_window_id);
   void WebContentsDestroyed() override;
   webview::PlatformViewsService::AsyncService* service_;
-  WebContentsProvider* web_contents_provider_;
+  base::WeakPtr<WebContentsProvider> web_contents_provider_;
 
   DISALLOW_COPY_AND_ASSIGN(CastAppRpcInstance);
 };
diff --git a/chromecast/browser/webview/platform_views_grpc_service.cc b/chromecast/browser/webview/platform_views_grpc_service.cc
index cc9fd685..9f9d04a 100644
--- a/chromecast/browser/webview/platform_views_grpc_service.cc
+++ b/chromecast/browser/webview/platform_views_grpc_service.cc
@@ -18,7 +18,7 @@
     std::unique_ptr<webview::PlatformViewsService::AsyncService> service,
     std::unique_ptr<grpc::ServerCompletionQueue> cq,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-    WebContentsProvider* web_contents_provider,
+    base::WeakPtr<WebContentsProvider> web_contents_provider,
     bool enabled_for_dev)
     : ui_task_runner_(std::move(ui_task_runner)),
       cq_(std::move(cq)),
diff --git a/chromecast/browser/webview/platform_views_grpc_service.h b/chromecast/browser/webview/platform_views_grpc_service.h
index df08589..da822d0 100644
--- a/chromecast/browser/webview/platform_views_grpc_service.h
+++ b/chromecast/browser/webview/platform_views_grpc_service.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/files/file_path.h"
+#include "base/memory/weak_ptr.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chromecast/browser/webview/proto/webview.grpc.pb.h"
@@ -26,7 +27,7 @@
       std::unique_ptr<webview::PlatformViewsService::AsyncService> service,
       std::unique_ptr<grpc::ServerCompletionQueue> cq,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-      WebContentsProvider* web_contents_provider,
+      base::WeakPtr<WebContentsProvider> web_contents_provider,
       bool enabled_for_dev);
   ~PlatformViewsAsyncService() override;
 
@@ -44,7 +45,7 @@
   std::unique_ptr<webview::PlatformViewsService::AsyncService> service_;
 
   WebviewWindowManager window_manager_;
-  WebContentsProvider* web_contents_provider_;
+  base::WeakPtr<WebContentsProvider> web_contents_provider_;
   bool enabled_for_dev_;
 
   DISALLOW_COPY_AND_ASSIGN(PlatformViewsAsyncService);
diff --git a/chromecast/browser/webview/web_content_controller.cc b/chromecast/browser/webview/web_content_controller.cc
index 0f97c377..1b61d3a5 100644
--- a/chromecast/browser/webview/web_content_controller.cc
+++ b/chromecast/browser/webview/web_content_controller.cc
@@ -31,6 +31,33 @@
 
 namespace chromecast {
 
+WebContentController::WebviewWindowVisibilityObserver::
+    WebviewWindowVisibilityObserver(aura::Window* window,
+                                    WebContentController* controller)
+    : window_(window), controller_(controller) {
+  DCHECK(window_);
+  DCHECK(controller_);
+  window_->AddObserver(this);
+}
+
+void WebContentController::WebviewWindowVisibilityObserver::
+    OnWindowVisibilityChanged(aura::Window* window, bool visible) {
+  if (window == window_ && visible && window->CanFocus())
+    controller_->OnVisible(window);
+}
+
+void WebContentController::WebviewWindowVisibilityObserver::OnWindowDestroyed(
+    aura::Window* window) {
+  if (window == window_)
+    window_ = nullptr;
+}
+
+WebContentController::WebviewWindowVisibilityObserver::
+    ~WebviewWindowVisibilityObserver() {
+  if (window_)
+    window_->RemoveObserver(this);
+}
+
 WebContentController::WebContentController(Client* client) : client_(client) {
   js_channels_ = std::make_unique<WebContentJsChannels>(client_);
   JsClientInstance::AddObserver(this);
@@ -149,6 +176,11 @@
 }
 
 void WebContentController::AttachTo(aura::Window* window, int window_id) {
+  // Register our observer on the window so we can act later once it
+  // becomes visible.
+  window_visibility_observer_ =
+      std::make_unique<WebviewWindowVisibilityObserver>(window, this);
+
   content::WebContents* contents = GetWebContents();
   auto* contents_window = contents->GetNativeView();
   contents_window->set_id(window_id);
@@ -170,6 +202,11 @@
   HandleResize(contents_window->bounds().size());
 }
 
+void WebContentController::OnVisible(aura::Window* window) {
+  // Acquire initial focus.
+  GetWebContents()->SetInitialFocus();
+}
+
 void WebContentController::ProcessInputEvent(const webview::InputEvent& ev) {
   content::WebContents* contents = GetWebContents();
   DCHECK(contents);
diff --git a/chromecast/browser/webview/web_content_controller.h b/chromecast/browser/webview/web_content_controller.h
index 44f8cf9..c17dd687 100644
--- a/chromecast/browser/webview/web_content_controller.h
+++ b/chromecast/browser/webview/web_content_controller.h
@@ -63,6 +63,9 @@
   // Attach this web contents to an aura window as a child.
   void AttachTo(aura::Window* window, int window_id);
 
+  // Invoked when the aura window becomes visible and is fully initialized.
+  void OnVisible(aura::Window* window);
+
  protected:
   // content::WebContentsObserver
   void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
@@ -139,6 +142,30 @@
   std::set<content::RenderFrameHost*> current_render_frame_set_;
   std::set<content::RenderWidgetHost*> current_render_widget_set_;
 
+  // Observes the aura window and calls back to the controller for visibility
+  // events.
+  class WebviewWindowVisibilityObserver : public aura::WindowObserver {
+   public:
+    explicit WebviewWindowVisibilityObserver(aura::Window* window,
+                                             WebContentController* controller);
+    ~WebviewWindowVisibilityObserver() override;
+
+    WebviewWindowVisibilityObserver(const WebviewWindowVisibilityObserver&) =
+        delete;
+    WebviewWindowVisibilityObserver& operator=(
+        const WebviewWindowVisibilityObserver&) = delete;
+
+   private:
+    // aura::WindowObserver
+    void OnWindowVisibilityChanged(aura::Window* window, bool visible) override;
+    void OnWindowDestroyed(aura::Window* window) override;
+
+    aura::Window* window_;
+    WebContentController* controller_;
+  };
+
+  std::unique_ptr<WebviewWindowVisibilityObserver> window_visibility_observer_;
+
   base::WeakPtrFactory<WebContentController> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(WebContentController);
diff --git a/chromecast/common/extensions_api/history.json b/chromecast/common/extensions_api/history.json
index f7ef04a..1f660f63 100644
--- a/chromecast/common/extensions_api/history.json
+++ b/chromecast/common/extensions_api/history.json
@@ -40,6 +40,13 @@
             "description": "The <a href='#transition_types'>transition type</a> for this visit from its referrer."
           }
         }
+      },
+      {
+        "id": "UrlDetails",
+        "type": "object",
+        "properties": {
+          "url": {"type": "string", "description": "The URL for the operation. It must be in the format as returned from a call to history.search."}
+        }
       }
     ],
     "functions": [
@@ -74,10 +81,7 @@
         "parameters": [
           {
             "name": "details",
-            "type": "object",
-            "properties": {
-              "url": {"type": "string", "description": "The URL for which to retrieve visit information.  It must be in the format as returned from a call to history.search."}
-            }
+            "$ref": "UrlDetails"
           },
           {
             "name": "callback",
@@ -95,10 +99,7 @@
         "parameters": [
           {
             "name": "details",
-            "type": "object",
-            "properties": {
-              "url": {"type": "string", "description": "The URL to add."}
-            }
+            "$ref": "UrlDetails"
           },
           {
             "name": "callback",
@@ -115,10 +116,7 @@
         "parameters": [
           {
             "name": "details",
-            "type": "object",
-            "properties": {
-              "url": {"type": "string", "description": "The URL to remove."}
-            }
+            "$ref": "UrlDetails"
           },
           {
             "name": "callback",
diff --git a/chromecast/common/extensions_api/windows.json b/chromecast/common/extensions_api/windows.json
index e748ad0..e462400 100644
--- a/chromecast/common/extensions_api/windows.json
+++ b/chromecast/common/extensions_api/windows.json
@@ -92,6 +92,14 @@
         "type": "string",
         "description": "Specifies what type of browser window to create. 'panel' is deprecated and only available to existing whitelisted extensions on Chrome OS.",
         "enum": ["normal", "popup", "panel"]
+      },
+      {
+        "id": "QueryOptions",
+        "type": "object",
+        "properties": {
+          "populate": {"type": "boolean", "optional": true, "description": "If true, the $(ref:windows.Window) object has a <var>tabs</var> property that contains a list of the $(ref:tabs.Tab) objects. The <code>Tab</code> objects only contain the <code>url</code>, <code>pendingUrl</code>, <code>title</code>, and <code>favIconUrl</code> properties if the extension's manifest file includes the <code>\"tabs\"</code> permission." },
+          "windowTypes": {"type": "array", "items": { "$ref": "WindowType" }, "optional": true, "description": "If set, the $(ref:windows.Window) returned is filtered based on its type. If unset, the default filter is set to <code>['normal', 'popup']</code>."}
+        }
       }
     ],
     "properties": {
@@ -112,14 +120,9 @@
         "parameters": [
           {"type": "integer", "name": "windowId", "minimum": -2},
           {
-            "type": "object",
-            "name": "getInfo",
-            "optional": true,
-            "description": "",
-            "properties": {
-              "populate": {"type": "boolean", "optional": true, "description": "If true, the $(ref:windows.Window) object will have a <var>tabs</var> property that contains a list of the $(ref:tabs.Tab) objects. The <code>Tab</code> objects only contain the <code>url</code>, <code>title</code> and <code>favIconUrl</code> properties if the extension's manifest file includes the <code>\"tabs\"</code> permission." },
-              "windowTypes": {"type": "array", "items": { "$ref": "WindowType" }, "optional": true, "description": "If set, the $(ref:windows.Window) returned will be filtered based on its type. If unset the default filter is set to <code>['normal', 'popup']</code>."}
-            }
+            "name": "queryOptions",
+            "$ref": "QueryOptions",
+            "optional": true
           },
           {
             "type": "function",
@@ -138,14 +141,9 @@
         "description": "Gets the <a href='#current-window'>current window</a>.",
         "parameters": [
           {
-            "type": "object",
-            "name": "getInfo",
-            "optional": true,
-            "description": "",
-            "properties": {
-              "populate": {"type": "boolean", "optional": true, "description": "If true, the $(ref:windows.Window) object will have a <var>tabs</var> property that contains a list of the $(ref:tabs.Tab) objects. The <code>Tab</code> objects only contain the <code>url</code>, <code>title</code> and <code>favIconUrl</code> properties if the extension's manifest file includes the <code>\"tabs\"</code> permission." },
-              "windowTypes": {"type": "array", "items": { "$ref": "WindowType" }, "optional": true, "description": "If set, the $(ref:windows.Window) returned will be filtered based on its type. If unset the default filter is set to <code>['normal', 'popup']</code>."}
-            }
+            "name": "queryOptions",
+            "$ref": "QueryOptions",
+            "optional": true
           },
           {
             "type": "function",
@@ -164,14 +162,9 @@
         "description": "Gets the window that was most recently focused &mdash; typically the window 'on top'.",
         "parameters": [
           {
-            "type": "object",
-            "name": "getInfo",
-            "optional": true,
-            "description": "",
-            "properties": {
-              "populate": {"type": "boolean", "optional": true, "description": "If true, the $(ref:windows.Window) object will have a <var>tabs</var> property that contains a list of the $(ref:tabs.Tab) objects. The <code>Tab</code> objects only contain the <code>url</code>, <code>title</code> and <code>favIconUrl</code> properties if the extension's manifest file includes the <code>\"tabs\"</code> permission." },
-              "windowTypes": {"type": "array", "items": { "$ref": "WindowType" }, "optional": true, "description": "If set, the $(ref:windows.Window) returned will be filtered based on its type. If unset the default filter is set to <code>['normal', 'popup']</code>."}
-            }
+            "name": "queryOptions",
+            "$ref": "QueryOptions",
+            "optional": true
           },
           {
             "type": "function",
@@ -190,14 +183,9 @@
         "description": "Gets all windows.",
         "parameters": [
           {
-            "type": "object",
-            "name": "getInfo",
-            "optional": true,
-            "description": "",
-            "properties": {
-              "populate": {"type": "boolean", "optional": true, "description": "If true, each $(ref:windows.Window) object will have a <var>tabs</var> property that contains a list of the $(ref:tabs.Tab) objects for that window. The <code>Tab</code> objects only contain the <code>url</code>, <code>title</code> and <code>favIconUrl</code> properties if the extension's manifest file includes the <code>\"tabs\"</code> permission." },
-              "windowTypes": {"type": "array", "items": { "$ref": "WindowType" }, "optional": true, "description": "If set, the $(ref:windows.Window) returned will be filtered based on its type. If unset the default filter is set to <code>['normal', 'popup']</code>."}
-            }
+            "name": "queryOptions",
+            "$ref": "QueryOptions",
+            "optional": true
           },
           {
             "type": "function",
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn
index 349a141..59cad0d 100644
--- a/chromeos/BUILD.gn
+++ b/chromeos/BUILD.gn
@@ -285,7 +285,7 @@
     tast_disabled_tests = [
       # crbug.com/1115622
       "ui.ChromeLoginGAIA",
-      "inputs.VirtualKeyboardOOBE",
+      "inputs.VirtualKeyboardOOBE.stable",
 
       # crbug.com/1097630
       "security.OpenFDs",
diff --git a/chromeos/audio/cras_audio_handler.cc b/chromeos/audio/cras_audio_handler.cc
index 9be1d19..09f640a 100644
--- a/chromeos/audio/cras_audio_handler.cc
+++ b/chromeos/audio/cras_audio_handler.cc
@@ -15,7 +15,6 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
-#include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
@@ -999,8 +998,6 @@
   GetNumberOfOutputStreams();
   CrasAudioClient::Get()->SetFixA2dpPacketSize(base::FeatureList::IsEnabled(
       chromeos::features::kBluetoothFixA2dpPacketSize));
-  CrasAudioClient::Get()->SetNextHandsfreeProfile(base::FeatureList::IsEnabled(
-      chromeos::features::kBluetoothNextHandsfreeProfile));
 }
 
 void CrasAudioHandler::ApplyAudioPolicy() {
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd
index d56d66e..ecbeaffe 100644
--- a/chromeos/chromeos_strings.grd
+++ b/chromeos/chromeos_strings.grd
@@ -168,7 +168,7 @@
 
       <!-- Managed user session warning -->
       <message name="IDS_ASH_LOGIN_MANAGED_SESSION_MONITORING_USER_WARNING" desc="Text shown in the user pod in case the user is managed.">
-        <ph name="ENROLLMENT_DOMAIN">$1<ex>example.com</ex></ph> manages this user. It may remotely manage settings and monitor user activity.
+        <ph name="ENROLLMENT_DOMAIN">$1<ex>example.com</ex></ph> manages this user and may remotely manage settings and monitor user activity.
       </message>
 
       <!-- Pop-up enterprise management. -->
@@ -322,7 +322,9 @@
         <ph name="ATTEMPTS_LEFT">$1<ex>3</ex></ph> attempts left
       </message>
       <message name="IDS_REQUEST_PIN_DIALOG_ERROR_ATTEMPTS" desc="The text displayed in the certificate provider PIN request dialog when the previous login attempt was unsuccessful but there are more attempts remaining. Includes the reason for the previous failure.">
-        <ph name="ERROR_MESSAGE">$1<ex>Invalid PIN.</ex></ph> <ph name="ATTEMPTS_LEFT">$2<ex>3</ex></ph> attempts left
+        {ATTEMPTS_LEFT, plural,
+          =1 {<ph name="ERROR_MESSAGE">{1}<ex>Invalid PIN.</ex></ph> {0} attempt left}
+          other {<ph name="ERROR_MESSAGE">{1}<ex>Invalid PIN.</ex></ph> {0} attempts left}}
       </message>
 
       <!-- Print Management App -->
diff --git a/chromeos/chromeos_strings_grd/IDS_ASH_LOGIN_MANAGED_SESSION_MONITORING_USER_WARNING.png.sha1 b/chromeos/chromeos_strings_grd/IDS_ASH_LOGIN_MANAGED_SESSION_MONITORING_USER_WARNING.png.sha1
index 48d5ce4..1a93b1c 100644
--- a/chromeos/chromeos_strings_grd/IDS_ASH_LOGIN_MANAGED_SESSION_MONITORING_USER_WARNING.png.sha1
+++ b/chromeos/chromeos_strings_grd/IDS_ASH_LOGIN_MANAGED_SESSION_MONITORING_USER_WARNING.png.sha1
@@ -1 +1 @@
-abbc52d3b2dc1af788daab188bf24b924412ea27
\ No newline at end of file
+d7a2f899b0e414b7dbd10dca29673608bba076aa
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_REQUEST_PIN_DIALOG_ERROR_ATTEMPTS.png.sha1 b/chromeos/chromeos_strings_grd/IDS_REQUEST_PIN_DIALOG_ERROR_ATTEMPTS.png.sha1
new file mode 100644
index 0000000..a9d5735
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_REQUEST_PIN_DIALOG_ERROR_ATTEMPTS.png.sha1
@@ -0,0 +1 @@
+bff3e9c779eeec926cb2a4e6483f615b8b797900
\ No newline at end of file
diff --git a/chromeos/components/bloom/BUILD.gn b/chromeos/components/bloom/BUILD.gn
index 2bed35c..e74fb1c1a 100644
--- a/chromeos/components/bloom/BUILD.gn
+++ b/chromeos/components/bloom/BUILD.gn
@@ -8,6 +8,8 @@
     "bloom_controller_impl.h",
     "bloom_interaction.cc",
     "bloom_interaction.h",
+    "bloom_result_builder.cc",
+    "bloom_result_builder.h",
     "server/bloom_server_proxy.h",
     "server/bloom_server_proxy_impl.cc",
     "server/bloom_server_proxy_impl.h",
@@ -23,6 +25,7 @@
     "//chromeos/components/bloom/public/cpp:future",
     "//chromeos/services/assistant/public/shared",
     "//components/signin/public/identity_manager",
+    "//services/data_decoder/public/cpp",
     "//services/network/public/cpp",
     "//ui/gfx",
   ]
@@ -33,6 +36,7 @@
 
   sources = [
     "bloom_controller_impl_unittest.cc",
+    "bloom_result_builder_unittest.cc",
     "server/bloom_server_proxy_impl_unittest.cc",
   ]
 
@@ -44,6 +48,7 @@
     "//chromeos/services/assistant/public/shared",
     "//components/signin/public/identity_manager",
     "//components/signin/public/identity_manager:test_support",
+    "//services/data_decoder/public/cpp:test_support",
     "//services/network:test_support",
     "//services/network/public/cpp",
     "//testing/gmock",
diff --git a/chromeos/components/bloom/DEPS b/chromeos/components/bloom/DEPS
index a93f07b..39c67035 100644
--- a/chromeos/components/bloom/DEPS
+++ b/chromeos/components/bloom/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+ash/public",
   "+components/signin/public/identity_manager",
+  "+services/data_decoder/public/cpp",
   "+services/network/public",
   "+ui/gfx",
 ]
diff --git a/chromeos/components/bloom/bloom_controller_impl.cc b/chromeos/components/bloom/bloom_controller_impl.cc
index bbfafcdb..77129b0 100644
--- a/chromeos/components/bloom/bloom_controller_impl.cc
+++ b/chromeos/components/bloom/bloom_controller_impl.cc
@@ -6,6 +6,7 @@
 
 #include "base/logging.h"
 #include "chromeos/components/bloom/bloom_interaction.h"
+#include "chromeos/components/bloom/public/cpp/bloom_result.h"
 #include "chromeos/components/bloom/public/cpp/bloom_screenshot_delegate.h"
 #include "chromeos/components/bloom/public/cpp/bloom_ui_delegate.h"
 #include "chromeos/components/bloom/server/bloom_server_proxy.h"
@@ -59,7 +60,7 @@
   ui_delegate_->OnShowUI();
 }
 
-void BloomControllerImpl::ShowResult(const std::string& result) {
+void BloomControllerImpl::ShowResult(const BloomResult& result) {
   ui_delegate_->OnShowResult(result);
 }
 
diff --git a/chromeos/components/bloom/bloom_controller_impl.h b/chromeos/components/bloom/bloom_controller_impl.h
index 2163e82..55f1e354 100644
--- a/chromeos/components/bloom/bloom_controller_impl.h
+++ b/chromeos/components/bloom/bloom_controller_impl.h
@@ -20,6 +20,7 @@
 class BloomScreenshotDelegate;
 class BloomServerProxy;
 class BloomUiDelegate;
+struct BloomResult;
 
 class BloomControllerImpl : public BloomController {
  public:
@@ -35,7 +36,7 @@
   void StopInteraction(BloomInteractionResolution resolution) override;
 
   void ShowUI();
-  void ShowResult(const std::string& result);
+  void ShowResult(const BloomResult& result);
 
   void SetScreenshotDelegate(
       std::unique_ptr<BloomScreenshotDelegate> delegate);
diff --git a/chromeos/components/bloom/bloom_controller_impl_unittest.cc b/chromeos/components/bloom/bloom_controller_impl_unittest.cc
index d5d0e62..3b787a2e 100644
--- a/chromeos/components/bloom/bloom_controller_impl_unittest.cc
+++ b/chromeos/components/bloom/bloom_controller_impl_unittest.cc
@@ -5,6 +5,7 @@
 #include "chromeos/components/bloom/bloom_controller_impl.h"
 #include "base/test/task_environment.h"
 #include "chromeos/components/bloom/public/cpp/bloom_interaction_resolution.h"
+#include "chromeos/components/bloom/public/cpp/bloom_result.h"
 #include "chromeos/components/bloom/public/cpp/bloom_screenshot_delegate.h"
 #include "chromeos/components/bloom/public/cpp/bloom_ui_delegate.h"
 #include "chromeos/components/bloom/server/bloom_server_proxy.h"
@@ -24,12 +25,20 @@
 
 using ::testing::_;
 using ::testing::AnyNumber;
+using ::testing::Invoke;
 using ::testing::NiceMock;
+using ::testing::WithArgs;
 
 const char kEmail[] = "test@gmail.com";
 
 #define EXPECT_NO_CALLS(args...) EXPECT_CALL(args).Times(0)
 
+BloomResult ResultWithQuery(const std::string& query) {
+  BloomResult result;
+  result.query = query;
+  return result;
+}
+
 class ScreenshotDelegateMock : public BloomScreenshotDelegate {
  public:
   ScreenshotDelegateMock() {
@@ -63,7 +72,7 @@
  public:
   MOCK_METHOD(void, OnInteractionStarted, ());
   MOCK_METHOD(void, OnShowUI, ());
-  MOCK_METHOD(void, OnShowResult, (const std::string& html));
+  MOCK_METHOD(void, OnShowResult, (const BloomResult& result));
   MOCK_METHOD(void,
               OnInteractionFinished,
               (BloomInteractionResolution resolution));
@@ -80,7 +89,7 @@
 
   void OnShowUI() override { EXPECT_TRUE(has_interaction_); }
 
-  void OnShowResult(const std::string& html) override {
+  void OnShowResult(const BloomResult& html) override {
     EXPECT_TRUE(has_interaction_);
   }
 
@@ -118,11 +127,11 @@
                const gfx::Image& screenshot,
                Callback callback));
 
-  void SendResponse(base::Optional<std::string> html = std::string("<html/>")) {
+  void SendResponse(base::Optional<BloomResult> result = BloomResult()) {
     EXPECT_TRUE(callback_) << "AnalyzeProblem() was never called.";
 
     if (callback_)
-      std::move(callback_).Run(html);
+      std::move(callback_).Run(std::move(result));
   }
 
   void SendResponseFailure() { SendResponse(base::nullopt); }
@@ -343,9 +352,12 @@
   auto* delegate = AddUiDelegateMock();
   StartInteractionAndSendAccessTokenAndScreenshot();
 
-  EXPECT_CALL(*delegate, OnShowResult("<html>response</html>"));
+  EXPECT_CALL(*delegate, OnShowResult)
+      .WillOnce(WithArgs<0>(Invoke([](const BloomResult& result) {
+        EXPECT_EQ("The expected result", result.query);
+      })));
 
-  bloom_server().SendResponse("<html>response</html>");
+  bloom_server().SendResponse(ResultWithQuery("The expected result"));
 }
 
 }  // namespace bloom
diff --git a/chromeos/components/bloom/bloom_interaction.cc b/chromeos/components/bloom/bloom_interaction.cc
index e8912b6..482ef237 100644
--- a/chromeos/components/bloom/bloom_interaction.cc
+++ b/chromeos/components/bloom/bloom_interaction.cc
@@ -8,6 +8,7 @@
 #include "base/memory/weak_ptr.h"
 #include "chromeos/components/bloom/bloom_controller_impl.h"
 #include "chromeos/components/bloom/bloom_interaction.h"
+#include "chromeos/components/bloom/public/cpp/bloom_result.h"
 #include "chromeos/components/bloom/public/cpp/bloom_screenshot_delegate.h"
 #include "chromeos/components/bloom/public/cpp/future_value.h"
 #include "chromeos/components/bloom/server/bloom_server_proxy.h"
@@ -46,14 +47,14 @@
       Bind(&BloomInteraction::OnServerResponse));
 }
 
-void BloomInteraction::OnServerResponse(base::Optional<std::string> html) {
-  if (!html) {
+void BloomInteraction::OnServerResponse(base::Optional<BloomResult> result) {
+  if (!result) {
     controller_->StopInteraction(BloomInteractionResolution ::kServerError);
     return;
   }
 
   DVLOG(2) << "Got server response";
-  controller_->ShowResult(html.value());
+  controller_->ShowResult(std::move(result.value()));
 }
 
 void BloomInteraction::FetchAccessTokenAsync() {
diff --git a/chromeos/components/bloom/bloom_interaction.h b/chromeos/components/bloom/bloom_interaction.h
index 5dcbeb9..ea31f7f3 100644
--- a/chromeos/components/bloom/bloom_interaction.h
+++ b/chromeos/components/bloom/bloom_interaction.h
@@ -25,6 +25,7 @@
 namespace bloom {
 
 class BloomControllerImpl;
+struct BloomResult;
 
 template <typename _Type>
 class FutureValue;
@@ -52,7 +53,7 @@
   void StartAssistantInteraction(std::string&& access_token,
                                  gfx::Image&& screenshot);
 
-  void OnServerResponse(base::Optional<std::string> html);
+  void OnServerResponse(base::Optional<BloomResult> html);
 
   void FetchAccessTokenAsync();
   void FetchScreenshotAsync();
diff --git a/chromeos/components/bloom/bloom_result_builder.cc b/chromeos/components/bloom/bloom_result_builder.cc
new file mode 100644
index 0000000..eb71671
--- /dev/null
+++ b/chromeos/components/bloom/bloom_result_builder.cc
@@ -0,0 +1,248 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/components/bloom/bloom_result_builder.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/json/json_writer.h"
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+
+namespace chromeos {
+namespace bloom {
+
+namespace {
+
+std::string ToString(const base::Value& json) {
+  std::string result;
+  base::JSONWriter::WriteWithOptions(
+      json, base::JSONWriter::OPTIONS_PRETTY_PRINT, &result);
+  return result;
+}
+
+}  // namespace
+
+BloomResultBuilder::BloomResultBuilder() = default;
+BloomResultBuilder::~BloomResultBuilder() = default;
+
+BloomResult BloomResultBuilder::Build(const base::Value& root) {
+  BloomResult result;
+
+  result.query = GetQuery(root);
+
+  for (const auto& section : FindList("contentGroups", root).GetList())
+    result.sections.push_back(BuildSection(section));
+
+  return result;
+}
+
+std::string BloomResultBuilder::GetQuery(const base::Value& root) {
+  return FindString("query.text", root);
+}
+
+BloomResultSection BloomResultBuilder::BuildSection(
+    const base::Value& section) {
+  BloomResultSection result;
+
+  result.title = FindString("title", section);
+
+  for (const auto& entry : FindList("results", section).GetList()) {
+    const std::string& type = FindString("type", entry);
+
+    if (type == "QA")
+      result.entries.push_back(BuildQuestionAndAnswer(entry));
+    else if (type == "EXPLAINER")
+      result.entries.push_back(BuildExplainer(entry));
+    else if (type == "VIDEO_PROCEDURAL")
+      result.entries.push_back(BuildVideo(entry));
+    else if (type == "WEB_RESULT")
+      result.entries.push_back(BuildWebResult(entry));
+    else
+      LOG(WARNING) << "Unknown section type '" << type << "'";
+  }
+
+  return result;
+}
+
+std::unique_ptr<BloomQuestionAndAnswerEntry>
+BloomResultBuilder::BuildQuestionAndAnswer(const base::Value& entry) {
+  auto result = std::make_unique<BloomQuestionAndAnswerEntry>();
+
+  result->question = BuildTextElement(FindNthElement(entry, 0));
+  result->answer = BuildTextElement(FindNthElement(entry, 1));
+  result->source = BuildSourceElement(FindNthElement(entry, 2));
+
+  return result;
+}
+
+std::unique_ptr<BloomExplainerEntry> BloomResultBuilder::BuildExplainer(
+    const base::Value& entry) {
+  auto result = std::make_unique<BloomExplainerEntry>();
+
+  result->title = BuildTitleElement(FindNthElement(entry, 0));
+  result->image = BuildImageElement(FindNthElement(entry, 1));
+
+  auto elements = FindList("elements", entry).GetList();
+  // |index| starts at 2 because we've already consumed the title and the
+  // image.
+  for (size_t index = 2; index < elements.size(); index++) {
+    auto el = BuildElement(elements[index]);
+    if (el)
+      result->elements.push_back(std::move(el));
+  }
+
+  return result;
+}
+
+std::unique_ptr<BloomVideoEntry> BloomResultBuilder::BuildVideo(
+    const base::Value& entry) {
+  auto result = std::make_unique<BloomVideoEntry>();
+
+  result->video = BuildVideoElement(FindNthElement(entry, 0));
+  result->source = BuildSourceElement(FindNthElement(entry, 1));
+
+  return result;
+}
+
+std::unique_ptr<BloomWebResultEntry> BloomResultBuilder::BuildWebResult(
+    const base::Value& entry) {
+  auto result = std::make_unique<BloomWebResultEntry>();
+
+  result->title = BuildTextElement(FindNthElement(entry, 0));
+  result->snippet = BuildTextElement(FindNthElement(entry, 1));
+  result->source = BuildSourceElement(FindNthElement(entry, 2));
+
+  return result;
+}
+
+std::unique_ptr<BloomElement> BloomResultBuilder::BuildElement(
+    const base::Value& element) {
+  if (HasKey("text", element))
+    return std::make_unique<BloomTextElement>(BuildTextElement(element));
+  if (HasKey("image", element))
+    return std::make_unique<BloomImageElement>(BuildImageElement(element));
+  if (HasKey("math", element))
+    return std::make_unique<BloomMathElement>(BuildMathElement(element));
+  if (HasKey("title", element))
+    return std::make_unique<BloomTitleElement>(BuildTitleElement(element));
+  if (HasKey("attribution", element))
+    return std::make_unique<BloomSourceElement>(BuildSourceElement(element));
+  if (HasKey("video", element))
+    return std::make_unique<BloomVideoElement>(BuildVideoElement(element));
+
+  LOG(WARNING) << "Received element of unknown type. " << ToString(element);
+  return nullptr;
+}
+
+BloomImageElement BloomResultBuilder::BuildImageElement(
+    const base::Value& element) {
+  BloomImageElement result;
+  result.description = FindString("image.description", element);
+  result.url = GURL(FindString("image.url", element));
+  result.width = FindInt("image.width", element);
+  result.height = FindInt("image.height", element);
+  return result;
+}
+
+BloomMathElement BloomResultBuilder::BuildMathElement(
+    const base::Value& element) {
+  BloomMathElement result;
+  result.description = FindString("math.accessibilityDescription", element);
+  result.latex = FindString("math.latex", element);
+  return result;
+}
+
+BloomSourceElement BloomResultBuilder::BuildSourceElement(
+    const base::Value& element) {
+  BloomSourceElement result;
+  result.text = FindString("attribution.title", element);
+  result.favicon_url = GURL(FindString("attribution.faviconUrl", element));
+  result.url = GURL(FindString("url", element));
+  return result;
+}
+
+BloomTextElement BloomResultBuilder::BuildTextElement(
+    const base::Value& element) {
+  BloomTextElement result;
+  result.text = FindString("text.markdown", element);
+  return result;
+}
+
+BloomTitleElement BloomResultBuilder::BuildTitleElement(
+    const base::Value& element) {
+  BloomTitleElement result;
+  result.text = FindString("title.text", element);
+  return result;
+}
+
+BloomVideoElement BloomResultBuilder::BuildVideoElement(
+    const base::Value& element) {
+  BloomVideoElement result;
+  result.url = GURL(FindString("video.url", element));
+  result.title = FindString("video.title", element);
+  result.description = FindString("video.description", element);
+  result.thumbnail_url = GURL(FindString("video.thumbnailUrl", element));
+  result.video_id = FindString("video.videoId", element);
+  result.start_time = FindString("video.startTime", element);
+  result.duration = FindString("video.duration", element);
+  result.channel_title = FindString("video.channelTitle", element);
+  result.number_of_likes =
+      base::StringPrintf("%i", FindInt("video.numberOfLikes", element));
+  result.published_time = FindString("video.publishedTime", element);
+  result.number_of_views = FindString("video.numberOfViews", element);
+  return result;
+}
+
+bool BloomResultBuilder::HasKey(base::StringPiece key,
+                                const base::Value& parent) const {
+  return parent.FindKey(key) != nullptr;
+}
+
+const base::Value& BloomResultBuilder::FindList(
+    base::StringPiece key_path,
+    const base::Value& parent) const {
+  const base::Value* value = parent.FindListPath(key_path);
+  if (value)
+    return *value;
+
+  return default_list_;
+}
+
+int BloomResultBuilder::FindInt(base::StringPiece key_path,
+                                const base::Value& parent) const {
+  base::Optional<int> value = parent.FindIntPath(key_path);
+  return value.value_or(0);
+}
+
+const std::string& BloomResultBuilder::FindString(
+    base::StringPiece key_path,
+    const base::Value& parent) const {
+  const std::string* value = parent.FindStringPath(key_path);
+  if (value)
+    return *value;
+
+  return default_string_;
+}
+
+const base::Value& BloomResultBuilder::FindElement(const ConstListView& list,
+                                                   size_t index) const {
+  if (list.size() > index)
+    return list[index];
+
+  // Return a dictionary because element is a dictionary.
+  return default_dict_;
+}
+
+const base::Value& BloomResultBuilder::FindNthElement(const base::Value& entry,
+                                                      size_t index) const {
+  auto elements = FindList("elements", entry).GetList();
+  return FindElement(elements, index);
+}
+
+}  // namespace bloom
+}  // namespace chromeos
diff --git a/chromeos/components/bloom/bloom_result_builder.h b/chromeos/components/bloom/bloom_result_builder.h
new file mode 100644
index 0000000..4d1ef96
--- /dev/null
+++ b/chromeos/components/bloom/bloom_result_builder.h
@@ -0,0 +1,74 @@
+// 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 CHROMEOS_COMPONENTS_BLOOM_BLOOM_RESULT_BUILDER_H_
+#define CHROMEOS_COMPONENTS_BLOOM_BLOOM_RESULT_BUILDER_H_
+
+#include <memory>
+
+#include "base/strings/string_piece_forward.h"
+#include "base/values.h"
+#include "chromeos/components/bloom/public/cpp/bloom_result.h"
+
+namespace base {
+class Value;
+}  // namespace base
+
+namespace chromeos {
+namespace bloom {
+
+// Helper class that converts the Bloom server response into a formatted
+// result that can be displayed in the Assistant UI.
+class BloomResultBuilder {
+ public:
+  BloomResultBuilder();
+  BloomResultBuilder(BloomResultBuilder&) = delete;
+  BloomResultBuilder& operator=(BloomResultBuilder&) = delete;
+  ~BloomResultBuilder();
+
+  BloomResult Build(const base::Value& root);
+
+ private:
+  using ConstListView = base::Value::ConstListView;
+
+  std::string GetQuery(const base::Value& root);
+  BloomResultSection BuildSection(const base::Value& section);
+
+  std::unique_ptr<BloomQuestionAndAnswerEntry> BuildQuestionAndAnswer(
+      const base::Value& entry);
+  std::unique_ptr<BloomExplainerEntry> BuildExplainer(const base::Value& entry);
+  std::unique_ptr<BloomVideoEntry> BuildVideo(const base::Value& entry);
+  std::unique_ptr<BloomWebResultEntry> BuildWebResult(const base::Value& entry);
+
+  // This can be |nullptr| if the element is of an unknown type.
+  std::unique_ptr<BloomElement> BuildElement(const base::Value& element);
+  BloomImageElement BuildImageElement(const base::Value& element);
+  BloomMathElement BuildMathElement(const base::Value& element);
+  BloomSourceElement BuildSourceElement(const base::Value& element);
+  BloomTextElement BuildTextElement(const base::Value& element);
+  BloomTitleElement BuildTitleElement(const base::Value& element);
+  BloomVideoElement BuildVideoElement(const base::Value& element);
+
+  bool HasKey(base::StringPiece key, const base::Value& parent) const;
+  const base::Value& FindList(base::StringPiece key_path,
+                              const base::Value& parent) const;
+  int FindInt(base::StringPiece key_path, const base::Value& parent) const;
+  const std::string& FindString(base::StringPiece key_path,
+                                const base::Value& parent) const;
+  const base::Value& FindElement(const ConstListView& list, size_t index) const;
+  const base::Value& FindNthElement(const base::Value& entry,
+                                    size_t index) const;
+
+  // Default values returned when a JSON field is absent.
+  // We use this instead of nullptr to make the code robust to a bug on the
+  // server causing it to send invalid responses.
+  const base::Value default_dict_{base::Value::Type::DICTIONARY};
+  const base::Value default_list_{base::Value::Type::LIST};
+  const std::string default_string_;
+};
+
+}  // namespace bloom
+}  // namespace chromeos
+
+#endif  // CHROMEOS_COMPONENTS_BLOOM_BLOOM_RESULT_BUILDER_H_
diff --git a/chromeos/components/bloom/bloom_result_builder_unittest.cc b/chromeos/components/bloom/bloom_result_builder_unittest.cc
new file mode 100644
index 0000000..587ab105
--- /dev/null
+++ b/chromeos/components/bloom/bloom_result_builder_unittest.cc
@@ -0,0 +1,300 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/components/bloom/bloom_result_builder.h"
+
+#include "base/check.h"
+#include "base/json/json_reader.h"
+#include "base/logging.h"
+#include "base/optional.h"
+#include "base/values.h"
+#include "chromeos/components/bloom/bloom_result_builder.h"
+#include "chromeos/components/bloom/public/cpp/bloom_result.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+namespace bloom {
+
+namespace {
+
+// Implemented as a macro so we can fail the test when any of the |ASSERT| fail.
+#define GET_NTH_ELEMENT(result, index)       \
+  ({                                         \
+    ASSERT_GE(result.size(), (size_t)index); \
+    result[index].get();                     \
+  })
+
+// Implemented as a macro so we can fail the test when any of the |ASSERT| fail.
+#define GET_FIRST_ENTRY(result)                       \
+  ({                                                  \
+    ASSERT_GE(result.sections.size(), 1u);            \
+    ASSERT_GE(result.sections[0].entries.size(), 1u); \
+    result.sections[0].entries[0].get();              \
+  })
+
+}  // namespace
+
+void PrintTo(BloomResultEntry::Type type, std::ostream* os) {
+  *os << ToString(type);
+}
+
+class BloomResultBuilderTest : public ::testing::Test {
+ public:
+  BloomResult BuildResult(const std::string& json_string) {
+    base::JSONReader::ValueWithError json_value =
+        base::JSONReader::ReadAndReturnValueWithError(json_string);
+
+    CHECK(json_value.value) << "Invalid JSON.\n"
+                            << "    Error: " << json_value.error_message << "\n"
+                            << "    JSON: " << json_string;
+
+    return BloomResultBuilder().Build(json_value.value.value());
+  }
+};
+
+TEST_F(BloomResultBuilderTest, ShouldSetQuery) {
+  BloomResult result = BuildResult(R"(
+    {
+      "query": { "text": "The Query" }
+    }
+  )");
+
+  EXPECT_EQ("The Query", result.query);
+}
+
+TEST_F(BloomResultBuilderTest, ShouldAddSectionTitles) {
+  BloomResult result = BuildResult(R"(
+    {
+      "contentGroups": [
+        { "title": "The First Title" },
+        { "title": "The Second Title" }
+      ]
+    }
+  )");
+
+  ASSERT_EQ(2u, result.sections.size());
+  EXPECT_EQ("The First Title", result.sections[0].title);
+  EXPECT_EQ("The Second Title", result.sections[1].title);
+}
+
+TEST_F(BloomResultBuilderTest, ShouldAddQuestionAndAnswerEntry) {
+  BloomResult result = BuildResult(R"(
+    {
+      "contentGroups": [
+        {
+          "results": [
+            {
+              "type": "QA",
+              "elements": [
+                {
+                  "text": { "markdown": "The question" }
+                },
+                {
+                  "text": { "markdown": "The answer" }
+                },
+                {
+                  "attribution": {
+                    "title": "The source",
+                    "faviconUrl": "https://fav.icon"
+                  },
+                  "url": "https://source.url"
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    }
+  )");
+
+  const BloomResultEntry& entry = *GET_FIRST_ENTRY(result);
+
+  ASSERT_EQ(BloomResultEntry::Type::kQuestionAndAnswer, entry.type());
+
+  const BloomQuestionAndAnswerEntry& qa_entry = *entry.AsQuestionAndAnswer();
+
+  EXPECT_EQ("The question", qa_entry.question.text);
+  EXPECT_EQ("The answer", qa_entry.answer.text);
+
+  EXPECT_EQ("The source", qa_entry.source.text);
+  EXPECT_EQ(GURL("https://fav.icon"), qa_entry.source.favicon_url);
+  EXPECT_EQ(GURL("https://source.url"), qa_entry.source.url);
+}
+
+TEST_F(BloomResultBuilderTest, ShouldAddExplainer) {
+  BloomResult result = BuildResult(R"(
+    {
+      "contentGroups": [
+        {
+          "results": [
+            {
+              "type": "EXPLAINER",
+              "elements": [
+                {
+                  "title": { "text": "The title" }
+                },
+                {
+                  "image":  {
+                    "url": "https://image.url",
+                    "description": "The image",
+                    "width": 111,
+                    "height": 222
+                  }
+                },
+                {
+                  "text": { "markdown": "The explanation" }
+                },
+                {
+                  "text": { "markdown": "More explanation" }
+                },
+                {
+                  "math": {
+                    "latex": "The latex formula",
+                    "accessibilityDescription": "A Math result"
+                  }
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    }
+  )");
+
+  const BloomResultEntry& entry = *GET_FIRST_ENTRY(result);
+
+  ASSERT_EQ(BloomResultEntry::Type::kExplainer, entry.type());
+
+  const BloomExplainerEntry& explainer = *entry.AsExplainer();
+
+  EXPECT_EQ("The title", explainer.title.text);
+
+  EXPECT_EQ("The image", explainer.image.description);
+  EXPECT_EQ(GURL("https://image.url"), explainer.image.url);
+  EXPECT_EQ(111, explainer.image.width);
+  EXPECT_EQ(222, explainer.image.height);
+
+  const BloomElement& first_element = *GET_NTH_ELEMENT(explainer.elements, 0);
+  ASSERT_EQ(BloomElement::Type::kText, first_element.type());
+  EXPECT_EQ("The explanation", first_element.AsText()->text);
+
+  const BloomElement& second_element = *GET_NTH_ELEMENT(explainer.elements, 1);
+  ASSERT_EQ(BloomElement::Type::kText, second_element.type());
+  EXPECT_EQ("More explanation", second_element.AsText()->text);
+
+  const BloomElement& third_element = *GET_NTH_ELEMENT(explainer.elements, 2);
+  ASSERT_EQ(BloomElement::Type::kMath, third_element.type());
+  EXPECT_EQ("The latex formula", third_element.AsMath()->latex);
+  EXPECT_EQ("A Math result", third_element.AsMath()->description);
+}
+
+TEST_F(BloomResultBuilderTest, ShouldAddVideo) {
+  BloomResult result = BuildResult(R"(
+    {
+      "contentGroups": [
+        {
+          "results": [
+            {
+              "type": "VIDEO_PROCEDURAL",
+              "elements": [
+                {
+                  "video":  {
+                    "url": "https://video.url",
+                    "title": "The video title",
+                    "description": "The video description",
+                    "thumbnailUrl": "https://thumbnail.url",
+                    "videoId": "The video id",
+                    "startTime": "The start time",
+                    "duration": "The duration",
+                    "channelTitle": "The channel title",
+                    "numberOfLikes": 333,
+                    "publishedTime": "The published time",
+                    "numberOfViews": "666"
+                  }
+                },
+                {
+                  "attribution": {
+                    "title": "The source",
+                    "faviconUrl": "https://fav.icon"
+                  },
+                  "url": "https://source.url"
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    }
+  )");
+
+  const BloomResultEntry& entry = *GET_FIRST_ENTRY(result);
+
+  ASSERT_EQ(BloomResultEntry::Type::kVideo, entry.type());
+
+  const BloomVideoEntry& video = *entry.AsVideo();
+
+  EXPECT_EQ(GURL("https://video.url"), video.video.url);
+  EXPECT_EQ("The video title", video.video.title);
+  EXPECT_EQ("The video description", video.video.description);
+  EXPECT_EQ(GURL("https://thumbnail.url"), video.video.thumbnail_url);
+  EXPECT_EQ("The video id", video.video.video_id);
+  EXPECT_EQ("The start time", video.video.start_time);
+  EXPECT_EQ("The duration", video.video.duration);
+  EXPECT_EQ("The channel title", video.video.channel_title);
+  EXPECT_EQ("333", video.video.number_of_likes);
+  EXPECT_EQ("The published time", video.video.published_time);
+  EXPECT_EQ("666", video.video.number_of_views);
+
+  EXPECT_EQ("The source", video.source.text);
+  EXPECT_EQ(GURL("https://fav.icon"), video.source.favicon_url);
+  EXPECT_EQ(GURL("https://source.url"), video.source.url);
+}
+
+TEST_F(BloomResultBuilderTest, ShouldAddWebResult) {
+  BloomResult result = BuildResult(R"(
+    {
+      "contentGroups": [
+        {
+          "results": [
+            {
+              "type": "WEB_RESULT",
+              "elements": [
+                {
+                  "text": { "markdown": "The title" }
+                },
+                {
+                  "text": { "markdown": "The snippet" }
+                },
+                {
+                  "attribution": {
+                    "title": "The source",
+                    "faviconUrl": "https://fav.icon"
+                  },
+                  "url": "https://source.url"
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    }
+  )");
+
+  const BloomResultEntry& entry = *GET_FIRST_ENTRY(result);
+
+  ASSERT_EQ(BloomResultEntry::Type::kWebResult, entry.type());
+
+  const BloomWebResultEntry& web_result = *entry.AsWebResult();
+
+  EXPECT_EQ("The title", web_result.title.text);
+  EXPECT_EQ("The snippet", web_result.snippet.text);
+
+  EXPECT_EQ("The source", web_result.source.text);
+  EXPECT_EQ(GURL("https://fav.icon"), web_result.source.favicon_url);
+  EXPECT_EQ(GURL("https://source.url"), web_result.source.url);
+}
+
+}  // namespace bloom
+}  // namespace chromeos
diff --git a/chromeos/components/bloom/public/cpp/BUILD.gn b/chromeos/components/bloom/public/cpp/BUILD.gn
index 30dec04..d068762 100644
--- a/chromeos/components/bloom/public/cpp/BUILD.gn
+++ b/chromeos/components/bloom/public/cpp/BUILD.gn
@@ -10,13 +10,18 @@
     "bloom_controller.h",
     "bloom_interaction_resolution.cc",
     "bloom_interaction_resolution.h",
+    "bloom_result.cc",
+    "bloom_result.h",
     "bloom_screenshot_delegate.h",
     "bloom_ui_controller.cc",
     "bloom_ui_controller.h",
     "bloom_ui_delegate.h",
   ]
 
-  deps = [ "//base" ]
+  deps = [
+    "//base",
+    "//url",
+  ]
 
   defines = [ "IS_BLOOM_IMPL" ]
 
diff --git a/chromeos/components/bloom/public/cpp/bloom_controller_factory.cc b/chromeos/components/bloom/public/cpp/bloom_controller_factory.cc
index 57f727c0..07daa3f 100644
--- a/chromeos/components/bloom/public/cpp/bloom_controller_factory.cc
+++ b/chromeos/components/bloom/public/cpp/bloom_controller_factory.cc
@@ -40,10 +40,10 @@
     return delegate()->OnShowUI();
   }
 
-  void OnShowResult(const std::string& html) override {
+  void OnShowResult(const BloomResult& result) override {
     if (!delegate())
       return;
-    return delegate()->OnShowResult(html);
+    return delegate()->OnShowResult(result);
   }
 
   void OnInteractionFinished(BloomInteractionResolution resolution) override {
diff --git a/chromeos/components/bloom/public/cpp/bloom_result.cc b/chromeos/components/bloom/public/cpp/bloom_result.cc
new file mode 100644
index 0000000..e4823d9
--- /dev/null
+++ b/chromeos/components/bloom/public/cpp/bloom_result.cc
@@ -0,0 +1,256 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/components/bloom/public/cpp/bloom_result.h"
+
+namespace chromeos {
+namespace bloom {
+
+// BloomElement.
+
+const BloomImageElement* BloomElement::AsImage() const {
+  DCHECK(false);
+  return nullptr;
+}
+
+const BloomMathElement* BloomElement::AsMath() const {
+  DCHECK(false);
+  return nullptr;
+}
+
+const BloomSourceElement* BloomElement::AsSource() const {
+  DCHECK(false);
+  return nullptr;
+}
+
+const BloomTextElement* BloomElement::AsText() const {
+  DCHECK(false);
+  return nullptr;
+}
+
+const BloomTitleElement* BloomElement::AsTitle() const {
+  DCHECK(false);
+  return nullptr;
+}
+
+const BloomVideoElement* BloomElement::AsVideo() const {
+  DCHECK(false);
+  return nullptr;
+}
+
+std::string ToString(BloomElement::Type type) {
+#define CASE(name)               \
+  case BloomElement::Type::name: \
+    return #name;
+
+  switch (type) {
+    CASE(kImage);
+    CASE(kMath);
+    CASE(kSource);
+    CASE(kText);
+    CASE(kTitle);
+    CASE(kVideo);
+  }
+
+#undef CASE
+}
+
+// Image element.
+
+BloomImageElement::BloomImageElement() = default;
+BloomImageElement::BloomImageElement(BloomImageElement&&) = default;
+BloomImageElement& BloomImageElement::operator=(BloomImageElement&&) = default;
+BloomImageElement::~BloomImageElement() = default;
+
+BloomElement::Type BloomImageElement::type() const {
+  return Type::kImage;
+}
+
+const BloomImageElement* BloomImageElement::AsImage() const {
+  return this;
+}
+
+// Source element.
+
+BloomSourceElement::BloomSourceElement() = default;
+BloomSourceElement::BloomSourceElement(BloomSourceElement&&) = default;
+BloomSourceElement& BloomSourceElement::operator=(BloomSourceElement&&) =
+    default;
+BloomSourceElement::~BloomSourceElement() = default;
+
+BloomElement::Type BloomSourceElement::type() const {
+  return Type::kSource;
+}
+
+const BloomSourceElement* BloomSourceElement::AsSource() const {
+  return this;
+}
+
+// Math element.
+
+BloomMathElement::BloomMathElement() = default;
+BloomMathElement::BloomMathElement(BloomMathElement&&) = default;
+BloomMathElement& BloomMathElement::operator=(BloomMathElement&&) = default;
+BloomMathElement::~BloomMathElement() = default;
+
+BloomElement::Type BloomMathElement::type() const {
+  return Type::kMath;
+}
+
+const BloomMathElement* BloomMathElement::AsMath() const {
+  return this;
+}
+
+// Text element.
+
+BloomTextElement::BloomTextElement() = default;
+BloomTextElement::BloomTextElement(BloomTextElement&&) = default;
+BloomTextElement& BloomTextElement::operator=(BloomTextElement&&) = default;
+BloomTextElement::~BloomTextElement() = default;
+
+BloomElement::Type BloomTextElement::type() const {
+  return Type::kText;
+}
+
+const BloomTextElement* BloomTextElement::AsText() const {
+  return this;
+}
+
+// Title element.
+
+BloomTitleElement::BloomTitleElement() = default;
+BloomTitleElement::BloomTitleElement(BloomTitleElement&&) = default;
+BloomTitleElement& BloomTitleElement::operator=(BloomTitleElement&&) = default;
+BloomTitleElement::~BloomTitleElement() = default;
+
+BloomElement::Type BloomTitleElement::type() const {
+  return Type::kTitle;
+}
+
+const BloomTitleElement* BloomTitleElement::AsTitle() const {
+  return this;
+}
+
+// Video element.
+
+BloomVideoElement::BloomVideoElement() = default;
+BloomVideoElement::BloomVideoElement(BloomVideoElement&&) = default;
+BloomVideoElement& BloomVideoElement::operator=(BloomVideoElement&&) = default;
+BloomVideoElement::~BloomVideoElement() = default;
+
+BloomElement::Type BloomVideoElement::type() const {
+  return Type::kVideo;
+}
+
+const BloomVideoElement* BloomVideoElement::AsVideo() const {
+  return this;
+}
+
+// BloomResultEntry.
+
+BloomResultEntry::BloomResultEntry() = default;
+BloomResultEntry::~BloomResultEntry() = default;
+
+const BloomQuestionAndAnswerEntry* BloomResultEntry::AsQuestionAndAnswer()
+    const {
+  DCHECK(false);
+  return nullptr;
+}
+
+const BloomExplainerEntry* BloomResultEntry::AsExplainer() const {
+  DCHECK(false);
+  return nullptr;
+}
+
+const BloomVideoEntry* BloomResultEntry::AsVideo() const {
+  DCHECK(false);
+  return nullptr;
+}
+
+const BloomWebResultEntry* BloomResultEntry::AsWebResult() const {
+  DCHECK(false);
+  return nullptr;
+}
+
+std::string ToString(BloomResultEntry::Type type) {
+#define CASE(name)                   \
+  case BloomResultEntry::Type::name: \
+    return #name;
+
+  switch (type) {
+    CASE(kQuestionAndAnswer);
+    CASE(kExplainer);
+    CASE(kVideo);
+    CASE(kWebResult);
+  }
+
+#undef CASE
+}
+
+// Question and Answer.
+
+BloomQuestionAndAnswerEntry::BloomQuestionAndAnswerEntry() = default;
+BloomQuestionAndAnswerEntry::~BloomQuestionAndAnswerEntry() = default;
+
+BloomResultEntry::Type BloomQuestionAndAnswerEntry::type() const {
+  return Type::kQuestionAndAnswer;
+}
+
+const BloomQuestionAndAnswerEntry*
+BloomQuestionAndAnswerEntry::AsQuestionAndAnswer() const {
+  return this;
+}
+
+// Explainer.
+
+BloomExplainerEntry::BloomExplainerEntry() = default;
+BloomExplainerEntry::~BloomExplainerEntry() = default;
+
+BloomResultEntry::Type BloomExplainerEntry::type() const {
+  return Type::kExplainer;
+}
+
+const BloomExplainerEntry* BloomExplainerEntry::AsExplainer() const {
+  return this;
+}
+
+// Video.
+
+BloomVideoEntry::BloomVideoEntry() = default;
+BloomVideoEntry::~BloomVideoEntry() = default;
+
+BloomResultEntry::Type BloomVideoEntry::type() const {
+  return Type::kVideo;
+}
+
+const BloomVideoEntry* BloomVideoEntry::AsVideo() const {
+  return this;
+}
+
+// WebResult.
+
+BloomWebResultEntry::BloomWebResultEntry() = default;
+BloomWebResultEntry::~BloomWebResultEntry() = default;
+
+BloomResultEntry::Type BloomWebResultEntry::type() const {
+  return Type::kWebResult;
+}
+
+const BloomWebResultEntry* BloomWebResultEntry::AsWebResult() const {
+  return this;
+}
+
+BloomResultSection::BloomResultSection() = default;
+BloomResultSection::BloomResultSection(BloomResultSection&&) = default;
+BloomResultSection& BloomResultSection::operator=(BloomResultSection&&) =
+    default;
+BloomResultSection::~BloomResultSection() = default;
+
+BloomResult::BloomResult() = default;
+BloomResult::BloomResult(BloomResult&&) = default;
+BloomResult& BloomResult::operator=(BloomResult&&) = default;
+BloomResult::~BloomResult() = default;
+
+}  // namespace bloom
+}  // namespace chromeos
diff --git a/chromeos/components/bloom/public/cpp/bloom_result.h b/chromeos/components/bloom/public/cpp/bloom_result.h
new file mode 100644
index 0000000..601fe647
--- /dev/null
+++ b/chromeos/components/bloom/public/cpp/bloom_result.h
@@ -0,0 +1,279 @@
+// 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 CHROMEOS_COMPONENTS_BLOOM_PUBLIC_CPP_BLOOM_RESULT_H_
+#define CHROMEOS_COMPONENTS_BLOOM_PUBLIC_CPP_BLOOM_RESULT_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/component_export.h"
+#include "url/gurl.h"
+
+namespace chromeos {
+namespace bloom {
+
+struct BloomImageElement;
+struct BloomMathElement;
+struct BloomSourceElement;
+struct BloomTextElement;
+struct BloomTitleElement;
+struct BloomVideoElement;
+
+// Abstract base class representing individual elements (a text, a video, an
+// image, ...) that are used to compose the Bloom response entries.
+struct COMPONENT_EXPORT(BLOOM) BloomElement {
+  BloomElement() = default;
+  BloomElement(const BloomElement&) = delete;
+  BloomElement& operator=(const BloomElement&) = delete;
+  BloomElement(BloomElement&&) = default;
+  BloomElement& operator=(BloomElement&&) = default;
+  virtual ~BloomElement() = default;
+
+  enum class Type {
+    kImage,
+    kMath,
+    kSource,
+    kText,
+    kTitle,
+    kVideo,
+  };
+
+  virtual Type type() const = 0;
+
+  // Methods for checked downcasting to derived types.
+  // DCHECK when called on a wrong type.
+
+  virtual const BloomImageElement* AsImage() const;
+  virtual const BloomMathElement* AsMath() const;
+  virtual const BloomSourceElement* AsSource() const;
+  virtual const BloomTextElement* AsText() const;
+  virtual const BloomTitleElement* AsTitle() const;
+  virtual const BloomVideoElement* AsVideo() const;
+};
+
+std::string COMPONENT_EXPORT(BLOOM) ToString(BloomElement::Type type);
+
+struct COMPONENT_EXPORT(BLOOM) BloomImageElement : public BloomElement {
+  BloomImageElement();
+  BloomImageElement(const BloomImageElement&) = delete;
+  BloomImageElement& operator=(const BloomImageElement&) = delete;
+  BloomImageElement(BloomImageElement&&);
+  BloomImageElement& operator=(BloomImageElement&&);
+  ~BloomImageElement() override;
+
+  // BloomResultElement implementation:
+  Type type() const override;
+  const BloomImageElement* AsImage() const override;
+
+  GURL url;
+  std::string description;
+  int width;
+  int height;
+};
+
+struct COMPONENT_EXPORT(BLOOM) BloomMathElement : public BloomElement {
+  BloomMathElement();
+  BloomMathElement(const BloomMathElement&) = delete;
+  BloomMathElement& operator=(const BloomMathElement&) = delete;
+  BloomMathElement(BloomMathElement&&);
+  BloomMathElement& operator=(BloomMathElement&&);
+  ~BloomMathElement() override;
+
+  // BloomResultElement implementation:
+  Type type() const override;
+  const BloomMathElement* AsMath() const override;
+
+  std::string description;
+  std::string latex;
+};
+
+struct COMPONENT_EXPORT(BLOOM) BloomSourceElement : public BloomElement {
+  BloomSourceElement();
+  BloomSourceElement(const BloomSourceElement&) = delete;
+  BloomSourceElement& operator=(const BloomSourceElement&) = delete;
+  BloomSourceElement(BloomSourceElement&&);
+  BloomSourceElement& operator=(BloomSourceElement&&);
+  ~BloomSourceElement() override;
+
+  // BloomResultElement implementation:
+  Type type() const override;
+  const BloomSourceElement* AsSource() const override;
+
+  std::string text;
+  GURL favicon_url;
+  GURL url;
+};
+
+struct COMPONENT_EXPORT(BLOOM) BloomTextElement : public BloomElement {
+  BloomTextElement();
+  BloomTextElement(const BloomTextElement&) = delete;
+  BloomTextElement& operator=(const BloomTextElement&) = delete;
+  BloomTextElement(BloomTextElement&&);
+  BloomTextElement& operator=(BloomTextElement&&);
+  ~BloomTextElement() override;
+
+  // BloomResultElement implementation:
+  Type type() const override;
+  const BloomTextElement* AsText() const override;
+
+  std::string text;
+};
+
+struct COMPONENT_EXPORT(BLOOM) BloomTitleElement : public BloomElement {
+  BloomTitleElement();
+  BloomTitleElement(const BloomTitleElement&) = delete;
+  BloomTitleElement& operator=(const BloomTitleElement&) = delete;
+  BloomTitleElement(BloomTitleElement&&);
+  BloomTitleElement& operator=(BloomTitleElement&&);
+  ~BloomTitleElement() override;
+
+  // BloomResultElement implementation:
+  Type type() const override;
+  const BloomTitleElement* AsTitle() const override;
+
+  std::string text;
+};
+
+struct COMPONENT_EXPORT(BLOOM) BloomVideoElement : public BloomElement {
+  BloomVideoElement();
+  BloomVideoElement(const BloomVideoElement&) = delete;
+  BloomVideoElement& operator=(const BloomVideoElement&) = delete;
+  BloomVideoElement(BloomVideoElement&&);
+  BloomVideoElement& operator=(BloomVideoElement&&);
+  ~BloomVideoElement() override;
+
+  // BloomResultElement implementation:
+  Type type() const override;
+  const BloomVideoElement* AsVideo() const override;
+
+  GURL url;
+  std::string title;
+  std::string description;
+  GURL thumbnail_url;
+  std::string video_id;
+  std::string start_time;
+  std::string duration;
+  std::string channel_title;
+  std::string published_time;
+  std::string number_of_likes;
+  std::string number_of_views;
+};
+
+struct BloomQuestionAndAnswerEntry;
+struct BloomExplainerEntry;
+struct BloomVideoEntry;
+struct BloomWebResultEntry;
+
+// Abstract base class representing the different entries in the Bloom response.
+// Each entry contains a single answer, and is composed of multiple elements.
+struct COMPONENT_EXPORT(BLOOM) BloomResultEntry {
+  BloomResultEntry();
+  BloomResultEntry(const BloomResultEntry&) = delete;
+  BloomResultEntry& operator=(const BloomResultEntry&) = delete;
+  virtual ~BloomResultEntry();
+
+  enum class Type {
+    kQuestionAndAnswer,
+    kExplainer,
+    kVideo,
+    kWebResult,
+  };
+
+  virtual Type type() const = 0;
+
+  // Methods for checked downcasting to derived types.
+  // DCHECK when called on a wrong type.
+
+  virtual const BloomQuestionAndAnswerEntry* AsQuestionAndAnswer() const;
+  virtual const BloomExplainerEntry* AsExplainer() const;
+  virtual const BloomVideoEntry* AsVideo() const;
+  virtual const BloomWebResultEntry* AsWebResult() const;
+};
+
+std::string COMPONENT_EXPORT(BLOOM) ToString(BloomResultEntry::Type type);
+
+struct COMPONENT_EXPORT(BLOOM) BloomQuestionAndAnswerEntry
+    : public BloomResultEntry {
+  BloomQuestionAndAnswerEntry();
+  ~BloomQuestionAndAnswerEntry() override;
+
+  // BloomResultEntry implementation:
+  Type type() const override;
+  const BloomQuestionAndAnswerEntry* AsQuestionAndAnswer() const override;
+
+  BloomTextElement question;
+  BloomTextElement answer;
+  BloomSourceElement source;
+};
+
+struct COMPONENT_EXPORT(BLOOM) BloomExplainerEntry : public BloomResultEntry {
+  BloomExplainerEntry();
+  ~BloomExplainerEntry() override;
+
+  // BloomResultEntry implementation:
+  Type type() const override;
+  const BloomExplainerEntry* AsExplainer() const override;
+
+  BloomTitleElement title;
+  BloomImageElement image;
+  // An explainer ends with a variable amount of elements.
+  std::vector<std::unique_ptr<BloomElement>> elements;
+};
+
+struct COMPONENT_EXPORT(BLOOM) BloomVideoEntry : public BloomResultEntry {
+  BloomVideoEntry();
+  ~BloomVideoEntry() override;
+
+  // BloomResultEntry implementation:
+  Type type() const override;
+  const BloomVideoEntry* AsVideo() const override;
+
+  BloomVideoElement video;
+  BloomSourceElement source;
+};
+
+struct COMPONENT_EXPORT(BLOOM) BloomWebResultEntry : public BloomResultEntry {
+  BloomWebResultEntry();
+  ~BloomWebResultEntry() override;
+
+  // BloomResultEntry implementation:
+  Type type() const override;
+  const BloomWebResultEntry* AsWebResult() const override;
+
+  BloomTextElement title;
+  BloomTextElement snippet;
+  BloomSourceElement source;
+};
+
+struct COMPONENT_EXPORT(BLOOM) BloomResultSection {
+  BloomResultSection();
+  BloomResultSection(const BloomResultSection&) = delete;
+  BloomResultSection& operator=(const BloomResultSection&) = delete;
+  BloomResultSection(BloomResultSection&&);
+  BloomResultSection& operator=(BloomResultSection&&);
+  ~BloomResultSection();
+
+  std::string title;
+  std::vector<std::unique_ptr<BloomResultEntry>> entries;
+};
+
+struct COMPONENT_EXPORT(BLOOM) BloomResult {
+ public:
+  BloomResult();
+  BloomResult(const BloomResult&) = delete;
+  BloomResult& operator=(const BloomResult&) = delete;
+  BloomResult(BloomResult&&);
+  BloomResult& operator=(BloomResult&&);
+  ~BloomResult();
+
+  std::string query;
+  std::vector<BloomResultSection> sections;
+};
+
+}  // namespace bloom
+}  // namespace chromeos
+
+#endif  // CHROMEOS_COMPONENTS_BLOOM_PUBLIC_CPP_BLOOM_RESULT_H_
diff --git a/chromeos/components/bloom/public/cpp/bloom_ui_delegate.h b/chromeos/components/bloom/public/cpp/bloom_ui_delegate.h
index f214d3b..cf2dd0ac 100644
--- a/chromeos/components/bloom/public/cpp/bloom_ui_delegate.h
+++ b/chromeos/components/bloom/public/cpp/bloom_ui_delegate.h
@@ -10,6 +10,8 @@
 namespace chromeos {
 namespace bloom {
 
+struct BloomResult;
+
 class BloomUiDelegate {
  public:
   virtual ~BloomUiDelegate() = default;
@@ -20,7 +22,7 @@
   virtual void OnShowUI() = 0;
 
   // Called when the result is ready.
-  virtual void OnShowResult(const std::string& html) = 0;
+  virtual void OnShowResult(const BloomResult& result) = 0;
 
   virtual void OnInteractionFinished(BloomInteractionResolution resolution) = 0;
 };
diff --git a/chromeos/components/bloom/server/bloom_server_proxy.h b/chromeos/components/bloom/server/bloom_server_proxy.h
index 90f593bb..3892260 100644
--- a/chromeos/components/bloom/server/bloom_server_proxy.h
+++ b/chromeos/components/bloom/server/bloom_server_proxy.h
@@ -15,11 +15,13 @@
 namespace chromeos {
 namespace bloom {
 
+struct BloomResult;
+
 // Local object that handles all communication with the Bloom servers.
 class BloomServerProxy {
  public:
   using Callback =
-      base::OnceCallback<void(base::Optional<std::string> response)>;
+      base::OnceCallback<void(base::Optional<BloomResult> response)>;
 
   BloomServerProxy() = default;
   BloomServerProxy(BloomServerProxy&) = delete;
diff --git a/chromeos/components/bloom/server/bloom_server_proxy_impl.cc b/chromeos/components/bloom/server/bloom_server_proxy_impl.cc
index 957fa20..6cc80b7 100644
--- a/chromeos/components/bloom/server/bloom_server_proxy_impl.cc
+++ b/chromeos/components/bloom/server/bloom_server_proxy_impl.cc
@@ -9,13 +9,15 @@
 #include "base/base64.h"
 #include "base/bind.h"
 #include "base/check.h"
-#include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
 #include "base/values.h"
+#include "chromeos/components/bloom/bloom_result_builder.h"
+#include "chromeos/components/bloom/public/cpp/bloom_result.h"
 #include "chromeos/components/bloom/server/bloom_url_loader.h"
 #include "chromeos/services/assistant/public/shared/constants.h"
+#include "services/data_decoder/public/cpp/data_decoder.h"
 #include "ui/gfx/image/image.h"
 
 namespace chromeos {
@@ -23,6 +25,8 @@
 
 namespace {
 
+using ValueOrError = data_decoder::DataDecoder::ValueOrError;
+
 constexpr char kJsonMimeType[] = "application/json";
 
 std::string EncodeImage(const gfx::Image& image) {
@@ -59,6 +63,8 @@
 
 class BloomServerProxyImpl::Worker {
  public:
+  using ServerCallback = BloomURLLoader::Callback;
+
   Worker(BloomServerProxyImpl* parent,
          const std::string& access_token,
          Callback callback)
@@ -78,6 +84,8 @@
   }
 
  private:
+  typedef void (Worker::*JsonCallback)(ValueOrError);
+
   BloomURLLoader* url_loader() { return parent_->url_loader_.get(); }
 
   void SendCreateImageRequest(const gfx::Image& screenshot) {
@@ -111,15 +119,19 @@
       return;
     }
 
-    base::Optional<base::Value> json_reply =
-        base::JSONReader::Read(reply.value());
-    if (!json_reply) {
-      LOG(WARNING) << "Bloom servers responded with invalid JSON";
+    ParseJson(reply.value(), &Worker::OnCreateImageResponseParsed);
+  }
+
+  void OnCreateImageResponseParsed(ValueOrError json_reply) {
+    if (!json_reply.value) {
+      LOG(WARNING) << "Bloom servers responded with invalid JSON: "
+                   << json_reply.error.value();
       FinishWithError();
       return;
     }
 
-    const std::string* image_id = json_reply.value().FindStringKey("imageId");
+    const std::string* image_id =
+        json_reply.value.value().FindStringKey("imageId");
     if (!image_id) {
       LOG(WARNING) << "'imageId' tag is missing from Bloom server response";
       FinishWithError();
@@ -137,16 +149,19 @@
       return;
     }
 
-    base::Optional<base::Value> json_reply =
-        base::JSONReader::Read(reply.value());
-    if (!json_reply) {
-      LOG(WARNING) << "Bloom servers responded with invalid JSON";
+    ParseJson(reply.value(), &Worker::OnOcrImageResponseParsed);
+  }
+
+  void OnOcrImageResponseParsed(ValueOrError json_reply) {
+    if (!json_reply.value) {
+      LOG(WARNING) << "Bloom servers responded with invalid JSON: "
+                   << json_reply.error.value();
       FinishWithError();
       return;
     }
 
     const std::string* metadata_blob =
-        json_reply.value().FindStringKey("metadataBlob");
+        json_reply.value.value().FindStringKey("metadataBlob");
     if (!metadata_blob) {
       LOG(WARNING)
           << "'metadataBlob' tag is missing from Bloom server response.";
@@ -154,28 +169,52 @@
       return;
     }
 
-    LOG(WARNING) << "Bloom servers responded with valid response";
+    DVLOG(3) << "Bloom servers responded with valid response";
     SendSearchProblemRequest(*metadata_blob);
   }
 
   void OnSearchProblemResponse(base::Optional<std::string> reply) {
-    FinishWithReply(std::move(reply));
+    if (!reply) {
+      DVLOG(3) << "Bloom servers responded with error";
+      FinishWithError();
+      return;
+    }
+
+    ParseJson(reply.value(), &Worker::OnSearchProblemResponseParsed);
+  }
+
+  void OnSearchProblemResponseParsed(ValueOrError json) {
+    if (!json.value) {
+      LOG(WARNING) << "Bloom servers responded with invalid JSON: "
+                   << json.error.value();
+      FinishWithError();
+      return;
+    }
+
+    DVLOG(3) << "Bloom servers responded with success";
+    BloomResult result = BloomResultBuilder().Build(json.value.value());
+    FinishWithReply(std::move(result));
   }
 
   void SendPostJSONRequest(const GURL& url,
                            const base::Value& json,
-                           Callback callback) {
+                           ServerCallback callback) {
     url_loader()->SendPostRequest(url, access_token_, JSONToString(json),
                                   kJsonMimeType, std::move(callback));
   }
 
-  void SendGetRequest(const GURL& url, Callback callback) {
+  void SendGetRequest(const GURL& url, ServerCallback callback) {
     url_loader()->SendGetRequest(url, access_token_, std::move(callback));
   }
 
+  void ParseJson(const std::string& json, JsonCallback callback) {
+    data_decoder::DataDecoder::ParseJsonIsolated(
+        json, base::BindOnce(callback, weak_ptr_factory_.GetWeakPtr()));
+  }
+
   void FinishWithError() { FinishWithReply(base::nullopt); }
 
-  void FinishWithReply(base::Optional<std::string> reply) {
+  void FinishWithReply(base::Optional<BloomResult> reply) {
     std::move(callback_).Run(std::move(reply));
   }
 
diff --git a/chromeos/components/bloom/server/bloom_server_proxy_impl_unittest.cc b/chromeos/components/bloom/server/bloom_server_proxy_impl_unittest.cc
index 0fdd1a4..1988571 100644
--- a/chromeos/components/bloom/server/bloom_server_proxy_impl_unittest.cc
+++ b/chromeos/components/bloom/server/bloom_server_proxy_impl_unittest.cc
@@ -7,8 +7,12 @@
 #include "base/base64.h"
 #include "base/bind.h"
 #include "base/optional.h"
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "chromeos/components/bloom/public/cpp/bloom_result.h"
 #include "chromeos/components/bloom/server/bloom_url_loader.h"
 #include "chromeos/services/assistant/public/shared/constants.h"
+#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
 #include "services/network/test/test_shared_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -27,12 +31,6 @@
 using assistant::kBloomOcrImagePath;
 using assistant::kBloomSearchProblemPath;
 
-// We can't simply pass |base::nullopt| into an EXPECT_CALL call,
-// instead it must be fully typed to |base::Optional<std::string>|.
-// So this convenience wrapper hides those details.
-#define EXPECT_CALL_WITH_NULLOPT(mock) \
-  EXPECT_CALL(mock, Call(base::Optional<std::string>(base::nullopt)))
-
 std::string Quote(const std::string& data) {
   return "\"" + data + "\"";
 }
@@ -50,13 +48,36 @@
 // Mock for |BloomServerProxy::Callback|.
 class CallbackMock {
  public:
-  MOCK_METHOD(void, Call, (base::Optional<std::string>));
+  MOCK_METHOD(void, Call, (base::Optional<BloomResult>));
 
   auto BindOnce() {
     return base::BindOnce(&CallbackMock::Call, base::Unretained(this));
   }
 };
 
+MATCHER_P(BloomResultWithQuery, query, "") {
+  if (!arg.has_value()) {
+    *result_listener << "Received nullopt.";
+    return false;
+  }
+  if (arg.value().query != query) {
+    *result_listener << "Received BloomResult with wrong query.\n"
+                     << "  Expected:  '" << query << "'\n"
+                     << "  Actual:    '" << arg.value().query << "'\n";
+    return false;
+  }
+  return true;
+}
+
+MATCHER(NullBloomResult, "") {
+  if (arg.has_value()) {
+    *result_listener << "Expected nullopt but got BloomResult with query '"
+                     << arg.value().query << "'";
+    return false;
+  }
+  return true;
+}
+
 class BloomURLLoaderMock : public BloomURLLoader {
  public:
   BloomURLLoaderMock() {
@@ -120,7 +141,7 @@
   auto any_screenshot() { return gfx::test::CreateImage(5, 5); }
 
   auto any_callback() {
-    return base::BindOnce([](base::Optional<std::string>) {});
+    return base::BindOnce([](base::Optional<BloomResult>) {});
   }
 
   // Add mock expectations for all server calls.
@@ -132,20 +153,29 @@
   void RespondToUploadImageCall(base::Optional<std::string> json_response =
                                     ToJSON("imageId", "default-image-id")) {
     url_loader_mock().SendPostServerReply(json_response);
+    // Give the JSON Decoder a chance to run.
+    base::RunLoop().RunUntilIdle();
   }
 
   void RespondToOcrImageCall(base::Optional<std::string> json_response =
                                  ToJSON("metadataBlob",
                                         "default-metadata-blob")) {
     url_loader_mock().SendGetServerReply(json_response);
+    // Give the JSON Decoder a chance to run.
+    base::RunLoop().RunUntilIdle();
   }
 
   void RespondToProblemSearchCall(
       base::Optional<std::string> server_response = "default-server-response") {
     url_loader_mock().SendGetServerReply(server_response);
+    // Give the JSON Decoder a chance to run.
+    base::RunLoop().RunUntilIdle();
   }
 
  private:
+  base::test::TaskEnvironment scoped_task_env_;
+  data_decoder::test::InProcessDataDecoder scoped_json_decoder_;
+
   BloomServerProxyImpl server_proxy_{std::make_unique<BloomURLLoaderMock>()};
 };
 
@@ -204,20 +234,22 @@
 }
 
 TEST_F(BloomServerProxyImplTest, ShouldSendServerResponseToTheCallback) {
-  const base::Optional<std::string> server_response = "the-server-response";
-
   CallbackMock callback;
 
   ExpectServerCalls();
 
-  EXPECT_CALL(callback, Call(server_response));
+  EXPECT_CALL(callback, Call(BloomResultWithQuery("The Server Response")));
 
   server_proxy().AnalyzeProblem("access_token", any_screenshot(),
                                 callback.BindOnce());
 
   RespondToUploadImageCall();
   RespondToOcrImageCall();
-  RespondToProblemSearchCall(server_response);
+  RespondToProblemSearchCall(R"(
+    {
+      "query": { "text": "The Server Response" }
+    }
+  )");
 }
 
 TEST_F(BloomServerProxyImplTest,
@@ -225,7 +257,7 @@
   CallbackMock callback;
   ExpectServerCalls();
 
-  EXPECT_CALL_WITH_NULLOPT(callback);
+  EXPECT_CALL(callback, Call(NullBloomResult()));
 
   server_proxy().AnalyzeProblem("access_token", any_screenshot(),
                                 callback.BindOnce());
@@ -238,7 +270,7 @@
   CallbackMock callback;
   ExpectServerCalls();
 
-  EXPECT_CALL_WITH_NULLOPT(callback);
+  EXPECT_CALL(callback, Call(NullBloomResult()));
 
   server_proxy().AnalyzeProblem("access_token", any_screenshot(),
                                 callback.BindOnce());
@@ -251,7 +283,7 @@
   CallbackMock callback;
   ExpectServerCalls();
 
-  EXPECT_CALL_WITH_NULLOPT(callback);
+  EXPECT_CALL(callback, Call(NullBloomResult()));
 
   server_proxy().AnalyzeProblem("access_token", any_screenshot(),
                                 callback.BindOnce());
@@ -263,7 +295,7 @@
   CallbackMock callback;
   ExpectServerCalls();
 
-  EXPECT_CALL_WITH_NULLOPT(callback);
+  EXPECT_CALL(callback, Call(NullBloomResult()));
 
   server_proxy().AnalyzeProblem("access_token", any_screenshot(),
                                 callback.BindOnce());
@@ -277,7 +309,7 @@
   CallbackMock callback;
   ExpectServerCalls();
 
-  EXPECT_CALL_WITH_NULLOPT(callback);
+  EXPECT_CALL(callback, Call(NullBloomResult()));
 
   server_proxy().AnalyzeProblem("access_token", any_screenshot(),
                                 callback.BindOnce());
@@ -291,7 +323,7 @@
   CallbackMock callback;
   ExpectServerCalls();
 
-  EXPECT_CALL_WITH_NULLOPT(callback);
+  EXPECT_CALL(callback, Call(NullBloomResult()));
 
   server_proxy().AnalyzeProblem("access_token", any_screenshot(),
                                 callback.BindOnce());
@@ -301,11 +333,26 @@
 }
 
 TEST_F(BloomServerProxyImplTest,
+       ShouldSendNulloptToCallbackIfProblemSearchReturnsInvalidJSON) {
+  CallbackMock callback;
+  ExpectServerCalls();
+
+  EXPECT_CALL(callback, Call(NullBloomResult()));
+
+  server_proxy().AnalyzeProblem("access_token", any_screenshot(),
+                                callback.BindOnce());
+
+  RespondToUploadImageCall();
+  RespondToOcrImageCall();
+  RespondToProblemSearchCall("This is NOT valid JSON");
+}
+
+TEST_F(BloomServerProxyImplTest,
        ShouldSendNulloptToCallbackIfProblemSearchFails) {
   CallbackMock callback;
   ExpectServerCalls();
 
-  EXPECT_CALL_WITH_NULLOPT(callback);
+  EXPECT_CALL(callback, Call(NullBloomResult()));
 
   server_proxy().AnalyzeProblem("access_token", any_screenshot(),
                                 callback.BindOnce());
@@ -315,20 +362,5 @@
   RespondToProblemSearchCall(/*json_response=*/base::nullopt);
 }
 
-TEST_F(BloomServerProxyImplTest,
-       ShouldSendNulloptToCallbackIfInteractionIsCancelled) {
-  CallbackMock callback;
-  ExpectServerCalls();
-
-  EXPECT_CALL_WITH_NULLOPT(callback);
-
-  server_proxy().AnalyzeProblem("access_token", any_screenshot(),
-                                callback.BindOnce());
-
-  // To cancel the interaction, we start a second interaction.
-  server_proxy().AnalyzeProblem("access_token", any_screenshot(),
-                                any_callback());
-}
-
 }  // namespace bloom
 }  // namespace chromeos
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_pa.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_pa.xtb
index a873f75..9a81a01 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_pa.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_pa.xtb
@@ -3,7 +3,7 @@
 <translationbundle lang="pa">
 <translation id="1276998909102132017">ਗੈਲਰੀ ਚਿੱਤਰ</translation>
 <translation id="1430915738399379752">ਪ੍ਰਿੰਟ ਕਰੋ</translation>
-<translation id="1473110567575736769">3 ਸਕਿੰਟ ਦਾ ਟਾਈਮਰ</translation>
+<translation id="1473110567575736769">3 ਸਕਿੰਟਾਂ ਦਾ ਟਾਈਮਰ</translation>
 <translation id="1620510694547887537">ਕੈਮਰਾ</translation>
 <translation id="1627744224761163218">4 x 4</translation>
 <translation id="1664224225747386870">ਕੁਝ ਵੀ ਰਿਕਾਰਡ ਨਹੀਂ ਹੋਇਆ</translation>
@@ -31,7 +31,7 @@
 <translation id="3517926952904427380">ਪੋਰਟਰੇਟ ਫ਼ੋਟੋ ਖਿੱਚੀ ਨਹੀਂ ਜਾ ਸਕੀ</translation>
 <translation id="3569311554794739032">ਕੀ ਤੁਸੀਂ ਪੱਕਾ <ph name="FILE" /> ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?</translation>
 <translation id="3810838688059735925">ਵੀਡਿਓ</translation>
-<translation id="4000398125663085899">ਫ਼ਾਈਲਾਂ ਐਪ ਵਿੱਚ ਨਵੀਆਂ ਫ਼ੋਟੋਆਂ ਅਤੇ ਵੀਡੀਓ ਨੂੰ ਕਿਸੇ ਫੋਲਡਰ ਵਿੱਚ ਰੱਖਿਅਤ ਕੀਤਾ ਜਾਵੇਗਾ: ਮੇਰੀਆਂ ਫ਼ਾਈਲਾਂ &gt; ਕੈਮਰਾ</translation>
+<translation id="4000398125663085899">ਨਵੀਆਂ ਫ਼ੋਟੋਆਂ ਅਤੇ ਵੀਡੀਓ ਨੂੰ ਹੁਣ Files ਐਪ ਵਿੱਚ ਕਿਸੇ ਫੋਲਡਰ: ਮੇਰੀਆਂ ਫ਼ਾਈਲਾਂ &gt; ਕੈਮਰੇ ਵਿੱਚ ਰੱਖਿਅਤ ਕੀਤਾ ਜਾਵੇਗਾ</translation>
 <translation id="4118525110028899586">ਰਿਕਾਰਡਿੰਗ ਰੋਕੋ</translation>
 <translation id="4279490309300973883">ਪ੍ਰਤਿਬਿੰਬੀਕਰਨ</translation>
 <translation id="4329152592498422850">'ਵਰਗਾਕਾਰ ਫ਼ੋਟੋ ਖਿੱਚੋ' ਮੋਡ 'ਤੇ ਜਾਓ</translation>
diff --git a/chromeos/components/cdm_factory_daemon/BUILD.gn b/chromeos/components/cdm_factory_daemon/BUILD.gn
index e99e476..e298889d 100644
--- a/chromeos/components/cdm_factory_daemon/BUILD.gn
+++ b/chromeos/components/cdm_factory_daemon/BUILD.gn
@@ -27,6 +27,7 @@
   sources = [
     "cdm_storage_adapter.cc",
     "cdm_storage_adapter.h",
+    "chromeos_cdm_context.h",
     "chromeos_cdm_factory.cc",
     "chromeos_cdm_factory.h",
     "content_decryption_module_adapter.cc",
diff --git a/chromeos/components/cdm_factory_daemon/cdm_factory_daemon_proxy.cc b/chromeos/components/cdm_factory_daemon/cdm_factory_daemon_proxy.cc
index 2a24179..65a488e 100644
--- a/chromeos/components/cdm_factory_daemon/cdm_factory_daemon_proxy.cc
+++ b/chromeos/components/cdm_factory_daemon/cdm_factory_daemon_proxy.cc
@@ -98,6 +98,20 @@
   OutputProtectionImpl::Create(std::move(output_protection));
 }
 
+void CdmFactoryDaemonProxy::GetHwConfigData(GetHwConfigDataCallback callback) {
+  DCHECK(mojo_task_runner_->RunsTasksInCurrentSequence());
+  DVLOG(1) << "CdmFactoryDaemonProxy::GetHwConfigData called";
+  if (daemon_remote_.is_bound()) {
+    DVLOG(1) << "CdmFactoryDaemon mojo connection already exists, re-use it";
+    ProxyGetHwConfigData(std::move(callback));
+    return;
+  }
+
+  EstablishDaemonConnection(
+      base::BindOnce(&CdmFactoryDaemonProxy::ProxyGetHwConfigData,
+                     base::Unretained(this), std::move(callback)));
+}
+
 void CdmFactoryDaemonProxy::SendDBusRequest(base::ScopedFD fd,
                                             base::OnceClosure callback) {
   chromeos::CdmFactoryDaemonClient::Get()->BootstrapMojoConnection(
@@ -186,6 +200,16 @@
                                    std::move(output_protection));
 }
 
+void CdmFactoryDaemonProxy::ProxyGetHwConfigData(
+    GetHwConfigDataCallback callback) {
+  if (!daemon_remote_ || !daemon_remote_.is_bound()) {
+    LOG(ERROR) << "daemon_remote_ interface is not connected";
+    std::move(callback).Run(false, std::vector<uint8_t>());
+    return;
+  }
+  daemon_remote_->GetHwConfigData(std::move(callback));
+}
+
 // static
 CdmFactoryDaemonProxy& CdmFactoryDaemonProxy::GetInstance() {
   static base::NoDestructor<CdmFactoryDaemonProxy> instance;
diff --git a/chromeos/components/cdm_factory_daemon/cdm_factory_daemon_proxy.h b/chromeos/components/cdm_factory_daemon/cdm_factory_daemon_proxy.h
index de2b0f5..6204e4e 100644
--- a/chromeos/components/cdm_factory_daemon/cdm_factory_daemon_proxy.h
+++ b/chromeos/components/cdm_factory_daemon/cdm_factory_daemon_proxy.h
@@ -54,6 +54,7 @@
       override;
   void GetOutputProtection(mojo::PendingReceiver<cdm::mojom::OutputProtection>
                                output_protection) override;
+  void GetHwConfigData(GetHwConfigDataCallback callback) override;
 
  private:
   void SendDBusRequest(base::ScopedFD fd, base::OnceClosure callback);
@@ -66,6 +67,7 @@
       mojo::PendingRemote<arc::mojom::ProtectedBufferManager>
           protected_buffer_manager,
       mojo::PendingRemote<cdm::mojom::OutputProtection> output_protection);
+  void ProxyGetHwConfigData(GetHwConfigDataCallback callback);
   void OnGpuMojoConnectionError();
   void OnDaemonMojoConnectionError();
   void BindReceiver(mojo::PendingReceiver<CdmFactoryDaemon> receiver);
diff --git a/chromeos/components/cdm_factory_daemon/chromeos_cdm_context.h b/chromeos/components/cdm_factory_daemon/chromeos_cdm_context.h
new file mode 100644
index 0000000..de4d061
--- /dev/null
+++ b/chromeos/components/cdm_factory_daemon/chromeos_cdm_context.h
@@ -0,0 +1,42 @@
+// 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 CHROMEOS_COMPONENTS_CDM_FACTORY_DAEMON_CHROMEOS_CDM_CONTEXT_H_
+#define CHROMEOS_COMPONENTS_CDM_FACTORY_DAEMON_CHROMEOS_CDM_CONTEXT_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "media/base/decryptor.h"
+
+namespace media {
+class DecryptConfig;
+}
+
+namespace chromeos {
+
+// Interface for ChromeOS CDM Factory Daemon specific extensions to the
+// CdmContext interface.
+class ChromeOsCdmContext {
+ public:
+  ChromeOsCdmContext() = default;
+
+  using GetHwKeyDataCB =
+      base::OnceCallback<void(media::Decryptor::Status status,
+                              const std::vector<uint8_t>& key_data)>;
+
+  // Gets the HW specific key information for the key specified in
+  // |decrypt_config| and returns it via |callback|.
+  virtual void GetHwKeyData(const media::DecryptConfig* decrypt_config,
+                            const std::vector<uint8_t>& hw_identifier,
+                            GetHwKeyDataCB callback) = 0;
+
+ protected:
+  virtual ~ChromeOsCdmContext() = default;
+};
+
+}  // namespace chromeos
+
+#endif  // CHROMEOS_COMPONENTS_CDM_FACTORY_DAEMON_CHROMEOS_CDM_CONTEXT_H_
\ No newline at end of file
diff --git a/chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.cc b/chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.cc
index b9d1c91..f977aff 100644
--- a/chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.cc
+++ b/chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.cc
@@ -29,11 +29,30 @@
   return *remote;
 }
 
-// This holds the PendingRemote until we can bind it on the proper thread.
-mojo::PendingRemote<cdm::mojom::CdmFactoryDaemon>& GetBrowserProxy() {
-  static base::NoDestructor<mojo::PendingRemote<cdm::mojom::CdmFactoryDaemon>>
-      browser_proxy;
-  return *browser_proxy;
+// This holds the task runner we are bound to.
+scoped_refptr<base::SequencedTaskRunner>& GetFactoryTaskRunner() {
+  static base::NoDestructor<scoped_refptr<base::SequencedTaskRunner>> runner;
+  return *runner;
+}
+
+void CreateFactoryOnTaskRunner(
+    const std::string& key_system,
+    cdm::mojom::CdmFactoryDaemon::CreateFactoryCallback callback) {
+  GetCdmFactoryDaemonRemote()->CreateFactory(key_system, std::move(callback));
+}
+
+void CreateFactoryCallback(
+    scoped_refptr<base::SingleThreadTaskRunner> runner,
+    cdm::mojom::CdmFactoryDaemon::CreateFactoryCallback callback,
+    mojo::PendingRemote<cdm::mojom::CdmFactory> remote_factory) {
+  runner->PostTask(FROM_HERE, base::BindOnce(std::move(callback),
+                                             std::move(remote_factory)));
+}
+
+void GetOutputProtectionOnTaskRunner(
+    mojo::PendingReceiver<cdm::mojom::OutputProtection> output_protection) {
+  GetCdmFactoryDaemonRemote()->GetOutputProtection(
+      std::move(output_protection));
 }
 
 }  // namespace
@@ -51,10 +70,9 @@
 ChromeOsCdmFactory::GetCdmFactoryDaemonReceiver() {
   mojo::PendingRemote<chromeos::cdm::mojom::CdmFactoryDaemon> browser_proxy;
   auto receiver = browser_proxy.InitWithNewPipeAndPassReceiver();
+  GetCdmFactoryDaemonRemote().Bind(std::move(browser_proxy));
 
-  // This does not get called from the mojo thread we will be using, so hold
-  // onto it and then bind it when we get the first call.
-  GetBrowserProxy() = std::move(browser_proxy);
+  GetFactoryTaskRunner() = base::SequencedTaskRunnerHandle::Get();
   return receiver;
 }
 
@@ -84,6 +102,17 @@
       std::move(cdm_created_cb)));
 }
 
+// static
+void ChromeOsCdmFactory::GetHwConfigData(GetHwConfigDataCB callback) {
+  if (!GetFactoryTaskRunner()->RunsTasksInCurrentSequence()) {
+    GetFactoryTaskRunner()->PostTask(
+        FROM_HERE, base::BindOnce(&ChromeOsCdmFactory::GetHwConfigData,
+                                  std::move(callback)));
+    return;
+  }
+  GetCdmFactoryDaemonRemote()->GetHwConfigData(std::move(callback));
+}
+
 void ChromeOsCdmFactory::OnVerifiedAccessEnabled(
     const std::string& key_system,
     const media::CdmConfig& cdm_config,
@@ -101,23 +130,23 @@
                                   "Verified Access is disabled."));
     return;
   }
-  // This tests if it is bound already.
-  if (!GetCdmFactoryDaemonRemote()) {
-    DCHECK(GetBrowserProxy());
-    DVLOG(1) << "Binding the CdmFactoryDaemon browser proxy";
-    GetCdmFactoryDaemonRemote().Bind(std::move(GetBrowserProxy()));
-  }
-
   // If we haven't retrieved the remote CDM factory, do that first.
-  if (!remote_factory_.is_bound()) {
-    // Now invoke the call to create the Mojo interface for the CDM factory.
-    GetCdmFactoryDaemonRemote()->CreateFactory(
-        key_system,
-        base::BindOnce(&ChromeOsCdmFactory::OnCreateFactory,
-                       weak_factory_.GetWeakPtr(), cdm_config,
-                       session_message_cb, session_closed_cb,
-                       session_keys_change_cb, session_expiration_update_cb,
-                       std::move(cdm_created_cb)));
+  if (!remote_factory_) {
+    // Now invoke the call to create the Mojo interface for the CDM factory. We
+    // need to invoke the CreateFactory call on the factory task runner, but
+    // we then need to process the callback on the current runner, so there's a
+    // few layers of indirection here.
+    GetFactoryTaskRunner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            &CreateFactoryOnTaskRunner, key_system,
+            base::BindOnce(
+                &CreateFactoryCallback, base::ThreadTaskRunnerHandle::Get(),
+                base::BindOnce(
+                    &ChromeOsCdmFactory::OnCreateFactory,
+                    weak_factory_.GetWeakPtr(), cdm_config, session_message_cb,
+                    session_closed_cb, session_keys_change_cb,
+                    session_expiration_update_cb, std::move(cdm_created_cb)))));
     return;
   }
 
@@ -192,8 +221,11 @@
 
   // Create the OutputProtection interface to pass to the CDM.
   mojo::PendingRemote<cdm::mojom::OutputProtection> output_protection_remote;
-  GetCdmFactoryDaemonRemote()->GetOutputProtection(
-      output_protection_remote.InitWithNewPipeAndPassReceiver());
+  GetFactoryTaskRunner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &GetOutputProtectionOnTaskRunner,
+          output_protection_remote.InitWithNewPipeAndPassReceiver()));
 
   // Now create the remote CDM instance that links everything up.
   remote_factory_->CreateCdm(cdm->GetClientInterface(),
diff --git a/chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.h b/chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.h
index ce41d36..70fe4ae9 100644
--- a/chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.h
+++ b/chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.h
@@ -5,8 +5,12 @@
 #ifndef CHROMEOS_COMPONENTS_CDM_FACTORY_DAEMON_CHROMEOS_CDM_FACTORY_H_
 #define CHROMEOS_COMPONENTS_CDM_FACTORY_DAEMON_CHROMEOS_CDM_FACTORY_H_
 
+#include <vector>
+
+#include "base/callback.h"
 #include "base/component_export.h"
 #include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
 #include "chromeos/components/cdm_factory_daemon/mojom/cdm_factory_daemon.mojom.h"
 #include "media/base/cdm_config.h"
 #include "media/base/cdm_factory.h"
@@ -48,6 +52,13 @@
       const media::SessionExpirationUpdateCB& session_expiration_update_cb,
       media::CdmCreatedCB cdm_created_cb) override;
 
+  using GetHwConfigDataCB =
+      base::OnceCallback<void(bool success,
+                              const std::vector<uint8_t>& config_data)>;
+  // Used to get hardware specific configuration data from the daemon to be used
+  // for setting up decrypt+decode in the GPU.
+  static void GetHwConfigData(GetHwConfigDataCB callback);
+
  private:
   void OnVerifiedAccessEnabled(
       const std::string& key_system,
diff --git a/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter.cc b/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter.cc
index 4476f93..929503f8 100644
--- a/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter.cc
+++ b/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/bind.h"
 #include "base/time/time.h"
 #include "media/base/cdm_promise.h"
 #include "media/base/decoder_buffer.h"
@@ -251,6 +252,37 @@
   return this;
 }
 
+ChromeOsCdmContext* ContentDecryptionModuleAdapter::GetChromeOsCdmContext() {
+  return this;
+}
+
+void ContentDecryptionModuleAdapter::GetHwKeyData(
+    const media::DecryptConfig* decrypt_config,
+    const std::vector<uint8_t>& hw_identifier,
+    GetHwKeyDataCB callback) {
+  // This can get called from decoder threads or mojo threads, so we may need
+  // to repost the task.
+  if (!mojo_task_runner_->RunsTasksInCurrentSequence()) {
+    mojo_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&ContentDecryptionModuleAdapter::GetHwKeyData,
+                                  weak_factory_.GetWeakPtr(), decrypt_config,
+                                  hw_identifier, std::move(callback)));
+    return;
+  }
+  if (!cros_cdm_remote_) {
+    std::move(callback).Run(media::Decryptor::Status::kError,
+                            std::vector<uint8_t>());
+    return;
+  }
+  auto cros_decrypt_config = cdm::mojom::DecryptConfig::New();
+  cros_decrypt_config->key_id = decrypt_config->key_id();
+  cros_decrypt_config->iv = decrypt_config->iv();
+  cros_decrypt_config->encryption_scheme = decrypt_config->encryption_scheme();
+
+  cros_cdm_remote_->GetHwKeyData(std::move(cros_decrypt_config), hw_identifier,
+                                 std::move(callback));
+}
+
 void ContentDecryptionModuleAdapter::OnSessionMessage(
     const std::string& session_id,
     media::CdmMessageType message_type,
diff --git a/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter.h b/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter.h
index 6537792..df09013 100644
--- a/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter.h
+++ b/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter.h
@@ -12,6 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
 #include "chromeos/components/cdm_factory_daemon/cdm_storage_adapter.h"
+#include "chromeos/components/cdm_factory_daemon/chromeos_cdm_context.h"
 #include "chromeos/components/cdm_factory_daemon/mojom/content_decryption_module.mojom.h"
 #include "media/base/callback_registry.h"
 #include "media/base/cdm_context.h"
@@ -19,6 +20,7 @@
 #include "media/base/cdm_promise_adapter.h"
 #include "media/base/cdm_session_tracker.h"
 #include "media/base/content_decryption_module.h"
+#include "media/base/decrypt_config.h"
 #include "media/base/decryptor.h"
 #include "mojo/public/cpp/bindings/associated_receiver.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
@@ -40,6 +42,7 @@
     : public cdm::mojom::ContentDecryptionModuleClient,
       public media::ContentDecryptionModule,
       public media::CdmContext,
+      public chromeos::ChromeOsCdmContext,
       public media::Decryptor {
  public:
   ContentDecryptionModuleAdapter(
@@ -89,6 +92,12 @@
   std::unique_ptr<media::CallbackRegistration> RegisterEventCB(
       EventCB event_cb) override;
   Decryptor* GetDecryptor() override;
+  ChromeOsCdmContext* GetChromeOsCdmContext() override;
+
+  // chromeos::ChromeOsCdmContext:
+  void GetHwKeyData(const media::DecryptConfig* decrypt_config,
+                    const std::vector<uint8_t>& hw_identifier,
+                    GetHwKeyDataCB callback) override;
 
   // cdm::mojom::ContentDecryptionModuleClient:
   void OnSessionMessage(const std::string& session_id,
diff --git a/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter_unittest.cc b/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter_unittest.cc
index 8417658..94669059 100644
--- a/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter_unittest.cc
+++ b/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter_unittest.cc
@@ -86,6 +86,11 @@
               (const std::vector<uint8_t>&,
                cdm::mojom::DecryptConfigPtr,
                DecryptCallback));
+  MOCK_METHOD(void,
+              GetHwKeyData,
+              (cdm::mojom::DecryptConfigPtr,
+               const std::vector<uint8_t>&,
+               GetHwKeyDataCallback callback));
 
  private:
   mojo::AssociatedReceiver<ContentDecryptionModule> receiver_{this};
diff --git a/chromeos/components/cdm_factory_daemon/mojom/BUILD.gn b/chromeos/components/cdm_factory_daemon/mojom/BUILD.gn
index 65868985f..1740c865 100644
--- a/chromeos/components/cdm_factory_daemon/mojom/BUILD.gn
+++ b/chromeos/components/cdm_factory_daemon/mojom/BUILD.gn
@@ -22,10 +22,6 @@
     {
       types = [
         {
-          mojom = "chromeos.cdm.mojom.CdmKeyStatus"
-          cpp = "::media::CdmKeyInformation::KeyStatus"
-        },
-        {
           mojom = "chromeos.cdm.mojom.CdmMessageType"
           cpp = "::media::CdmMessageType"
         },
diff --git a/chromeos/components/cdm_factory_daemon/mojom/cdm_factory_daemon.mojom b/chromeos/components/cdm_factory_daemon/mojom/cdm_factory_daemon.mojom
index 6969778..86a834e 100644
--- a/chromeos/components/cdm_factory_daemon/mojom/cdm_factory_daemon.mojom
+++ b/chromeos/components/cdm_factory_daemon/mojom/cdm_factory_daemon.mojom
@@ -9,7 +9,7 @@
 // interface can also be used to connect directly to the OEMCrypto
 // implementation for ARC.
 
-// Next MinVersion: 2
+// Next MinVersion: 3
 
 module chromeos.cdm.mojom;
 
@@ -38,7 +38,7 @@
               pending_remote<OutputProtection> output_protection);
 };
 
-// Next Method ID: 4
+// Next Method ID: 5
 // Used for bootstrapping the connection between Chrome and the daemon, then
 // methods can be invoked to obtain interfaces to perform CDM or OEMCrypto
 // operations.
@@ -67,4 +67,10 @@
   // CreateCdm call in CdmFactory.
   [MinVersion=1]
   GetOutputProtection@3(pending_receiver<OutputProtection> output_protection);
+
+  // Returns binary configuration data used for setting up HW decrypt+decode. If
+  // successful, |success| will be true and |config_data| will be valid.
+  // Otherwise |success| will be false and |config_data| should not be used.
+  [MinVersion=2]
+  GetHwConfigData@4() => (bool success, array<uint8> config_data);
 };
diff --git a/chromeos/components/cdm_factory_daemon/mojom/content_decryption_module.mojom b/chromeos/components/cdm_factory_daemon/mojom/content_decryption_module.mojom
index 039e7e1..d8797e5 100644
--- a/chromeos/components/cdm_factory_daemon/mojom/content_decryption_module.mojom
+++ b/chromeos/components/cdm_factory_daemon/mojom/content_decryption_module.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Next MinVersion: 1
+// Next MinVersion: 2
 
 module chromeos.cdm.mojom;
 
@@ -132,7 +132,7 @@
   kFailure
 };
 
-// Next Method ID: 9
+// Next Method ID: 10
 interface ContentDecryptionModule {
   // Provides a server certificate to be used to encrypt messages to the
   // license server.
@@ -178,6 +178,14 @@
   // should be done before making this call.
   Decrypt@8(array<uint8> encrypted_data, DecryptConfig decrypt_config)
       => (DecryptStatus status, array<uint8> decrypted_data);
+
+  // Returns HW information for a specific key that is passed along as part of
+  // HW decrypt+decode. |hw_identifier| is specific to the HW implementation
+  // to allow it to correlate the decode session with the context to get the key
+  // from.
+  [MinVersion=1] GetHwKeyData@9(DecryptConfig decrypt_config,
+                                array<uint8> hw_identifier) =>
+      (DecryptStatus status, array<uint8> key_data);
 };
 
 // Session callbacks. See media/base/content_decryption_module.h for details.
diff --git a/chromeos/components/help_app_ui/help_app_ui.cc b/chromeos/components/help_app_ui/help_app_ui.cc
index 228f771b..e7a65c9 100644
--- a/chromeos/components/help_app_ui/help_app_ui.cc
+++ b/chromeos/components/help_app_ui/help_app_ui.cc
@@ -12,7 +12,6 @@
 #include "chromeos/components/local_search_service/local_search_service_proxy.h"
 #include "chromeos/components/local_search_service/local_search_service_proxy_factory.h"
 #include "chromeos/components/local_search_service/mojom/types.mojom.h"
-#include "chromeos/components/web_applications/manifest_request_filter.h"
 #include "chromeos/grit/chromeos_help_app_resources.h"
 #include "chromeos/strings/grit/chromeos_strings.h"
 #include "components/content_settings/core/common/content_settings_types.h"
diff --git a/chromeos/components/media_app_ui/media_app_ui.cc b/chromeos/components/media_app_ui/media_app_ui.cc
index f30cc518..5e4e2d01a 100644
--- a/chromeos/components/media_app_ui/media_app_ui.cc
+++ b/chromeos/components/media_app_ui/media_app_ui.cc
@@ -9,7 +9,6 @@
 #include "chromeos/components/media_app_ui/media_app_guest_ui.h"
 #include "chromeos/components/media_app_ui/media_app_page_handler.h"
 #include "chromeos/components/media_app_ui/url_constants.h"
-#include "chromeos/components/web_applications/manifest_request_filter.h"
 #include "chromeos/grit/chromeos_media_app_bundle_resources.h"
 #include "chromeos/grit/chromeos_media_app_resources.h"
 #include "chromeos/strings/grit/chromeos_strings.h"
diff --git a/chromeos/components/phonehub/fake_notification_access_manager.cc b/chromeos/components/phonehub/fake_notification_access_manager.cc
index 4e558d2f..8503773 100644
--- a/chromeos/components/phonehub/fake_notification_access_manager.cc
+++ b/chromeos/components/phonehub/fake_notification_access_manager.cc
@@ -26,6 +26,19 @@
   return has_access_been_granted_;
 }
 
+bool FakeNotificationAccessManager::HasNotificationSetupUiBeenDismissed()
+    const {
+  return has_notification_setup_ui_been_dismissed_;
+}
+
+void FakeNotificationAccessManager::DismissSetupRequiredUi() {
+  has_notification_setup_ui_been_dismissed_ = true;
+}
+
+void FakeNotificationAccessManager::ResetHasNotificationSetupUiBeenDismissed() {
+  has_notification_setup_ui_been_dismissed_ = false;
+}
+
 void FakeNotificationAccessManager::SetNotificationSetupOperationStatus(
     NotificationAccessSetupOperation::Status new_status) {
   if (new_status ==
diff --git a/chromeos/components/phonehub/fake_notification_access_manager.h b/chromeos/components/phonehub/fake_notification_access_manager.h
index 8da2ea76..a0a2af3 100644
--- a/chromeos/components/phonehub/fake_notification_access_manager.h
+++ b/chromeos/components/phonehub/fake_notification_access_manager.h
@@ -23,9 +23,14 @@
 
   // NotificationAccessManager:
   bool HasAccessBeenGranted() const override;
+  bool HasNotificationSetupUiBeenDismissed() const override;
+  void DismissSetupRequiredUi() override;
+
+  void ResetHasNotificationSetupUiBeenDismissed();
 
  private:
   bool has_access_been_granted_;
+  bool has_notification_setup_ui_been_dismissed_ = false;
 };
 
 }  // namespace phonehub
diff --git a/chromeos/components/phonehub/notification_access_manager.h b/chromeos/components/phonehub/notification_access_manager.h
index 6096108a..14ee5f7 100644
--- a/chromeos/components/phonehub/notification_access_manager.h
+++ b/chromeos/components/phonehub/notification_access_manager.h
@@ -41,6 +41,11 @@
 
   virtual bool HasAccessBeenGranted() const = 0;
 
+  virtual bool HasNotificationSetupUiBeenDismissed() const = 0;
+
+  // Disables the ability to show the banner within the PhoneHub UI.
+  virtual void DismissSetupRequiredUi() = 0;
+
   // Starts an attempt to enable the notification access. |delegate| will be
   // updated with the status of the flow as long as the operation object
   // returned by this function remains instantiated.
diff --git a/chromeos/components/phonehub/notification_access_manager_impl.cc b/chromeos/components/phonehub/notification_access_manager_impl.cc
index 54220ca..018d7b0a 100644
--- a/chromeos/components/phonehub/notification_access_manager_impl.cc
+++ b/chromeos/components/phonehub/notification_access_manager_impl.cc
@@ -18,6 +18,7 @@
 void NotificationAccessManagerImpl::RegisterPrefs(
     PrefRegistrySimple* registry) {
   registry->RegisterBooleanPref(prefs::kNotificationAccessGranted, false);
+  registry->RegisterBooleanPref(prefs::kHasDismissedSetupRequiredUi, false);
 }
 
 NotificationAccessManagerImpl::NotificationAccessManagerImpl(
@@ -40,6 +41,15 @@
   feature_status_provider_->RemoveObserver(this);
 }
 
+bool NotificationAccessManagerImpl::HasNotificationSetupUiBeenDismissed()
+    const {
+  return pref_service_->GetBoolean(prefs::kHasDismissedSetupRequiredUi);
+}
+
+void NotificationAccessManagerImpl::DismissSetupRequiredUi() {
+  pref_service_->SetBoolean(prefs::kHasDismissedSetupRequiredUi, true);
+}
+
 bool NotificationAccessManagerImpl::HasAccessBeenGranted() const {
   return pref_service_->GetBoolean(prefs::kNotificationAccessGranted);
 }
diff --git a/chromeos/components/phonehub/notification_access_manager_impl.h b/chromeos/components/phonehub/notification_access_manager_impl.h
index be6541f..ed57552 100644
--- a/chromeos/components/phonehub/notification_access_manager_impl.h
+++ b/chromeos/components/phonehub/notification_access_manager_impl.h
@@ -43,6 +43,9 @@
   void SetHasAccessBeenGrantedInternal(bool has_access_been_granted) override;
   void OnSetupRequested() override;
 
+  bool HasNotificationSetupUiBeenDismissed() const override;
+  void DismissSetupRequiredUi() override;
+
   // FeatureStatusProvider::Observer:
   void OnFeatureStatusChanged() override;
 
diff --git a/chromeos/components/phonehub/notification_access_manager_impl_unittest.cc b/chromeos/components/phonehub/notification_access_manager_impl_unittest.cc
index 0f5b80b..1606f67 100644
--- a/chromeos/components/phonehub/notification_access_manager_impl_unittest.cc
+++ b/chromeos/components/phonehub/notification_access_manager_impl_unittest.cc
@@ -93,6 +93,12 @@
     EXPECT_EQ(expected_value, manager_->HasAccessBeenGranted());
   }
 
+  bool HasNotificationSetupUiBeenDismissed() {
+    return manager_->HasNotificationSetupUiBeenDismissed();
+  }
+
+  void DismissSetupRequiredUi() { manager_->DismissSetupRequiredUi(); }
+
   std::unique_ptr<NotificationAccessSetupOperation> StartSetupOperation() {
     return manager_->AttemptNotificationSetup(&fake_delegate_);
   }
@@ -134,6 +140,30 @@
   std::unique_ptr<NotificationAccessManager> manager_;
 };
 
+TEST_F(NotificationAccessManagerImplTest, ShouldShowSetupRequiredUi) {
+  // Notification setup is not dismissed initially even when access has been
+  // granted.
+  Initialize(/*initial_has_access_been_granted=*/true);
+  EXPECT_FALSE(HasNotificationSetupUiBeenDismissed());
+
+  // Notification setup is not dismissed initially when access has not been
+  // granted.
+  Initialize(/*initial_has_access_been_granted=*/false);
+  EXPECT_FALSE(HasNotificationSetupUiBeenDismissed());
+
+  // Simlulate dismissal of UI.
+  DismissSetupRequiredUi();
+  EXPECT_TRUE(HasNotificationSetupUiBeenDismissed());
+
+  // Dismissal value is persisted on initialization with access not granted.
+  Initialize(/*initial_has_access_been_granted=*/false);
+  EXPECT_TRUE(HasNotificationSetupUiBeenDismissed());
+
+  // Dismissal value is persisted on initialization with access granted.
+  Initialize(/*initial_has_access_been_granted=*/true);
+  EXPECT_TRUE(HasNotificationSetupUiBeenDismissed());
+}
+
 TEST_F(NotificationAccessManagerImplTest, InitiallyGranted) {
   Initialize(/*initial_has_access_been_granted=*/true);
   VerifyNotificationAccessGrantedState(/*expected_value=*/true);
diff --git a/chromeos/components/phonehub/pref_names.cc b/chromeos/components/phonehub/pref_names.cc
index 0170d0e..663b538 100644
--- a/chromeos/components/phonehub/pref_names.cc
+++ b/chromeos/components/phonehub/pref_names.cc
@@ -21,6 +21,11 @@
 const char kIsAwaitingVerifiedHost[] =
     "cros.phonehub.is_awaiting_verified_host";
 
+// Whether the Notification access setup banner in the PhoneHub UI has
+// been dismissed.
+const char kHasDismissedSetupRequiredUi[] =
+    "cros.phonehub.has_dismissed_setup_required_ui";
+
 }  // namespace prefs
 }  // namespace phonehub
 }  // namespace chromeos
diff --git a/chromeos/components/phonehub/pref_names.h b/chromeos/components/phonehub/pref_names.h
index c43d09a..1ad1141 100644
--- a/chromeos/components/phonehub/pref_names.h
+++ b/chromeos/components/phonehub/pref_names.h
@@ -12,6 +12,7 @@
 extern const char kNotificationAccessGranted[];
 extern const char kHasDismissedUiAfterCompletingOnboarding[];
 extern const char kIsAwaitingVerifiedHost[];
+extern const char kHasDismissedSetupRequiredUi[];
 
 }  // namespace prefs
 }  // namespace phonehub
diff --git a/chromeos/components/print_management/print_management_ui.cc b/chromeos/components/print_management/print_management_ui.cc
index 86ef5ec..8f732118 100644
--- a/chromeos/components/print_management/print_management_ui.cc
+++ b/chromeos/components/print_management/print_management_ui.cc
@@ -7,7 +7,6 @@
 #include "base/memory/ptr_util.h"
 #include "chromeos/components/print_management/mojom/printing_manager.mojom.h"
 #include "chromeos/components/print_management/url_constants.h"
-#include "chromeos/components/web_applications/manifest_request_filter.h"
 #include "chromeos/grit/chromeos_print_management_resources.h"
 #include "chromeos/grit/chromeos_print_management_resources_map.h"
 #include "chromeos/strings/grit/chromeos_strings.h"
diff --git a/chromeos/components/quick_answers/understanding/intent_generator.cc b/chromeos/components/quick_answers/understanding/intent_generator.cc
index 319e50f1..d8a3a40c 100644
--- a/chromeos/components/quick_answers/understanding/intent_generator.cc
+++ b/chromeos/components/quick_answers/understanding/intent_generator.cc
@@ -26,7 +26,7 @@
 
 // TODO(llin): Finalize on the threshold based on user feedback.
 constexpr int kUnitConversionIntentAndSelectionLengthDiffThreshold = 5;
-constexpr int kTranslationTextLengthThreshold = 50;
+constexpr int kTranslationTextLengthThreshold = 100;
 constexpr int kDefinitionIntentAndSelectionLengthDiffThreshold = 2;
 
 // TODO(b/169370175): Remove the temporary invalid set after we ramp up to v2
@@ -144,20 +144,11 @@
   }
 
   if (text_classifier_) {
-    TextAnnotationRequestPtr text_annotation_request =
-        machine_learning::mojom::TextAnnotationRequest::New();
-
-    // TODO(b/159664194): There is a issue with text classifier that some
-    // capitalized words are not annotated properly. Convert the text to lower
-    // case for now. Clean up after the issue is fixed.
-    text_annotation_request->text = base::UTF16ToUTF8(
-        base::i18n::ToLower(base::UTF8ToUTF16(request.selected_text)));
-    text_annotation_request->default_locales =
-        request.context.device_properties.language;
-
-    text_classifier_->Annotate(
-        std::move(text_annotation_request),
-        base::BindOnce(&IntentGenerator::AnnotationCallback,
+    text_classifier_->FindLanguages(
+        !request.context.surrounding_text.empty()
+            ? request.context.surrounding_text
+            : request.selected_text,
+        base::BindOnce(&IntentGenerator::FindLanguagesCallback,
                        weak_factory_.GetWeakPtr(), request));
   }
 }
@@ -175,8 +166,8 @@
       // Skip the entity for definition annonation.
       if (it->second == IntentType::kDictionary &&
           ShouldSkipDefinition(request.selected_text)) {
-        // Fallback to language detection for generating translation intent.
-        MaybeGenerateTranslationIntent(request);
+        std::move(complete_callback_)
+            .Run(IntentInfo(request.selected_text, IntentType::kUnknown));
         return;
       }
       std::move(complete_callback_)
@@ -185,30 +176,41 @@
       return;
     }
   }
-  // Fallback to language detection for generating translation intent.
-  MaybeGenerateTranslationIntent(request);
+  std::move(complete_callback_)
+      .Run(IntentInfo(request.selected_text, IntentType::kUnknown));
 }
 
 void IntentGenerator::FindLanguagesCallback(
     const QuickAnswersRequest& request,
     std::vector<machine_learning::mojom::TextLanguagePtr> languages) {
-  auto intent_type = IntentType::kUnknown;
   // TODO(b/150034512): Take confidence level into consideration.
-  if (languages.empty() ||
-      languages.front()->locale == request.context.device_properties.language) {
-    std::move(complete_callback_)
-        .Run(IntentInfo(request.selected_text, IntentType::kUnknown));
+  if (!languages.empty() &&
+      !request.context.device_properties.language.empty() &&
+      languages.front()->locale != request.context.device_properties.language) {
+    MaybeGenerateTranslationIntent(request, languages.front()->locale);
     return;
   }
-  intent_type = IntentType::kTranslation;
-  std::move(complete_callback_)
-      .Run(IntentInfo(request.selected_text, intent_type,
-                      languages.front()->locale,
-                      request.context.device_properties.language));
+
+  TextAnnotationRequestPtr text_annotation_request =
+      machine_learning::mojom::TextAnnotationRequest::New();
+
+  // TODO(b/159664194): There is a issue with text classifier that some
+  // capitalized words are not annotated properly. Convert the text to lower
+  // case for now. Clean up after the issue is fixed.
+  text_annotation_request->text = base::UTF16ToUTF8(
+      base::i18n::ToLower(base::UTF8ToUTF16(request.selected_text)));
+  text_annotation_request->default_locales =
+      request.context.device_properties.language;
+
+  text_classifier_->Annotate(
+      std::move(text_annotation_request),
+      base::BindOnce(&IntentGenerator::AnnotationCallback,
+                     weak_factory_.GetWeakPtr(), request));
 }
 
 void IntentGenerator::MaybeGenerateTranslationIntent(
-    const QuickAnswersRequest& request) {
+    const QuickAnswersRequest& request,
+    const std::string& detected_locale) {
   DCHECK(complete_callback_);
 
   if (!features::IsQuickAnswersTranslationEnabled()) {
@@ -226,14 +228,10 @@
     return;
   }
 
-  if (text_classifier_) {
-    text_classifier_->FindLanguages(
-        !request.context.surrounding_text.empty()
-            ? request.context.surrounding_text
-            : request.selected_text,
-        base::BindOnce(&IntentGenerator::FindLanguagesCallback,
-                       weak_factory_.GetWeakPtr(), request));
-  }
+  std::move(complete_callback_)
+      .Run(IntentInfo(request.selected_text, IntentType::kTranslation,
+                      detected_locale,
+                      request.context.device_properties.language));
 }
 
 }  // namespace quick_answers
diff --git a/chromeos/components/quick_answers/understanding/intent_generator.h b/chromeos/components/quick_answers/understanding/intent_generator.h
index fad51037..8fd06f4 100644
--- a/chromeos/components/quick_answers/understanding/intent_generator.h
+++ b/chromeos/components/quick_answers/understanding/intent_generator.h
@@ -54,7 +54,8 @@
       const QuickAnswersRequest& request,
       std::vector<machine_learning::mojom::TextLanguagePtr> languages);
 
-  void MaybeGenerateTranslationIntent(const QuickAnswersRequest& request);
+  void MaybeGenerateTranslationIntent(const QuickAnswersRequest& request,
+                                      const std::string& detected_locale);
 
   IntentGeneratorCallback complete_callback_;
   mojo::Remote<::chromeos::machine_learning::mojom::TextClassifier>
diff --git a/chromeos/components/quick_answers/understanding/intent_generator_unittest.cc b/chromeos/components/quick_answers/understanding/intent_generator_unittest.cc
index 0e0e63c..08e5a876 100644
--- a/chromeos/components/quick_answers/understanding/intent_generator_unittest.cc
+++ b/chromeos/components/quick_answers/understanding/intent_generator_unittest.cc
@@ -124,7 +124,8 @@
   QuickAnswersRequest request;
   request.selected_text =
       "Search the world's information, including webpages, images, videos and "
-      "more.";
+      "more. Google has many special features to help you find exactly what "
+      "you're looking ...";
   request.context.device_properties.language = "es";
   intent_generator_->GenerateIntent(request);
 
@@ -133,10 +134,43 @@
   EXPECT_EQ(IntentType::kUnknown, intent_info_.intent_type);
   EXPECT_EQ(
       "Search the world's information, including webpages, images, videos and "
-      "more.",
+      "more. Google has many special features to help you find exactly what "
+      "you're looking ...",
       intent_info_.intent_text);
 }
 
+TEST_F(IntentGeneratorTest, TranslationIntentWithAnnotation) {
+  QuickAnswersRequest request;
+  request.selected_text = "unfathomable";
+  request.context.device_properties.language = "es";
+
+  // Create the test annotations.
+  std::vector<TextEntityPtr> entities;
+  entities.emplace_back(
+      TextEntity::New("dictionary",             // Entity name.
+                      1.0,                      // Confidence score.
+                      TextEntityData::New()));  // Data extracted.
+
+  auto dictionary_annotation = TextAnnotation::New(0,   // Start offset.
+                                                   12,  // End offset.
+                                                   std::move(entities));
+
+  std::vector<TextAnnotationPtr> annotations;
+  annotations.push_back(dictionary_annotation->Clone());
+  std::vector<TextLanguagePtr> languages;
+  languages.push_back(DefaultLanguage());
+  UseFakeServiceConnection(annotations, languages);
+
+  intent_generator_->GenerateIntent(request);
+
+  task_environment_.RunUntilIdle();
+
+  EXPECT_EQ(IntentType::kTranslation, intent_info_.intent_type);
+  EXPECT_EQ("unfathomable", intent_info_.intent_text);
+  EXPECT_EQ("en", intent_info_.source_language);
+  EXPECT_EQ("es", intent_info_.target_language);
+}
+
 TEST_F(IntentGeneratorTest, TranslationIntentNotEnabled) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitWithFeatures(
diff --git a/chromeos/components/scanning/resources/app_icon_192.png b/chromeos/components/scanning/resources/app_icon_192.png
deleted file mode 100644
index 1419460f..0000000
--- a/chromeos/components/scanning/resources/app_icon_192.png
+++ /dev/null
Binary files differ
diff --git a/chromeos/components/scanning/resources/scanning_app_icon_128.png b/chromeos/components/scanning/resources/scanning_app_icon_128.png
new file mode 100644
index 0000000..40a6b11
--- /dev/null
+++ b/chromeos/components/scanning/resources/scanning_app_icon_128.png
Binary files differ
diff --git a/chromeos/components/scanning/resources/scanning_app_icon_16.png b/chromeos/components/scanning/resources/scanning_app_icon_16.png
new file mode 100644
index 0000000..3b3f59ae
--- /dev/null
+++ b/chromeos/components/scanning/resources/scanning_app_icon_16.png
Binary files differ
diff --git a/chromeos/components/scanning/resources/scanning_app_icon_192.png b/chromeos/components/scanning/resources/scanning_app_icon_192.png
new file mode 100644
index 0000000..9cf7869
--- /dev/null
+++ b/chromeos/components/scanning/resources/scanning_app_icon_192.png
Binary files differ
diff --git a/chromeos/components/scanning/resources/scanning_app_icon_256.png b/chromeos/components/scanning/resources/scanning_app_icon_256.png
new file mode 100644
index 0000000..83a36f1d
--- /dev/null
+++ b/chromeos/components/scanning/resources/scanning_app_icon_256.png
Binary files differ
diff --git a/chromeos/components/scanning/resources/scanning_app_icon_32.png b/chromeos/components/scanning/resources/scanning_app_icon_32.png
new file mode 100644
index 0000000..b4976fa
--- /dev/null
+++ b/chromeos/components/scanning/resources/scanning_app_icon_32.png
Binary files differ
diff --git a/chromeos/components/scanning/resources/scanning_app_icon_48.png b/chromeos/components/scanning/resources/scanning_app_icon_48.png
new file mode 100644
index 0000000..4040f1ec
--- /dev/null
+++ b/chromeos/components/scanning/resources/scanning_app_icon_48.png
Binary files differ
diff --git a/chromeos/components/scanning/resources/scanning_app_icon_64.png b/chromeos/components/scanning/resources/scanning_app_icon_64.png
new file mode 100644
index 0000000..00468e0
--- /dev/null
+++ b/chromeos/components/scanning/resources/scanning_app_icon_64.png
Binary files differ
diff --git a/chromeos/components/scanning/resources/scanning_app_resources.grd b/chromeos/components/scanning/resources/scanning_app_resources.grd
index 6e2df5e..7b3c360 100644
--- a/chromeos/components/scanning/resources/scanning_app_resources.grd
+++ b/chromeos/components/scanning/resources/scanning_app_resources.grd
@@ -28,7 +28,13 @@
       <include name="IDR_SCANNING_APP_RESOLUTION_SELECT_JS" file="${root_gen_dir}/chromeos/components/scanning/resources/resolution_select.js" use_base_dir="false" type="BINDATA"/>
       <include name="IDR_SCANNING_APP_SCAN_SETTINGS_SECTION_JS" file="${root_gen_dir}/chromeos/components/scanning/resources/scan_settings_section.js" use_base_dir="false" type="BINDATA"/>
       <include name="IDR_SCANNING_APP_THROBBER_CSS_JS" file="${root_gen_dir}/chromeos/components/scanning/resources/throbber_css.js" use_base_dir="false" type="BINDATA"/>
-      <include name="IDR_SCANNING_APP_ICON" file="app_icon_192.png" type="BINDATA" />
+      <include name="IDR_SCANNING_APP_ICON_16" file="scanning_app_icon_16.png" type="BINDATA" />
+      <include name="IDR_SCANNING_APP_ICON_32" file="scanning_app_icon_32.png" type="BINDATA" />
+      <include name="IDR_SCANNING_APP_ICON_48" file="scanning_app_icon_48.png" type="BINDATA" />
+      <include name="IDR_SCANNING_APP_ICON_64" file="scanning_app_icon_64.png" type="BINDATA" />
+      <include name="IDR_SCANNING_APP_ICON_128" file="scanning_app_icon_128.png" type="BINDATA" />
+      <include name="IDR_SCANNING_APP_ICON_192" file="scanning_app_icon_192.png" type="BINDATA" />
+      <include name="IDR_SCANNING_APP_ICON_256" file="scanning_app_icon_256.png" type="BINDATA" />
     </includes>
 
     <structures>
diff --git a/chromeos/components/security_token_pin/error_generator.cc b/chromeos/components/security_token_pin/error_generator.cc
index 2bbe4cd..e5cd352 100644
--- a/chromeos/components/security_token_pin/error_generator.cc
+++ b/chromeos/components/security_token_pin/error_generator.cc
@@ -4,6 +4,7 @@
 
 #include "chromeos/components/security_token_pin/error_generator.h"
 
+#include "base/i18n/message_formatter.h"
 #include "base/i18n/number_formatting.h"
 #include "chromeos/strings/grit/chromeos_strings.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -51,9 +52,9 @@
     return l10n_util::GetStringFUTF16(IDS_REQUEST_PIN_DIALOG_ATTEMPTS_LEFT,
                                       base::FormatNumber(attempts_left));
   }
-  return l10n_util::GetStringFUTF16(IDS_REQUEST_PIN_DIALOG_ERROR_ATTEMPTS,
-                                    error_message,
-                                    base::FormatNumber(attempts_left));
+  return base::i18n::MessageFormatter::FormatWithNumberedArgs(
+      l10n_util::GetStringUTF16(IDS_REQUEST_PIN_DIALOG_ERROR_ATTEMPTS),
+      attempts_left, error_message);
 }
 
 }  // namespace security_token_pin
diff --git a/chromeos/components/telemetry_extension_ui/diagnostics_service.cc b/chromeos/components/telemetry_extension_ui/diagnostics_service.cc
index c79d92f..369739c 100644
--- a/chromeos/components/telemetry_extension_ui/diagnostics_service.cc
+++ b/chromeos/components/telemetry_extension_ui/diagnostics_service.cc
@@ -64,12 +64,12 @@
           std::move(callback)));
 }
 
+// TODO(b/171327161): Remove |low_mah| and |high_mah| from this routine.
 void DiagnosticsService::RunBatteryCapacityRoutine(
     uint32_t low_mah,
     uint32_t high_mah,
     RunBatteryCapacityRoutineCallback callback) {
   GetService()->RunBatteryCapacityRoutine(
-      low_mah, high_mah,
       base::BindOnce(
           [](health::mojom::DiagnosticsService::
                  RunBatteryCapacityRoutineCallback callback,
@@ -79,12 +79,13 @@
           std::move(callback)));
 }
 
+// TODO(b/171327161): Remove |maximum_cycle_count| and
+// |percent_battery_wear_allowed| from this routine.
 void DiagnosticsService::RunBatteryHealthRoutine(
     uint32_t maximum_cycle_count,
     uint32_t percent_battery_wear_allowed,
     RunBatteryHealthRoutineCallback callback) {
   GetService()->RunBatteryHealthRoutine(
-      maximum_cycle_count, percent_battery_wear_allowed,
       base::BindOnce(
           [](health::mojom::DiagnosticsService::RunBatteryHealthRoutineCallback
                  callback,
diff --git a/chromeos/components/web_applications/BUILD.gn b/chromeos/components/web_applications/BUILD.gn
index ad99ac2e..389cdde 100644
--- a/chromeos/components/web_applications/BUILD.gn
+++ b/chromeos/components/web_applications/BUILD.gn
@@ -5,11 +5,6 @@
 assert(is_chromeos, "These utils are Chrome OS only")
 
 static_library("web_applications") {
-  sources = [
-    "manifest_request_filter.cc",
-    "manifest_request_filter.h",
-  ]
-
   deps = [
     "//base",
     "//base:i18n",
diff --git a/chromeos/components/web_applications/manifest_request_filter.cc b/chromeos/components/web_applications/manifest_request_filter.cc
deleted file mode 100644
index c37053f..0000000
--- a/chromeos/components/web_applications/manifest_request_filter.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromeos/components/web_applications/manifest_request_filter.h"
-
-#include <string>
-
-#include "base/bind.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/public/browser/web_ui_data_source.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/base/template_expressions.h"
-
-namespace web_app {
-
-void SetManifestRequestFilter(content::WebUIDataSource* source,
-                              int manifest_idr,
-                              int name_ids) {
-  ui::TemplateReplacements replacements;
-  base::string16 name = l10n_util::GetStringUTF16(name_ids);
-  base::ReplaceChars(name, base::ASCIIToUTF16("\""), base::ASCIIToUTF16("\\\""),
-                     &name);
-  replacements["name"] = base::UTF16ToUTF8(name);
-
-  scoped_refptr<base::RefCountedMemory> bytes =
-      ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
-          manifest_idr);
-  base::StringPiece content(reinterpret_cast<const char*>(bytes->front()),
-                            bytes->size());
-  std::string response = ui::ReplaceTemplateExpressions(content, replacements);
-
-  source->SetRequestFilter(
-      base::BindRepeating(
-          [](const std::string& path) { return path == "manifest.json"; }),
-      base::BindRepeating(
-          [](const std::string& response, const std::string& path,
-             content::WebUIDataSource::GotDataCallback callback) {
-            std::string response_copy = response;
-            std::move(callback).Run(
-                base::RefCountedString::TakeString(&response_copy));
-          },
-          std::move(response)));
-}
-
-}  // namespace web_app
diff --git a/chromeos/components/web_applications/manifest_request_filter.h b/chromeos/components/web_applications/manifest_request_filter.h
deleted file mode 100644
index bb272fc..0000000
--- a/chromeos/components/web_applications/manifest_request_filter.h
+++ /dev/null
@@ -1,23 +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 CHROMEOS_COMPONENTS_WEB_APPLICATIONS_MANIFEST_REQUEST_FILTER_H_
-#define CHROMEOS_COMPONENTS_WEB_APPLICATIONS_MANIFEST_REQUEST_FILTER_H_
-
-namespace content {
-class WebUIDataSource;
-}
-
-namespace web_app {
-
-// Calls |source->SetRequestFilter()| to set up respones to requests for
-// "manifest.json" while replacing $i18nRaw{name} in the contents indicated by
-// |manifest_idr| with the name from |name_ids|.
-void SetManifestRequestFilter(content::WebUIDataSource* source,
-                              int manifest_idr,
-                              int name_ids);
-
-}  // namespace web_app
-
-#endif  // CHROMEOS_COMPONENTS_WEB_APPLICATIONS_MANIFEST_REQUEST_FILTER_H_
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc
index 6ff38bca..d071a86 100644
--- a/chromeos/constants/chromeos_features.cc
+++ b/chromeos/constants/chromeos_features.cc
@@ -144,11 +144,6 @@
 const base::Feature kBluetoothPhoneFilter{"BluetoothPhoneFilter",
                                           base::FEATURE_ENABLED_BY_DEFAULT};
 
-// If enabled, browser will notify Chrome OS audio server to register HFP 1.7
-// to BlueZ, which includes wideband speech feature.
-const base::Feature kBluetoothNextHandsfreeProfile{
-    "BluetoothNextHandsfreeProfile", base::FEATURE_ENABLED_BY_DEFAULT};
-
 // Enable or disables running the Camera App as a System Web App.
 const base::Feature kCameraSystemWebApp{"CameraSystemWebApp",
                                         base::FEATURE_DISABLED_BY_DEFAULT};
@@ -327,6 +322,11 @@
 const base::Feature kClipboardHistory{"ClipboardHistory",
                                       base::FEATURE_DISABLED_BY_DEFAULT};
 
+// If enabled, the clipboard nudge shown prefs will be reset at the start of
+// each new user session.
+const base::Feature kClipboardHistoryNudgeSessionReset{
+    "ClipboardHistoryNudgeSessionReset", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enables rendering html in Clipboard History only if an img or table tag is
 // present.
 const base::Feature kClipboardHistorySimpleRender{
@@ -730,6 +730,10 @@
          base::FeatureList::IsEnabled(kClipboardHistorySimpleRender);
 }
 
+bool IsClipboardHistoryNudgeSessionResetEnabled() {
+  return base::FeatureList::IsEnabled(kClipboardHistoryNudgeSessionReset);
+}
+
 bool IsClipboardHistorySimpleRenderEnabled() {
   return base::FeatureList::IsEnabled(kClipboardHistorySimpleRender);
 }
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h
index d522df9..4d53e63 100644
--- a/chromeos/constants/chromeos_features.h
+++ b/chromeos/constants/chromeos_features.h
@@ -80,8 +80,6 @@
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kBluetoothPhoneFilter;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
-extern const base::Feature kBluetoothNextHandsfreeProfile;
-COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kCameraSystemWebApp;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kCdmFactoryDaemon;
@@ -150,6 +148,8 @@
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kClipboardHistory;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
+extern const base::Feature kClipboardHistoryNudgeSessionReset;
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kClipboardHistorySimpleRender;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kEnableFilesAppCopyImage;
@@ -318,6 +318,8 @@
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsMinimumChromeVersionEnabled();
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsClipboardHistoryEnabled();
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
+bool IsClipboardHistoryNudgeSessionResetEnabled();
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 bool IsClipboardHistorySimpleRenderEnabled();
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsOobeScreensPriorityEnabled();
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsPhoneHubEnabled();
diff --git a/chromeos/constants/chromeos_pref_names.cc b/chromeos/constants/chromeos_pref_names.cc
index 15605ab..0a5f9268 100644
--- a/chromeos/constants/chromeos_pref_names.cc
+++ b/chromeos/constants/chromeos_pref_names.cc
@@ -113,5 +113,9 @@
 // Boolean pref indicating whether the user has enabled Suggested Content.
 const char kSuggestedContentEnabled[] = "settings.suggested_content_enabled";
 
+// Boolean pref recording whether a search result has ever been launched from
+// the Chrome OS launcher.
+const char kLauncherResultEverLaunched[] = "launcher.result_ever_launched";
+
 }  // namespace prefs
 }  // namespace chromeos
diff --git a/chromeos/constants/chromeos_pref_names.h b/chromeos/constants/chromeos_pref_names.h
index d5263d8..b3305d7 100644
--- a/chromeos/constants/chromeos_pref_names.h
+++ b/chromeos/constants/chromeos_pref_names.h
@@ -50,6 +50,8 @@
 extern const char kLoginDisplayPasswordButtonEnabled[];
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const char kSuggestedContentEnabled[];
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
+extern const char kLauncherResultEverLaunched[];
 
 }  // namespace prefs
 }  // namespace chromeos
diff --git a/chromeos/crosapi/mojom/keystore_service.mojom b/chromeos/crosapi/mojom/keystore_service.mojom
index 88553e8..b51ba09 100644
--- a/chromeos/crosapi/mojom/keystore_service.mojom
+++ b/chromeos/crosapi/mojom/keystore_service.mojom
@@ -24,9 +24,9 @@
   kDevice = 1,
 };
 
-// Returned by ChallengeAttestationOnlyKeystore().
-[Stable]
-union ChallengeAttestationOnlyKeystoreResult {
+// Returned by methods that either return a string, or an error.
+[Stable, RenamedFrom="crosapi.mojom.ChallengeAttestationOnlyKeystoreResult"]
+union KeystoreStringResult {
   // Implies failure.
   string error_message;
 
@@ -60,7 +60,7 @@
   // certificate with the migrated key.
   ChallengeAttestationOnlyKeystore@0(
       string challenge, KeystoreType type, bool migrate) =>
-          (ChallengeAttestationOnlyKeystoreResult result);
+          (KeystoreStringResult result);
 
   // Returns the key stores available to the client. These are used as inputs to
   // the other methods on this interface.
diff --git a/chromeos/dbus/audio/cras_audio_client.cc b/chromeos/dbus/audio/cras_audio_client.cc
index be0408bd..871ba24 100644
--- a/chromeos/dbus/audio/cras_audio_client.cc
+++ b/chromeos/dbus/audio/cras_audio_client.cc
@@ -273,16 +273,6 @@
                             base::DoNothing());
   }
 
-  void SetNextHandsfreeProfile(bool enabled) override {
-    dbus::MethodCall method_call(cras::kCrasControlInterface,
-                                 cras::kSetNextHandsfreeProfile);
-    dbus::MessageWriter writer(&method_call);
-    writer.AppendBool(enabled);
-    cras_proxy_->CallMethod(&method_call,
-                            dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
-                            base::DoNothing());
-  }
-
   void AddActiveInputNode(uint64_t node_id) override {
     dbus::MethodCall method_call(cras::kCrasControlInterface,
                                  cras::kAddActiveInputNode);
diff --git a/chromeos/dbus/audio/cras_audio_client.h b/chromeos/dbus/audio/cras_audio_client.h
index ef1e4c73..636a33d8 100644
--- a/chromeos/dbus/audio/cras_audio_client.h
+++ b/chromeos/dbus/audio/cras_audio_client.h
@@ -134,8 +134,6 @@
 
   // Enables or disables the usage of fixed A2DP packet size in CRAS.
   virtual void SetFixA2dpPacketSize(bool enabled) = 0;
-  // Enables or disables the next Handsfree profile next version in CRAS.
-  virtual void SetNextHandsfreeProfile(bool enabled) = 0;
 
   // Adds input node |node_id| to the active input list. This is used to add
   // an additional active input node besides the one set by SetActiveInputNode.
diff --git a/chromeos/dbus/audio/fake_cras_audio_client.cc b/chromeos/dbus/audio/fake_cras_audio_client.cc
index 5209d111..6a97e32 100644
--- a/chromeos/dbus/audio/fake_cras_audio_client.cc
+++ b/chromeos/dbus/audio/fake_cras_audio_client.cc
@@ -205,7 +205,6 @@
                                           VoidDBusMethodCallback callback) {}
 
 void FakeCrasAudioClient::SetFixA2dpPacketSize(bool enabled) {}
-void FakeCrasAudioClient::SetNextHandsfreeProfile(bool enabled) {}
 
 void FakeCrasAudioClient::AddActiveInputNode(uint64_t node_id) {
   for (size_t i = 0; i < node_list_.size(); ++i) {
diff --git a/chromeos/dbus/audio/fake_cras_audio_client.h b/chromeos/dbus/audio/fake_cras_audio_client.h
index 59f69eb..6498fe5 100644
--- a/chromeos/dbus/audio/fake_cras_audio_client.h
+++ b/chromeos/dbus/audio/fake_cras_audio_client.h
@@ -45,7 +45,6 @@
                        const std::string& hotword_model,
                        VoidDBusMethodCallback callback) override;
   void SetFixA2dpPacketSize(bool enabled) override;
-  void SetNextHandsfreeProfile(bool enabled) override;
   void AddActiveInputNode(uint64_t node_id) override;
   void RemoveActiveInputNode(uint64_t node_id) override;
   void AddActiveOutputNode(uint64_t node_id) override;
diff --git a/chromeos/dbus/cros_healthd/fake_cros_healthd_service.cc b/chromeos/dbus/cros_healthd/fake_cros_healthd_service.cc
index 6e22e7b..6f032fb 100644
--- a/chromeos/dbus/cros_healthd/fake_cros_healthd_service.cc
+++ b/chromeos/dbus/cros_healthd/fake_cros_healthd_service.cc
@@ -76,8 +76,6 @@
 }
 
 void FakeCrosHealthdService::RunBatteryCapacityRoutine(
-    uint32_t low_mah,
-    uint32_t high_mah,
     RunBatteryCapacityRoutineCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
       FROM_HERE,
@@ -86,8 +84,6 @@
 }
 
 void FakeCrosHealthdService::RunBatteryHealthRoutine(
-    uint32_t maximum_cycle_count,
-    uint32_t percent_battery_wear_allowed,
     RunBatteryHealthRoutineCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
       FROM_HERE,
@@ -232,6 +228,16 @@
   std::move(callback).Run(run_routine_response_.Clone());
 }
 
+void FakeCrosHealthdService::RunDnsLatencyRoutine(
+    RunDnsLatencyRoutineCallback callback) {
+  std::move(callback).Run(run_routine_response_.Clone());
+}
+
+void FakeCrosHealthdService::RunDnsResolutionRoutine(
+    RunDnsResolutionRoutineCallback callback) {
+  std::move(callback).Run(run_routine_response_.Clone());
+}
+
 void FakeCrosHealthdService::AddBluetoothObserver(
     mojom::CrosHealthdBluetoothObserverPtr observer) {
   bluetooth_observers_.Add(observer.PassInterface());
diff --git a/chromeos/dbus/cros_healthd/fake_cros_healthd_service.h b/chromeos/dbus/cros_healthd/fake_cros_healthd_service.h
index f96bc62..76db2f8 100644
--- a/chromeos/dbus/cros_healthd/fake_cros_healthd_service.h
+++ b/chromeos/dbus/cros_healthd/fake_cros_healthd_service.h
@@ -58,12 +58,8 @@
   void RunUrandomRoutine(uint32_t length_seconds,
                          RunUrandomRoutineCallback callback) override;
   void RunBatteryCapacityRoutine(
-      uint32_t low_mah,
-      uint32_t high_mah,
       RunBatteryCapacityRoutineCallback callback) override;
   void RunBatteryHealthRoutine(
-      uint32_t maximum_cycle_count,
-      uint32_t percent_battery_wear_allowed,
       RunBatteryHealthRoutineCallback callback) override;
   void RunSmartctlCheckRoutine(
       RunSmartctlCheckRoutineCallback callback) override;
@@ -108,6 +104,9 @@
       RunHasSecureWiFiConnectionRoutineCallback callback) override;
   void RunDnsResolverPresentRoutine(
       RunDnsResolverPresentRoutineCallback callback) override;
+  void RunDnsLatencyRoutine(RunDnsLatencyRoutineCallback callback) override;
+  void RunDnsResolutionRoutine(
+      RunDnsResolutionRoutineCallback callback) override;
 
   // CrosHealthdEventService overrides:
   void AddBluetoothObserver(
diff --git a/chromeos/services/cros_healthd/public/cpp/service_connection.cc b/chromeos/services/cros_healthd/public/cpp/service_connection.cc
index 21243a6..4f70f59 100644
--- a/chromeos/services/cros_healthd/public/cpp/service_connection.cc
+++ b/chromeos/services/cros_healthd/public/cpp/service_connection.cc
@@ -43,13 +43,9 @@
       mojom::CrosHealthdDiagnosticsService::RunUrandomRoutineCallback callback)
       override;
   void RunBatteryCapacityRoutine(
-      uint32_t low_mah,
-      uint32_t high_mah,
       mojom::CrosHealthdDiagnosticsService::RunBatteryCapacityRoutineCallback
           callback) override;
   void RunBatteryHealthRoutine(
-      uint32_t maximum_cycle_count,
-      uint32_t percent_battery_wear_allowed,
       mojom::CrosHealthdDiagnosticsService::RunBatteryHealthRoutineCallback
           callback) override;
   void RunSmartctlCheckRoutine(
@@ -119,6 +115,12 @@
   void RunDnsResolverPresentRoutine(
       mojom::CrosHealthdDiagnosticsService::RunDnsResolverPresentRoutineCallback
           callback) override;
+  void RunDnsLatencyRoutine(
+      mojom::CrosHealthdDiagnosticsService::RunDnsLatencyRoutineCallback
+          callback) override;
+  void RunDnsResolutionRoutine(
+      mojom::CrosHealthdDiagnosticsService::RunDnsResolutionRoutineCallback
+          callback) override;
   void AddBluetoothObserver(
       mojo::PendingRemote<mojom::CrosHealthdBluetoothObserver> pending_observer)
       override;
@@ -226,25 +228,21 @@
 }
 
 void ServiceConnectionImpl::RunBatteryCapacityRoutine(
-    uint32_t low_mah,
-    uint32_t high_mah,
     mojom::CrosHealthdDiagnosticsService::RunBatteryCapacityRoutineCallback
         callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   BindCrosHealthdDiagnosticsServiceIfNeeded();
   cros_healthd_diagnostics_service_->RunBatteryCapacityRoutine(
-      low_mah, high_mah, std::move(callback));
+      std::move(callback));
 }
 
 void ServiceConnectionImpl::RunBatteryHealthRoutine(
-    uint32_t maximum_cycle_count,
-    uint32_t percent_battery_wear_allowed,
     mojom::CrosHealthdDiagnosticsService::RunBatteryHealthRoutineCallback
         callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   BindCrosHealthdDiagnosticsServiceIfNeeded();
   cros_healthd_diagnostics_service_->RunBatteryHealthRoutine(
-      maximum_cycle_count, percent_battery_wear_allowed, std::move(callback));
+      std::move(callback));
 }
 
 void ServiceConnectionImpl::RunSmartctlCheckRoutine(
@@ -413,6 +411,23 @@
       std::move(callback));
 }
 
+void ServiceConnectionImpl::RunDnsLatencyRoutine(
+    mojom::CrosHealthdDiagnosticsService::RunDnsLatencyRoutineCallback
+        callback) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  BindCrosHealthdDiagnosticsServiceIfNeeded();
+  cros_healthd_diagnostics_service_->RunDnsLatencyRoutine(std::move(callback));
+}
+
+void ServiceConnectionImpl::RunDnsResolutionRoutine(
+    mojom::CrosHealthdDiagnosticsService::RunDnsResolutionRoutineCallback
+        callback) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  BindCrosHealthdDiagnosticsServiceIfNeeded();
+  cros_healthd_diagnostics_service_->RunDnsResolutionRoutine(
+      std::move(callback));
+}
+
 void ServiceConnectionImpl::AddBluetoothObserver(
     mojo::PendingRemote<mojom::CrosHealthdBluetoothObserver> pending_observer) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/chromeos/services/cros_healthd/public/cpp/service_connection.h b/chromeos/services/cros_healthd/public/cpp/service_connection.h
index 2b484724..ecb2894 100644
--- a/chromeos/services/cros_healthd/public/cpp/service_connection.h
+++ b/chromeos/services/cros_healthd/public/cpp/service_connection.h
@@ -65,8 +65,6 @@
   // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunBatteryCapacityRoutine(
-      uint32_t low_mah,
-      uint32_t high_mah,
       mojom::CrosHealthdDiagnosticsService::RunBatteryCapacityRoutineCallback
           callback) = 0;
 
@@ -74,8 +72,6 @@
   // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunBatteryHealthRoutine(
-      uint32_t maximum_cycle_count,
-      uint32_t percent_battery_wear_allowed,
       mojom::CrosHealthdDiagnosticsService::RunBatteryHealthRoutineCallback
           callback) = 0;
 
@@ -214,6 +210,20 @@
       mojom::CrosHealthdDiagnosticsService::RunDnsResolverPresentRoutineCallback
           callback) = 0;
 
+  // Requests that cros_healthd runs the DNS latency routine. See
+  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // details.
+  virtual void RunDnsLatencyRoutine(
+      mojom::CrosHealthdDiagnosticsService::RunDnsLatencyRoutineCallback
+          callback) = 0;
+
+  // Requests that cros_healthd runs the DNS resolution routine. See
+  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // details.
+  virtual void RunDnsResolutionRoutine(
+      mojom::CrosHealthdDiagnosticsService::RunDnsResolutionRoutineCallback
+          callback) = 0;
+
   // Subscribes to cros_healthd's Bluetooth-related events. See
   // src/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
diff --git a/chromeos/services/cros_healthd/public/cpp/service_connection_unittest.cc b/chromeos/services/cros_healthd/public/cpp/service_connection_unittest.cc
index a51cdd3..1d2bc1c 100644
--- a/chromeos/services/cros_healthd/public/cpp/service_connection_unittest.cc
+++ b/chromeos/services/cros_healthd/public/cpp/service_connection_unittest.cc
@@ -323,7 +323,6 @@
   FakeCrosHealthdClient::Get()->SetRunRoutineResponseForTesting(response);
   bool callback_done = false;
   ServiceConnection::GetInstance()->RunBatteryCapacityRoutine(
-      /*low_mah=*/1001, /*high_mah=*/120345,
       base::BindOnce(
           [](bool* callback_done, mojom::RunRoutineResponsePtr response) {
             EXPECT_EQ(response, MakeRunRoutineResponse());
@@ -340,7 +339,6 @@
   FakeCrosHealthdClient::Get()->SetRunRoutineResponseForTesting(response);
   bool callback_done = false;
   ServiceConnection::GetInstance()->RunBatteryHealthRoutine(
-      /*maximum_cycle_count=*/2, /*percent_battery_wear_allowed=*/90,
       base::BindOnce(
           [](bool* callback_done, mojom::RunRoutineResponsePtr response) {
             EXPECT_EQ(response, MakeRunRoutineResponse());
@@ -588,6 +586,32 @@
   run_loop.Run();
 }
 
+// Test that we can run the DNS latency routine.
+TEST_F(CrosHealthdServiceConnectionTest, RunDnsLatencyRoutine) {
+  auto response = MakeRunRoutineResponse();
+  FakeCrosHealthdClient::Get()->SetRunRoutineResponseForTesting(response);
+  base::RunLoop run_loop;
+  ServiceConnection::GetInstance()->RunDnsLatencyRoutine(
+      base::BindLambdaForTesting([&](mojom::RunRoutineResponsePtr response) {
+        EXPECT_EQ(response, MakeRunRoutineResponse());
+        run_loop.Quit();
+      }));
+  run_loop.Run();
+}
+
+// Test that we can run the DNS resolution routine.
+TEST_F(CrosHealthdServiceConnectionTest, RunDnsResolutionRoutine) {
+  auto response = MakeRunRoutineResponse();
+  FakeCrosHealthdClient::Get()->SetRunRoutineResponseForTesting(response);
+  base::RunLoop run_loop;
+  ServiceConnection::GetInstance()->RunDnsResolutionRoutine(
+      base::BindLambdaForTesting([&](mojom::RunRoutineResponsePtr response) {
+        EXPECT_EQ(response, MakeRunRoutineResponse());
+        run_loop.Quit();
+      }));
+  run_loop.Run();
+}
+
 // Test that we can add a Bluetooth observer.
 TEST_F(CrosHealthdServiceConnectionTest, AddBluetoothObserver) {
   MockCrosHealthdBluetoothObserver observer;
diff --git a/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom b/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom
index 56db81d0..86c89df 100644
--- a/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom
+++ b/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom
@@ -81,38 +81,30 @@
       => (RunRoutineResponse response);
 
   // Requests that the BatteryCapacity routine is created and started on the
-  // platform. This routine checks the battery's design capacity against the
-  // inputs. The routine will pass iff the design capacity of the battery read
-  // from the platform is inclusively within these bounds. This routine is only
-  // available if GetAvailableRoutines returned kBatteryCapactity.
-  //
-  // The request:
-  // * |low_mah| - lower bound for the battery's design capacity (mAh).
-  // * |high_mah| - upper bound for the battery's design capacity (mAh).
+  // platform. This routine checks the battery's design capacity against inputs
+  // configured in cros_config. If no configuration data is present in
+  // cros_config, the routine will fall back to fleet-wide default values of
+  // [1000, 10000]. The routine will pass iff the design capacity of the battery
+  // read from the platform is inclusively within these bounds. This routine is
+  // only available if GetAvailableRoutines returned kBatteryCapactity.
   //
   // The response:
   // * |response| - contains a unique identifier and status for the created
   //                routine.
-  RunBatteryCapacityRoutine(uint32 low_mah, uint32 high_mah)
-      => (RunRoutineResponse response);
+  RunBatteryCapacityRoutine() => (RunRoutineResponse response);
 
   // Requests that the BatteryHealth routine is created and started on the
   // platform. This routine checks the cycle count and percent wear of the
-  // battery. This routine is only available if GetAvailableRoutines returned
-  // kBatteryHealth.
-  //
-  // The request:
-  // * |maximum_cycle_count| - maximum cycle count allowed for the routine to
-  //                           pass.
-  // * |percent_battery_wear_allowed| - maximum percent battery wear allowed for
-  //                                    the routine to pass.
+  // battery against inputs configured in cros_config. If no configuration data
+  // is present in cros_config, the routine will fall back to fleet-wide default
+  // values of 1000 for the maximum allowable cycle count and 50% for maximum
+  // battery wear percentage allowed. This routine is only available if
+  // GetAvailableRoutines returned kBatteryHealth.
   //
   // The response:
   // * |response| - contains a unique identifier and status for the created
   //                routine.
-  RunBatteryHealthRoutine(uint32 maximum_cycle_count,
-                          uint32 percent_battery_wear_allowed)
-      => (RunRoutineResponse response);
+  RunBatteryHealthRoutine() => (RunRoutineResponse response);
 
   // Requests that the SmartctlCheck routine is created and started on the
   // platform. This routine checks available spare NVMe capacity against the
@@ -357,6 +349,26 @@
   // * |response| - contains a unique identifier and status for the created
   //                routine.
   RunDnsResolverPresentRoutine() => (RunRoutineResponse response);
+
+  // Requests that the DnsLatency routine is created and started on the
+  // platform. This routine checks whether the DNS latency is below an
+  // acceptable threshold. This routine is only available if
+  // GetAvailableRoutines returned kDnsLatency.
+  //
+  // The response:
+  // * |response| - contains a unique identifier and status for the created
+  //                routine.
+  RunDnsLatencyRoutine() => (RunRoutineResponse response);
+
+  // Requests that the DnsResolution routine is created and started on the
+  // platform. This routine checks whether a DNS resolution can be completed
+  // successfully. This routine is only available if GetAvailableRoutines
+  // returned kDnsResolution.
+  //
+  // The response:
+  // * |response| - contains a unique identifier and status for the created
+  //                routine.
+  RunDnsResolutionRoutine() => (RunRoutineResponse response);
 };
 
 // Event interface exposed by the cros_healthd daemon.
diff --git a/chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom b/chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom
index 8ad21e03..c643347 100644
--- a/chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom
+++ b/chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom
@@ -36,6 +36,8 @@
   kGatewayCanBePinged = 17,
   kHasSecureWiFiConnection = 18,
   kDnsResolverPresent = 19,
+  kDnsLatency = 20,
+  kDnsResolution = 21,
 };
 
 // Enumeration of the possible DiskRead routine's command type
diff --git a/chromeos/services/network_health/public/mojom/network_diagnostics.mojom b/chromeos/services/network_health/public/mojom/network_diagnostics.mojom
index a21bcf6..4770439b 100644
--- a/chromeos/services/network_health/public/mojom/network_diagnostics.mojom
+++ b/chromeos/services/network_health/public/mojom/network_diagnostics.mojom
@@ -60,9 +60,8 @@
 // Problems related to the DnsLatencyProblem routine.
 [Extensible]
 enum DnsLatencyProblem {
-  // The routine was unable to successfully resolve all the hosts. Note that
-  // this will be true if one or more hosts could not be successfully resolved.
-  kFailedToResolveAllHosts,
+  // The routine was unable to resolve one or more hosts.
+  kHostResolutionFailure,
   // Average DNS latency across hosts is slightly above expected threshold
   kSlightlyAboveThreshold,
   // Average DNS latency across hosts is significantly above expected threshold
diff --git a/chromeos/strings/chromeos_strings_bn.xtb b/chromeos/strings/chromeos_strings_bn.xtb
index ba4c934..d8d4c19 100644
--- a/chromeos/strings/chromeos_strings_bn.xtb
+++ b/chromeos/strings/chromeos_strings_bn.xtb
@@ -3,6 +3,7 @@
 <translationbundle lang="bn">
 <translation id="1018656279737460067">বাতিল হয়েছে</translation>
 <translation id="1195447618553298278">অজানা ত্রুটি৷</translation>
+<translation id="1330426557709298164">JPG</translation>
 <translation id="1413240736185167732">প্রিন্ট করা যায়নি - ফিল্টার কাজ করছে না</translation>
 <translation id="1468664791493211953">অফার</translation>
 <translation id="1478594628797167447">স্ক্যানার</translation>
@@ -46,6 +47,7 @@
 <translation id="4227825898293920515">পাসওয়ার্ডের মেয়াদ <ph name="TIME" />-এ শেষ হবে</translation>
 <translation id="4238516577297848345">প্রিন্ট করার কোনও কাজ চালু নেই</translation>
 <translation id="4297501883039923494">বন্ধ হয়ে গেছে - অজানা সমস্যা</translation>
+<translation id="4382484599443659549">পিডিএফ</translation>
 <translation id="4429881212383817840">Kerberos টিকিটের মেয়াদ শীঘ্রই শেষ হয়ে যাবে</translation>
 <translation id="445059817448385655">পুরনো পাসওয়ার্ড</translation>
 <translation id="4627232916386272576"><ph name="DOCUMENT_TITLE" />, <ph name="PRINTER_NAME" />, <ph name="CREATION_TIME" />, <ph name="TOTAL_PAGE_NUMBER" />টির মধ্যে <ph name="PRINTED_PAGE_NUMBER" /> নম্বর পৃষ্ঠা। প্রিন্ট করা বাতিল করতে এন্টার প্রেস করুন।</translation>
@@ -72,6 +74,7 @@
 <translation id="6058625436358447366">সম্পূর্ণ করতে, আপনার পুরনো ও নতুন পাসওয়ার্ড লিখুন</translation>
 <translation id="6106186594183574873">সম্পূর্ণ করতে, আপনার পুরনো পাসওয়ার্ড লিখুন</translation>
 <translation id="6146993107019042706">সম্পূর্ণ করতে, আপনার নতুন পাসওয়ার্ড লিখুন</translation>
+<translation id="6147514244879357420">PNG</translation>
 <translation id="636850387210749493">এন্টারপ্রাইজ নথিভুক্তিকরণ</translation>
 <translation id="649050271426829538">বন্ধ হয়ে গেছে - প্রিন্টারে কাগজ আটকে গেছে</translation>
 <translation id="6517239166834772319">ঘুরে দেখুন</translation>
diff --git a/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java b/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java
index 0287ac3..28b231d 100644
--- a/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java
+++ b/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java
@@ -14,11 +14,11 @@
 
 import androidx.annotation.VisibleForTesting;
 
+import org.chromium.base.CollectionUtil;
 import org.chromium.base.Log;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
-import java.util.Iterator;
 
 /**
  * The class to call Android's AutofillManager.
@@ -158,25 +158,9 @@
         mInputUIObservers.add(new WeakReference<InputUIObserver>(observer));
     }
 
-    public void removeInputUIObserver(InputUIObserver observer) {
-        if (observer == null) return;
-        for (Iterator<WeakReference<InputUIObserver>> i = mInputUIObservers.listIterator();
-                i.hasNext();) {
-            WeakReference<InputUIObserver> o = i.next();
-            if (o.get() == null || o.get() == observer) i.remove();
-        }
-    }
-
     @VisibleForTesting
     public void notifyInputUIChange() {
-        for (Iterator<WeakReference<InputUIObserver>> i = mInputUIObservers.listIterator();
-                i.hasNext();) {
-            WeakReference<InputUIObserver> o = i.next();
-            InputUIObserver observer = o.get();
-            if (observer == null) {
-                i.remove();
-                continue;
-            }
+        for (InputUIObserver observer : CollectionUtil.strengthen(mInputUIObservers)) {
             observer.onInputUIShown();
         }
     }
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc
index c7e7044..8b3435a 100644
--- a/components/autofill/content/renderer/autofill_agent.cc
+++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -40,7 +40,6 @@
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_data_predictions.h"
 #include "components/autofill/core/common/form_field_data.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/autofill/core/common/password_form_fill_data.h"
 #include "components/autofill/core/common/save_password_progress_logger.h"
 #include "content/public/common/content_switches.h"
diff --git a/components/autofill/content/renderer/html_based_username_detector.h b/components/autofill/content/renderer/html_based_username_detector.h
index 5a32cb4..ef1c22a 100644
--- a/components/autofill/content/renderer/html_based_username_detector.h
+++ b/components/autofill/content/renderer/html_based_username_detector.h
@@ -8,7 +8,7 @@
 #include <map>
 #include <vector>
 
-#include "components/autofill/core/common/password_form.h"
+#include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/renderer_id.h"
 #include "third_party/blink/public/web/web_form_control_element.h"
 #include "third_party/blink/public/web/web_input_element.h"
diff --git a/components/autofill/content/renderer/password_autofill_agent.h b/components/autofill/content/renderer/password_autofill_agent.h
index 3738a1f..da3bfe3 100644
--- a/components/autofill/content/renderer/password_autofill_agent.h
+++ b/components/autofill/content/renderer/password_autofill_agent.h
@@ -24,7 +24,6 @@
 #include "components/autofill/content/renderer/html_based_username_detector.h"
 #include "components/autofill/core/common/field_data_manager.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/autofill/core/common/password_form_fill_data.h"
 #include "components/autofill/core/common/renderer_id.h"
 #include "content/public/renderer/render_frame_observer.h"
diff --git a/components/autofill/content/renderer/password_form_conversion_utils.cc b/components/autofill/content/renderer/password_form_conversion_utils.cc
index 93824ca..81cea7d9 100644
--- a/components/autofill/content/renderer/password_form_conversion_utils.cc
+++ b/components/autofill/content/renderer/password_form_conversion_utils.cc
@@ -10,7 +10,6 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
 #include "components/autofill/content/renderer/html_based_username_detector.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/autofill/core/common/renderer_id.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/base/url_util.h"
diff --git a/components/autofill/content/renderer/password_form_conversion_utils.h b/components/autofill/content/renderer/password_form_conversion_utils.h
index 07a2ad0..1685530 100644
--- a/components/autofill/content/renderer/password_form_conversion_utils.h
+++ b/components/autofill/content/renderer/password_form_conversion_utils.h
@@ -14,7 +14,6 @@
 #include "base/strings/string_piece.h"
 #include "components/autofill/content/renderer/form_autofill_util.h"
 #include "components/autofill/content/renderer/html_based_username_detector.h"
-#include "components/autofill/core/common/password_form.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "url/gurl.h"
 
diff --git a/components/autofill/content/renderer/password_generation_agent.cc b/components/autofill/content/renderer/password_generation_agent.cc
index a87d298c..1d8af55e 100644
--- a/components/autofill/content/renderer/password_generation_agent.cc
+++ b/components/autofill/content/renderer/password_generation_agent.cc
@@ -19,7 +19,6 @@
 #include "components/autofill/content/renderer/password_form_conversion_utils.h"
 #include "components/autofill/core/common/autofill_switches.h"
 #include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/autofill/core/common/password_form_generation_data.h"
 #include "components/autofill/core/common/password_generation_util.h"
 #include "components/autofill/core/common/signatures.h"
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h
index a18c4d9..d8f8ad7 100644
--- a/components/autofill/core/browser/form_structure.h
+++ b/components/autofill/core/browser/form_structure.h
@@ -25,7 +25,6 @@
 #include "components/autofill/core/browser/form_types.h"
 #include "components/autofill/core/browser/proto/api_v1.pb.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/autofill/core/common/renderer_id.h"
 #include "url/gurl.h"
 #include "url/origin.h"
diff --git a/components/autofill/core/browser/form_structure_unittest.cc b/components/autofill/core/browser/form_structure_unittest.cc
index 6eb7902fa..f9559df 100644
--- a/components/autofill/core/browser/form_structure_unittest.cc
+++ b/components/autofill/core/browser/form_structure_unittest.cc
@@ -26,7 +26,6 @@
 #include "components/autofill/core/common/autofill_prefs.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_field_data.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/autofill/core/common/signatures.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
diff --git a/components/autofill/core/common/password_form_fill_data.h b/components/autofill/core/common/password_form_fill_data.h
index 36f83ca6..9308187 100644
--- a/components/autofill/core/common/password_form_fill_data.h
+++ b/components/autofill/core/common/password_form_fill_data.h
@@ -9,7 +9,6 @@
 #include <vector>
 
 #include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/autofill/core/common/renderer_id.h"
 
 namespace autofill {
diff --git a/components/autofill/core/common/password_generation_util.h b/components/autofill/core/common/password_generation_util.h
index 43115bf..abcee73d 100644
--- a/components/autofill/core/common/password_generation_util.h
+++ b/components/autofill/core/common/password_generation_util.h
@@ -5,7 +5,9 @@
 #ifndef COMPONENTS_AUTOFILL_CORE_COMMON_PASSWORD_GENERATION_UTIL_H_
 #define COMPONENTS_AUTOFILL_CORE_COMMON_PASSWORD_GENERATION_UTIL_H_
 
-#include "components/autofill/core/common/password_form.h"
+#include "base/i18n/rtl.h"
+#include "base/strings/string16.h"
+#include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/renderer_id.h"
 #include "ui/gfx/geometry/rect_f.h"
 
diff --git a/components/autofill/core/common/save_password_progress_logger_unittest.cc b/components/autofill/core/common/save_password_progress_logger_unittest.cc
index bce8f456..550f2e9 100644
--- a/components/autofill/core/common/save_password_progress_logger_unittest.cc
+++ b/components/autofill/core/common/save_password_progress_logger_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/bind.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/common/password_form.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
diff --git a/components/autofill_assistant/browser/actions/collect_user_data_action.h b/components/autofill_assistant/browser/actions/collect_user_data_action.h
index 5a7fac9..d5e75b7 100644
--- a/components/autofill_assistant/browser/actions/collect_user_data_action.h
+++ b/components/autofill_assistant/browser/actions/collect_user_data_action.h
@@ -14,7 +14,6 @@
 #include "base/optional.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/personal_data_manager_observer.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/autofill_assistant/browser/actions/action.h"
 #include "components/autofill_assistant/browser/user_data.h"
 #include "components/autofill_assistant/browser/user_model.h"
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc
index 1522e950..5dd9dfd 100644
--- a/components/autofill_assistant/browser/script_executor.cc
+++ b/components/autofill_assistant/browser/script_executor.cc
@@ -970,13 +970,6 @@
       current_action_data_.navigation_info;
 
   if (processed_action.status() != ProcessedActionStatusProto::ACTION_APPLIED) {
-    if (delegate_->HasNavigationError()) {
-      // Overwrite the original error, as the root cause is most likely a
-      // navigation error.
-      processed_action.mutable_status_details()->set_original_status(
-          processed_action.status());
-      processed_action.set_status(ProcessedActionStatusProto::NAVIGATION_ERROR);
-    }
     VLOG(1) << "Action failed: " << processed_action.status();
     // Remove unexecuted actions, this will cause the |ProcessNextActions| call
     // to immediately ask for new actions.
diff --git a/components/autofill_assistant/browser/script_executor_unittest.cc b/components/autofill_assistant/browser/script_executor_unittest.cc
index 306a74d..d7a3db1 100644
--- a/components/autofill_assistant/browser/script_executor_unittest.cc
+++ b/components/autofill_assistant/browser/script_executor_unittest.cc
@@ -1164,30 +1164,6 @@
   EXPECT_FALSE(processed_actions_capture[0].navigation_info().ended());
 }
 
-TEST_F(ScriptExecutorTest, ReportErrorAsNavigationError) {
-  ActionsResponseProto actions_response;
-  *actions_response.add_actions()->mutable_click()->mutable_element_to_click() =
-      ToSelectorProto("will fail");
-
-  EXPECT_CALL(mock_service_, OnGetActions(_, _, _, _, _, _))
-      .WillOnce(RunOnceCallback<5>(net::HTTP_OK, Serialize(actions_response)));
-  std::vector<ProcessedActionProto> processed_actions_capture;
-  EXPECT_CALL(mock_service_, OnGetNextActions(_, _, _, _, _, _))
-      .WillOnce(DoAll(SaveArg<3>(&processed_actions_capture),
-                      RunOnceCallback<5>(net::HTTP_OK, "")));
-
-  delegate_.UpdateNavigationState(/* navigating= */ false, /* error= */ true);
-  EXPECT_CALL(executor_callback_, Run(_));
-  executor_->Run(&user_data_, executor_callback_.Get());
-
-  ASSERT_EQ(1u, processed_actions_capture.size());
-
-  // The original error is overwritten; a navigation error is reported.
-  EXPECT_EQ(NAVIGATION_ERROR, processed_actions_capture[0].status());
-  EXPECT_EQ(ELEMENT_RESOLUTION_FAILED,
-            processed_actions_capture[0].status_details().original_status());
-}
-
 TEST_F(ScriptExecutorTest, NavigateWhileRunningInterrupt) {
   SetupInterruptibleScript(kScriptPath, "element");
   RegisterInterrupt("interrupt", "interrupt_trigger");
diff --git a/components/autofill_assistant/browser/user_data.cc b/components/autofill_assistant/browser/user_data.cc
index d973009e..9e9c18e 100644
--- a/components/autofill_assistant/browser/user_data.cc
+++ b/components/autofill_assistant/browser/user_data.cc
@@ -6,7 +6,6 @@
 
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
-#include "components/autofill/core/common/password_form.h"
 
 namespace autofill_assistant {
 
diff --git a/components/autofill_assistant/browser/website_login_manager_impl.cc b/components/autofill_assistant/browser/website_login_manager_impl.cc
index d3d1ff8..682553b 100644
--- a/components/autofill_assistant/browser/website_login_manager_impl.cc
+++ b/components/autofill_assistant/browser/website_login_manager_impl.cc
@@ -24,10 +24,10 @@
 
 // Creates a |PasswordForm| with minimal initialization (origin, username,
 // password).
-autofill::PasswordForm CreatePasswordForm(
+password_manager::PasswordForm CreatePasswordForm(
     const WebsiteLoginManager::Login& login,
     const std::string& password) {
-  autofill::PasswordForm form;
+  password_manager::PasswordForm form;
   form.url = login.origin.GetOrigin();
   form.signon_realm = password_manager::GetSignonRealm(form.url);
   form.username_value = base::UTF8ToUTF16(login.username);
@@ -141,7 +141,7 @@
  protected:
   // From PendingRequest:
   void OnFetchCompleted() override {
-    std::vector<const autofill::PasswordForm*> matches =
+    std::vector<const password_manager::PasswordForm*> matches =
         form_fetcher_->GetNonFederatedMatches();
     for (const auto* match : matches) {
       if (base::UTF16ToUTF8(match->username_value) == login_.username) {
@@ -184,8 +184,8 @@
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
     password_manager::PasswordStore::FormDigest digest(
-        autofill::PasswordForm::Scheme::kHtml, password_form_.signon_realm,
-        password_form_.url);
+        password_manager::PasswordForm::Scheme::kHtml,
+        password_form_.signon_realm, password_form_.url);
     form_fetcher_ = std::make_unique<password_manager::FormFetcherImpl>(
         digest, client, true);
   }
@@ -217,7 +217,7 @@
   }
 
  private:
-  const autofill::PasswordForm password_form_;
+  const password_manager::PasswordForm password_form_;
   const autofill::FormData form_data_;
   password_manager::PasswordManagerClient* const client_ = nullptr;
   // This callback will execute when presaving is completed.
@@ -242,7 +242,8 @@
     base::OnceCallback<void(std::vector<Login>)> callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   password_manager::PasswordStore::FormDigest digest(
-      autofill::PasswordForm::Scheme::kHtml, url.GetOrigin().spec(), GURL());
+      password_manager::PasswordForm::Scheme::kHtml, url.GetOrigin().spec(),
+      GURL());
   pending_requests_.emplace_back(std::make_unique<PendingFetchLoginsRequest>(
       digest, client_, std::move(callback),
       base::BindOnce(&WebsiteLoginManagerImpl::OnRequestFinished,
@@ -255,7 +256,8 @@
     base::OnceCallback<void(bool, std::string)> callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   password_manager::PasswordStore::FormDigest digest(
-      autofill::PasswordForm::Scheme::kHtml, login.origin.spec(), GURL());
+      password_manager::PasswordForm::Scheme::kHtml, login.origin.spec(),
+      GURL());
   pending_requests_.emplace_back(std::make_unique<PendingFetchPasswordRequest>(
       digest, client_, login, std::move(callback),
       base::BindOnce(&WebsiteLoginManagerImpl::OnRequestFinished,
diff --git a/components/autofill_assistant/browser/website_login_manager_impl.h b/components/autofill_assistant/browser/website_login_manager_impl.h
index a365d98..b8656e2 100644
--- a/components/autofill_assistant/browser/website_login_manager_impl.h
+++ b/components/autofill_assistant/browser/website_login_manager_impl.h
@@ -7,7 +7,6 @@
 
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/autofill_assistant/browser/website_login_manager.h"
 #include "content/public/browser/web_contents.h"
 
diff --git a/components/autofill_assistant/browser/website_login_manager_impl_unittest.cc b/components/autofill_assistant/browser/website_login_manager_impl_unittest.cc
index c6438d9..3e73e11 100644
--- a/components/autofill_assistant/browser/website_login_manager_impl_unittest.cc
+++ b/components/autofill_assistant/browser/website_login_manager_impl_unittest.cc
@@ -20,8 +20,8 @@
 
 using autofill::FormData;
 using autofill::FormFieldData;
-using autofill::PasswordForm;
 using base::ASCIIToUTF16;
+using password_manager::PasswordForm;
 using testing::_;
 using testing::Invoke;
 using testing::Mock;
@@ -163,7 +163,7 @@
           })));
 
   password_manager::PasswordStore::FormDigest form_digest(
-      autofill::PasswordForm::Scheme::kHtml, kFakeUrl, GURL(kFakeUrl));
+      password_manager::PasswordForm::Scheme::kHtml, kFakeUrl, GURL(kFakeUrl));
   // Presave generated password. Form with empty username is presaved.
   EXPECT_CALL(*store(), GetLogins(form_digest, _));
   EXPECT_CALL(*store(),
diff --git a/components/browser_ui/DIR_METADATA b/components/browser_ui/DIR_METADATA
index 4001c3a..496d412 100644
--- a/components/browser_ui/DIR_METADATA
+++ b/components/browser_ui/DIR_METADATA
@@ -2,6 +2,6 @@
   component: "UI>Browser>Mobile"
 }
 
-team_email: "chrome-android-app@chromium.org"
+team_email: "clank-app-team@google.com"
 
 os: ANDROID
diff --git a/components/browser_ui/android/bottomsheet/DIR_METADATA b/components/browser_ui/android/bottomsheet/DIR_METADATA
index db76369..1a43921 100644
--- a/components/browser_ui/android/bottomsheet/DIR_METADATA
+++ b/components/browser_ui/android/bottomsheet/DIR_METADATA
@@ -2,6 +2,6 @@
   component: "UI>Browser>Mobile>NavPanel"
 }
 
-team_email: "chrome-android-app@chromium.org"
+team_email: "clank-app-team@google.com"
 
 os: ANDROID
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_bn.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_bn.xtb
index 36cd388..6db5477 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_bn.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_bn.xtb
@@ -38,6 +38,7 @@
 <translation id="1994173015038366702">সাইট URL</translation>
 <translation id="2025115093177348061">অগমেন্টেড রিয়েলিটি</translation>
 <translation id="2030769033451695672"><ph name="URL_OF_THE_CURRENT_TAB" />-এ ফিরে যেতে ট্যাপ করুন</translation>
+<translation id="2054665754582400095">আপনার উপস্থিতি</translation>
 <translation id="2079545284768500474">আগের অবস্থায় ফিরুন</translation>
 <translation id="2091887806945687916">আওয়াজ</translation>
 <translation id="2107397443965016585">সাইটকে সুরক্ষিত কন্টেন্ট চালানোর অনুমতি দেওয়ার আগে জিজ্ঞাসা করুন (প্রস্তাবিত)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_iw.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_iw.xtb
index 5d1816d..b7ab117a 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_iw.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_iw.xtb
@@ -42,7 +42,7 @@
 <translation id="2079545284768500474">ביטול הפעולה</translation>
 <translation id="2091887806945687916">צליל</translation>
 <translation id="2107397443965016585">יש לבקש ממני אישור לפני מתן הרשאה לאתרים להציג תוכן מוגן (מומלץ)</translation>
-<translation id="2146738493024040262">פתח אפליקציה ללא התקנה</translation>
+<translation id="2146738493024040262">פתיחת אפליקציה ללא התקנה</translation>
 <translation id="2148716181193084225">היום</translation>
 <translation id="2182457891543959921">תוצג שאלה לפני מתן הרשאה לאתרים ליצור מפה בתלת ממד של הסביבה שלך או לעקוב אחר מיקום המצלמה (מומלץ)</translation>
 <translation id="2212565012507486665">‏אישור קובצי cookie</translation>
diff --git a/components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/BitmapCache.java b/components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/BitmapCache.java
index fb71cf29..e322aa7c 100644
--- a/components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/BitmapCache.java
+++ b/components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/BitmapCache.java
@@ -12,13 +12,13 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.collection.LruCache;
 
+import org.chromium.base.CollectionUtil;
 import org.chromium.base.DiscardableReferencePool;
 import org.chromium.base.SysUtils;
 import org.chromium.base.ThreadUtils;
 
 import java.lang.ref.WeakReference;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
 
 /**
@@ -164,13 +164,7 @@
      * garbage collector.
      */
     private static void compactDeduplicationCache() {
-        // Too many angle brackets for clang-format :-(
-        // clang-format off
-        for (Iterator<Map.Entry<String, WeakReference<Bitmap>>> it =
-                sDeduplicationCache.entrySet().iterator(); it.hasNext();) {
-            // clang-format on
-            if (it.next().getValue().get() == null) it.remove();
-        }
+        CollectionUtil.strengthen(sDeduplicationCache.values());
     }
 
     @VisibleForTesting
diff --git a/components/browser_ui/widget/android/DIR_METADATA b/components/browser_ui/widget/android/DIR_METADATA
index 4001c3a..496d412 100644
--- a/components/browser_ui/widget/android/DIR_METADATA
+++ b/components/browser_ui/widget/android/DIR_METADATA
@@ -2,6 +2,6 @@
   component: "UI>Browser>Mobile"
 }
 
-team_email: "chrome-android-app@chromium.org"
+team_email: "clank-app-team@google.com"
 
 os: ANDROID
diff --git a/components/browsing_data/core/counters/passwords_counter.cc b/components/browsing_data/core/counters/passwords_counter.cc
index f8b47a3..d6b6ba4 100644
--- a/components/browsing_data/core/counters/passwords_counter.cc
+++ b/components/browsing_data/core/counters/passwords_counter.cc
@@ -47,7 +47,8 @@
              base::OnceClosure fetch_complete);
 
   void OnGetPasswordStoreResults(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> results) override;
+      std::vector<std::unique_ptr<password_manager::PasswordForm>> results)
+      override;
 
   // Called when the contents of the password store change. Triggers new
   // counting.
@@ -102,20 +103,20 @@
 }
 
 void PasswordStoreFetcher::OnGetPasswordStoreResults(
-    std::vector<std::unique_ptr<autofill::PasswordForm>> results) {
+    std::vector<std::unique_ptr<password_manager::PasswordForm>> results) {
   domain_examples_.clear();
 
   results.erase(
       std::remove_if(
           results.begin(), results.end(),
-          [this](const std::unique_ptr<autofill::PasswordForm>& form) {
+          [this](const std::unique_ptr<password_manager::PasswordForm>& form) {
             return (form->date_created < start_ || form->date_created >= end_);
           }),
       results.end());
   num_passwords_ = results.size();
   std::sort(results.begin(), results.end(),
-            [](const std::unique_ptr<autofill::PasswordForm>& a,
-               const std::unique_ptr<autofill::PasswordForm>& b) {
+            [](const std::unique_ptr<password_manager::PasswordForm>& a,
+               const std::unique_ptr<password_manager::PasswordForm>& b) {
               return a->times_used > b->times_used;
             });
 
diff --git a/components/cronet/cronet_url_request_context.cc b/components/cronet/cronet_url_request_context.cc
index 012183e..d1f7650 100644
--- a/components/cronet/cronet_url_request_context.cc
+++ b/components/cronet/cronet_url_request_context.cc
@@ -420,7 +420,8 @@
   if (context_->reporting_service()) {
     for (const auto& preloaded_header : config->preloaded_report_to_headers) {
       context_->reporting_service()->ProcessHeader(
-          preloaded_header.origin.GetURL(), preloaded_header.value);
+          preloaded_header.origin.GetURL(), net::NetworkIsolationKey(),
+          preloaded_header.value);
     }
   }
 
diff --git a/components/enterprise/BUILD.gn b/components/enterprise/BUILD.gn
index 9f82abd..498f2468 100644
--- a/components/enterprise/BUILD.gn
+++ b/components/enterprise/BUILD.gn
@@ -34,6 +34,7 @@
       "browser/reporting/report_request_queue_generator.h",
       "browser/reporting/report_scheduler.cc",
       "browser/reporting/report_scheduler.h",
+      "browser/reporting/report_type.h",
       "browser/reporting/report_uploader.cc",
       "browser/reporting/report_uploader.h",
       "browser/reporting/reporting_delegate_factory.h",
diff --git a/components/enterprise/browser/reporting/profile_report_generator.cc b/components/enterprise/browser/reporting/profile_report_generator.cc
index 1c6e46e..e26c1cc 100644
--- a/components/enterprise/browser/reporting/profile_report_generator.cc
+++ b/components/enterprise/browser/reporting/profile_report_generator.cc
@@ -31,32 +31,44 @@
 
 std::unique_ptr<em::ChromeUserProfileInfo>
 ProfileReportGenerator::MaybeGenerate(const base::FilePath& path,
-                                      const std::string& name) {
+                                      const std::string& name,
+                                      ReportType report_type) {
   if (!delegate_->Init(path)) {
     return nullptr;
   }
 
   report_ = std::make_unique<em::ChromeUserProfileInfo>();
   report_->set_id(path.AsUTF8Unsafe());
-  report_->set_name(name);
-  report_->set_is_full_report(true);
 
-  delegate_->GetSigninUserInfo(report_.get());
-  if (extensions_enabled_) {
-    delegate_->GetExtensionInfo(report_.get());
-  }
-  delegate_->GetExtensionRequest(report_.get());
+  if (report_type == ReportType::kExtensionRequest) {
+#if defined(OS_CHROMEOS)
+    // Extension request is aggregated at the user level on CrOS.
+    report_->set_name(name);
+    delegate_->GetSigninUserInfo(report_.get());
+#endif  // defined(OS_CHROMEOS)
+    delegate_->GetExtensionRequest(report_.get());
 
-  if (policies_enabled_) {
-    // TODO(crbug.com/983151): Upload policy error as their IDs.
-    auto client = delegate_->MakePolicyConversionsClient();
-    policies_ = policy::DictionaryPolicyConversions(std::move(client))
-                    .EnableConvertTypes(false)
-                    .EnablePrettyPrint(false)
-                    .ToValue();
-    GetChromePolicyInfo();
-    GetExtensionPolicyInfo();
-    GetPolicyFetchTimestampInfo();
+  } else {
+    report_->set_name(name);
+    report_->set_is_full_report(true);
+
+    delegate_->GetSigninUserInfo(report_.get());
+    if (extensions_enabled_) {
+      delegate_->GetExtensionInfo(report_.get());
+    }
+    delegate_->GetExtensionRequest(report_.get());
+
+    if (policies_enabled_) {
+      // TODO(crbug.com/983151): Upload policy error as their IDs.
+      auto client = delegate_->MakePolicyConversionsClient();
+      policies_ = policy::DictionaryPolicyConversions(std::move(client))
+                      .EnableConvertTypes(false)
+                      .EnablePrettyPrint(false)
+                      .ToValue();
+      GetChromePolicyInfo();
+      GetExtensionPolicyInfo();
+      GetPolicyFetchTimestampInfo();
+    }
   }
 
   return std::move(report_);
diff --git a/components/enterprise/browser/reporting/profile_report_generator.h b/components/enterprise/browser/reporting/profile_report_generator.h
index 63ce13d..111fe96b 100644
--- a/components/enterprise/browser/reporting/profile_report_generator.h
+++ b/components/enterprise/browser/reporting/profile_report_generator.h
@@ -9,6 +9,8 @@
 #include <string>
 
 #include "base/values.h"
+#include "components/enterprise/browser/reporting/report_request_definition.h"
+#include "components/enterprise/browser/reporting/report_type.h"
 #include "components/policy/core/browser/policy_conversions_client.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 
@@ -72,7 +74,8 @@
   // generated.
   std::unique_ptr<enterprise_management::ChromeUserProfileInfo> MaybeGenerate(
       const base::FilePath& path,
-      const std::string& name);
+      const std::string& name,
+      ReportType report_type = ReportType::kFull);
 
  protected:
   void GetChromePolicyInfo();
diff --git a/components/enterprise/browser/reporting/report_type.h b/components/enterprise/browser/reporting/report_type.h
new file mode 100644
index 0000000..f244dc6
--- /dev/null
+++ b/components/enterprise/browser/reporting/report_type.h
@@ -0,0 +1,18 @@
+// 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 COMPONENTS_ENTERPRISE_BROWSER_REPORTING_REPORT_TYPE_H_
+#define COMPONENTS_ENTERPRISE_BROWSER_REPORTING_REPORT_TYPE_H_
+
+namespace enterprise_reporting {
+
+enum ReportType : uint32_t {
+  kFull = 0,
+  kBrowserVersion = 1u << 0,
+  kExtensionRequest = 2u << 1,
+};
+
+}  // namespace enterprise_reporting
+
+#endif  // COMPONENTS_ENTERPRISE_BROWSER_REPORTING_REPORT_TYPE_H_
diff --git a/components/exo/pointer.cc b/components/exo/pointer.cc
index aaeeef03..dea51f8 100644
--- a/components/exo/pointer.cc
+++ b/components/exo/pointer.cc
@@ -30,8 +30,9 @@
 #include "ui/base/cursor/cursor_size.h"
 #include "ui/base/cursor/cursor_util.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
+#include "ui/base/layout.h"
+#include "ui/base/resource/scale_factor.h"
 #include "ui/display/manager/display_manager.h"
-#include "ui/display/manager/managed_display_info.h"
 #include "ui/display/screen.h"
 #include "ui/events/event.h"
 #include "ui/events/event_constants.h"
@@ -750,10 +751,12 @@
 
     // TODO(oshima|weidongg): Add cutsom cursor API to handle size/display
     // change without explicit management like this. https://crbug.com/721601.
-    const display::Display& display = cursor_client->GetDisplay();
-    float scale =
-        helper->GetDisplayInfo(display.id()).GetDensityRatio() / capture_ratio_;
 
+    // Scaling bitmap to match the corresponding supported scale factor of ash.
+    const display::Display& display = cursor_client->GetDisplay();
+    float scale = ui::GetScaleForScaleFactor(ui::GetSupportedScaleFactor(
+                      display.device_scale_factor())) /
+                  capture_scale_;
     if (cursor_client->GetCursorSize() == ui::CursorSize::kLarge)
       scale *= kLargeCursorScale;
 
diff --git a/components/media_router/browser/android/java/strings/translations/android_chrome_media_router_strings_iw.xtb b/components/media_router/browser/android/java/strings/translations/android_chrome_media_router_strings_iw.xtb
index c0d0f56..06aa14f 100644
--- a/components/media_router/browser/android/java/strings/translations/android_chrome_media_router_strings_iw.xtb
+++ b/components/media_router/browser/android/java/strings/translations/android_chrome_media_router_strings_iw.xtb
@@ -1,5 +1,5 @@
 <?xml version="1.0" ?>
 <!DOCTYPE translationbundle>
 <translationbundle lang="iw">
-<translation id="7366340029385295517">מעביר אל <ph name="SCREEN_NAME" /></translation>
+<translation id="7366340029385295517">ההעברה אל <ph name="SCREEN_NAME" /> מתבצעת</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/components/messages/OWNERS b/components/messages/OWNERS
index ea0fc81..9150fab7 100644
--- a/components/messages/OWNERS
+++ b/components/messages/OWNERS
@@ -3,5 +3,5 @@
 mdjones@chromium.org
 lazzzis@google.com
 
-# TEAM: chrome-android-app@chromium.org
+# TEAM: clank-app-team@google.com
 # COMPONENT: UI>Browser>Mobile>Messages
\ No newline at end of file
diff --git a/components/messages/android/java/res/values/dimens.xml b/components/messages/android/java/res/values/dimens.xml
index 55eab918..b22cb20 100644
--- a/components/messages/android/java/res/values/dimens.xml
+++ b/components/messages/android/java/res/values/dimens.xml
@@ -17,5 +17,6 @@
     <dimen name="message_shadow_top_margin">8dp</dimen>
     <dimen name="message_shadow_lateral_margin">12dp</dimen>
     <dimen name="message_shadow_bottom_margin">16dp</dimen>
+    <dimen name="message_bubble_inset">8dp</dimen>
 
 </resources>
\ No newline at end of file
diff --git a/components/metrics/unsent_log_store_metrics_impl.cc b/components/metrics/unsent_log_store_metrics_impl.cc
index 0b4c491..f6efa5a0 100644
--- a/components/metrics/unsent_log_store_metrics_impl.cc
+++ b/components/metrics/unsent_log_store_metrics_impl.cc
@@ -15,14 +15,16 @@
                                 UnsentLogStoreMetrics::END_RECALL_STATUS);
 }
 
-void UnsentLogStoreMetricsImpl::RecordCompressionRatio(
-    size_t compressed_size, size_t original_size) {
+void UnsentLogStoreMetricsImpl::RecordCompressionRatio(size_t compressed_size,
+                                                       size_t original_size) {
   base::UmaHistogramPercentageObsoleteDoNotUse(
       "UMA.ProtoCompressionRatio",
       static_cast<int>(100 * compressed_size / original_size));
 }
 
 void UnsentLogStoreMetricsImpl::RecordDroppedLogSize(size_t size) {
+  base::UmaHistogramCounts1M("UMA.UnsentLogs.DroppedSize",
+                             static_cast<int>(size));
 }
 
 void UnsentLogStoreMetricsImpl::RecordDroppedLogsNum(int dropped_logs_num) {
diff --git a/components/metrics/unsent_log_store_metrics_impl_unittest.cc b/components/metrics/unsent_log_store_metrics_impl_unittest.cc
index 8027cb6b..1cc1a2b 100644
--- a/components/metrics/unsent_log_store_metrics_impl_unittest.cc
+++ b/components/metrics/unsent_log_store_metrics_impl_unittest.cc
@@ -10,6 +10,22 @@
 
 namespace metrics {
 
+TEST(UnsentLogStoreMetricsImplTest, RecordDroppedLogSize) {
+  UnsentLogStoreMetricsImpl impl;
+  base::HistogramTester histogram_tester;
+
+  impl.RecordDroppedLogSize(99999);
+  histogram_tester.ExpectBucketCount("UMA.UnsentLogs.DroppedSize", 99999, 1);
+}
+
+TEST(UnsentLogStoreMetricsImplTest, RecordDroppedLogsNum) {
+  UnsentLogStoreMetricsImpl impl;
+  base::HistogramTester histogram_tester;
+
+  impl.RecordDroppedLogsNum(17);
+  histogram_tester.ExpectBucketCount("UMA.UnsentLogs.Dropped", 17, 1);
+}
+
 TEST(UnsentLogStoreMetricsImplTest, RecordLastUnsentLogMetadataMetrics) {
   base::test::ScopedFeatureList feature_override;
   feature_override.InitAndEnableFeature(
diff --git a/components/omnibox/browser/clipboard_provider.cc b/components/omnibox/browser/clipboard_provider.cc
index 26f5065..1d6c144 100644
--- a/components/omnibox/browser/clipboard_provider.cc
+++ b/components/omnibox/browser/clipboard_provider.cc
@@ -596,7 +596,7 @@
 
   if (!base::GetFieldTrialParamByFeatureAsBool(
           omnibox::kEnableClipboardProviderImageSuggestions,
-          OmniboxFieldTrial::kImageSearchSuggestionThumbnail, false)) {
+          OmniboxFieldTrial::kImageSearchSuggestionThumbnail, true)) {
     // If Omnibox image suggestion do not need thumbnail, release memory.
     match.search_terms_args.reset();
   }
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc
index 6c37dcb..5478e192 100644
--- a/components/omnibox/browser/omnibox_field_trial.cc
+++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -518,8 +518,10 @@
     return kMaxNumHQPUrlsIndexedAtStartupOnLowEndDevices;
   return kMaxNumHQPUrlsIndexedAtStartupOnNonLowEndDevices;
 #else
-  // Default value is set to -1 for unlimited number of urls.
-  return -1;
+  // Use 20,000 entries as a safety cap for users with spammed history,
+  // such as users who were stuck in a redirect loop with autogenerated URLs.
+  // This limit will only affect 0.01% of Windows users. crbug.com/750845.
+  return 20000;
 #endif  // defined(OS_ANDROID)
 }
 
diff --git a/components/omnibox/browser/url_index_private_data.cc b/components/omnibox/browser/url_index_private_data.cc
index 023d5d45..ce73f7a 100644
--- a/components/omnibox/browser/url_index_private_data.cc
+++ b/components/omnibox/browser/url_index_private_data.cc
@@ -436,7 +436,8 @@
   // Limiting the number of URLs indexed degrades the quality of suggestions to
   // save memory. This limit is only applied for urls indexed at startup and
   // more urls can be indexed during the browsing session. The primary use case
-  // is for Android devices where the session is typically short.
+  // is for Android devices where the session is typically short, and low-memory
+  // machines in general (Desktop or Mobile).
   const int max_urls_indexed =
       OmniboxFieldTrial::MaxNumHQPUrlsIndexedAtStartup();
   int num_urls_indexed = 0;
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc
index 4e9a0f0..308a1e72 100644
--- a/components/omnibox/common/omnibox_features.cc
+++ b/components/omnibox/common/omnibox_features.cc
@@ -22,13 +22,6 @@
     base::FEATURE_DISABLED_BY_DEFAULT;
 #endif
 
-const auto enabled_by_default_ios_only =
-#if defined(OS_IOS)
-    base::FEATURE_ENABLED_BY_DEFAULT;
-#else
-    base::FEATURE_DISABLED_BY_DEFAULT;
-#endif
-
 const auto enabled_by_default_desktop_android =
 #if defined(OS_IOS)
     base::FEATURE_DISABLED_BY_DEFAULT;
@@ -87,7 +80,7 @@
 // Feature to enable clipboard provider to suggest searching for copied images.
 const base::Feature kEnableClipboardProviderImageSuggestions{
     "OmniboxEnableClipboardProviderImageSuggestions",
-    enabled_by_default_ios_only};
+    enabled_by_default_android_ios};
 
 // Feature to enable the search provider to send a request to the suggest
 // server on focus.  This allows the suggest server to warm up, by, for
diff --git a/components/password_manager/core/browser/password_form_metrics_recorder.h b/components/password_manager/core/browser/password_form_metrics_recorder.h
index 0055514..05ce2f1 100644
--- a/components/password_manager/core/browser/password_form_metrics_recorder.h
+++ b/components/password_manager/core/browser/password_form_metrics_recorder.h
@@ -18,7 +18,7 @@
 #include "base/time/clock.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom.h"
 #include "components/autofill/core/common/signatures.h"
-#include "components/password_manager/core/browser/password_form_forward.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
diff --git a/components/password_manager/core/browser/ui/saved_passwords_presenter.cc b/components/password_manager/core/browser/ui/saved_passwords_presenter.cc
index cc91f8cd..9b8e94f 100644
--- a/components/password_manager/core/browser/ui/saved_passwords_presenter.cc
+++ b/components/password_manager/core/browser/ui/saved_passwords_presenter.cc
@@ -102,7 +102,7 @@
       PasswordStore& store =
           old_form.IsUsingAccountStore() ? *account_store_ : *profile_store_;
 
-      autofill::PasswordForm new_form = old_form;
+      PasswordForm new_form = old_form;
       new_form.username_value = new_username;
       new_form.password_value = new_password;
 
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index d6d58f5..395f684 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -16778,7 +16778,7 @@
     },
     {
       'name': 'DeviceArcDataSnapshotHours',
-      'owners': ['file://components/policy/resources/OWNERS'],
+      'owners': ['pbond@chromium.org', 'file://components/policy/resources/OWNERS'],
       'type': 'dict',
       'schema': {
         'type': 'object',
@@ -16826,7 +16826,7 @@
       'id': 794,
       'caption': '''Intervals when ARC data snapshot update process can be started for Managed Guest Sessions''',
       'tags': [],
-      'desc': '''If "DeviceArcDataSnapshotHours" policy is set, then the ARC data snapshotting mechanism is turned on. And the ARC data snapshotting update can be started automatically during the defined time intervals. When an interval starts, ARC snapshot update is required and no user is logged-in, the ARC data snapshot update process is started without user notification. If the user session is active, the UI notification is shown and have to be accepted in order to reboot a device and start ARC data snapshot update process. Note: a device is blocked for usage during the ARC data snapshot update process.''',
+      'desc': '''If "DeviceArcDataSnapshotHours" policy is set, then the ARC data snapshotting mechanism is turned on. And the ARC data snapshot update can be started automatically during the defined time intervals. When an interval starts, ARC data snapshot update is required and no user is logged-in, the ARC data snapshot update process is started without user notification. If the user session is active, the UI notification is shown and have to be accepted in order to reboot a device and start ARC data snapshot update process. Note: a device is blocked for usage during the ARC data snapshot update process.''',
     },
     {
       'name': 'IsolateOrigins',
diff --git a/components/policy/resources/policy_templates_it.xtb b/components/policy/resources/policy_templates_it.xtb
index b5c06e3..e32546b8 100644
--- a/components/policy/resources/policy_templates_it.xtb
+++ b/components/policy/resources/policy_templates_it.xtb
@@ -2923,7 +2923,7 @@
 
       Se il criterio viene impostato su False, il port forwarding nei container Crostini viene disattivato.</translation>
 <translation id="538108065117008131">Consenti a <ph name="PRODUCT_FRAME_NAME" /> di gestire i seguenti tipi di contenuto.</translation>
-<translation id="5383436189211119400">Se il criterio "DeviceArcDataSnapshotHours" viene impostato, viene attivato il meccanismo di creazione di istantanee dei dati ARC. L'aggiornamento delle istantanee dei dati ARC può essere avviato automaticamente durante gli intervalli di tempo definiti. Quando inizia un intervallo, l'aggiornamento delle istantanee dei dati ARC è necessario e non ci sono utenti che hanno eseguito l'accesso, la procedura di aggiornamento delle istantanee dei dati ARC viene avviata senza informare l'utente. Se è attiva la sessione utente, nell'interfaccia utente viene mostrata la notifica, che deve essere accettata per poter riavviare un dispositivo e avviare la procedura di aggiornamento delle istantanee dei dati ARC. Nota: durante la procedura di aggiornamento delle istantanee dei dati ARC non è possibile usare il dispositivo.</translation>
+<translation id="5383436189211119400">Se il criterio "DeviceArcDataSnapshotHours" viene impostato, viene attivato il meccanismo di creazione di istantanee dei dati ARC. L'aggiornamento delle istantanee dei dati ARC può essere avviato automaticamente durante gli intervalli di tempo definiti. Quando inizia un intervallo, l'aggiornamento delle istantanee dei dati ARC è necessario e non ci sono utenti che hanno eseguito l'accesso, la procedura di aggiornamento delle istantanee dei dati ARC viene avviata senza informare l'utente. Se è attiva la sessione utente, nell'interfaccia utente viene mostrata la notifica, che deve essere accettata per poter riavviare il dispositivo e avviare la procedura di aggiornamento delle istantanee dei dati ARC. Nota: durante la procedura di aggiornamento delle istantanee dei dati ARC non è possibile usare il dispositivo.</translation>
 <translation id="538768040137709073">Consente di attivare la funzione Appunti condivisi che permette agli utenti di inviare testi tra computer desktop Chrome e un dispositivo Android quando la sincronizzazione è attivata e l'utente ha effettuato l'accesso.
 
           Se il criterio è impostato su true, la funzionalità di invio testi tra dispositivi è attivata per gli utenti Chrome.
@@ -4479,7 +4479,7 @@
 
       Questo criterio è deprecato. Usa il criterio <ph name="PRINTERS_BULK_BLOCKLIST" />.
       </translation>
-<translation id="7358744897221281073">Se questa impostazione viene attivata, gli utenti che hanno già attivato Phone Hub potranno continuare su Chrome OS attività quali la visualizzazione delle pagine web del loro telefono.
+<translation id="7358744897221281073">Se questa impostazione viene attivata, gli utenti che hanno già attivato Phone Hub potranno continuare attività su Chrome OS, come ad esempio la visualizzazione di pagine web che avevano iniziato a consultare sul telefono.
 
       Se viene disattivata, gli utenti non potranno usare questa funzionalità. Gli utenti non potranno usare questa funzionalità anche se viene disattivato il criterio PhoneHubAllowed.
 
diff --git a/components/policy/resources/policy_templates_vi.xtb b/components/policy/resources/policy_templates_vi.xtb
index be8c59e..e58ce91 100644
--- a/components/policy/resources/policy_templates_vi.xtb
+++ b/components/policy/resources/policy_templates_vi.xtb
@@ -41,11 +41,11 @@
 
       Chính sách này chỉ ảnh hưởng đến những người có miền khớp với miền đăng ký của thiết bị. Đối với tất cả người dùng khác, cookie do IdP đặt chỉ được chuyển tới hồ sơ của người dùng trong lần đăng nhập đầu tiên của họ trên thiết bị.</translation>
 <translation id="1029052664284722254">Buộc thiết bị khởi động lại khi đăng xuất người dùng</translation>
-<translation id="1032533786864478457">Nếu bạn đặt chính sách này thành Bật, thì người dùng có thể thiết lập các thiết bị để đồng bộ hóa tin nhắn văn bản của họ với Chromebook. Người dùng phải chọn sử dụng tính năng này một cách rõ ràng thông qua việc hoàn tất quy trình thiết lập. Sau khi hoàn tất, họ có thể gửi và nhận tin nhắn văn bản trên Chromebook.
+<translation id="1032533786864478457">Nếu bạn đặt chính sách này thành Bật, thì người dùng có thể thiết lập các thiết bị của họ để đồng bộ hóa tin nhắn văn bản của họ với Chromebook. Người dùng phải chọn sử dụng tính năng này một cách rõ ràng thông qua việc hoàn tất quy trình thiết lập. Sau khi hoàn tất, họ có thể gửi và nhận tin nhắn văn bản trên Chromebook.
 
       Nếu bạn đặt chính sách này thành Tắt, thì người dùng sẽ không thể thiết lập tính năng đồng bộ hóa tin nhắn văn bản.
 
-      Nếu bạn không đặt chính sách này thì theo mặc định, người dùng khác chứ không phải người dùng được quản lý sẽ được phép dùng tính năng nêu trên.</translation>
+      Nếu bạn không đặt chính sách này, người dùng được quản lý sẽ không thể sử dụng tính năng này theo mặc định, nhưng những người dùng khác có thể sử dụng tính năng này.</translation>
 <translation id="1040446814317236570">Bật tách URL PAC (cho https://)</translation>
 <translation id="1046484220783400299">Bật các tính năng nền tảng web không dùng nữa trong một khoảng thời gian giới hạn</translation>
 <translation id="1047128214168693844">Không cho phép bất kỳ trang web nào theo dõi vị trí thực của người dùng</translation>
@@ -663,9 +663,9 @@
           Nếu bạn tắt tùy chọn cài đặt này, thì người dùng sẽ không được phép chuyển tệp. Nếu bạn bật hoặc không đặt tùy chọn cài đặt này, thì người dùng có thể chuyển tệp.</translation>
 <translation id="2057317273526988987">Cho phép truy cập vào một danh sách các URL</translation>
 <translation id="2061810934846663491">Định cấu hình tên miền bắt buộc cho máy chủ truy cập từ xa</translation>
-<translation id="2069350366303315077">Khi bạn đặt chính sách này thành Bật, thì <ph name="PRODUCT_NAME" /> sẽ thực thi các phiên khách và ngăn chặn phiên đăng nhập vào hồ sơ. Phiên đăng nhập khách là hồ sơ <ph name="PRODUCT_NAME" />, trong đó các cửa sổ đều ở Chế độ ẩn danh.
+<translation id="2069350366303315077">Khi bạn đặt chính sách này thành Bật, thì <ph name="PRODUCT_NAME" /> sẽ thực thi các phiên khách và ngăn chặn các phiên đăng nhập vào hồ sơ. Phiên đăng nhập khách là các hồ sơ <ph name="PRODUCT_NAME" />, trong đó các cửa sổ đều ở Chế độ ẩn danh.
 
-      Nếu bạn không đặt hoặc đặt chính sách này thành Tắt hay tắt Chế độ khách trên trình duyệt, (thông qua <ph name="BROWSER_GUEST_MODE_ENABLED_POLICY_NAME" />), thì người dùng có thể sử dụng các hồ sơ mới và hiện có.</translation>
+      Nếu bạn không đặt hoặc đặt chính sách này thành Tắt hay tắt Chế độ khách trên trình duyệt (thông qua <ph name="BROWSER_GUEST_MODE_ENABLED_POLICY_NAME" />), thì người dùng có thể sử dụng các hồ sơ mới và hiện có.</translation>
 <translation id="2073552873076775140">Cho phép đăng nhập vào <ph name="PRODUCT_NAME" /></translation>
 <translation id="2075732129949889165">Playbook Crostini Ansible</translation>
 <translation id="2077129598763517140">Sử dụng chế độ tăng tốc phần cứng khi khả dụng</translation>
@@ -1000,7 +1000,7 @@
 <translation id="2482676533225429905">Nhắn tin gốc</translation>
 <translation id="2483146640187052324">Dự đoán tác vụ mạng trên kết nối mạng bất kỳ</translation>
 <translation id="2498238926436517902">Luôn tự động ẩn giá</translation>
-<translation id="250022556568924228">Nếu bạn đặt chính sách này, <ph name="PRODUCT_OS_NAME" /> sẽ tải Điều khoản dịch vụ xuống và hiển thị với người dùng ở bất cứ thời điểm nào bắt đầu phiên truy cập tài khoản trên thiết bị. Người dùng chỉ có thể đăng nhập vào phiên đó sau khi chấp nhận Điều khoản dịch vụ.
+<translation id="250022556568924228">Nếu bạn đặt chính sách này, <ph name="PRODUCT_OS_NAME" /> sẽ tải Điều khoản dịch vụ xuống và hiển thị với người dùng ở bất cứ thời điểm nào phiên truy cập tài khoản trên thiết bị bắt đầu. Người dùng chỉ có thể đăng nhập vào phiên đó sau khi chấp nhận Điều khoản dịch vụ.
 
       Nếu bạn không đặt chính sách này, Điều khoản dịch vụ sẽ không xuất hiện.
 
@@ -1192,11 +1192,11 @@
 <translation id="2759224876420453487">Kiểm soát hoạt động của người dùng trong một phiên đa cấu hình</translation>
 <translation id="2759426227259007018">Nếu bạn đặt chính sách này, hệ thống sẽ chỉ định những ứng dụng mà người dùng có thể bật làm ứng dụng ghi chú trên màn hình khóa của <ph name="PRODUCT_OS_NAME" />.
 
-      Nếu bạn bật ứng dụng ghi chú ưa thích trên màn hình khóa, thì thành phần trên giao diện người dùng để chạy ứng dụng đó sẽ xuất hiện trên màn hình. Sau khi chạy, ứng dụng có thể tạo một cửa sổ ở đầu màn hình khóa và tạo các ghi chú trong ngữ cảnh này. Ứng dụng này có thể nhập các ghi chú đã tạo vào phiên truy cập của người dùng chính, khi phiên được mở khóa. Bạn chỉ dùng được ứng dụng ghi chú của <ph name="PRODUCT_NAME" /> trên màn hình khóa.
+      Nếu ứng dụng ghi chú ưa thích được bật trên màn hình khóa, thì thành phần trên giao diện người dùng để chạy ứng dụng đó sẽ xuất hiện trên màn hình. Sau khi chạy, ứng dụng có thể tạo một cửa sổ ở phía trên màn hình khóa và tạo các ghi chú trong bối cảnh này. Ứng dụng này có thể nhập các ghi chú đã tạo vào phiên truy cập của người dùng chính, khi phiên được mở khóa. Chỉ các ứng dụng ghi chú của <ph name="PRODUCT_NAME" /> mới được hỗ trợ trên màn hình khóa.
 
-      Nếu bạn đặt chính sách này, người dùng có thể bật một ứng dụng trên màn hình khóa khi mã nhận dạng tiện ích của ứng dụng đó có trong giá trị danh sách của chính sách. Do vậy, khi bạn đặt chính sách này thành một danh sách trống, tính năng ghi chú trên màn hình khóa sẽ tắt. Xin lưu ý rằng không phải cứ có mã nhận dạng ứng dụng trong chính sách là người dùng có thể bật ứng dụng đó làm ứng dụng ghi chú trên màn hình khóa. Ví dụ: trên <ph name="PRODUCT_NAME" /> 61, chúng tôi cũng hạn chế một số ứng dụng có sẵn theo nền tảng.
+      Nếu bạn đặt chính sách này, người dùng có thể bật một ứng dụng trên màn hình khóa nếu mã tiện ích của ứng dụng đó có trong giá trị danh sách của chính sách. Do vậy, khi bạn đặt chính sách này thành một danh sách trống, tính năng ghi chú trên màn hình khóa sẽ bị tắt. Xin lưu ý rằng không phải cứ có mã ứng dụng trong chính sách là người dùng có thể bật ứng dụng đó làm ứng dụng ghi chú trên màn hình khóa. Ví dụ: trên <ph name="PRODUCT_NAME" /> 61, chúng tôi cũng hạn chế một số ứng dụng có sẵn theo nền tảng.
 
-      Nếu bạn không đặt chính sách này, sẽ không có hạn chế nào do chính sách này áp dụng cho một số ứng dụng mà người dùng có thể bật trên màn hình khóa.</translation>
+      Nếu bạn không đặt chính sách này, sẽ không có hạn chế nào được áp dụng theo chính sách này cho một số ứng dụng mà người dùng có thể bật trên màn hình khóa.</translation>
 <translation id="2761483219396643566">Thời gian chờ cảnh báo trạng thái không sử dụng khi chạy trên nguồn pin</translation>
 <translation id="2765601181281280493">Khi đặt chính sách này, bạn có thể tạo danh sách các mẫu URL chỉ định những trang web không được phép yêu cầu người dùng cấp quyền truy cập vào một cổng nối tiếp.
 
@@ -1542,7 +1542,7 @@
       Các trang web được định cấu hình sẽ tự động mở trong trình duyệt khác không phải là <ph name="PRODUCT_NAME" />.</translation>
 <translation id="3255624750680556186">Nếu bạn không đặt hoặc đặt chính sách này thành Bật, thì thiết bị sẽ kích hoạt chức năng Powerwash.
 
-      Nếu bạn đặt chính sách này thành Tắt, thì thiết bị sẽ không kích hoạt chức năng Powerwash. Trường hợp ngoại lệ là thiết bị vẫn có thể kích hoạt chức năng Powerwash nếu bạn đặt chính sách <ph name="TPM_FIRMWARE_UPDATE_SETTINGS_NAME" /> thành một giá trị cho phép cập nhật chương trình cơ sở TPM, tuy nhiên chương trình đó lại chưa được cập nhật.</translation>
+      Nếu bạn đặt chính sách này thành Tắt, thì thiết bị sẽ không kích hoạt chức năng Powerwash. Một trường hợp ngoại lệ là thiết bị vẫn có thể kích hoạt chức năng Powerwash nếu bạn đặt chính sách <ph name="TPM_FIRMWARE_UPDATE_SETTINGS_NAME" /> thành một giá trị cho phép cập nhật chương trình cơ sở TPM, tuy nhiên chương trình đó lại chưa được cập nhật.</translation>
 <translation id="3255762580838224124">Nếu đặt chính sách này, thì mỗi màn hình sẽ xoay theo một hướng chỉ định mỗi khi khởi động lại và vào lần đầu tiên màn hình được kết nối sau khi giá trị chính sách thay đổi. Người dùng có thể thay đổi chế độ xoay màn hình thông qua trang cài đặt sau khi đăng nhập. Tuy nhiên, chế độ này sẽ chuyển về như cũ vào lần khởi động lại tiếp theo. Chính sách này áp dụng cho màn hình chính và phụ.
 
       Nếu bạn chưa đặt chính sách này, thì giá trị mặc định là 0 độ và người dùng có thể thay đổi giá trị này. Trong trường hợp này, giá trị mặc định không được áp dụng thêm lần nữa khi khởi động lại.</translation>
@@ -3440,9 +3440,9 @@
 <translation id="6034341625190551415">Kiểm soát phiên công khai và loại tài khoản kiosk.</translation>
 <translation id="6034603289689965535">Cho phép trang hiển thị cửa sổ bật lên khi đang hủy tải trang</translation>
 <translation id="6036523166753287175">Bật tính năng chặn tường lửa từ máy chủ truy cập từ xa</translation>
-<translation id="603768430528561926">Nếu bạn không đặt hoặc đặt chính sách này thành Bật, thì người dùng thiết bị của doanh nghiệp sẽ có thể đổi ưu đãi bằng cách đăng ký<ph name="PRODUCT_OS_NAME" />.
+<translation id="603768430528561926">Nếu bạn không đặt hoặc đặt chính sách này thành Bật, thì người dùng thiết bị của doanh nghiệp sẽ có thể sử dụng ưu đãi bằng cách đăng ký<ph name="PRODUCT_OS_NAME" />.
 
-      Nếu bạn đặt chính sách này thành Tắt, thì người dùng không thể đổi các ưu đãi này.</translation>
+      Nếu bạn đặt chính sách này thành Tắt, thì người dùng không thể sử dụng các ưu đãi này.</translation>
 <translation id="6048199181629830227">Bật tính năng quản lý nguồn điện khi chuyển đổi vào giờ cao điểm</translation>
 <translation id="6054485492411959335">Chỉ định những máy in mà người dùng có thể sử dụng.
 
@@ -3660,7 +3660,7 @@
       Nếu bạn không đặt chính sách này hoặc danh sách trống, thì tất cả lược đồ đều truy cập được trong <ph name="PRODUCT_NAME" />.</translation>
 <translation id="6338982178236723271">Báo cáo thông tin về hệ thống</translation>
 <translation id="6342187235303612558">Chặn người dùng tải lên hoặc tải xuống các tệp hiện không được hỗ trợ quét tìm phần mềm độc hại hoặc quét tìm dựa trên tính năng Ngăn chặn mất dữ liệu.</translation>
-<translation id="6353890097388312479">Nếu bạn không đặt hoặc đặt chính sách này thành Tất cả (0), thì người dùng có thể chỉnh sửa các tùy chọn cài đặt tin cậy cho tất cả chứng chỉ CA, xóa chứng chỉ do người dùng nhập và nhập chứng chỉ bằng Trình quản lý chứng chỉ. Nếu bạn đặt chính sách này thành UserOnly (1), người dùng có thể chỉ quản lý các chứng chỉ do người dùng nhập nhưng không thể thay đổi các tùy chọn cài đặt tin cậy của chứng chỉ tích hợp. Nếu bạn đặt chính sách này thành Không (2), người dùng có thể xem (nhưng không thể quản lý) chứng chỉ CA.</translation>
+<translation id="6353890097388312479">Nếu bạn không đặt hoặc đặt chính sách này thành Tất cả (0), thì người dùng có thể chỉnh sửa các tùy chọn cài đặt về độ tin cậy cho tất cả chứng chỉ CA, xóa chứng chỉ do người dùng nhập và nhập chứng chỉ bằng Trình quản lý chứng chỉ. Nếu bạn đặt chính sách này thành UserOnly (1), người dùng có thể chỉ quản lý các chứng chỉ do người dùng nhập nhưng không thể thay đổi các tùy chọn cài đặt về độ tin cậy của chứng chỉ tích hợp. Nếu bạn đặt chính sách này thành Không (2), người dùng có thể xem (nhưng không thể quản lý) các chứng chỉ CA.</translation>
 <translation id="6366574325767783825">Nếu bạn không đặt hoặc đặt chính sách này thành True, thì <ph name="PRODUCT_NAME" /> sẽ chấp nhận nội dung web được phân phối dưới dạng Signed HTTP Exchanges.
 
       Nếu bạn đặt chính sách này thành False, thì Signed HTTP Exchanges sẽ không tải được.</translation>
@@ -3756,11 +3756,11 @@
 
       Nếu bạn đặt chính sách này, hệ thống sẽ chỉ định những ứng dụng mà người dùng có thể bật làm ứng dụng ghi chú trên màn hình khóa của <ph name="PRODUCT_OS_NAME" />.
 
-      Nếu bạn bật ứng dụng ghi chú ưa thích trên màn hình khóa, thì thành phần trên giao diện người dùng để chạy ứng dụng đó sẽ xuất hiện trên màn hình. Sau khi chạy, ứng dụng có thể tạo một cửa sổ ở đầu màn hình khóa và tạo các ghi chú trong ngữ cảnh này. Ứng dụng này có thể nhập các ghi chú đã tạo vào phiên truy cập của người dùng chính, khi phiên được mở khóa. Bạn chỉ dùng được ứng dụng ghi chú của <ph name="PRODUCT_NAME" /> trên màn hình khóa.
+      Nếu ứng dụng ghi chú ưa thích được bật trên màn hình khóa, thì thành phần trên giao diện người dùng để chạy ứng dụng đó sẽ xuất hiện trên màn hình. Sau khi chạy, ứng dụng có thể tạo một cửa sổ ở phía trên màn hình khóa và tạo các ghi chú trong bối cảnh này. Ứng dụng này có thể nhập các ghi chú đã tạo vào phiên truy cập của người dùng chính, khi phiên được mở khóa. Chỉ các ứng dụng ghi chú của <ph name="PRODUCT_NAME" /> mới được hỗ trợ trên màn hình khóa.
 
-      Nếu bạn đặt chính sách này, người dùng có thể bật một ứng dụng trên màn hình khóa khi mã nhận dạng tiện ích của ứng dụng đó có trong giá trị danh sách của chính sách. Do vậy, khi bạn đặt chính sách này thành một danh sách trống, tính năng ghi chú trên màn hình khóa sẽ tắt. Xin lưu ý rằng không phải cứ có mã nhận dạng ứng dụng trong chính sách là người dùng có thể bật ứng dụng đó làm ứng dụng ghi chú trên màn hình khóa. Ví dụ: trên <ph name="PRODUCT_NAME" /> 61, chúng tôi cũng hạn chế một số ứng dụng có sẵn theo nền tảng.
+      Nếu bạn đặt chính sách này, người dùng có thể bật một ứng dụng trên màn hình khóa nếu mã tiện ích của ứng dụng đó có trong giá trị danh sách của chính sách. Do vậy, khi bạn đặt chính sách này thành một danh sách trống, tính năng ghi chú trên màn hình khóa sẽ bị tắt. Xin lưu ý rằng không phải cứ có mã ứng dụng trong chính sách là người dùng có thể bật ứng dụng đó làm ứng dụng ghi chú trên màn hình khóa. Ví dụ: trên <ph name="PRODUCT_NAME" /> 61, chúng tôi cũng hạn chế một số ứng dụng có sẵn theo nền tảng.
 
-      Nếu bạn không đặt chính sách này, sẽ không có hạn chế nào do chính sách này áp dụng cho một số ứng dụng mà người dùng có thể bật trên màn hình khóa.</translation>
+      Nếu bạn không đặt chính sách này, sẽ không có hạn chế nào áp dụng theo chính sách này cho một số ứng dụng mà người dùng có thể bật trên màn hình khóa.</translation>
 <translation id="6506486086262398387">Nếu bạn đặt chính sách này thành Bật, tính năng Chia sẻ tệp trong mạng của <ph name="PRODUCT_OS_NAME" /> sẽ sử dụng NTLM để xác thực các lượt chia sẻ SMB nếu cần. Nếu bạn đặt chính sách này thành Tắt, tính năng xác thực bằng NTLM cho các lượt chia sẻ SMB sẽ bị tắt.
 
       Nếu bạn không đặt chính sách này, chế độ mặc định sẽ là tắt đối với người dùng được quản lý và bật đối với người dùng khác.</translation>
diff --git a/components/power_metrics/BUILD.gn b/components/power_metrics/BUILD.gn
new file mode 100644
index 0000000..64daf044
--- /dev/null
+++ b/components/power_metrics/BUILD.gn
@@ -0,0 +1,17 @@
+# 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.
+
+if (is_android) {
+  static_library("power_metrics") {
+    sources = [
+      "android_battery_metrics.cc",
+      "android_battery_metrics.h",
+    ]
+
+    deps = [
+      "//base",
+      "//net",
+    ]
+  }
+}
diff --git a/components/power_metrics/DEPS b/components/power_metrics/DEPS
new file mode 100644
index 0000000..ba0a8ec
--- /dev/null
+++ b/components/power_metrics/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+net/android",
+]
diff --git a/components/power_metrics/OWNERS b/components/power_metrics/OWNERS
new file mode 100644
index 0000000..bf09681
--- /dev/null
+++ b/components/power_metrics/OWNERS
@@ -0,0 +1,5 @@
+eseckler@chromium.org
+skyostil@chromium.org
+khokhlov@google.com
+
+# COMPONENT: Speed>Metrics
diff --git a/chrome/browser/android/battery/android_battery_metrics.cc b/components/power_metrics/android_battery_metrics.cc
similarity index 91%
rename from chrome/browser/android/battery/android_battery_metrics.cc
rename to components/power_metrics/android_battery_metrics.cc
index 8ccc81c8..8d9fd5d04 100644
--- a/chrome/browser/android/battery/android_battery_metrics.cc
+++ b/components/power_metrics/android_battery_metrics.cc
@@ -2,17 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/android/battery/android_battery_metrics.h"
+#include "components/power_metrics/android_battery_metrics.h"
 
 #include "base/android/radio_utils.h"
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/optional.h"
 #include "base/power_monitor/power_monitor.h"
 #include "net/android/network_library.h"
 #include "net/android/traffic_stats.h"
 
+namespace power_metrics {
 namespace {
 
 void Report30SecondRadioUsage(int64_t tx_bytes, int64_t rx_bytes) {
@@ -115,10 +117,7 @@
 constexpr base::TimeDelta AndroidBatteryMetrics::kMetricsInterval;
 
 AndroidBatteryMetrics::AndroidBatteryMetrics()
-    : app_state_listener_(base::android::ApplicationStatusListener::New(
-          base::BindRepeating(&AndroidBatteryMetrics::OnAppStateChanged,
-                              base::Unretained(this)))),
-      app_state_(base::android::ApplicationStatusListener::GetState()),
+    : app_visible_(false),
       on_battery_power_(base::PowerMonitor::IsOnBatteryPower()) {
   base::PowerMonitor::AddObserver(this);
   UpdateMetricsEnabled();
@@ -128,10 +127,9 @@
   base::PowerMonitor::RemoveObserver(this);
 }
 
-void AndroidBatteryMetrics::OnAppStateChanged(
-    base::android::ApplicationState state) {
+void AndroidBatteryMetrics::OnAppVisibilityChanged(bool visible) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  app_state_ = state;
+  app_visible_ = visible;
   UpdateMetricsEnabled();
 }
 
@@ -144,12 +142,10 @@
 void AndroidBatteryMetrics::UpdateMetricsEnabled() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  // We want to attribute battery drain to Chrome while it is in the foreground.
-  // Battery drain will only be reflected in remaining battery capacity when the
-  // device is not on a charger.
-  bool should_be_enabled =
-      app_state_ == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES &&
-      on_battery_power_;
+  // We want to attribute battery drain to chromium while the embedding app is
+  // visible. Battery drain will only be reflected in remaining battery capacity
+  // when the device is not on a charger.
+  bool should_be_enabled = app_visible_ && on_battery_power_;
 
   if (should_be_enabled && !metrics_timer_.IsRunning()) {
     // Capture first capacity measurement and enable the repeating timer.
@@ -237,3 +233,5 @@
 bool AndroidBatteryMetrics::IsMeasuringDrainExclusively() const {
   return observed_capacity_drops_ >= 2;
 }
+
+}  // namespace power_metrics
diff --git a/chrome/browser/android/battery/android_battery_metrics.h b/components/power_metrics/android_battery_metrics.h
similarity index 64%
rename from chrome/browser/android/battery/android_battery_metrics.h
rename to components/power_metrics/android_battery_metrics.h
index cc7040d3..0f8c91e 100644
--- a/chrome/browser/android/battery/android_battery_metrics.h
+++ b/components/power_metrics/android_battery_metrics.h
@@ -2,44 +2,47 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ANDROID_BATTERY_ANDROID_BATTERY_METRICS_H_
-#define CHROME_BROWSER_ANDROID_BATTERY_ANDROID_BATTERY_METRICS_H_
+#ifndef COMPONENTS_POWER_METRICS_ANDROID_BATTERY_METRICS_H_
+#define COMPONENTS_POWER_METRICS_ANDROID_BATTERY_METRICS_H_
 
-#include "base/android/application_status_listener.h"
 #include "base/macros.h"
 #include "base/power_monitor/power_observer.h"
 #include "base/sequence_checker.h"
 #include "base/timer/timer.h"
 
-// Records metrics around battery usage on Android.
+namespace power_metrics {
+
+// Records metrics around battery usage on Android. The metrics are only tracked
+// while the device is not charging and the app is visible (embedder should call
+// OnAppVisibilityChanged()). This class is not thread-safe.
 class AndroidBatteryMetrics : public base::PowerObserver {
  public:
   AndroidBatteryMetrics();
   ~AndroidBatteryMetrics() override;
 
-  // base::PowerObserver implementation:
-  void OnPowerStateChange(bool on_battery_power) override;
+  // Should be called by the embedder when the embedder app becomes visible or
+  // invisible.
+  void OnAppVisibilityChanged(bool visible);
 
  private:
-  // Called by base::android::ApplicationStatusListener.
-  void OnAppStateChanged(base::android::ApplicationState);
+  // base::PowerObserver implementation:
+  void OnPowerStateChange(bool on_battery_power) override;
 
   void UpdateMetricsEnabled();
   void CaptureAndReportMetrics();
   void UpdateAndReportRadio();
 
   // Whether or not we've seen at least two consecutive capacity drops while
-  // Chrome was the foreground app. Battery drain reported prior to this could
+  // the embedding app was visible. Battery drain reported prior to this could
   // be caused by a different app.
   bool IsMeasuringDrainExclusively() const;
 
   // Battery drain is captured and reported periodically in this interval while
-  // the device is on battery power and Chrome is the foreground activity.
+  // the device is on battery power and the app is visible.
   static constexpr base::TimeDelta kMetricsInterval =
       base::TimeDelta::FromSeconds(30);
 
-  std::unique_ptr<base::android::ApplicationStatusListener> app_state_listener_;
-  base::android::ApplicationState app_state_;
+  bool app_visible_;
   bool on_battery_power_;
   int last_remaining_capacity_uah_ = 0;
   int64_t last_tx_bytes_ = -1;
@@ -47,8 +50,7 @@
   base::RepeatingTimer metrics_timer_;
   int skipped_timers_ = 0;
 
-  // Number of consecutive charge drops seen while the app has been in the
-  // foreground.
+  // Number of consecutive charge drops seen while the app has been visible.
   int observed_capacity_drops_ = 0;
 
   SEQUENCE_CHECKER(sequence_checker_);
@@ -56,4 +58,6 @@
   DISALLOW_COPY_AND_ASSIGN(AndroidBatteryMetrics);
 };
 
-#endif  // CHROME_BROWSER_ANDROID_BATTERY_ANDROID_BATTERY_METRICS_H_
+}  // namespace power_metrics
+
+#endif  // COMPONENTS_POWER_METRICS_ANDROID_BATTERY_METRICS_H_
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
index 4e36d45..3830168 100644
--- a/components/printing/renderer/print_render_frame_helper.cc
+++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -44,6 +44,7 @@
 #include "third_party/blink/public/common/css/page_orientation.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
 #include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom.h"
+#include "third_party/blink/public/mojom/page/widget.mojom.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_data.h"
 #include "third_party/blink/public/platform/web_double_size.h"
@@ -696,16 +697,25 @@
       nullptr);
 
   blink::WebWidgetClient web_widget_client;
+  mojo::AssociatedRemote<blink::mojom::FrameWidget> frame_widget;
+  mojo::PendingAssociatedReceiver<blink::mojom::FrameWidget>
+      frame_widget_receiver =
+          frame_widget.BindNewEndpointAndPassDedicatedReceiver();
+
+  mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> frame_widget_host;
+  ignore_result(frame_widget_host.BindNewEndpointAndPassDedicatedReceiver());
+
+  mojo::AssociatedRemote<blink::mojom::Widget> widget_remote;
+  mojo::PendingAssociatedReceiver<blink::mojom::Widget> widget_receiver =
+      widget_remote.BindNewEndpointAndPassDedicatedReceiver();
+
+  mojo::AssociatedRemote<blink::mojom::WidgetHost> widget_host_remote;
+  ignore_result(widget_host_remote.BindNewEndpointAndPassDedicatedReceiver());
+
   blink::WebFrameWidget::CreateForMainFrame(
-      &web_widget_client, frame,
-      blink::CrossVariantMojoAssociatedRemote<
-          blink::mojom::FrameWidgetHostInterfaceBase>(),
-      blink::CrossVariantMojoAssociatedReceiver<
-          blink::mojom::FrameWidgetInterfaceBase>(),
-      blink::CrossVariantMojoAssociatedRemote<
-          blink::mojom::WidgetHostInterfaceBase>(),
-      blink::CrossVariantMojoAssociatedReceiver<
-          blink::mojom::WidgetInterfaceBase>());
+      &web_widget_client, frame, frame_widget_host.Unbind(),
+      std::move(frame_widget_receiver), widget_host_remote.Unbind(),
+      std::move(widget_receiver));
   web_view->DidAttachLocalMainFrame();
 
   base::Value html(
@@ -942,16 +952,26 @@
   blink::WebLocalFrame* main_frame = blink::WebLocalFrame::CreateMainFrame(
       web_view, this, nullptr, base::UnguessableToken::Create(), nullptr);
   frame_.Reset(main_frame);
+  blink::WebWidgetClient web_widget_client;
+  mojo::AssociatedRemote<blink::mojom::FrameWidget> frame_widget;
+  mojo::PendingAssociatedReceiver<blink::mojom::FrameWidget>
+      frame_widget_receiver =
+          frame_widget.BindNewEndpointAndPassDedicatedReceiver();
+
+  mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> frame_widget_host;
+  ignore_result(frame_widget_host.BindNewEndpointAndPassDedicatedReceiver());
+
+  mojo::AssociatedRemote<blink::mojom::Widget> widget_remote;
+  mojo::PendingAssociatedReceiver<blink::mojom::Widget> widget_receiver =
+      widget_remote.BindNewEndpointAndPassDedicatedReceiver();
+
+  mojo::AssociatedRemote<blink::mojom::WidgetHost> widget_host_remote;
+  ignore_result(widget_host_remote.BindNewEndpointAndPassDedicatedReceiver());
+
   blink::WebFrameWidget::CreateForMainFrame(
-      this, main_frame,
-      blink::CrossVariantMojoAssociatedRemote<
-          blink::mojom::FrameWidgetHostInterfaceBase>(),
-      blink::CrossVariantMojoAssociatedReceiver<
-          blink::mojom::FrameWidgetInterfaceBase>(),
-      blink::CrossVariantMojoAssociatedRemote<
-          blink::mojom::WidgetHostInterfaceBase>(),
-      blink::CrossVariantMojoAssociatedReceiver<
-          blink::mojom::WidgetInterfaceBase>());
+      this, main_frame, frame_widget_host.Unbind(),
+      std::move(frame_widget_receiver), widget_host_remote.Unbind(),
+      std::move(widget_receiver));
   web_view->DidAttachLocalMainFrame();
   node_to_print_.Reset();
 
diff --git a/components/security_interstitials/content/blocked_interception_blocking_page.cc b/components/security_interstitials/content/blocked_interception_blocking_page.cc
index 4e83727..340cde9f 100644
--- a/components/security_interstitials/content/blocked_interception_blocking_page.cc
+++ b/components/security_interstitials/content/blocked_interception_blocking_page.cc
@@ -16,7 +16,6 @@
 #include "content/public/browser/ssl_status.h"
 #include "content/public/browser/web_contents.h"
 #include "net/base/net_errors.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 
 using content::NavigationController;
 using content::NavigationEntry;
diff --git a/components/security_interstitials/content/legacy_tls_blocking_page.cc b/components/security_interstitials/content/legacy_tls_blocking_page.cc
index 93d6e0f4..38ec49e3b 100644
--- a/components/security_interstitials/content/legacy_tls_blocking_page.cc
+++ b/components/security_interstitials/content/legacy_tls_blocking_page.cc
@@ -16,7 +16,6 @@
 #include "content/public/browser/ssl_status.h"
 #include "content/public/browser/web_contents.h"
 #include "net/base/net_errors.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 
 using content::NavigationController;
 using content::NavigationEntry;
diff --git a/components/security_interstitials/content/ssl_blocking_page.cc b/components/security_interstitials/content/ssl_blocking_page.cc
index a45ac94..50fc2d5 100644
--- a/components/security_interstitials/content/ssl_blocking_page.cc
+++ b/components/security_interstitials/content/ssl_blocking_page.cc
@@ -26,7 +26,6 @@
 #include "content/public/browser/ssl_status.h"
 #include "content/public/browser/web_contents.h"
 #include "net/base/net_errors.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 
 using base::TimeTicks;
 using content::NavigationEntry;
diff --git a/components/services/filesystem/directory_test_helper.cc b/components/services/filesystem/directory_test_helper.cc
index b9904f7c..4e878532 100644
--- a/components/services/filesystem/directory_test_helper.cc
+++ b/components/services/filesystem/directory_test_helper.cc
@@ -52,8 +52,8 @@
 
 mojo::Remote<mojom::Directory> DirectoryTestHelper::CreateTempDir() {
   mojo::Remote<mojom::Directory> remote;
-  blocking_state_.Post(FROM_HERE, &BlockingState::BindNewTempDirectory,
-                       remote.BindNewPipeAndPassReceiver());
+  blocking_state_.AsyncCall(&BlockingState::BindNewTempDirectory)
+      .WithArgs(remote.BindNewPipeAndPassReceiver());
   return remote;
 }
 
diff --git a/components/services/patch/public/mojom/file_patcher.mojom b/components/services/patch/public/mojom/file_patcher.mojom
index ab0be5b..a986305 100644
--- a/components/services/patch/public/mojom/file_patcher.mojom
+++ b/components/services/patch/public/mojom/file_patcher.mojom
@@ -5,21 +5,22 @@
 module patch.mojom;
 
 import "mojo/public/mojom/base/file.mojom";
+import "mojo/public/mojom/base/read_only_file.mojom";
 
 interface FilePatcher {
   // Patch |input_file| with |patch_file| using the bsdiff algorithm
   // (Courgette's version) and place the output in |output_file|.
   // Returns |result| bsdiff::BSDiffStatus::OK on success.
   PatchFileBsdiff(
-      mojo_base.mojom.File input_file,
-      mojo_base.mojom.File patch_file,
+      mojo_base.mojom.ReadOnlyFile input_file,
+      mojo_base.mojom.ReadOnlyFile patch_file,
       mojo_base.mojom.File output_file) => (int32 result);
 
   // Patch |input_file| with |patch_file| using the Courgette algorithm
   // and place the output in |output_file|.
   // Returns |result| courgette::Status::C_OK on success.
   PatchFileCourgette(
-      mojo_base.mojom.File input_file,
-      mojo_base.mojom.File patch_file,
+      mojo_base.mojom.ReadOnlyFile input_file,
+      mojo_base.mojom.ReadOnlyFile patch_file,
       mojo_base.mojom.File output_file) => (int32 result);
 };
diff --git a/components/services/unzip/public/mojom/unzipper.mojom b/components/services/unzip/public/mojom/unzipper.mojom
index 8fd46f5a..2822066c 100644
--- a/components/services/unzip/public/mojom/unzipper.mojom
+++ b/components/services/unzip/public/mojom/unzipper.mojom
@@ -5,8 +5,8 @@
 module unzip.mojom;
 
 import "components/services/filesystem/public/mojom/directory.mojom";
-import "mojo/public/mojom/base/file.mojom";
 import "mojo/public/mojom/base/file_path.mojom";
+import "mojo/public/mojom/base/read_only_file.mojom";
 
 interface UnzipFilter {
   [Sync]
@@ -16,14 +16,14 @@
 interface Unzipper {
   // Unzip |zip_file| into |output_dir|.
   // Returns true on success, false otherwise.
-  Unzip(mojo_base.mojom.File zip_file,
+  Unzip(mojo_base.mojom.ReadOnlyFile zip_file,
         pending_remote<filesystem.mojom.Directory> output_dir)
        => (bool result);
 
   // Same as |unzip| but only includes the files for which |filter| returns
   // true. Note that this incurs one IPC for each file of the archive.
   UnzipWithFilter(
-      mojo_base.mojom.File zip_file,
+      mojo_base.mojom.ReadOnlyFile zip_file,
       pending_remote<filesystem.mojom.Directory> output_dir,
       pending_remote<UnzipFilter> filter) => (bool result);
 };
diff --git a/components/strings/components_google_chrome_strings_iw.xtb b/components/strings/components_google_chrome_strings_iw.xtb
index 8476dc11..75575a94 100644
--- a/components/strings/components_google_chrome_strings_iw.xtb
+++ b/components/strings/components_google_chrome_strings_iw.xtb
@@ -19,15 +19,15 @@
           ‏&gt;
           <ph name="PROXIES_TITLE" />
           ובדוק שהתצורה שלך מוגדרת לאפשרות "ללא שרת proxy‏" או "ישיר".</translation>
-<translation id="6341737370356890233">‏עבור אל
+<translation id="6341737370356890233">‏יש לעבור אל
         תפריט Chrome‏ &gt;
         <ph name="SETTINGS_TITLE" />
         &gt;
         <ph name="ADVANCED_TITLE" />
-        ובטל את הבחירה באפשרות '<ph name="NO_PREFETCH_DESCRIPTION" />'.
+        ולבטל את הבחירה באפשרות '<ph name="NO_PREFETCH_DESCRIPTION" />'.
         אם פעולה זו אינה פותרת את הבעיה, מומלץ לבחור שוב באפשרות זו
         לקבלת ביצועים משופרים.</translation>
-<translation id="6855094794438142393">‏עבור אל
+<translation id="6855094794438142393">‏יש לעבור אל
           תפריט Chrome ‏&gt;
           <ph name="SETTINGS_TITLE" />
           &gt;
@@ -36,7 +36,7 @@
           <ph name="PROXIES_TITLE" />
           &gt;
           הגדרות LAN
-          ובטל את הבחירה באפשרות "השתמש בשרת עבור רשת LAN".</translation>
+          ולבטל את הבחירה באפשרות "שימוש בשרת עבור רשת LAN".</translation>
 <translation id="8187289872471304532">‏עבור אל
           'יישומים' &gt; 'העדפות מערכת' &gt; 'רשת' &gt; 'מתקדם' &gt; שרתי Proxy'
           ובטל את הבחירה בשרתי proxy שנבחרו.</translation>
diff --git a/components/strings/components_strings_bn.xtb b/components/strings/components_strings_bn.xtb
index b546497..57d7963e 100644
--- a/components/strings/components_strings_bn.xtb
+++ b/components/strings/components_strings_bn.xtb
@@ -284,6 +284,7 @@
 <translation id="204357726431741734">আপনার Google অ্যাকাউন্টে সেভ করা পাসওয়ার্ড ব্যবহার করতে সাইন-ইন করুন</translation>
 <translation id="2053111141626950936"><ph name="LANGUAGE" /> ভাষার পৃষ্ঠা অনুবাদ করা হবে না।</translation>
 <translation id="2053553514270667976">পিন কোড</translation>
+<translation id="2054665754582400095">আপনার উপস্থিতি</translation>
 <translation id="2064691555167957331">{COUNT,plural, =1{১টি প্রস্তাব}one{#টি প্রস্তাব}other{#টি প্রস্তাব}}</translation>
 <translation id="2079545284768500474">আগের অবস্থায় ফিরুন</translation>
 <translation id="20817612488360358">সিস্টেম প্রক্সি সেটিংস ব্যবহার করার জন্য সেট আছে কিন্তু একটি সুনির্দিষ্ট প্রক্সি কনফিগারেশনও নির্দিষ্ট করা আছে৷</translation>
diff --git a/components/strings/components_strings_iw.xtb b/components/strings/components_strings_iw.xtb
index 4489bc8e..708844c 100644
--- a/components/strings/components_strings_iw.xtb
+++ b/components/strings/components_strings_iw.xtb
@@ -62,7 +62,7 @@
 <translation id="1201895884277373915">עוד מאתר זה</translation>
 <translation id="1206967143813997005">חתימה ראשונית לא חוקית</translation>
 <translation id="1209206284964581585">הסתר בינתיים</translation>
-<translation id="121201262018556460">ניסית להגיע אל <ph name="DOMAIN" />, אך השרת הציג אישור המכיל מפתח חלש. ייתכן שתוקף פרץ את המפתח הפרטי, והשרת אינו השרת שרצית (ייתכן שאתה מתקשר עם תוקף).</translation>
+<translation id="121201262018556460">ניסית להגיע אל <ph name="DOMAIN" />, אך השרת הציג אישור המכיל מפתח חלש. ייתכן שתוקף פרץ את המפתח הפרטי, והשרת אינו השרת שרצית (ייתכן שניסית לתקשר עם תוקף).</translation>
 <translation id="1219129156119358924">אבטחת מערכת</translation>
 <translation id="1227224963052638717">מדיניות לא ידועה.</translation>
 <translation id="1228893227497259893">מזהה יישות שגוי</translation>
@@ -552,13 +552,13 @@
 <translation id="3194737229810486521"><ph name="URL" /> רוצה לאחסן נתונים במכשיר שלך באופן קבוע</translation>
 <translation id="3195213714973468956"><ph name="PRINTER_NAME" /> בשרת <ph name="SERVER_NAME" /></translation>
 <translation id="320323717674993345">בטל תשלום</translation>
-<translation id="3207960819495026254">מסומן בסימניה</translation>
+<translation id="3207960819495026254">מסומן בסימנייה</translation>
 <translation id="3209034400446768650">כניסה לדף עשויה להיות כרוכה בתשלום</translation>
 <translation id="3212581601480735796">הפעילות שלך ב-<ph name="HOSTNAME" /> מנוטרת</translation>
 <translation id="3215092763954878852">‏לא ניתן להשתמש ב-WebAuthn</translation>
 <translation id="3218181027817787318">יחסי</translation>
 <translation id="3225919329040284222">השרת הציג אישור שאינו תואם את הציפיות המובנות. ציפיות אלה נכללות עבור אתרי אינטרנט מסוימים בעלי אבטחה גבוהה כדי להגן עליך.</translation>
-<translation id="3226128629678568754">לחץ על לחצן הטעינה מחדש כדי לשלוח מחדש את הנתונים הדרושים לטעינת הדף.</translation>
+<translation id="3226128629678568754">יש ללחוץ על לחצן הטעינה מחדש כדי לשלוח מחדש את הנתונים הדרושים לטעינת הדף.</translation>
 <translation id="3226387218769101247">תמונות ממוזערות</translation>
 <translation id="3227137524299004712">מיקרופון</translation>
 <translation id="3229041911291329567">פרטי גרסה של המכשיר והדפדפן</translation>
@@ -716,7 +716,7 @@
 <translation id="3831915413245941253">הותקנו תוספים מהדומיין <ph name="ENROLLMENT_DOMAIN" /> כדי להשתמש בפונקציות נוספות. לתוספים יש גישה לחלק מהנתונים שלך.</translation>
 <translation id="3832522519263485449">ניקובים מרובים בצד שמאל</translation>
 <translation id="385051799172605136">חזרה</translation>
-<translation id="3858027520442213535">עדכן את התאריך והשעה</translation>
+<translation id="3858027520442213535">עדכון התאריך והשעה</translation>
 <translation id="3884278016824448484">מזהה מכשיר מתנגש</translation>
 <translation id="3885155851504623709">פאריש</translation>
 <translation id="388632593194507180">זוהה מעקב</translation>
@@ -1036,7 +1036,7 @@
 <translation id="5125394840236832993">B-Plus</translation>
 <translation id="5126510351761255129">אימות הכרטיס</translation>
 <translation id="5135404736266831032">ניהול כתובות...</translation>
-<translation id="5138227688689900538">פחות אפליקציות</translation>
+<translation id="5138227688689900538">פחות מידע</translation>
 <translation id="5141240743006678641">‏הצפנת סיסמאות מסונכרנות באמצעות פרטי הכניסה שלך ל-Google</translation>
 <translation id="5145883236150621069">קיים קוד שגיאה בתגובת המדיניות</translation>
 <translation id="5146995429444047494">התראות של <ph name="ORIGIN" /> נחסמו</translation>
@@ -1253,7 +1253,7 @@
 <translation id="5990559369517809815">בקשות שנשלחו לשרת נחסמו על ידי תוסף.</translation>
 <translation id="5992691462791905444">‏קיפול מסוג Engineering Z</translation>
 <translation id="6000758707621254961"><ph name="RESULT_COUNT" /> תוצאות בשביל '<ph name="SEARCH_TEXT" />'</translation>
-<translation id="6008122969617370890">‏סדר מ-N עד 1</translation>
+<translation id="6008122969617370890">‏סידור מ-N עד 1</translation>
 <translation id="6008256403891681546">JCB</translation>
 <translation id="6014801569448771146">בדיקת הסיסמאות</translation>
 <translation id="6015796118275082299">שנה</translation>
@@ -1336,11 +1336,11 @@
 <translation id="6312113039770857350">דף האינטרנט אינו זמין</translation>
 <translation id="6321917430147971392">‏בדוק את הגדרות ה-DNS</translation>
 <translation id="6322182122604171028">‏לא ניתן היה להשתמש ב-Windows Hello</translation>
-<translation id="6328639280570009161">נסה להשבית את חיזוי הרשת</translation>
+<translation id="6328639280570009161">יש לנסות להשבית את חיזוי הרשת</translation>
 <translation id="6328784461820205019">‏"החיבור שלך אינו פרטי" או "&lt;span class="error-code"&gt;NET::ERR_CERT_AUTHORITY_INVALID&lt;/span&gt;" או "&lt;span class="error-code"&gt;ERR_CERT_COMMON_NAME_INVALID&lt;/span&gt;" או "&lt;span class="error-code"&gt;NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM&lt;/span&gt;" או "&lt;span class="error-code"&gt;ERR_CERT_SYMANTEC_LEGACY&lt;/span&gt;" או "שגיאת אישור SSL"</translation>
 <translation id="6328786501058569169">האתר הזה מטעה</translation>
-<translation id="6337133576188860026">פינוי של פחות מ-<ph name="SIZE" /> מהשטח. ייתכן שחלק מהאתרים ייטענו לאט יותר בביקור הבא שלך.</translation>
-<translation id="6337534724793800597">סנן מדיניות לפי שם</translation>
+<translation id="6337133576188860026">פינוי של פחות מ-<ph name="SIZE" /> מהנפח. ייתכן שחלק מהאתרים ייטענו לאט יותר בביקור הבא שלך.</translation>
+<translation id="6337534724793800597">סינון מדיניות לפי שם</translation>
 <translation id="6353505687280762741">{COUNT,plural, =0{אין}=1{סיסמה אחת (עבור <ph name="DOMAIN_LIST" />, מסונכרנת)}=2{שתי סיסמאות (עבור <ph name="DOMAIN_LIST" />, מסונכרנות)}many{# סיסמאות (עבור <ph name="DOMAIN_LIST" />, מסונכרנות)}other{# סיסמאות (עבור <ph name="DOMAIN_LIST" />, מסונכרנות)}}</translation>
 <translation id="6358450015545214790">מה זה אומר?</translation>
 <translation id="6361757823711327522">B7</translation>
@@ -1527,7 +1527,7 @@
 <translation id="7181261019481237103">פתיחת חלון אנונימי</translation>
 <translation id="7182878459783632708">לא הוגדרה מדיניות</translation>
 <translation id="7186367841673660872">דף זה תורגם מ<ph name="ORIGINAL_LANGUAGE" />ל<ph name="LANGUAGE_LANGUAGE" /></translation>
-<translation id="7192203810768312527">פינוי של <ph name="SIZE" /> מהשטח. תיתכן טעינה איטית יותר של אתרים מסוימים בביקור הבא שלך.</translation>
+<translation id="7192203810768312527">פינוי של <ph name="SIZE" /> מהנפח. תיתכן טעינה איטית יותר של אתרים מסוימים בביקור הבא שלך.</translation>
 <translation id="719464814642662924">Visa</translation>
 <translation id="7201591969684833065">מנהל המערכת יכול לראות:</translation>
 <translation id="7202346780273620635">Letter-Extra</translation>
@@ -1598,7 +1598,7 @@
 <translation id="7419106976560586862">נתיב פרופיל</translation>
 <translation id="7437289804838430631">הוספת פרטים ליצירת קשר</translation>
 <translation id="7438976808740265764">‏התמיכה ב-Flash Player תופסק אחרי דצמבר 2020.</translation>
-<translation id="7440140511386898319">עיון במצב לא מקוון</translation>
+<translation id="7440140511386898319">עיון במצב אופליין</translation>
 <translation id="7441627299479586546">נושא המדיניות שגוי</translation>
 <translation id="7442725080345379071">כתום בהיר</translation>
 <translation id="7445762425076701745">לא ניתן לאמת לגמרי את הזהות של השרת שאליו אתה מחובר. אתה מחובר לשרת באמצעות שם שקיים רק ברשת שלך, ושלרשות אישורים חיצונית אין דרך לאמת את בעלותך עליו. מכיוון שחלק מרשויות האישורים ינפיקו אישורים לשמות אלה ללא קשר, אין דרך להבטיח שאתה מחובר לאתר המיועד ואינך גורם תוקף.</translation>
@@ -1713,7 +1713,7 @@
 <translation id="782886543891417279">‏ייתכן שתידרש להיכנס לדף ההתחברות של רשת ה-Wi-Fi שבה אתה משתמש (<ph name="WIFI_NAME" />).</translation>
 <translation id="7836231406687464395">Postfix (Envelope)‎</translation>
 <translation id="7844689747373518809">{COUNT,plural, =0{ללא}=1{אפליקציה אחת (<ph name="EXAMPLE_APP_1" />)}=2{2 אפליקציות (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}many{# אפליקציות (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}other{# אפליקציות (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">עם זאת, אינך בלתי נראה. המעבר למצב גלישה בסתר לא מסתיר את הגלישה שלך מהמעסיק, מספק האינטרנט או מהאתרים שאליהם אתה נכנס.</translation>
+<translation id="785549533363645510">עם זאת, עדיין אפשר לראות אותך. המעבר למצב גלישה בסתר לא מסתיר את הגלישה שלך מהמעסיק, מספק האינטרנט או מהאתרים שאליהם נכנסת.</translation>
 <translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
 <translation id="7862185352068345852">לצאת מהאתר?</translation>
 <translation id="7865448901209910068">המהירות הטובה ביותר</translation>
diff --git a/components/strings/components_strings_vi.xtb b/components/strings/components_strings_vi.xtb
index 412c7a5..3946754 100644
--- a/components/strings/components_strings_vi.xtb
+++ b/components/strings/components_strings_vi.xtb
@@ -909,7 +909,7 @@
 <translation id="4597348597567598915">Kích thước 8</translation>
 <translation id="4600854749408232102">C6/C5 (Phong bì)</translation>
 <translation id="4628948037717959914">Ảnh</translation>
-<translation id="4631649115723685955">Đã liên kết ưu đãi bằng tiền mặt</translation>
+<translation id="4631649115723685955">Đã liên kết ưu đãi hoàn tiền</translation>
 <translation id="464342062220857295">Tìm kiếm tính năng</translation>
 <translation id="4644670975240021822">Thứ tự đảo ngược hướng xuống</translation>
 <translation id="4646534391647090355">Chuyển đến đó ngay</translation>
diff --git a/components/sync/driver/data_type_manager_impl.cc b/components/sync/driver/data_type_manager_impl.cc
index dbc8477..1b2183b 100644
--- a/components/sync/driver/data_type_manager_impl.cc
+++ b/components/sync/driver/data_type_manager_impl.cc
@@ -544,8 +544,7 @@
   association_info.high_priority_types_before = high_priority_types_before;
   association_types_queue_.push(association_info);
 
-  // Start associating those types that are already downloaded (does nothing
-  // if model associator is busy).
+  // Start associating those types that are already downloaded.
   StartNextAssociation(READY_AT_CONFIG);
 }
 
@@ -682,6 +681,33 @@
 
   DVLOG(1) << "Associating " << ModelTypeSetToString(types_to_associate);
   model_association_manager_.Associate(types_to_associate);
+
+  DCHECK(state_ == STOPPING || state_ == CONFIGURING);
+
+  if (state_ == STOPPING)
+    return;
+
+  if (needs_reconfigure_) {
+    ProcessReconfigure();
+    return;
+  }
+
+  // If this model association was for the full set of types, then this priority
+  // set is done. Otherwise it was just the ready types and the unready types
+  // still need to be associated.
+  if (types_to_associate == association_types_queue_.front().types) {
+    association_types_queue_.pop();
+    if (!association_types_queue_.empty()) {
+      StartNextAssociation(READY_AT_CONFIG);
+    } else if (download_types_queue_.empty()) {
+      state_ = CONFIGURED;
+      NotifyDone(ConfigureResult(OK, types_to_associate));
+    }
+  } else {
+    DCHECK_EQ(association_types_queue_.front().ready_types, types_to_associate);
+    // Will do nothing if the types are still downloading.
+    StartNextAssociation(UNREADY_AT_CONFIG);
+  }
 }
 
 void DataTypeManagerImpl::OnSingleDataTypeWillStop(ModelType type,
@@ -742,40 +768,6 @@
   }
 }
 
-void DataTypeManagerImpl::OnModelAssociationDone(const ModelTypeSet& types) {
-  DCHECK(state_ == STOPPING || state_ == CONFIGURING);
-
-  if (state_ == STOPPING)
-    return;
-
-  // Ignore abort/unrecoverable error if we need to reconfigure anyways.
-  if (needs_reconfigure_) {
-    ProcessReconfigure();
-    return;
-  }
-
-  DCHECK(!association_types_queue_.empty());
-
-  // If this model association was for the full set of types, then this priority
-  // set is done. Otherwise it was just the ready types and the unready types
-  // still need to be associated.
-  ConfigureResult result(OK, types);
-  if (result.requested_types == association_types_queue_.front().types) {
-    association_types_queue_.pop();
-    if (!association_types_queue_.empty()) {
-      StartNextAssociation(READY_AT_CONFIG);
-    } else if (download_types_queue_.empty()) {
-      state_ = CONFIGURED;
-      NotifyDone(result);
-    }
-  } else {
-    DCHECK_EQ(association_types_queue_.front().ready_types,
-              result.requested_types);
-    // Will do nothing if the types are still downloading.
-    StartNextAssociation(UNREADY_AT_CONFIG);
-  }
-}
-
 void DataTypeManagerImpl::Stop(ShutdownReason reason) {
   if (state_ == STOPPED)
     return;
diff --git a/components/sync/driver/data_type_manager_impl.h b/components/sync/driver/data_type_manager_impl.h
index c31c710..035a7f8 100644
--- a/components/sync/driver/data_type_manager_impl.h
+++ b/components/sync/driver/data_type_manager_impl.h
@@ -58,7 +58,6 @@
   // |ModelAssociationManagerDelegate| implementation.
   void OnAllDataTypesReadyForConfigure() override;
   void OnSingleDataTypeAssociationDone(ModelType type) override;
-  void OnModelAssociationDone(const ModelTypeSet& types) override;
   void OnSingleDataTypeWillStop(ModelType type,
                                 const SyncError& error) override;
 
diff --git a/components/sync/driver/model_association_manager.cc b/components/sync/driver/model_association_manager.cc
index c7c9c2a..de154d7 100644
--- a/components/sync/driver/model_association_manager.cc
+++ b/components/sync/driver/model_association_manager.cc
@@ -215,8 +215,6 @@
     }
   }
   DCHECK(associating_types.Empty());
-
-  delegate_->OnModelAssociationDone(types_to_associate);
 }
 
 void ModelAssociationManager::Stop(ShutdownReason shutdown_reason) {
diff --git a/components/sync/driver/model_association_manager.h b/components/sync/driver/model_association_manager.h
index 651d35e6..1cc0608 100644
--- a/components/sync/driver/model_association_manager.h
+++ b/components/sync/driver/model_association_manager.h
@@ -36,10 +36,6 @@
   virtual void OnSingleDataTypeWillStop(ModelType type,
                                         const SyncError& error) = 0;
 
-  // Called when the ModelAssociationManager has tried to perform model
-  // association for all desired types and has nothing left to do.
-  virtual void OnModelAssociationDone(const ModelTypeSet& types) = 0;
-
   virtual ~ModelAssociationManagerDelegate() = default;
 };
 
diff --git a/components/sync/driver/model_association_manager_unittest.cc b/components/sync/driver/model_association_manager_unittest.cc
index 4370a3f..cba9eefa 100644
--- a/components/sync/driver/model_association_manager_unittest.cc
+++ b/components/sync/driver/model_association_manager_unittest.cc
@@ -43,10 +43,6 @@
               OnSingleDataTypeWillStop,
               (ModelType, const SyncError& error),
               (override));
-  MOCK_METHOD(void,
-              OnModelAssociationDone,
-              (const ModelTypeSet& result),
-              (override));
 };
 
 class SyncModelAssociationManagerTest : public testing::Test {
@@ -76,7 +72,6 @@
   ModelAssociationManager model_association_manager(&controllers_, &delegate_);
   ModelTypeSet types(BOOKMARKS, APPS);
   EXPECT_CALL(delegate_, OnAllDataTypesReadyForConfigure());
-  EXPECT_CALL(delegate_, OnModelAssociationDone(types));
 
   EXPECT_EQ(GetController(BOOKMARKS)->state(), DataTypeController::NOT_RUNNING);
   EXPECT_EQ(GetController(APPS)->state(), DataTypeController::NOT_RUNNING);
@@ -99,7 +94,6 @@
   ModelAssociationManager model_association_manager(&controllers_, &delegate_);
   ModelTypeSet types;
   types.Put(BOOKMARKS);
-  EXPECT_CALL(delegate_, OnModelAssociationDone(types));
   EXPECT_CALL(delegate_, OnSingleDataTypeWillStop(BOOKMARKS, _));
 
   model_association_manager.Initialize(/*desired_types=*/types,
@@ -125,7 +119,6 @@
   ModelTypeSet types;
   types.Put(BOOKMARKS);
   EXPECT_CALL(delegate_, OnSingleDataTypeWillStop(BOOKMARKS, _));
-  EXPECT_CALL(delegate_, OnModelAssociationDone(types));
 
   model_association_manager.Initialize(/*desired_types=*/types,
                                        /*preferred_types=*/types,
@@ -142,7 +135,6 @@
   ModelAssociationManager model_association_manager(&controllers_, &delegate_);
   ModelTypeSet types;
   types.Put(BOOKMARKS);
-  EXPECT_CALL(delegate_, OnModelAssociationDone(types));
 
   model_association_manager.Initialize(/*desired_types=*/types,
                                        /*preferred_types=*/types,
@@ -364,7 +356,6 @@
   EXPECT_CALL(delegate_, OnAllDataTypesReadyForConfigure());
   EXPECT_CALL(delegate_, OnSingleDataTypeAssociationDone(BOOKMARKS));
   EXPECT_CALL(delegate_, OnSingleDataTypeAssociationDone(APPS));
-  EXPECT_CALL(delegate_, OnModelAssociationDone(desired_types));
 
   model_association_manager.Initialize(desired_types, preferred_types,
                                        BuildConfigureContext());
@@ -403,7 +394,6 @@
   EXPECT_CALL(delegate_, OnAllDataTypesReadyForConfigure());
   EXPECT_CALL(delegate_, OnSingleDataTypeAssociationDone(BOOKMARKS));
   EXPECT_CALL(delegate_, OnSingleDataTypeAssociationDone(APPS));
-  EXPECT_CALL(delegate_, OnModelAssociationDone(desired_types));
 
   model_association_manager.Initialize(desired_types, preferred_types,
                                        BuildConfigureContext());
@@ -449,7 +439,6 @@
   EXPECT_CALL(delegate_, OnAllDataTypesReadyForConfigure());
   EXPECT_CALL(delegate_, OnSingleDataTypeAssociationDone(BOOKMARKS));
   EXPECT_CALL(delegate_, OnSingleDataTypeAssociationDone(APPS));
-  EXPECT_CALL(delegate_, OnModelAssociationDone(desired_types));
 
   model_association_manager.Initialize(desired_types, preferred_types,
                                        configure_context);
@@ -470,7 +459,6 @@
   EXPECT_CALL(delegate_, OnSingleDataTypeWillStop(BOOKMARKS, _));
   EXPECT_CALL(delegate_, OnAllDataTypesReadyForConfigure());
   EXPECT_CALL(delegate_, OnSingleDataTypeAssociationDone(BOOKMARKS));
-  EXPECT_CALL(delegate_, OnModelAssociationDone(desired_types));
 
   model_association_manager.Initialize(desired_types, preferred_types,
                                        configure_context);
@@ -503,7 +491,6 @@
   EXPECT_CALL(delegate_, OnAllDataTypesReadyForConfigure());
   EXPECT_CALL(delegate_, OnSingleDataTypeAssociationDone(BOOKMARKS));
   EXPECT_CALL(delegate_, OnSingleDataTypeAssociationDone(APPS));
-  EXPECT_CALL(delegate_, OnModelAssociationDone(desired_types));
 
   model_association_manager.Initialize(desired_types, preferred_types,
                                        configure_context);
@@ -524,7 +511,6 @@
   EXPECT_CALL(delegate_, OnSingleDataTypeWillStop(BOOKMARKS, _));
   EXPECT_CALL(delegate_, OnAllDataTypesReadyForConfigure());
   EXPECT_CALL(delegate_, OnSingleDataTypeAssociationDone(BOOKMARKS));
-  EXPECT_CALL(delegate_, OnModelAssociationDone(desired_types));
 
   model_association_manager.Initialize(desired_types, preferred_types,
                                        configure_context);
diff --git a/components/sync/protocol/password_specifics.proto b/components/sync/protocol/password_specifics.proto
index 4f65a532..4e44da7 100644
--- a/components/sync/protocol/password_specifics.proto
+++ b/components/sync/protocol/password_specifics.proto
@@ -19,7 +19,8 @@
 import "components/sync/protocol/encryption.proto";
 
 // These are the properties that get serialized into the |encrypted| field of
-// PasswordSpecifics. They correspond to fields in autofill::PasswordForm.
+// PasswordSpecifics. They correspond to fields in
+// password_manager::PasswordForm.
 //
 // Sync unique tag is calculated as
 // EscapePath(origin) + "|" +
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc
index 0107fac..f5a466d 100644
--- a/components/translate/core/browser/translate_manager.cc
+++ b/components/translate/core/browser/translate_manager.cc
@@ -213,9 +213,14 @@
     return false;
 
   const std::string source_language = language_state_.original_language();
-  if (source_language.empty() ||
-      source_language == translate::kUnknownLanguageCode)
+  if (source_language.empty())
     return false;
+  // Translation of unknown source language pages is supported on desktop
+  // platforms, but not mobile.
+#if defined(OS_ANDROID) || defined(OS_IOS)
+  if (source_language == translate::kUnknownLanguageCode)
+    return false;
+#endif
 
   std::unique_ptr<TranslatePrefs> translate_prefs(
       translate_client_->GetTranslatePrefs());
diff --git a/components/translate/core/browser/translate_manager_unittest.cc b/components/translate/core/browser/translate_manager_unittest.cc
index acc3020..4ae7e95 100644
--- a/components/translate/core/browser/translate_manager_unittest.cc
+++ b/components/translate/core/browser/translate_manager_unittest.cc
@@ -1019,7 +1019,13 @@
   translate_manager_->GetLanguageState()->LanguageDetermined(
       translate::kUnknownLanguageCode, true);
 
+  // Translation of unknown source language pages is supported on desktop
+  // platforms, but not mobile.
+#if defined(OS_ANDROID) || defined(OS_IOS)
   EXPECT_FALSE(translate_manager_->CanManuallyTranslate());
+#else
+  EXPECT_TRUE(translate_manager_->CanManuallyTranslate());
+#endif
 }
 
 TEST_F(TranslateManagerTest, PredefinedTargetLanguage) {
diff --git a/components/user_manager/known_user.cc b/components/user_manager/known_user.cc
index cb8fc18..fca0c615 100644
--- a/components/user_manager/known_user.cc
+++ b/components/user_manager/known_user.cc
@@ -81,6 +81,10 @@
 // Key of the boolean flag telling if user is enterprise managed.
 const char kIsEnterpriseManaged[] = "is_enterprise_managed";
 
+// Key of the name of the entity (either a domain or email address) that manages
+// the policies for this account.
+const char kAccountManager[] = "enterprise_account_manager";
+
 // Key of the last input method user used which is suitable for login/lock
 // screen.
 const char kLastInputMethod[] = "last_input_method";
@@ -112,6 +116,7 @@
                                kLastOnlineSignin,
                                kOfflineSigninLimit,
                                kIsEnterpriseManaged,
+                               kAccountManager,
                                kLastInputMethod,
                                kPinAutosubmitLength,
                                kPinAutosubmitBackfillNeeded,
@@ -678,6 +683,15 @@
   return false;
 }
 
+void SetAccountManager(const AccountId& account_id,
+                       const std::string& manager) {
+  SetStringPref(account_id, kAccountManager, manager);
+}
+
+bool GetAccountManager(const AccountId& account_id, std::string* manager) {
+  return GetStringPref(account_id, kAccountManager, manager);
+}
+
 void SetUserLastInputMethod(const AccountId& account_id,
                             const std::string& input_method) {
   SetStringPref(account_id, kLastInputMethod, input_method);
diff --git a/components/user_manager/known_user.h b/components/user_manager/known_user.h
index 6e367ab..ce68cfe 100644
--- a/components/user_manager/known_user.h
+++ b/components/user_manager/known_user.h
@@ -232,6 +232,10 @@
 
 bool USER_MANAGER_EXPORT GetIsEnterpriseManaged(const AccountId& account_id);
 
+void USER_MANAGER_EXPORT SetAccountManager(const AccountId& account_id,
+                                           const std::string& manager);
+bool USER_MANAGER_EXPORT GetAccountManager(const AccountId& account_id,
+                                           std::string* manager);
 void USER_MANAGER_EXPORT
 SetUserLastInputMethod(const AccountId& account_id,
                        const std::string& input_method);
diff --git a/components/viz/service/display/dc_layer_overlay.cc b/components/viz/service/display/dc_layer_overlay.cc
index 2272a82..d95dc99 100644
--- a/components/viz/service/display/dc_layer_overlay.cc
+++ b/components/viz/service/display/dc_layer_overlay.cc
@@ -36,8 +36,6 @@
 constexpr int kDCLayerDebugBorderWidth = 4;
 constexpr gfx::Insets kDCLayerDebugBorderInsets = gfx::Insets(-2);
 
-using RenderPassListWithFilters = base::flat_map<AggregatedRenderPassId, float>;
-
 // This is used for a histogram to determine why overlays are or aren't used,
 // so don't remove entries and make sure to update enums.xml if it changes.
 enum DCLayerResult {
@@ -255,7 +253,7 @@
     const gfx::RectF& target_quad,
     QuadList::ConstIterator quad_list_begin,
     QuadList::ConstIterator quad_list_end,
-    RenderPassListWithFilters& render_pass_has_pixel_moving_filters) {
+    const DCLayerOverlayProcessor::FilterOperationsMap& render_pass_filters) {
   for (auto overlap_iter = quad_list_begin; overlap_iter != quad_list_end;
        ++overlap_iter) {
     float opacity = overlap_iter->shared_quad_state->opacity;
@@ -267,13 +265,13 @@
     // Expand the overlap_rect for the render pass draw quad with pixel moving
     // foreground filters.
     bool has_pixel_moving_filter = false;
-    if (!render_pass_has_pixel_moving_filters.empty() &&
+    if (!render_pass_filters.empty() &&
         quad->material == DrawQuad::Material::kAggregatedRenderPass) {
       const auto* rpdq = AggregatedRenderPassDrawQuad::MaterialCast(quad);
-      auto render_pass_it =
-          render_pass_has_pixel_moving_filters.find(rpdq->render_pass_id);
-      if (render_pass_it != render_pass_has_pixel_moving_filters.end()) {
-        float max_pixel_movement = render_pass_it->second;
+      auto render_pass_it = render_pass_filters.find(rpdq->render_pass_id);
+      if (render_pass_it != render_pass_filters.end()) {
+        auto* filters = render_pass_it->second;
+        float max_pixel_movement = filters->MaximumPixelMovement();
         overlap_rect =
             GetExpandedRectWithPixelMovingFilter(rpdq, max_pixel_movement);
         has_pixel_moving_filter = true;
@@ -374,11 +372,8 @@
     }
   }
 
-  // TODO(magchen@): deprecate histogram UnderlayDamage::kOccludingDamageOnly
-  // and remove occluding_damage_equal_to_damage_rect here.
   OverlayProcessorInterface::RecordOverlayDamageRectHistograms(
-      is_overlay, has_occluding_surface_damage, damage_rect->IsEmpty(),
-      /*occluding_damage_equal_to_damage_rect=*/false);
+      is_overlay, has_occluding_surface_damage, damage_rect->IsEmpty());
 }
 }  // namespace
 
@@ -581,6 +576,8 @@
 void DCLayerOverlayProcessor::Process(
     DisplayResourceProvider* resource_provider,
     const gfx::RectF& display_rect,
+    const FilterOperationsMap& render_pass_filters,
+    const FilterOperationsMap& render_pass_backdrop_filters,
     AggregatedRenderPassList* render_pass_list,
     gfx::Rect* damage_rect,
     SurfaceDamageRectList* surface_damage_rect_list,
@@ -590,21 +587,6 @@
   processed_yuv_overlay_count_ = 0;
   surface_damage_rect_list_ = surface_damage_rect_list;
 
-  // Which render passes have backdrop filters or pixel moving foreground
-  // filters.
-  base::flat_set<AggregatedRenderPassId> render_pass_has_backdrop_filters;
-  RenderPassListWithFilters render_pass_has_pixel_moving_filters;
-
-  for (const auto& render_pass : *render_pass_list) {
-    if (!render_pass->backdrop_filters.IsEmpty())
-      render_pass_has_backdrop_filters.insert(render_pass->id);
-
-    if (render_pass->filters.HasFilterThatMovesPixels()) {
-      render_pass_has_pixel_moving_filters.insert(
-          {render_pass->id, render_pass->filters.MaximumPixelMovement()});
-    }
-  }
-
   // Output rects of child render passes that have backdrop filters in target
   // space. These rects are used to determine if the overlay rect could be read
   // by backdrop filters.
@@ -632,7 +614,9 @@
   for (auto it = quad_list->begin(); it != quad_list->end(); ++it, ++index) {
     if (it->material == DrawQuad::Material::kAggregatedRenderPass) {
       const auto* rpdq = AggregatedRenderPassDrawQuad::MaterialCast(*it);
-      if (render_pass_has_backdrop_filters.count(rpdq->render_pass_id)) {
+      auto render_pass_it =
+          render_pass_backdrop_filters.find(rpdq->render_pass_id);
+      if (render_pass_it != render_pass_backdrop_filters.end()) {
         backdrop_filter_rects.push_back(
             gfx::ToEnclosingRect(ClippedQuadRectangle(rpdq)));
       }
@@ -704,9 +688,9 @@
         gfx::ToEnclosingRect(ClippedQuadRectangle(*it));
 
     // Quad is considered an "overlay" if it has no occluders.
-    bool is_overlay = !HasOccludingQuads(
-        gfx::RectF(quad_rectangle_in_target_space), quad_list->begin(), it,
-        render_pass_has_pixel_moving_filters);
+    bool is_overlay =
+        !HasOccludingQuads(gfx::RectF(quad_rectangle_in_target_space),
+                           quad_list->begin(), it, render_pass_filters);
 
     // Protected video is always put in an overlay, but texture quads can be
     // skipped if they're not underlay compatible.
diff --git a/components/viz/service/display/dc_layer_overlay.h b/components/viz/service/display/dc_layer_overlay.h
index 544cde4..daf08e9 100644
--- a/components/viz/service/display/dc_layer_overlay.h
+++ b/components/viz/service/display/dc_layer_overlay.h
@@ -78,6 +78,8 @@
 class VIZ_SERVICE_EXPORT DCLayerOverlayProcessor
     : public ui::GpuSwitchingObserver {
  public:
+  using FilterOperationsMap =
+      base::flat_map<AggregatedRenderPassId, cc::FilterOperations*>;
   // When |skip_initialization_for_testing| is true, object will be isolated
   // for unit tests.
   // allowed_yuv_overlay_count will be limited to 1 if
@@ -94,6 +96,8 @@
   // Virtual for testing.
   virtual void Process(DisplayResourceProvider* resource_provider,
                        const gfx::RectF& display_rect,
+                       const FilterOperationsMap& render_pass_filters,
+                       const FilterOperationsMap& render_pass_backdrop_filters,
                        AggregatedRenderPassList* render_passes,
                        gfx::Rect* damage_rect,
                        SurfaceDamageRectList* surface_damage_rect_list,
diff --git a/components/viz/service/display/direct_renderer.cc b/components/viz/service/display/direct_renderer.cc
index e356f1a..5b094621 100644
--- a/components/viz/service/display/direct_renderer.cc
+++ b/components/viz/service/display/direct_renderer.cc
@@ -368,12 +368,11 @@
 
     // If we promote any quad to an underlay then the main plane must support
     // alpha.
-    // TODO(ccameron): We should update |frame_color_space|, and
+    // TODO(ccameron): We should update
+    // |root_render_pass->has_transparent_background|, |frame_color_space|, and
     // |frame_buffer_format| based on the change in |frame_has_alpha|.
-    if (current_frame()->output_surface_plane) {
+    if (current_frame()->output_surface_plane)
       frame_has_alpha |= current_frame()->output_surface_plane->enable_blending;
-      root_render_pass->has_transparent_background = frame_has_alpha;
-    }
 
     overlay_processor_->AdjustOutputSurfaceOverlay(
         &(current_frame()->output_surface_plane));
diff --git a/components/viz/service/display/gl_renderer_unittest.cc b/components/viz/service/display/gl_renderer_unittest.cc
index cb48150..ca1987d 100644
--- a/components/viz/service/display/gl_renderer_unittest.cc
+++ b/components/viz/service/display/gl_renderer_unittest.cc
@@ -2529,9 +2529,11 @@
                                 /*allowed_yuv_overlay_count=*/1,
                                 true) {}
   ~MockDCLayerOverlayProcessor() override = default;
-  MOCK_METHOD6(Process,
+  MOCK_METHOD8(Process,
                void(DisplayResourceProvider* resource_provider,
                     const gfx::RectF& display_rect,
+                    const FilterOperationsMap& render_pass_filters,
+                    const FilterOperationsMap& render_pass_backdrop_filters,
                     AggregatedRenderPassList* render_passes,
                     gfx::Rect* damage_rect,
                     SurfaceDamageRectList* surface_damage_rect_list,
@@ -2738,7 +2740,7 @@
   EXPECT_CALL(*mock_ca_processor, ProcessForCALayerOverlays(_, _, _, _, _, _))
       .Times(0);
 #elif defined(OS_WIN)
-  EXPECT_CALL(*dc_processor, Process(_, _, _, _, _, _)).Times(0);
+  EXPECT_CALL(*dc_processor, Process(_, _, _, _, _, _, _, _)).Times(0);
 #endif
   DrawFrame(&renderer, viewport_size);
 #if defined(USE_OZONE) || defined(OS_ANDROID)
@@ -2770,7 +2772,7 @@
   EXPECT_CALL(*mock_ca_processor, ProcessForCALayerOverlays(_, _, _, _, _, _))
       .Times(1);
 #elif defined(OS_WIN)
-  EXPECT_CALL(*dc_processor, Process(_, _, _, _, _, _)).Times(1);
+  EXPECT_CALL(*dc_processor, Process(_, _, _, _, _, _, _, _)).Times(1);
 #endif
   DrawFrame(&renderer, viewport_size);
 
diff --git a/components/viz/service/display/overlay_processor_interface.cc b/components/viz/service/display/overlay_processor_interface.cc
index e8b0800..64c6da7 100644
--- a/components/viz/service/display/overlay_processor_interface.cc
+++ b/components/viz/service/display/overlay_processor_interface.cc
@@ -34,7 +34,7 @@
 enum class UnderlayDamage {
   kZeroDamageRect,
   kNonOccludingDamageOnly,
-  kOccludingDamageOnly,
+  kOccludingDamageOnly,  // deprecated
   kOccludingAndNonOccludingDamages,
   kMaxValue = kOccludingAndNonOccludingDamages,
 };
@@ -52,8 +52,7 @@
 void OverlayProcessorInterface::RecordOverlayDamageRectHistograms(
     bool is_overlay,
     bool has_occluding_surface_damage,
-    bool zero_damage_rect,
-    bool occluding_damage_equal_to_damage_rect) {
+    bool zero_damage_rect) {
   if (is_overlay) {
     UMA_HISTOGRAM_BOOLEAN("Viz.DisplayCompositor.RootDamageRect.Overlay",
                           !zero_damage_rect);
@@ -63,11 +62,7 @@
       underlay_damage = UnderlayDamage::kZeroDamageRect;
     } else {
       if (has_occluding_surface_damage) {
-        if (occluding_damage_equal_to_damage_rect) {
-          underlay_damage = UnderlayDamage::kOccludingDamageOnly;
-        } else {
-          underlay_damage = UnderlayDamage::kOccludingAndNonOccludingDamages;
-        }
+        underlay_damage = UnderlayDamage::kOccludingAndNonOccludingDamages;
       } else {
         underlay_damage = UnderlayDamage::kNonOccludingDamageOnly;
       }
diff --git a/components/viz/service/display/overlay_processor_interface.h b/components/viz/service/display/overlay_processor_interface.h
index b2135bdd..6ade5fb 100644
--- a/components/viz/service/display/overlay_processor_interface.h
+++ b/components/viz/service/display/overlay_processor_interface.h
@@ -61,8 +61,7 @@
   static void RecordOverlayDamageRectHistograms(
       bool is_overlay,
       bool has_occluding_surface_damage,
-      bool zero_damage_rect,
-      bool occluding_damage_equal_to_damage_rect);
+      bool zero_damage_rect);
 
   // Data needed to represent |OutputSurface| as an overlay plane. Due to the
   // default values for the primary plane, this is a partial list of
diff --git a/components/viz/service/display/overlay_processor_using_strategy.cc b/components/viz/service/display/overlay_processor_using_strategy.cc
index beddfaf3..02a15ef 100644
--- a/components/viz/service/display/overlay_processor_using_strategy.cc
+++ b/components/viz/service/display/overlay_processor_using_strategy.cc
@@ -176,10 +176,9 @@
     }
 
     if (overlay.plane_z_order) {
-      RecordOverlayDamageRectHistograms(
-          (overlay.plane_z_order > 0), !overlay.no_occluding_damage,
-          damage_rect->IsEmpty(),
-          false /* occluding_damage_equal_to_damage_rect */);
+      RecordOverlayDamageRectHistograms((overlay.plane_z_order > 0),
+                                        !overlay.no_occluding_damage,
+                                        damage_rect->IsEmpty());
     }
   }
 
diff --git a/components/viz/service/display/overlay_processor_win.cc b/components/viz/service/display/overlay_processor_win.cc
index 718863c..fc34539 100644
--- a/components/viz/service/display/overlay_processor_win.cc
+++ b/components/viz/service/display/overlay_processor_win.cc
@@ -88,7 +88,8 @@
 
   dc_layer_overlay_processor_->Process(
       resource_provider, gfx::RectF(root_render_pass->output_rect),
-      render_passes, damage_rect, surface_damage_rect_list, candidates);
+      render_pass_filters, render_pass_backdrop_filters, render_passes,
+      damage_rect, surface_damage_rect_list, candidates);
 
   bool was_using_dc_layers = using_dc_layers_;
   if (!candidates->empty()) {
diff --git a/components/viz/service/display/skia_output_surface.h b/components/viz/service/display/skia_output_surface.h
index 05592eb..ef08ef2 100644
--- a/components/viz/service/display/skia_output_surface.h
+++ b/components/viz/service/display/skia_output_surface.h
@@ -129,7 +129,7 @@
   // Optionally the caller may specify |on_finished| callback to be called after
   // the GPU has finished processing all submitted commands. The callback may be
   // called on a different thread.
-  virtual gpu::SyncToken SubmitPaint(base::OnceClosure on_finished) = 0;
+  virtual void EndPaint(base::OnceClosure on_finished) = 0;
 
   // Make a promise SkImage from a render pass id. The render pass has been
   // painted with BeginPaintRenderPass and FinishPaintRenderPass. The format
@@ -170,6 +170,9 @@
       base::OnceClosure callback,
       std::vector<gpu::SyncToken> sync_tokens) = 0;
 
+  // Flush pending GPU tasks.
+  virtual gpu::SyncToken Flush() = 0;
+
 #if defined(OS_APPLE)
   virtual SkCanvas* BeginPaintRenderPassOverlay(
       const gfx::Size& size,
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
index b7d6639..f844a46 100644
--- a/components/viz/service/display/skia_renderer.cc
+++ b/components/viz/service/display/skia_renderer.cc
@@ -746,10 +746,13 @@
 
   skia_output_surface_->SwapBuffers(std::move(output_frame));
   swap_buffer_rect_ = gfx::Rect();
+
+  FlushOutputSurface();
 }
 
 void SkiaRenderer::SwapBuffersSkipped() {
   skia_output_surface_->SwapBuffersSkipped();
+  FlushOutputSurface();
 }
 
 void SkiaRenderer::SwapBuffersComplete() {
@@ -2504,20 +2507,27 @@
   if (delegated_ink_point_renderer_)
     DrawDelegatedInkTrail();
 
+  bool is_root_render_pass =
+      current_frame()->current_render_pass == current_frame()->root_render_pass;
+
   base::OnceClosure on_finished_callback;
   // Signal |current_frame_resource_fence_| when the root render pass is
   // finished.
   if (current_frame_resource_fence_ &&
-      current_frame_resource_fence_->WasSet() &&
-      current_frame()->current_render_pass ==
-          current_frame()->root_render_pass) {
+      current_frame_resource_fence_->WasSet() && is_root_render_pass) {
     on_finished_callback = base::BindOnce(
         &FrameResourceFence::Signal, std::move(current_frame_resource_fence_));
   }
-  gpu::SyncToken sync_token =
-      skia_output_surface_->SubmitPaint(std::move(on_finished_callback));
+  skia_output_surface_->EndPaint(std::move(on_finished_callback));
 
-  lock_set_for_external_use_->UnlockResources(sync_token);
+  // Defer flushing drawing task for root render pass, to avoid extra
+  // MakeCurrent() call. It is expensive on GL.
+  // TODO(https://crbug.com/1141008): Consider deferring drawing tasks for
+  // all render passes.
+  if (is_root_render_pass)
+    return;
+
+  FlushOutputSurface();
 }
 
 void SkiaRenderer::GenerateMipmap() {
@@ -2581,6 +2591,11 @@
                          color_space, format}));
 }
 
+void SkiaRenderer::FlushOutputSurface() {
+  auto sync_token = skia_output_surface_->Flush();
+  lock_set_for_external_use_->UnlockResources(sync_token);
+}
+
 #if defined(OS_APPLE)
 void SkiaRenderer::PrepareRenderPassOverlay(CALayerOverlay* overlay) {
   DCHECK(!current_canvas_);
diff --git a/components/viz/service/display/skia_renderer.h b/components/viz/service/display/skia_renderer.h
index c6a9bbf..b5a3d53c 100644
--- a/components/viz/service/display/skia_renderer.h
+++ b/components/viz/service/display/skia_renderer.h
@@ -242,6 +242,10 @@
   // Returns the color filter that should be applied to the current canvas.
   sk_sp<SkColorFilter> GetContentColorFilter();
 
+  // Flush SkiaOutputSurface, so all pending GPU tasks in SkiaOutputSurface will
+  // be sent to GPU scheduler.
+  void FlushOutputSurface();
+
 #if defined(OS_APPLE)
   void PrepareRenderPassOverlay(CALayerOverlay* overlay);
 #endif
diff --git a/components/viz/service/display_embedder/output_presenter.cc b/components/viz/service/display_embedder/output_presenter.cc
index ba55af0a4..48710f3b 100644
--- a/components/viz/service/display_embedder/output_presenter.cc
+++ b/components/viz/service/display_embedder/output_presenter.cc
@@ -115,14 +115,4 @@
   }
 }
 
-std::unique_ptr<OutputPresenter::Image>
-OutputPresenter::AllocateBackgroundImage(gfx::ColorSpace color_space,
-                                         gfx::Size image_size) {
-  return nullptr;
-}
-
-void OutputPresenter::ScheduleBackground(Image* image) {
-  NOTREACHED();
-}
-
 }  // namespace viz
diff --git a/components/viz/service/display_embedder/output_presenter.h b/components/viz/service/display_embedder/output_presenter.h
index 7916c94..52b9ed3 100644
--- a/components/viz/service/display_embedder/output_presenter.h
+++ b/components/viz/service/display_embedder/output_presenter.h
@@ -86,9 +86,6 @@
       gfx::ColorSpace color_space,
       gfx::Size image_size,
       size_t num_images) = 0;
-  virtual std::unique_ptr<Image> AllocateBackgroundImage(
-      gfx::ColorSpace color_space,
-      gfx::Size image_size);
   virtual void SwapBuffers(SwapCompletionCallback completion_callback,
                            BufferPresentedCallback presentation_callback) = 0;
   virtual void PostSubBuffer(const gfx::Rect& rect,
@@ -105,7 +102,6 @@
       gpu::SharedImageRepresentationOverlay::ScopedReadAccess;
   virtual void ScheduleOverlays(SkiaOutputSurface::OverlayList overlays,
                                 std::vector<ScopedOverlayAccess*> accesses) = 0;
-  virtual void ScheduleBackground(Image* image);
 };
 
 }  // namespace viz
diff --git a/components/viz/service/display_embedder/output_presenter_gl.cc b/components/viz/service/display_embedder/output_presenter_gl.cc
index d1ef91a..d587bf4 100644
--- a/components/viz/service/display_embedder/output_presenter_gl.cc
+++ b/components/viz/service/display_embedder/output_presenter_gl.cc
@@ -17,7 +17,6 @@
 #include "ui/display/types/display_snapshot.h"
 #include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/geometry/rect_conversions.h"
-#include "ui/gfx/overlay_transform.h"
 #include "ui/gl/gl_fence.h"
 #include "ui/gl/gl_surface.h"
 
@@ -283,20 +282,6 @@
   return images;
 }
 
-std::unique_ptr<OutputPresenter::Image>
-OutputPresenterGL::AllocateBackgroundImage(gfx::ColorSpace color_space,
-                                           gfx::Size image_size) {
-  auto image = std::make_unique<PresenterImageGL>();
-  if (!image->Initialize(shared_image_factory_,
-                         shared_image_representation_factory_, image_size,
-                         color_space, image_format_, dependency_,
-                         shared_image_usage_)) {
-    DLOG(ERROR) << "Failed to initialize image.";
-    return nullptr;
-  }
-  return image;
-}
-
 void OutputPresenterGL::SwapBuffers(
     SwapCompletionCallback completion_callback,
     BufferPresentedCallback presentation_callback) {
@@ -344,22 +329,6 @@
                                     plane.enable_blending, std::move(fence));
 }
 
-void OutputPresenterGL::ScheduleBackground(Image* image) {
-  // Background is not seen by user, and is created before buffer queue buffers.
-  // So fence is not needed.
-  auto* gl_image =
-      reinterpret_cast<PresenterImageGL*>(image)->GetGLImage(nullptr);
-
-  // Background is also z-order 0.
-  constexpr int kPlaneZOrder = INT32_MIN;
-  // Background always uses the full texture.
-  constexpr gfx::RectF kUVRect(0.f, 0.f, 1.0f, 1.0f);
-  gl_surface_->ScheduleOverlayPlane(
-      kPlaneZOrder, gfx::OVERLAY_TRANSFORM_NONE, gl_image, gfx::Rect(),
-      /*crop_rect=*/kUVRect,
-      /*enable_blend=*/false, /*gpu_fence=*/nullptr);
-}
-
 void OutputPresenterGL::CommitOverlayPlanes(
     SwapCompletionCallback completion_callback,
     BufferPresentedCallback presentation_callback) {
diff --git a/components/viz/service/display_embedder/output_presenter_gl.h b/components/viz/service/display_embedder/output_presenter_gl.h
index 7bf8c8b7..4cb0ef9a 100644
--- a/components/viz/service/display_embedder/output_presenter_gl.h
+++ b/components/viz/service/display_embedder/output_presenter_gl.h
@@ -49,8 +49,6 @@
       gfx::ColorSpace color_space,
       gfx::Size image_size,
       size_t num_images) final;
-  std::unique_ptr<Image> AllocateBackgroundImage(gfx::ColorSpace color_space,
-                                                 gfx::Size image_size) final;
   void SwapBuffers(SwapCompletionCallback completion_callback,
                    BufferPresentedCallback presentation_callback) final;
   void PostSubBuffer(const gfx::Rect& rect,
@@ -64,7 +62,6 @@
       bool is_submitted) final;
   void ScheduleOverlays(SkiaOutputSurface::OverlayList overlays,
                         std::vector<ScopedOverlayAccess*> accesses) final;
-  void ScheduleBackground(Image* image) final;
 
  private:
   scoped_refptr<gl::GLSurface> gl_surface_;
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
index 2d18278..45493f5 100644
--- a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
+++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
@@ -102,15 +102,13 @@
     SkiaOutputSurfaceDependency* deps,
     gpu::SharedImageRepresentationFactory* representation_factory,
     gpu::MemoryTracker* memory_tracker,
-    const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback,
-    bool needs_background_image)
+    const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback)
     : SkiaOutputDevice(deps->GetSharedContextState()->gr_context(),
                        memory_tracker,
                        did_swap_buffer_complete_callback),
       presenter_(std::move(presenter)),
       dependency_(deps),
-      representation_factory_(representation_factory),
-      needs_background_image_(needs_background_image) {
+      representation_factory_(representation_factory) {
   capabilities_.uses_default_gl_framebuffer = false;
   capabilities_.preserve_buffer_content = true;
   capabilities_.only_invalidates_damage_rect = false;
@@ -127,6 +125,9 @@
   capabilities_.max_frames_pending = capabilities_.number_of_buffers - 1;
 
   presenter_->InitializeCapabilities(&capabilities_);
+
+  if (capabilities_.supports_post_sub_buffer)
+    capabilities_.supports_target_damage = true;
 }
 
 SkiaOutputDeviceBufferQueue::~SkiaOutputDeviceBufferQueue() {
@@ -182,21 +183,6 @@
 void SkiaOutputDeviceBufferQueue::SchedulePrimaryPlane(
     const base::Optional<OverlayProcessorInterface::OutputSurfaceOverlayPlane>&
         plane) {
-  if (background_image_) {
-    if (!background_image_is_scheduled_)
-      background_image_->BeginPresent();
-
-    // WaylandWindow can attach a null wl_buffer to its surface to hide its
-    // content so needs to reschedule |background_image_| so that
-    // the wl_surface has a non-null wl_buffer when the window re-appears.
-    //
-    // TODO(fangzhoug): It should not be necessary to schedule
-    // |background_image_| every frame. Make this a responsibility of
-    // WaylandWindow instead.
-    presenter_->ScheduleBackground(background_image_.get());
-    background_image_is_scheduled_ = true;
-  }
-
   if (plane) {
     // If the current_image_ is nullptr, it means there is no change on the
     // primary plane. So we just need to schedule the last submitted image.
@@ -445,12 +431,6 @@
   overlay_transform_ = transform;
   FreeAllSurfaces();
 
-  if (needs_background_image_ && !background_image_) {
-    background_image_ =
-        presenter_->AllocateBackgroundImage(color_space_, gfx::Size(4, 4));
-    background_image_is_scheduled_ = false;
-  }
-
   images_ = presenter_->AllocateImages(color_space_, image_size_,
                                        capabilities_.number_of_buffers);
   if (images_.empty())
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue.h b/components/viz/service/display_embedder/skia_output_device_buffer_queue.h
index 1f2ea75f2..402f39c1 100644
--- a/components/viz/service/display_embedder/skia_output_device_buffer_queue.h
+++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue.h
@@ -30,8 +30,7 @@
       SkiaOutputSurfaceDependency* deps,
       gpu::SharedImageRepresentationFactory* representation_factory,
       gpu::MemoryTracker* memory_tracker,
-      const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback,
-      bool needs_background_image);
+      const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback);
 
   ~SkiaOutputDeviceBufferQueue() override;
 
@@ -127,13 +126,6 @@
 
   // Set to true if no image is to be used for the primary plane of this frame.
   bool current_frame_has_no_primary_plane_ = false;
-  // Whether the platform needs an occluded background image. Wayland needs it
-  // for opaque accelerated widgets and event wiring.
-  bool needs_background_image_ = false;
-  // A 4x4 small image that will be scaled to cover an opaque region.
-  std::unique_ptr<OutputPresenter::Image> background_image_ = nullptr;
-  // Set to true if background has been scheduled in a frame.
-  bool background_image_is_scheduled_ = false;
 };
 
 }  // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc b/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc
index 2220f339..28ef78e 100644
--- a/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc
+++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc
@@ -290,7 +290,7 @@
             gl_surface_, dependency_.get(), shared_image_factory_.get(),
             shared_image_representation_factory_.get()),
         dependency_.get(), shared_image_representation_factory_.get(),
-        memory_tracker_.get(), present_callback, false);
+        memory_tracker_.get(), present_callback);
   }
 
   void TearDownOnGpu() override {
diff --git a/components/viz/service/display_embedder/skia_output_device_vulkan.cc b/components/viz/service/display_embedder/skia_output_device_vulkan.cc
index f9239300..88e120f 100644
--- a/components/viz/service/display_embedder/skia_output_device_vulkan.cc
+++ b/components/viz/service/display_embedder/skia_output_device_vulkan.cc
@@ -302,6 +302,7 @@
   capabilities_.preserve_buffer_content = true;
   capabilities_.output_surface_origin = gfx::SurfaceOrigin::kTopLeft;
   capabilities_.supports_post_sub_buffer = true;
+  capabilities_.supports_target_damage = true;
   capabilities_.orientation_mode = OutputSurface::OrientationMode::kHardware;
 #if defined(OS_ANDROID)
   // With vulkan, if the chrome is launched in landscape mode, the chrome is
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc
index 65233f9d..056d804 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -400,22 +400,14 @@
   if (image_contexts.empty())
     return gpu::SyncToken();
 
-  gpu::SyncToken sync_token(
-      gpu::CommandBufferNamespace::VIZ_SKIA_OUTPUT_SURFACE,
-      impl_on_gpu_->command_buffer_id(), ++sync_fence_release_);
-  sync_token.SetVerifyFlush();
-
   // impl_on_gpu_ is released on the GPU thread by a posted task from
   // SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained.
-  auto callback =
-      base::BindOnce(&SkiaOutputSurfaceImplOnGpu::ReleaseImageContexts,
-                     base::Unretained(impl_on_gpu_.get()),
-                     std::move(image_contexts), sync_fence_release_);
+  auto callback = base::BindOnce(
+      &SkiaOutputSurfaceImplOnGpu::ReleaseImageContexts,
+      base::Unretained(impl_on_gpu_.get()), std::move(image_contexts));
   EnqueueGpuTask(std::move(callback), {}, /*make_current=*/true,
                  /*need_framebuffer=*/false);
-  // Defer ReleaseImageContexts.
-  FlushGpuTasks(/*wait_for_finish=*/false);
-  return sync_token;
+  return Flush();
 }
 
 std::unique_ptr<ExternalUseClient::ImageContext>
@@ -471,7 +463,6 @@
   EnqueueGpuTask(std::move(callback), std::move(resource_sync_tokens_),
                  /*make_current=*/true,
                  /*need_framebuffer=*/!dependency_->IsOffscreen());
-  FlushGpuTasks(/*wait_for_finish=*/false);
 
   // Recreate |root_recorder_| after SwapBuffers has been scheduled on GPU
   // thread to save some time in BeginPaintCurrentFrame
@@ -486,7 +477,6 @@
                              base::Unretained(impl_on_gpu_.get()));
   EnqueueGpuTask(std::move(task), std::move(resource_sync_tokens_),
                  /*make_current=*/false, /*need_framebuffer=*/false);
-  FlushGpuTasks(/*wait_for_finish=*/false);
 
   // TODO(vasilyt): reuse root recorder
   RecreateRootRecorder();
@@ -556,8 +546,7 @@
 }
 #endif  // defined(OS_APPLE)
 
-gpu::SyncToken SkiaOutputSurfaceImpl::SubmitPaint(
-    base::OnceClosure on_finished) {
+void SkiaOutputSurfaceImpl::EndPaint(base::OnceClosure on_finished) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(current_paint_);
   // If current_render_pass_id_ is not null, we are painting a render pass.
@@ -565,11 +554,6 @@
 
   bool painting_render_pass = !current_paint_->render_pass_id().is_null();
 
-  gpu::SyncToken sync_token(
-      gpu::CommandBufferNamespace::VIZ_SKIA_OUTPUT_SURFACE,
-      impl_on_gpu_->command_buffer_id(), ++sync_fence_release_);
-  sync_token.SetVerifyFlush();
-
   auto ddl = current_paint_->recorder()->detach();
 
   // impl_on_gpu_ is released on the GPU thread by a posted task from
@@ -590,16 +574,13 @@
       post_task_timestamp = base::TimeTicks::Now();
     }
 
-    auto task =
-        base::BindOnce(&SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass,
-                       base::Unretained(impl_on_gpu_.get()),
-                       post_task_timestamp, current_paint_->render_pass_id(),
-                       std::move(ddl), std::move(images_in_current_paint_),
-                       resource_sync_tokens_, sync_fence_release_);
+    auto task = base::BindOnce(
+        &SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass,
+        base::Unretained(impl_on_gpu_.get()), post_task_timestamp,
+        current_paint_->render_pass_id(), std::move(ddl),
+        std::move(images_in_current_paint_), resource_sync_tokens_);
     EnqueueGpuTask(std::move(task), std::move(resource_sync_tokens_),
                    /*make_current=*/true, /*need_framebuffer=*/false);
-    // Maybe not flush here to avoid an extra MakeCurrent() call.
-    FlushGpuTasks(/*wait_for_finish=*/false);
   } else {
     // Draw on the root render pass.
     current_buffer_modified_ = true;
@@ -616,15 +597,13 @@
         &SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame,
         base::Unretained(impl_on_gpu_.get()), std::move(ddl),
         std::move(overdraw_ddl), std::move(images_in_current_paint_),
-        resource_sync_tokens_, sync_fence_release_, std::move(on_finished),
-        draw_rectangle_);
+        resource_sync_tokens_, std::move(on_finished), draw_rectangle_);
     EnqueueGpuTask(std::move(task), std::move(resource_sync_tokens_),
                    /*make_current=*/true, /*need_framebuffer=*/true);
     draw_rectangle_.reset();
   }
   images_in_current_paint_.clear();
   current_paint_.reset();
-  return sync_token;
 }
 
 sk_sp<SkImage> SkiaOutputSurfaceImpl::MakePromiseSkImageFromRenderPass(
@@ -794,7 +773,6 @@
   if (capabilities_.preserve_buffer_content &&
       capabilities_.supports_post_sub_buffer) {
     capabilities_.only_invalidates_damage_rect = false;
-    capabilities_.supports_target_damage = true;
     // If there is only one pending frame, then we can use damage area hint from
     // SkiaOutputDevice, otherwise we have to track damage area in
     // SkiaOutputSurfaceImpl.
@@ -1123,6 +1101,20 @@
   observers_.RemoveObserver(observer);
 }
 
+gpu::SyncToken SkiaOutputSurfaceImpl::Flush() {
+  gpu::SyncToken sync_token(
+      gpu::CommandBufferNamespace::VIZ_SKIA_OUTPUT_SURFACE,
+      impl_on_gpu_->command_buffer_id(), ++sync_fence_release_);
+  sync_token.SetVerifyFlush();
+  auto callback = base::BindOnce(
+      &SkiaOutputSurfaceImplOnGpu::ReleaseFenceSyncAndPushTextureUpdates,
+      base::Unretained(impl_on_gpu_.get()), sync_fence_release_);
+  EnqueueGpuTask(std::move(callback), {}, /*make_current=*/false,
+                 /*need_framebuffer=*/false);
+  FlushGpuTasks(/*wait_for_finish=*/false);
+  return sync_token;
+}
+
 void SkiaOutputSurfaceImpl::PrepareYUVATextureIndices(
     const std::vector<ImageContext*>& contexts,
     bool has_alpha,
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.h b/components/viz/service/display_embedder/skia_output_surface_impl.h
index 0e6b0c8..eefddd8 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl.h
+++ b/components/viz/service/display_embedder/skia_output_surface_impl.h
@@ -106,7 +106,7 @@
                                  ResourceFormat format,
                                  bool mipmap,
                                  sk_sp<SkColorSpace> color_space) override;
-  gpu::SyncToken SubmitPaint(base::OnceClosure on_finished) override;
+  void EndPaint(base::OnceClosure on_finished) override;
   void MakePromiseSkImage(ImageContext* image_context) override;
   sk_sp<SkImage> MakePromiseSkImageFromRenderPass(
       const AggregatedRenderPassId& id,
@@ -126,6 +126,7 @@
                   std::unique_ptr<CopyOutputRequest> request) override;
   void AddContextLostObserver(ContextLostObserver* observer) override;
   void RemoveContextLostObserver(ContextLostObserver* observer) override;
+  gpu::SyncToken Flush() override;
 
 #if defined(OS_APPLE)
   SkCanvas* BeginPaintRenderPassOverlay(
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
index 829b4df..60592ce7 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -480,7 +480,6 @@
     sk_sp<SkDeferredDisplayList> overdraw_ddl,
     std::vector<ImageContextImpl*> image_contexts,
     std::vector<gpu::SyncToken> sync_tokens,
-    uint64_t sync_fence_release,
     base::OnceClosure on_finished,
     base::Optional<gfx::Rect> draw_rectangle) {
   TRACE_EVENT0("viz", "SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame");
@@ -577,7 +576,6 @@
       return;
     }
   }
-  ReleaseFenceSyncAndPushTextureUpdates(sync_fence_release);
 }
 
 void SkiaOutputSurfaceImplOnGpu::ScheduleOutputSurfaceAsOverlay(
@@ -610,8 +608,7 @@
     AggregatedRenderPassId id,
     sk_sp<SkDeferredDisplayList> ddl,
     std::vector<ImageContextImpl*> image_contexts,
-    std::vector<gpu::SyncToken> sync_tokens,
-    uint64_t sync_fence_release) {
+    std::vector<gpu::SyncToken> sync_tokens) {
   TRACE_EVENT0("viz", "SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass");
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(ddl);
@@ -670,7 +667,6 @@
       return;
     }
   }
-  ReleaseFenceSyncAndPushTextureUpdates(sync_fence_release);
 }
 
 void SkiaOutputSurfaceImplOnGpu::RemoveRenderPassResource(
@@ -960,8 +956,7 @@
 
 void SkiaOutputSurfaceImplOnGpu::ReleaseImageContexts(
     std::vector<std::unique_ptr<ExternalUseClient::ImageContext>>
-        image_contexts,
-    uint64_t sync_fence_release) {
+        image_contexts) {
   DCHECK(!image_contexts.empty());
   // The window could be destroyed already, and the MakeCurrent will fail with
   // an destroyed window, so MakeCurrent without requiring the fbo0.
@@ -971,7 +966,6 @@
   }
 
   image_contexts.clear();
-  ReleaseFenceSyncAndPushTextureUpdates(sync_fence_release);
 }
 
 void SkiaOutputSurfaceImplOnGpu::ScheduleOverlays(
@@ -1120,26 +1114,16 @@
 
     if (MakeCurrent(/*need_framebuffer=*/true)) {
       if (gl_surface_->IsSurfaceless()) {
-#if defined(USE_OZONE)
-        bool needs_background_image = ui::OzonePlatform::GetInstance()
-                                          ->GetPlatformProperties()
-                                          .needs_background_image;
-#else   // defined(USE_OZONE)
-        bool needs_background_image = false;
-#endif  // !defined(USE_OZONE)
-
 #if !defined(OS_WIN)
         output_device_ = std::make_unique<SkiaOutputDeviceBufferQueue>(
             std::make_unique<OutputPresenterGL>(
                 gl_surface_, dependency_, shared_image_factory_.get(),
                 shared_image_representation_factory_.get()),
             dependency_, shared_image_representation_factory_.get(),
-            memory_tracker_, GetDidSwapBuffersCompleteCallback(),
-            needs_background_image);
-#else   // !defined(OS_WIN)
+            memory_tracker_, GetDidSwapBuffersCompleteCallback());
+#else
         NOTIMPLEMENTED();
-        (void)needs_background_image;
-#endif  // defined(OS_WIN)
+#endif
       } else {
         if (dependency_->NeedsSupportForExternalStencil()) {
           output_device_ = std::make_unique<SkiaOutputDeviceWebView>(
@@ -1191,14 +1175,6 @@
   }
 #endif  // defined(USE_X11)
 
-#if defined(USE_OZONE)
-  bool needs_background_image = ui::OzonePlatform::GetInstance()
-                                    ->GetPlatformProperties()
-                                    .needs_background_image;
-#else   // defined(USE_OZONE)
-  bool needs_background_image = false;
-#endif  // !defined(USE_OZONE)
-
 #if !defined(OS_WIN)
 #if defined(OS_FUCHSIA)
   auto output_presenter = OutputPresenterFuchsia::Create(
@@ -1217,11 +1193,10 @@
     output_device_ = std::make_unique<SkiaOutputDeviceBufferQueue>(
         std::move(output_presenter), dependency_,
         shared_image_representation_factory_.get(), memory_tracker_,
-        GetDidSwapBuffersCompleteCallback(), needs_background_image);
+        GetDidSwapBuffersCompleteCallback());
     return true;
   }
 #endif  // !defined(OS_WIN)
-  (void)needs_background_image;
 
   auto output_device = SkiaOutputDeviceVulkan::Create(
       vulkan_context_provider_, dependency_->GetSurfaceHandle(),
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
index 5a13f3a..4b632be 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -123,7 +123,6 @@
                                sk_sp<SkDeferredDisplayList> overdraw_ddl,
                                std::vector<ImageContextImpl*> image_contexts,
                                std::vector<gpu::SyncToken> sync_tokens,
-                               uint64_t sync_fence_release,
                                base::OnceClosure on_finished,
                                base::Optional<gfx::Rect> draw_rectangle);
   void ScheduleOutputSurfaceAsOverlay(
@@ -140,8 +139,7 @@
                              AggregatedRenderPassId id,
                              sk_sp<SkDeferredDisplayList> ddl,
                              std::vector<ImageContextImpl*> image_contexts,
-                             std::vector<gpu::SyncToken> sync_tokens,
-                             uint64_t sync_fence_release);
+                             std::vector<gpu::SyncToken> sync_tokens);
   // Deletes resources for RenderPasses in |ids|. Also takes ownership of
   // |images_contexts| and destroys them on GPU thread.
   void RemoveRenderPassResource(
@@ -162,8 +160,7 @@
   size_t max_resource_cache_bytes() const { return max_resource_cache_bytes_; }
   void ReleaseImageContexts(
       std::vector<std::unique_ptr<ExternalUseClient::ImageContext>>
-          image_contexts,
-      uint64_t sync_fence_release);
+          image_contexts);
   void ScheduleOverlays(SkiaOutputSurface::OverlayList overlays,
                         std::vector<ImageContextImpl*> image_contexts);
 
@@ -209,6 +206,8 @@
   // It will do nothing when Vulkan is used.
   bool MakeCurrent(bool need_framebuffer);
 
+  void ReleaseFenceSyncAndPushTextureUpdates(uint64_t sync_fence_release);
+
  private:
   class OffscreenSurface;
   class DisplayContext;
@@ -234,8 +233,6 @@
 
   void PullTextureUpdates(std::vector<gpu::SyncToken> sync_token);
 
-  void ReleaseFenceSyncAndPushTextureUpdates(uint64_t sync_fence_release);
-
   void SwapBuffersInternal(OutputSurfaceFrame* frame = nullptr);
 
   GrDirectContext* gr_context() { return context_state_->gr_context(); }
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc b/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
index 903d98a..c94533f 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
@@ -94,7 +94,8 @@
   SkCanvas* root_canvas = output_surface_->BeginPaintCurrentFrame();
   root_canvas->drawRect(
       SkRect::MakeXYWH(rect.x(), rect.y(), rect.height(), rect.width()), paint);
-  return output_surface_->SubmitPaint(std::move(closure));
+  output_surface_->EndPaint(std::move(closure));
+  return output_surface_->Flush();
 }
 
 void SkiaOutputSurfaceImplTest::BlockMainThread() {
@@ -132,7 +133,7 @@
   UnblockMainThread();
 }
 
-TEST_F(SkiaOutputSurfaceImplTest, SubmitPaint) {
+TEST_F(SkiaOutputSurfaceImplTest, EndPaint) {
   output_surface_->Reshape(kSurfaceRect.size(), 1, gfx::ColorSpace(),
                            gfx::BufferFormat::RGBX_8888, /*use_stencil=*/false);
   constexpr gfx::Rect output_rect(0, 0, 10, 10);
@@ -162,9 +163,10 @@
   output_surface_->CopyOutput(AggregatedRenderPassId{0}, geometry, color_space,
                               std::move(request));
   output_surface_->SwapBuffersSkipped();
+  output_surface_->Flush();
   BlockMainThread();
 
-  // SubmitPaint draw is deferred until CopyOutput.
+  // EndPaint draw is deferred until CopyOutput.
   base::OnceClosure closure =
       base::BindOnce(&SkiaOutputSurfaceImplTest::CheckSyncTokenOnGpuThread,
                      base::Unretained(this), sync_token);
@@ -227,6 +229,7 @@
   output_surface_->CopyOutput(AggregatedRenderPassId{0}, geometry, color_space,
                               std::move(request));
   output_surface_->SwapBuffersSkipped();
+  output_surface_->Flush();
   run_loop.Run();
 
   EXPECT_EQ(color_space, result->GetRGBAColorSpace());
@@ -265,6 +268,7 @@
   output_surface_->CopyOutput(AggregatedRenderPassId{0}, geometry, color_space,
                               std::move(request));
   output_surface_->SwapBuffersSkipped();
+  output_surface_->Flush();
   run_loop.Run();
 
   EXPECT_EQ(gfx::ColorSpace::CreateSRGB(), result->GetRGBAColorSpace());
diff --git a/components/viz/test/fake_skia_output_surface.cc b/components/viz/test/fake_skia_output_surface.cc
index ebc2a07..519db12 100644
--- a/components/viz/test/fake_skia_output_surface.cc
+++ b/components/viz/test/fake_skia_output_surface.cc
@@ -207,18 +207,13 @@
   return sk_surface->getCanvas();
 }
 
-gpu::SyncToken FakeSkiaOutputSurface::SubmitPaint(
-    base::OnceClosure on_finished) {
+void FakeSkiaOutputSurface::EndPaint(base::OnceClosure on_finished) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   sk_surfaces_[current_render_pass_id_]->flushAndSubmit();
   current_render_pass_id_ = AggregatedRenderPassId{0};
 
   if (on_finished)
     std::move(on_finished).Run();
-
-  gpu::SyncToken sync_token;
-  context_provider()->ContextGL()->GenSyncTokenCHROMIUM(sync_token.GetData());
-  return sync_token;
 }
 
 sk_sp<SkImage> FakeSkiaOutputSurface::MakePromiseSkImageFromRenderPass(
@@ -316,6 +311,12 @@
   NOTIMPLEMENTED();
 }
 
+gpu::SyncToken FakeSkiaOutputSurface::Flush() {
+  gpu::SyncToken sync_token;
+  context_provider()->ContextGL()->GenSyncTokenCHROMIUM(sync_token.GetData());
+  return sync_token;
+}
+
 #if defined(OS_APPLE)
 SkCanvas* FakeSkiaOutputSurface::BeginPaintRenderPassOverlay(
     const gfx::Size& size,
diff --git a/components/viz/test/fake_skia_output_surface.h b/components/viz/test/fake_skia_output_surface.h
index 5ade5910..a617d5a 100644
--- a/components/viz/test/fake_skia_output_surface.h
+++ b/components/viz/test/fake_skia_output_surface.h
@@ -79,7 +79,7 @@
                                  ResourceFormat format,
                                  bool mipmap,
                                  sk_sp<SkColorSpace> color_space) override;
-  gpu::SyncToken SubmitPaint(base::OnceClosure on_finished) override;
+  void EndPaint(base::OnceClosure on_finished) override;
   void MakePromiseSkImage(ImageContext* image_context) override;
   sk_sp<SkImage> MakePromiseSkImageFromRenderPass(
       const AggregatedRenderPassId& id,
@@ -100,6 +100,7 @@
                   std::unique_ptr<CopyOutputRequest> request) override;
   void AddContextLostObserver(ContextLostObserver* observer) override;
   void RemoveContextLostObserver(ContextLostObserver* observer) override;
+  gpu::SyncToken Flush() override;
 #if defined(OS_APPLE)
   SkCanvas* BeginPaintRenderPassOverlay(
       const gfx::Size& size,
diff --git a/content/app/content_main_runner_impl.cc b/content/app/content_main_runner_impl.cc
index d5781e9..78235d4 100644
--- a/content/app/content_main_runner_impl.cc
+++ b/content/app/content_main_runner_impl.cc
@@ -15,6 +15,7 @@
 
 #include "base/allocator/allocator_check.h"
 #include "base/allocator/allocator_extension.h"
+#include "base/allocator/allocator_shim.h"
 #include "base/allocator/buildflags.h"
 #include "base/at_exit.h"
 #include "base/base_switches.h"
@@ -232,6 +233,13 @@
 #endif  // V8_USE_EXTERNAL_STARTUP_DATA
 }
 
+void EnablePCScanForMallocPartitionsIfNeeded() {
+#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
+  CHECK(base::FeatureList::GetInstance());
+  base::allocator::EnablePCScanIfNeeded();
+#endif
+}
+
 #if BUILDFLAG(USE_ZYGOTE_HANDLE)
 pid_t LaunchZygoteHelper(base::CommandLine* cmd_line,
                          base::ScopedFD* control_fd) {
@@ -479,6 +487,10 @@
   InitializeFieldTrialAndFeatureList();
   delegate->PostFieldTrialInitialization();
 
+  // After feature list has been initialized, enable pcscan on malloc
+  // partitions.
+  EnablePCScanForMallocPartitionsIfNeeded();
+
   for (size_t i = 0; i < base::size(kMainFunctions); ++i) {
     if (process_type == kMainFunctions[i].name)
       return kMainFunctions[i].function(main_params);
@@ -529,6 +541,11 @@
     }
   }
 
+  if (process_type != switches::kZygoteProcess) {
+    // Zygote processes are handled in RunZygote.
+    EnablePCScanForMallocPartitionsIfNeeded();
+  }
+
 #if BUILDFLAG(USE_ZYGOTE_HANDLE)
   // Zygote startup is special -- see RunZygote comments above
   // for why we don't use ZygoteMain directly.
@@ -826,6 +843,10 @@
       // has been updated.
       InitializeFieldTrialAndFeatureList();
       delegate_->PostFieldTrialInitialization();
+
+      // After feature list has been initialized, enable pcscan on malloc
+      // partitions.
+      EnablePCScanForMallocPartitionsIfNeeded();
     }
 
 #if defined(OS_LINUX) || defined(OS_CHROMEOS)
@@ -965,6 +986,9 @@
 #endif
   }
 
+  // Enable PCScan once we are certain that FeatureList was initialized.
+  EnablePCScanForMallocPartitionsIfNeeded();
+
   if (should_start_service_manager_only) {
     DVLOG(0) << "Chrome is running in ServiceManager only mode.";
     return -1;
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index 21adc2b..fca8aedf 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -1513,9 +1513,8 @@
   return false;
 }
 
-bool BrowserAccessibility::IsChildOfPlainTextField() const {
-  ui::AXNode* textfield_node = node()->GetTextFieldAncestor();
-  return textfield_node && textfield_node->data().IsPlainTextField();
+bool BrowserAccessibility::IsDescendantOfPlainTextField() const {
+  return node()->IsDescendantOfPlainTextField();
 }
 
 gfx::NativeViewAccessible BrowserAccessibility::GetClosestPlatformObject()
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h
index 134ce361..e77d1bc 100644
--- a/content/browser/accessibility/browser_accessibility.h
+++ b/content/browser/accessibility/browser_accessibility.h
@@ -422,7 +422,7 @@
   gfx::NativeViewAccessible GetPreviousSibling() override;
 
   bool IsChildOfLeaf() const override;
-  bool IsChildOfPlainTextField() const override;
+  bool IsDescendantOfPlainTextField() const override;
   bool IsLeaf() const override;
   bool IsToplevelBrowserWindow() override;
   gfx::NativeViewAccessible GetClosestPlatformObject() const override;
diff --git a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
index 46cd95a1..460fe2c 100644
--- a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
+++ b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -1471,8 +1471,16 @@
   EXPECT_GT(bounds.y(), 0);
 }
 
+// http://crbug.com/1141280
+#if defined(OS_LINUX)
+#define MAYBE_NonInteractiveChangesAreBatched \
+  DISABLED_NonInteractiveChangesAreBatched
+#else
+#define MAYBE_NonInteractiveChangesAreBatched NonInteractiveChangesAreBatched
+#endif
+
 IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
-                       NonInteractiveChangesAreBatched) {
+                       MAYBE_NonInteractiveChangesAreBatched) {
   // Ensure that normal DOM changes are batched together, and do not occur
   // more than once every kDelayForDeferredUpdatesAfterPageLoad.
   const char url_str[] =
diff --git a/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index 15deaf5..680dafa3 100644
--- a/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -31,7 +31,7 @@
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 
 namespace content {
 
diff --git a/content/browser/appcache/appcache_manifest_parser_unittest.cc b/content/browser/appcache/appcache_manifest_parser_unittest.cc
index a66003ef..29639af 100644
--- a/content/browser/appcache/appcache_manifest_parser_unittest.cc
+++ b/content/browser/appcache/appcache_manifest_parser_unittest.cc
@@ -28,6 +28,9 @@
     blink::TrialTokenValidator::SetOriginTrialPolicyGetter(base::BindRepeating(
         []() -> blink::OriginTrialPolicy* { return &g_origin_trial_policy; }));
   }
+  void TearDown() override {
+    blink::TrialTokenValidator::ResetOriginTrialPolicyGetter();
+  }
 };
 
 TEST_F(AppCacheManifestParserTest, NoData) {
diff --git a/content/browser/appcache/appcache_update_job_unittest.cc b/content/browser/appcache/appcache_update_job_unittest.cc
index ed6ac5c..7d961ae 100644
--- a/content/browser/appcache/appcache_update_job_unittest.cc
+++ b/content/browser/appcache/appcache_update_job_unittest.cc
@@ -791,6 +791,7 @@
   }
 
   void TearDown() override {
+    blink::TrialTokenValidator::ResetOriginTrialPolicyGetter();
     weak_partition_factory_.reset();
     browser_context_.reset();
 
diff --git a/content/browser/bluetooth/bluetooth_blocklist.cc b/content/browser/bluetooth/bluetooth_blocklist.cc
index ff6f57e..2521543c 100644
--- a/content/browser/bluetooth/bluetooth_blocklist.cc
+++ b/content/browser/bluetooth/bluetooth_blocklist.cc
@@ -184,8 +184,6 @@
 }
 
 void BluetoothBlocklist::PopulateWithServerProvidedValues() {
-  // DCHECK to maybe help debug https://crbug.com/604078.
-  DCHECK(GetContentClient());
   Add(GetContentClient()->browser()->GetWebBluetoothBlocklist());
 }
 
diff --git a/content/browser/bluetooth/bluetooth_blocklist_unittest.cc b/content/browser/bluetooth/bluetooth_blocklist_unittest.cc
index 01630c83..15a87e6 100644
--- a/content/browser/bluetooth/bluetooth_blocklist_unittest.cc
+++ b/content/browser/bluetooth/bluetooth_blocklist_unittest.cc
@@ -53,20 +53,31 @@
 }
 
 TEST_F(BluetoothBlocklistTest, InvalidUUID) {
+#ifdef OFFICIAL_BUILD
+  // The official build does not print the reason a CHECK failed.
+  const char kErrorRegex[] = "";
+#else
+  const char kErrorRegex[] = "uuid.IsValid\\(\\)";
+#endif
   BluetoothUUID empty_string_uuid("");
   EXPECT_DEATH_IF_SUPPORTED(
-      list_.Add(empty_string_uuid, BluetoothBlocklist::Value::EXCLUDE), "");
-  EXPECT_DEATH_IF_SUPPORTED(list_.IsExcluded(empty_string_uuid), "");
-  EXPECT_DEATH_IF_SUPPORTED(list_.IsExcludedFromReads(empty_string_uuid), "");
-  EXPECT_DEATH_IF_SUPPORTED(list_.IsExcludedFromWrites(empty_string_uuid), "");
+      list_.Add(empty_string_uuid, BluetoothBlocklist::Value::EXCLUDE),
+      kErrorRegex);
+  EXPECT_DEATH_IF_SUPPORTED(list_.IsExcluded(empty_string_uuid), kErrorRegex);
+  EXPECT_DEATH_IF_SUPPORTED(list_.IsExcludedFromReads(empty_string_uuid),
+                            kErrorRegex);
+  EXPECT_DEATH_IF_SUPPORTED(list_.IsExcludedFromWrites(empty_string_uuid),
+                            kErrorRegex);
 
   BluetoothUUID invalid_string_uuid("Not a valid UUID string.");
   EXPECT_DEATH_IF_SUPPORTED(
-      list_.Add(invalid_string_uuid, BluetoothBlocklist::Value::EXCLUDE), "");
-  EXPECT_DEATH_IF_SUPPORTED(list_.IsExcluded(invalid_string_uuid), "");
-  EXPECT_DEATH_IF_SUPPORTED(list_.IsExcludedFromReads(invalid_string_uuid), "");
+      list_.Add(invalid_string_uuid, BluetoothBlocklist::Value::EXCLUDE),
+      kErrorRegex);
+  EXPECT_DEATH_IF_SUPPORTED(list_.IsExcluded(invalid_string_uuid), kErrorRegex);
+  EXPECT_DEATH_IF_SUPPORTED(list_.IsExcludedFromReads(invalid_string_uuid),
+                            kErrorRegex);
   EXPECT_DEATH_IF_SUPPORTED(list_.IsExcludedFromWrites(invalid_string_uuid),
-                            "");
+                            kErrorRegex);
 }
 
 // Abreviated UUIDs used to create, or test against, the blocklist work
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc
index b6363aec..7fa85f3 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -22,6 +22,7 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents_observer.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/mojom/input/focus_type.mojom.h"
 
 #if defined(OS_MAC)
@@ -102,7 +103,7 @@
     owner_web_contents_ = owner_web_contents;
   }
 
-  blink::mojom::RendererPreferences* renderer_prefs =
+  blink::RendererPreferences* renderer_prefs =
       GetWebContents()->GetMutableRendererPrefs();
   blink::UserAgentOverride guest_user_agent_override =
       renderer_prefs->user_agent_override;
diff --git a/content/browser/browser_plugin/browser_plugin_guest.h b/content/browser/browser_plugin/browser_plugin_guest.h
index 4e1cf01..347c1f83 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/content/browser/browser_plugin/browser_plugin_guest.h
@@ -77,8 +77,8 @@
   // container, then this call is a no-op. For guest types that can be
   // navigated, this call adds the associated RenderWdigetHostViewGuest to the
   // view hierarchy and sets up the appropriate
-  // blink::mojom::RendererPreferences so that this guest can navigate and
-  // resize offscreen.
+  // blink::RendererPreferences so that this guest can navigate and resize
+  // offscreen.
   void Init();
 
   // Returns a WeakPtr to this BrowserPluginGuest.
diff --git a/content/browser/devtools/protocol/webauthn_handler.cc b/content/browser/devtools/protocol/webauthn_handler.cc
index fd69a47..a08da03 100644
--- a/content/browser/devtools/protocol/webauthn_handler.cc
+++ b/content/browser/devtools/protocol/webauthn_handler.cc
@@ -9,6 +9,9 @@
 #include <utility>
 #include <vector>
 
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "content/browser/renderer_host/render_frame_host_impl.h"
@@ -30,6 +33,8 @@
     "U2F only supports the \"usb\", \"ble\" and \"nfc\" transports";
 static constexpr char kCouldNotCreateCredential[] =
     "An error occurred trying to create the credential";
+static constexpr char kCouldNotStoreLargeBlob[] =
+    "An error occurred trying to store the large blob";
 static constexpr char kCredentialNotFound[] =
     "Could not find a credential matching the ID";
 static constexpr char kDevToolsNotAttached[] =
@@ -38,10 +43,16 @@
     "An error occurred when trying to create the authenticator";
 static constexpr char kHandleRequiredForResidentCredential[] =
     "The User Handle is required for Resident Credentials";
+static constexpr char kInvalidCtapVersion[] =
+    "Invalid CTAP version. Valid values are \"ctap2_0\" and \"ctap2_1\"";
 static constexpr char kInvalidProtocol[] = "The protocol is not valid";
 static constexpr char kInvalidTransport[] = "The transport is not valid";
 static constexpr char kInvalidUserHandle[] =
     "The User Handle must have a maximum size of ";
+static constexpr char kLargeBlobRequiresResidentKey[] =
+    "Large blob requires resident key support";
+static constexpr char kLargeBlobRequiresCtap2_1[] =
+    "Large blob requires a CTAP 2.1 authenticator";
 static constexpr char kResidentCredentialNotSupported[] =
     "The Authenticator does not support Resident Credentials.";
 static constexpr char kRpIdRequired[] =
@@ -50,6 +61,38 @@
     "The Virtual Authenticator Environment has not been enabled for this "
     "session";
 
+class GetCredentialCallbackAggregator
+    : public base::RefCounted<GetCredentialCallbackAggregator> {
+ public:
+  REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
+
+  explicit GetCredentialCallbackAggregator(
+      std::unique_ptr<WebAuthn::Backend::GetCredentialsCallback> callback)
+      : callback_(std::move(callback)) {}
+  GetCredentialCallbackAggregator(const GetCredentialCallbackAggregator&) =
+      delete;
+  GetCredentialCallbackAggregator operator=(
+      const GetCredentialCallbackAggregator&) = delete;
+
+  void OnLargeBlob(std::unique_ptr<WebAuthn::Credential> credential,
+                   const base::Optional<std::vector<uint8_t>>& blob) {
+    if (blob) {
+      credential->SetLargeBlob(Binary::fromVector(*blob));
+    }
+    credentials_->emplace_back(std::move(credential));
+  }
+
+ private:
+  friend class base::RefCounted<GetCredentialCallbackAggregator>;
+  ~GetCredentialCallbackAggregator() {
+    callback_->sendSuccess(std::move(credentials_));
+  }
+
+  std::unique_ptr<WebAuthn::Backend::GetCredentialsCallback> callback_;
+  std::unique_ptr<Array<WebAuthn::Credential>> credentials_ =
+      std::make_unique<Array<WebAuthn::Credential>>();
+};
+
 device::ProtocolVersion ConvertToProtocolVersion(base::StringPiece protocol) {
   if (protocol == WebAuthn::AuthenticatorProtocolEnum::Ctap2)
     return device::ProtocolVersion::kCtap2;
@@ -58,6 +101,15 @@
   return device::ProtocolVersion::kUnknown;
 }
 
+base::Optional<device::Ctap2Version> ConvertToCtap2Version(
+    base::StringPiece version) {
+  if (version == WebAuthn::Ctap2VersionEnum::Ctap2_0)
+    return device::Ctap2Version::kCtap2_0;
+  if (version == WebAuthn::Ctap2VersionEnum::Ctap2_1)
+    return device::Ctap2Version::kCtap2_1;
+  return base::nullopt;
+}
+
 std::vector<uint8_t> CopyBinaryToVector(const Binary& binary) {
   return std::vector<uint8_t>(binary.data(), binary.data() + binary.size());
 }
@@ -143,6 +195,20 @@
     return Response::InvalidParams(kCableNotSupportedOnU2f);
   }
 
+  auto ctap2_version = ConvertToCtap2Version(
+      options->GetCtap2Version(WebAuthn::Ctap2VersionEnum::Ctap2_0));
+  if (!ctap2_version)
+    return Response::InvalidParams(kInvalidCtapVersion);
+
+  bool has_large_blob = options->GetHasLargeBlob(/*default=*/false);
+  bool has_resident_key = options->GetHasResidentKey(/*default=*/false);
+  if (has_large_blob && !has_resident_key)
+    return Response::InvalidParams(kLargeBlobRequiresResidentKey);
+  if (has_large_blob && (protocol != device::ProtocolVersion::kCtap2 ||
+                         ctap2_version < device::Ctap2Version::kCtap2_1)) {
+    return Response::InvalidParams(kLargeBlobRequiresCtap2_1);
+  }
+
   VirtualAuthenticator* authenticator = nullptr;
   switch (protocol) {
     case device::ProtocolVersion::kU2f:
@@ -150,13 +216,12 @@
       break;
     case device::ProtocolVersion::kCtap2:
       authenticator = authenticator_manager->CreateCTAP2Authenticator(
-          device::Ctap2Version::kCtap2_0, *transport,
+          *ctap2_version, *transport,
           transport == device::FidoTransportProtocol::kInternal
               ? device::AuthenticatorAttachment::kPlatform
               : device::AuthenticatorAttachment::kCrossPlatform,
-          options->GetHasResidentKey(/*default=*/false),
-          options->GetHasUserVerification(/*default=*/false),
-          options->GetHasLargeBlob(/*default=*/false));
+          has_resident_key, options->GetHasUserVerification(/*default=*/false),
+          has_large_blob);
       break;
     case device::ProtocolVersion::kUnknown:
       NOTREACHED();
@@ -188,84 +253,136 @@
   return Response::Success();
 }
 
-Response WebAuthnHandler::AddCredential(
+void WebAuthnHandler::AddCredential(
     const String& authenticator_id,
-    std::unique_ptr<WebAuthn::Credential> credential) {
+    std::unique_ptr<WebAuthn::Credential> credential,
+    std::unique_ptr<AddCredentialCallback> callback) {
   VirtualAuthenticator* authenticator;
   Response response = FindAuthenticator(authenticator_id, &authenticator);
-  if (!response.IsSuccess())
-    return response;
+  if (!response.IsSuccess()) {
+    callback->sendFailure(std::move(response));
+    return;
+  }
 
   Binary user_handle = credential->GetUserHandle(Binary());
   if (credential->HasUserHandle() &&
       user_handle.size() > device::kUserHandleMaxLength) {
-    return Response::InvalidParams(
+    callback->sendFailure(Response::InvalidParams(
         kInvalidUserHandle +
-        base::NumberToString(device::kUserHandleMaxLength));
+        base::NumberToString(device::kUserHandleMaxLength)));
+    return;
   }
 
-  if (!credential->HasRpId())
-    return Response::InvalidParams(kRpIdRequired);
+  if (!credential->HasRpId()) {
+    callback->sendFailure(Response::InvalidParams(kRpIdRequired));
+    return;
+  }
+  if (credential->HasLargeBlob() && !credential->GetIsResidentCredential()) {
+    callback->sendFailure(
+        Response::InvalidParams(kLargeBlobRequiresResidentKey));
+    return;
+  }
 
   bool credential_created;
+  std::vector<uint8_t> credential_id =
+      CopyBinaryToVector(credential->GetCredentialId());
   if (credential->GetIsResidentCredential()) {
-    if (!authenticator->has_resident_key())
-      return Response::InvalidParams(kResidentCredentialNotSupported);
+    if (!authenticator->has_resident_key()) {
+      callback->sendFailure(
+          Response::InvalidParams(kResidentCredentialNotSupported));
+      return;
+    }
 
-    if (!credential->HasUserHandle())
-      return Response::InvalidParams(kHandleRequiredForResidentCredential);
+    if (!credential->HasUserHandle()) {
+      callback->sendFailure(
+          Response::InvalidParams(kHandleRequiredForResidentCredential));
+      return;
+    }
 
     credential_created = authenticator->AddResidentRegistration(
-        CopyBinaryToVector(credential->GetCredentialId()),
-        credential->GetRpId(""),
-        CopyBinaryToVector(credential->GetPrivateKey()),
+        credential_id, credential->GetRpId(""), credential->GetPrivateKey(),
         credential->GetSignCount(), CopyBinaryToVector(user_handle));
   } else {
     credential_created = authenticator->AddRegistration(
-        CopyBinaryToVector(credential->GetCredentialId()),
-        credential->GetRpId(""),
-        CopyBinaryToVector(credential->GetPrivateKey()),
+        credential_id, credential->GetRpId(""), credential->GetPrivateKey(),
         credential->GetSignCount());
   }
 
-  if (!credential_created)
-    return Response::ServerError(kCouldNotCreateCredential);
+  if (!credential_created) {
+    callback->sendFailure(Response::ServerError(kCouldNotCreateCredential));
+    return;
+  }
 
-  return Response::Success();
+  if (credential->HasLargeBlob()) {
+    authenticator->SetLargeBlob(
+        credential_id, CopyBinaryToVector(credential->GetLargeBlob({})),
+        base::BindOnce(
+            [](std::unique_ptr<AddCredentialCallback> callback, bool success) {
+              if (!success) {
+                callback->sendFailure(
+                    Response::ServerError(kCouldNotStoreLargeBlob));
+                return;
+              }
+              callback->sendSuccess();
+            },
+            std::move(callback)));
+    return;
+  }
+
+  callback->sendSuccess();
 }
 
-Response WebAuthnHandler::GetCredential(
+void WebAuthnHandler::GetCredential(
     const String& authenticator_id,
     const Binary& credential_id,
-    std::unique_ptr<WebAuthn::Credential>* out_credential) {
+    std::unique_ptr<GetCredentialCallback> callback) {
   VirtualAuthenticator* authenticator;
   Response response = FindAuthenticator(authenticator_id, &authenticator);
-  if (!response.IsSuccess())
-    return response;
+  if (!response.IsSuccess()) {
+    callback->sendFailure(response);
+    return;
+  }
 
   auto registration =
       authenticator->registrations().find(CopyBinaryToVector(credential_id));
-  if (registration == authenticator->registrations().end())
-    return Response::InvalidParams(kCredentialNotFound);
+  if (registration == authenticator->registrations().end()) {
+    callback->sendFailure(Response::InvalidParams(kCredentialNotFound));
+    return;
+  }
 
-  *out_credential = BuildCredentialFromRegistration(*registration);
-  return Response::Success();
+  authenticator->GetLargeBlob(
+      registration->first,
+      base::BindOnce(
+          [](std::unique_ptr<WebAuthn::Credential> registration,
+             std::unique_ptr<GetCredentialCallback> callback,
+             const base::Optional<std::vector<uint8_t>>& blob) {
+            if (blob) {
+              registration->SetLargeBlob(Binary::fromVector(*blob));
+            }
+            callback->sendSuccess(std::move(registration));
+          },
+          BuildCredentialFromRegistration(*registration), std::move(callback)));
 }
 
-Response WebAuthnHandler::GetCredentials(
+void WebAuthnHandler::GetCredentials(
     const String& authenticator_id,
-    std::unique_ptr<Array<WebAuthn::Credential>>* out_credentials) {
+    std::unique_ptr<GetCredentialsCallback> callback) {
   VirtualAuthenticator* authenticator;
   Response response = FindAuthenticator(authenticator_id, &authenticator);
-  if (!response.IsSuccess())
-    return response;
-
-  *out_credentials = std::make_unique<Array<WebAuthn::Credential>>();
-  for (const auto& registration : authenticator->registrations()) {
-    (*out_credentials)
-        ->emplace_back(BuildCredentialFromRegistration(registration));
+  if (!response.IsSuccess()) {
+    callback->sendFailure(response);
+    return;
   }
-  return Response::Success();
+
+  auto aggregator = base::MakeRefCounted<GetCredentialCallbackAggregator>(
+      std::move(callback));
+  for (const auto& registration : authenticator->registrations()) {
+    authenticator->GetLargeBlob(
+        registration.first,
+        base::BindOnce(&GetCredentialCallbackAggregator::OnLargeBlob,
+                       aggregator,
+                       BuildCredentialFromRegistration(registration)));
+  }
 }
 
 Response WebAuthnHandler::RemoveCredential(const String& authenticator_id,
diff --git a/content/browser/devtools/protocol/webauthn_handler.h b/content/browser/devtools/protocol/webauthn_handler.h
index df5733c..3e26843e 100644
--- a/content/browser/devtools/protocol/webauthn_handler.h
+++ b/content/browser/devtools/protocol/webauthn_handler.h
@@ -20,6 +20,8 @@
  public:
   CONTENT_EXPORT WebAuthnHandler();
   CONTENT_EXPORT ~WebAuthnHandler() override;
+  WebAuthnHandler(const WebAuthnHandler&) = delete;
+  WebAuthnHandler operator=(const WebAuthnHandler&) = delete;
 
   // DevToolsDomainHandler:
   void SetRenderer(int process_host_id,
@@ -33,17 +35,15 @@
       std::unique_ptr<WebAuthn::VirtualAuthenticatorOptions> options,
       String* out_authenticator_id) override;
   Response RemoveVirtualAuthenticator(const String& authenticator_id) override;
-  Response AddCredential(
+  void AddCredential(const String& authenticator_id,
+                     std::unique_ptr<protocol::WebAuthn::Credential> credential,
+                     std::unique_ptr<AddCredentialCallback> callback) override;
+  void GetCredential(const String& authenticator_id,
+                     const Binary& credential_id,
+                     std::unique_ptr<GetCredentialCallback> callback) override;
+  void GetCredentials(
       const String& authenticator_id,
-      std::unique_ptr<protocol::WebAuthn::Credential> credential) override;
-  Response GetCredential(
-      const String& authenticator_id,
-      const Binary& credential_id,
-      std::unique_ptr<WebAuthn::Credential>* out_credential) override;
-  Response GetCredentials(
-      const String& authenticator_id,
-      std::unique_ptr<protocol::Array<protocol::WebAuthn::Credential>>*
-          out_credentials) override;
+      std::unique_ptr<GetCredentialsCallback> callback) override;
   Response RemoveCredential(const String& in_authenticator_id,
                             const Binary& credential_id) override;
   Response ClearCredentials(const String& in_authenticator_id) override;
@@ -58,7 +58,6 @@
   Response FindAuthenticator(const String& id,
                              VirtualAuthenticator** out_authenticator);
   RenderFrameHostImpl* frame_host_ = nullptr;
-  DISALLOW_COPY_AND_ASSIGN(WebAuthnHandler);
 };
 
 }  // namespace protocol
diff --git a/content/browser/devtools/protocol_config.json b/content/browser/devtools/protocol_config.json
index 593c420..38f725e 100644
--- a/content/browser/devtools/protocol_config.json
+++ b/content/browser/devtools/protocol_config.json
@@ -110,7 +110,8 @@
             },
             {
                 "domain": "WebAuthn",
-                "include": ["enable", "disable", "addVirtualAuthenticator", "removeVirtualAuthenticator", "addCredential", "removeCredential", "clearCredentials", "getCredential", "getCredentials", "setUserVerified", "setAutomaticPresenceSimulation"]
+                "include": ["enable", "disable", "addVirtualAuthenticator", "removeVirtualAuthenticator", "addCredential", "removeCredential", "clearCredentials", "getCredential", "getCredentials", "setUserVerified", "setAutomaticPresenceSimulation"],
+                "async": ["addCredential", "getCredential", "getCredentials"]
             }
         ]
     },
diff --git a/content/browser/do_not_track_browsertest.cc b/content/browser/do_not_track_browsertest.cc
index 974eaa5..6801b88 100644
--- a/content/browser/do_not_track_browsertest.cc
+++ b/content/browser/do_not_track_browsertest.cc
@@ -17,7 +17,7 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 
 #if defined(OS_ANDROID)
 #include "base/system/sys_info.h"
@@ -31,7 +31,7 @@
  public:
   void UpdateRendererPreferencesForWorker(
       BrowserContext*,
-      blink::mojom::RendererPreferences* prefs) override {
+      blink::RendererPreferences* prefs) override {
     if (do_not_track_enabled_) {
       prefs->enable_do_not_track = true;
       prefs->enable_referrers = true;
@@ -71,7 +71,7 @@
     if (!original_client_)
       return false;
     client_.EnableDoNotTrack();
-    blink::mojom::RendererPreferences* prefs =
+    blink::RendererPreferences* prefs =
         shell()->web_contents()->GetMutableRendererPrefs();
     EXPECT_FALSE(prefs->enable_do_not_track);
     prefs->enable_do_not_track = true;
diff --git a/content/browser/loader/browser_initiated_resource_request.cc b/content/browser/loader/browser_initiated_resource_request.cc
index d9cbc45..bd4811fd 100644
--- a/content/browser/loader/browser_initiated_resource_request.cc
+++ b/content/browser/loader/browser_initiated_resource_request.cc
@@ -18,7 +18,7 @@
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/request_mode.h"
 #include "services/network/public/cpp/resource_request.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 
 namespace content {
 
@@ -26,7 +26,7 @@
     net::HttpRequestHeaders* headers,
     BrowserContext* browser_context,
     bool should_update_existing_headers,
-    const blink::mojom::RendererPreferences& renderer_preferences) {
+    const blink::RendererPreferences& renderer_preferences) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   // Set the DoNotTrack header if appropriate.
diff --git a/content/browser/loader/browser_initiated_resource_request.h b/content/browser/loader/browser_initiated_resource_request.h
index f18f548e..c864549 100644
--- a/content/browser/loader/browser_initiated_resource_request.h
+++ b/content/browser/loader/browser_initiated_resource_request.h
@@ -10,9 +10,7 @@
 }  // namespace net
 
 namespace blink {
-namespace mojom {
-class RendererPreferences;
-}  // namespace mojom
+struct RendererPreferences;
 }  // namespace blink
 
 namespace content {
@@ -29,7 +27,7 @@
     net::HttpRequestHeaders* headers,
     BrowserContext* browser_context,
     bool should_update_existing_headers,
-    const blink::mojom::RendererPreferences& renderer_preferences);
+    const blink::RendererPreferences& renderer_preferences);
 
 }  // namespace content
 
diff --git a/content/browser/loader/prefetch_url_loader_service.cc b/content/browser/loader/prefetch_url_loader_service.cc
index ad8b9264..2412483 100644
--- a/content/browser/loader/prefetch_url_loader_service.cc
+++ b/content/browser/loader/prefetch_url_loader_service.cc
@@ -25,8 +25,8 @@
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 
 namespace {
 void DumpWithoutCrashing(const network::ResourceRequest& request) {
@@ -330,8 +330,8 @@
 }
 
 void PrefetchURLLoaderService::NotifyUpdate(
-    blink::mojom::RendererPreferencesPtr new_prefs) {
-  SetAcceptLanguages(new_prefs->accept_languages);
+    const blink::RendererPreferences& new_prefs) {
+  SetAcceptLanguages(new_prefs.accept_languages);
 }
 
 base::UnguessableToken PrefetchURLLoaderService::GenerateRecursivePrefetchToken(
diff --git a/content/browser/loader/prefetch_url_loader_service.h b/content/browser/loader/prefetch_url_loader_service.h
index f930519..fb693e1 100644
--- a/content/browser/loader/prefetch_url_loader_service.h
+++ b/content/browser/loader/prefetch_url_loader_service.h
@@ -98,7 +98,7 @@
       const network::ResourceRequest& request);
 
   // blink::mojom::RendererPreferenceWatcher.
-  void NotifyUpdate(blink::mojom::RendererPreferencesPtr new_prefs) override;
+  void NotifyUpdate(const blink::RendererPreferences& new_prefs) override;
 
   // For URLLoaderThrottlesGetter.
   std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
diff --git a/content/browser/renderer_host/cross_process_frame_connector.cc b/content/browser/renderer_host/cross_process_frame_connector.cc
index 3af7cf0..f36a88d8 100644
--- a/content/browser/renderer_host/cross_process_frame_connector.cc
+++ b/content/browser/renderer_host/cross_process_frame_connector.cc
@@ -29,21 +29,6 @@
 
 namespace content {
 
-namespace {
-
-// Return the root RenderFrameHost in the outermost WebContents.
-RenderFrameHostImpl* RootRenderFrameHost(RenderFrameHostImpl* frame) {
-  RenderFrameHostImpl* current = frame;
-  while (true) {
-    RenderFrameHostImpl* parent = current->ParentOrOuterDelegateFrame();
-    if (!parent)
-      return current;
-    current = parent;
-  };
-}
-
-}  // namespace
-
 CrossProcessFrameConnector::CrossProcessFrameConnector(
     RenderFrameProxyHost* frame_proxy_in_parent_renderer)
     : FrameConnectorDelegate(IsUseZoomForDSFEnabled()),
@@ -55,7 +40,8 @@
   // GetScreenInfo() on the root RenderWidgetHost, which will be guaranteed to
   // be on the correct display. All subsequent updates to |screen_info_|
   // ultimately come from the root, so it makes sense to do it here as well.
-  RootRenderFrameHost(current_child_frame_host())
+  current_child_frame_host()
+      ->GetOutermostMainFrame()
       ->GetRenderWidgetHost()
       ->GetScreenInfo(&screen_info_);
 }
@@ -381,7 +367,8 @@
   if (!frame_proxy_in_parent_renderer_)
     return nullptr;
 
-  RenderFrameHostImpl* root = RootRenderFrameHost(current_child_frame_host());
+  RenderFrameHostImpl* root =
+      current_child_frame_host()->GetOutermostMainFrame();
   return static_cast<RenderWidgetHostViewBase*>(root->GetView());
 }
 
diff --git a/content/browser/renderer_host/frame_tree.cc b/content/browser/renderer_host/frame_tree.cc
index f7f3d97..45dc1aa 100644
--- a/content/browser/renderer_host/frame_tree.cc
+++ b/content/browser/renderer_host/frame_tree.cc
@@ -383,7 +383,7 @@
   // The accessibility tree data for the root of the frame tree keeps
   // track of the focused frame too, so update that every time the
   // focused frame changes.
-  root()->current_frame_host()->UpdateAXTreeData();
+  root()->current_frame_host()->GetOutermostMainFrame()->UpdateAXTreeData();
 }
 
 void FrameTree::SetFrameRemoveListener(
diff --git a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
index a99baeb0..2a516c6 100644
--- a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
@@ -74,9 +74,9 @@
 #include "net/test/url_request/url_request_failed_job.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/blink/public/common/page_state/page_state_serialization.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/mojom/frame/frame.mojom-test-utils.h"
 #include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 
 namespace content {
 namespace {
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 04c748c..5400eb49 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -115,10 +115,10 @@
 #include "third_party/blink/public/common/blob/blob_utils.h"
 #include "third_party/blink/public/common/client_hints/client_hints.h"
 #include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
 #include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
 #include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h"
 #include "third_party/blink/public/platform/resource_request_blocked_reason.h"
@@ -281,11 +281,10 @@
     return;
 
   bool is_reload = NavigationTypeUtils::IsReload(navigation_type);
-  blink::mojom::RendererPreferences render_prefs =
-      frame_tree_node->render_manager()
-          ->current_host()
-          ->GetDelegate()
-          ->GetRendererPrefs();
+  blink::RendererPreferences render_prefs = frame_tree_node->render_manager()
+                                                ->current_host()
+                                                ->GetDelegate()
+                                                ->GetRendererPrefs();
   UpdateAdditionalHeadersForBrowserInitiatedRequest(headers, browser_context,
                                                     is_reload, render_prefs);
 
diff --git a/content/browser/renderer_host/render_frame_host_delegate.h b/content/browser/renderer_host/render_frame_host_delegate.h
index b70b462a5..537c779 100644
--- a/content/browser/renderer_host/render_frame_host_delegate.h
+++ b/content/browser/renderer_host/render_frame_host_delegate.h
@@ -572,9 +572,11 @@
   // widget should be created associated with the given
   // |agent_scheduling_group|, but it should not be shown yet. That should
   // happen in response to ShowCreatedWidget.
-  virtual void CreateNewWidget(
+  virtual void CreateNewPopupWidget(
       AgentSchedulingGroupHost& agent_scheduling_group,
       int32_t route_id,
+      mojo::PendingAssociatedReceiver<blink::mojom::PopupWidgetHost>
+          blink_popup_widget_host,
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
           blink_widget_host,
       mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) {}
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 36316e0..573257b 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -1906,8 +1906,15 @@
 
   accessibility_reset_count_++;
   if (accessibility_reset_count_ > max_accessibility_resets_) {
+    // This will both create an "Aw Snap..." and generate a second crash report
+    // in addition to the DumpWithoutCrashing() for the first reset.
     render_accessibility_->FatalError();
   } else {
+    // Crash keys set in BrowserAccessibilityManager::Unserialize().
+    if (accessibility_reset_count_ == 1) {
+      // Only send crash report first time -- don't skew crash stats too much.
+      base::debug::DumpWithoutCrashing();
+    }
     AccessibilityReset();
   }
 }
@@ -5271,15 +5278,18 @@
       proxy_host->GetFrameToken(), portal->GetDevToolsFrameToken());
 }
 
-void RenderFrameHostImpl::CreateNewWidget(
+void RenderFrameHostImpl::CreateNewPopupWidget(
+    mojo::PendingAssociatedReceiver<blink::mojom::PopupWidgetHost>
+        blink_popup_widget_host,
     mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host,
     mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget,
-    CreateNewWidgetCallback callback) {
+    CreateNewPopupWidgetCallback callback) {
   int32_t widget_route_id = GetProcess()->GetNextRoutingID();
   std::move(callback).Run(widget_route_id);
-  delegate_->CreateNewWidget(agent_scheduling_group_, widget_route_id,
-                             std::move(blink_widget_host),
-                             std::move(blink_widget));
+  delegate_->CreateNewPopupWidget(agent_scheduling_group_, widget_route_id,
+                                  std::move(blink_popup_widget_host),
+                                  std::move(blink_widget_host),
+                                  std::move(blink_widget));
 }
 
 void RenderFrameHostImpl::IssueKeepAliveHandle(
@@ -9494,6 +9504,16 @@
   return nullptr;
 }
 
+RenderFrameHostImpl* RenderFrameHostImpl::GetOutermostMainFrame() {
+  RenderFrameHostImpl* current = this;
+  while (true) {
+    RenderFrameHostImpl* parent = current->ParentOrOuterDelegateFrame();
+    if (!parent)
+      return current;
+    current = parent;
+  };
+}
+
 scoped_refptr<WebAuthRequestSecurityChecker>
 RenderFrameHostImpl::GetWebAuthRequestSecurityChecker() {
   if (!webauth_request_security_checker_)
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
index 2e8077b..dcdc9bc 100644
--- a/content/browser/renderer_host/render_frame_host_impl.h
+++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -1563,6 +1563,9 @@
   // WebContents.
   RenderFrameHostImpl* ParentOrOuterDelegateFrame();
 
+  // Returns the global root RenderFrameHostImpl in the outermost WebContents.
+  RenderFrameHostImpl* GetOutermostMainFrame();
+
   void SetIsOuterDelegateFrame(bool is_outer_frame) {
     is_outer_delegate_frame_ = is_outer_frame;
   }
@@ -2015,11 +2018,13 @@
       CreatePortalCallback callback) override;
   void AdoptPortal(const blink::PortalToken& portal_token,
                    AdoptPortalCallback callback) override;
-  void CreateNewWidget(
+  void CreateNewPopupWidget(
+      mojo::PendingAssociatedReceiver<blink::mojom::PopupWidgetHost>
+          blink_popup_widget_host,
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
           blink_widget_host,
       mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget,
-      CreateNewWidgetCallback callback) override;
+      CreateNewPopupWidgetCallback callback) override;
   void IssueKeepAliveHandle(
       mojo::PendingReceiver<mojom::KeepAliveHandle> receiver) override;
   void DidCommitProvisionalLoad(
diff --git a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
index 35232960..0859b25 100644
--- a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
+++ b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
@@ -3842,14 +3842,13 @@
   // has time to see the otp usage, and records it, before we test for it below.
   EXPECT_EQ("hello", EvalJs(shell(), script));
 
-  RenderFrameHostImpl* main_rfh = web_contents()->GetMainFrame();
-  EXPECT_TRUE(main_rfh->DocumentUsedWebOTP());
+  EXPECT_TRUE(web_contents()->GetMainFrame()->DocumentUsedWebOTP());
 
   // Loads a URL that maps to the same SiteInstance as the first URL, to make
   // sure the navigation will not be cross-process.
   const GURL second_url(embedded_test_server()->GetURL("/title2.html"));
   ASSERT_TRUE(NavigateToURL(shell(), second_url));
-  EXPECT_FALSE(main_rfh->DocumentUsedWebOTP());
+  EXPECT_FALSE(web_contents()->GetMainFrame()->DocumentUsedWebOTP());
 }
 
 // It is hard to test this feature fully at the integration test level. Indeed,
diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h
index 9b18440..0733e77 100644
--- a/content/browser/renderer_host/render_view_host_delegate.h
+++ b/content/browser/renderer_host/render_view_host_delegate.h
@@ -23,12 +23,10 @@
 }
 
 namespace blink {
-namespace mojom {
-class RendererPreferences;
-}
 namespace web_pref {
 struct WebPreferences;
 }
+struct RendererPreferences;
 }  // namespace blink
 
 namespace gfx {
@@ -99,7 +97,7 @@
 
   // Return a dummy RendererPreferences object that will be used by the renderer
   // associated with the owning RenderViewHost.
-  virtual blink::mojom::RendererPreferences GetRendererPrefs() const = 0;
+  virtual const blink::RendererPreferences& GetRendererPrefs() const = 0;
 
   // Notification from the renderer host that blocked UI event occurred.
   // This happens when there are tab-modal dialogs. In this case, the
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index 393502b..a210fd0 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -149,20 +149,6 @@
 }
 #endif  // OS_WIN
 
-#if defined(USE_OZONE) || defined(USE_X11)
-bool IsSelectionBufferAvailable() {
-#if defined(USE_OZONE)
-  if (features::IsUsingOzonePlatform())
-    return ui::Clipboard::GetForCurrentThread()->IsSelectionBufferAvailable();
-#endif
-#if defined(USE_X11)
-  return true;
-#else
-  return false;
-#endif
-}
-#endif  // defined(USE_OZONE) || defined(USE_X11)
-
 // Set of RenderViewHostImpl* that can be attached as UserData to a
 // RenderProcessHost. Used to keep track of whether any RenderViewHostImpl
 // instances are in the bfcache.
@@ -253,7 +239,7 @@
 
 // static
 void RenderViewHostImpl::GetPlatformSpecificPrefs(
-    blink::mojom::RendererPreferences* prefs) {
+    blink::RendererPreferences* prefs) {
 #if defined(OS_WIN)
   // Note that what is called "height" in this struct is actually the font size;
   // font "height" typically includes ascender, descender, and padding and is
@@ -287,7 +273,9 @@
   prefs->focus_ring_color = SK_AlphaTRANSPARENT;
 #endif
 #if defined(USE_OZONE) || defined(USE_X11)
-  prefs->selection_clipboard_buffer_available = IsSelectionBufferAvailable();
+  prefs->selection_clipboard_buffer_available =
+      ui::Clipboard::IsSupportedClipboardBuffer(
+          ui::ClipboardBuffer::kSelection);
 #endif
 }
 
@@ -442,9 +430,8 @@
   GetWidget()->set_renderer_initialized(true);
 
   mojom::CreateViewParamsPtr params = mojom::CreateViewParams::New();
-  params->renderer_preferences = delegate_->GetRendererPrefs().Clone();
-  RenderViewHostImpl::GetPlatformSpecificPrefs(
-      params->renderer_preferences.get());
+  params->renderer_preferences = delegate_->GetRendererPrefs();
+  RenderViewHostImpl::GetPlatformSpecificPrefs(&params->renderer_preferences);
   params->web_preferences = delegate_->GetOrCreateWebPreferences();
   params->view_id = GetRoutingID();
   if (main_rfh) {
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h
index 4eaa941f..7efb15b 100644
--- a/content/browser/renderer_host/render_view_host_impl.h
+++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -34,6 +34,7 @@
 #include "content/public/browser/render_view_host.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "net/base/load_states.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/mojom/page/page.mojom.h"
 #include "third_party/blink/public/web/web_ax_enums.h"
 #include "third_party/blink/public/web/web_console_message.h"
@@ -94,8 +95,7 @@
   // Convenience function, just like RenderViewHost::From.
   static RenderViewHostImpl* From(RenderWidgetHost* rwh);
 
-  static void GetPlatformSpecificPrefs(
-      blink::mojom::RendererPreferences* prefs);
+  static void GetPlatformSpecificPrefs(blink::RendererPreferences* prefs);
 
   // Checks whether any RenderViewHostImpl instance associated with a given
   // process is not currently in the back-forward cache.
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 2edfd99..364a5a7 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -587,6 +587,13 @@
   blink_widget_.Bind(std::move(widget));
 }
 
+void RenderWidgetHostImpl::BindPopupWidgetInterface(
+    mojo::PendingAssociatedReceiver<blink::mojom::PopupWidgetHost>
+        popup_widget_host) {
+  blink_popup_widget_host_receiver_.reset();
+  blink_popup_widget_host_receiver_.Bind(std::move(popup_widget_host));
+}
+
 std::pair<mojo::PendingAssociatedRemote<blink::mojom::FrameWidgetHost>,
           mojo::PendingAssociatedReceiver<blink::mojom::FrameWidget>>
 RenderWidgetHostImpl::BindNewFrameWidgetInterfaces() {
@@ -650,15 +657,6 @@
   CancelKeyboardLock();
   RejectMouseLockOrUnlockIfNecessary(
       blink::mojom::PointerLockResult::kElementDestroyed);
-
-  if (GetProcess()->IsInitializedAndNotDead() && !owner_delegate()) {
-    // Tell the RendererWidget to close. We only want to do this if the
-    // RenderWidget is the root of the renderer object graph, which is for
-    // pepper fullscreen and popups.
-    bool rv = Send(new WidgetMsg_Close(routing_id_));
-    DCHECK(rv);
-  }
-
   Destroy(also_delete);
 }
 
@@ -2171,6 +2169,10 @@
     view_.reset();
   }
 
+  // Reset the popup host receiver, this will cause a disconnection notification
+  // on the renderer to delete Popup widgets.
+  blink_popup_widget_host_receiver_.reset();
+
   render_process_blocked_state_changed_subscription_.reset();
   pending_show_closure_.Reset();
   GetProcess()->RemovePriorityClient(this);
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index 481cf121..bef9b1c 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -146,6 +146,7 @@
       public IPC::Listener,
       public RenderFrameMetadataProvider::Observer,
       public blink::mojom::FrameWidgetHost,
+      public blink::mojom::PopupWidgetHost,
       public blink::mojom::WidgetHost,
       public blink::mojom::PointerLockContext {
  public:
@@ -323,6 +324,11 @@
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> widget_host,
       mojo::PendingAssociatedRemote<blink::mojom::Widget> widget);
 
+  // Bind the provided popup widget interface.
+  void BindPopupWidgetInterface(
+      mojo::PendingAssociatedReceiver<blink::mojom::PopupWidgetHost>
+          popup_widget_host);
+
   // Allocate and bind new frame widget interfaces.
   std::pair<mojo::PendingAssociatedRemote<blink::mojom::FrameWidgetHost>,
             mojo::PendingAssociatedReceiver<blink::mojom::FrameWidget>>
@@ -1322,6 +1328,11 @@
       blink_frame_widget_host_receiver_{this};
   mojo::AssociatedRemote<blink::mojom::FrameWidget> blink_frame_widget_;
 
+  // If this is initialized with a popup this member will be valid and
+  // manages the lifecycle of the popup in blink.
+  mojo::AssociatedReceiver<blink::mojom::PopupWidgetHost>
+      blink_popup_widget_host_receiver_{this};
+
   mojo::AssociatedReceiver<blink::mojom::WidgetHost>
       blink_widget_host_receiver_{this};
   mojo::AssociatedRemote<blink::mojom::Widget> blink_widget_;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index df81ab5..bad1b9eb2 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -133,10 +133,6 @@
 #include "ui/display/win/test/scoped_screen_win.h"
 #endif
 
-#if defined(USE_X11)
-#include "ui/base/ui_base_features.h"
-#endif
-
 using testing::_;
 
 using blink::WebGestureEvent;
@@ -6296,12 +6292,15 @@
   }
 }
 
-#if defined(USE_X11)
 // This test will verify that after selection, the selected text is written to
 // the clipboard from the focused widget.
 TEST_F(InputMethodStateAuraTest, SelectedTextCopiedToClipboard) {
-  if (features::IsUsingOzonePlatform())
+  // Skip test for platforms that do not support selection clipboard.
+  if (!ui::Clipboard::IsSupportedClipboardBuffer(
+          ui::ClipboardBuffer::kSelection)) {
     return;
+  }
+
   ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
   EXPECT_TRUE(!!clipboard);
   std::vector<std::string> texts = {"text0", "text1", "text2", "text3"};
@@ -6324,7 +6323,6 @@
     EXPECT_EQ(expected_text, result_text);
   }
 }
-#endif
 
 // This test verifies that when any view on the page cancels an ongoing
 // composition, the RenderWidgetHostViewAura will receive the notification and
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index 262677bf..b4e0fe7 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -381,7 +381,8 @@
   // different timing in the test, let's simulate a CreateNewWidget call coming
   // from the IO thread.  Use the existing window routing id to cause a
   // deliberate collision.
-  pending_rfh->CreateNewWidget(
+  pending_rfh->CreateNewPopupWidget(
+      mojo::PendingAssociatedReceiver<blink::mojom::PopupWidgetHost>(),
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>(),
       mojo::PendingAssociatedRemote<blink::mojom::Widget>(), base::DoNothing());
 
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc
index 18bc53c..eec9cef 100644
--- a/content/browser/service_worker/embedded_worker_instance.cc
+++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -365,12 +365,12 @@
       std::move(coep_reporter_for_subresources),
       ContentBrowserClient::URLLoaderFactoryType::kServiceWorkerSubResource);
 
-  // TODO(crbug.com/862854): Support changes to
-  // blink::mojom::RendererPreferences while the worker is running.
+  // TODO(crbug.com/862854): Support changes to blink::RendererPreferences while
+  // the worker is running.
   DCHECK(process_manager->browser_context() || process_manager->IsShutdown());
-  params->renderer_preferences = blink::mojom::RendererPreferences::New();
+  params->renderer_preferences = blink::RendererPreferences();
   GetContentClient()->browser()->UpdateRendererPreferencesForWorker(
-      process_manager->browser_context(), params->renderer_preferences.get());
+      process_manager->browser_context(), &params->renderer_preferences);
 
   // Create a RendererPreferenceWatcher to observe updates in the preferences.
   mojo::PendingRemote<blink::mojom::RendererPreferenceWatcher> watcher_remote;
diff --git a/content/browser/service_worker/service_worker_registry.cc b/content/browser/service_worker/service_worker_registry.cc
index 6b9f082f..62dc4f9 100644
--- a/content/browser/service_worker/service_worker_registry.cc
+++ b/content/browser/service_worker/service_worker_registry.cc
@@ -145,7 +145,10 @@
     ServiceWorkerRegistry* old_registry)
     : context_(context),
       storage_control_(std::make_unique<ServiceWorkerStorageControlImpl>(
-          ServiceWorkerStorage::Create(old_registry->storage()))),
+          ServiceWorkerStorage::Create(
+              old_registry->user_data_directory_,
+              old_registry->database_task_runner_,
+              old_registry->quota_manager_proxy_.get()))),
       special_storage_policy_(old_registry->special_storage_policy_) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
   DCHECK(context_);
@@ -154,10 +157,6 @@
 
 ServiceWorkerRegistry::~ServiceWorkerRegistry() = default;
 
-ServiceWorkerStorage* ServiceWorkerRegistry::storage() const {
-  return storage_control_->storage();
-}
-
 void ServiceWorkerRegistry::CreateNewRegistration(
     blink::mojom::ServiceWorkerRegistrationOptions options,
     NewRegistrationCallback callback) {
@@ -539,22 +538,6 @@
                                         const std::vector<std::string>& keys,
                                         GetUserDataCallback callback) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
-  if (registration_id == blink::mojom::kInvalidServiceWorkerRegistrationId ||
-      keys.empty()) {
-    RunSoon(FROM_HERE,
-            base::BindOnce(std::move(callback), std::vector<std::string>(),
-                           blink::ServiceWorkerStatusCode::kErrorFailed));
-    return;
-  }
-  for (const std::string& key : keys) {
-    if (key.empty()) {
-      RunSoon(FROM_HERE,
-              base::BindOnce(std::move(callback), std::vector<std::string>(),
-                             blink::ServiceWorkerStatusCode::kErrorFailed));
-      return;
-    }
-  }
-
   GetRemoteStorageControl()->GetUserData(
       registration_id, keys,
       base::BindOnce(&ServiceWorkerRegistry::DidGetUserData,
@@ -566,14 +549,6 @@
     const std::string& key_prefix,
     GetUserDataCallback callback) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
-  if (registration_id == blink::mojom::kInvalidServiceWorkerRegistrationId ||
-      key_prefix.empty()) {
-    RunSoon(FROM_HERE,
-            base::BindOnce(std::move(callback), std::vector<std::string>(),
-                           blink::ServiceWorkerStatusCode::kErrorFailed));
-    return;
-  }
-
   GetRemoteStorageControl()->GetUserDataByKeyPrefix(
       registration_id, key_prefix,
       base::BindOnce(&ServiceWorkerRegistry::DidGetUserData,
@@ -585,15 +560,6 @@
     const std::string& key_prefix,
     GetUserKeysAndDataCallback callback) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
-  if (registration_id == blink::mojom::kInvalidServiceWorkerRegistrationId ||
-      key_prefix.empty()) {
-    RunSoon(FROM_HERE,
-            base::BindOnce(std::move(callback),
-                           blink::ServiceWorkerStatusCode::kErrorFailed,
-                           base::flat_map<std::string, std::string>()));
-    return;
-  }
-
   GetRemoteStorageControl()->GetUserKeysAndDataByKeyPrefix(
       registration_id, key_prefix,
       base::BindOnce(&ServiceWorkerRegistry::DidGetUserKeysAndData,
@@ -618,12 +584,6 @@
   // storage::mojom::ServiceWorkerUserDataPtr instead of converting
   //|key_value_pairs|.
   for (const auto& kv : key_value_pairs) {
-    if (kv.first.empty()) {
-      RunSoon(FROM_HERE,
-              base::BindOnce(std::move(callback),
-                             blink::ServiceWorkerStatusCode::kErrorFailed));
-      return;
-    }
     user_data.push_back(storage::mojom::ServiceWorkerUserData::New(
         registration_id, kv.first, kv.second));
   }
@@ -638,22 +598,6 @@
                                           const std::vector<std::string>& keys,
                                           StatusCallback callback) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
-  if (registration_id == blink::mojom::kInvalidServiceWorkerRegistrationId ||
-      keys.empty()) {
-    RunSoon(FROM_HERE,
-            base::BindOnce(std::move(callback),
-                           blink::ServiceWorkerStatusCode::kErrorFailed));
-    return;
-  }
-  for (const std::string& key : keys) {
-    if (key.empty()) {
-      RunSoon(FROM_HERE,
-              base::BindOnce(std::move(callback),
-                             blink::ServiceWorkerStatusCode::kErrorFailed));
-      return;
-    }
-  }
-
   GetRemoteStorageControl()->ClearUserData(
       registration_id, keys,
       base::BindOnce(&ServiceWorkerRegistry::DidClearUserData,
@@ -665,22 +609,6 @@
     const std::vector<std::string>& key_prefixes,
     StatusCallback callback) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
-  if (registration_id == blink::mojom::kInvalidServiceWorkerRegistrationId ||
-      key_prefixes.empty()) {
-    RunSoon(FROM_HERE,
-            base::BindOnce(std::move(callback),
-                           blink::ServiceWorkerStatusCode::kErrorFailed));
-    return;
-  }
-  for (const std::string& key_prefix : key_prefixes) {
-    if (key_prefix.empty()) {
-      RunSoon(FROM_HERE,
-              base::BindOnce(std::move(callback),
-                             blink::ServiceWorkerStatusCode::kErrorFailed));
-      return;
-    }
-  }
-
   GetRemoteStorageControl()->ClearUserDataByKeyPrefixes(
       registration_id, key_prefixes,
       base::BindOnce(&ServiceWorkerRegistry::DidClearUserData,
@@ -691,13 +619,6 @@
     const std::string& key_prefix,
     StatusCallback callback) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
-  if (key_prefix.empty()) {
-    RunSoon(FROM_HERE,
-            base::BindOnce(std::move(callback),
-                           blink::ServiceWorkerStatusCode::kErrorFailed));
-    return;
-  }
-
   GetRemoteStorageControl()->ClearUserDataForAllRegistrationsByKeyPrefix(
       key_prefix,
       base::BindOnce(&ServiceWorkerRegistry::DidClearUserData,
@@ -708,14 +629,6 @@
     const std::string& key,
     GetUserDataForAllRegistrationsCallback callback) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
-  if (key.empty()) {
-    RunSoon(FROM_HERE,
-            base::BindOnce(std::move(callback),
-                           std::vector<std::pair<int64_t, std::string>>(),
-                           blink::ServiceWorkerStatusCode::kErrorFailed));
-    return;
-  }
-
   GetRemoteStorageControl()->GetUserDataForAllRegistrations(
       key,
       base::BindOnce(&ServiceWorkerRegistry::DidGetUserDataForAllRegistrations,
@@ -726,14 +639,6 @@
     const std::string& key_prefix,
     GetUserDataForAllRegistrationsCallback callback) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
-  if (key_prefix.empty()) {
-    RunSoon(FROM_HERE,
-            base::BindOnce(std::move(callback),
-                           std::vector<std::pair<int64_t, std::string>>(),
-                           blink::ServiceWorkerStatusCode::kErrorFailed));
-    return;
-  }
-
   GetRemoteStorageControl()->GetUserDataForAllRegistrationsByKeyPrefix(
       key_prefix,
       base::BindOnce(&ServiceWorkerRegistry::DidGetUserDataForAllRegistrations,
diff --git a/content/browser/service_worker/service_worker_registry.h b/content/browser/service_worker/service_worker_registry.h
index 81eefa01..230acc1 100644
--- a/content/browser/service_worker/service_worker_registry.h
+++ b/content/browser/service_worker/service_worker_registry.h
@@ -83,8 +83,6 @@
 
   ~ServiceWorkerRegistry();
 
-  ServiceWorkerStorage* storage() const;
-
   // Creates a new in-memory representation of registration. Can be null when
   // storage is disabled. This method must be called after storage is
   // initialized.
diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc
index 02c7add..872e4f0 100644
--- a/content/browser/service_worker/service_worker_storage.cc
+++ b/content/browser/service_worker/service_worker_storage.cc
@@ -105,14 +105,6 @@
       quota_manager_proxy));
 }
 
-// static
-std::unique_ptr<ServiceWorkerStorage> ServiceWorkerStorage::Create(
-    ServiceWorkerStorage* old_storage) {
-  return base::WrapUnique(new ServiceWorkerStorage(
-      old_storage->user_data_directory_, old_storage->database_task_runner_,
-      old_storage->quota_manager_proxy_.get()));
-}
-
 void ServiceWorkerStorage::GetRegisteredOrigins(
     GetRegisteredOriginsCallback callback) {
   switch (state_) {
@@ -821,10 +813,14 @@
       break;
   }
 
-  // TODO(bashi): Consider replacing these DCHECKs with returning errors once
-  // this class is moved to the Storage Service.
-  DCHECK_NE(registration_id, blink::mojom::kInvalidServiceWorkerRegistrationId);
-  DCHECK(!key_prefix.empty());
+  if (registration_id == blink::mojom::kInvalidServiceWorkerRegistrationId ||
+      key_prefix.empty()) {
+    RunSoon(FROM_HERE,
+            base::BindOnce(std::move(callback),
+                           ServiceWorkerDatabase::Status::kErrorFailed,
+                           base::flat_map<std::string, std::string>()));
+    return;
+  }
 
   database_task_runner_->PostTask(
       FROM_HERE,
diff --git a/content/browser/service_worker/service_worker_storage.h b/content/browser/service_worker/service_worker_storage.h
index 00a5f08..1f9d4a5 100644
--- a/content/browser/service_worker/service_worker_storage.h
+++ b/content/browser/service_worker/service_worker_storage.h
@@ -110,10 +110,6 @@
       scoped_refptr<base::SequencedTaskRunner> database_task_runner,
       storage::QuotaManagerProxy* quota_manager_proxy);
 
-  // Used for DeleteAndStartOver. Creates new storage based on |old_storage|.
-  static std::unique_ptr<ServiceWorkerStorage> Create(
-      ServiceWorkerStorage* old_storage);
-
   // Returns all origins which have service worker registrations.
   void GetRegisteredOrigins(GetRegisteredOriginsCallback callback);
 
diff --git a/content/browser/service_worker/service_worker_storage_control_impl.h b/content/browser/service_worker/service_worker_storage_control_impl.h
index aaf8339..cf15482 100644
--- a/content/browser/service_worker/service_worker_storage_control_impl.h
+++ b/content/browser/service_worker/service_worker_storage_control_impl.h
@@ -36,10 +36,6 @@
 
   ~ServiceWorkerStorageControlImpl() override;
 
-  // TODO(crbug.com/1055677): Remove this accessor after all
-  // ServiceWorkerStorage method calls are replaced with mojo methods.
-  ServiceWorkerStorage* storage() const { return storage_.get(); }
-
   void Bind(mojo::PendingReceiver<storage::mojom::ServiceWorkerStorageControl>
                 receiver);
 
diff --git a/content/browser/service_worker/service_worker_storage_control_impl_unittest.cc b/content/browser/service_worker/service_worker_storage_control_impl_unittest.cc
index b872f1c..46301fa1 100644
--- a/content/browser/service_worker/service_worker_storage_control_impl_unittest.cc
+++ b/content/browser/service_worker/service_worker_storage_control_impl_unittest.cc
@@ -669,18 +669,16 @@
 
   // Helper function that reads uncommitted resource ids from database.
   std::vector<int64_t> GetUncommittedResourceIds() {
-    std::vector<int64_t> ids;
+    std::vector<int64_t> result;
     base::RunLoop loop;
-    ServiceWorkerStorage* internal_storage = storage_impl_->storage();
-    ServiceWorkerDatabase* database_raw = internal_storage->database_.get();
-    internal_storage->database_task_runner_->PostTask(
-        FROM_HERE, base::BindLambdaForTesting([&]() {
-          EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
-                    database_raw->GetUncommittedResourceIds(&ids));
+    storage()->GetUncommittedResourceIdsForTest(base::BindLambdaForTesting(
+        [&](DatabaseStatus status, const std::vector<int64_t>& ids) {
+          EXPECT_EQ(status, ServiceWorkerDatabase::Status::kOk);
+          result = ids;
           loop.Quit();
         }));
     loop.Run();
-    return ids;
+    return result;
   }
 
  private:
diff --git a/content/browser/service_worker/service_worker_update_checker.cc b/content/browser/service_worker/service_worker_update_checker.cc
index 7394d00..74c77dc 100644
--- a/content/browser/service_worker/service_worker_update_checker.cc
+++ b/content/browser/service_worker/service_worker_update_checker.cc
@@ -25,6 +25,7 @@
 #include "net/http/http_request_headers.h"
 #include "services/network/public/cpp/constants.h"
 #include "services/network/public/cpp/features.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 
 namespace content {
 
@@ -55,7 +56,7 @@
                     network::kDefaultAcceptHeaderValue);
 
   BrowserContext* browser_context = process_manager->browser_context();
-  blink::mojom::RendererPreferences renderer_preferences;
+  blink::RendererPreferences renderer_preferences;
   GetContentClient()->browser()->UpdateRendererPreferencesForWorker(
       browser_context, &renderer_preferences);
   UpdateAdditionalHeadersForBrowserInitiatedRequest(
diff --git a/content/browser/sms/webotp_service.cc b/content/browser/sms/webotp_service.cc
index b7011fa..41173dc 100644
--- a/content/browser/sms/webotp_service.cc
+++ b/content/browser/sms/webotp_service.cc
@@ -69,8 +69,10 @@
 }
 
 WebOTPService::~WebOTPService() {
-  if (callback_)
-    CompleteRequest(SmsStatus::kUnhandledRequest);
+  // Resolve any pending callback and invoke clean up to unsubscribe this
+  // service from fetcher.
+  CompleteRequest(SmsStatus::kUnhandledRequest);
+
   DCHECK(!callback_);
 }
 
diff --git a/content/browser/sms/webotp_service_unittest.cc b/content/browser/sms/webotp_service_unittest.cc
index fed70b3..a4d4681 100644
--- a/content/browser/sms/webotp_service_unittest.cc
+++ b/content/browser/sms/webotp_service_unittest.cc
@@ -371,6 +371,10 @@
   loop.Run();
 
   ASSERT_FALSE(fetcher.HasSubscribers());
+
+  // Explicitly delete contents to ensure the invariant that the fetcher
+  // lifetime is longer than service.
+  DeleteContents();
 }
 
 TEST_F(WebOTPServiceTest, Abort) {
diff --git a/content/browser/tracing/perfetto_file_tracer.cc b/content/browser/tracing/perfetto_file_tracer.cc
index db67a7e..6be3ba8 100644
--- a/content/browser/tracing/perfetto_file_tracer.cc
+++ b/content/browser/tracing/perfetto_file_tracer.cc
@@ -166,8 +166,8 @@
           },
           base::Unretained(this), has_been_disabled_));
 
-  background_drainer_.Post(FROM_HERE, &BackgroundDrainer::StartDrain,
-                           std::move(data_pipe.consumer_handle));
+  background_drainer_.AsyncCall(&BackgroundDrainer::StartDrain)
+      .WithArgs(std::move(data_pipe.consumer_handle));
 }
 
 void PerfettoFileTracer::OnTracingSessionEnded() {
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 23d44183..6c85eca 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2623,7 +2623,7 @@
 void WebContentsImpl::SyncRendererPrefs() {
   OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::SyncRendererPrefs");
 
-  blink::mojom::RendererPreferences renderer_preferences = GetRendererPrefs();
+  blink::RendererPreferences renderer_preferences = GetRendererPrefs();
   RenderViewHostImpl::GetPlatformSpecificPrefs(&renderer_preferences);
   SendPageMessage(
       new PageMsg_SetRendererPrefs(MSG_ROUTING_NONE, renderer_preferences));
@@ -3680,9 +3680,11 @@
   return new_contents_impl;
 }
 
-void WebContentsImpl::CreateNewWidget(
+void WebContentsImpl::CreateNewPopupWidget(
     AgentSchedulingGroupHost& agent_scheduling_group,
     int32_t route_id,
+    mojo::PendingAssociatedReceiver<blink::mojom::PopupWidgetHost>
+        blink_popup_widget_host,
     mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host,
     mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) {
   OPTIONAL_TRACE_EVENT1(
@@ -3703,6 +3705,7 @@
 
   widget_host->BindWidgetInterfaces(std::move(blink_widget_host),
                                     std::move(blink_widget));
+  widget_host->BindPopupWidgetInterface(std::move(blink_popup_widget_host));
   RenderWidgetHostViewBase* widget_view =
       static_cast<RenderWidgetHostViewBase*>(
           view_->CreateViewForChildWidget(widget_host));
@@ -4651,7 +4654,7 @@
   return GetRenderViewHost()->contents_mime_type();
 }
 
-blink::mojom::RendererPreferences* WebContentsImpl::GetMutableRendererPrefs() {
+blink::RendererPreferences* WebContentsImpl::GetMutableRendererPrefs() {
   return &renderer_preferences_;
 }
 
@@ -6749,7 +6752,7 @@
   return render_view_host_delegate_view_;
 }
 
-blink::mojom::RendererPreferences WebContentsImpl::GetRendererPrefs() const {
+const blink::RendererPreferences& WebContentsImpl::GetRendererPrefs() const {
   return renderer_preferences_;
 }
 
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 1d602b6..7292fde 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -67,6 +67,7 @@
 #include "services/network/public/mojom/fetch_api.mojom-forward.h"
 #include "third_party/blink/public/common/frame/transient_allow_fullscreen.h"
 #include "third_party/blink/public/common/page/drag_operation.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
 #include "third_party/blink/public/mojom/choosers/color_chooser.mojom.h"
 #include "third_party/blink/public/mojom/choosers/popup_menu.mojom.h"
@@ -75,7 +76,6 @@
 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
 #include "third_party/blink/public/mojom/page/display_cutout.mojom.h"
 #include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "ui/accessibility/ax_mode.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/gfx/geometry/rect_f.h"
@@ -473,7 +473,7 @@
       base::OnceCallback<void(uint64_t, data_decoder::mojom::WebBundlerError)>
           callback) override;
   const std::string& GetContentsMimeType() override;
-  blink::mojom::RendererPreferences* GetMutableRendererPrefs() override;
+  blink::RendererPreferences* GetMutableRendererPrefs() override;
   void Close() override;
   void SetClosedByUserGesture(bool value) override;
   bool GetClosedByUserGesture() override;
@@ -731,12 +731,15 @@
       blink::mojom::TextAutosizerPageInfoPtr page_info) override;
   bool HasSeenRecentScreenOrientationChange() override;
   bool IsTransientAllowFullscreenActive() const override;
-  void CreateNewWidget(AgentSchedulingGroupHost& agent_scheduling_group,
-                       int32_t route_id,
-                       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
-                           blink_widget_host,
-                       mojo::PendingAssociatedRemote<blink::mojom::Widget>
-                           blink_widget) override;
+  void CreateNewPopupWidget(
+      AgentSchedulingGroupHost& agent_scheduling_group,
+      int32_t route_id,
+      mojo::PendingAssociatedReceiver<blink::mojom::PopupWidgetHost>
+          blink_popup_widget_host,
+      mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
+          blink_widget_host,
+      mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget)
+      override;
   bool ShowPopupMenu(
       RenderFrameHostImpl* render_frame_host,
       mojo::PendingRemote<blink::mojom::PopupMenuClient>* popup_client,
@@ -788,7 +791,7 @@
                               const base::string16& message,
                               int32_t line_no,
                               const base::string16& source_id) override;
-  blink::mojom::RendererPreferences GetRendererPrefs() const override;
+  const blink::RendererPreferences& GetRendererPrefs() const override;
   void DidReceiveInputEvent(RenderWidgetHostImpl* render_widget_host,
                             const blink::WebInputEvent& event) override;
   bool ShouldIgnoreInputEvents() override;
@@ -1850,7 +1853,7 @@
   bool is_showing_before_unload_dialog_;
 
   // Settings that get passed to the renderer process.
-  blink::mojom::RendererPreferences renderer_preferences_;
+  blink::RendererPreferences renderer_preferences_;
 
   // The time that this WebContents was last made active. The initial value is
   // the WebContents creation time.
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index 311dc3f..78a2d7c 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -2972,7 +2972,7 @@
     run_loop_.reset();
   }
 
-  const blink::mojom::RendererPreferences& renderer_preferences() const {
+  const blink::RendererPreferences& renderer_preferences() const {
     return renderer_preferences_;
   }
 
@@ -2983,8 +2983,7 @@
     IPC_END_MESSAGE_MAP()
   }
 
-  void OnSetRendererPrefs(
-      const blink::mojom::RendererPreferences& renderer_prefs) {
+  void OnSetRendererPrefs(const blink::RendererPreferences& renderer_prefs) {
     outgoing_message_seen_ = true;
     renderer_preferences_ = renderer_prefs;
     if (run_loop_)
@@ -2994,7 +2993,7 @@
   RenderProcessHostImpl* rph_;
   bool outgoing_message_seen_;
   std::unique_ptr<base::RunLoop> run_loop_;
-  blink::mojom::RendererPreferences renderer_preferences_;
+  blink::RendererPreferences renderer_preferences_;
 };
 }  // namespace
 
@@ -3009,7 +3008,7 @@
   EXPECT_TRUE(NavigateToURL(shell(), url));
 
   // Retrieve an arbitrary renderer preference.
-  blink::mojom::RendererPreferences* renderer_preferences =
+  blink::RendererPreferences* renderer_preferences =
       web_contents->GetMutableRendererPrefs();
   const bool use_custom_colors_old = renderer_preferences->use_custom_colors;
 
diff --git a/content/browser/webauth/virtual_authenticator.cc b/content/browser/webauth/virtual_authenticator.cc
index ad72500..fe4e477 100644
--- a/content/browser/webauth/virtual_authenticator.cc
+++ b/content/browser/webauth/virtual_authenticator.cc
@@ -51,7 +51,7 @@
 bool VirtualAuthenticator::AddRegistration(
     std::vector<uint8_t> key_handle,
     const std::string& rp_id,
-    const std::vector<uint8_t>& private_key,
+    base::span<const uint8_t> private_key,
     int32_t counter) {
   base::Optional<std::unique_ptr<device::VirtualFidoDevice::PrivateKey>>
       fido_private_key =
@@ -71,7 +71,7 @@
 bool VirtualAuthenticator::AddResidentRegistration(
     std::vector<uint8_t> key_handle,
     std::string rp_id,
-    const std::vector<uint8_t>& private_key,
+    base::span<const uint8_t> private_key,
     int32_t counter,
     std::vector<uint8_t> user_handle) {
   base::Optional<std::unique_ptr<device::VirtualFidoDevice::PrivateKey>>
@@ -221,7 +221,7 @@
 }
 
 void VirtualAuthenticator::OnLargeBlobCompressed(
-    const std::vector<uint8_t>& key_handle,
+    base::span<const uint8_t> key_handle,
     SetLargeBlobCallback callback,
     data_decoder::DataDecoder::ResultOrError<mojo_base::BigBuffer> result) {
   auto registration = state_->registrations.find(key_handle);
diff --git a/content/browser/webauth/virtual_authenticator.h b/content/browser/webauth/virtual_authenticator.h
index 167f8131..45b2f6af 100644
--- a/content/browser/webauth/virtual_authenticator.h
+++ b/content/browser/webauth/virtual_authenticator.h
@@ -9,6 +9,7 @@
 #include <string>
 #include <vector>
 
+#include "base/containers/span.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
@@ -52,14 +53,14 @@
   // false otherwise.
   bool AddRegistration(std::vector<uint8_t> key_handle,
                        const std::string& rp_id,
-                       const std::vector<uint8_t>& private_key,
+                       base::span<const uint8_t> private_key,
                        int32_t counter);
 
   // Register a new resident credential. Returns true if the registration was
   // successful, false otherwise.
   bool AddResidentRegistration(std::vector<uint8_t> key_handle,
                                std::string rp_id,
-                               const std::vector<uint8_t>& private_key,
+                               base::span<const uint8_t> private_key,
                                int32_t counter,
                                std::vector<uint8_t> user_handle);
 
@@ -70,11 +71,6 @@
   // credential was found and removed, false otherwise.
   bool RemoveRegistration(const std::vector<uint8_t>& key_handle);
 
-  // Returns the large blob associated with the credential identified by
-  // |key_handle|, if any.
-  base::Optional<std::vector<uint8_t>> GetLargeBlob(
-      base::span<const uint8_t> key_handle);
-
   // Sets whether tests of user presence succeed or not for new requests sent to
   // this authenticator. The default is true.
   void SetUserPresence(bool is_user_present);
@@ -129,7 +125,7 @@
       GetLargeBlobCallback callback,
       data_decoder::DataDecoder::ResultOrError<mojo_base::BigBuffer> result);
   void OnLargeBlobCompressed(
-      const std::vector<uint8_t>& key_handle,
+      base::span<const uint8_t> key_handle,
       SetLargeBlobCallback callback,
       data_decoder::DataDecoder::ResultOrError<mojo_base::BigBuffer> result);
 
diff --git a/content/browser/worker_host/mock_shared_worker.cc b/content/browser/worker_host/mock_shared_worker.cc
index 8c4c962..1461d24 100644
--- a/content/browser/worker_host/mock_shared_worker.cc
+++ b/content/browser/worker_host/mock_shared_worker.cc
@@ -103,7 +103,7 @@
     const blink::UserAgentMetadata& ua_metadata,
     bool pause_on_start,
     const base::UnguessableToken& devtools_worker_token,
-    blink::mojom::RendererPreferencesPtr renderer_preferences,
+    const blink::RendererPreferences& renderer_preferences,
     mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
         preference_watcher_receiver,
     mojo::PendingRemote<blink::mojom::WorkerContentSettingsProxy>
diff --git a/content/browser/worker_host/mock_shared_worker.h b/content/browser/worker_host/mock_shared_worker.h
index 4c3c38a..cebd4f2 100644
--- a/content/browser/worker_host/mock_shared_worker.h
+++ b/content/browser/worker_host/mock_shared_worker.h
@@ -21,7 +21,7 @@
 #include "services/metrics/public/cpp/ukm_source_id.h"
 #include "services/network/public/mojom/content_security_policy.mojom-forward.h"
 #include "third_party/blink/public/common/messaging/message_port_channel.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_container.mojom.h"
 #include "third_party/blink/public/mojom/worker/shared_worker_factory.mojom.h"
@@ -83,7 +83,7 @@
       const blink::UserAgentMetadata& ua_metadata,
       bool pause_on_start,
       const base::UnguessableToken& devtools_worker_token,
-      blink::mojom::RendererPreferencesPtr renderer_preferences,
+      const blink::RendererPreferences& renderer_preferences,
       mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
           preference_watcher_receiver,
       mojo::PendingRemote<blink::mojom::WorkerContentSettingsProxy>
diff --git a/content/browser/worker_host/shared_worker_host.cc b/content/browser/worker_host/shared_worker_host.cc
index 2ab9af7..23345f3b 100644
--- a/content/browser/worker_host/shared_worker_host.cc
+++ b/content/browser/worker_host/shared_worker_host.cc
@@ -36,6 +36,7 @@
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
 #include "third_party/blink/public/common/messaging/message_port_channel.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
 #include "third_party/blink/public/mojom/renderer_preference_watcher.mojom.h"
 #include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h"
@@ -175,9 +176,9 @@
       instance_.creation_address_space(),
       std::move(outside_fetch_client_settings_object)));
 
-  auto renderer_preferences = blink::mojom::RendererPreferences::New();
+  auto renderer_preferences = blink::RendererPreferences();
   GetContentClient()->browser()->UpdateRendererPreferencesForWorker(
-      worker_process_host_->GetBrowserContext(), renderer_preferences.get());
+      worker_process_host_->GetBrowserContext(), &renderer_preferences);
 
   // Create a RendererPreferenceWatcher to observe updates in the preferences.
   mojo::PendingRemote<blink::mojom::RendererPreferenceWatcher> watcher_remote;
diff --git a/content/browser/worker_host/worker_script_fetch_initiator.cc b/content/browser/worker_host/worker_script_fetch_initiator.cc
index deb5879..034ff5b 100644
--- a/content/browser/worker_host/worker_script_fetch_initiator.cc
+++ b/content/browser/worker_host/worker_script_fetch_initiator.cc
@@ -51,7 +51,7 @@
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
 #include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
 #include "url/origin.h"
 
@@ -278,7 +278,7 @@
   resource_request->headers.SetHeaderIfMissing(
       net::HttpRequestHeaders::kAccept, network::kDefaultAcceptHeaderValue);
 
-  blink::mojom::RendererPreferences renderer_preferences;
+  blink::RendererPreferences renderer_preferences;
   GetContentClient()->browser()->UpdateRendererPreferencesForWorker(
       browser_context, &renderer_preferences);
   UpdateAdditionalHeadersForBrowserInitiatedRequest(
diff --git a/content/child/browser_font_resource_trusted.cc b/content/child/browser_font_resource_trusted.cc
index 1bafbe0..1dd1e44 100644
--- a/content/child/browser_font_resource_trusted.cc
+++ b/content/child/browser_font_resource_trusted.cc
@@ -19,18 +19,17 @@
 #include "ppapi/thunk/thunk.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
-#include "third_party/blink/public/platform/web_float_rect.h"
 #include "third_party/blink/public/platform/web_font.h"
 #include "third_party/blink/public/platform/web_font_description.h"
 #include "third_party/blink/public/platform/web_rect.h"
 #include "third_party/blink/public/platform/web_text_run.h"
 #include "third_party/icu/source/common/unicode/ubidi.h"
 #include "third_party/skia/include/core/SkRect.h"
+#include "ui/gfx/geometry/rect_f.h"
 
 using ppapi::StringVar;
 using ppapi::thunk::EnterResourceNoLock;
 using ppapi::thunk::PPB_ImageData_API;
-using blink::WebFloatRect;
 using blink::WebFont;
 using blink::WebFontDescription;
 using blink::WebRect;
@@ -398,10 +397,10 @@
       // 0 characters starting at the character in question, it would give us
       // a 0-width rect around the insertion point. But that will be on the
       // right side of the character for an RTL run, which would be wrong.
-      WebFloatRect rect = font_->SelectionRectForText(
+      gfx::RectF rect = font_->SelectionRectForText(
           run, gfx::PointF(), font_->Height(), char_offset - run_begin,
           char_offset - run_begin + 1);
-      return cur_pixel_offset + static_cast<int>(rect.x);
+      return cur_pixel_offset + static_cast<int>(rect.x());
     } else {
       // Character is past this run, account for the pixels and continue
       // looking.
diff --git a/content/child/webthemeengine_impl_default.h b/content/child/webthemeengine_impl_default.h
index 815b3d2..9da412ed 100644
--- a/content/child/webthemeengine_impl_default.h
+++ b/content/child/webthemeengine_impl_default.h
@@ -32,8 +32,8 @@
                                              system_theme_color) const override;
 #if defined(OS_WIN)
   // Caches the scrollbar metrics. These are retrieved in the browser and passed
-  // to the renderer in blink::mojom::RendererPreferences because the required
-  // Windows system calls cannot be made in sandboxed renderers.
+  // to the renderer in blink::RendererPreferences because the required Windows
+  // system calls cannot be made in sandboxed renderers.
   static void cacheScrollBarMetrics(int32_t vertical_scroll_bar_width,
                                     int32_t horizontal_scroll_bar_height,
                                     int32_t vertical_arrow_bitmap_height,
diff --git a/content/common/DEPS b/content/common/DEPS
index 77ed800..680e32b 100644
--- a/content/common/DEPS
+++ b/content/common/DEPS
@@ -24,7 +24,6 @@
   "+third_party/blink/public/platform/viewport_intersection_state.h",
   "+third_party/blink/public/platform/web_content_security_policy.h",
   "+third_party/blink/public/common/page/drag_operation.h",
-  "+third_party/blink/public/platform/web_float_rect.h",
   "+third_party/blink/public/platform/web_fullscreen_video_status.h",
   "+third_party/blink/public/platform/web_http_body.h",
   "+third_party/blink/public/platform/web_history_scroll_restoration_type.h",
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index 1f64242..9ede8f6 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -420,8 +420,10 @@
 
 
   // Similar to CreateNewWindow, except used for sub-widgets, like <select>
-  // dropdowns.
-  [Sync] CreateNewWidget(
+  // dropdowns. Upon return, the renderer side popup will be owned by the
+  // PopupWidgetHost.
+  [Sync] CreateNewPopupWidget(
+         pending_associated_receiver<blink.mojom.PopupWidgetHost> popup_host,
          pending_associated_receiver<blink.mojom.WidgetHost> blink_widget_host,
          pending_associated_remote<blink.mojom.Widget> blink_widget)
       => (int32 routing_id);
diff --git a/content/common/page_messages.h b/content/common/page_messages.h
index bf96f06..0da06ba 100644
--- a/content/common/page_messages.h
+++ b/content/common/page_messages.h
@@ -8,6 +8,7 @@
 #include "content/public/common/common_param_traits.h"
 #include "content/public/common/page_visibility_state.h"
 #include "ipc/ipc_message_macros.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 
 // IPC messages for page-level actions.
 // TODO(https://crbug.com/775827): Convert to mojo.
@@ -27,7 +28,7 @@
                     int /* history_length */)
 
 // Sends updated preferences to the renderer.
-IPC_MESSAGE_ROUTED1(PageMsg_SetRendererPrefs, blink::mojom::RendererPreferences)
+IPC_MESSAGE_ROUTED1(PageMsg_SetRendererPrefs, blink::RendererPreferences)
 
 // -----------------------------------------------------------------------------
 // Messages sent from the renderer to the browser.
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index eb3f50df..fc5ebd0 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -40,7 +40,6 @@
 #include "net/base/network_change_notifier.h"
 #include "ppapi/buildflags/buildflags.h"
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "ui/base/ime/text_input_type.h"
 #include "ui/gfx/color_space.h"
 #include "ui/gfx/geometry/point.h"
diff --git a/content/common/widget_messages.h b/content/common/widget_messages.h
index 74b682a..b1774046 100644
--- a/content/common/widget_messages.h
+++ b/content/common/widget_messages.h
@@ -16,7 +16,6 @@
 #include "ipc/ipc_message_macros.h"
 #include "third_party/blink/public/common/widget/visual_properties.h"
 #include "third_party/blink/public/mojom/page/record_content_to_visible_time_request.mojom-forward.h"
-#include "third_party/blink/public/platform/web_float_rect.h"
 #include "ui/base/ime/text_input_action.h"
 #include "ui/base/ime/text_input_mode.h"
 #include "ui/base/ui_base_types.h"
@@ -32,10 +31,6 @@
 // Browser -> Renderer Messages.
 //
 
-// Tells the render widget to close.
-// Expects a Close_ACK message when finished.
-IPC_MESSAGE_ROUTED0(WidgetMsg_Close)
-
 // Reply to WidgetHostMsg_RequestSetBounds, WidgetHostMsg_ShowWidget, and
 // FrameHostMsg_ShowCreatedWindow, to inform the renderer that the browser has
 // processed the bounds-setting.  The browser may have ignored the new bounds,
@@ -50,8 +45,7 @@
 
 // Sent by the renderer process to request that the browser close the widget.
 // This corresponds to the window.close() API, and the browser may ignore
-// this message.  Otherwise, the browser will generate a WidgetMsg_Close
-// message to close the widget.
+// this message.
 IPC_MESSAGE_ROUTED0(WidgetHostMsg_Close)
 
 // Sent by the renderer process to request that the browser change the bounds of
diff --git a/content/public/android/java/src/org/chromium/content/browser/SpeechRecognitionImpl.java b/content/public/android/java/src/org/chromium/content/browser/SpeechRecognitionImpl.java
index 1720bba..c7f5860 100644
--- a/content/public/android/java/src/org/chromium/content/browser/SpeechRecognitionImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/SpeechRecognitionImpl.java
@@ -70,6 +70,8 @@
 
         @Override
         public void onBeginningOfSpeech() {
+            if (mNativeSpeechRecognizerImplAndroid == 0) return;
+
             mState = STATE_CAPTURING_SPEECH;
             SpeechRecognitionImplJni.get().onSoundStart(
                     mNativeSpeechRecognizerImplAndroid, SpeechRecognitionImpl.this);
@@ -86,6 +88,7 @@
             // equivalent (onsoundend) event. Thus, the only way to provide a valid onsoundend
             // event is to trigger it when the last result is received or the session is aborted.
             if (!mContinuous) {
+                if (mNativeSpeechRecognizerImplAndroid == 0) return;
                 SpeechRecognitionImplJni.get().onSoundEnd(
                         mNativeSpeechRecognizerImplAndroid, SpeechRecognitionImpl.this);
                 // Since Android doesn't have a dedicated event for when audio capture is finished,
@@ -141,6 +144,8 @@
 
         @Override
         public void onReadyForSpeech(Bundle bundle) {
+            if (mNativeSpeechRecognizerImplAndroid == 0) return;
+
             mState = STATE_AWAITING_SPEECH;
             SpeechRecognitionImplJni.get().onAudioStart(
                     mNativeSpeechRecognizerImplAndroid, SpeechRecognitionImpl.this);
@@ -159,6 +164,8 @@
         public void onRmsChanged(float rms) { }
 
         private void handleResults(Bundle bundle, boolean provisional) {
+            if (mNativeSpeechRecognizerImplAndroid == 0) return;
+
             if (mContinuous && provisional) {
                 // In continuous mode, Android's recognizer sends final results as provisional.
                 provisional = false;
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index f8f5b9b0..922cb0a 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -50,8 +50,8 @@
 #include "storage/browser/quota/quota_manager.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
-#include "third_party/blink/public/mojom/renderer_preference_watcher.mojom.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/shell_dialogs/select_file_policy.h"
 #include "url/gurl.h"
@@ -382,7 +382,7 @@
 
 void ContentBrowserClient::UpdateRendererPreferencesForWorker(
     BrowserContext* browser_context,
-    blink::mojom::RendererPreferences* out_prefs) {
+    blink::RendererPreferences* out_prefs) {
   // |browser_context| may be null (e.g. during shutdown of a service worker).
 }
 
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index e222a02..3a620d6 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -85,7 +85,6 @@
 namespace blink {
 namespace mojom {
 class BadgeService;
-class RendererPreferences;
 class RendererPreferenceWatcher;
 class WebUsbService;
 class WindowFeatures;
@@ -95,6 +94,7 @@
 struct WebPreferences;
 }  // namespace web_pref
 class AssociatedInterfaceRegistry;
+struct RendererPreferences;
 class URLLoaderThrottle;
 }  // namespace blink
 
@@ -673,7 +673,7 @@
   // from their closest ancestor frame.
   virtual void UpdateRendererPreferencesForWorker(
       BrowserContext* browser_context,
-      blink::mojom::RendererPreferences* out_prefs);
+      blink::RendererPreferences* out_prefs);
 
   // Allow the embedder to control if access to file system by a shared worker
   // is allowed.
diff --git a/content/public/browser/renderer_preferences_util.cc b/content/public/browser/renderer_preferences_util.cc
index fee03cb..e7bd0ec11 100644
--- a/content/public/browser/renderer_preferences_util.cc
+++ b/content/public/browser/renderer_preferences_util.cc
@@ -9,13 +9,13 @@
 #include "base/strings/string_number_conversions.h"
 #include "build/build_config.h"
 #include "content/public/common/content_switches.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "ui/gfx/font_render_params.h"
 
 namespace content {
 
 void UpdateFontRendererPreferencesFromSystemSettings(
-    blink::mojom::RendererPreferences* prefs) {
+    blink::RendererPreferences* prefs) {
   static const base::NoDestructor<gfx::FontRenderParams> params(
       gfx::GetFontRenderParams(gfx::FontRenderParamsQuery(), nullptr));
   prefs->should_antialias_text = params->antialiasing;
diff --git a/content/public/browser/renderer_preferences_util.h b/content/public/browser/renderer_preferences_util.h
index eb81d84..ed443a5 100644
--- a/content/public/browser/renderer_preferences_util.h
+++ b/content/public/browser/renderer_preferences_util.h
@@ -8,16 +8,14 @@
 #include "content/common/content_export.h"
 
 namespace blink {
-namespace mojom {
-class RendererPreferences;
-}
+struct RendererPreferences;
 }  // namespace blink
 
 namespace content {
 
 // Updates |prefs| from system settings.
 CONTENT_EXPORT void UpdateFontRendererPreferencesFromSystemSettings(
-    blink::mojom::RendererPreferences* prefs);
+    blink::RendererPreferences* prefs);
 
 }  // namespace content
 
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index 7c95dd0..5922d41 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -52,14 +52,12 @@
 #endif
 
 namespace blink {
-namespace mojom {
-class RendererPreferences;
-}
 namespace web_pref {
 struct WebPreferences;
 }
 struct Manifest;
 struct UserAgentOverride;
+struct RendererPreferences;
 }  // namespace blink
 
 namespace base {
@@ -836,7 +834,7 @@
   virtual const std::string& GetContentsMimeType() = 0;
 
   // Returns the settings which get passed to the renderer.
-  virtual blink::mojom::RendererPreferences* GetMutableRendererPrefs() = 0;
+  virtual blink::RendererPreferences* GetMutableRendererPrefs() = 0;
 
   // Tells the tab to close now. The tab will take care not to close until it's
   // out of nested run loops.
diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h
index 49222db..e762cbd 100644
--- a/content/public/common/common_param_traits_macros.h
+++ b/content/public/common/common_param_traits_macros.h
@@ -17,12 +17,12 @@
 #include "services/network/public/cpp/network_ipc_param_traits.h"
 #include "services/network/public/mojom/referrer_policy.mojom.h"
 #include "third_party/blink/public/common/page/drag_operation.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/common/security/security_style.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
 #include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
 #include "third_party/blink/public/mojom/page_state/page_state.mojom.h"
 #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "third_party/blink/public/mojom/v8_cache_options.mojom.h"
 #include "third_party/blink/public/mojom/window_features/window_features.mojom.h"
 #include "third_party/blink/public/platform/web_rect.h"
@@ -109,7 +109,7 @@
   IPC_STRUCT_TRAITS_MEMBER(ua_metadata_override)
 IPC_STRUCT_TRAITS_END()
 
-IPC_STRUCT_TRAITS_BEGIN(blink::mojom::RendererPreferences)
+IPC_STRUCT_TRAITS_BEGIN(blink::RendererPreferences)
   IPC_STRUCT_TRAITS_MEMBER(can_accept_load_drops)
   IPC_STRUCT_TRAITS_MEMBER(should_antialias_text)
   IPC_STRUCT_TRAITS_MEMBER(hinting)
@@ -155,6 +155,9 @@
   IPC_STRUCT_TRAITS_MEMBER(arrow_bitmap_height_vertical_scroll_bar_in_dips)
   IPC_STRUCT_TRAITS_MEMBER(arrow_bitmap_width_horizontal_scroll_bar_in_dips)
 #endif
+#if defined(USE_X11) || defined(USE_OZONE)
+  IPC_STRUCT_TRAITS_MEMBER(selection_clipboard_buffer_available)
+#endif
 IPC_STRUCT_TRAITS_END()
 
 IPC_ENUM_TRAITS(blink::DragOperation)  // Bitmask.
diff --git a/content/public/test/mock_render_thread.cc b/content/public/test/mock_render_thread.cc
index f4f66903c..662e3e0 100644
--- a/content/public/test/mock_render_thread.cc
+++ b/content/public/test/mock_render_thread.cc
@@ -339,12 +339,20 @@
           blink_frame_widget.BindNewEndpointAndPassDedicatedReceiver();
 
   mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> blink_frame_widget_host;
-  mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetHost>
-      blink_frame_widget_host_receiver =
-          blink_frame_widget_host.BindNewEndpointAndPassDedicatedReceiver();
+  ignore_result(
+      blink_frame_widget_host.BindNewEndpointAndPassDedicatedReceiver());
+
+  mojo::AssociatedRemote<blink::mojom::Widget> blink_widget;
+  mojo::PendingAssociatedReceiver<blink::mojom::Widget> blink_widget_receiver =
+      blink_widget.BindNewEndpointAndPassDedicatedReceiver();
+
+  mojo::AssociatedRemote<blink::mojom::WidgetHost> blink_widget_host;
+  ignore_result(blink_widget_host.BindNewEndpointAndPassDedicatedReceiver());
 
   reply->frame_widget = std::move(blink_frame_widget_receiver);
   reply->frame_widget_host = blink_frame_widget_host.Unbind();
+  reply->widget = std::move(blink_widget_receiver);
+  reply->widget_host = blink_widget_host.Unbind();
 }
 
 }  // namespace content
diff --git a/content/public/test/mock_render_thread.h b/content/public/test/mock_render_thread.h
index 110c379..b561f6a 100644
--- a/content/public/test/mock_render_thread.h
+++ b/content/public/test/mock_render_thread.h
@@ -43,9 +43,8 @@
 }
 
 // This class is a very simple mock of RenderThread. It simulates an IPC channel
-// which supports only three messages:
-// ViewHostMsg_CreateWidget : sync message sent by the Widget.
-// WidgetMsg_Close : async, send to the Widget.
+// which supports the following message:
+// FrameHostMsg_CreateChildFrame : sync message sent by the renderer.
 class MockRenderThread : public RenderThread {
  public:
   MockRenderThread();
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index 4166b1a9..108be294 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -47,10 +47,10 @@
 #include "third_party/blink/public/common/input/web_input_event.h"
 #include "third_party/blink/public/common/input/web_mouse_event.h"
 #include "third_party/blink/public/common/loader/previews_state.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/common/widget/visual_properties.h"
 #include "third_party/blink/public/mojom/leak_detector/leak_detector.mojom.h"
 #include "third_party/blink/public/mojom/page/record_content_to_visible_time_request.mojom.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/public/platform/web_runtime_features.h"
@@ -484,7 +484,7 @@
   mojom::CreateViewParamsPtr view_params = mojom::CreateViewParams::New();
   view_params->opener_frame_token = base::nullopt;
   view_params->window_was_created_with_opener = false;
-  view_params->renderer_preferences = blink::mojom::RendererPreferences::New();
+  view_params->renderer_preferences = blink::RendererPreferences();
   view_params->web_preferences = blink::web_pref::WebPreferences();
   view_params->view_id = render_thread_->GetNextRoutingID();
   view_params->main_frame_widget_routing_id =
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 7120c3d3..d9b5338 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -89,8 +89,6 @@
     "loader/resource_dispatcher.h",
     "loader/sync_load_context.cc",
     "loader/sync_load_context.h",
-    "loader/sync_load_response.cc",
-    "loader/sync_load_response.h",
     "loader/tracked_child_url_loader_factory_bundle.cc",
     "loader/tracked_child_url_loader_factory_bundle.h",
     "loader/url_loader_client_impl.cc",
diff --git a/content/renderer/agent_scheduling_group.cc b/content/renderer/agent_scheduling_group.cc
index 865c929..e6f55e56 100644
--- a/content/renderer/agent_scheduling_group.cc
+++ b/content/renderer/agent_scheduling_group.cc
@@ -7,7 +7,10 @@
 #include "base/feature_list.h"
 #include "base/util/type_safety/pass_key.h"
 #include "content/public/common/content_features.h"
+#include "content/renderer/compositor/compositor_dependencies.h"
+#include "content/renderer/render_frame_proxy.h"
 #include "content/renderer/render_thread_impl.h"
+#include "content/renderer/render_view_impl.h"
 
 namespace content {
 
@@ -128,16 +131,50 @@
 }
 
 void AgentSchedulingGroup::CreateView(mojom::CreateViewParamsPtr params) {
-  ToImpl(render_thread_).CreateView(std::move(params), PassKey());
+  RenderThreadImpl& renderer = ToImpl(render_thread_);
+
+  RenderViewImpl::Create(
+      *this, &renderer, std::move(params), RenderWidget::ShowCallback(),
+      // TODO(crbug.com/1111231): Use proper per-ASG task-runner.
+      renderer.GetWebMainThreadScheduler()->DefaultTaskRunner());
 }
 
 void AgentSchedulingGroup::DestroyView(int32_t view_id,
                                        DestroyViewCallback callback) {
-  ToImpl(render_thread_).DestroyView(view_id, std::move(callback), PassKey());
+  RenderViewImpl* view = RenderViewImpl::FromRoutingID(view_id);
+  DCHECK(view);
+
+  // This IPC can be called from re-entrant contexts. We can't destroy a
+  // RenderViewImpl while references still exist on the stack, so we dispatch a
+  // non-nestable task. This method is called exactly once by the browser
+  // process, and is used to release ownership of the corresponding
+  // RenderViewImpl instance. https://crbug.com/1000035.
+  base::ThreadTaskRunnerHandle::Get()->PostNonNestableTask(
+      FROM_HERE, base::BindOnce(
+                     [](RenderViewImpl* view, DestroyViewCallback callback) {
+                       view->Destroy();
+                       std::move(callback).Run();
+                     },
+                     base::Unretained(view), std::move(callback)));
 }
 
 void AgentSchedulingGroup::CreateFrame(mojom::CreateFrameParamsPtr params) {
-  ToImpl(render_thread_).CreateFrame(std::move(params), PassKey());
+  mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
+      interface_provider(
+          std::move(params->interface_bundle->interface_provider));
+  mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
+      browser_interface_broker(
+          std::move(params->interface_bundle->browser_interface_broker));
+
+  RenderFrameImpl::CreateFrame(
+      *this, params->routing_id, std::move(interface_provider),
+      std::move(browser_interface_broker), params->previous_routing_id,
+      params->opener_frame_token, params->parent_routing_id,
+      params->previous_sibling_routing_id, params->frame_token,
+      params->devtools_frame_token, params->replication_state,
+      &ToImpl(render_thread_), std::move(params->widget_params),
+      std::move(params->frame_owner_properties),
+      params->has_committed_real_load);
 }
 
 void AgentSchedulingGroup::CreateFrameProxy(
@@ -148,10 +185,9 @@
     const FrameReplicationState& replicated_state,
     const base::UnguessableToken& frame_token,
     const base::UnguessableToken& devtools_frame_token) {
-  ToImpl(render_thread_)
-      .CreateFrameProxy(routing_id, render_view_routing_id, opener_frame_token,
-                        parent_routing_id, replicated_state, frame_token,
-                        devtools_frame_token, PassKey());
+  RenderFrameProxy::CreateFrameProxy(
+      *this, routing_id, render_view_routing_id, opener_frame_token,
+      parent_routing_id, replicated_state, frame_token, devtools_frame_token);
 }
 
 void AgentSchedulingGroup::BindAssociatedRouteProvider(
diff --git a/content/renderer/loader/resource_dispatcher.cc b/content/renderer/loader/resource_dispatcher.cc
index fb9e54f..3300c56 100644
--- a/content/renderer/loader/resource_dispatcher.cc
+++ b/content/renderer/loader/resource_dispatcher.cc
@@ -27,7 +27,6 @@
 #include "content/public/renderer/resource_dispatcher_delegate.h"
 #include "content/renderer/loader/request_extra_data.h"
 #include "content/renderer/loader/sync_load_context.h"
-#include "content/renderer/loader/sync_load_response.h"
 #include "content/renderer/loader/url_loader_client_impl.h"
 #include "content/renderer/render_frame_impl.h"
 #include "content/renderer/render_thread_impl.h"
@@ -48,6 +47,7 @@
 #include "third_party/blink/public/common/loader/throttling_url_loader.h"
 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
 #include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
+#include "third_party/blink/public/platform/sync_load_response.h"
 
 namespace content {
 
@@ -433,7 +433,7 @@
     int routing_id,
     const net::NetworkTrafficAnnotationTag& traffic_annotation,
     uint32_t loader_options,
-    SyncLoadResponse* response,
+    blink::SyncLoadResponse* response,
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles,
     base::TimeDelta timeout,
@@ -458,17 +458,18 @@
 
   // A task is posted to a separate thread to execute the request so that
   // this thread may block on a waitable event. It is safe to pass raw
-  // pointers to |sync_load_response| and |event| as this stack frame will
+  // pointers to on-stack objects as this stack frame will
   // survive until the request is complete.
   scoped_refptr<base::SingleThreadTaskRunner> task_runner =
       base::ThreadPool::CreateSingleThreadTaskRunner({});
+  SyncLoadContext* context_for_redirect = nullptr;
   task_runner->PostTask(
       FROM_HERE,
       base::BindOnce(
           &SyncLoadContext::StartAsyncWithWaitableEvent, std::move(request),
           routing_id, task_runner, traffic_annotation, loader_options,
           std::move(pending_factory), std::move(throttles),
-          base::Unretained(response),
+          base::Unretained(response), base::Unretained(&context_for_redirect),
           base::Unretained(&redirect_or_response_event),
           base::Unretained(terminate_sync_load_event_), timeout,
           std::move(download_to_blob_registry), cors_exempt_header_list_,
@@ -478,7 +479,7 @@
   // when the final response is complete.
   redirect_or_response_event.Wait();
 
-  while (response->context_for_redirect) {
+  while (context_for_redirect) {
     DCHECK(response->redirect_info);
     bool follow_redirect = peer->OnReceivedRedirect(
         *response->redirect_info, response->head.Clone(),
@@ -486,14 +487,12 @@
     redirect_or_response_event.Reset();
     if (follow_redirect) {
       task_runner->PostTask(
-          FROM_HERE,
-          base::BindOnce(&SyncLoadContext::FollowRedirect,
-                         base::Unretained(response->context_for_redirect)));
+          FROM_HERE, base::BindOnce(&SyncLoadContext::FollowRedirect,
+                                    base::Unretained(context_for_redirect)));
     } else {
       task_runner->PostTask(
-          FROM_HERE,
-          base::BindOnce(&SyncLoadContext::CancelRedirect,
-                         base::Unretained(response->context_for_redirect)));
+          FROM_HERE, base::BindOnce(&SyncLoadContext::CancelRedirect,
+                                    base::Unretained(context_for_redirect)));
     }
     redirect_or_response_event.Wait();
   }
diff --git a/content/renderer/loader/resource_dispatcher.h b/content/renderer/loader/resource_dispatcher.h
index 585d6c204..592d8f4 100644
--- a/content/renderer/loader/resource_dispatcher.h
+++ b/content/renderer/loader/resource_dispatcher.h
@@ -43,6 +43,7 @@
 namespace blink {
 class ResourceLoadInfoNotifierWrapper;
 class ThrottlingURLLoader;
+struct SyncLoadResponse;
 }
 
 namespace net {
@@ -60,7 +61,6 @@
 namespace content {
 class RequestPeer;
 class ResourceDispatcherDelegate;
-struct SyncLoadResponse;
 class URLLoaderClientImpl;
 
 // This class serves as a communication interface to the ResourceDispatcherHost
@@ -99,7 +99,7 @@
       int routing_id,
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       uint32_t loader_options,
-      SyncLoadResponse* response,
+      blink::SyncLoadResponse* response,
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles,
       base::TimeDelta timeout,
diff --git a/content/renderer/loader/sync_load_context.cc b/content/renderer/loader/sync_load_context.cc
index c095cfa0..08b9c893 100644
--- a/content/renderer/loader/sync_load_context.cc
+++ b/content/renderer/loader/sync_load_context.cc
@@ -12,7 +12,6 @@
 #include "base/optional.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/time/time.h"
-#include "content/renderer/loader/sync_load_response.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
 #include "net/url_request/redirect_info.h"
 #include "services/network/public/cpp/resource_request.h"
@@ -20,6 +19,7 @@
 #include "third_party/blink/public/common/client_hints/client_hints.h"
 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
 #include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
+#include "third_party/blink/public/platform/sync_load_response.h"
 
 namespace content {
 
@@ -97,7 +97,8 @@
     std::unique_ptr<network::PendingSharedURLLoaderFactory>
         pending_url_loader_factory,
     std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles,
-    SyncLoadResponse* response,
+    blink::SyncLoadResponse* response,
+    SyncLoadContext** context_for_redirect,
     base::WaitableEvent* redirect_or_response_event,
     base::WaitableEvent* abort_event,
     base::TimeDelta timeout,
@@ -105,11 +106,11 @@
     const std::vector<std::string>& cors_exempt_header_list,
     std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
         resource_load_info_notifier_wrapper) {
-  auto* context =
-      new SyncLoadContext(request.get(), std::move(pending_url_loader_factory),
-                          response, redirect_or_response_event, abort_event,
-                          timeout, std::move(download_to_blob_registry),
-                          loading_task_runner, cors_exempt_header_list);
+  auto* context = new SyncLoadContext(
+      request.get(), std::move(pending_url_loader_factory), response,
+      context_for_redirect, redirect_or_response_event, abort_event, timeout,
+      std::move(download_to_blob_registry), loading_task_runner,
+      cors_exempt_header_list);
   context->request_id_ = context->resource_dispatcher_->StartAsync(
       std::move(request), routing_id, std::move(loading_task_runner),
       traffic_annotation, loader_options, base::WrapUnique(context),
@@ -120,7 +121,8 @@
 SyncLoadContext::SyncLoadContext(
     network::ResourceRequest* request,
     std::unique_ptr<network::PendingSharedURLLoaderFactory> url_loader_factory,
-    SyncLoadResponse* response,
+    blink::SyncLoadResponse* response,
+    SyncLoadContext** context_for_redirect,
     base::WaitableEvent* redirect_or_response_event,
     base::WaitableEvent* abort_event,
     base::TimeDelta timeout,
@@ -128,6 +130,7 @@
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     const std::vector<std::string>& cors_exempt_header_list)
     : response_(response),
+      context_for_redirect_(context_for_redirect),
       body_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL),
       download_to_blob_registry_(std::move(download_to_blob_registry)),
       task_runner_(std::move(task_runner)),
@@ -169,7 +172,7 @@
   response_->url = redirect_info.new_url;
   response_->head = std::move(head);
   response_->redirect_info = redirect_info;
-  response_->context_for_redirect = this;
+  *context_for_redirect_ = this;
   resource_dispatcher_->SetDefersLoading(request_id_, true);
   signals_->SignalRedirectOrResponseComplete();
   return true;
@@ -182,14 +185,15 @@
   }
 
   response_->redirect_info = net::RedirectInfo();
-  response_->context_for_redirect = nullptr;
+  *context_for_redirect_ = nullptr;
 
   resource_dispatcher_->SetDefersLoading(request_id_, false);
 }
 
 void SyncLoadContext::CancelRedirect() {
   response_->redirect_info = net::RedirectInfo();
-  response_->context_for_redirect = nullptr;
+  *context_for_redirect_ = nullptr;
+
   response_->error_code = net::ERR_ABORTED;
   CompleteRequest();
 }
@@ -295,7 +299,7 @@
     return;
   }
 
-  response_->data.append(static_cast<const char*>(buffer), read_bytes);
+  response_->data.Append(static_cast<const char*>(buffer), read_bytes);
   body_handle_->EndReadData(read_bytes);
   body_watcher_.ArmOrNotify();
 }
diff --git a/content/renderer/loader/sync_load_context.h b/content/renderer/loader/sync_load_context.h
index 212df58..919df7b2 100644
--- a/content/renderer/loader/sync_load_context.h
+++ b/content/renderer/loader/sync_load_context.h
@@ -31,12 +31,11 @@
 namespace blink {
 class ResourceLoadInfoNotifierWrapper;
 class URLLoaderThrottle;
+struct SyncLoadResponse;
 }
 
 namespace content {
 
-struct SyncLoadResponse;
-
 // This class owns the context necessary to perform an asynchronous request
 // while the main thread is blocked so that it appears to be synchronous.
 // There are a couple of modes to load a request:
@@ -52,8 +51,13 @@
   // and |response| will be populated with the response data. |abort_event|
   // will be signalled from the main thread to abort the sync request on a
   // worker thread when the worker thread is being terminated.
-  // If |download_to_blob_registry| is not null, it is used to redirect the
-  // download to a blob, with the resulting blob populated in |response|.
+  // The pointer whose address is `context_for_redirect` is held by the caller
+  // that is blocked on this method, so it will remain valid until the operation
+  // completes. If there are redirects, `context_for_redirect` will point to the
+  // callee context.
+  // If |download_to_blob_registry| is not null, it is used to
+  // redirect the download to a blob, with the resulting blob populated in
+  // |response|.
   static void StartAsyncWithWaitableEvent(
       std::unique_ptr<network::ResourceRequest> request,
       int routing_id,
@@ -63,7 +67,8 @@
       std::unique_ptr<network::PendingSharedURLLoaderFactory>
           pending_url_loader_factory,
       std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles,
-      SyncLoadResponse* response,
+      blink::SyncLoadResponse* response,
+      SyncLoadContext** context_for_redirect,
       base::WaitableEvent* completed_event,
       base::WaitableEvent* abort_event,
       base::TimeDelta timeout,
@@ -84,7 +89,8 @@
       network::ResourceRequest* request,
       std::unique_ptr<network::PendingSharedURLLoaderFactory>
           url_loader_factory,
-      SyncLoadResponse* response,
+      blink::SyncLoadResponse* response,
+      SyncLoadContext** context_for_redirect,
       base::WaitableEvent* completed_event,
       base::WaitableEvent* abort_event,
       base::TimeDelta timeout,
@@ -117,7 +123,13 @@
   // This raw pointer will remain valid for the lifetime of this object because
   // it remains on the stack until |event_| is signaled.
   // Set to null after CompleteRequest() is called.
-  SyncLoadResponse* response_;
+  blink::SyncLoadResponse* response_;
+
+  // This raw pointer will be set to `this` when receiving redirects on
+  // independent thread and set to nullptr in `FollowRedirect()` or
+  // `CancelRedirect()` on the same thread after `redirect_or_response_event_`
+  // is signaled, which protects it against race condition.
+  SyncLoadContext** context_for_redirect_;
 
   enum class Mode { kInitial, kDataPipe, kBlob };
   Mode mode_ = Mode::kInitial;
diff --git a/content/renderer/loader/sync_load_context_unittest.cc b/content/renderer/loader/sync_load_context_unittest.cc
index 62c5f0015..5c89221a 100644
--- a/content/renderer/loader/sync_load_context_unittest.cc
+++ b/content/renderer/loader/sync_load_context_unittest.cc
@@ -7,7 +7,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/test/task_environment.h"
 #include "base/threading/thread.h"
-#include "content/renderer/loader/sync_load_response.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/system/data_pipe_utils.h"
@@ -16,6 +15,7 @@
 #include "services/network/test/test_url_loader_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
+#include "third_party/blink/public/platform/sync_load_response.h"
 
 namespace content {
 
@@ -102,36 +102,38 @@
   void StartAsyncWithWaitableEventOnLoadingThread(
       std::unique_ptr<network::ResourceRequest> request,
       std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_factory,
-      SyncLoadResponse* out_response,
+      blink::SyncLoadResponse* out_response,
+      SyncLoadContext** context_for_redirect,
       base::WaitableEvent* redirect_or_response_event) {
     loading_thread_.task_runner()->PostTask(
         FROM_HERE,
-        base::BindOnce(&SyncLoadContext::StartAsyncWithWaitableEvent,
-                       std::move(request), MSG_ROUTING_NONE,
-                       loading_thread_.task_runner(),
-                       TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* loader_options */,
-                       std::move(pending_factory),
-                       std::vector<std::unique_ptr<blink::URLLoaderThrottle>>(),
-                       out_response, redirect_or_response_event,
-                       nullptr /* terminate_sync_load_event */,
-                       base::TimeDelta::FromSeconds(60) /* timeout */,
-                       mojo::NullRemote() /* download_to_blob_registry */,
-                       std::vector<std::string>() /* cors_exempt_header_list */,
-                       std::make_unique<blink::ResourceLoadInfoNotifierWrapper>(
-                           /*resource_load_info_notifier=*/nullptr,
-                           task_environment_.GetMainThreadTaskRunner())));
+        base::BindOnce(
+            &SyncLoadContext::StartAsyncWithWaitableEvent, std::move(request),
+            MSG_ROUTING_NONE, loading_thread_.task_runner(),
+            TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* loader_options */,
+            std::move(pending_factory),
+            std::vector<std::unique_ptr<blink::URLLoaderThrottle>>(),
+            out_response, context_for_redirect, redirect_or_response_event,
+            nullptr /* terminate_sync_load_event */,
+            base::TimeDelta::FromSeconds(60) /* timeout */,
+            mojo::NullRemote() /* download_to_blob_registry */,
+            std::vector<std::string>() /* cors_exempt_header_list */,
+            std::make_unique<blink::ResourceLoadInfoNotifierWrapper>(
+                /*resource_load_info_notifier=*/nullptr,
+                task_environment_.GetMainThreadTaskRunner())));
   }
 
   static void RunSyncLoadContextViaDataPipe(
       network::ResourceRequest* request,
-      SyncLoadResponse* response,
+      blink::SyncLoadResponse* response,
+      SyncLoadContext** context_for_redirect,
       std::string expected_data,
       base::WaitableEvent* redirect_or_response_event,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
     DCHECK(task_runner->BelongsToCurrentThread());
     auto* context = new SyncLoadContext(
         request, std::make_unique<MockPendingSharedURLLoaderFactory>(),
-        response, redirect_or_response_event,
+        response, context_for_redirect, redirect_or_response_event,
         nullptr /* terminate_sync_load_event */,
         base::TimeDelta::FromSeconds(60) /* timeout */,
         mojo::NullRemote() /* download_to_blob_registry */, task_runner,
@@ -170,20 +172,23 @@
   request->url = expected_url;
   auto pending_factory = std::make_unique<MockPendingSharedURLLoaderFactory>();
   pending_factory->factory()->AddResponse(expected_url.spec(), expected_data);
-  SyncLoadResponse response;
+  blink::SyncLoadResponse response;
+  SyncLoadContext* context_for_redirect = nullptr;
   base::WaitableEvent redirect_or_response_event(
       base::WaitableEvent::ResetPolicy::MANUAL,
       base::WaitableEvent::InitialState::NOT_SIGNALED);
   StartAsyncWithWaitableEventOnLoadingThread(
       std::move(request), std::move(pending_factory), &response,
-      &redirect_or_response_event);
+      &context_for_redirect, &redirect_or_response_event);
 
   // Wait until the response is received.
   redirect_or_response_event.Wait();
 
   // Check if |response| is set properly after the WaitableEvent fires.
   EXPECT_EQ(net::OK, response.error_code);
-  EXPECT_EQ(expected_data, response.data);
+  const char* response_data = nullptr;
+  size_t size = response.data.GetSomeData(response_data, 0);
+  EXPECT_EQ(expected_data, std::string(response_data, size));
 }
 
 TEST_F(SyncLoadContextTest, ResponseBodyViaDataPipe) {
@@ -193,15 +198,16 @@
   // Create and exercise SyncLoadContext on the |loading_thread_|.
   auto request = std::make_unique<network::ResourceRequest>();
   request->url = expected_url;
-  SyncLoadResponse response;
+  blink::SyncLoadResponse response;
   base::WaitableEvent redirect_or_response_event(
       base::WaitableEvent::ResetPolicy::MANUAL,
       base::WaitableEvent::InitialState::NOT_SIGNALED);
+  SyncLoadContext* context_for_redirect = nullptr;
   loading_thread_.task_runner()->PostTask(
       FROM_HERE,
       base::BindOnce(&SyncLoadContextTest::RunSyncLoadContextViaDataPipe,
-                     request.get(), &response, expected_data,
-                     &redirect_or_response_event,
+                     request.get(), &response, &context_for_redirect,
+                     expected_data, &redirect_or_response_event,
                      loading_thread_.task_runner()));
 
   // Wait until the response is received.
@@ -209,7 +215,9 @@
 
   // Check if |response| is set properly after the WaitableEvent fires.
   EXPECT_EQ(net::OK, response.error_code);
-  EXPECT_EQ(expected_data, response.data);
+  const char* response_data = nullptr;
+  size_t size = response.data.GetSomeData(response_data, 0);
+  EXPECT_EQ(expected_data, std::string(response_data, size));
 }
 
 }  // namespace content
diff --git a/content/renderer/loader/web_url_loader_impl.cc b/content/renderer/loader/web_url_loader_impl.cc
index 9b48cd38..c16026c 100644
--- a/content/renderer/loader/web_url_loader_impl.cc
+++ b/content/renderer/loader/web_url_loader_impl.cc
@@ -38,7 +38,6 @@
 #include "content/public/renderer/request_peer.h"
 #include "content/renderer/loader/request_extra_data.h"
 #include "content/renderer/loader/resource_dispatcher.h"
-#include "content/renderer/loader/sync_load_response.h"
 #include "content/renderer/variations_render_thread_observer.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "net/base/filename_util.h"
@@ -77,6 +76,7 @@
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
 #include "third_party/blink/public/platform/resource_request_blocked_reason.h"
+#include "third_party/blink/public/platform/sync_load_response.h"
 #include "third_party/blink/public/platform/url_conversion.h"
 #include "third_party/blink/public/platform/web_http_load_info.h"
 #include "third_party/blink/public/platform/web_security_origin.h"
@@ -384,7 +384,7 @@
              bool pass_response_pipe_to_client,
              bool no_mime_sniffing,
              base::TimeDelta timeout_interval,
-             SyncLoadResponse* sync_load_response,
+             blink::SyncLoadResponse* sync_load_response,
              std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
                  resource_load_info_notifier_wrapper);
 
@@ -543,7 +543,7 @@
     bool pass_response_pipe_to_client,
     bool no_mime_sniffing,
     base::TimeDelta timeout_interval,
-    SyncLoadResponse* sync_load_response,
+    blink::SyncLoadResponse* sync_load_response,
     std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
         resource_load_info_notifier_wrapper) {
   DCHECK(request_id_ == -1);
@@ -1015,7 +1015,7 @@
     std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
         resource_load_info_notifier_wrapper) {
   TRACE_EVENT0("loading", "WebURLLoaderImpl::loadSynchronously");
-  SyncLoadResponse sync_load_response;
+  blink::SyncLoadResponse sync_load_response;
 
   DCHECK(!context_->client());
   context_->set_client(client);
@@ -1062,7 +1062,7 @@
         std::move(sync_load_response.downloaded_blob->blob));
   }
 
-  data.Assign(sync_load_response.data.data(), sync_load_response.data.size());
+  data.Assign(sync_load_response.data);
 }
 
 void WebURLLoaderImpl::LoadAsynchronously(
diff --git a/content/renderer/loader/web_url_loader_impl_unittest.cc b/content/renderer/loader/web_url_loader_impl_unittest.cc
index 15828204..4e9c8735 100644
--- a/content/renderer/loader/web_url_loader_impl_unittest.cc
+++ b/content/renderer/loader/web_url_loader_impl_unittest.cc
@@ -22,7 +22,6 @@
 #include "content/public/renderer/request_peer.h"
 #include "content/renderer/loader/request_extra_data.h"
 #include "content/renderer/loader/resource_dispatcher.h"
-#include "content/renderer/loader/sync_load_response.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "net/base/host_port_pair.h"
@@ -40,6 +39,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/platform/sync_load_response.h"
 #include "third_party/blink/public/platform/web_data.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_url.h"
@@ -71,7 +71,7 @@
       int routing_id,
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       uint32_t loader_options,
-      SyncLoadResponse* response,
+      blink::SyncLoadResponse* response,
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles,
       base::TimeDelta timeout,
@@ -120,7 +120,7 @@
   }
   bool defers_loading() const { return defers_loading_; }
 
-  void set_sync_load_response(SyncLoadResponse&& sync_load_response) {
+  void set_sync_load_response(blink::SyncLoadResponse&& sync_load_response) {
     sync_load_response_ = std::move(sync_load_response);
   }
 
@@ -130,7 +130,7 @@
   bool defers_loading_;
   GURL url_;
   GURL stream_url_;
-  SyncLoadResponse sync_load_response_;
+  blink::SyncLoadResponse sync_load_response_;
 
   DISALLOW_COPY_AND_ASSIGN(TestResourceDispatcher);
 };
@@ -650,10 +650,10 @@
   request->priority = net::HIGHEST;
 
   // Prepare a mock response
-  SyncLoadResponse sync_load_response;
+  blink::SyncLoadResponse sync_load_response;
   sync_load_response.error_code = net::OK;
   sync_load_response.url = url;
-  sync_load_response.data = kBodyData;
+  sync_load_response.data.Assign(blink::WebData(kBodyData));
   ASSERT_EQ(17u, sync_load_response.data.size());
   sync_load_response.head->encoded_body_length = kEncodedBodyLength;
   sync_load_response.head->encoded_data_length = kEncodedDataLength;
diff --git a/content/renderer/loader/web_worker_fetch_context_impl.cc b/content/renderer/loader/web_worker_fetch_context_impl.cc
index 7538c5ab..43294fc 100644
--- a/content/renderer/loader/web_worker_fetch_context_impl.cc
+++ b/content/renderer/loader/web_worker_fetch_context_impl.cc
@@ -163,7 +163,7 @@
 
 scoped_refptr<WebWorkerFetchContextImpl> WebWorkerFetchContextImpl::Create(
     ServiceWorkerProviderContext* provider_context,
-    blink::mojom::RendererPreferences renderer_preferences,
+    const blink::RendererPreferences& renderer_preferences,
     mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
         watcher_receiver,
     std::unique_ptr<network::PendingSharedURLLoaderFactory>
@@ -199,7 +199,7 @@
 
   scoped_refptr<WebWorkerFetchContextImpl> worker_fetch_context =
       base::AdoptRef(new WebWorkerFetchContextImpl(
-          std::move(renderer_preferences), std::move(watcher_receiver),
+          renderer_preferences, std::move(watcher_receiver),
           std::move(service_worker_client_receiver),
           std::move(service_worker_worker_client_registry),
           std::move(service_worker_container_host),
@@ -225,7 +225,7 @@
 }
 
 WebWorkerFetchContextImpl::WebWorkerFetchContextImpl(
-    blink::mojom::RendererPreferences renderer_preferences,
+    const blink::RendererPreferences& renderer_preferences,
     mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
         preference_watcher_receiver,
     mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient>
@@ -256,7 +256,7 @@
       pending_fallback_factory_(std::move(pending_fallback_factory)),
       pending_subresource_loader_updater_(
           std::move(pending_subresource_loader_updater)),
-      renderer_preferences_(std::move(renderer_preferences)),
+      renderer_preferences_(renderer_preferences),
       preference_watcher_pending_receiver_(
           std::move(preference_watcher_receiver)),
       throttle_provider_(std::move(throttle_provider)),
@@ -667,13 +667,13 @@
 }
 
 void WebWorkerFetchContextImpl::NotifyUpdate(
-    blink::mojom::RendererPreferencesPtr new_prefs) {
+    const blink::RendererPreferences& new_prefs) {
   if (accept_languages_watcher_ &&
-      renderer_preferences_.accept_languages != new_prefs->accept_languages)
+      renderer_preferences_.accept_languages != new_prefs.accept_languages)
     accept_languages_watcher_->NotifyUpdate();
-  renderer_preferences_ = *new_prefs;
+  renderer_preferences_ = new_prefs;
   for (auto& watcher : child_preference_watchers_)
-    watcher->NotifyUpdate(new_prefs.Clone());
+    watcher->NotifyUpdate(new_prefs);
 }
 
 blink::WebString WebWorkerFetchContextImpl::GetAcceptLanguages() const {
diff --git a/content/renderer/loader/web_worker_fetch_context_impl.h b/content/renderer/loader/web_worker_fetch_context_impl.h
index b8bd345..aece5be 100644
--- a/content/renderer/loader/web_worker_fetch_context_impl.h
+++ b/content/renderer/loader/web_worker_fetch_context_impl.h
@@ -18,9 +18,9 @@
 #include "mojo/public/cpp/bindings/remote_set.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/mojom/url_loader_factory.mojom-forward.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/mojom/loader/resource_load_info_notifier.mojom.h"
 #include "third_party/blink/public/mojom/renderer_preference_watcher.mojom.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_container.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-forward.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
@@ -73,7 +73,7 @@
   // chrome-extension://).
   static scoped_refptr<WebWorkerFetchContextImpl> Create(
       ServiceWorkerProviderContext* provider_context,
-      blink::mojom::RendererPreferences renderer_preferences,
+      const blink::RendererPreferences& renderer_preferences,
       mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
           watcher_receiver,
       std::unique_ptr<network::PendingSharedURLLoaderFactory>
@@ -192,7 +192,7 @@
   //
   // Regarding the rest of params, see the comments on Create().
   WebWorkerFetchContextImpl(
-      blink::mojom::RendererPreferences renderer_preferences,
+      const blink::RendererPreferences& renderer_preferences,
       mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
           watcher_receiver,
       mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient>
@@ -243,7 +243,7 @@
           subresource_loader_factories) override;
 
   // Implements blink::mojom::RendererPreferenceWatcher.
-  void NotifyUpdate(blink::mojom::RendererPreferencesPtr new_prefs) override;
+  void NotifyUpdate(const blink::RendererPreferences& new_prefs) override;
 
   void ResetWeakWrapperResourceLoadInfoNotifier();
 
@@ -325,7 +325,7 @@
   net::SiteForCookies site_for_cookies_;
   base::Optional<url::Origin> top_frame_origin_;
 
-  blink::mojom::RendererPreferences renderer_preferences_;
+  blink::RendererPreferences renderer_preferences_;
 
   // |preference_watcher_receiver_| and |child_preference_watchers_| are for
   // keeping track of updates in the renderer preferences.
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 335fd25c..cabe1f72 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -2777,8 +2777,8 @@
   return render_view_->GetBlinkPreferences();
 }
 
-const blink::mojom::RendererPreferences&
-RenderFrameImpl::GetRendererPreferences() const {
+const blink::RendererPreferences& RenderFrameImpl::GetRendererPreferences()
+    const {
   return render_view_->renderer_preferences();
 }
 
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 15a8fdc..8f027e62 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -78,6 +78,7 @@
 #include "third_party/blink/public/common/loader/loading_behavior_flag.h"
 #include "third_party/blink/public/common/loader/previews_state.h"
 #include "third_party/blink/public/common/navigation/triggering_event_info.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/common/unique_name/unique_name_helper.h"
 #include "third_party/blink/public/mojom/autoplay/autoplay.mojom.h"
 #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
@@ -92,7 +93,6 @@
 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h"
 #include "third_party/blink/public/mojom/loader/resource_load_info_notifier.mojom.h"
 #include "third_party/blink/public/mojom/media/renderer_audio_input_stream_factory.mojom.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
 #include "third_party/blink/public/mojom/use_counter/css_property_id.mojom.h"
 #include "third_party/blink/public/platform/web_media_player.h"
@@ -800,7 +800,7 @@
   void OnSetPepperVolume(int32_t pp_instance, double volume);
 #endif  // ENABLE_PLUGINS
 
-  const blink::mojom::RendererPreferences& GetRendererPreferences() const;
+  const blink::RendererPreferences& GetRendererPreferences() const;
 
   // Called when an ongoing renderer-initiated navigation was dropped by the
   // browser.
diff --git a/content/renderer/render_process_impl.cc b/content/renderer/render_process_impl.cc
index ab0a696..dd3a4d9 100644
--- a/content/renderer/render_process_impl.cc
+++ b/content/renderer/render_process_impl.cc
@@ -38,6 +38,7 @@
 #include "content/public/renderer/content_renderer_client.h"
 #include "services/network/public/cpp/features.h"
 #include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/web/blink.h"
 #include "third_party/blink/public/web/web_frame.h"
 #include "v8/include/v8.h"
 
@@ -159,17 +160,20 @@
     v8::V8::SetFlagsFromString(kWasmThreadsFlag, sizeof(kWasmThreadsFlag));
     enableSharedArrayBuffer = true;
   } else {
+    bool processIscrossOriginIsolated =
+        base::FeatureList::IsEnabled(network::features::kCrossOriginIsolated) &&
+        blink::IsCrossOriginIsolated();
     enableSharedArrayBuffer =
         base::FeatureList::IsEnabled(features::kSharedArrayBuffer) ||
-        base::FeatureList::IsEnabled(network::features::kCrossOriginIsolated);
+        processIscrossOriginIsolated;
   }
 
   if (enableSharedArrayBuffer) {
-    SetV8FlagIfFeature(features::kSharedArrayBuffer,
-                       "--harmony-sharedarraybuffer");
+    constexpr char kSABFlag[] = "--harmony-sharedarraybuffer";
+    v8::V8::SetFlagsFromString(kSABFlag, sizeof(kSABFlag));
   } else {
-    SetV8FlagIfNotFeature(features::kSharedArrayBuffer,
-                          "--no-harmony-sharedarraybuffer");
+    constexpr char kNoSABFlag[] = "--no-harmony-sharedarraybuffer";
+    v8::V8::SetFlagsFromString(kNoSABFlag, sizeof(kNoSABFlag));
   }
 
   SetV8FlagIfFeature(features::kWebAssemblyTiering, "--wasm-tier-up");
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index aa587df..5ae999d 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -1639,72 +1639,6 @@
   return gpu_->GetGpuChannel().get();
 }
 
-void RenderThreadImpl::CreateView(mojom::CreateViewParamsPtr params,
-                                  PassKey<AgentSchedulingGroup>) {
-  CompositorDependencies* compositor_deps = this;
-  is_scroll_animator_enabled_ = params->web_preferences.enable_scroll_animator;
-  // TODO(crbug.com/1111231): For as long as views are created via the
-  // `Renderer` interface (as opposed to `AgentSchedulingGroup`), we will always
-  // have *exactly one* `AgentSchedulingGroup` in the process.
-  DCHECK_EQ(agent_scheduling_groups_.size(), 1ul);
-  AgentSchedulingGroup& agent_scheduling_group =
-      *agent_scheduling_groups_.begin()->get();
-
-  RenderViewImpl::Create(agent_scheduling_group, compositor_deps,
-                         std::move(params), RenderWidget::ShowCallback(),
-                         GetWebMainThreadScheduler()->DefaultTaskRunner());
-}
-
-void RenderThreadImpl::DestroyView(
-    int32_t view_id,
-    mojom::AgentSchedulingGroup::DestroyViewCallback callback,
-    PassKey<AgentSchedulingGroup>) {
-  RenderViewImpl* view = RenderViewImpl::FromRoutingID(view_id);
-  DCHECK(view);
-
-  // This IPC can be called from re-entrant contexts. We can't destroy a
-  // RenderViewImpl while references still exist on the stack, so we dispatch a
-  // non-nestable task. This method is called exactly once by the browser
-  // process, and is used to release ownership of the corresponding
-  // RenderViewImpl instance. https://crbug.com/1000035.
-  base::ThreadTaskRunnerHandle::Get()->PostNonNestableTask(
-      FROM_HERE,
-      base::BindOnce(
-          [](RenderViewImpl* view,
-             mojom::AgentSchedulingGroup::DestroyViewCallback callback) {
-            view->Destroy();
-            std::move(callback).Run();
-          },
-          base::Unretained(view), std::move(callback)));
-}
-
-void RenderThreadImpl::CreateFrame(mojom::CreateFrameParamsPtr params,
-                                   PassKey<AgentSchedulingGroup>) {
-  CompositorDependencies* compositor_deps = this;
-  mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
-      interface_provider(
-          std::move(params->interface_bundle->interface_provider));
-  mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
-      browser_interface_broker(
-          std::move(params->interface_bundle->browser_interface_broker));
-  // TODO(crbug.com/1111231): For as long as frames are created via the
-  // `Renderer` interface (as opposed to `AgentSchedulingGroup`), we will always
-  // have *exactly one* `AgentSchedulingGroup` in the process.
-  DCHECK_EQ(agent_scheduling_groups_.size(), 1ul);
-  AgentSchedulingGroup& agent_scheduling_group =
-      *agent_scheduling_groups_.begin()->get();
-
-  RenderFrameImpl::CreateFrame(
-      agent_scheduling_group, params->routing_id, std::move(interface_provider),
-      std::move(browser_interface_broker), params->previous_routing_id,
-      params->opener_frame_token, params->parent_routing_id,
-      params->previous_sibling_routing_id, params->frame_token,
-      params->devtools_frame_token, params->replication_state, compositor_deps,
-      std::move(params->widget_params),
-      std::move(params->frame_owner_properties),
-      params->has_committed_real_load);
-}
-
 void RenderThreadImpl::CreateAgentSchedulingGroup(
     mojo::PendingRemote<mojom::AgentSchedulingGroupHost>
         agent_scheduling_group_host,
@@ -1724,28 +1658,6 @@
       std::move(agent_scheduling_group)));
 }
 
-void RenderThreadImpl::CreateFrameProxy(
-    int32_t routing_id,
-    int32_t render_view_routing_id,
-    const base::Optional<base::UnguessableToken>& opener_frame_token,
-    int32_t parent_routing_id,
-    const FrameReplicationState& replicated_state,
-    const base::UnguessableToken& frame_token,
-    const base::UnguessableToken& devtools_frame_token,
-    PassKey<AgentSchedulingGroup>) {
-  // TODO(crbug.com/1111231): For as long as frame proxies are created via the
-  // `Renderer` interface (as opposed to `AgentSchedulingGroup`), we will always
-  // have *exactly one* `AgentSchedulingGroup` in the process.
-  DCHECK_EQ(agent_scheduling_groups_.size(), 1ul);
-  AgentSchedulingGroup& agent_scheduling_group =
-      *agent_scheduling_groups_.begin()->get();
-
-  RenderFrameProxy::CreateFrameProxy(agent_scheduling_group, routing_id,
-                                     render_view_routing_id, opener_frame_token,
-                                     parent_routing_id, replicated_state,
-                                     frame_token, devtools_frame_token);
-}
-
 void RenderThreadImpl::OnNetworkConnectionChanged(
     net::NetworkChangeNotifier::ConnectionType type,
     double max_bandwidth_mbps) {
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index a2427ff6..b9897506 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -207,24 +207,6 @@
   // viz::mojom::CompositingModeWatcher implementation.
   void CompositingModeFallbackToSoftware() override;
 
-  // Formerly in mojom::Renderer (moved to mojom::AgentSchedulingGroup):
-  void CreateView(mojom::CreateViewParamsPtr params,
-                  util::PassKey<AgentSchedulingGroup>);
-  void DestroyView(int32_t view_id,
-                   mojom::AgentSchedulingGroup::DestroyViewCallback,
-                   util::PassKey<AgentSchedulingGroup>);
-  void CreateFrame(mojom::CreateFrameParamsPtr params,
-                   util::PassKey<AgentSchedulingGroup>);
-  void CreateFrameProxy(
-      int32_t routing_id,
-      int32_t render_view_routing_id,
-      const base::Optional<base::UnguessableToken>& opener_frame_token,
-      int32_t parent_routing_id,
-      const FrameReplicationState& replicated_state,
-      const base::UnguessableToken& frame_token,
-      const base::UnguessableToken& devtools_frame_token,
-      util::PassKey<AgentSchedulingGroup>);
-
   // Whether gpu compositing is being used or is disabled for software
   // compositing. Clients of the compositor should give resources that match
   // the appropriate mode.
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index b757beb23..85b88eb 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -751,11 +751,7 @@
     EXPECT_EQ(widget_screen_rect, gfx::Rect(popup->ViewRect()));
     EXPECT_EQ(screen_rect, gfx::Rect(popup->GetScreenInfo().rect));
 
-    // Close and destroy the widget.
-    {
-      WidgetMsg_Close msg(popup_widget->routing_id());
-      popup_widget->OnMessageReceived(msg);
-    }
+    popup->GetClientForTesting()->BrowserClosedIpcChannelForPopupWidget();
   }
 
   // Enable device emulation on the parent widget.
@@ -814,11 +810,7 @@
     EXPECT_EQ(emulated_widget_rect,
               gfx::Rect(main_widget()->GetWebWidget()->GetScreenInfo().rect));
 
-    // Close and destroy the widget.
-    {
-      WidgetMsg_Close msg(popup_widget->routing_id());
-      popup_widget->OnMessageReceived(msg);
-    }
+    popup->GetClientForTesting()->BrowserClosedIpcChannelForPopupWidget();
   }
 }
 
@@ -1001,7 +993,7 @@
 }
 
 TEST_F(RenderViewImplTest, BeginNavigationHandlesAllTopLevel) {
-  blink::mojom::RendererPreferences prefs = view()->renderer_preferences();
+  blink::RendererPreferences prefs = view()->renderer_preferences();
   prefs.browser_handles_all_top_level_requests = true;
   view()->OnSetRendererPrefs(prefs);
 
@@ -1264,18 +1256,26 @@
   widget_params->routing_id = kProxyRoutingId + 2;
   widget_params->visual_properties = test_visual_properties;
 
+  mojo::AssociatedRemote<blink::mojom::Widget> blink_widget;
+  mojo::PendingAssociatedReceiver<blink::mojom::Widget> blink_widget_receiver =
+      blink_widget.BindNewEndpointAndPassDedicatedReceiver();
+
+  mojo::AssociatedRemote<blink::mojom::WidgetHost> blink_widget_host;
+  ignore_result(blink_widget_host.BindNewEndpointAndPassDedicatedReceiver());
+
   mojo::AssociatedRemote<blink::mojom::FrameWidget> blink_frame_widget;
   mojo::PendingAssociatedReceiver<blink::mojom::FrameWidget>
       blink_frame_widget_receiver =
           blink_frame_widget.BindNewEndpointAndPassDedicatedReceiver();
 
   mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> blink_frame_widget_host;
-  mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetHost>
-      blink_frame_widget_host_receiver =
-          blink_frame_widget_host.BindNewEndpointAndPassDedicatedReceiver();
+  ignore_result(
+      blink_frame_widget_host.BindNewEndpointAndPassDedicatedReceiver());
 
   widget_params->frame_widget = std::move(blink_frame_widget_receiver);
   widget_params->frame_widget_host = blink_frame_widget_host.Unbind();
+  widget_params->widget = std::move(blink_widget_receiver);
+  widget_params->widget_host = blink_widget_host.Unbind();
 
   RenderFrameImpl::CreateFrame(
       *agent_scheduling_group_, routing_id, std::move(stub_interface_provider),
diff --git a/content/renderer/render_view_fuchsia.cc b/content/renderer/render_view_fuchsia.cc
index 383a88cb..64b0ee0 100644
--- a/content/renderer/render_view_fuchsia.cc
+++ b/content/renderer/render_view_fuchsia.cc
@@ -12,7 +12,7 @@
 namespace {
 
 SkFontHinting RendererPreferencesToSkiaHinting(
-    const blink::mojom::RendererPreferences& prefs) {
+    const blink::RendererPreferences& prefs) {
   switch (prefs.hinting) {
     case gfx::FontRenderParams::HINTING_NONE:
       return SkFontHinting::kNone;
@@ -31,7 +31,7 @@
 }  // namespace
 
 void RenderViewImpl::UpdateFontRenderingFromRendererPrefs() {
-  const blink::mojom::RendererPreferences& prefs = renderer_preferences_;
+  const blink::RendererPreferences& prefs = renderer_preferences_;
   blink::WebFontRenderStyle::SetHinting(
       RendererPreferencesToSkiaHinting(prefs));
   blink::WebFontRenderStyle::SetAutoHint(prefs.use_autohinter);
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index b058da6..54838ac2 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -172,7 +172,7 @@
   if (params->window_was_created_with_opener)
     GetWebView()->SetOpenedByDOM();
 
-  OnSetRendererPrefs(*params->renderer_preferences);
+  OnSetRendererPrefs(params->renderer_preferences);
 
   GetContentClient()->renderer()->RenderViewCreated(this);
 
@@ -480,7 +480,7 @@
   DCHECK_EQ(GetRoutingID(), creator_frame->render_view()->GetRoutingID());
 
   view_params->window_was_created_with_opener = true;
-  view_params->renderer_preferences = renderer_preferences_.Clone();
+  view_params->renderer_preferences = renderer_preferences_;
   view_params->web_preferences = webview_->GetWebPreferences();
   view_params->view_id = reply->route_id;
   view_params->main_frame_frame_token = reply->main_frame_frame_token;
@@ -541,12 +541,20 @@
       blink_widget_host_receiver =
           blink_widget_host.InitWithNewEndpointAndPassReceiver();
 
+  mojo::PendingAssociatedRemote<blink::mojom::PopupWidgetHost>
+      blink_popup_widget_host;
+  mojo::PendingAssociatedReceiver<blink::mojom::PopupWidgetHost>
+      blink_popup_widget_host_receiver =
+          blink_popup_widget_host.InitWithNewEndpointAndPassReceiver();
+
   // Do a synchronous IPC to obtain a routing ID.
   int32_t widget_routing_id = MSG_ROUTING_NONE;
   bool success =
-      RenderFrameImpl::FromWebFrame(creator)->GetFrameHost()->CreateNewWidget(
-          std::move(blink_widget_host_receiver), std::move(blink_widget),
-          &widget_routing_id);
+      RenderFrameImpl::FromWebFrame(creator)
+          ->GetFrameHost()
+          ->CreateNewPopupWidget(std::move(blink_popup_widget_host_receiver),
+                                 std::move(blink_widget_host_receiver),
+                                 std::move(blink_widget), &widget_routing_id);
   if (!success) {
     // When the renderer is being killed the mojo message will fail.
     return nullptr;
@@ -564,9 +572,9 @@
 
   // The returned WebPagePopup is self-referencing, so the pointer here is not
   // an owning pointer. It is de-referenced by calling Close().
-  blink::WebPagePopup* popup_web_widget =
-      blink::WebPagePopup::Create(popup_widget, std::move(blink_widget_host),
-                                  std::move(blink_widget_receiver));
+  blink::WebPagePopup* popup_web_widget = blink::WebPagePopup::Create(
+      popup_widget, std::move(blink_popup_widget_host),
+      std::move(blink_widget_host), std::move(blink_widget_receiver));
 
   // Adds a self-reference on the |popup_widget| so it will not be destroyed
   // when leaving scope. The WebPagePopup takes responsibility for Close()ing
@@ -753,13 +761,13 @@
 }
 
 void RenderViewImpl::OnSetRendererPrefs(
-    const blink::mojom::RendererPreferences& renderer_prefs) {
+    const blink::RendererPreferences& renderer_prefs) {
   std::string old_accept_languages = renderer_preferences_.accept_languages;
 
   renderer_preferences_ = renderer_prefs;
 
   for (auto& watcher : renderer_preference_watchers_)
-    watcher->NotifyUpdate(renderer_prefs.Clone());
+    watcher->NotifyUpdate(renderer_prefs);
 
   UpdateFontRenderingFromRendererPrefs();
   UpdateThemePrefs();
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index f65e67d..2873d02 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -42,9 +42,9 @@
 #include "third_party/blink/public/common/dom_storage/session_storage_namespace_id.h"
 #include "third_party/blink/public/common/feature_policy/feature_policy_features.h"
 #include "third_party/blink/public/common/input/web_input_event.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
 #include "third_party/blink/public/mojom/renderer_preference_watcher.mojom.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "third_party/blink/public/platform/web_security_origin.h"
 #include "third_party/blink/public/web/web_ax_object.h"
 #include "third_party/blink/public/web/web_console_message.h"
@@ -140,7 +140,7 @@
   // or not.
   bool widgets_never_composited() const { return widgets_never_composited_; }
 
-  const blink::mojom::RendererPreferences& renderer_preferences() const {
+  const blink::RendererPreferences& renderer_preferences() const {
     return renderer_preferences_;
   }
 
@@ -173,7 +173,7 @@
   unsigned GetLocalSessionHistoryLengthForTesting() const;
 
   // Registers a watcher to observe changes in the
-  // blink::mojom::RendererPreferences.
+  // blink::RendererPreferences.
   void RegisterRendererPreferenceWatcher(
       mojo::PendingRemote<blink::mojom::RendererPreferenceWatcher> watcher);
 
@@ -329,8 +329,7 @@
       blink::WebNavigationPolicy policy);
 
   void OnMoveOrResizeStarted();
-  void OnSetRendererPrefs(
-      const blink::mojom::RendererPreferences& renderer_prefs);
+  void OnSetRendererPrefs(const blink::RendererPreferences& renderer_prefs);
 
   // Misc private functions ----------------------------------------------------
 
@@ -391,7 +390,7 @@
 
   // Settings ------------------------------------------------------------------
 
-  blink::mojom::RendererPreferences renderer_preferences_;
+  blink::RendererPreferences renderer_preferences_;
   // These are observing changes in |renderer_preferences_|. This is used for
   // keeping WorkerFetchContext in sync.
   mojo::RemoteSet<blink::mojom::RendererPreferenceWatcher>
diff --git a/content/renderer/render_view_linux.cc b/content/renderer/render_view_linux.cc
index 64adc50..108619c9 100644
--- a/content/renderer/render_view_linux.cc
+++ b/content/renderer/render_view_linux.cc
@@ -5,7 +5,7 @@
 #include "content/renderer/render_view_impl.h"
 
 #include "skia/ext/legacy_display_globals.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/platform/web_font_render_style.h"
 #include "ui/gfx/font_render_params.h"
 
@@ -16,7 +16,7 @@
 namespace {
 
 SkFontHinting RendererPreferencesToSkiaHinting(
-    const blink::mojom::RendererPreferences& prefs) {
+    const blink::RendererPreferences& prefs) {
   if (!prefs.should_antialias_text) {
     // When anti-aliasing is off, GTK maps all non-zero hinting settings to
     // 'Normal' hinting so we do the same. Otherwise, folks who have 'Slight'
@@ -52,7 +52,7 @@
 }  // namespace
 
 void RenderViewImpl::UpdateFontRenderingFromRendererPrefs() {
-  const blink::mojom::RendererPreferences& prefs = renderer_preferences_;
+  const blink::RendererPreferences& prefs = renderer_preferences_;
   WebFontRenderStyle::SetHinting(RendererPreferencesToSkiaHinting(prefs));
   WebFontRenderStyle::SetAutoHint(prefs.use_autohinter);
   WebFontRenderStyle::SetUseBitmaps(prefs.use_bitmaps);
diff --git a/content/renderer/render_view_win.cc b/content/renderer/render_view_win.cc
index dd0ae6b..c55d5de 100644
--- a/content/renderer/render_view_win.cc
+++ b/content/renderer/render_view_win.cc
@@ -5,7 +5,7 @@
 #include "content/child/webthemeengine_impl_default.h"
 #include "content/renderer/render_view_impl.h"
 #include "skia/ext/legacy_display_globals.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/web/win/web_font_rendering.h"
 #include "ui/gfx/font_render_params.h"
 
@@ -14,7 +14,7 @@
 namespace content {
 
 void RenderViewImpl::UpdateFontRenderingFromRendererPrefs() {
-  const blink::mojom::RendererPreferences& prefs = renderer_preferences_;
+  const blink::RendererPreferences& prefs = renderer_preferences_;
 
   // Cache the system font metrics in blink.
   blink::WebFontRendering::SetMenuFontMetrics(
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index bfed755..e19c07f 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -208,7 +208,6 @@
 
   bool handled = false;
   IPC_BEGIN_MESSAGE_MAP(RenderWidget, message)
-    IPC_MESSAGE_HANDLER(WidgetMsg_Close, OnClose)
     IPC_MESSAGE_HANDLER(WidgetMsg_SetBounds_ACK, OnRequestSetBoundsAck)
     IPC_MESSAGE_HANDLER(DragMsg_TargetDragEnter, OnDragTargetDragEnter)
     IPC_MESSAGE_UNHANDLED(handled = false)
@@ -229,7 +228,7 @@
   return agent_scheduling_group_.Send(message);
 }
 
-void RenderWidget::OnClose() {
+void RenderWidget::BrowserClosedIpcChannelForPopupWidget() {
   DCHECK(for_popup_);
 
   Close(base::WrapUnique(this));
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index 5f2b9ee..898f099 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -137,8 +137,8 @@
   // Creates a RenderWidget for a popup. This is separate from CreateForFrame()
   // because popups do not not need to be faked out.
   // A RenderWidget popup is owned by the browser process. The object will be
-  // destroyed by the WidgetMsg_Close message. The object can request its own
-  // destruction via ClosePopupWidgetSoon().
+  // destroyed when the blink::mojom::WidgetHost channel is disconnected. The
+  // object can request its own destruction via ClosePopupWidgetSoon().
   static RenderWidget* CreateForPopup(
       AgentSchedulingGroup& agent_scheduling_group,
       int32_t widget_routing_id,
@@ -197,6 +197,7 @@
   void ScheduleAnimation() override;
   void CloseWidgetSoon() override;
   void ClosePopupWidgetSoon() override;
+  void BrowserClosedIpcChannelForPopupWidget() override;
   void Show(blink::WebNavigationPolicy) override;
   void SetWindowRect(const gfx::Rect&) override;
   viz::FrameSinkId GetFrameSinkId() override;
@@ -253,7 +254,6 @@
                               int widget_routing_id);
 
   // RenderWidget IPC message handlers.
-  void OnClose();
   void OnRequestSetBoundsAck();
 
   void OnDragTargetDragEnter(
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index 0337fdf..f53f8fc 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -94,7 +94,7 @@
     const GURL& service_worker_scope,
     const GURL& script_url,
     bool is_starting_installed_worker,
-    blink::mojom::RendererPreferencesPtr renderer_preferences,
+    const blink::RendererPreferences& renderer_preferences,
     mojo::PendingReceiver<blink::mojom::ServiceWorker> service_worker_receiver,
     mojo::PendingReceiver<blink::mojom::ControllerServiceWorker>
         controller_receiver,
@@ -117,7 +117,7 @@
       script_url_(script_url),
       is_starting_installed_worker_(is_starting_installed_worker),
       script_url_to_skip_throttling_(script_url_to_skip_throttling),
-      renderer_preferences_(std::move(renderer_preferences)),
+      renderer_preferences_(renderer_preferences),
       preference_watcher_receiver_(std::move(preference_watcher_receiver)),
       initiator_thread_task_runner_(std::move(initiator_thread_task_runner)),
       proxy_(nullptr),
@@ -377,7 +377,7 @@
           service_worker_provider_info_->script_loader_factory_remote));
 
   return base::MakeRefCounted<ServiceWorkerFetchContextImpl>(
-      *renderer_preferences_, script_url_, loader_factories_->PassInterface(),
+      renderer_preferences_, script_url_, loader_factories_->PassInterface(),
       std::move(pending_script_loader_factory), script_url_to_skip_throttling_,
       GetContentClient()->renderer()->CreateURLLoaderThrottleProvider(
           URLLoaderThrottleProviderType::kWorker),
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h
index 7ad6902c..8e2c21f 100644
--- a/content/renderer/service_worker/service_worker_context_client.h
+++ b/content/renderer/service_worker/service_worker_context_client.h
@@ -94,7 +94,7 @@
       const GURL& service_worker_scope,
       const GURL& script_url,
       bool is_starting_installed_worker,
-      blink::mojom::RendererPreferencesPtr renderer_preferences,
+      const blink::RendererPreferences& renderer_preferences,
       mojo::PendingReceiver<blink::mojom::ServiceWorker>
           service_worker_receiver,
       mojo::PendingReceiver<blink::mojom::ControllerServiceWorker>
@@ -222,7 +222,7 @@
   // See comments in EmbeddedWorkerStartParams::script_url_to_skip_throttling.
   const GURL script_url_to_skip_throttling_;
 
-  blink::mojom::RendererPreferencesPtr renderer_preferences_;
+  blink::RendererPreferences renderer_preferences_;
   // Passed on creation of ServiceWorkerFetchContext.
   mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
       preference_watcher_receiver_;
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.cc b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
index 1a14e13c..7ad2dd9 100644
--- a/content/renderer/service_worker/service_worker_fetch_context_impl.cc
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
@@ -21,7 +21,7 @@
 namespace content {
 
 ServiceWorkerFetchContextImpl::ServiceWorkerFetchContextImpl(
-    const blink::mojom::RendererPreferences& renderer_preferences,
+    const blink::RendererPreferences& renderer_preferences,
     const GURL& worker_script_url,
     std::unique_ptr<network::PendingSharedURLLoaderFactory>
         pending_url_loader_factory,
@@ -192,11 +192,11 @@
 }
 
 void ServiceWorkerFetchContextImpl::NotifyUpdate(
-    blink::mojom::RendererPreferencesPtr new_prefs) {
+    const blink::RendererPreferences& new_prefs) {
   DCHECK(accept_languages_watcher_);
-  if (renderer_preferences_.accept_languages != new_prefs->accept_languages)
+  if (renderer_preferences_.accept_languages != new_prefs.accept_languages)
     accept_languages_watcher_->NotifyUpdate();
-  renderer_preferences_ = *new_prefs;
+  renderer_preferences_ = new_prefs;
 }
 
 blink::WebString ServiceWorkerFetchContextImpl::GetAcceptLanguages() const {
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.h b/content/renderer/service_worker/service_worker_fetch_context_impl.h
index d07041e..a8f8543 100644
--- a/content/renderer/service_worker/service_worker_fetch_context_impl.h
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl.h
@@ -9,8 +9,8 @@
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/mojom/renderer_preference_watcher.mojom.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker.mojom-forward.h"
 #include "third_party/blink/public/mojom/worker/subresource_loader_updater.mojom.h"
 #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_fetch_context.h"
@@ -41,7 +41,7 @@
   // browser process so that it doesn't need to be throttled in the renderer
   // again.
   ServiceWorkerFetchContextImpl(
-      const blink::mojom::RendererPreferences& renderer_preferences,
+      const blink::RendererPreferences& renderer_preferences,
       const GURL& worker_script_url,
       std::unique_ptr<network::PendingSharedURLLoaderFactory>
           pending_url_loader_factory,
@@ -92,9 +92,9 @@
   ~ServiceWorkerFetchContextImpl() override;
 
   // Implements blink::mojom::RendererPreferenceWatcher.
-  void NotifyUpdate(blink::mojom::RendererPreferencesPtr new_prefs) override;
+  void NotifyUpdate(const blink::RendererPreferences& new_prefs) override;
 
-  blink::mojom::RendererPreferences renderer_preferences_;
+  blink::RendererPreferences renderer_preferences_;
   const GURL worker_script_url_;
   // Consumed on the worker thread to create |web_url_loader_factory_|.
   std::unique_ptr<network::PendingSharedURLLoaderFactory>
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl_unittest.cc b/content/renderer/service_worker/service_worker_fetch_context_impl_unittest.cc
index 3bedd8a0..34bbca3 100644
--- a/content/renderer/service_worker/service_worker_fetch_context_impl_unittest.cc
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl_unittest.cc
@@ -8,6 +8,7 @@
 #include "content/public/renderer/websocket_handshake_throttle_provider.h"
 #include "content/renderer/loader/request_extra_data.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 
 namespace content {
 
@@ -42,7 +43,7 @@
   const GURL kScriptUrl("https://example.com/main.js");
   const GURL kScriptUrlToSkipThrottling("https://example.com/skip.js");
   auto context = base::MakeRefCounted<ServiceWorkerFetchContextImpl>(
-      blink::mojom::RendererPreferences(), kScriptUrl,
+      blink::RendererPreferences(), kScriptUrl,
       /*pending_url_loader_factory=*/nullptr,
       /*pending_script_loader_factory=*/nullptr, kScriptUrlToSkipThrottling,
       std::make_unique<FakeURLLoaderThrottleProvider>(),
diff --git a/content/renderer/worker/dedicated_worker_host_factory_client.cc b/content/renderer/worker/dedicated_worker_host_factory_client.cc
index b1e96b4..3433c691 100644
--- a/content/renderer/worker/dedicated_worker_host_factory_client.cc
+++ b/content/renderer/worker/dedicated_worker_host_factory_client.cc
@@ -89,7 +89,7 @@
 
 scoped_refptr<WebWorkerFetchContextImpl>
 DedicatedWorkerHostFactoryClient::CreateWorkerFetchContext(
-    blink::mojom::RendererPreferences renderer_preference,
+    const blink::RendererPreferences& renderer_preference,
     mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
         watcher_receiver,
     mojo::PendingRemote<blink::mojom::ResourceLoadInfoNotifier>
@@ -98,8 +98,8 @@
   DCHECK(subresource_loader_factory_bundle_);
   scoped_refptr<WebWorkerFetchContextImpl> worker_fetch_context =
       WebWorkerFetchContextImpl::Create(
-          service_worker_provider_context_.get(),
-          std::move(renderer_preference), std::move(watcher_receiver),
+          service_worker_provider_context_.get(), renderer_preference,
+          std::move(watcher_receiver),
           subresource_loader_factory_bundle_->Clone(),
           subresource_loader_factory_bundle_->CloneWithoutAppCacheFactory(),
           std::move(pending_subresource_loader_updater_),
diff --git a/content/renderer/worker/dedicated_worker_host_factory_client.h b/content/renderer/worker/dedicated_worker_host_factory_client.h
index 315b658..e9c906e 100644
--- a/content/renderer/worker/dedicated_worker_host_factory_client.h
+++ b/content/renderer/worker/dedicated_worker_host_factory_client.h
@@ -10,9 +10,9 @@
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/mojom/loader/resource_load_info_notifier.mojom.h"
 #include "third_party/blink/public/mojom/renderer_preference_watcher.mojom-forward.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom-forward.h"
 #include "third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom.h"
 #include "third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h"
 
@@ -58,7 +58,7 @@
       scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
 
   scoped_refptr<WebWorkerFetchContextImpl> CreateWorkerFetchContext(
-      blink::mojom::RendererPreferences renderer_preference,
+      const blink::RendererPreferences& renderer_preference,
       mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
           watcher_receiver,
       mojo::PendingRemote<blink::mojom::ResourceLoadInfoNotifier>
diff --git a/content/renderer/worker/embedded_shared_worker_stub.cc b/content/renderer/worker/embedded_shared_worker_stub.cc
index 154e5ce..d4eaf8d 100644
--- a/content/renderer/worker/embedded_shared_worker_stub.cc
+++ b/content/renderer/worker/embedded_shared_worker_stub.cc
@@ -38,7 +38,7 @@
     const blink::UserAgentMetadata& ua_metadata,
     bool pause_on_start,
     const base::UnguessableToken& devtools_worker_token,
-    const blink::mojom::RendererPreferences& renderer_preferences,
+    const blink::RendererPreferences& renderer_preferences,
     mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
         preference_watcher_receiver,
     mojo::PendingRemote<blink::mojom::WorkerContentSettingsProxy>
@@ -141,7 +141,7 @@
 scoped_refptr<blink::WebWorkerFetchContext>
 EmbeddedSharedWorkerStub::CreateWorkerFetchContext(
     const GURL& url,
-    const blink::mojom::RendererPreferences& renderer_preferences,
+    const blink::RendererPreferences& renderer_preferences,
     mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
         preference_watcher_receiver,
     const std::vector<std::string>& cors_exempt_header_list) {
@@ -154,8 +154,7 @@
   // |pending_resource_load_info_notifier| are not used for shared workers.
   scoped_refptr<WebWorkerFetchContextImpl> worker_fetch_context =
       WebWorkerFetchContextImpl::Create(
-          service_worker_provider_context_.get(),
-          std::move(renderer_preferences),
+          service_worker_provider_context_.get(), renderer_preferences,
           std::move(preference_watcher_receiver),
           subresource_loader_factory_bundle_->Clone(),
           std::move(fallback_factory),
diff --git a/content/renderer/worker/embedded_shared_worker_stub.h b/content/renderer/worker/embedded_shared_worker_stub.h
index 81d768d..acb041a0 100644
--- a/content/renderer/worker/embedded_shared_worker_stub.h
+++ b/content/renderer/worker/embedded_shared_worker_stub.h
@@ -17,12 +17,12 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
 #include "services/network/public/mojom/url_loader_factory.mojom-forward.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/common/tokens/tokens.h"
 #include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
 #include "third_party/blink/public/mojom/browser_interface_broker.mojom-forward.h"
 #include "third_party/blink/public/mojom/devtools/devtools_agent.mojom-forward.h"
 #include "third_party/blink/public/mojom/renderer_preference_watcher.mojom-forward.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom-forward.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom-forward.h"
 #include "third_party/blink/public/mojom/worker/shared_worker.mojom.h"
@@ -64,7 +64,7 @@
       const blink::UserAgentMetadata& ua_metadata,
       bool pause_on_start,
       const base::UnguessableToken& devtools_worker_token,
-      const blink::mojom::RendererPreferences& renderer_preferences,
+      const blink::RendererPreferences& renderer_preferences,
       mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
           preference_watcher_receiver,
       mojo::PendingRemote<blink::mojom::WorkerContentSettingsProxy>
@@ -96,7 +96,7 @@
 
   scoped_refptr<blink::WebWorkerFetchContext> CreateWorkerFetchContext(
       const GURL& url,
-      const blink::mojom::RendererPreferences& renderer_preferences,
+      const blink::RendererPreferences& renderer_preferences,
       mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
           preference_watcher_receiver,
       const std::vector<std::string>& cors_exempt_header_list);
diff --git a/content/renderer/worker/shared_worker_factory_impl.cc b/content/renderer/worker/shared_worker_factory_impl.cc
index d67764c..9369b9c 100644
--- a/content/renderer/worker/shared_worker_factory_impl.cc
+++ b/content/renderer/worker/shared_worker_factory_impl.cc
@@ -31,7 +31,7 @@
     const blink::UserAgentMetadata& ua_metadata,
     bool pause_on_start,
     const base::UnguessableToken& devtools_worker_token,
-    blink::mojom::RendererPreferencesPtr renderer_preferences,
+    const blink::RendererPreferences& renderer_preferences,
     mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
         preference_watcher_receiver,
     mojo::PendingRemote<blink::mojom::WorkerContentSettingsProxy>
@@ -51,7 +51,7 @@
   // Bound to the lifetime of the underlying blink::WebSharedWorker instance.
   new EmbeddedSharedWorkerStub(
       std::move(info), token, constructor_origin, user_agent, ua_metadata,
-      pause_on_start, devtools_worker_token, *renderer_preferences,
+      pause_on_start, devtools_worker_token, renderer_preferences,
       std::move(preference_watcher_receiver), std::move(content_settings),
       std::move(service_worker_container_info),
       appcache_host_id.value_or(base::UnguessableToken()),
diff --git a/content/renderer/worker/shared_worker_factory_impl.h b/content/renderer/worker/shared_worker_factory_impl.h
index bf085b0..7206766 100644
--- a/content/renderer/worker/shared_worker_factory_impl.h
+++ b/content/renderer/worker/shared_worker_factory_impl.h
@@ -9,6 +9,7 @@
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom-forward.h"
 #include "third_party/blink/public/mojom/worker/shared_worker_factory.mojom.h"
 
@@ -35,7 +36,7 @@
       const blink::UserAgentMetadata& ua_metadata,
       bool pause_on_start,
       const base::UnguessableToken& devtools_worker_token,
-      blink::mojom::RendererPreferencesPtr renderer_preferences,
+      const blink::RendererPreferences& renderer_preferences,
       mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
           preference_watcher_receiver,
       mojo::PendingRemote<blink::mojom::WorkerContentSettingsProxy>
diff --git a/content/shell/browser/shell.cc b/content/shell/browser/shell.cc
index 3731fda..19993bb 100644
--- a/content/shell/browser/shell.cc
+++ b/content/shell/browser/shell.cc
@@ -40,7 +40,7 @@
 #include "content/shell/common/shell_switches.h"
 #include "media/media_buildflags.h"
 #include "third_party/blink/public/common/peerconnection/webrtc_ip_handling_policy.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 
 namespace content {
 
diff --git a/content/test/content_test_suite.cc b/content/test/content_test_suite.cc
index 89850063..22348bdc 100644
--- a/content/test/content_test_suite.cc
+++ b/content/test/content_test_suite.cc
@@ -90,9 +90,21 @@
         gpu_feature_info->disabled_extensions);
     gl::init::InitializeExtensionSettingsOneOffPlatform();
   }
-  testing::TestEventListeners& listeners =
-      testing::UnitTest::GetInstance()->listeners();
-  listeners.Append(new TestInitializationListener);
+  // TestEventListeners repeater event propagation is disabled in death test
+  // child process.
+  if (command_line->HasSwitch("gtest_internal_run_death_test")) {
+    test_content_client_initializer_ =
+        std::make_unique<TestContentClientInitializer>();
+  } else {
+    testing::TestEventListeners& listeners =
+        testing::UnitTest::GetInstance()->listeners();
+    listeners.Append(new TestInitializationListener);
+  }
+}
+
+void ContentTestSuite::Shutdown() {
+  test_content_client_initializer_.reset();
+  ContentTestSuiteBase::Shutdown();
 }
 
 }  // namespace content
diff --git a/content/test/content_test_suite.h b/content/test/content_test_suite.h
index f17b155..c85f818e 100644
--- a/content/test/content_test_suite.h
+++ b/content/test/content_test_suite.h
@@ -19,6 +19,8 @@
 
 namespace content {
 
+class TestContentClientInitializer;
+
 class ContentTestSuite : public ContentTestSuiteBase {
  public:
   ContentTestSuite(int argc, char** argv);
@@ -26,8 +28,11 @@
 
  protected:
   void Initialize() override;
+  void Shutdown() override;
 
  private:
+  std::unique_ptr<TestContentClientInitializer>
+      test_content_client_initializer_;
   base::TestDiscardableMemoryAllocator discardable_memory_allocator_;
 
 #if defined(OS_WIN)
diff --git a/content/test/gpu/gpu_tests/gpu_integration_test.py b/content/test/gpu/gpu_tests/gpu_integration_test.py
index d206a54..5050942e 100644
--- a/content/test/gpu/gpu_tests/gpu_integration_test.py
+++ b/content/test/gpu/gpu_tests/gpu_integration_test.py
@@ -563,6 +563,26 @@
         'qualcomm-adreno-(tm)-430',  # android-nexus-6p
         'qualcomm-adreno-(tm)-540',  # android-pixel-2
         'nvidia-nvidia-tegra',  # android-nexus-9 and android-shield-android-tv
+        'vmware',  # VMs
+        'vmware,-0x1050',  # ChromeOS VMs
+        # Fuchsia VMs
+        ('google-angle-(vulkan-1.1.0(swiftshader-device-('
+         'llvm-7.0.1)-(0x0000c0de)))'),
+        # These browsers are analogous to a particular OS, and specifying the
+        # OS name is clearer.
+        'cros-chrome',  # ChromeOS
+        'web-engine-shell',  # Fuchsia
+        # WebGL version is already handled by having expectations in separate
+        # files.
+        # TODO(crbug.com/1140283): Consider merging the two files and using
+        # these tags once stale expectations are removed and the files are more
+        # reasonably sized.
+        'webgl-version-1',
+        'webgl-version-2',
+        # GPU tests are always run in remote mode on the bots, and it shouldn't
+        # make a difference to these tests anyways.
+        'chromeos-local',
+        'chromeos-remote',
     ]
 
 
diff --git a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
index 25046f3..b3eabe0 100644
--- a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
@@ -1,10 +1,12 @@
 # BEGIN TAG HEADER (autogenerated, see validate_tag_consistency.py)
 # OS
-# tags: [ android android-pie
+# tags: [ android android-lollipop android-marshmallow android-nougat
+#             android-pie
 #         chromeos
 #         fuchsia
-#         linux
-#         mac catalina lion highsierra mojave mountainlion sierra
+#         linux ubuntu
+#         mac bigsur catalina lion highsierra mac-10.12 mojave mountainlion
+#             sierra
 #         win win7 win8 win10 ]
 # Devices
 # tags: [ android-nexus-5 android-nexus-5x android-nexus-6 android-nexus-6p
@@ -21,10 +23,11 @@
 # GPU
 # tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f
 #         apple apple-apple-a12z
+#         arm
+#         google google-0xffff
 #         intel intel-0xa2e intel-0xd26 intel-0xa011 intel-0x3e92 intel-0x5912
 #         nvidia nvidia-0xfe9 nvidia-0x1cb3 nvidia-0x2184
-#         qualcomm
-#         google-0xffff ]
+#         qualcomm ]
 # Decoder
 # tags: [ passthrough no-passthrough ]
 # ANGLE Backend
diff --git a/content/test/gpu/gpu_tests/test_expectations/depth_capture_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/depth_capture_expectations.txt
index 90adfdca..5d095af6 100644
--- a/content/test/gpu/gpu_tests/test_expectations/depth_capture_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/depth_capture_expectations.txt
@@ -1,10 +1,12 @@
 # BEGIN TAG HEADER (autogenerated, see validate_tag_consistency.py)
 # OS
-# tags: [ android android-pie
+# tags: [ android android-lollipop android-marshmallow android-nougat
+#             android-pie
 #         chromeos
 #         fuchsia
-#         linux
-#         mac catalina lion highsierra mojave mountainlion sierra
+#         linux ubuntu
+#         mac bigsur catalina lion highsierra mac-10.12 mojave mountainlion
+#             sierra
 #         win win7 win8 win10 ]
 # Devices
 # tags: [ android-nexus-5 android-nexus-5x android-nexus-6 android-nexus-6p
@@ -21,10 +23,11 @@
 # GPU
 # tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f
 #         apple apple-apple-a12z
+#         arm
+#         google google-0xffff
 #         intel intel-0xa2e intel-0xd26 intel-0xa011 intel-0x3e92 intel-0x5912
 #         nvidia nvidia-0xfe9 nvidia-0x1cb3 nvidia-0x2184
-#         qualcomm
-#         google-0xffff ]
+#         qualcomm ]
 # Decoder
 # tags: [ passthrough no-passthrough ]
 # ANGLE Backend
diff --git a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt
index 77397cd..9483a2d 100644
--- a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt
@@ -1,10 +1,12 @@
 # BEGIN TAG HEADER (autogenerated, see validate_tag_consistency.py)
 # OS
-# tags: [ android android-pie
+# tags: [ android android-lollipop android-marshmallow android-nougat
+#             android-pie
 #         chromeos
 #         fuchsia
-#         linux
-#         mac catalina lion highsierra mojave mountainlion sierra
+#         linux ubuntu
+#         mac bigsur catalina lion highsierra mac-10.12 mojave mountainlion
+#             sierra
 #         win win7 win8 win10 ]
 # Devices
 # tags: [ android-nexus-5 android-nexus-5x android-nexus-6 android-nexus-6p
@@ -21,10 +23,11 @@
 # GPU
 # tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f
 #         apple apple-apple-a12z
+#         arm
+#         google google-0xffff
 #         intel intel-0xa2e intel-0xd26 intel-0xa011 intel-0x3e92 intel-0x5912
 #         nvidia nvidia-0xfe9 nvidia-0x1cb3 nvidia-0x2184
-#         qualcomm
-#         google-0xffff ]
+#         qualcomm ]
 # Decoder
 # tags: [ passthrough no-passthrough ]
 # ANGLE Backend
diff --git a/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt
index 8804799..59259e05 100644
--- a/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt
@@ -1,10 +1,12 @@
 # BEGIN TAG HEADER (autogenerated, see validate_tag_consistency.py)
 # OS
-# tags: [ android android-pie
+# tags: [ android android-lollipop android-marshmallow android-nougat
+#             android-pie
 #         chromeos
 #         fuchsia
-#         linux
-#         mac catalina lion highsierra mojave mountainlion sierra
+#         linux ubuntu
+#         mac bigsur catalina lion highsierra mac-10.12 mojave mountainlion
+#             sierra
 #         win win7 win8 win10 ]
 # Devices
 # tags: [ android-nexus-5 android-nexus-5x android-nexus-6 android-nexus-6p
@@ -21,10 +23,11 @@
 # GPU
 # tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f
 #         apple apple-apple-a12z
+#         arm
+#         google google-0xffff
 #         intel intel-0xa2e intel-0xd26 intel-0xa011 intel-0x3e92 intel-0x5912
 #         nvidia nvidia-0xfe9 nvidia-0x1cb3 nvidia-0x2184
-#         qualcomm
-#         google-0xffff ]
+#         qualcomm ]
 # Decoder
 # tags: [ passthrough no-passthrough ]
 # ANGLE Backend
diff --git a/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt
index cd6939e9..d4b37e6 100644
--- a/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt
@@ -1,10 +1,12 @@
 # BEGIN TAG HEADER (autogenerated, see validate_tag_consistency.py)
 # OS
-# tags: [ android android-pie
+# tags: [ android android-lollipop android-marshmallow android-nougat
+#             android-pie
 #         chromeos
 #         fuchsia
-#         linux
-#         mac catalina lion highsierra mojave mountainlion sierra
+#         linux ubuntu
+#         mac bigsur catalina lion highsierra mac-10.12 mojave mountainlion
+#             sierra
 #         win win7 win8 win10 ]
 # Devices
 # tags: [ android-nexus-5 android-nexus-5x android-nexus-6 android-nexus-6p
@@ -21,10 +23,11 @@
 # GPU
 # tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f
 #         apple apple-apple-a12z
+#         arm
+#         google google-0xffff
 #         intel intel-0xa2e intel-0xd26 intel-0xa011 intel-0x3e92 intel-0x5912
 #         nvidia nvidia-0xfe9 nvidia-0x1cb3 nvidia-0x2184
-#         qualcomm
-#         google-0xffff ]
+#         qualcomm ]
 # Decoder
 # tags: [ passthrough no-passthrough ]
 # ANGLE Backend
diff --git a/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt
index 2a6dbf9..9f544e5 100644
--- a/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt
@@ -1,10 +1,12 @@
 # BEGIN TAG HEADER (autogenerated, see validate_tag_consistency.py)
 # OS
-# tags: [ android android-pie
+# tags: [ android android-lollipop android-marshmallow android-nougat
+#             android-pie
 #         chromeos
 #         fuchsia
-#         linux
-#         mac catalina lion highsierra mojave mountainlion sierra
+#         linux ubuntu
+#         mac bigsur catalina lion highsierra mac-10.12 mojave mountainlion
+#             sierra
 #         win win7 win8 win10 ]
 # Devices
 # tags: [ android-nexus-5 android-nexus-5x android-nexus-6 android-nexus-6p
@@ -21,10 +23,11 @@
 # GPU
 # tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f
 #         apple apple-apple-a12z
+#         arm
+#         google google-0xffff
 #         intel intel-0xa2e intel-0xd26 intel-0xa011 intel-0x3e92 intel-0x5912
 #         nvidia nvidia-0xfe9 nvidia-0x1cb3 nvidia-0x2184
-#         qualcomm
-#         google-0xffff ]
+#         qualcomm ]
 # Decoder
 # tags: [ passthrough no-passthrough ]
 # ANGLE Backend
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
index 8106e6b..9544fd3 100644
--- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -1,10 +1,12 @@
 # BEGIN TAG HEADER (autogenerated, see validate_tag_consistency.py)
 # OS
-# tags: [ android android-pie
+# tags: [ android android-lollipop android-marshmallow android-nougat
+#             android-pie
 #         chromeos
 #         fuchsia
-#         linux
-#         mac catalina lion highsierra mojave mountainlion sierra
+#         linux ubuntu
+#         mac bigsur catalina lion highsierra mac-10.12 mojave mountainlion
+#             sierra
 #         win win7 win8 win10 ]
 # Devices
 # tags: [ android-nexus-5 android-nexus-5x android-nexus-6 android-nexus-6p
@@ -21,10 +23,11 @@
 # GPU
 # tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f
 #         apple apple-apple-a12z
+#         arm
+#         google google-0xffff
 #         intel intel-0xa2e intel-0xd26 intel-0xa011 intel-0x3e92 intel-0x5912
 #         nvidia nvidia-0xfe9 nvidia-0x1cb3 nvidia-0x2184
-#         qualcomm
-#         google-0xffff ]
+#         qualcomm ]
 # Decoder
 # tags: [ passthrough no-passthrough ]
 # ANGLE Backend
diff --git a/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt
index 83574e2f..8ff36c1 100644
--- a/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt
@@ -1,10 +1,12 @@
 # BEGIN TAG HEADER (autogenerated, see validate_tag_consistency.py)
 # OS
-# tags: [ android android-pie
+# tags: [ android android-lollipop android-marshmallow android-nougat
+#             android-pie
 #         chromeos
 #         fuchsia
-#         linux
-#         mac catalina lion highsierra mojave mountainlion sierra
+#         linux ubuntu
+#         mac bigsur catalina lion highsierra mac-10.12 mojave mountainlion
+#             sierra
 #         win win7 win8 win10 ]
 # Devices
 # tags: [ android-nexus-5 android-nexus-5x android-nexus-6 android-nexus-6p
@@ -21,10 +23,11 @@
 # GPU
 # tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f
 #         apple apple-apple-a12z
+#         arm
+#         google google-0xffff
 #         intel intel-0xa2e intel-0xd26 intel-0xa011 intel-0x3e92 intel-0x5912
 #         nvidia nvidia-0xfe9 nvidia-0x1cb3 nvidia-0x2184
-#         qualcomm
-#         google-0xffff ]
+#         qualcomm ]
 # Decoder
 # tags: [ passthrough no-passthrough ]
 # ANGLE Backend
diff --git a/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt
index 9c02e5d8..4cfa431 100644
--- a/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt
@@ -1,10 +1,12 @@
 # BEGIN TAG HEADER (autogenerated, see validate_tag_consistency.py)
 # OS
-# tags: [ android android-pie
+# tags: [ android android-lollipop android-marshmallow android-nougat
+#             android-pie
 #         chromeos
 #         fuchsia
-#         linux
-#         mac catalina lion highsierra mojave mountainlion sierra
+#         linux ubuntu
+#         mac bigsur catalina lion highsierra mac-10.12 mojave mountainlion
+#             sierra
 #         win win7 win8 win10 ]
 # Devices
 # tags: [ android-nexus-5 android-nexus-5x android-nexus-6 android-nexus-6p
@@ -21,10 +23,11 @@
 # GPU
 # tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f
 #         apple apple-apple-a12z
+#         arm
+#         google google-0xffff
 #         intel intel-0xa2e intel-0xd26 intel-0xa011 intel-0x3e92 intel-0x5912
 #         nvidia nvidia-0xfe9 nvidia-0x1cb3 nvidia-0x2184
-#         qualcomm
-#         google-0xffff ]
+#         qualcomm ]
 # Decoder
 # tags: [ passthrough no-passthrough ]
 # ANGLE Backend
diff --git a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
index 26ab8c59..ea8841c1 100644
--- a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
@@ -1,10 +1,12 @@
 # BEGIN TAG HEADER (autogenerated, see validate_tag_consistency.py)
 # OS
-# tags: [ android android-pie
+# tags: [ android android-lollipop android-marshmallow android-nougat
+#             android-pie
 #         chromeos
 #         fuchsia
-#         linux
-#         mac catalina lion highsierra mojave mountainlion sierra
+#         linux ubuntu
+#         mac bigsur catalina lion highsierra mac-10.12 mojave mountainlion
+#             sierra
 #         win win7 win8 win10 ]
 # Devices
 # tags: [ android-nexus-5 android-nexus-5x android-nexus-6 android-nexus-6p
@@ -21,10 +23,11 @@
 # GPU
 # tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f
 #         apple apple-apple-a12z
+#         arm
+#         google google-0xffff
 #         intel intel-0xa2e intel-0xd26 intel-0xa011 intel-0x3e92 intel-0x5912
 #         nvidia nvidia-0xfe9 nvidia-0x1cb3 nvidia-0x2184
-#         qualcomm
-#         google-0xffff ]
+#         qualcomm ]
 # Decoder
 # tags: [ passthrough no-passthrough ]
 # ANGLE Backend
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
index 0e97202..dba0514 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -1,10 +1,12 @@
 # BEGIN TAG HEADER (autogenerated, see validate_tag_consistency.py)
 # OS
-# tags: [ android android-pie
+# tags: [ android android-lollipop android-marshmallow android-nougat
+#             android-pie
 #         chromeos
 #         fuchsia
-#         linux
-#         mac catalina lion highsierra mojave mountainlion sierra
+#         linux ubuntu
+#         mac bigsur catalina lion highsierra mac-10.12 mojave mountainlion
+#             sierra
 #         win win7 win8 win10 ]
 # Devices
 # tags: [ android-nexus-5 android-nexus-5x android-nexus-6 android-nexus-6p
@@ -21,10 +23,11 @@
 # GPU
 # tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f
 #         apple apple-apple-a12z
+#         arm
+#         google google-0xffff
 #         intel intel-0xa2e intel-0xd26 intel-0xa011 intel-0x3e92 intel-0x5912
 #         nvidia nvidia-0xfe9 nvidia-0x1cb3 nvidia-0x2184
-#         qualcomm
-#         google-0xffff ]
+#         qualcomm ]
 # Decoder
 # tags: [ passthrough no-passthrough ]
 # ANGLE Backend
@@ -160,11 +163,6 @@
 crbug.com/798117 [ linux nvidia ] conformance/glsl/bugs/assign-to-swizzled-twice-in-function.html [ Failure ]
 crbug.com/792210 [ nvidia ] conformance/glsl/bugs/in-parameter-passed-as-inout-argument-and-global.html [ Failure ]
 
-# Fails everywhere
-crbug.com/1004581 [ win ] conformance/rendering/multisample-corruption.html [ RetryOnFailure ]
-crbug.com/1004581 [ linux ] conformance/rendering/multisample-corruption.html [ RetryOnFailure ]
-crbug.com/1004581 [ mac ] conformance/rendering/multisample-corruption.html [ RetryOnFailure ]
-
 ####################
 # Win failures     #
 ####################
@@ -774,6 +772,8 @@
 crbug.com/1130708 [ mac apple-apple-a12z no-passthrough ] conformance2/textures/webgl_canvas/tex-2d-rgb5_a1-rgba-unsigned_byte.html [ Failure ]
 crbug.com/1130708 [ mac apple-apple-a12z no-passthrough ] conformance2/textures/misc/tex-mipmap-levels.html [ Failure ]
 crbug.com/1130711 [ mac apple-apple-a12z no-passthrough ] deqp/functional/gles3/negativeshaderapi.html [ Failure ]
+crbug.com/1141066 [ mac apple-apple-a12z angle-opengl passthrough ] conformance/textures/misc/texture-copying-and-deletion.html [ Failure ]
+crbug.com/1141066 [ mac apple-apple-a12z angle-opengl passthrough ] conformance/textures/misc/texture-copying-feedback-loops.html [ Failure ]
 
 ####################
 # Linux failures   #
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index 7290ed8f..79b66eee 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -1,10 +1,12 @@
 # BEGIN TAG HEADER (autogenerated, see validate_tag_consistency.py)
 # OS
-# tags: [ android android-pie
+# tags: [ android android-lollipop android-marshmallow android-nougat
+#             android-pie
 #         chromeos
 #         fuchsia
-#         linux
-#         mac catalina lion highsierra mojave mountainlion sierra
+#         linux ubuntu
+#         mac bigsur catalina lion highsierra mac-10.12 mojave mountainlion
+#             sierra
 #         win win7 win8 win10 ]
 # Devices
 # tags: [ android-nexus-5 android-nexus-5x android-nexus-6 android-nexus-6p
@@ -21,10 +23,11 @@
 # GPU
 # tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f
 #         apple apple-apple-a12z
+#         arm
+#         google google-0xffff
 #         intel intel-0xa2e intel-0xd26 intel-0xa011 intel-0x3e92 intel-0x5912
 #         nvidia nvidia-0xfe9 nvidia-0x1cb3 nvidia-0x2184
-#         qualcomm
-#         google-0xffff ]
+#         qualcomm ]
 # Decoder
 # tags: [ passthrough no-passthrough ]
 # ANGLE Backend
@@ -160,10 +163,6 @@
 crbug.com/1018028 [ win angle-vulkan nvidia ] conformance/rendering/bind-framebuffer-flush-bug.html [ Failure ]
 crbug.com/1110111 [ win nvidia ] conformance/rendering/point-no-attributes.html [ RetryOnFailure ]
 
-crbug.com/1004581 [ win ] conformance/rendering/multisample-corruption.html [ RetryOnFailure ]
-crbug.com/1004581 [ linux ] conformance/rendering/multisample-corruption.html [ RetryOnFailure ]
-crbug.com/1004581 [ mac ] conformance/rendering/multisample-corruption.html [ RetryOnFailure ]
-
 # Skipping new tests
 crbug.com/angleproject/5038 conformance/extensions/ext-color-buffer-half-float.html [ Skip ]
 
@@ -229,6 +228,7 @@
 crbug.com/1136369 [ fuchsia ] deqp/data/gles2/shaders/conversions.html [ Skip ]
 crbug.com/1136369 [ fuchsia ] deqp/data/gles2/shaders/functions.html [ Skip ]
 crbug.com/1136369 [ fuchsia ] deqp/data/gles2/shaders/swizzles.html [ Skip ]
+crbug.com/1141040 [ fuchsia ] conformance/textures/misc/tex-image-and-sub-image-2d-with-array-buffer-view.html [ Skip ]
 
 # Video not supported on Fuchsia qemu boards.
 [ fuchsia fuchsia-board-qemu-x64 ] conformance/extensions/oes-texture-float-with-video.html [ Skip ]
@@ -390,6 +390,7 @@
 crbug.com/angleproject/2926 [ win amd angle-vulkan passthrough ] deqp/data/gles2/shaders/linkage.html [ Failure ]
 crbug.com/974347 [ win amd angle-vulkan passthrough ] conformance/textures/image/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ]
 crbug.com/974347 [ win amd angle-vulkan passthrough ] conformance/textures/image/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html [ Failure ]
+crbug.com/1004581 [ win amd angle-vulkan passthrough ] conformance/rendering/multisample-corruption.html [ Failure ]
 crbug.com/1010942 [ win amd angle-vulkan passthrough ] conformance/glsl/samplers/glsl-function-texture2dproj.html [ Failure ]
 crbug.com/angleproject/4286 [ win amd angle-vulkan passthrough ] conformance/rendering/out-of-bounds-array-buffers.html [ Failure ]
 
@@ -485,6 +486,8 @@
 crbug.com/1130759 [ mac apple-apple-a12z angle-metal ] conformance/textures/misc/texture-mips.html [ Failure ]
 crbug.com/1130760 [ mac apple-apple-a12z angle-metal ] conformance/extensions/webgl-draw-buffers.html [ Failure ]
 crbug.com/1130760 [ mac apple-apple-a12z angle-metal ] conformance/ogles/GL/discard/discard_001_to_002.html [ Failure ]
+crbug.com/1141066 [ mac apple-apple-a12z angle-opengl passthrough ] conformance/textures/misc/texture-copying-and-deletion.html [ Failure ]
+crbug.com/1141066 [ mac apple-apple-a12z angle-opengl passthrough ] conformance/textures/misc/texture-copying-feedback-loops.html [ Failure ]
 
 ####################
 # Linux failures   #
diff --git a/content/test/gpu/validate_tag_consistency.py b/content/test/gpu/validate_tag_consistency.py
index 19ea3bc..b4670848 100755
--- a/content/test/gpu/validate_tag_consistency.py
+++ b/content/test/gpu/validate_tag_consistency.py
@@ -11,11 +11,13 @@
 
 TAG_HEADER = """\
 # OS
-# tags: [ android android-pie
+# tags: [ android android-lollipop android-marshmallow android-nougat
+#             android-pie
 #         chromeos
 #         fuchsia
-#         linux
-#         mac catalina lion highsierra mojave mountainlion sierra
+#         linux ubuntu
+#         mac bigsur catalina lion highsierra mac-10.12 mojave mountainlion
+#             sierra
 #         win win7 win8 win10 ]
 # Devices
 # tags: [ android-nexus-5 android-nexus-5x android-nexus-6 android-nexus-6p
@@ -32,10 +34,11 @@
 # GPU
 # tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f
 #         apple apple-apple-a12z
+#         arm
+#         google google-0xffff
 #         intel intel-0xa2e intel-0xd26 intel-0xa011 intel-0x3e92 intel-0x5912
 #         nvidia nvidia-0xfe9 nvidia-0x1cb3 nvidia-0x2184
-#         qualcomm
-#         google-0xffff ]
+#         qualcomm ]
 # Decoder
 # tags: [ passthrough no-passthrough ]
 # ANGLE Backend
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc
index 3461b8c..2d416e2 100644
--- a/content/test/test_render_frame.cc
+++ b/content/test/test_render_frame.cc
@@ -129,7 +129,9 @@
     return true;
   }
 
-  bool CreateNewWidget(
+  bool CreateNewPopupWidget(
+      mojo::PendingAssociatedReceiver<blink::mojom::PopupWidgetHost>
+          blink_popup_widget_host,
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
           blink_widget_host,
       mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget,
@@ -140,11 +142,13 @@
     return true;
   }
 
-  void CreateNewWidget(
+  void CreateNewPopupWidget(
+      mojo::PendingAssociatedReceiver<blink::mojom::PopupWidgetHost>
+          blink_popup_widget_host,
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
           blink_widget_host,
       mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget,
-      CreateNewWidgetCallback callback) override {
+      CreateNewPopupWidgetCallback callback) override {
     std::move(callback).Run(MSG_ROUTING_NONE);
   }
 
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc
index 3117f4b..fbaeabb 100644
--- a/content/test/test_web_contents.cc
+++ b/content/test/test_web_contents.cc
@@ -386,9 +386,11 @@
   return nullptr;
 }
 
-void TestWebContents::CreateNewWidget(
+void TestWebContents::CreateNewPopupWidget(
     AgentSchedulingGroupHost& agent_scheduling_group,
     int32_t route_id,
+    mojo::PendingAssociatedReceiver<blink::mojom::PopupWidgetHost>
+        blink_popup_widget_host,
     mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host,
     mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) {}
 
diff --git a/content/test/test_web_contents.h b/content/test/test_web_contents.h
index 0cf1a1b..763e6bc 100644
--- a/content/test/test_web_contents.h
+++ b/content/test/test_web_contents.h
@@ -175,12 +175,15 @@
       bool is_new_browsing_instance,
       bool has_user_gesture,
       SessionStorageNamespace* session_storage_namespace) override;
-  void CreateNewWidget(AgentSchedulingGroupHost& agent_scheduling_group,
-                       int32_t route_id,
-                       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
-                           blink_widget_host,
-                       mojo::PendingAssociatedRemote<blink::mojom::Widget>
-                           blink_widget) override;
+  void CreateNewPopupWidget(
+      AgentSchedulingGroupHost& agent_scheduling_group,
+      int32_t route_id,
+      mojo::PendingAssociatedReceiver<blink::mojom::PopupWidgetHost>
+          blink_popup_widget_host,
+      mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
+          blink_widget_host,
+      mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget)
+      override;
   void ShowCreatedWindow(RenderFrameHost* opener,
                          int route_id,
                          WindowOpenDisposition disposition,
diff --git a/content/web_test/renderer/test_runner.h b/content/web_test/renderer/test_runner.h
index 53c1ac1..6e79c768 100644
--- a/content/web_test/renderer/test_runner.h
+++ b/content/web_test/renderer/test_runner.h
@@ -361,7 +361,7 @@
   // Disable any mock orientation on |view| that is set.
   void DisableMockScreenOrientation(WebViewTestProxy* view);
 
-  // Modify accept_languages in blink::mojom::RendererPreferences.
+  // Modify accept_languages in blink::RendererPreferences.
   void SetAcceptLanguages(const std::string& accept_languages);
 
   ///////////////////////////////////////////////////////////////////////////
diff --git a/device/bluetooth/bluetooth_device_unittest.cc b/device/bluetooth/bluetooth_device_unittest.cc
index 3906a21..2377535b 100644
--- a/device/bluetooth/bluetooth_device_unittest.cc
+++ b/device/bluetooth/bluetooth_device_unittest.cc
@@ -2020,6 +2020,36 @@
   EXPECT_EQ(0u, device->GetGattServices().size());
 }
 
+#if defined(OS_WIN)
+TEST_P(BluetoothTestWinrtOnly, GattServicesDiscovered_SomeServicesBlocked) {
+#else
+TEST_F(BluetoothTest, DISABLED_GattServicesDiscovered_SomeServicesBlocked) {
+#endif
+  if (!PlatformSupportsLowEnergy()) {
+    LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+    return;
+  }
+  InitWithFakeAdapter();
+  StartLowEnergyDiscoverySession();
+  TestBluetoothAdapterObserver observer(adapter_);
+  BluetoothDevice* device = SimulateLowEnergyDevice(3);
+  ResetEventCounts();
+  ASSERT_TRUE(ConnectGatt(device));
+  EXPECT_EQ(1, gatt_discovery_attempts_);
+  EXPECT_EQ(0, observer.gatt_services_discovered_count());
+
+  SimulateGattServicesDiscovered(
+      device,
+      /*uuids=*/{kTestUUIDGenericAccess, kTestUUIDHeartRate},
+      /*blocked_uuids=*/{kTestUUIDU2f});
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_TRUE(device->IsGattServicesDiscoveryComplete());
+  EXPECT_EQ(1, observer.gatt_services_discovered_count());
+  // Even though some services are blocked they should still appear in the list.
+  EXPECT_EQ(3u, device->GetGattServices().size());
+}
+
 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
 TEST_F(BluetoothTest, GetDeviceTransportType) {
   if (!PlatformSupportsLowEnergy()) {
diff --git a/device/bluetooth/bluetooth_gatt_discoverer_winrt.cc b/device/bluetooth/bluetooth_gatt_discoverer_winrt.cc
index 663a6a3..17e4aaa 100644
--- a/device/bluetooth/bluetooth_gatt_discoverer_winrt.cc
+++ b/device/bluetooth/bluetooth_gatt_discoverer_winrt.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
+#include "base/strings/stringprintf.h"
 #include "base/win/post_async_results.h"
 #include "components/device_event_log/device_event_log.h"
 #include "device/bluetooth/bluetooth_remote_gatt_service_winrt.h"
@@ -65,6 +66,46 @@
 using ABI::Windows::Foundation::Collections::IVectorView;
 using Microsoft::WRL::ComPtr;
 
+std::string GattCommunicationStatusToString(GattCommunicationStatus status) {
+  switch (status) {
+    case GattCommunicationStatus_Success:
+      return "Success";
+    case ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
+        GattCommunicationStatus_Unreachable:
+      return "Unreachable";
+    case ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
+        GattCommunicationStatus_ProtocolError:
+      return "ProtocolError";
+    case GattCommunicationStatus_AccessDenied:
+      return "AccessDenied";
+    default:
+      return base::StringPrintf("Unknown (%d)", status);
+  }
+}
+
+std::string GattOpenStatusToString(GattOpenStatus status) {
+  switch (status) {
+    case ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
+        GattOpenStatus_Unspecified:
+      return "Unspecified";
+    case GattOpenStatus_Success:
+      return "Success";
+    case GattOpenStatus_AlreadyOpened:
+      return "AlreadyOpened";
+    case ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
+        GattOpenStatus_NotFound:
+      return "NotFound";
+    case ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
+        GattOpenStatus_SharingViolation:
+      return "SharingViolation";
+    case ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
+        GattOpenStatus_AccessDenied:
+      return "AccessDenied";
+    default:
+      return base::StringPrintf("Unknown (%d)", status);
+  }
+}
+
 template <typename IGattResult>
 bool CheckCommunicationStatus(IGattResult* gatt_result,
                               bool allow_access_denied = false) {
@@ -85,7 +126,8 @@
     if (status == GattCommunicationStatus_AccessDenied) {
       BLUETOOTH_LOG(DEBUG) << "GATT access denied error";
     } else {
-      BLUETOOTH_LOG(DEBUG) << "Unexpected GattCommunicationStatus: " << status;
+      BLUETOOTH_LOG(DEBUG) << "Unexpected GattCommunicationStatus: "
+                           << GattCommunicationStatusToString(status);
     }
     BLUETOOTH_LOG(DEBUG)
         << "GATT Error Code: "
@@ -263,13 +305,16 @@
     GattOpenStatus status) {
   if (status != GattOpenStatus_Success &&
       status != GattOpenStatus_AlreadyOpened) {
-    BLUETOOTH_LOG(DEBUG) << "Failed to open service "
-                         << service_attribute_handle << ": " << status;
-    std::move(callback_).Run(false);
+    BLUETOOTH_LOG(DEBUG) << "Ignoring failure to open service "
+                         << service_attribute_handle << ": "
+                         << GattOpenStatusToString(status);
+
+    // Enumerate no characteristics on services the browser is unable to access.
+    service_to_characteristics_map_.insert({service_attribute_handle, {}});
+    RunCallbackIfDone();
     return;
   }
 
-
   ComPtr<IAsyncOperation<GattCharacteristicsResult*>> get_characteristics_op;
   HRESULT hr = gatt_service_3->GetCharacteristicsAsync(&get_characteristics_op);
   if (FAILED(hr)) {
@@ -297,7 +342,8 @@
     ComPtr<IGattCharacteristicsResult> characteristics_result) {
   // A few GATT services like HID over GATT (short UUID 0x1812) are protected
   // by the OS, leading to an access denied error.
-  if (!CheckCommunicationStatus(characteristics_result.Get(), true)) {
+  if (!CheckCommunicationStatus(characteristics_result.Get(),
+                                /*allow_access_denied=*/true)) {
     BLUETOOTH_LOG(DEBUG) << "Failed to get characteristics for service "
                          << service_attribute_handle << ".";
     std::move(callback_).Run(false);
diff --git a/device/bluetooth/strings/bluetooth_strings_gu.xtb b/device/bluetooth/strings/bluetooth_strings_gu.xtb
index b8e32a32..48b83a2 100644
--- a/device/bluetooth/strings/bluetooth_strings_gu.xtb
+++ b/device/bluetooth/strings/bluetooth_strings_gu.xtb
@@ -16,6 +16,7 @@
 <translation id="4986357476502426173"><ph name="DEVICE_NAME" />, વીડિયો ડિવાઇસ</translation>
 <translation id="5271696982761495740">ટૅબ્લેટ (<ph name="ADDRESS" />)</translation>
 <translation id="5376363957846771741">અજ્ઞાત અથવા અનસપોર્ટેડ ઉપકરણ (<ph name="ADDRESS" />)</translation>
+<translation id="571460437990229974"><ph name="DEVICE_NAME_AND_TYPE" /> <ph name="CONNECTION_STATUS" /></translation>
 <translation id="5716052956047449618"><ph name="DEVICE_NAME" />, મોડેમ</translation>
 <translation id="6459740836740815150"><ph name="DEVICE_NAME" />, કાર ઑડિયો ડિવાઇસ</translation>
 <translation id="6542922424766292144"><ph name="DEVICE_NAME" />, કીબોર્ડ</translation>
diff --git a/device/bluetooth/strings/bluetooth_strings_or.xtb b/device/bluetooth/strings/bluetooth_strings_or.xtb
index 38986ca..61062d91 100644
--- a/device/bluetooth/strings/bluetooth_strings_or.xtb
+++ b/device/bluetooth/strings/bluetooth_strings_or.xtb
@@ -16,6 +16,7 @@
 <translation id="4986357476502426173"><ph name="DEVICE_NAME" />, ଭିଡିଓ ଡିଭାଇସ୍</translation>
 <translation id="5271696982761495740">ଟାବଲେଟ୍ (<ph name="ADDRESS" />)</translation>
 <translation id="5376363957846771741">ଅଜଣା କିମ୍ବା ଅସମର୍ଥିତ ଡିଭାଇସ୍‌ (<ph name="ADDRESS" />)</translation>
+<translation id="571460437990229974"><ph name="DEVICE_NAME_AND_TYPE" /> <ph name="CONNECTION_STATUS" /></translation>
 <translation id="5716052956047449618"><ph name="DEVICE_NAME" />, ମୋଡେମ୍</translation>
 <translation id="6459740836740815150"><ph name="DEVICE_NAME" />, କାରର ଅଡିଓ ଡିଭାଇସ୍</translation>
 <translation id="6542922424766292144"><ph name="DEVICE_NAME" />, କୀବୋର୍ଡ</translation>
diff --git a/device/bluetooth/strings/bluetooth_strings_te.xtb b/device/bluetooth/strings/bluetooth_strings_te.xtb
index c53ec0b..5bd6322 100644
--- a/device/bluetooth/strings/bluetooth_strings_te.xtb
+++ b/device/bluetooth/strings/bluetooth_strings_te.xtb
@@ -16,6 +16,7 @@
 <translation id="4986357476502426173"><ph name="DEVICE_NAME" />, వీడియో పరికరం</translation>
 <translation id="5271696982761495740">టాబ్లెట్ (<ph name="ADDRESS" />)</translation>
 <translation id="5376363957846771741">తెలియని లేదా మద్దతు లేని పరికరం (<ph name="ADDRESS" />)</translation>
+<translation id="571460437990229974"><ph name="DEVICE_NAME_AND_TYPE" /> <ph name="CONNECTION_STATUS" /></translation>
 <translation id="5716052956047449618"><ph name="DEVICE_NAME" />, మోడెమ్</translation>
 <translation id="6459740836740815150"><ph name="DEVICE_NAME" />, కారు ఆడియో పరికరం</translation>
 <translation id="6542922424766292144"><ph name="DEVICE_NAME" />, కీబోర్డ్</translation>
diff --git a/device/bluetooth/test/bluetooth_test.h b/device/bluetooth/test/bluetooth_test.h
index 06fac412..ee56f54 100644
--- a/device/bluetooth/test/bluetooth_test.h
+++ b/device/bluetooth/test/bluetooth_test.h
@@ -357,12 +357,14 @@
   // Simulates a connection status change to disconnect.
   virtual void SimulateStatusChangeToDisconnect(BluetoothDevice* device) {}
 
-  // Simulates success of discovering services. |uuids| is used to create a
-  // service for each UUID string. Multiple UUIDs with the same value produce
-  // multiple service instances.
+  // Simulates success of discovering services. |uuids| and |blocked_uuids| are
+  // used to create a service for each UUID string. Multiple UUIDs with the same
+  // value produce multiple service instances. UUIDs in the |blocked_uuids| list
+  // create services which cannot be accessed (WinRT-only).
   virtual void SimulateGattServicesDiscovered(
       BluetoothDevice* device,
-      const std::vector<std::string>& uuids) {}
+      const std::vector<std::string>& uuids,
+      const std::vector<std::string>& blocked_uuids = {}) {}
 
   // Simulates a GATT Services changed event.
   virtual void SimulateGattServicesChanged(BluetoothDevice* device) {}
diff --git a/device/bluetooth/test/bluetooth_test_android.cc b/device/bluetooth/test/bluetooth_test_android.cc
index 164c20c..da2d47c 100644
--- a/device/bluetooth/test/bluetooth_test_android.cc
+++ b/device/bluetooth/test/bluetooth_test_android.cc
@@ -163,7 +163,9 @@
 
 void BluetoothTestAndroid::SimulateGattServicesDiscovered(
     BluetoothDevice* device,
-    const std::vector<std::string>& uuids) {
+    const std::vector<std::string>& uuids,
+    const std::vector<std::string>& blocked_uuids) {
+  DCHECK(blocked_uuids.empty()) << "Setting blocked_uuids unsupported.";
   BluetoothDeviceAndroid* device_android = nullptr;
   if (device) {
     device_android = static_cast<BluetoothDeviceAndroid*>(device);
diff --git a/device/bluetooth/test/bluetooth_test_android.h b/device/bluetooth/test/bluetooth_test_android.h
index 3791ec60..3c7650b 100644
--- a/device/bluetooth/test/bluetooth_test_android.h
+++ b/device/bluetooth/test/bluetooth_test_android.h
@@ -36,7 +36,8 @@
   void SimulateGattDisconnection(BluetoothDevice* device) override;
   void SimulateGattServicesDiscovered(
       BluetoothDevice* device,
-      const std::vector<std::string>& uuids) override;
+      const std::vector<std::string>& uuids,
+      const std::vector<std::string>& blocked_uuids = {}) override;
   void SimulateGattServicesDiscoveryError(BluetoothDevice* device) override;
   void SimulateGattCharacteristic(BluetoothRemoteGattService* service,
                                   const std::string& uuid,
diff --git a/device/bluetooth/test/bluetooth_test_mac.h b/device/bluetooth/test/bluetooth_test_mac.h
index 773878ca..e9a1029 100644
--- a/device/bluetooth/test/bluetooth_test_mac.h
+++ b/device/bluetooth/test/bluetooth_test_mac.h
@@ -54,7 +54,8 @@
   void SimulateGattDisconnectionError(BluetoothDevice* device) override;
   void SimulateGattServicesDiscovered(
       BluetoothDevice* device,
-      const std::vector<std::string>& uuids) override;
+      const std::vector<std::string>& uuids,
+      const std::vector<std::string>& blocked_uuids = {}) override;
   void SimulateGattServicesChanged(BluetoothDevice* device) override;
   void SimulateGattServiceRemoved(BluetoothRemoteGattService* service) override;
   void SimulateGattCharacteristic(BluetoothRemoteGattService* service,
diff --git a/device/bluetooth/test/bluetooth_test_mac.mm b/device/bluetooth/test/bluetooth_test_mac.mm
index 11541af2..066dcb46 100644
--- a/device/bluetooth/test/bluetooth_test_mac.mm
+++ b/device/bluetooth/test/bluetooth_test_mac.mm
@@ -344,7 +344,9 @@
 
 void BluetoothTestMac::SimulateGattServicesDiscovered(
     BluetoothDevice* device,
-    const std::vector<std::string>& uuids) {
+    const std::vector<std::string>& uuids,
+    const std::vector<std::string>& blocked_uuids) {
+  DCHECK(blocked_uuids.empty()) << "Setting blocked_uuids unsupported.";
   AddServicesToDeviceMac(device, uuids);
   [GetMockCBPeripheral(device) mockDidDiscoverEvents];
 }
diff --git a/device/bluetooth/test/bluetooth_test_win.cc b/device/bluetooth/test/bluetooth_test_win.cc
index 7c13ed5..7d71a0ac 100644
--- a/device/bluetooth/test/bluetooth_test_win.cc
+++ b/device/bluetooth/test/bluetooth_test_win.cc
@@ -351,7 +351,9 @@
 
 void BluetoothTestWin::SimulateGattServicesDiscovered(
     BluetoothDevice* device,
-    const std::vector<std::string>& uuids) {
+    const std::vector<std::string>& uuids,
+    const std::vector<std::string>& blocked_uuids) {
+  DCHECK(blocked_uuids.empty());
   std::string address =
       device ? device->GetAddress() : remembered_device_address_;
 
@@ -988,14 +990,16 @@
 
 void BluetoothTestWinrt::SimulateGattServicesDiscovered(
     BluetoothDevice* device,
-    const std::vector<std::string>& uuids) {
+    const std::vector<std::string>& uuids,
+    const std::vector<std::string>& blocked_uuids) {
   if (!UsesNewBleImplementation() || !PlatformSupportsLowEnergy())
-    return BluetoothTestWin::SimulateGattServicesDiscovered(device, uuids);
+    return BluetoothTestWin::SimulateGattServicesDiscovered(device, uuids,
+                                                            blocked_uuids);
 
   auto* const ble_device =
       static_cast<TestBluetoothDeviceWinrt*>(device)->ble_device();
   DCHECK(ble_device);
-  ble_device->SimulateGattServicesDiscovered(uuids);
+  ble_device->SimulateGattServicesDiscovered(uuids, blocked_uuids);
 }
 
 void BluetoothTestWinrt::SimulateGattServicesChanged(BluetoothDevice* device) {
diff --git a/device/bluetooth/test/bluetooth_test_win.h b/device/bluetooth/test/bluetooth_test_win.h
index 99e511a1..a6e6c2b9 100644
--- a/device/bluetooth/test/bluetooth_test_win.h
+++ b/device/bluetooth/test/bluetooth_test_win.h
@@ -44,7 +44,8 @@
   void SimulateStatusChangeToDisconnect(BluetoothDevice* device) override;
   void SimulateGattServicesDiscovered(
       BluetoothDevice* device,
-      const std::vector<std::string>& uuids) override;
+      const std::vector<std::string>& uuids,
+      const std::vector<std::string>& blocked_uuids = {}) override;
   void SimulateGattServiceRemoved(BluetoothRemoteGattService* service) override;
   void SimulateGattCharacteristic(BluetoothRemoteGattService* service,
                                   const std::string& uuid,
@@ -204,7 +205,8 @@
   void SimulateStatusChangeToDisconnect(BluetoothDevice* device) override;
   void SimulateGattServicesDiscovered(
       BluetoothDevice* device,
-      const std::vector<std::string>& uuids) override;
+      const std::vector<std::string>& uuids,
+      const std::vector<std::string>& blocked_uuids = {}) override;
   void SimulateGattServicesChanged(BluetoothDevice* device) override;
   void SimulateGattServiceRemoved(BluetoothRemoteGattService* service) override;
   void SimulateGattServicesDiscoveryError(BluetoothDevice* device) override;
diff --git a/device/bluetooth/test/fake_bluetooth_le_device_winrt.cc b/device/bluetooth/test/fake_bluetooth_le_device_winrt.cc
index 123fb4c..c40645a 100644
--- a/device/bluetooth/test/fake_bluetooth_le_device_winrt.cc
+++ b/device/bluetooth/test/fake_bluetooth_le_device_winrt.cc
@@ -325,14 +325,23 @@
 }
 
 void FakeBluetoothLEDeviceWinrt::SimulateGattServicesDiscovered(
-    const std::vector<std::string>& uuids) {
+    const std::vector<std::string>& uuids,
+    const std::vector<std::string>& blocked_uuids) {
   for (const auto& uuid : uuids) {
     // Attribute handles need to be unique for a given BLE device. Increasing by
     // a large number ensures enough address space for the contained
     // characteristics and descriptors.
-    fake_services_.push_back(
-        Make<FakeGattDeviceServiceWinrt>(bluetooth_test_winrt_, this, uuid,
-                                         service_attribute_handle_ += 0x0400));
+    fake_services_.push_back(Make<FakeGattDeviceServiceWinrt>(
+        bluetooth_test_winrt_, this, uuid, service_attribute_handle_ += 0x0400,
+        /*allowed=*/true));
+  }
+  for (const auto& uuid : blocked_uuids) {
+    // Attribute handles need to be unique for a given BLE device. Increasing by
+    // a large number ensures enough address space for the contained
+    // characteristics and descriptors.
+    fake_services_.push_back(Make<FakeGattDeviceServiceWinrt>(
+        bluetooth_test_winrt_, this, uuid, service_attribute_handle_ += 0x0400,
+        /*allowed=*/false));
   }
 
   DCHECK(gatt_services_callback_);
diff --git a/device/bluetooth/test/fake_bluetooth_le_device_winrt.h b/device/bluetooth/test/fake_bluetooth_le_device_winrt.h
index 793179b..f522f70 100644
--- a/device/bluetooth/test/fake_bluetooth_le_device_winrt.h
+++ b/device/bluetooth/test/fake_bluetooth_le_device_winrt.h
@@ -134,7 +134,9 @@
   void SimulateGattDisconnection();
   void SimulateDeviceBreaksConnection();
   void SimulateGattNameChange(const std::string& new_name);
-  void SimulateGattServicesDiscovered(const std::vector<std::string>& uuids);
+  void SimulateGattServicesDiscovered(
+      const std::vector<std::string>& uuids,
+      const std::vector<std::string>& blocked_uuids);
   void SimulateGattServicesChanged();
   void SimulateStatusChangeToDisconnect();
   void SimulateGattServiceRemoved(BluetoothRemoteGattService* service);
diff --git a/device/bluetooth/test/fake_gatt_device_service_winrt.cc b/device/bluetooth/test/fake_gatt_device_service_winrt.cc
index 50e2f63..be0324d 100644
--- a/device/bluetooth/test/fake_gatt_device_service_winrt.cc
+++ b/device/bluetooth/test/fake_gatt_device_service_winrt.cc
@@ -34,6 +34,8 @@
     GattDeviceServicesResult;
 using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::GattOpenStatus;
 using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
+    GattOpenStatus_AccessDenied;
+using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
     GattOpenStatus_AlreadyOpened;
 using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
     GattOpenStatus_Success;
@@ -55,11 +57,13 @@
     BluetoothTestWinrt* bluetooth_test_winrt,
     ComPtr<FakeBluetoothLEDeviceWinrt> fake_device,
     base::StringPiece uuid,
-    uint16_t attribute_handle)
+    uint16_t attribute_handle,
+    bool allowed)
     : bluetooth_test_winrt_(bluetooth_test_winrt),
       fake_device_(std::move(fake_device)),
       uuid_(BluetoothUUID::GetCanonicalValueAsGUID(uuid)),
       attribute_handle_(attribute_handle),
+      allowed_(allowed),
       characteristic_attribute_handle_(attribute_handle_) {
   fake_device_->AddReference();
 }
@@ -118,9 +122,13 @@
   if (sharing_mode != GattSharingMode_SharedReadAndWrite)
     return E_NOTIMPL;
 
-  GattOpenStatus status =
-      opened_ ? GattOpenStatus_AlreadyOpened : GattOpenStatus_Success;
-  opened_ = true;
+  GattOpenStatus status;
+  if (allowed_) {
+    status = opened_ ? GattOpenStatus_AlreadyOpened : GattOpenStatus_Success;
+    opened_ = true;
+  } else {
+    status = GattOpenStatus_AccessDenied;
+  }
 
   auto async_op = Make<base::win::AsyncOperation<GattOpenStatus>>();
   base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/device/bluetooth/test/fake_gatt_device_service_winrt.h b/device/bluetooth/test/fake_gatt_device_service_winrt.h
index 2f81757..d34ff29 100644
--- a/device/bluetooth/test/fake_gatt_device_service_winrt.h
+++ b/device/bluetooth/test/fake_gatt_device_service_winrt.h
@@ -35,7 +35,8 @@
       BluetoothTestWinrt* bluetooth_test_winrt,
       Microsoft::WRL::ComPtr<FakeBluetoothLEDeviceWinrt> fake_device,
       base::StringPiece uuid,
-      uint16_t attribute_handle);
+      uint16_t attribute_handle,
+      bool allowed);
   ~FakeGattDeviceServiceWinrt() override;
 
   // IGattDeviceService:
@@ -117,10 +118,11 @@
   void SimulateGattCharacteristic(base::StringPiece uuid, int proporties);
 
  private:
-  BluetoothTestWinrt* bluetooth_test_winrt_;
-  Microsoft::WRL::ComPtr<FakeBluetoothLEDeviceWinrt> fake_device_;
-  GUID uuid_;
-  uint16_t attribute_handle_;
+  BluetoothTestWinrt* const bluetooth_test_winrt_;
+  const Microsoft::WRL::ComPtr<FakeBluetoothLEDeviceWinrt> fake_device_;
+  const GUID uuid_;
+  const uint16_t attribute_handle_;
+  const bool allowed_;
   bool opened_ = false;
 
   std::vector<Microsoft::WRL::ComPtr<FakeGattCharacteristicWinrt>>
diff --git a/device/fido/large_blob.cc b/device/fido/large_blob.cc
index 2c5e1b1..f6633f1 100644
--- a/device/fido/large_blob.cc
+++ b/device/fido/large_blob.cc
@@ -91,9 +91,9 @@
   const std::array<uint8_t, 4> offset_array =
       fido_parsing_utils::Uint32LittleEndian(offset_);
   pin_auth.insert(pin_auth.end(), offset_array.begin(), offset_array.end());
-  if (set_) {
-    pin_auth.insert(pin_auth.end(), set_->begin(), set_->end());
-  }
+  std::array<uint8_t, crypto::kSHA256Length> set_hash =
+      crypto::SHA256Hash(*set_);
+  pin_auth.insert(pin_auth.end(), set_hash.begin(), set_hash.end());
   std::tie(pin_uv_auth_protocol_, pin_uv_auth_param_) =
       pin_uv_auth_token.PinAuth(pin_auth);
 }
diff --git a/device/fido/virtual_ctap2_device.cc b/device/fido/virtual_ctap2_device.cc
index 6118251..59ee3f0 100644
--- a/device/fido/virtual_ctap2_device.cc
+++ b/device/fido/virtual_ctap2_device.cc
@@ -564,8 +564,10 @@
   if (config.large_blob_support) {
     DCHECK(config.resident_key_support);
     DCHECK(base::Contains(config.ctap2_versions, Ctap2Version::kCtap2_1));
-    DCHECK(config.pin_uv_auth_token_support)
-        << "PinUvAuthToken support is required to write large blobs";
+    DCHECK((!config.pin_support && !config.internal_uv_support) ||
+           config.pin_uv_auth_token_support)
+        << "PinUvAuthToken support is required to write large blobs for "
+           "uv-enabled authenticators";
     options_updated = true;
     options.supports_large_blobs = true;
   }
@@ -2342,9 +2344,9 @@
             AuthenticatorSupportedOptions::UserVerificationAvailability::
                 kSupportedAndConfigured) {
       // verify(pinUvAuthToken,
-      //        32×0xff || h’0c00' || uint32LittleEndian(offset) ||
+      //        32×0xff || h’0c00' || uint32LittleEndian(offset) || SHA-256(
       //          contents of set byte string, i.e. not including an outer CBOR
-      //          tag with major type two,
+      //          tag with major type two),
       //        pinUvAuthParam)
       std::vector<uint8_t> pinauth_bytes;
       pinauth_bytes.insert(pinauth_bytes.begin(),
@@ -2355,7 +2357,10 @@
       auto offset_vec = fido_parsing_utils::Uint32LittleEndian(offset);
       pinauth_bytes.insert(pinauth_bytes.end(), offset_vec.begin(),
                            offset_vec.end());
-      pinauth_bytes.insert(pinauth_bytes.end(), set.begin(), set.end());
+      std::array<uint8_t, crypto::kSHA256Length> set_hash =
+          crypto::SHA256Hash(set);
+      pinauth_bytes.insert(pinauth_bytes.end(), set_hash.begin(),
+                           set_hash.end());
       CtapDeviceResponseCode pin_status = VerifyPINUVAuthToken(
           *device_info_, mutable_state()->pin_token, request_map,
           cbor::Value(
diff --git a/docs/ui/android/night_mode.md b/docs/ui/android/night_mode.md
index 4d1a0bf9..284ad5e 100644
--- a/docs/ui/android/night_mode.md
+++ b/docs/ui/android/night_mode.md
@@ -115,7 +115,7 @@
   * `RemoteView` is an exception. See [RemoteViewsWithNightModeInflater.java](https://cs.chromium.org/chromium/src/chrome/android/java/src/org/chromium/chrome/browser/night_mode/RemoteViewsWithNightModeInflater.java) for details.
 * Make sure color resources are accessed from `Activity` or `View` context instead of `Application` context
 * Check whether `Configuration.uiMode & UI_MODE_NIGHT_MASK` gives the correct UI night mode
-  * If uiMode is not correct, it could be a support library issue or an Android framework issue. You can contact chrome-android-app@chromium.org for help.
+  * If uiMode is not correct, it could be a support library issue or an Android framework issue. You can contact clank-app-team@google.com for help.
 
 ## Test new features in night mode
 ### Automatic Testing
diff --git a/extensions/browser/app_window/app_window_contents.cc b/extensions/browser/app_window/app_window_contents.cc
index 3928051c..686f978 100644
--- a/extensions/browser/app_window/app_window_contents.cc
+++ b/extensions/browser/app_window/app_window_contents.cc
@@ -17,7 +17,7 @@
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/app_window/native_app_window.h"
 #include "extensions/common/extension_messages.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 
 namespace extensions {
 
diff --git a/extensions/common/api/management.json b/extensions/common/api/management.json
index a44baf11..39386c5 100644
--- a/extensions/common/api/management.json
+++ b/extensions/common/api/management.json
@@ -160,7 +160,19 @@
             }
           }
         }
-     }
+      },
+      {
+        "id": "UninstallOptions",
+        "description": "Information about an icon belonging to an extension, app, or theme.",
+        "type": "object",
+        "properties": {
+          "showConfirmDialog": {
+            "type": "boolean",
+            "optional": true,
+            "description": "Whether or not a confirm-uninstall dialog should prompt the user. Defaults to false for self uninstalls. If an extension uninstalls another extension, this parameter is ignored and the dialog is always shown."
+          }
+        }
+      }
     ],
     "functions": [
       {
@@ -299,16 +311,9 @@
             "description": "This should be the id from an item of $(ref:management.ExtensionInfo)."
           },
           {
-            "type": "object",
             "name": "options",
-            "optional": true,
-            "properties": {
-              "showConfirmDialog": {
-                "type": "boolean",
-                "optional": true,
-                "description": "Whether or not a confirm-uninstall dialog should prompt the user. Defaults to false for self uninstalls. If an extension uninstalls another extension, this parameter is ignored and the dialog is always shown."
-              }
-            }
+            "$ref": "UninstallOptions",
+            "optional": true
           },
           {
             "name": "callback",
@@ -323,16 +328,9 @@
         "description": "Uninstalls the calling extension. Note: This function can be used without requesting the 'management' permission in the manifest.",
         "parameters": [
           {
-            "type": "object",
             "name": "options",
-            "optional": true,
-            "properties": {
-              "showConfirmDialog": {
-                "type": "boolean",
-                "optional": true,
-                "description": "Whether or not a confirm-uninstall dialog should prompt the user. Defaults to false."
-              }
-            }
+            "$ref": "UninstallOptions",
+            "optional": true
           },
           {
             "name": "callback",
diff --git a/fuchsia/cast_streaming/cast_message_port_impl.cc b/fuchsia/cast_streaming/cast_message_port_impl.cc
index e362fe7..65bd137 100644
--- a/fuchsia/cast_streaming/cast_message_port_impl.cc
+++ b/fuchsia/cast_streaming/cast_message_port_impl.cc
@@ -273,6 +273,11 @@
              << ", namespace=" << message_namespace
              << ", message=" << str_message;
   }
+
+  // Acknowledge the message and unblock the receipt of another.
+  fuchsia::web::MessagePort_PostMessage_Result result;
+  result.set_response(fuchsia::web::MessagePort_PostMessage_Response());
+  callback(std::move(result));
 }
 
 void CastMessagePortImpl::ReceiveMessage(
diff --git a/gpu/command_buffer/service/external_semaphore_pool.cc b/gpu/command_buffer/service/external_semaphore_pool.cc
index 2d8af08..e4a8180 100644
--- a/gpu/command_buffer/service/external_semaphore_pool.cc
+++ b/gpu/command_buffer/service/external_semaphore_pool.cc
@@ -15,11 +15,14 @@
 namespace gpu {
 namespace {
 
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_FUCHSIA)
 // On Android, semaphores are created with handle type
 // VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT. With this handle type,
 // the semaphore will not be reset to un-signalled state after waiting,
 // so semaphores cannot be reused on Android.
+// On Fuchsia semaphores are passed to scenic as zx::event. Scenic doesn't reset
+// them after waiting, so they would have to be reset explicitly to be reused.
+// OTOH new semaphores are cheap, so reuse doesn't provide significant benefits.
 constexpr size_t kMaxSemaphoresInPool = 0;
 #else
 constexpr size_t kMaxSemaphoresInPool = 16;
diff --git a/gpu/command_buffer/service/shared_context_state.cc b/gpu/command_buffer/service/shared_context_state.cc
index eaf0b3a..314bbf06 100644
--- a/gpu/command_buffer/service/shared_context_state.cc
+++ b/gpu/command_buffer/service/shared_context_state.cc
@@ -301,6 +301,7 @@
     // in GetCapabilities and ensuring these are also used by the
     // PaintOpBufferSerializer.
     GrContextOptions options = GetDefaultGrContextOptions(GrContextType::kGL);
+    options.fSuppressMipmapSupport = workarounds.disable_mipmap_generation;
     options.fDriverBugWorkarounds =
         GrDriverBugWorkarounds(workarounds.ToIntSet());
     options.fPersistentCache = cache;
diff --git a/gpu/config/gpu_workaround_list.txt b/gpu/config/gpu_workaround_list.txt
index 5233bf15..dc7dfb38 100644
--- a/gpu/config/gpu_workaround_list.txt
+++ b/gpu/config/gpu_workaround_list.txt
@@ -39,6 +39,7 @@
 disable_imagebitmap_from_video_using_gpu
 disable_larger_than_screen_overlays
 disable_mediafoundation_async_h264_encoding
+disable_mipmap_generation
 disable_multisampling_color_mask_usage
 disable_nv12_dxgi_video
 disable_nv12_dynamic_textures
diff --git a/gpu/ipc/service/image_transport_surface_win.cc b/gpu/ipc/service/image_transport_surface_win.cc
index 3eef9c5..1c6f9f6 100644
--- a/gpu/ipc/service/image_transport_surface_win.cc
+++ b/gpu/ipc/service/image_transport_surface_win.cc
@@ -17,6 +17,7 @@
 #include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_surface_egl.h"
 #include "ui/gl/gl_switches.h"
+#include "ui/gl/gl_utils.h"
 #include "ui/gl/init/gl_factory.h"
 #include "ui/gl/vsync_provider_win.h"
 
@@ -34,6 +35,9 @@
   settings.use_angle_texture_offset = features::IsUsingSkiaRenderer();
   settings.reset_vp_when_colorspace_changes =
       workarounds.reset_vp_when_colorspace_changes;
+  settings.force_root_surface_full_damage =
+      features::IsUsingSkiaRenderer() &&
+      gl::ShouldForceDirectCompositionRootSurfaceFullDamage();
   return settings;
 }
 }  // namespace
diff --git a/headless/app/headless_shell_switches.cc b/headless/app/headless_shell_switches.cc
index cace234..19302330 100644
--- a/headless/app/headless_shell_switches.cc
+++ b/headless/app/headless_shell_switches.cc
@@ -75,6 +75,9 @@
 // affects HTTP and HTTPS requests.
 const char kProxyServer[] = "proxy-server";
 
+// Do not use system proxy configuration service.
+const char kNoSystemProxyConfigService[] = "no-system-proxy-config-service";
+
 // Use the given address instead of the default loopback for accepting remote
 // debugging connections. Should be used together with --remote-debugging-port.
 // Note that the remote debugging protocol does not perform any authentication,
diff --git a/headless/app/headless_shell_switches.h b/headless/app/headless_shell_switches.h
index 27e3c5b..3011369 100644
--- a/headless/app/headless_shell_switches.h
+++ b/headless/app/headless_shell_switches.h
@@ -27,6 +27,7 @@
 HEADLESS_EXPORT extern const char kPrintToPDFNoHeader[];
 HEADLESS_EXPORT extern const char kProxyBypassList[];
 HEADLESS_EXPORT extern const char kProxyServer[];
+HEADLESS_EXPORT extern const char kNoSystemProxyConfigService[];
 HEADLESS_EXPORT extern const char kRemoteDebuggingAddress[];
 HEADLESS_EXPORT extern const char kRepl[];
 HEADLESS_EXPORT extern const char kScreenshot[];
diff --git a/headless/lib/browser/DEPS b/headless/lib/browser/DEPS
index dc784cce..2884f436 100644
--- a/headless/lib/browser/DEPS
+++ b/headless/lib/browser/DEPS
@@ -12,7 +12,7 @@
   "+storage/common/quota",
   "+third_party/skia/include",
   "+third_party/blink/public/mojom/quota",
-  "+third_party/blink/public/mojom/renderer_preferences.mojom.h",
+  "+third_party/blink/public/common/renderer_preferences/renderer_preferences.h",
   "+ui/aura",
   "+ui/compositor",
   "+ui/events/keycodes/dom",
diff --git a/headless/lib/browser/headless_request_context_manager.cc b/headless/lib/browser/headless_request_context_manager.cc
index ebd811c..4148c58 100644
--- a/headless/lib/browser/headless_request_context_manager.cc
+++ b/headless/lib/browser/headless_request_context_manager.cc
@@ -210,8 +210,13 @@
               : nullptr),
       resource_context_(std::make_unique<content::ResourceContext>()) {
   if (!proxy_config_) {
-    proxy_config_monitor_ = std::make_unique<HeadlessProxyConfigMonitor>(
-        base::ThreadTaskRunnerHandle::Get());
+    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+    if (command_line->HasSwitch(switches::kNoSystemProxyConfigService)) {
+      proxy_config_ = std::make_unique<net::ProxyConfig>();
+    } else {
+      proxy_config_monitor_ = std::make_unique<HeadlessProxyConfigMonitor>(
+          base::ThreadTaskRunnerHandle::Get());
+    }
   }
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
   auto crypt_config = BuildCryptConfigOnce(user_data_path_);
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc
index f3cd399a..8bb3024c 100644
--- a/headless/lib/browser/headless_web_contents_impl.cc
+++ b/headless/lib/browser/headless_web_contents_impl.cc
@@ -40,7 +40,7 @@
 #include "headless/lib/browser/protocol/headless_handler.h"
 #include "headless/public/internal/headless_devtools_client_impl.h"
 #include "printing/buildflags/buildflags.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/compositor/compositor.h"
 #include "ui/gfx/switches.h"
diff --git a/headless/test/headless_protocol_browsertest.cc b/headless/test/headless_protocol_browsertest.cc
index e797a672..b9c0f8b 100644
--- a/headless/test/headless_protocol_browsertest.cc
+++ b/headless/test/headless_protocol_browsertest.cc
@@ -16,6 +16,7 @@
 #include "components/viz/common/switches.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test.h"
+#include "headless/app/headless_shell_switches.h"
 #include "headless/public/devtools/domains/runtime.h"
 #include "headless/public/headless_browser.h"
 #include "headless/public/headless_browser_context.h"
@@ -56,6 +57,10 @@
     // Make sure the navigations spawn new processes. We run test harness
     // in one process (harness.test) and tests in another.
     command_line->AppendSwitch(::switches::kSitePerProcess);
+
+    // Make sure proxy related tests are not affected by a platform specific
+    // system proxy configuration service.
+    command_line->AppendSwitch(switches::kNoSystemProxyConfigService);
   }
 
  private:
@@ -286,8 +291,8 @@
     static const char* const compositor_switches[] = {
         // We control BeginFrames ourselves and need all compositing stages to
         // run.
-        switches::kRunAllCompositorStagesBeforeDraw,
-        switches::kDisableNewContentRenderingTimeout,
+        ::switches::kRunAllCompositorStagesBeforeDraw,
+        ::switches::kDisableNewContentRenderingTimeout,
 
         // Animtion-only BeginFrames are only supported when updates from the
         // impl-thread are disabled, see go/headless-rendering.
@@ -433,13 +438,7 @@
 
 HEADLESS_PROTOCOL_COMPOSITOR_TEST(RendererOpacityAnimation,
                                   "sanity/renderer-opacity-animation.js")
-// Flaky on Windows (crbug.com/1134929).
-#if defined(OS_WIN)
-#define MAYBE_BrowserSetInitialProxyConfig DISABLED_BrowserSetInitialProxyConfig
-#else
-#define MAYBE_BrowserSetInitialProxyConfig BrowserSetInitialProxyConfig
-#endif
-HEADLESS_PROTOCOL_COMPOSITOR_TEST(MAYBE_BrowserSetInitialProxyConfig,
+HEADLESS_PROTOCOL_COMPOSITOR_TEST(BrowserSetInitialProxyConfig,
                                   "sanity/browser-set-initial-proxy-config.js")
 
 }  // namespace headless
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index 217b0e6..e9be584e 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -39,7 +39,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -76,7 +76,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -113,7 +113,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -150,7 +150,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -187,7 +187,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -224,7 +224,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -261,7 +261,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -298,7 +298,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -335,7 +335,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -372,7 +372,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -419,7 +419,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -466,7 +466,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -513,7 +513,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -560,7 +560,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -607,7 +607,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -654,7 +654,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -701,7 +701,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -748,7 +748,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -795,7 +795,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -842,7 +842,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -889,7 +889,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -936,7 +936,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -983,7 +983,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1030,7 +1030,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1077,7 +1077,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1124,7 +1124,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1161,7 +1161,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1198,7 +1198,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1235,7 +1235,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1272,7 +1272,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1309,7 +1309,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1346,7 +1346,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1383,7 +1383,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1420,7 +1420,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1457,7 +1457,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1494,7 +1494,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1531,7 +1531,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1568,7 +1568,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1605,7 +1605,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1642,7 +1642,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1679,7 +1679,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1726,7 +1726,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1773,7 +1773,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1810,7 +1810,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1847,7 +1847,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1884,7 +1884,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1921,7 +1921,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1958,7 +1958,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -1995,7 +1995,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2032,7 +2032,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2069,7 +2069,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2104,7 +2104,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2139,7 +2139,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2176,7 +2176,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2213,7 +2213,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2250,7 +2250,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2287,7 +2287,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2324,7 +2324,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2361,7 +2361,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2398,7 +2398,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2435,7 +2435,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2472,7 +2472,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2509,7 +2509,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2546,7 +2546,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2583,7 +2583,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2620,7 +2620,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2657,7 +2657,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2694,7 +2694,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2731,7 +2731,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2768,7 +2768,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2805,7 +2805,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2842,7 +2842,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2879,7 +2879,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2916,7 +2916,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2953,7 +2953,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -2990,7 +2990,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3027,7 +3027,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3064,7 +3064,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3111,7 +3111,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3158,7 +3158,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3205,7 +3205,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3250,7 +3250,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3295,7 +3295,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3340,7 +3340,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3387,7 +3387,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3434,7 +3434,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3481,7 +3481,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3528,7 +3528,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3575,7 +3575,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3622,7 +3622,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3669,7 +3669,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3716,7 +3716,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3763,7 +3763,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3810,7 +3810,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3857,7 +3857,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3904,7 +3904,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3949,7 +3949,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -3994,7 +3994,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4041,7 +4041,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4088,7 +4088,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4135,7 +4135,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4172,7 +4172,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4209,7 +4209,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4246,7 +4246,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4283,7 +4283,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4319,7 +4319,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4356,7 +4356,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4393,7 +4393,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4430,7 +4430,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4467,7 +4467,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4504,7 +4504,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4541,7 +4541,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4577,7 +4577,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4613,7 +4613,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4650,7 +4650,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4687,7 +4687,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4724,7 +4724,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4761,7 +4761,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4798,7 +4798,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4835,7 +4835,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4872,7 +4872,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4909,7 +4909,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4946,7 +4946,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -4983,7 +4983,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5020,7 +5020,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5057,7 +5057,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5094,7 +5094,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5141,7 +5141,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5188,7 +5188,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5235,7 +5235,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5282,7 +5282,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5329,7 +5329,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5376,7 +5376,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5423,7 +5423,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5470,7 +5470,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5517,7 +5517,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5564,7 +5564,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5611,7 +5611,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5658,7 +5658,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5705,7 +5705,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5752,7 +5752,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5799,7 +5799,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5836,7 +5836,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5873,7 +5873,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5910,7 +5910,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5947,7 +5947,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -5984,7 +5984,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6031,7 +6031,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6068,7 +6068,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6105,7 +6105,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6142,7 +6142,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6290,7 +6290,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6327,7 +6327,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6364,7 +6364,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6401,7 +6401,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6437,7 +6437,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6473,7 +6473,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6508,7 +6508,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6544,7 +6544,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6579,7 +6579,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6614,7 +6614,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6685,7 +6685,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6732,7 +6732,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6779,7 +6779,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6826,7 +6826,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6873,7 +6873,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6918,7 +6918,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -6965,7 +6965,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7012,7 +7012,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7059,7 +7059,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7106,7 +7106,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7153,7 +7153,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7198,7 +7198,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7245,7 +7245,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7292,7 +7292,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7339,7 +7339,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7386,7 +7386,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7433,7 +7433,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7480,7 +7480,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7597,7 +7597,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7634,7 +7634,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7671,7 +7671,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7708,7 +7708,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7745,7 +7745,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7782,7 +7782,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7819,7 +7819,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7856,7 +7856,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7893,7 +7893,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7930,7 +7930,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -7967,7 +7967,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8004,7 +8004,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8041,7 +8041,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8077,7 +8077,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8114,7 +8114,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8151,7 +8151,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8188,7 +8188,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8262,7 +8262,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8299,7 +8299,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8336,7 +8336,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8373,7 +8373,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8410,7 +8410,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8447,7 +8447,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8484,7 +8484,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8521,7 +8521,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8558,7 +8558,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8595,7 +8595,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8632,7 +8632,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8669,7 +8669,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8705,7 +8705,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8742,7 +8742,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8779,7 +8779,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8816,7 +8816,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8853,7 +8853,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8890,7 +8890,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8927,7 +8927,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -8964,7 +8964,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9001,7 +9001,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9038,7 +9038,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9075,7 +9075,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9112,7 +9112,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9149,7 +9149,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9186,7 +9186,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9223,7 +9223,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9260,7 +9260,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9297,7 +9297,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9337,7 +9337,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9377,7 +9377,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9414,7 +9414,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9451,7 +9451,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9488,7 +9488,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9562,7 +9562,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9599,7 +9599,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9636,7 +9636,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9672,7 +9672,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9744,7 +9744,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9780,7 +9780,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9816,7 +9816,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9852,7 +9852,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9888,7 +9888,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9924,7 +9924,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9961,7 +9961,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -9998,7 +9998,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10045,7 +10045,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10092,7 +10092,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10139,7 +10139,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10186,7 +10186,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10233,7 +10233,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10280,7 +10280,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10327,7 +10327,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10374,7 +10374,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10421,7 +10421,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10468,7 +10468,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10515,7 +10515,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10562,7 +10562,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10609,7 +10609,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10656,7 +10656,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10702,7 +10702,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10738,7 +10738,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10847,7 +10847,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10894,7 +10894,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10940,7 +10940,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -10977,7 +10977,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11024,7 +11024,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11071,7 +11071,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11118,7 +11118,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11165,7 +11165,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11212,7 +11212,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11258,7 +11258,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11294,7 +11294,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11330,7 +11330,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11367,7 +11367,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11404,7 +11404,7 @@
       service_account: "chromium-cipd-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11441,7 +11441,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11478,7 +11478,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11515,7 +11515,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11552,7 +11552,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11589,7 +11589,7 @@
       service_account: "chromium-cipd-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11626,7 +11626,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11663,7 +11663,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11774,7 +11774,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11811,7 +11811,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11848,7 +11848,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11885,7 +11885,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11922,7 +11922,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11959,7 +11959,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -11996,7 +11996,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12033,7 +12033,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12067,7 +12067,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12104,7 +12104,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12141,7 +12141,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12178,7 +12178,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12215,7 +12215,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12252,7 +12252,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12359,7 +12359,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12396,7 +12396,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12433,7 +12433,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12470,7 +12470,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12507,7 +12507,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12544,7 +12544,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12581,7 +12581,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12618,7 +12618,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12655,7 +12655,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12692,7 +12692,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12729,7 +12729,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12766,7 +12766,7 @@
       service_account: "chromium-cipd-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12803,7 +12803,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12840,7 +12840,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12877,7 +12877,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12914,7 +12914,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12951,7 +12951,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -12988,7 +12988,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -13025,7 +13025,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -13099,7 +13099,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -13136,7 +13136,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -13173,7 +13173,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -13210,7 +13210,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -13247,7 +13247,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -13432,7 +13432,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -13469,7 +13469,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -13506,7 +13506,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -13584,7 +13584,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -13623,7 +13623,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -13780,7 +13780,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -13858,7 +13858,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -14271,7 +14271,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -14308,7 +14308,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -14382,7 +14382,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -14713,7 +14713,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -14787,7 +14787,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -14972,7 +14972,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -15083,7 +15083,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -15157,7 +15157,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -15193,7 +15193,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -15230,7 +15230,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -15304,7 +15304,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -15341,7 +15341,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -15378,7 +15378,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -15415,7 +15415,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -15452,7 +15452,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -15489,7 +15489,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -15526,7 +15526,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -15563,7 +15563,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -15637,7 +15637,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -15787,7 +15787,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -15823,7 +15823,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -15858,7 +15858,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -15895,7 +15895,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -16004,7 +16004,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -16039,7 +16039,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -16146,7 +16146,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -16441,7 +16441,7 @@
       service_account: "component-mapping-updater@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -16619,7 +16619,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -16655,7 +16655,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -16692,7 +16692,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -16728,7 +16728,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -16764,7 +16764,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -16800,7 +16800,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -16944,7 +16944,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -16981,7 +16981,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -17018,7 +17018,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -17055,7 +17055,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -17092,7 +17092,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -17129,7 +17129,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -17166,7 +17166,7 @@
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -17312,7 +17312,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -17348,7 +17348,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -17420,7 +17420,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 50
       }
       experiments {
         key: "luci.use_realms"
@@ -17515,7 +17515,7 @@
       service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -17557,7 +17557,7 @@
       service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -17599,7 +17599,7 @@
       service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -17641,7 +17641,7 @@
       service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -17683,7 +17683,7 @@
       service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -17725,7 +17725,7 @@
       service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -19900,7 +19900,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -19945,7 +19945,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -19990,7 +19990,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20035,7 +20035,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20080,7 +20080,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20125,7 +20125,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20170,7 +20170,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20215,7 +20215,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20260,7 +20260,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20305,7 +20305,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20350,7 +20350,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20395,7 +20395,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20440,7 +20440,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20485,7 +20485,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20530,7 +20530,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20575,7 +20575,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20620,7 +20620,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20665,7 +20665,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20710,7 +20710,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20755,7 +20755,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20800,7 +20800,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20845,7 +20845,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20890,7 +20890,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20935,7 +20935,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -20980,7 +20980,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21025,7 +21025,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21070,7 +21070,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21115,7 +21115,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21159,7 +21159,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21203,7 +21203,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21247,7 +21247,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21291,7 +21291,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21335,7 +21335,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21379,7 +21379,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21424,7 +21424,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21469,7 +21469,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21514,7 +21514,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21559,7 +21559,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21604,7 +21604,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21649,7 +21649,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21694,7 +21694,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21739,7 +21739,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21784,7 +21784,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21829,7 +21829,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21874,7 +21874,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21918,7 +21918,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -21963,7 +21963,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22008,7 +22008,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22053,7 +22053,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22098,7 +22098,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22143,7 +22143,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22188,7 +22188,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22233,7 +22233,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22278,7 +22278,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22323,7 +22323,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22368,7 +22368,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22413,7 +22413,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22458,7 +22458,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22501,7 +22501,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22544,7 +22544,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22587,7 +22587,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22630,7 +22630,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22673,7 +22673,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22716,7 +22716,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22760,7 +22760,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22805,7 +22805,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22850,7 +22850,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22895,7 +22895,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22940,7 +22940,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -22985,7 +22985,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23030,7 +23030,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23075,7 +23075,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23120,7 +23120,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23165,7 +23165,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23210,7 +23210,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23254,7 +23254,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23298,7 +23298,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23342,7 +23342,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23386,7 +23386,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23430,7 +23430,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23474,7 +23474,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23518,7 +23518,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23562,7 +23562,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23606,7 +23606,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23650,7 +23650,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23694,7 +23694,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23738,7 +23738,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23782,7 +23782,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23826,7 +23826,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23870,7 +23870,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23914,7 +23914,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -23958,7 +23958,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24002,7 +24002,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24046,7 +24046,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24090,7 +24090,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24134,7 +24134,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24178,7 +24178,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24222,7 +24222,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24266,7 +24266,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24310,7 +24310,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24354,7 +24354,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24398,7 +24398,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24441,7 +24441,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24484,7 +24484,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24527,7 +24527,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24570,7 +24570,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24613,7 +24613,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24656,7 +24656,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24699,7 +24699,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24742,7 +24742,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24785,7 +24785,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24828,7 +24828,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24871,7 +24871,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24914,7 +24914,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -24957,7 +24957,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25000,7 +25000,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25044,7 +25044,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25088,7 +25088,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25132,7 +25132,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25176,7 +25176,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25220,7 +25220,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25264,7 +25264,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25308,7 +25308,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25352,7 +25352,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25396,7 +25396,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25440,7 +25440,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25484,7 +25484,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25528,7 +25528,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25572,7 +25572,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25616,7 +25616,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25660,7 +25660,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25704,7 +25704,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25748,7 +25748,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25792,7 +25792,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25836,7 +25836,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25880,7 +25880,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25923,7 +25923,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -25966,7 +25966,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26010,7 +26010,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26057,7 +26057,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26104,7 +26104,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26151,7 +26151,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26198,7 +26198,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26245,7 +26245,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26292,7 +26292,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26339,7 +26339,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26386,7 +26386,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26433,7 +26433,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26480,7 +26480,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26527,7 +26527,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26574,7 +26574,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26619,7 +26619,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26664,7 +26664,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26708,7 +26708,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26753,7 +26753,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26798,7 +26798,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26843,7 +26843,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26888,7 +26888,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26933,7 +26933,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -26978,7 +26978,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27023,7 +27023,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27068,7 +27068,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27113,7 +27113,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27158,7 +27158,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27203,7 +27203,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27248,7 +27248,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27293,7 +27293,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27336,7 +27336,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27381,7 +27381,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27426,7 +27426,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27471,7 +27471,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27516,7 +27516,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27561,7 +27561,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27606,7 +27606,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27651,7 +27651,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27696,7 +27696,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27741,7 +27741,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27786,7 +27786,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27831,7 +27831,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27876,7 +27876,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27920,7 +27920,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -27965,7 +27965,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28010,7 +28010,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28055,7 +28055,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28100,7 +28100,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28145,7 +28145,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28190,7 +28190,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28235,7 +28235,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28280,7 +28280,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28325,7 +28325,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28370,7 +28370,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28415,7 +28415,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28460,7 +28460,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28505,7 +28505,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28550,7 +28550,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28594,7 +28594,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28638,7 +28638,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28683,7 +28683,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28728,7 +28728,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28773,7 +28773,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28818,7 +28818,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28863,7 +28863,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28908,7 +28908,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28953,7 +28953,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -28998,7 +28998,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29043,7 +29043,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29092,7 +29092,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29137,7 +29137,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29186,7 +29186,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29231,7 +29231,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29276,7 +29276,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29321,7 +29321,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29366,7 +29366,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29411,7 +29411,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29456,7 +29456,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29501,7 +29501,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29545,7 +29545,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29590,7 +29590,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29635,7 +29635,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29678,7 +29678,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29722,7 +29722,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29765,7 +29765,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29808,7 +29808,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29852,7 +29852,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29896,7 +29896,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29939,7 +29939,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -29983,7 +29983,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30027,7 +30027,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30071,7 +30071,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30115,7 +30115,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30159,7 +30159,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30203,7 +30203,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30247,7 +30247,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30291,7 +30291,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30335,7 +30335,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30379,7 +30379,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30423,7 +30423,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30467,7 +30467,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30511,7 +30511,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30555,7 +30555,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30599,7 +30599,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30643,7 +30643,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30686,7 +30686,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30730,7 +30730,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30775,7 +30775,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30820,7 +30820,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30865,7 +30865,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30909,7 +30909,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30953,7 +30953,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -30997,7 +30997,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31041,7 +31041,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31086,7 +31086,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31131,7 +31131,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31176,7 +31176,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31219,7 +31219,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31263,7 +31263,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31308,7 +31308,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31353,7 +31353,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31398,7 +31398,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31443,7 +31443,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31488,7 +31488,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31533,7 +31533,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31578,7 +31578,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31623,7 +31623,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31668,7 +31668,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31712,7 +31712,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31757,7 +31757,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31802,7 +31802,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31846,7 +31846,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31891,7 +31891,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31936,7 +31936,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -31981,7 +31981,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -32026,7 +32026,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -32071,7 +32071,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -32116,7 +32116,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -32161,7 +32161,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -32206,7 +32206,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -32251,7 +32251,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -32296,7 +32296,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -32340,7 +32340,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
@@ -32385,7 +32385,7 @@
       }
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 10
+        value: 0
       }
       experiments {
         key: "luci.use_realms"
diff --git a/infra/config/generated/luci-scheduler.cfg b/infra/config/generated/luci-scheduler.cfg
index 4e598a1..2c1a5fe 100644
--- a/infra/config/generated/luci-scheduler.cfg
+++ b/infra/config/generated/luci-scheduler.cfg
@@ -4624,6 +4624,10 @@
 job {
   id: "android-weblayer-x86-fyi-rel-10-tests"
   realm: "ci"
+  acls {
+    role: TRIGGERER
+    granted_to: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+  }
   acl_sets: "ci"
   buildbucket {
     server: "cr-buildbucket.appspot.com"
@@ -6410,7 +6414,6 @@
   triggers: "android-pie-x86-rel"
   triggers: "android-weblayer-pie-x86-fyi-rel"
   triggers: "android-weblayer-x86-fyi-rel"
-  triggers: "android-weblayer-x86-fyi-rel-10-tests"
   triggers: "chromeos-amd64-generic-asan-rel"
   triggers: "chromeos-amd64-generic-cfi-thin-lto-rel"
   triggers: "chromeos-amd64-generic-dbg"
diff --git a/infra/config/lib/ci.star b/infra/config/lib/ci.star
index 57757ac..3209deb 100644
--- a/infra/config/lib/ci.star
+++ b/infra/config/lib/ci.star
@@ -396,9 +396,9 @@
     ]
     merged_resultdb_bigquery_exports.extend(resultdb_bigquery_exports or [])
 
-    # Enable "chromium.resultdb.result_sink" on all ci builders for 10% by default.
+    # Enable "chromium.resultdb.result_sink" on all ci builders for 50% by default.
     experiments = experiments or {}
-    experiments.setdefault("chromium.resultdb.result_sink", 10)
+    experiments.setdefault("chromium.resultdb.result_sink", 50)
 
     # Define the builder first so that any validation of luci.builder arguments
     # (e.g. bucket) occurs before we try to use it
diff --git a/infra/config/lib/try.star b/infra/config/lib/try.star
index 63107a7..c5c6715 100644
--- a/infra/config/lib/try.star
+++ b/infra/config/lib/try.star
@@ -155,9 +155,9 @@
     if not branches.matches(branch_selector):
         return
 
-    # Enable "chromium.resultdb.result_sink" on all try builders for 10% by default.
+    # Disable "chromium.resultdb.result_sink" on all try builders by default.
     experiments = experiments or {}
-    experiments.setdefault("chromium.resultdb.result_sink", 10)
+    experiments.setdefault("chromium.resultdb.result_sink", 0)
 
     # Define the builder first so that any validation of luci.builder arguments
     # (e.g. bucket) occurs before we try to use it
diff --git a/infra/config/subprojects/chromium/ci.star b/infra/config/subprojects/chromium/ci.star
index c7302fc..b8c4590 100644
--- a/infra/config/subprojects/chromium/ci.star
+++ b/infra/config/subprojects/chromium/ci.star
@@ -996,6 +996,7 @@
         category = "tester|weblayer",
         short_name = "10",
     ),
+    triggered_by = ["android-weblayer-x86-fyi-rel"],
 )
 
 ci.android_fyi_builder(
diff --git a/ios/build/bots/scripts/PRESUBMIT.py b/ios/build/bots/scripts/PRESUBMIT.py
index 85b1c81..ac3ad27 100644
--- a/ios/build/bots/scripts/PRESUBMIT.py
+++ b/ios/build/bots/scripts/PRESUBMIT.py
@@ -22,7 +22,7 @@
       'test_apps_test.py',
       # 'test_runner_test.py',
       'wpr_runner_test.py',
-      # 'xcode_log_parser_test.py',
+      'xcode_log_parser_test.py',
       # 'xcodebuild_runner_test.py',
   ]
 
diff --git a/ios/build/bots/scripts/xcode_log_parser.py b/ios/build/bots/scripts/xcode_log_parser.py
index c9ccbe0..6605480 100644
--- a/ios/build/bots/scripts/xcode_log_parser.py
+++ b/ios/build/bots/scripts/xcode_log_parser.py
@@ -166,6 +166,7 @@
       xcresult: (str) A path to xcresult.
       results: (dict) A dictionary with passed and failed tests.
     """
+    # See TESTS_REF in xcode_log_parser_test.py for an example of |root|.
     root = json.loads(Xcode11LogParser._xcresulttool_get(xcresult, 'testsRef'))
     for summary in root['summaries']['_values'][0][
         'testableSummaries']['_values']:
@@ -187,7 +188,8 @@
           if test['testStatus']['_value'] == 'Success':
             results['passed'].append(test_name)
           else:
-            # Parse data for failed test by its id.
+            # Parse data for failed test by its id. See SINGLE_TEST_SUMMARY_REF
+            # in xcode_log_parser_test.py for an example of |rootFailure|.
             rootFailure = json.loads(
                 Xcode11LogParser._xcresulttool_get(
                     xcresult, test['summaryRef']['id']['_value']))
@@ -204,11 +206,12 @@
             results['failed'][test_name] = failure_message
 
   @staticmethod
-  def collect_test_results(xcresult, output):
-    """Gets test result and diagnostic data from xcresult.
+  def collect_test_results(output_path, output):
+    """Gets test result, diagnostic data & artifacts from xcresult.
 
     Args:
-      xcresult: (str) A path to xcresult.
+      output_path: (str) An output path passed in --resultBundlePath when
+          running xcodebuild.
       output: [str] An output of test run.
 
     Returns:
@@ -220,26 +223,26 @@
           }
         }
     """
-    LOGGER.info('Reading %s' % xcresult)
+    LOGGER.info('Reading %s' % output_path)
     test_results = {
         'passed': [],
         'failed': {}
     }
-    if not os.path.exists(xcresult):
-      test_results['failed']['TESTS_DID_NOT_START'] = [
-          '%s with test results does not exist.' % xcresult]
-      return test_results
 
     # During a run `xcodebuild .. -resultBundlePath %output_path%`
     # that generates output_path folder,
     # but Xcode 11+ generates `output_path.xcresult` and `output_path`
     # where output_path.xcresult is a folder with results and `output_path`
     # is symlink to the `output_path.xcresult` folder.
-    # `xcresulttool` with folder/symlink behaves
-    # in different way on laptop and on bots.
-    # To support debugging added this check.
-    if not xcresult.endswith('.xcresult'):
-      xcresult += '.xcresult'
+    # `xcresulttool` with folder/symlink behaves in different way on laptop and
+    # on bots. This piece of code uses .xcresult folder.
+    xcresult = output_path + '.xcresult'
+
+    if not os.path.exists(xcresult):
+      test_results['failed']['TESTS_DID_NOT_START'] = [
+          '%s with test results does not exist.' % xcresult
+      ]
+      return test_results
 
     plist_path = os.path.join(xcresult, 'Info.plist')
     if not os.path.exists(plist_path):
@@ -248,6 +251,7 @@
       test_results['passed'] = parse_passed_tests_for_interrupted_run(output)
       return test_results
 
+    # See XCRESULT_ROOT in xcode_log_parser_test.py for an example of |root|.
     root = json.loads(Xcode11LogParser._xcresulttool_get(xcresult))
     metrics = root['metrics']
     # In case of test crash both numbers of run and failed tests are equal to 0.
@@ -259,35 +263,123 @@
       test_results['failed'] = Xcode11LogParser._list_of_failed_tests(root)
       Xcode11LogParser._get_test_statuses(xcresult, test_results)
     Xcode11LogParser._export_diagnostic_data(xcresult)
+    Xcode11LogParser._copy_artifacts(xcresult)
+    # Remove the symbol link file.
+    if os.path.islink(output_path):
+      os.unlink(output_path)
+    Xcode11LogParser._zip_and_remove_folder(xcresult)
     return test_results
 
   @staticmethod
-  def copy_screenshots(output_folder):
-    """Copy screenshots of failed tests to output folder.
+  def _copy_artifacts(xcresult):
+    """Copy screenshots, crash logs of failed tests to output folder.
 
     Args:
-      output_folder: (str) A full path to folder where
+      xcresult: (str) A path to xcresult directory.
     """
-    plist_path = os.path.join(output_folder + '.xcresult', 'Info.plist')
-    if not os.path.exists(plist_path):
-      LOGGER.info('%s does not exist.' % plist_path)
+    if not os.path.exists(xcresult):
+      LOGGER.warn('%s does not exist.' % xcresult)
       return
 
-    root = json.loads(Xcode11LogParser._xcresulttool_get(output_folder))
-    if 'testFailureSummaries' not in root['issues']:
-      LOGGER.info('No failures in %s' % output_folder)
+    root = json.loads(Xcode11LogParser._xcresulttool_get(xcresult))
+    if 'testFailureSummaries' not in root.get('issues', {}):
+      LOGGER.info('No failures in %s' % xcresult)
       return
 
-    for failure_summary in root['issues']['testFailureSummaries']['_values']:
-      test_case = failure_summary['testCaseName']['_value']
-      test_case_folder = os.path.join(output_folder, 'failures',
-                                      format_test_case(test_case))
-      copy_screenshots_for_failed_test(failure_summary['message']['_value'],
-                                       test_case_folder)
+    # See TESTS_REF['summaries']['_values'] in xcode_log_parser_test.py.
+    test_summaries = json.loads(
+        Xcode11LogParser._xcresulttool_get(xcresult, 'testsRef')).get(
+            'summaries', {}).get('_values', [])
+
+    test_summary_refs = {}
+
+    for summaries in test_summaries:
+      for summary in summaries.get('testableSummaries', {}).get('_values', []):
+        for all_tests in summary.get('tests', {}).get('_values', []):
+          for test_suite in all_tests.get('subtests', {}).get('_values', []):
+            for test_case in test_suite.get('subtests', {}).get('_values', []):
+              for test in test_case.get('subtests', {}).get('_values', []):
+                if test['testStatus']['_value'] != 'Success':
+                  test_summary_refs[
+                      test['identifier']
+                      ['_value']] = test['summaryRef']['id']['_value']
+
+    def extract_attachments(test,
+                            test_activities,
+                            xcresult,
+                            include_jpg=True,
+                            attachment_index=0):
+      """Exrtact attachments from xcretult folder.
+
+      Copies all attachments under test_activities and nested subactivities(if
+      any) to the same directory as xcresult directory. Uses incremental
+      attachment_index starting from attachment_index + 1.
+
+      Args:
+        test: (str) Test name.
+        test_activities: (list) List of test activities (dict) that
+            store data about each test step.
+        xcresult: (str) A path to test results.
+        include_jpg: (bool) Whether include jpg or jpeg attachments.
+        attachment_index: (int) An attachment index, used as an incremental id
+            for file names in format
+            `attempt_%d_TestCase_testMethod_attachment_index`:
+              attempt_0_TestCase_testMethod_1.jpg
+              ....
+              attempt_0_TestCase_testMethod_3.crash
+
+      Returns:
+        Last used attachment_index.
+      """
+      for activity_summary in test_activities:
+        if 'subactivities' in activity_summary:
+          attachment_index = extract_attachments(
+              test,
+              activity_summary.get('subactivities', {}).get('_values', []),
+              xcresult, attachment_index)
+        for attachment in activity_summary.get('attachments',
+                                               {}).get('_values', []):
+          payload_ref = attachment['payloadRef']['id']['_value']
+          _, file_name_extension = os.path.splitext(
+              attachment['filename']['_value'])
+          if not include_jpg and file_name_extension in ['.jpg', '.jpeg']:
+            continue
+
+          attachment_index += 1
+          attachment_filename = (
+              '%s_%s_%d%s' %
+              (os.path.splitext(os.path.basename(xcresult))[0],
+               test.replace('/', '_'), attachment_index, file_name_extension))
+          # Extracts attachment to the same folder containing xcresult.
+          attachment_output_path = os.path.abspath(
+              os.path.join(xcresult, os.pardir, attachment_filename))
+          Xcode11LogParser._export_data(xcresult, payload_ref, 'file',
+                                        attachment_output_path)
+      return attachment_index
+
+    for test, summaryRef in test_summary_refs.iteritems():
+      # See SINGLE_TEST_SUMMARY_REF in xcode_log_parser_test.py for an example
+      # of |test_summary|.
+      test_summary = json.loads(
+          Xcode11LogParser._xcresulttool_get(xcresult, summaryRef))
+      # Extract all attachments except for screenshots from each step of the
+      # failed test.
+      index = extract_attachments(
+          test,
+          test_summary.get('activitySummaries', {}).get('_values', []),
+          xcresult,
+          include_jpg=False)
+      # Extract all attachments for at the failure step.
+      extract_attachments(
+          test,
+          test_summary.get('failureSummaries', {}).get('_values', []),
+          xcresult,
+          include_jpg=True,
+          attachment_index=index)
 
   @staticmethod
   def _export_diagnostic_data(xcresult):
-    """Exports diagnostic data from xcresult to xcresult_diagnostic folder.
+    """Exports diagnostic data from xcresult to xcresult_diagnostic.zip.
 
     Since Xcode 11 format of result bundles changed, to get diagnostic data
     need to run command below:
@@ -297,22 +389,53 @@
     Args:
       xcresult: (str) A path to xcresult directory.
     """
-    plist_path = os.path.join(xcresult, 'Info.plist')
-    if not (os.path.exists(xcresult) and os.path.exists(plist_path)):
+    if not os.path.exists(xcresult):
+      LOGGER.warn('%s does not exist.' % xcresult)
       return
     root = json.loads(Xcode11LogParser._xcresulttool_get(xcresult))
     try:
       diagnostics_ref = root['actions']['_values'][0]['actionResult'][
           'diagnosticsRef']['id']['_value']
-      export_command = ['xcresulttool', 'export',
-                        '--type', 'directory',
-                        '--id', diagnostics_ref,
-                        '--path', xcresult,
-                        '--output-path', '%s_diagnostic' % xcresult]
-      subprocess.check_output(export_command).strip()
+      diagnostic_folder = '%s_diagnostic' % xcresult
+      Xcode11LogParser._export_data(xcresult, diagnostics_ref, 'directory',
+                                    diagnostic_folder)
+      Xcode11LogParser._zip_and_remove_folder(diagnostic_folder)
     except KeyError:
       LOGGER.warn('Did not parse diagnosticsRef from %s!' % xcresult)
 
+  @staticmethod
+  def _export_data(xcresult, ref_id, output_type, output_path):
+    """Exports data from xcresult using xcresulttool.
+
+    Since Xcode 11 format of result bundles changed, to get diagnostic data
+    need to run command below:
+    xcresulttool export --type directory --id DIAGNOSTICS_REF --output-path
+    ./export_folder --path ./RB.xcresult
+
+    Args:
+      xcresult: (str) A path to xcresult directory.
+      ref_id: (str) A reference id of exporting entity.
+      output_type: (str) An export type (can be directory or file).
+      output_path: (str) An output location.
+    """
+    export_command = [
+        'xcresulttool', 'export', '--type', output_type, '--id', ref_id,
+        '--path', xcresult, '--output-path', output_path
+    ]
+    subprocess.check_output(export_command).strip()
+
+  @staticmethod
+  def _zip_and_remove_folder(dir_path):
+    """Zips folder to the parent folder and then removes original folder.
+
+    Args:
+      dir_path: (str) A path to directory.
+    """
+    shutil.make_archive(
+        os.path.join(os.path.dirname(dir_path), os.path.basename(dir_path)),
+        'zip', dir_path)
+    shutil.rmtree(dir_path)
+
 
 class XcodeLogParser(object):
   """Xcode log parser. Parses logs for Xcode until version 11."""
@@ -335,10 +458,7 @@
       }
     """
     root_summary = plistlib.readPlist(summary_plist)
-    status_summary = {
-        'passed': [],
-        'failed': {}
-    }
+    status_summary = {'passed': [], 'failed': {}}
     for summary in root_summary['TestableSummaries']:
       failed_egtests = {}  # Contains test identifier and message
       passed_egtests = []
@@ -366,7 +486,7 @@
 
   @staticmethod
   def collect_test_results(output_folder, output):
-    """Gets test result data from Info.plist.
+    """Gets test result data from Info.plist and copies artifacts.
 
     Args:
       output_folder: (str) A path to output folder.
@@ -380,14 +500,12 @@
           }
       }
     """
-    test_results = {
-        'passed': [],
-        'failed': {}
-    }
+    test_results = {'passed': [], 'failed': {}}
     plist_path = os.path.join(output_folder, 'Info.plist')
     if not os.path.exists(plist_path):
       test_results['failed']['BUILD_INTERRUPTED'] = [
-          '%s with test results does not exist.' % plist_path] + output
+          '%s with test results does not exist.' % plist_path
+      ] + output
       test_results['passed'] = parse_passed_tests_for_interrupted_run(output)
       return test_results
 
@@ -395,25 +513,26 @@
 
     for action in root['Actions']:
       action_result = action['ActionResult']
-      if ((root['TestsCount'] == 0 and
-           root['TestsFailedCount'] == 0)
-          or 'TestSummaryPath' not in action_result):
+      if ((root['TestsCount'] == 0 and root['TestsFailedCount'] == 0) or
+          'TestSummaryPath' not in action_result):
         test_results['failed']['TESTS_DID_NOT_START'] = []
-        if ('ErrorSummaries' in action_result
-            and action_result['ErrorSummaries']):
+        if ('ErrorSummaries' in action_result and
+            action_result['ErrorSummaries']):
           test_results['failed']['TESTS_DID_NOT_START'].append('\n'.join(
               error_summary['Message']
               for error_summary in action_result['ErrorSummaries']))
       else:
-        summary_plist = os.path.join(os.path.dirname(plist_path),
-                                     action_result['TestSummaryPath'])
+        summary_plist = os.path.join(
+            os.path.dirname(plist_path), action_result['TestSummaryPath'])
         summary = XcodeLogParser._test_status_summary(summary_plist)
         test_results['failed'] = summary['failed']
         test_results['passed'] = summary['passed']
+
+    XcodeLogParser._copy_screenshots(output_folder)
     return test_results
 
   @staticmethod
-  def copy_screenshots(output_folder):
+  def _copy_screenshots(output_folder):
     """Copy screenshots of failed tests to output folder.
 
     Args:
diff --git a/ios/build/bots/scripts/xcode_log_parser_test.py b/ios/build/bots/scripts/xcode_log_parser_test.py
index 0d24e897..81a4ec4 100644
--- a/ios/build/bots/scripts/xcode_log_parser_test.py
+++ b/ios/build/bots/scripts/xcode_log_parser_test.py
@@ -14,12 +14,75 @@
 import xcode_log_parser
 
 
-_XTEST_RESULT = '/tmp/temp_file.xcresult'
+OUTPUT_PATH = '/tmp/attempt_0'
+XCRESULT_PATH = '/tmp/attempt_0.xcresult'
 XCODE11_DICT = {
     'path': '/Users/user1/Xcode.app',
     'version': '11.0',
     'build': '11M336w',
 }
+# A sample of json result when executing xcresulttool on .xcresult dir without
+# --id. Some unused keys and values were removed.
+XCRESULT_ROOT = """
+{
+  "_type" : {
+    "_name" : "ActionsInvocationRecord"
+  },
+  "actions" : {
+    "_values" : [
+      {
+        "actionResult" : {
+          "_type" : {
+            "_name" : "ActionResult"
+          },
+          "diagnosticsRef" : {
+            "id" : {
+              "_value" : "DIAGNOSTICS_REF_ID"
+            }
+          },
+          "logRef" : {
+            "id" : {
+              "_value" : "0~6jr1GkZxoWVzWfcUNA5feff3l7g8fPHJ1rqKetCBa3QXhCGY74PnEuRwzktleMTFounMfCdDpSr1hRfhUGIUEQ=="
+            }
+          },
+          "testsRef" : {
+            "id" : {
+              "_value" : "0~iRbOkDnmtKVIvHSV2jkeuNcg4RDTUaCLZV7KijyxdCqvhqtp08MKxl0MwjBAPpjmruoI7qNHzBR1RJQAlANNHA=="
+            }
+          }
+        }
+      }
+    ]
+  },
+  "issues" : {
+    "testFailureSummaries" : {
+      "_values" : [
+        {
+          "documentLocationInCreatingWorkspace" : {
+            "url" : {
+              "_value" : "file:\/\/\/..\/..\/ios\/web\/shell\/test\/page_state_egtest.mm#CharacterRangeLen=0&EndingLineNumber=130&StartingLineNumber=130"
+            }
+          },
+          "message" : {
+            "_value": "Fail. Screenshots: {\\n\\"Failure\\": \\"path.png\\"\\n}"
+          },
+          "testCaseName" : {
+            "_value": "-[PageStateTestCase testZeroContentOffsetAfterLoad]"
+          }
+        }
+      ]
+    }
+  },
+  "metrics" : {
+    "testsCount" : {
+      "_value" : "2"
+    },
+    "testsFailedCount" : {
+      "_value" : "1"
+    }
+  }
+}"""
+
 REF_ID = """
   {
     "actions": {
@@ -35,28 +98,9 @@
     }
   }"""
 
-ACTIONS_RECORD_FAILED_TEST = """
-  {
-    "issues": {
-      "testFailureSummaries": {
-        "_values": [{
-          "documentLocationInCreatingWorkspace": {
-            "url": {
-              "_value": "file://<unknown>#CharacterRangeLen=0"
-            }
-          },
-          "message": {
-            "_value": "Fail. Screenshots: {\\n\\"Failure\\": \\"path.png\\"\\n}"
-          },
-          "testCaseName": {
-            "_value": "-[WebUITestCase testBackForwardFromWebURL]"
-          }
-        }]
-      }
-    }
-  }"""
-
-PASSED_TESTS = """
+# A sample of json result when executing xcresulttool on .xcresult dir with
+# "testsRef" as --id input. Some unused keys and values were removed.
+TESTS_REF = """
   {
     "summaries": {
       "_values": [{
@@ -70,31 +114,54 @@
                 "_name": "Array"
               },
               "_values": [{
+                "identifier" : {
+                  "_value" : "All tests"
+                },
+                "name" : {
+                  "_value" : "All tests"
+                },
                 "subtests": {
                   "_values": [{
+                    "identifier" : {
+                      "_value" : "ios_web_shell_eg2tests_module.xctest"
+                    },
+                    "name" : {
+                      "_value" : "ios_web_shell_eg2tests_module.xctest"
+                    },
                     "subtests": {
                       "_values": [{
+                        "identifier" : {
+                          "_value" : "PageStateTestCase"
+                        },
+                        "name" : {
+                          "_value" : "PageStateTestCase"
+                        },
                         "subtests": {
                           "_values": [{
                             "testStatus": {
                               "_value": "Success"
                             },
                             "identifier": {
-                              "_value": "TestCase1/testMethod1"
+                              "_value": "PageStateTestCase/testMethod1"
                             },
                             "name": {
                               "_value": "testMethod1"
                             }
                           },
                           {
+                            "summaryRef": {
+                              "id": {
+                                "_value": "0~7Q_uAuUSJtx9gtHM08psXFm3g_xiTTg5bpdoDO88nMXo_iMwQTXpqlrlMe5AtkYmnZ7Ux5uEgAe83kJBfoIckw=="
+                              }
+                            },
                             "testStatus": {
                               "_value": "Failure"
                             },
                             "identifier": {
-                              "_value": "TestCase1/testFailed1"
+                              "_value": "PageStateTestCase\/testZeroContentOffsetAfterLoad"
                             },
                             "name": {
-                              "_value": "testFailed1"
+                              "_value": "testZeroContentOffsetAfterLoad"
                             }
                           },
                           {
@@ -102,10 +169,10 @@
                               "_value": "Success"
                             },
                             "identifier": {
-                              "_value": "TestCase2/testMethod1"
+                              "_value": "PageStateTestCase/testMethod2"
                             },
                             "name": {
-                              "_value": "testMethod1"
+                              "_value": "testMethod2"
                             }
                           }]
                         }
@@ -122,6 +189,194 @@
   }
 """
 
+# A sample of json result when executing xcresulttool on .xcresult dir with
+# a single test summaryRef id value as --id input. Some unused keys and values
+# were removed.
+SINGLE_TEST_SUMMARY_REF = """
+{
+  "_type" : {
+    "_name" : "ActionTestSummary",
+    "_supertype" : {
+      "_name" : "ActionTestSummaryIdentifiableObject",
+      "_supertype" : {
+        "_name" : "ActionAbstractTestSummary"
+      }
+    }
+  },
+  "activitySummaries" : {
+    "_values" : [
+      {
+        "attachments" : {
+          "_values" : [
+            {
+              "filename" : {
+                "_value" : "Screenshot_25659115-F3E4-47AE-AA34-551C94333D7E.jpg"
+              },
+              "payloadRef" : {
+                "id" : {
+                  "_value" : "SCREENSHOT_REF_ID_1"
+                }
+              }
+            }
+          ]
+        },
+        "title" : {
+          "_value" : "Start Test at 2020-10-19 14:12:58.111"
+        }
+      },
+      {
+        "subactivities" : {
+          "_values" : [
+            {
+              "attachments" : {
+                "_values" : [
+                  {
+                    "filename" : {
+                      "_value" : "Screenshot_23D95D0E-8B97-4F99-BE3C-A46EDE5999D7.jpg"
+                    },
+                    "payloadRef" : {
+                      "id" : {
+                        "_value" : "SCREENSHOT_REF_ID_2"
+                      }
+                    }
+                  }
+                ]
+              },
+              "subactivities" : {
+                "_values" : [
+                  {
+                    "subactivities" : {
+                      "_values" : [
+                        {
+                          "attachments" : {
+                            "_values" : [
+                              {
+                                "filename" : {
+                                  "_value" : "Crash_3F0A2B1C-7ADA-436E-A54C-D4C39B8411F8.crash"
+                                },
+                                "payloadRef" : {
+                                  "id" : {
+                                    "_value" : "CRASH_REF_ID_IN_ACTIVITY_SUMMARIES"
+                                  }
+                                }
+                              }
+                            ]
+                          },
+                          "title" : {
+                            "_value" : "Wait for org.chromium.ios-web-shell-eg2tests to idle"
+                          }
+                        }
+                      ]
+                    },
+                    "title" : {
+                      "_value" : "Activate org.chromium.ios-web-shell-eg2tests"
+                    }
+                  }
+                ]
+              },
+              "title" : {
+                "_value" : "Open org.chromium.ios-web-shell-eg2tests"
+              }
+            }
+          ]
+        },
+        "title" : {
+          "_value" : "Set Up"
+        }
+      },
+      {
+        "title" : {
+          "_value" : "Find the Target Application 'org.chromium.ios-web-shell-eg2tests'"
+        }
+      },
+      {
+        "attachments" : {
+          "_values" : [
+            {
+              "filename" : {
+                "_value" : "Screenshot_278BA84B-2196-4CCD-9D31-2C07DDDC9DFC.jpg"
+              },
+              "payloadRef" : {
+                "id" : {
+                  "_value" : "SCREENSHOT_REF_ID_3"
+                }
+              }
+
+            }
+          ]
+        },
+        "title" : {
+          "_value" : "Uncaught Exception at page_state_egtest.mm:131: \\nCannot scroll, the..."
+        }
+      },
+      {
+        "title" : {
+          "_value" : "Uncaught Exception: Immediately halt execution of testcase (EarlGreyInternalTestInterruptException)"
+        }
+      },
+      {
+        "title" : {
+          "_value" : "Tear Down"
+        }
+      }
+    ]
+  },
+  "failureSummaries" : {
+    "_values" : [
+      {
+        "attachments" : {
+          "_values" : [
+            {
+              "filename" : {
+                "_value" : "kXCTAttachmentLegacyScreenImageData_1_6CED1FE5-96CA-47EA-9852-6FADED687262.jpeg"
+              },
+              "payloadRef" : {
+                "id" : {
+                  "_value" : "SCREENSHOT_REF_ID_IN_FAILURE_SUMMARIES"
+                }
+              }
+            }
+          ]
+        },
+        "fileName" : {
+          "_value" : "\/..\/..\/ios\/web\/shell\/test\/page_state_egtest.mm"
+        },
+        "lineNumber" : {
+          "_value" : "131"
+        },
+        "message" : {
+          "_value" : "Some logs."
+        }
+      },
+      {
+        "message" : {
+          "_value" : "Immediately halt execution of testcase (EarlGreyInternalTestInterruptException)"
+        }
+      }
+    ]
+  },
+  "identifier" : {
+    "_value" : "PageStateTestCase\/testZeroContentOffsetAfterLoad"
+  },
+  "name" : {
+    "_value" : "testZeroContentOffsetAfterLoad"
+  },
+  "testStatus" : {
+    "_value" : "Failure"
+  }
+}"""
+
+
+def _xcresulttool_get_side_effect(xcresult_path, ref_id=None):
+  """Side effect for _xcresulttool_get in Xcode11LogParser tested."""
+  if ref_id is None:
+    return XCRESULT_ROOT
+  if ref_id == 'testsRef':
+    return TESTS_REF
+  # Other situation in use cases of xcode_log_parser is asking for single test
+  # summary ref.
+  return SINGLE_TEST_SUMMARY_REF
+
 
 class XCode11LogParserTest(test_runner_test.TestCase):
   """Test case to test Xcode11LogParser."""
@@ -154,29 +409,35 @@
 
   def testXcresulttoolListFailedTests(self):
     failure_message = [
-        'file://<unknown>#CharacterRangeLen=0'
+        'file:///../../ios/web/shell/test/page_state_egtest.mm#'
+        'CharacterRangeLen=0&EndingLineNumber=130&StartingLineNumber=130'
     ] + 'Fail. Screenshots: {\n\"Failure\": \"path.png\"\n}'.splitlines()
     expected = {
-        'WebUITestCase/testBackForwardFromWebURL': failure_message
+        'PageStateTestCase/testZeroContentOffsetAfterLoad': failure_message
     }
-    self.assertEqual(expected,
-                     xcode_log_parser.Xcode11LogParser()._list_of_failed_tests(
-                         json.loads(ACTIONS_RECORD_FAILED_TEST)))
+    self.assertEqual(
+        expected,
+        xcode_log_parser.Xcode11LogParser()._list_of_failed_tests(
+            json.loads(XCRESULT_ROOT)))
 
   @mock.patch('xcode_log_parser.Xcode11LogParser._xcresulttool_get')
   def testXcresulttoolListPassedTests(self, mock_xcresult):
-    mock_xcresult.return_value = PASSED_TESTS
-    expected = ['TestCase1/testMethod1', 'TestCase2/testMethod1']
-    self.assertEqual(
-        expected,
-        xcode_log_parser.Xcode11LogParser()._get_test_statuses(_XTEST_RESULT))
+    mock_xcresult.side_effect = _xcresulttool_get_side_effect
+    expected = [
+        'PageStateTestCase/testMethod1', 'PageStateTestCase/testMethod2'
+    ]
+    results = {'passed': [], 'failed': {}}
+    xcode_log_parser.Xcode11LogParser()._get_test_statuses(OUTPUT_PATH, results)
+    self.assertEqual(expected, results['passed'])
 
+  @mock.patch('xcode_log_parser.Xcode11LogParser._zip_and_remove_folder')
+  @mock.patch('xcode_log_parser.Xcode11LogParser._copy_artifacts')
+  @mock.patch('xcode_log_parser.Xcode11LogParser._export_diagnostic_data')
   @mock.patch('os.path.exists', autospec=True)
   @mock.patch('xcode_log_parser.Xcode11LogParser._xcresulttool_get')
   @mock.patch('xcode_log_parser.Xcode11LogParser._list_of_failed_tests')
-  @mock.patch('xcode_log_parser.Xcode11LogParser._list_of_passed_tests')
-  def testCollectTestTesults(self, mock_get_passed_tests, mock_get_failed_tests,
-                             mock_root, mock_exist_file):
+  def testCollectTestTesults(self, mock_get_failed_tests, mock_root,
+                             mock_exist_file, *args):
     metrics_json = """
     {
       "metrics": {
@@ -190,7 +451,8 @@
     }"""
     expected_test_results = {
         'passed': [
-            'TestCase1/testMethod1', 'TestCase2/testMethod1'],
+            'PageStateTestCase/testMethod1', 'PageStateTestCase/testMethod2'
+        ],
         'failed': {
             'WebUITestCase/testBackForwardFromWebURL': [
                 'file://<unknown>#CharacterRangeLen=0',
@@ -198,59 +460,102 @@
             ]
         }
     }
-    mock_get_passed_tests.return_value = expected_test_results['passed']
     mock_get_failed_tests.return_value = expected_test_results['failed']
-    mock_root.return_value = metrics_json
+    mock_root.side_effect = _xcresulttool_get_side_effect
     mock_exist_file.return_value = True
-    self.assertEqual(expected_test_results,
-                     xcode_log_parser.Xcode11LogParser().collect_test_results(
-                         _XTEST_RESULT, []))
+    self.assertEqual(
+        expected_test_results,
+        xcode_log_parser.Xcode11LogParser().collect_test_results(
+            OUTPUT_PATH, []))
 
+  @mock.patch('xcode_log_parser.Xcode11LogParser._zip_and_remove_folder')
+  @mock.patch('xcode_log_parser.Xcode11LogParser._copy_artifacts')
+  @mock.patch('xcode_log_parser.Xcode11LogParser._export_diagnostic_data')
   @mock.patch('os.path.exists', autospec=True)
   @mock.patch('xcode_log_parser.Xcode11LogParser._xcresulttool_get')
-  def testCollectTestsRanZeroTests(self, mock_root, mock_exist_file):
+  def testCollectTestsRanZeroTests(self, mock_root, mock_exist_file, *args):
     metrics_json = '{"metrics": {}}'
     expected_test_results = {
         'passed': [],
         'failed': {'TESTS_DID_NOT_START': ['0 tests executed!']}}
     mock_root.return_value = metrics_json
     mock_exist_file.return_value = True
-    self.assertEqual(expected_test_results,
-                     xcode_log_parser.Xcode11LogParser().collect_test_results(
-                         _XTEST_RESULT, []))
+    self.assertEqual(
+        expected_test_results,
+        xcode_log_parser.Xcode11LogParser().collect_test_results(
+            OUTPUT_PATH, []))
 
   @mock.patch('os.path.exists', autospec=True)
   def testCollectTestsDidNotRun(self, mock_exist_file):
     mock_exist_file.return_value = False
     expected_test_results = {
         'passed': [],
-        'failed': {'TESTS_DID_NOT_START': [
-            '%s with test results does not exist.' % _XTEST_RESULT]}}
-    self.assertEqual(expected_test_results,
-                     xcode_log_parser.Xcode11LogParser().collect_test_results(
-                         _XTEST_RESULT, []))
+        'failed': {
+            'TESTS_DID_NOT_START': [
+                '%s.xcresult with test results does not exist.' % OUTPUT_PATH
+            ]
+        }
+    }
+    self.assertEqual(
+        expected_test_results,
+        xcode_log_parser.Xcode11LogParser().collect_test_results(
+            OUTPUT_PATH, []))
 
   @mock.patch('os.path.exists', autospec=True)
   def testCollectTestsInterruptedRun(self, mock_exist_file):
     mock_exist_file.side_effect = [True, False]
     expected_test_results = {
         'passed': [],
-        'failed': {'BUILD_INTERRUPTED': [
-            '%s with test results does not exist.' % os.path.join(
-                _XTEST_RESULT + '.xcresult', 'Info.plist')]}}
-    self.assertEqual(expected_test_results,
-                     xcode_log_parser.Xcode11LogParser().collect_test_results(
-                         _XTEST_RESULT, []))
+        'failed': {
+            'BUILD_INTERRUPTED': [
+                '%s with test results does not exist.' %
+                os.path.join(OUTPUT_PATH + '.xcresult', 'Info.plist')
+            ]
+        }
+    }
+    self.assertEqual(
+        expected_test_results,
+        xcode_log_parser.Xcode11LogParser().collect_test_results(
+            OUTPUT_PATH, []))
 
+  @mock.patch('subprocess.check_output', autospec=True)
   @mock.patch('os.path.exists', autospec=True)
   @mock.patch('xcode_log_parser.Xcode11LogParser._xcresulttool_get')
-  @mock.patch('shutil.copyfile', autospec=True)
-  def testCopyScreenshots(self, mock_copy, mock_xcresulttool_get,
-                          mock_exist_file):
-    mock_exist_file.return_value = True
-    mock_xcresulttool_get.return_value = ACTIONS_RECORD_FAILED_TEST
-    xcode_log_parser.Xcode11LogParser().copy_screenshots(_XTEST_RESULT)
-    self.assertEqual(1, mock_copy.call_count)
+  def testCopyScreenshots(self, mock_xcresulttool_get, mock_path_exists,
+                          mock_process):
+    mock_path_exists.return_value = True
+    mock_xcresulttool_get.side_effect = _xcresulttool_get_side_effect
+    xcode_log_parser.Xcode11LogParser()._copy_artifacts(XCRESULT_PATH)
+    mock_process.assert_any_call([
+        'xcresulttool', 'export', '--type', 'file', '--id',
+        'SCREENSHOT_REF_ID_IN_FAILURE_SUMMARIES', '--path', XCRESULT_PATH,
+        '--output-path',
+        '/tmp/attempt_0_PageStateTestCase_testZeroContentOffsetAfterLoad_2.jpeg'
+    ])
+    mock_process.assert_any_call([
+        'xcresulttool', 'export', '--type', 'file', '--id',
+        'CRASH_REF_ID_IN_ACTIVITY_SUMMARIES', '--path', XCRESULT_PATH,
+        '--output-path',
+        '/tmp/attempt_0_PageStateTestCase_testZeroContentOffsetAfterLoad_1'
+        '.crash'
+    ])
+    # Ensures screenshots in activitySummaries are not copied.
+    self.assertEqual(2, mock_process.call_count)
+
+  @mock.patch('xcode_log_parser.Xcode11LogParser._zip_and_remove_folder')
+  @mock.patch('subprocess.check_output', autospec=True)
+  @mock.patch('os.path.exists', autospec=True)
+  @mock.patch('xcode_log_parser.Xcode11LogParser._xcresulttool_get')
+  def testExportDiagnosticData(self, mock_xcresulttool_get, mock_path_exists,
+                               mock_process, _):
+    mock_path_exists.return_value = True
+    mock_xcresulttool_get.side_effect = _xcresulttool_get_side_effect
+    xcode_log_parser.Xcode11LogParser._export_diagnostic_data(XCRESULT_PATH)
+    mock_process.assert_called_with([
+        'xcresulttool', 'export', '--type', 'directory', '--id',
+        'DIAGNOSTICS_REF_ID', '--path', XCRESULT_PATH, '--output-path',
+        '/tmp/attempt_0.xcresult_diagnostic'
+    ])
 
   @mock.patch('os.path.exists', autospec=True)
   def testCollectTestResults_interruptedTests(self, mock_path_exists):
diff --git a/ios/build/bots/scripts/xcodebuild_runner.py b/ios/build/bots/scripts/xcodebuild_runner.py
index 2a64c0a4..e12d5cf 100644
--- a/ios/build/bots/scripts/xcodebuild_runner.py
+++ b/ios/build/bots/scripts/xcodebuild_runner.py
@@ -232,7 +232,6 @@
           if failure:
             LOGGER.info('Failure for passed tests %s: %s' % (status, failure))
         break
-      self._log_parser.copy_screenshots(outdir_attempt)
 
       # If tests are not completed(interrupted or did not start)
       # re-run them with the same number of shards,
diff --git a/ios/chrome/app/README.md b/ios/chrome/app/README.md
deleted file mode 100644
index f28e8c4..0000000
--- a/ios/chrome/app/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# App
-
------
-**Some of the files in this directory are only used in the new iOS Chrome
-architecture:**
-
-* `app_delegate.h` and `.mm`
-* `application_phase.h`
-* `application_state.h` and `.mm`
-* `application_step.h`
-* `main.mm`
-
------
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_iw.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_iw.xtb
index 81053fe2..d93453b 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_iw.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_iw.xtb
@@ -43,7 +43,7 @@
 <translation id="5030102366287574140">‏Chrome יכול להגן עליך מפני פרצות באבטחת מידע, אתרים לא בטוחים וסכנות נוספות.</translation>
 <translation id="5162467219239570114">‏Chrome אינו מעודכן. אם אין עדכון זמין ב-<ph name="BEGIN_LINK" />App Store<ph name="END_LINK" />, ייתכן שהמכשיר שלך אינו תומך עוד בגרסאות חדשות של Chrome.</translation>
 <translation id="5389212809648216794">‏Google Chrome לא יכול להשתמש במצלמה כי אפליקציה אחרת משתמשת בה</translation>
-<translation id="5639704535586432836">‏עבור אל 'הגדרות' &gt; 'פרטיות' &gt; 'מצלמה' &gt; Google Chrome והפעל את המצלמה.</translation>
+<translation id="5639704535586432836">‏יש לעבור אל 'הגדרות' &gt; 'פרטיות' &gt; 'מצלמה' &gt; Google Chrome ולהפעיל את המצלמה.</translation>
 <translation id="5642200033778930880">‏Google Chrome לא יכול להשתמש במצלמה במצב תצוגה מפוצלת</translation>
 <translation id="5690427481109656848">Google LLC</translation>
 <translation id="571296537125272375">‏Chrome לא יכול לחפש עדכונים</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_iw.xtb b/ios/chrome/app/strings/resources/ios_strings_iw.xtb
index 6cb7c0f..004597d8 100644
--- a/ios/chrome/app/strings/resources/ios_strings_iw.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_iw.xtb
@@ -76,7 +76,7 @@
 <translation id="165877110639533037">אין כרטיסיות פתוחות</translation>
 <translation id="1674504678466460478"><ph name="SOURCE_LANGUAGE" /> ל<ph name="TARGET_LANGUAGE" /></translation>
 <translation id="168715261339224929">כדי שהסימניות שלך יופיעו בכל המכשירים, יש להפעיל סנכרון.</translation>
-<translation id="1687475363370981210">סמן את הכול כ'נקרא'</translation>
+<translation id="1687475363370981210">סימון הכול כ'נקרא'</translation>
 <translation id="1689333818294560261">כינוי</translation>
 <translation id="1690731385917361335">אין פריטים</translation>
 <translation id="1692118695553449118">סנכרון מופעל</translation>
@@ -86,7 +86,7 @@
 <translation id="1752547299766512813">שמירת סיסמאות</translation>
 <translation id="1753905327828125965">עם המבקרים הרבים ביותר</translation>
 <translation id="1803264062614276815">שם בעל הכרטיס</translation>
-<translation id="1809939268435598390">מחק תיקיה</translation>
+<translation id="1809939268435598390">מחיקת תיקייה</translation>
 <translation id="1813414402673211292">ניקוי נתוני גלישה</translation>
 <translation id="1820259098641718022">נוסף לרשימת הקריאה</translation>
 <translation id="1870148520156231997">הצגת הסיסמה</translation>
@@ -114,7 +114,7 @@
 <translation id="2198757192731523470">‏Google תוכל להשתמש בהיסטוריית הגלישה שלך לצורך התאמה אישית של החיפוש, מודעות ושירותי Google אחרים.</translation>
 <translation id="2218443599109088993">התרחקות</translation>
 <translation id="2230173723195178503">דף האינטרנט נטען</translation>
-<translation id="2239626343334228536">מנקה נתוני גלישה…</translation>
+<translation id="2239626343334228536">ניקוי נתוני הגלישה מתבצע…</translation>
 <translation id="2257567812274161158">הסנכרון לא פועל.</translation>
 <translation id="225943865679747347">קוד שגיאה: <ph name="ERROR_CODE" /></translation>
 <translation id="2267753748892043616">חשבון חדש</translation>
@@ -139,7 +139,7 @@
 <translation id="2497852260688568942">מנהל המערכת שלך השבית את הסנכרון</translation>
 <translation id="2500374554657206846">אפשרויות לשמירת סיסמה</translation>
 <translation id="2523363575747517183">האתר הזה מנסה שוב ושוב לפתוח אפליקציה אחרת.</translation>
-<translation id="2529021024822217800">פתח הכול</translation>
+<translation id="2529021024822217800">פתיחת הכול</translation>
 <translation id="2562041823070056534">הכרטיסייה נשלחת אל <ph name="DEVICE_NAME" />...</translation>
 <translation id="2570206273416014374">‏חלק מקובצי ה-Cookie והחיפושים נשלחים מסרגל הכתובות ומתיבת החיפוש אל מנוע החיפוש שהוגדר כברירת מחדל.</translation>
 <translation id="2578571896248130439">שליחת דף האינטרנט</translation>
@@ -147,7 +147,7 @@
 <translation id="2600682495497606169">‏ניקוי קובצי ה-cookie של אתרים</translation>
 <translation id="2625189173221582860">הסיסמה הועתקה</translation>
 <translation id="2647269890314209800">‏קובצי Cookie בשימוש</translation>
-<translation id="2648803196158606475">מחק פריטים שנקראו</translation>
+<translation id="2648803196158606475">מחיקת פריטים שנקראו</translation>
 <translation id="2653659639078652383">שליחה</translation>
 <translation id="2690858294534178585">המצלמה נמצאת בשימוש</translation>
 <translation id="2691653761409724435">לא זמין במצב לא מקוון</translation>
@@ -165,21 +165,21 @@
 <translation id="2780046210906776326">אין חשבונות אימייל</translation>
 <translation id="2781331604911854368">מופעל</translation>
 <translation id="2781692009645368755">Google Pay</translation>
-<translation id="2800683595868705743">‏צא מ-Tab Switcher</translation>
+<translation id="2800683595868705743">‏יציאה מ-Tab Switcher</translation>
 <translation id="2815198996063984598">2. מקישים על אפליקציית הדפדפן שמוגדרת כברירת מחדל</translation>
 <translation id="2830972654601096923">ניהול כתובות...</translation>
 <translation id="2834956026595107950"><ph name="TITLE" />, <ph name="STATE" />, <ph name="URL" /></translation>
 <translation id="2840687315230832938">ההגדרה הראשונית של הסנכרון לא הושלמה</translation>
 <translation id="2843803966603263712">‏איפוס ההגדרות של Google Translate</translation>
 <translation id="2858204748079866344">‏כדי לשמור על הפרטיות שלך, מערכת Chrome לא ממלאת באופן אוטומטי את הסיסמה שלך בשדה הזה.</translation>
-<translation id="285960592395650245">נסה שוב להוריד</translation>
+<translation id="285960592395650245">יש לנסות להוריד שוב</translation>
 <translation id="2870560284913253234">אתר</translation>
 <translation id="2871695793448672541">נסתר, סיסמה</translation>
 <translation id="2876369937070532032">‏שולחת ל-Google כתובות URL של חלק מהדפים שאליהם נכנסת, אם מתגלה סיכון אבטחה</translation>
 <translation id="288655811176831528">סגירת הכרטיסייה</translation>
 <translation id="2898963176829412617">תיקייה חדשה…</translation>
 <translation id="2916171785467530738">השלמה אוטומטית של חיפושים וכתובות אתרים</translation>
-<translation id="291754862089661335">‏מקם את קוד ה-QR או הברקוד במסגרת זו</translation>
+<translation id="291754862089661335">‏יש למקם את קוד ה-QR או הברקוד במסגרת זו</translation>
 <translation id="2921219216347069551">לא ניתן לשתף את הדף</translation>
 <translation id="2923448633003185837">הדבקה וחיפוש</translation>
 <translation id="292639812446257861">סמן כ'לא נקרא'</translation>
@@ -195,7 +195,7 @@
 <translation id="3112556859945124369">סימון…</translation>
 <translation id="3131206671572504478">‏חסימת כל קובצי ה-cookie</translation>
 <translation id="3153862085237805241">שמור כרטיס</translation>
-<translation id="3157684681743766797">סמן הכול…</translation>
+<translation id="3157684681743766797">סימון הכול…</translation>
 <translation id="3161291298470460782">‏הפעולה הזו תוציא אותך מהחשבון, תשבית את הסנכרון ותנקה את כל נתוני Chrome מהמכשיר הזה. הנתונים המסונכרנים יישארו בחשבון Google שלך.</translation>
 <translation id="3169472444629675720">Discover</translation>
 <translation id="3175081911749765310">שירותי אינטרנט</translation>
@@ -204,7 +204,7 @@
 <translation id="3196681740617426482">‏אתרים יכולים להשתמש בקובצי cookie כדי לשפר את חוויית הגלישה – למשל כדי למנוע את ניתוקך מהחשבון או כדי לזכור את הפריטים שהוספת לעגלת הקניות.
 
 במצב אנונימי אתרים לא יכולים להשתמש בקובצי cookie כדי לקבל מידע על פעילות הגלישה שלך באתרים שונים – למשל כדי להציג מודעות מותאמות.</translation>
-<translation id="3207960819495026254">מסומן בסימניה</translation>
+<translation id="3207960819495026254">מסומן בסימנייה</translation>
 <translation id="3224641773458703735">כדי שניתן יהיה לייצא את הסיסמאות, יש להגדיר קוד גישה במכשיר.</translation>
 <translation id="3240426699337459095">הקישור הועתק</translation>
 <translation id="3244271242291266297">MM</translation>
@@ -318,7 +318,7 @@
 <translation id="4505980578794259603">בדיקה אחרונה: <ph name="TIME" />.</translation>
 <translation id="4508750114462689118">סגירת קידום הכניסה</translation>
 <translation id="4526249700380860531">‏הצגה וינוהל של סיסמאות שמורות ב-<ph name="BEGIN_LINK" />passwords.google.com<ph name="END_LINK" /></translation>
-<translation id="4536418791685807335">נסה להיכנס שוב.</translation>
+<translation id="4536418791685807335">יש לנסות להיכנס שוב.</translation>
 <translation id="457386861538956877">עוד...</translation>
 <translation id="4592368184551360546">מקלדת</translation>
 <translation id="461440297010471931">‏חיפוש באמצעות Google</translation>
@@ -391,7 +391,7 @@
 <translation id="5317780077021120954">שמור</translation>
 <translation id="5327248766486351172">שם</translation>
 <translation id="5339316356165661760">הפעלת הסנכרון</translation>
-<translation id="5388358297987318779">פתח תמונה</translation>
+<translation id="5388358297987318779">פתיחת תמונה</translation>
 <translation id="5407969256130905701">ביטול השינויים</translation>
 <translation id="5409365236829784218">אין יישומים מותקנים שיכולים לפתוח את הקובץ הזה.</translation>
 <translation id="5416022985862681400">7 הימים האחרונים</translation>
@@ -422,7 +422,7 @@
 <translation id="5711039611392265845">‏אפשר למצוא הגדרות נוספות בנושא פרטיות, אבטחה ואיסוף נתונים בדף <ph name="BEGIN_LINK" />סנכרון ושירותי Google<ph name="END_LINK" />.</translation>
 <translation id="5724941645893276623">כדי לגלוש באינטרנט בפרטיות צריך להוסיף כרטיסייה חדשה</translation>
 <translation id="5728700505257787410">מצטערים, אירעה בעיה בכניסה לחשבון שלך.</translation>
-<translation id="5737974891429562743">פרטי הכניסה לחשבון אינם עדכניים. עדכן כדי להפעיל את הסינכרון.</translation>
+<translation id="5737974891429562743">פרטי הכניסה לחשבון אינם עדכניים. יש לעדכן כדי להפעיל את הסנכרון.</translation>
 <translation id="5738887413654608789">‏תקשורת Bluetooth מאפשרת לך למצוא אתרי אינטרנט רלוונטיים לפי המיקום שלך.</translation>
 <translation id="5758631781033351321">רשימת הקריאה זמינה כאן</translation>
 <translation id="5782227691023083829">מתרגם...</translation>
@@ -449,7 +449,7 @@
 <translation id="5982717868370722439">הוספת נתונים קיימים אל <ph name="USER_EMAIL" />.</translation>
 <translation id="5984222099446776634">ביקרת לאחרונה</translation>
 <translation id="5988851877894965432">‏פתיחת כתובות URL ב-Chrome</translation>
-<translation id="6012140227487808125">מצפין…</translation>
+<translation id="6012140227487808125">ההצפנה מתבצעת…</translation>
 <translation id="6021332621416007159">פתח ב...</translation>
 <translation id="6039429417015973673"><ph name="TITLE" />, <ph name="PUBLISHER_INFORMATION" />, <ph name="PUBLICATION_DATE" /></translation>
 <translation id="6040143037577758943">סגור</translation>
@@ -459,7 +459,7 @@
 <translation id="6066301408025741299">יש להקיש כדי לבטל.</translation>
 <translation id="6108923351542677676">ההגדרה מתבצעת…</translation>
 <translation id="6119050551270742952">דף האינטרנט הנוכחי מוצג במצב אנונימי</translation>
-<translation id="6122191549521593678">מקוון</translation>
+<translation id="6122191549521593678">אונליין</translation>
 <translation id="6125339936101702016">מנוהל על ידי <ph name="COMPANY" />. <ph name="BEGIN_LINK" />מידע נוסף<ph name="END_LINK" /></translation>
 <translation id="6127379762771434464">הפריט הוסר</translation>
 <translation id="6136914049981179737">שניות</translation>
@@ -472,7 +472,7 @@
 <translation id="6196207969502475924">חיפוש קולי</translation>
 <translation id="6202364442240589072">{COUNT,plural, =1{סגירת כרטיסייה אחת ({COUNT})}two{סגירת {COUNT} כרטיסיות}many{סגירת {COUNT} כרטיסיות}other{סגירת {COUNT} כרטיסיות}}</translation>
 <translation id="6219688215832490856">לא לתרגם אף פעם</translation>
-<translation id="6254066287920239840">פתח קישורים באפליקציה ולא בדפדפן.</translation>
+<translation id="6254066287920239840">פתיחת קישורים באפליקציה ולא בדפדפן.</translation>
 <translation id="6255097610484507482">עריכת כרטיס אשראי</translation>
 <translation id="6284652193729350524">הצגת הצעה לתרגום <ph name="LANGUAGE" /></translation>
 <translation id="6303969859164067831">יציאה וכיבוי הסנכרון</translation>
@@ -577,7 +577,7 @@
 <translation id="721597782417389033">כינוי הכרטיס לא חוקי</translation>
 <translation id="7265758999917665941">אף פעם עבור אתר זה</translation>
 <translation id="7272437679830969316">לא ניתן לאמת את הזהות שלך. הסיסמה לא הועתקה.</translation>
-<translation id="7291368939935408496">מכין סיסמאות...</translation>
+<translation id="7291368939935408496">הכנת הסיסמאות מתבצעת...</translation>
 <translation id="7293171162284876153">‏כדי להתחיל לסנכרן צריך להפעיל את האפשרות "סנכרון הנתונים מ-Chrome".</translation>
 <translation id="7313347584264171202">הכרטיסיות במצב אנונימי זמינות כאן</translation>
 <translation id="7336264872878993241">הושלמה הורדה של <ph name="PERCENT" /> אחוז</translation>
@@ -692,7 +692,7 @@
 <translation id="8574235780160508979">‏התנאים וההגבלות של Chrome ישתנו ב-31 במרץ. <ph name="BEGIN_LINK" />יש לקרוא אותם<ph name="END_LINK" /></translation>
 <translation id="8588404856427128947">כבוי</translation>
 <translation id="8591976964826315682">‏חסימת קובצי cookie של צד שלישי במצב אנונימי</translation>
-<translation id="8605219856220328675">סגור כרטיסייה.</translation>
+<translation id="8605219856220328675">סגירת כרטיסייה.</translation>
 <translation id="8620640915598389714">עריכה</translation>
 <translation id="8636825310635137004">כדי לקבל את הכרטיסיות מהמכשירים האחרים שלך, הפעל את הסנכרון.</translation>
 <translation id="8654802032646794042">ביטול</translation>
diff --git a/ios/chrome/browser/README.md b/ios/chrome/browser/README.md
deleted file mode 100644
index ff049a4..0000000
--- a/ios/chrome/browser/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Browser
-
------
-**Some of the files in this directory are only used in the new iOS Chrome
-architecture:**
-
-* `browser_coordinator.h`, `.mm`, and `+internal.h`
-* `url_opening.h`
-
------
diff --git a/ios/chrome/browser/autofill/manual_fill/passwords_fetcher.h b/ios/chrome/browser/autofill/manual_fill/passwords_fetcher.h
index fe34a5f..1c7a7a8b 100644
--- a/ios/chrome/browser/autofill/manual_fill/passwords_fetcher.h
+++ b/ios/chrome/browser/autofill/manual_fill/passwords_fetcher.h
@@ -6,14 +6,12 @@
 #define IOS_CHROME_BROWSER_AUTOFILL_MANUAL_FILL_PASSWORDS_FETCHER_H_
 
 #import <Foundation/Foundation.h>
+
 #include <memory>
 #include <vector>
 
 #include "base/memory/ref_counted.h"
-
-namespace autofill {
-struct PasswordForm;
-}  // namespace autofill
+#include "components/password_manager/core/browser/password_form_forward.h"
 
 @class PasswordFetcher;
 
@@ -29,7 +27,8 @@
 // Saved passwords has been fetched or updated.
 - (void)passwordFetcher:(PasswordFetcher*)passwordFetcher
       didFetchPasswords:
-          (std::vector<std::unique_ptr<autofill::PasswordForm>>)passwords;
+          (std::vector<std::unique_ptr<password_manager::PasswordForm>>)
+              passwords;
 
 @end
 
diff --git a/ios/chrome/browser/autofill/manual_fill/passwords_fetcher.mm b/ios/chrome/browser/autofill/manual_fill/passwords_fetcher.mm
index 65df9d0c..64463ce 100644
--- a/ios/chrome/browser/autofill/manual_fill/passwords_fetcher.mm
+++ b/ios/chrome/browser/autofill/manual_fill/passwords_fetcher.mm
@@ -5,8 +5,8 @@
 #import "ios/chrome/browser/autofill/manual_fill/passwords_fetcher.h"
 
 #include "base/stl_util.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_list_sorter.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/password_manager/core/browser/password_store_consumer.h"
@@ -87,7 +87,7 @@
       _passwordStore->GetAutofillableLogins(_savedPasswordsConsumer.get());
     } else {
       password_manager::PasswordStore::FormDigest digest = {
-          autofill::PasswordForm::Scheme::kHtml, std::string(), URL};
+          password_manager::PasswordForm::Scheme::kHtml, std::string(), URL};
       digest.signon_realm = URL.spec();
       _passwordStore->GetLogins(digest, _savedPasswordsConsumer.get());
     }
@@ -102,7 +102,7 @@
 #pragma mark - SavePasswordsConsumerDelegate
 
 - (void)onGetPasswordStoreResults:
-    (std::vector<std::unique_ptr<autofill::PasswordForm>>)results {
+    (std::vector<std::unique_ptr<password_manager::PasswordForm>>)results {
   // Filter out Android facet IDs and any blocked passwords.
   base::EraseIf(results, [](const auto& form) {
     return form->blocked_by_user ||
diff --git a/ios/chrome/browser/autofill/manual_fill/passwords_fetcher_unittest.mm b/ios/chrome/browser/autofill/manual_fill/passwords_fetcher_unittest.mm
index a6bb15d..ddedd73 100644
--- a/ios/chrome/browser/autofill/manual_fill/passwords_fetcher_unittest.mm
+++ b/ios/chrome/browser/autofill/manual_fill/passwords_fetcher_unittest.mm
@@ -10,8 +10,8 @@
 #include "base/strings/utf_string_conversions.h"
 #import "base/test/ios/wait_util.h"
 #include "base/test/task_environment.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/keyed_service/core/service_access_type.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
 #include "components/password_manager/core/browser/test_password_store.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
@@ -30,7 +30,7 @@
 // from the password store.
 @interface TestPasswordFetcherDelegate : NSObject<PasswordFetcherDelegate> {
   // Ivar to store the results from the store.
-  std::vector<std::unique_ptr<autofill::PasswordForm>> _passwords;
+  std::vector<std::unique_ptr<password_manager::PasswordForm>> _passwords;
 }
 
 // Returns the count of recieved passwords.
@@ -42,7 +42,8 @@
 
 - (void)passwordFetcher:(PasswordFetcher*)passwordFetcher
       didFetchPasswords:
-          (std::vector<std::unique_ptr<autofill::PasswordForm>>)passwords {
+          (std::vector<std::unique_ptr<password_manager::PasswordForm>>)
+              passwords {
   _passwords = std::move(passwords);
 }
 
@@ -75,8 +76,8 @@
         .get();
   }
 
-  autofill::PasswordForm Form1() {
-    autofill::PasswordForm form;
+  password_manager::PasswordForm Form1() {
+    password_manager::PasswordForm form;
     form.url = GURL("http://www.example.com/accounts/LoginAuth");
     form.action = GURL("http://www.example.com/accounts/Login");
     form.username_element = base::ASCIIToUTF16("Email");
@@ -85,7 +86,7 @@
     form.password_value = base::ASCIIToUTF16("test");
     form.submit_element = base::ASCIIToUTF16("signIn");
     form.signon_realm = "http://www.example.com/";
-    form.scheme = autofill::PasswordForm::Scheme::kHtml;
+    form.scheme = password_manager::PasswordForm::Scheme::kHtml;
     form.blocked_by_user = false;
     return form;
   }
@@ -95,7 +96,7 @@
 
   // Creates and adds a saved password form.
   void AddSavedForm2() {
-    auto form = std::make_unique<autofill::PasswordForm>();
+    auto form = std::make_unique<password_manager::PasswordForm>();
     form->url = GURL("http://www.example2.com/accounts/LoginAuth");
     form->action = GURL("http://www.example2.com/accounts/Login");
     form->username_element = base::ASCIIToUTF16("Email");
@@ -104,7 +105,7 @@
     form->password_value = base::ASCIIToUTF16("test");
     form->submit_element = base::ASCIIToUTF16("signIn");
     form->signon_realm = "http://www.example2.com/";
-    form->scheme = autofill::PasswordForm::Scheme::kHtml;
+    form->scheme = password_manager::PasswordForm::Scheme::kHtml;
     form->blocked_by_user = false;
     GetPasswordStore()->AddLogin(*std::move(form));
   }
@@ -112,7 +113,7 @@
   // Creates and adds a blocked site form to never offer to save
   // user's password to those sites.
   void AddBlockedForm() {
-    auto form = std::make_unique<autofill::PasswordForm>();
+    auto form = std::make_unique<password_manager::PasswordForm>();
     form->url = GURL("http://www.secret.com/login");
     form->action = GURL("http://www.secret.com/action");
     form->username_element = base::ASCIIToUTF16("email");
@@ -121,7 +122,7 @@
     form->password_value = base::ASCIIToUTF16("cantsay");
     form->submit_element = base::ASCIIToUTF16("signIn");
     form->signon_realm = "http://www.secret.test/";
-    form->scheme = autofill::PasswordForm::Scheme::kHtml;
+    form->scheme = password_manager::PasswordForm::Scheme::kHtml;
     form->blocked_by_user = true;
     GetPasswordStore()->AddLogin(*std::move(form));
   }
diff --git a/ios/chrome/browser/credential_provider/archivable_credential+password_form.h b/ios/chrome/browser/credential_provider/archivable_credential+password_form.h
index 01c147a..47b1114 100644
--- a/ios/chrome/browser/credential_provider/archivable_credential+password_form.h
+++ b/ios/chrome/browser/credential_provider/archivable_credential+password_form.h
@@ -5,18 +5,16 @@
 #ifndef IOS_CHROME_BROWSER_CREDENTIAL_PROVIDER_ARCHIVABLE_CREDENTIAL_PASSWORD_FORM_H_
 #define IOS_CHROME_BROWSER_CREDENTIAL_PROVIDER_ARCHIVABLE_CREDENTIAL_PASSWORD_FORM_H_
 
+#include "components/password_manager/core/browser/password_form_forward.h"
 #import "ios/chrome/common/credential_provider/archivable_credential.h"
 
-namespace autofill {
-struct PasswordForm;
-}
-
 // Category for adding convenience logic related to PasswordForms.
 @interface ArchivableCredential (PasswordForm)
 
 // Convenience initializer from a PasswordForm. Will return nil for forms
 // blacklisted by the user, with an empty origin or Android forms.
-- (instancetype)initWithPasswordForm:(const autofill::PasswordForm&)passwordForm
+- (instancetype)initWithPasswordForm:
+                    (const password_manager::PasswordForm&)passwordForm
                              favicon:(NSString*)favicon
                 validationIdentifier:(NSString*)validationIdentifier;
 
diff --git a/ios/chrome/browser/credential_provider/archivable_credential+password_form.mm b/ios/chrome/browser/credential_provider/archivable_credential+password_form.mm
index 6112740..1fd2a49 100644
--- a/ios/chrome/browser/credential_provider/archivable_credential+password_form.mm
+++ b/ios/chrome/browser/credential_provider/archivable_credential+password_form.mm
@@ -6,8 +6,8 @@
 
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_ui_utils.h"
 #import "ios/chrome/browser/credential_provider/credential_provider_util.h"
 #include "url/gurl.h"
@@ -25,7 +25,8 @@
 
 @implementation ArchivableCredential (PasswordForm)
 
-- (instancetype)initWithPasswordForm:(const autofill::PasswordForm&)passwordForm
+- (instancetype)initWithPasswordForm:
+                    (const password_manager::PasswordForm&)passwordForm
                              favicon:(NSString*)favicon
                 validationIdentifier:(NSString*)validationIdentifier {
   if (passwordForm.blocked_by_user) {
diff --git a/ios/chrome/browser/credential_provider/archivable_credential+password_form_unittest.mm b/ios/chrome/browser/credential_provider/archivable_credential+password_form_unittest.mm
index 1f5b8f33..eb4281247 100644
--- a/ios/chrome/browser/credential_provider/archivable_credential+password_form_unittest.mm
+++ b/ios/chrome/browser/credential_provider/archivable_credential+password_form_unittest.mm
@@ -6,7 +6,7 @@
 
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "testing/gtest_mac.h"
 #include "testing/platform_test.h"
 #include "url/gurl.h"
@@ -17,7 +17,7 @@
 
 namespace {
 
-using autofill::PasswordForm;
+using password_manager::PasswordForm;
 using ArchivableCredentialPasswordFormTest = PlatformTest;
 
 // Tests the creation of a credential from a password form.
diff --git a/ios/chrome/browser/credential_provider/credential_provider_service.h b/ios/chrome/browser/credential_provider/credential_provider_service.h
index 3b104d4..791d0ab 100644
--- a/ios/chrome/browser/credential_provider/credential_provider_service.h
+++ b/ios/chrome/browser/credential_provider/credential_provider_service.h
@@ -59,25 +59,26 @@
   // Replaces all data with credentials created from the passed forms and then
   // syncs to disk.
   void SyncAllCredentials(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> forms);
+      std::vector<std::unique_ptr<password_manager::PasswordForm>> forms);
 
   // Syncs the credential store to disk.
   void SyncStore(bool set_first_time_sync_flag);
 
   // Add credentials from |forms|.
   void AddCredentials(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> forms);
+      std::vector<std::unique_ptr<password_manager::PasswordForm>> forms);
 
   // Removes credentials from |forms|.
   void RemoveCredentials(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> forms);
+      std::vector<std::unique_ptr<password_manager::PasswordForm>> forms);
 
   // Syncs account_validation_id_.
   void UpdateAccountValidationId();
 
   // PasswordStoreConsumer:
   void OnGetPasswordStoreResults(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> results) override;
+      std::vector<std::unique_ptr<password_manager::PasswordForm>> results)
+      override;
 
   // PasswordStore::Observer:
   void OnLoginsChanged(
@@ -86,7 +87,7 @@
   // Completion called after the affiliations are injected in the added forms.
   // If no affiliation matcher is available, it is called right away.
   void OnInjectedAffiliationAfterLoginsChanged(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> forms);
+      std::vector<std::unique_ptr<password_manager::PasswordForm>> forms);
 
   // syncer::SyncServiceObserver:
   void OnSyncConfigurationCompleted(syncer::SyncService* sync) override;
diff --git a/ios/chrome/browser/credential_provider/credential_provider_service.mm b/ios/chrome/browser/credential_provider/credential_provider_service.mm
index db791ed..3c96320e 100644
--- a/ios/chrome/browser/credential_provider/credential_provider_service.mm
+++ b/ios/chrome/browser/credential_provider/credential_provider_service.mm
@@ -36,7 +36,7 @@
 
 namespace {
 
-using autofill::PasswordForm;
+using password_manager::PasswordForm;
 using password_manager::AffiliatedMatchHelper;
 using password_manager::PasswordStore;
 using password_manager::PasswordStoreChange;
diff --git a/ios/chrome/browser/credential_provider/credential_provider_service_unittest.mm b/ios/chrome/browser/credential_provider/credential_provider_service_unittest.mm
index aba3dfc..ebc08a52 100644
--- a/ios/chrome/browser/credential_provider/credential_provider_service_unittest.mm
+++ b/ios/chrome/browser/credential_provider/credential_provider_service_unittest.mm
@@ -7,7 +7,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/strings/utf_string_conversions.h"
 #import "base/test/ios/wait_util.h"
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_store_default.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #include "ios/chrome/browser/signin/authentication_service_factory.h"
@@ -28,7 +28,7 @@
 
 namespace {
 
-using autofill::PasswordForm;
+using password_manager::PasswordForm;
 using base::test::ios::WaitUntilConditionOrTimeout;
 using base::test::ios::kWaitForFileOperationTimeout;
 using password_manager::PasswordStoreDefault;
diff --git a/ios/chrome/browser/credential_provider/credential_provider_util.h b/ios/chrome/browser/credential_provider/credential_provider_util.h
index 32fe1e98..56a91baa 100644
--- a/ios/chrome/browser/credential_provider/credential_provider_util.h
+++ b/ios/chrome/browser/credential_provider/credential_provider_util.h
@@ -7,10 +7,11 @@
 
 #import <Foundation/Foundation.h>
 
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 
 // Returns the equivalent of a unique record identifier. Built from the unique
 // columns in the logins database.
-NSString* RecordIdentifierForPasswordForm(const autofill::PasswordForm& form);
+NSString* RecordIdentifierForPasswordForm(
+    const password_manager::PasswordForm& form);
 
 #endif  // IOS_CHROME_BROWSER_CREDENTIAL_PROVIDER_CREDENTIAL_PROVIDER_UTIL_H_
diff --git a/ios/chrome/browser/credential_provider/credential_provider_util.mm b/ios/chrome/browser/credential_provider/credential_provider_util.mm
index b365e80f..69c0f52 100644
--- a/ios/chrome/browser/credential_provider/credential_provider_util.mm
+++ b/ios/chrome/browser/credential_provider/credential_provider_util.mm
@@ -14,7 +14,8 @@
 using base::SysUTF16ToNSString;
 using base::UTF8ToUTF16;
 
-NSString* RecordIdentifierForPasswordForm(const autofill::PasswordForm& form) {
+NSString* RecordIdentifierForPasswordForm(
+    const password_manager::PasswordForm& form) {
   // These are the UNIQUE keys in the login database.
   return SysUTF16ToNSString(
       UTF8ToUTF16(form.url.spec() + "|") + form.username_element +
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index ca51f57..b9aaf50 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -655,6 +655,16 @@
      flag_descriptions::kIncognitoAuthenticationName,
      flag_descriptions::kIncognitoAuthenticationDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(kIncognitoAuthentication)},
+    {"location-first-run-modal", flag_descriptions::kLocationFirstRunModalName,
+     flag_descriptions::kLocationFirstRunModalDescription, flags_ui::kOsIos,
+     FEATURE_VALUE_TYPE(kLocationFirstRunModal)},
+    {"location-remove-first-run",
+     flag_descriptions::kLocationRemoveFirstRunPromptName,
+     flag_descriptions::kLocationRemoveFirstRunPromptDescription,
+     flags_ui::kOsIos, FEATURE_VALUE_TYPE(kLocationRemoveFirstRunPrompt)},
+    {"location-change-string", flag_descriptions::kLocationStringChangeName,
+     flag_descriptions::kLocationStringChangeDescription, flags_ui::kOsIos,
+     FEATURE_VALUE_TYPE(kLocationStringChange)},
 };
 
 bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index a27c1e5..93e596d 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -323,6 +323,24 @@
     "When enabled, an interstitial will be shown on navigations to lookalike "
     "URLs.";
 
+const char kLocationFirstRunModalName[] =
+    "Location Permisssions First Run Modal";
+const char kLocationFirstRunModalDescription[] =
+    "When enabled, a modal detailing location data usage in Chrome will be "
+    "presented just before triggering the native location permissions prompt.";
+
+const char kLocationRemoveFirstRunPromptName[] =
+    "Remove Location Permissions Prompt in First Run";
+const char kLocationRemoveFirstRunPromptDescription[] =
+    "When enabled, a location permissions prompt will not be triggered right "
+    "after First Run anymore.";
+
+const char kLocationStringChangeName[] =
+    "Use New Location Permissions Prompt String";
+const char kLocationStringChangeDescription[] =
+    "When enabled, a better string will used in the location permissions "
+    "prompt.";
+
 const char kLockBottomToolbarName[] = "Lock bottom toolbar";
 const char kLockBottomToolbarDescription[] =
     "When enabled, the bottom toolbar will not get collapsed when scrolling "
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index 4bcea15..f90c252 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -279,6 +279,21 @@
 extern const char kIOSLookalikeUrlNavigationSuggestionsUIName[];
 extern const char kIOSLookalikeUrlNavigationSuggestionsUIDescription[];
 
+// Title and description for the flag to add a First Run modal for location
+// permissions.
+extern const char kLocationFirstRunModalName[];
+extern const char kLocationFirstRunModalDescription[];
+
+// Title and description for the flag to remove the First Run location
+// permissions prompt.
+extern const char kLocationRemoveFirstRunPromptName[];
+extern const char kLocationRemoveFirstRunPromptDescription[];
+
+// Title and description for the flag to change the string in the location
+// permissions prompt.
+extern const char kLocationStringChangeName[];
+extern const char kLocationStringChangeDescription[];
+
 // Title and description for the flag to lock the bottom toolbar into place.
 extern const char kLockBottomToolbarName[];
 extern const char kLockBottomToolbarDescription[];
diff --git a/ios/chrome/browser/infobars/overlays/infobar_overlay_request_factory_impl_unittest.mm b/ios/chrome/browser/infobars/overlays/infobar_overlay_request_factory_impl_unittest.mm
index 73d6460..2766404 100644
--- a/ios/chrome/browser/infobars/overlays/infobar_overlay_request_factory_impl_unittest.mm
+++ b/ios/chrome/browser/infobars/overlays/infobar_overlay_request_factory_impl_unittest.mm
@@ -9,10 +9,10 @@
 #include "base/test/scoped_feature_list.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/infobars/core/infobar.h"
 #include "components/infobars/core/infobar_feature.h"
 #include "components/password_manager/core/browser/mock_password_form_manager_for_ui.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/translate/core/browser/mock_translate_infobar_delegate.h"
 #include "ios/chrome/browser/infobars/infobar_ios.h"
 #include "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_autofill_save_card_infobar_delegate_mobile.h"
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_check_manager.h b/ios/chrome/browser/passwords/ios_chrome_password_check_manager.h
index 92a34d2..976d5eeb 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_check_manager.h
+++ b/ios/chrome/browser/passwords/ios_chrome_password_check_manager.h
@@ -73,19 +73,20 @@
       const password_manager::CredentialWithPassword& credential) const;
 
   // Edits |username| and |password| for |form| and its duplicates.
-  bool EditPasswordForm(const autofill::PasswordForm& form,
+  bool EditPasswordForm(const password_manager::PasswordForm& form,
                         base::StringPiece new_username,
                         base::StringPiece new_password);
 
   // Edits password form using |insecure_credentials_manager_|.
-  void EditCompromisedPasswordForm(const autofill::PasswordForm& form,
+  void EditCompromisedPasswordForm(const password_manager::PasswordForm& form,
                                    base::StringPiece password);
 
   // Deletes |form| and its duplicates.
-  void DeletePasswordForm(const autofill::PasswordForm& form);
+  void DeletePasswordForm(const password_manager::PasswordForm& form);
 
   // Deletes compromised credentials which are related to |form|.
-  void DeleteCompromisedPasswordForm(const autofill::PasswordForm& form);
+  void DeleteCompromisedPasswordForm(
+      const password_manager::PasswordForm& form);
 
   void AddObserver(Observer* observer) { observers_.AddObserver(observer); }
   void RemoveObserver(Observer* observer) {
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_check_manager.mm b/ios/chrome/browser/passwords/ios_chrome_password_check_manager.mm
index 175fe722..120b975f 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_check_manager.mm
+++ b/ios/chrome/browser/passwords/ios_chrome_password_check_manager.mm
@@ -71,10 +71,10 @@
 }
 
 // Function which returns duplicates of passed form.
-std::vector<autofill::PasswordForm> GetDuplicatesOfForm(
-    const autofill::PasswordForm& form,
+std::vector<password_manager::PasswordForm> GetDuplicatesOfForm(
+    const password_manager::PasswordForm& form,
     SavedPasswordsView passwords) {
-  std::vector<autofill::PasswordForm> duplicates;
+  std::vector<password_manager::PasswordForm> duplicates;
   auto tie = [](const auto& form) {
     return std::tie(form.signon_realm, form.username_value,
                     form.password_value);
@@ -163,7 +163,7 @@
 }
 
 bool IOSChromePasswordCheckManager::EditPasswordForm(
-    const autofill::PasswordForm& form,
+    const password_manager::PasswordForm& form,
     base::StringPiece new_username,
     base::StringPiece new_password) {
   auto duplicates =
@@ -174,14 +174,14 @@
 }
 
 void IOSChromePasswordCheckManager::EditCompromisedPasswordForm(
-    const autofill::PasswordForm& form,
+    const password_manager::PasswordForm& form,
     base::StringPiece password) {
   insecure_credentials_manager_.UpdateCredential(
       password_manager::CredentialView(form), password);
 }
 
 void IOSChromePasswordCheckManager::DeletePasswordForm(
-    const autofill::PasswordForm& form) {
+    const password_manager::PasswordForm& form) {
   auto duplicates =
       GetDuplicatesOfForm(form, saved_passwords_presenter_.GetSavedPasswords());
   for (auto& duplicate : duplicates) {
@@ -190,7 +190,7 @@
 }
 
 void IOSChromePasswordCheckManager::DeleteCompromisedPasswordForm(
-    const autofill::PasswordForm& form) {
+    const password_manager::PasswordForm& form) {
   insecure_credentials_manager_.RemoveCredential(
       password_manager::CredentialView(form));
 }
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_check_manager_unittest.mm b/ios/chrome/browser/passwords/ios_chrome_password_check_manager_unittest.mm
index 309de1e11..cbfc25d 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_check_manager_unittest.mm
+++ b/ios/chrome/browser/passwords/ios_chrome_password_check_manager_unittest.mm
@@ -49,7 +49,7 @@
 constexpr char kPassword1[] = "s3cre3t";
 constexpr char kPassword2[] = "bett3r_S3cre3t";
 
-using autofill::PasswordForm;
+using password_manager::PasswordForm;
 using password_manager::BulkLeakCheckServiceInterface;
 using password_manager::CredentialWithPassword;
 using password_manager::MockBulkLeakCheckService;
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h
index 83d5a72..3d0644b 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h
+++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h
@@ -36,7 +36,7 @@
 
 // Shows UI to notify the user about auto sign in.
 - (void)showAutosigninNotification:
-    (std::unique_ptr<autofill::PasswordForm>)formSignedIn;
+    (std::unique_ptr<password_manager::PasswordForm>)formSignedIn;
 
 @end
 
@@ -68,7 +68,7 @@
       password_manager::PasswordManagerDriver* driver,
       autofill::mojom::FocusedFieldType focused_field_type) override;
   bool PromptUserToChooseCredentials(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms,
+      std::vector<std::unique_ptr<password_manager::PasswordForm>> local_forms,
       const url::Origin& origin,
       CredentialsCallback callback) override;
   void AutomaticPasswordSave(
@@ -83,10 +83,10 @@
   password_manager::PasswordStore* GetProfilePasswordStore() const override;
   password_manager::PasswordStore* GetAccountPasswordStore() const override;
   void NotifyUserAutoSignin(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms,
+      std::vector<std::unique_ptr<password_manager::PasswordForm>> local_forms,
       const url::Origin& origin) override;
   void NotifyUserCouldBeAutoSignedIn(
-      std::unique_ptr<autofill::PasswordForm> form) override;
+      std::unique_ptr<password_manager::PasswordForm> form) override;
   void NotifySuccessfulLoginWithExistingPassword(
       std::unique_ptr<password_manager::PasswordFormManagerForUI>
           submitted_manager) override;
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm
index 41b9d68..b1fd3f9 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm
+++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm
@@ -11,8 +11,8 @@
 #include "base/no_destructor.h"
 #include "components/autofill/core/browser/logging/log_manager.h"
 #include "components/autofill/core/browser/logging/log_router.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/keyed_service/core/service_access_type.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_form_manager_for_ui.h"
 #include "components/password_manager/core/browser/password_manager.h"
 #include "components/password_manager/core/browser/password_manager_constants.h"
@@ -86,7 +86,7 @@
 }
 
 bool IOSChromePasswordManagerClient::PromptUserToChooseCredentials(
-    std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms,
+    std::vector<std::unique_ptr<password_manager::PasswordForm>> local_forms,
     const url::Origin& origin,
     CredentialsCallback callback) {
   NOTIMPLEMENTED();
@@ -180,7 +180,7 @@
 }
 
 void IOSChromePasswordManagerClient::NotifyUserAutoSignin(
-    std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms,
+    std::vector<std::unique_ptr<password_manager::PasswordForm>> local_forms,
     const url::Origin& origin) {
   DCHECK(!local_forms.empty());
   helper_.NotifyUserAutoSignin();
@@ -188,7 +188,7 @@
 }
 
 void IOSChromePasswordManagerClient::NotifyUserCouldBeAutoSignedIn(
-    std::unique_ptr<autofill::PasswordForm> form) {
+    std::unique_ptr<password_manager::PasswordForm> form) {
   helper_.NotifyUserCouldBeAutoSignedIn(std::move(form));
 }
 
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.mm b/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.mm
index d1d8f58..575b42e 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.mm
+++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.mm
@@ -5,7 +5,6 @@
 #import "ios/chrome/browser/passwords/ios_chrome_password_manager_driver.h"
 
 #include "base/strings/string16.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/autofill/core/common/password_form_fill_data.h"
 #include "components/password_manager/core/browser/password_generation_frame_helper.h"
 #include "components/password_manager/core/browser/password_manager.h"
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.mm b/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.mm
index c840124..d6c3382 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.mm
+++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.mm
@@ -8,6 +8,7 @@
 
 #include "base/strings/string16.h"
 #include "base/strings/sys_string_conversions.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_form_manager_for_ui.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ios/chrome/grit/ios_theme_resources.h"
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm
index 88be70b..9f8cbbe7 100644
--- a/ios/chrome/browser/passwords/password_controller.mm
+++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -24,7 +24,6 @@
 #include "components/autofill/core/browser/ui/popup_item_ids.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/autofill/core/common/password_form_fill_data.h"
 #include "components/autofill/core/common/password_form_generation_data.h"
 #include "components/autofill/core/common/renderer_id.h"
@@ -35,6 +34,7 @@
 #include "components/autofill/ios/form_util/unique_id_data_tab_helper.h"
 #include "components/infobars/core/infobar_manager.h"
 #include "components/password_manager/core/browser/password_bubble_experiment.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_form_manager_for_ui.h"
 #include "components/password_manager/core/browser/password_generation_frame_helper.h"
 #include "components/password_manager/core/browser/password_manager.h"
@@ -82,7 +82,7 @@
 using autofill::FormActivityObserverBridge;
 using autofill::FormData;
 using autofill::PasswordFormGenerationData;
-using autofill::PasswordForm;
+using password_manager::PasswordForm;
 using autofill::FormRendererId;
 using autofill::FieldRendererId;
 using base::SysNSStringToUTF16;
@@ -159,7 +159,7 @@
 
   // User credential waiting to be displayed in autosign-in snackbar, once tab
   // becomes active.
-  std::unique_ptr<autofill::PasswordForm> _pendingAutoSigninPasswordForm;
+  std::unique_ptr<PasswordForm> _pendingAutoSigninPasswordForm;
 }
 
 - (instancetype)initWithWebState:(WebState*)webState {
@@ -299,8 +299,7 @@
 
 // Shows auto sign-in notification and schedules hiding it after 3 seconds.
 // TODO(crbug.com/435048): Animate appearance.
-- (void)showAutosigninNotification:
-    (std::unique_ptr<autofill::PasswordForm>)formSignedIn {
+- (void)showAutosigninNotification:(std::unique_ptr<PasswordForm>)formSignedIn {
   if (!_webState)
     return;
 
diff --git a/ios/chrome/browser/passwords/password_controller_unittest.mm b/ios/chrome/browser/passwords/password_controller_unittest.mm
index 9fd956280..7b714d7 100644
--- a/ios/chrome/browser/passwords/password_controller_unittest.mm
+++ b/ios/chrome/browser/passwords/password_controller_unittest.mm
@@ -67,7 +67,7 @@
 using autofill::FormFieldData;
 using autofill::FormRendererId;
 using autofill::FieldRendererId;
-using autofill::PasswordForm;
+using password_manager::PasswordForm;
 using autofill::PasswordFormFillData;
 using base::SysUTF8ToNSString;
 using FillingAssistance =
@@ -175,7 +175,7 @@
   form.signon_realm = origin_url;
   form.username_value = ASCIIToUTF16(username_value);
   form.password_value = ASCIIToUTF16(password_value);
-  form.in_store = autofill::PasswordForm::Store::kProfileStore;
+  form.in_store = password_manager::PasswordForm::Store::kProfileStore;
   return form;
 }
 
@@ -1305,7 +1305,7 @@
   bool* p_get_logins_called = &get_logins_called;
 
   password_manager::PasswordStore::FormDigest expected_form_digest(
-      autofill::PasswordForm::Scheme::kHtml, "https://chromium.test/",
+      password_manager::PasswordForm::Scheme::kHtml, "https://chromium.test/",
       GURL("https://chromium.test/"));
   // TODO(crbug.com/949519): replace WillRepeatedly with WillOnce when the old
   // parser is gone.
diff --git a/ios/chrome/browser/passwords/password_manager_app_interface.mm b/ios/chrome/browser/passwords/password_manager_app_interface.mm
index c016d9b..5d81cbe3 100644
--- a/ios/chrome/browser/passwords/password_manager_app_interface.mm
+++ b/ios/chrome/browser/passwords/password_manager_app_interface.mm
@@ -6,8 +6,8 @@
 
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/keyed_service/core/service_access_type.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
@@ -35,13 +35,13 @@
   }
 
   // Store a PasswordForm representing a PasswordCredential.
-  autofill::PasswordForm passwordCredentialForm;
+  password_manager::PasswordForm passwordCredentialForm;
   passwordCredentialForm.username_value = base::SysNSStringToUTF16(username);
   passwordCredentialForm.password_value = base::SysNSStringToUTF16(password);
   passwordCredentialForm.url =
       chrome_test_util::GetCurrentWebState()->GetLastCommittedURL().GetOrigin();
   passwordCredentialForm.signon_realm = passwordCredentialForm.url.spec();
-  passwordCredentialForm.scheme = autofill::PasswordForm::Scheme::kHtml;
+  passwordCredentialForm.scheme = password_manager::PasswordForm::Scheme::kHtml;
   passwordStore->AddLogin(passwordCredentialForm);
 
   return nil;
diff --git a/ios/chrome/browser/passwords/save_passwords_consumer.h b/ios/chrome/browser/passwords/save_passwords_consumer.h
index 0bb3ab5f..b40827e 100644
--- a/ios/chrome/browser/passwords/save_passwords_consumer.h
+++ b/ios/chrome/browser/passwords/save_passwords_consumer.h
@@ -15,7 +15,7 @@
 // Callback called when the async request launched from
 // |getLoginsFromPasswordStore| finishes.
 - (void)onGetPasswordStoreResults:
-    (std::vector<std::unique_ptr<autofill::PasswordForm>>)results;
+    (std::vector<std::unique_ptr<password_manager::PasswordForm>>)results;
 
 @end
 
@@ -27,7 +27,8 @@
   explicit SavePasswordsConsumer(id<SavePasswordsConsumerDelegate> delegate);
   ~SavePasswordsConsumer() override;
   void OnGetPasswordStoreResults(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> results) override;
+      std::vector<std::unique_ptr<password_manager::PasswordForm>> results)
+      override;
 
  private:
   __weak id<SavePasswordsConsumerDelegate> delegate_ = nil;
diff --git a/ios/chrome/browser/passwords/save_passwords_consumer.mm b/ios/chrome/browser/passwords/save_passwords_consumer.mm
index 082e07b..776f6c6 100644
--- a/ios/chrome/browser/passwords/save_passwords_consumer.mm
+++ b/ios/chrome/browser/passwords/save_passwords_consumer.mm
@@ -6,7 +6,7 @@
 
 #include <utility>
 
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -21,7 +21,7 @@
 SavePasswordsConsumer::~SavePasswordsConsumer() = default;
 
 void SavePasswordsConsumer::OnGetPasswordStoreResults(
-    std::vector<std::unique_ptr<autofill::PasswordForm>> results) {
+    std::vector<std::unique_ptr<password_manager::PasswordForm>> results) {
   [delegate_ onGetPasswordStoreResults:std::move(results)];
 }
 
diff --git a/ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.h b/ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.h
index 9d995971..dcf2f40 100644
--- a/ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.h
+++ b/ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.h
@@ -8,7 +8,7 @@
 #import <Foundation/Foundation.h>
 #include <memory>
 
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 #import "ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "url/gurl.h"
@@ -39,10 +39,10 @@
 
  private:
   MockIOSChromeSavePasswordInfoBarDelegate(
-      std::unique_ptr<autofill::PasswordForm> form,
+      std::unique_ptr<password_manager::PasswordForm> form,
       std::unique_ptr<GURL> url);
 
-  std::unique_ptr<autofill::PasswordForm> form_;
+  std::unique_ptr<password_manager::PasswordForm> form_;
   std::unique_ptr<GURL> url_;
 };
 
diff --git a/ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.mm b/ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.mm
index 9ecb393..ea86e35 100644
--- a/ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.mm
+++ b/ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.mm
@@ -15,7 +15,7 @@
 
 namespace {
 std::unique_ptr<password_manager::PasswordFormManagerForUI> CreateFormManager(
-    autofill::PasswordForm* form,
+    password_manager::PasswordForm* form,
     GURL* url) {
   std::unique_ptr<password_manager::MockPasswordFormManagerForUI> form_manager =
       std::make_unique<password_manager::MockPasswordFormManagerForUI>();
@@ -36,8 +36,8 @@
 MockIOSChromeSavePasswordInfoBarDelegate::Create(NSString* username,
                                                  NSString* password,
                                                  const GURL& url) {
-  std::unique_ptr<autofill::PasswordForm> form =
-      std::make_unique<autofill::PasswordForm>();
+  std::unique_ptr<password_manager::PasswordForm> form =
+      std::make_unique<password_manager::PasswordForm>();
   form->username_value = base::SysNSStringToUTF16(username);
   form->password_value = base::SysNSStringToUTF16(password);
   return base::WrapUnique(new MockIOSChromeSavePasswordInfoBarDelegate(
@@ -46,7 +46,7 @@
 
 MockIOSChromeSavePasswordInfoBarDelegate::
     MockIOSChromeSavePasswordInfoBarDelegate(
-        std::unique_ptr<autofill::PasswordForm> form,
+        std::unique_ptr<password_manager::PasswordForm> form,
         std::unique_ptr<GURL> url)
     : IOSChromeSavePasswordInfoBarDelegate(
           /*is_sync_user=*/false,
diff --git a/ios/chrome/browser/passwords/test/test_password_manager_client.h b/ios/chrome/browser/passwords/test/test_password_manager_client.h
index a852f92..33abccd 100644
--- a/ios/chrome/browser/passwords/test/test_password_manager_client.h
+++ b/ios/chrome/browser/passwords/test/test_password_manager_client.h
@@ -32,10 +32,11 @@
   // PromptUserTo*Ptr functions allow to both override PromptUserTo* methods
   // and expect calls.
   MOCK_METHOD1(PromptUserToSavePasswordPtr, void(PasswordFormManagerForUI*));
-  MOCK_METHOD3(PromptUserToChooseCredentialsPtr,
-               bool(const std::vector<autofill::PasswordForm*>& local_forms,
-                    const url::Origin& origin,
-                    CredentialsCallback callback));
+  MOCK_METHOD3(
+      PromptUserToChooseCredentialsPtr,
+      bool(const std::vector<password_manager::PasswordForm*>& local_forms,
+           const url::Origin& origin,
+           CredentialsCallback callback));
 
   scoped_refptr<TestPasswordStore> password_store() const;
   void set_password_store(scoped_refptr<TestPasswordStore> store);
@@ -59,7 +60,7 @@
   // Mocks choosing a credential by the user. To put expectation on this
   // function being called, use PromptUserToChooseCredentialsPtr.
   bool PromptUserToChooseCredentials(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms,
+      std::vector<std::unique_ptr<password_manager::PasswordForm>> local_forms,
       const url::Origin& origin,
       CredentialsCallback callback) override;
 
diff --git a/ios/chrome/browser/passwords/test/test_password_manager_client.mm b/ios/chrome/browser/passwords/test/test_password_manager_client.mm
index 6194ffca..d2be2fb6 100644
--- a/ios/chrome/browser/passwords/test/test_password_manager_client.mm
+++ b/ios/chrome/browser/passwords/test/test_password_manager_client.mm
@@ -83,20 +83,21 @@
 }
 
 bool TestPasswordManagerClient::PromptUserToChooseCredentials(
-    std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms,
+    std::vector<std::unique_ptr<password_manager::PasswordForm>> local_forms,
     const url::Origin& origin,
     CredentialsCallback callback) {
   EXPECT_FALSE(local_forms.empty());
-  const autofill::PasswordForm* form = local_forms[0].get();
+  const password_manager::PasswordForm* form = local_forms[0].get();
   base::SequencedTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
       base::BindOnce(std::move(callback),
-                     base::Owned(new autofill::PasswordForm(*form))));
-  std::vector<autofill::PasswordForm*> raw_forms(local_forms.size());
-  std::transform(local_forms.begin(), local_forms.end(), raw_forms.begin(),
-                 [](const std::unique_ptr<autofill::PasswordForm>& form) {
-                   return form.get();
-                 });
+                     base::Owned(new password_manager::PasswordForm(*form))));
+  std::vector<password_manager::PasswordForm*> raw_forms(local_forms.size());
+  std::transform(
+      local_forms.begin(), local_forms.end(), raw_forms.begin(),
+      [](const std::unique_ptr<password_manager::PasswordForm>& form) {
+        return form.get();
+      });
   PromptUserToChooseCredentialsPtr(raw_forms, origin, base::DoNothing());
   return true;
 }
diff --git a/ios/chrome/browser/ui/activity_services/activities/copy_activity_unittest.mm b/ios/chrome/browser/ui/activity_services/activities/copy_activity_unittest.mm
index 6a9c9d5a..4d78681 100644
--- a/ios/chrome/browser/ui/activity_services/activities/copy_activity_unittest.mm
+++ b/ios/chrome/browser/ui/activity_services/activities/copy_activity_unittest.mm
@@ -55,9 +55,9 @@
                               thumbnailGenerator:nil];
   }
 
-  NSURL* GetExpectedURL() {
-    return [NSURL URLWithString:base::SysUTF8ToNSString(kTestShareURL)];
-  }
+  NSString* GetURLString() { return base::SysUTF8ToNSString(kTestShareURL); }
+
+  NSURL* GetExpectedURL() { return [NSURL URLWithString:GetURLString()]; }
 };
 
 // Tests that the activity can be performed.
@@ -95,13 +95,16 @@
 
   [activity_partial_mock verify];
 
-  // Additional text is stored as the first pasteboard item.
-  EXPECT_TRUE([kTestAdditionaText
-      isEqualToString:UIPasteboard.generalPasteboard.string]);
+  ASSERT_TRUE(UIPasteboard.generalPasteboard.hasURLs);
+  ASSERT_TRUE(UIPasteboard.generalPasteboard.hasStrings);
 
-  // URL is stored as the second pasteboard item, but can be accessed as the
-  // first (and only) URL item.
-  ASSERT_TRUE([UIPasteboard generalPasteboard].hasURLs);
-  NSURL* expected_url = GetExpectedURL();
-  EXPECT_TRUE([expected_url isEqual:UIPasteboard.generalPasteboard.URLs[0]]);
+  // The first pasteboard item has both a URL and string representation of the
+  // test URL.
+  EXPECT_TRUE(
+      [GetURLString() isEqualToString:UIPasteboard.generalPasteboard.string]);
+  EXPECT_TRUE([GetExpectedURL() isEqual:UIPasteboard.generalPasteboard.URL]);
+
+  // The second pasteboard item has the additional text stored as string.
+  EXPECT_TRUE(
+      [kTestAdditionaText isEqual:UIPasteboard.generalPasteboard.strings[1]]);
 }
diff --git a/ios/chrome/browser/ui/autofill/autofill_app_interface.mm b/ios/chrome/browser/ui/autofill/autofill_app_interface.mm
index 3f9b719..3445aad2 100644
--- a/ios/chrome/browser/ui/autofill/autofill_app_interface.mm
+++ b/ios/chrome/browser/ui/autofill/autofill_app_interface.mm
@@ -56,11 +56,12 @@
 class TestStoreConsumer : public password_manager::PasswordStoreConsumer {
  public:
   void OnGetPasswordStoreResults(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> obtained) override {
+      std::vector<std::unique_ptr<password_manager::PasswordForm>> obtained)
+      override {
     obtained_ = std::move(obtained);
   }
 
-  const std::vector<autofill::PasswordForm>& GetStoreResults() {
+  const std::vector<password_manager::PasswordForm>& GetStoreResults() {
     results_.clear();
     ResetObtained();
     GetPasswordStore()->GetAllLogins(this);
@@ -94,19 +95,19 @@
   }
 
   // Temporary cache of obtained store results.
-  std::vector<std::unique_ptr<autofill::PasswordForm>> obtained_;
+  std::vector<std::unique_ptr<password_manager::PasswordForm>> obtained_;
 
   // Combination of fillable and blocked credentials from the store.
-  std::vector<autofill::PasswordForm> results_;
+  std::vector<password_manager::PasswordForm> results_;
 };
 
 // Saves |form| to the password store and waits until the async processing is
 // done.
-void SaveToPasswordStore(const autofill::PasswordForm& form) {
+void SaveToPasswordStore(const password_manager::PasswordForm& form) {
   GetPasswordStore()->AddLogin(form);
   // When we retrieve the form from the store, |in_store| should be set.
-  autofill::PasswordForm expected_form = form;
-  expected_form.in_store = autofill::PasswordForm::Store::kProfileStore;
+  password_manager::PasswordForm expected_form = form;
+  expected_form.in_store = password_manager::PasswordForm::Store::kProfileStore;
   // Check the result and ensure PasswordStore processed this.
   TestStoreConsumer consumer;
   for (const auto& result : consumer.GetStoreResults()) {
@@ -117,7 +118,7 @@
 
 // Saves an example form in the store.
 void SaveExamplePasswordForm() {
-  autofill::PasswordForm example;
+  password_manager::PasswordForm example;
   example.username_value = base::ASCIIToUTF16(kExampleUsername);
   example.password_value = base::ASCIIToUTF16(kExamplePassword);
   example.url = GURL("https://example.com/");
@@ -127,7 +128,7 @@
 
 // Saves an example form in the store for the passed URL.
 void SaveLocalPasswordForm(const GURL& url) {
-  autofill::PasswordForm localForm;
+  password_manager::PasswordForm localForm;
   localForm.username_value = base::ASCIIToUTF16(kExampleUsername);
   localForm.password_value = base::ASCIIToUTF16(kExamplePassword);
   localForm.url = url;
diff --git a/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_mediator.mm b/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_mediator.mm
index 6bc0afd..8d6dd6c 100644
--- a/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_mediator.mm
+++ b/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_mediator.mm
@@ -668,7 +668,8 @@
 
 - (void)passwordFetcher:(PasswordFetcher*)passwordFetcher
       didFetchPasswords:
-          (std::vector<std::unique_ptr<autofill::PasswordForm>>)passwords {
+          (std::vector<std::unique_ptr<password_manager::PasswordForm>>)
+              passwords {
   self.consumer.passwordButtonHidden = passwords.empty();
 }
 
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/BUILD.gn b/ios/chrome/browser/ui/autofill/manual_fill/BUILD.gn
index 85e8c789..940835c 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/BUILD.gn
+++ b/ios/chrome/browser/ui/autofill/manual_fill/BUILD.gn
@@ -166,6 +166,7 @@
     "//components/autofill/ios/form_util:form_util",
     "//components/autofill/ios/form_util:test_support",
     "//components/leveldb_proto:leveldb_proto",
+    "//components/password_manager/core/browser",
     "//components/prefs",
     "//ios/chrome/browser",
     "//ios/chrome/browser/browser_state:test_support",
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credential+PasswordForm.h b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credential+PasswordForm.h
index d3f7744f..cb1742d 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credential+PasswordForm.h
+++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credential+PasswordForm.h
@@ -5,17 +5,14 @@
 #ifndef IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_MANUAL_FILL_CREDENTIAL_PASSWORDFORM_H_
 #define IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_MANUAL_FILL_CREDENTIAL_PASSWORDFORM_H_
 
+#include "components/password_manager/core/browser/password_form_forward.h"
 #import "ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credential.h"
 
-namespace autofill {
-struct PasswordForm;
-}
-
 @interface ManualFillCredential (PasswordForm)
 
 // Convenience initializer from a PasswordForm.
 - (instancetype)initWithPasswordForm:
-    (const autofill::PasswordForm&)passwordForm;
+    (const password_manager::PasswordForm&)passwordForm;
 
 @end
 
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credential+PasswordForm.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credential+PasswordForm.mm
index 05d60c9..9001875 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credential+PasswordForm.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credential+PasswordForm.mm
@@ -5,7 +5,7 @@
 #import "ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credential+PasswordForm.h"
 
 #include "base/strings/sys_string_conversions.h"
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_ui_utils.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "url/gurl.h"
@@ -17,7 +17,7 @@
 @implementation ManualFillCredential (PasswordForm)
 
 - (instancetype)initWithPasswordForm:
-    (const autofill::PasswordForm&)passwordForm {
+    (const password_manager::PasswordForm&)passwordForm {
   std::string host = passwordForm.url.host();
   std::string site_name =
       net::registry_controlled_domains::GetDomainAndRegistry(
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credential+PasswordForm_unittest.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credential+PasswordForm_unittest.mm
index 231dff6..605d46d 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credential+PasswordForm_unittest.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credential+PasswordForm_unittest.mm
@@ -5,7 +5,7 @@
 #import "ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credential+PasswordForm.h"
 
 #include "base/strings/sys_string_conversions.h"
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "testing/platform_test.h"
 #include "url/gurl.h"
 
@@ -13,7 +13,7 @@
 #error "This file requires ARC support."
 #endif
 
-using autofill::PasswordForm;
+using password_manager::PasswordForm;
 using ManualFillCredentialFormPasswordiOSTest = PlatformTest;
 
 // Tests the creation of a credential from a password form.
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_mediator.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_mediator.mm
index 01271e9..eb9626a 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_mediator.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_mediator.mm
@@ -101,7 +101,8 @@
 
 - (void)passwordFetcher:(PasswordFetcher*)passwordFetcher
       didFetchPasswords:
-          (std::vector<std::unique_ptr<autofill::PasswordForm>>)passwords {
+          (std::vector<std::unique_ptr<password_manager::PasswordForm>>)
+              passwords {
   NSMutableArray<ManualFillCredential*>* credentials =
       [[NSMutableArray alloc] initWithCapacity:passwords.size()];
   for (const auto& form : passwords) {
diff --git a/ios/chrome/browser/ui/badges/BUILD.gn b/ios/chrome/browser/ui/badges/BUILD.gn
index 2c3edd1..4098404 100644
--- a/ios/chrome/browser/ui/badges/BUILD.gn
+++ b/ios/chrome/browser/ui/badges/BUILD.gn
@@ -96,17 +96,22 @@
     ":public",
     "//base",
     "//ios/chrome/app/strings:ios_strings_grit",
+    "//ios/chrome/browser/infobars",
     "//ios/chrome/browser/infobars:public",
+    "//ios/chrome/browser/infobars/overlays",
     "//ios/chrome/browser/main:public",
+    "//ios/chrome/browser/overlays",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
+    "//ios/chrome/browser/ui/infobars:feature_flags",
     "//ios/chrome/browser/ui/list_model",
     "//ios/chrome/browser/ui/popup_menu/public:popup_menu_ui",
     "//ios/chrome/browser/ui/popup_menu/public/cells",
     "//ios/chrome/browser/ui/table_view:styler",
     "//ios/chrome/browser/ui/table_view/cells",
     "//ios/chrome/browser/ui/util",
+    "//ios/chrome/browser/web_state_list",
     "//ios/chrome/common/ui/colors",
     "//ios/chrome/common/ui/util",
     "//ui/base",
diff --git a/ios/chrome/browser/ui/badges/badge_popup_menu_coordinator.mm b/ios/chrome/browser/ui/badges/badge_popup_menu_coordinator.mm
index 721e583d..86a8f26 100644
--- a/ios/chrome/browser/ui/badges/badge_popup_menu_coordinator.mm
+++ b/ios/chrome/browser/ui/badges/badge_popup_menu_coordinator.mm
@@ -6,15 +6,20 @@
 
 #include "base/metrics/histogram_macros.h"
 #include "base/notreached.h"
+#include "ios/chrome/browser/infobars/infobar_ios.h"
+#include "ios/chrome/browser/infobars/infobar_manager_impl.h"
 #include "ios/chrome/browser/infobars/infobar_metrics_recorder.h"
 #import "ios/chrome/browser/infobars/infobar_type.h"
+#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h"
 #import "ios/chrome/browser/main/browser.h"
+#include "ios/chrome/browser/overlays/public/overlay_request_queue.h"
 #import "ios/chrome/browser/ui/badges/badge_constants.h"
 #import "ios/chrome/browser/ui/badges/badge_item.h"
 #import "ios/chrome/browser/ui/badges/badge_popup_menu_item.h"
 #import "ios/chrome/browser/ui/badges/badges_histograms.h"
 #import "ios/chrome/browser/ui/commands/command_dispatcher.h"
 #import "ios/chrome/browser/ui/commands/infobar_commands.h"
+#import "ios/chrome/browser/ui/infobars/infobar_feature.h"
 #import "ios/chrome/browser/ui/popup_menu/public/cells/popup_menu_item.h"
 #import "ios/chrome/browser/ui/popup_menu/public/popup_menu_consumer.h"
 #import "ios/chrome/browser/ui/popup_menu/public/popup_menu_presenter.h"
@@ -23,6 +28,7 @@
 #import "ios/chrome/browser/ui/popup_menu/public/popup_menu_table_view_controller_delegate.h"
 #import "ios/chrome/browser/ui/table_view/cells/table_view_item.h"
 #import "ios/chrome/browser/ui/util/layout_guide_names.h"
+#import "ios/chrome/browser/web_state_list/web_state_list.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -94,31 +100,31 @@
                        didSelectItem:(TableViewItem<PopupMenuItem>*)item
                               origin:(CGPoint)origin {
   [self dismissPopupMenu];
-  id<InfobarCommands> handler =
-      HandlerForProtocol(self.browser->GetCommandDispatcher(), InfobarCommands);
   switch (item.actionIdentifier) {
     case PopupMenuActionShowSavePasswordOptions: {
       UMA_HISTOGRAM_ENUMERATION(kInfobarOverflowMenuTappedHistogram,
                                 MobileMessagesInfobarType::SavePassword);
-      [handler displayModalInfobar:InfobarType::kInfobarTypePasswordSave];
+      [self
+          addModalRequestForInfobarType:InfobarType::kInfobarTypePasswordSave];
       break;
     }
     case PopupMenuActionShowUpdatePasswordOptions: {
       UMA_HISTOGRAM_ENUMERATION(kInfobarOverflowMenuTappedHistogram,
                                 MobileMessagesInfobarType::UpdatePassword);
-      [handler displayModalInfobar:InfobarType::kInfobarTypePasswordUpdate];
+      [self addModalRequestForInfobarType:InfobarType::
+                                              kInfobarTypePasswordUpdate];
       break;
     }
     case PopupMenuActionShowSaveCardOptions: {
       UMA_HISTOGRAM_ENUMERATION(kInfobarOverflowMenuTappedHistogram,
                                 MobileMessagesInfobarType::SaveCard);
-      [handler displayModalInfobar:InfobarType::kInfobarTypeSaveCard];
+      [self addModalRequestForInfobarType:InfobarType::kInfobarTypeSaveCard];
       break;
     }
     case PopupMenuActionShowTranslateOptions: {
       UMA_HISTOGRAM_ENUMERATION(kInfobarOverflowMenuTappedHistogram,
                                 MobileMessagesInfobarType::Translate);
-      [handler displayModalInfobar:InfobarType::kInfobarTypeTranslate];
+      [self addModalRequestForInfobarType:InfobarType::kInfobarTypeTranslate];
       break;
     }
     default:
@@ -129,6 +135,42 @@
 
 #pragma mark - Private
 
+// Adds a modal request for the Infobar of |infobarType|.
+- (void)addModalRequestForInfobarType:(InfobarType)infobarType {
+  if (base::FeatureList::IsEnabled(kInfobarOverlayUI)) {
+    web::WebState* webState =
+        self.browser->GetWebStateList()->GetActiveWebState();
+    DCHECK(webState);
+    InfoBarIOS* infobar = [self infobarWithType:infobarType];
+    DCHECK(infobar);
+    InfobarOverlayRequestInserter::CreateForWebState(webState);
+    InsertParams params(infobar);
+    params.overlay_type = InfobarOverlayType::kModal;
+    params.insertion_index = OverlayRequestQueue::FromWebState(
+                                 webState, OverlayModality::kInfobarModal)
+                                 ->size();
+    params.source = InfobarOverlayInsertionSource::kBadge;
+    InfobarOverlayRequestInserter::FromWebState(webState)->InsertOverlayRequest(
+        params);
+  } else {
+    id<InfobarCommands> handler = HandlerForProtocol(
+        self.browser->GetCommandDispatcher(), InfobarCommands);
+    [handler displayModalInfobar:infobarType];
+  }
+}
+
+// Retrieves the existing Infobar of |type|.
+- (InfoBarIOS*)infobarWithType:(InfobarType)type {
+  InfoBarManagerImpl* manager = InfoBarManagerImpl::FromWebState(
+      self.browser->GetWebStateList()->GetActiveWebState());
+  for (size_t index = 0; index < manager->infobar_count(); ++index) {
+    InfoBarIOS* infobar = static_cast<InfoBarIOS*>(manager->infobar_at(index));
+    if (infobar->infobar_type() == type)
+      return infobar;
+  }
+  return nullptr;
+}
+
 - (void)dismissPopupMenu {
   if (self.popupMenuPresenter) {
     [self.popupMenuPresenter dismissAnimated:YES];
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 0b521a1..f48a73ea 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -89,6 +89,7 @@
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h"
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_ui_element.h"
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_ui_updater.h"
+#include "ios/chrome/browser/ui/fullscreen/scoped_fullscreen_disabler.h"
 #import "ios/chrome/browser/ui/gestures/view_revealing_animatee.h"
 #import "ios/chrome/browser/ui/image_util/image_copier.h"
 #import "ios/chrome/browser/ui/image_util/image_saver.h"
@@ -467,6 +468,10 @@
 
   // Presenter for in-product help bubbles.
   BubblePresenter* _bubblePresenter;
+
+  // The disabler that prevents the toolbar from being scrolled offscreen when
+  // the thumb strip is visible.
+  std::unique_ptr<ScopedFullscreenDisabler> _fullscreenDisabler;
 }
 
 // Activates/deactivates the object. This will enable/disable the ability for
@@ -2814,6 +2819,13 @@
 #pragma mark - ViewRevealingAnimatee
 
 - (void)willAnimateViewReveal:(ViewRevealState)currentViewRevealState {
+  // Disable fullscreen if the thumb strip is about to be shown.
+  if (currentViewRevealState == ViewRevealState::Hidden &&
+      !_fullscreenDisabler) {
+    _fullscreenDisabler = std::make_unique<ScopedFullscreenDisabler>(
+        FullscreenController::FromBrowser(_browser));
+  }
+
   // Hide the tab strip and take a snapshot of it. If a snapshot of a hidden
   // view is taken, the snapshot will be a blank view. However, if the view's
   // parent is hidden but the view itself is not, the snapshot will not be a
@@ -2858,6 +2870,11 @@
   self.tabStripView.hidden = (viewRevealState != ViewRevealState::Hidden);
   [self.tabStripSnapshot removeFromSuperview];
   self.bottomPosition = (viewRevealState == ViewRevealState::Revealed);
+
+  if (viewRevealState == ViewRevealState::Hidden) {
+    // Stop disabling fullscreen.
+    _fullscreenDisabler.reset();
+  }
 }
 
 #pragma mark - BubblePresenterDelegate
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
index 2c60ec4c..2899ec2 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -436,10 +436,9 @@
     UIViewController* newFeedViewController = discoverFeedItem.discoverFeed;
 
     if (newFeedViewController != self.discoverFeedVC) {
-      // If previous VC is not nil, remove it from the view hierarchy and stop
-      // osberving its feedView.
+      // If previous VC is not nil, remove it from the view hierarchy.
       if (self.discoverFeedVC) {
-        [self removeContentSizeKVO];
+        self.feedView = nil;
         [self.discoverFeedVC willMoveToParentViewController:nil];
         [self.discoverFeedVC.view removeFromSuperview];
         [self.discoverFeedVC removeFromParentViewController];
@@ -458,7 +457,6 @@
             self.feedView = static_cast<UICollectionView*>(view);
           }
         }
-        [self addContentSizeKVO];
         self.discoverFeedVC = newFeedViewController;
         return cell;
       }
@@ -833,6 +831,15 @@
 
 #pragma mark - Private
 
+// |self.feedView| setter.
+- (void)setFeedView:(UICollectionView*)feedView {
+  if (feedView != _feedView) {
+    [self removeContentSizeKVO];
+    _feedView = feedView;
+    [self addContentSizeKVO];
+  }
+}
+
 // Adds KVO observing for the feedView contentSize if there is not one already.
 - (void)addContentSizeKVO {
   if (!self.observingDiscoverFeedHeight) {
diff --git a/ios/chrome/browser/ui/infobars/test/test_infobar_password_delegate.mm b/ios/chrome/browser/ui/infobars/test/test_infobar_password_delegate.mm
index 821f8624..f7ac4475 100644
--- a/ios/chrome/browser/ui/infobars/test/test_infobar_password_delegate.mm
+++ b/ios/chrome/browser/ui/infobars/test/test_infobar_password_delegate.mm
@@ -5,10 +5,10 @@
 #import "ios/chrome/browser/ui/infobars/test/test_infobar_password_delegate.h"
 
 #include "base/strings/sys_string_conversions.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/infobars/core/infobar.h"
 #include "components/password_manager/core/browser/credential_manager_password_form_manager.h"
 #include "components/password_manager/core/browser/fake_form_fetcher.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_form_manager_for_ui.h"
 #include "components/password_manager/core/browser/stub_form_saver.h"
 #include "components/password_manager/core/browser/stub_password_manager_client.h"
@@ -18,7 +18,7 @@
 #error "This file requires ARC support."
 #endif
 
-using autofill::PasswordForm;
+using password_manager::PasswordForm;
 using base::ASCIIToUTF16;
 
 namespace {
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator_unittest.mm b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator_unittest.mm
index 95fca1b..990853c 100644
--- a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator_unittest.mm
@@ -9,7 +9,6 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/infobars/core/infobar.h"
 #include "components/infobars/core/infobar_feature.h"
 #include "ios/chrome/browser/infobars/infobar_ios.h"
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/update_password_infobar_banner_overlay_mediator_unittest.mm b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/update_password_infobar_banner_overlay_mediator_unittest.mm
index 7fb094f8..9c292530 100644
--- a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/update_password_infobar_banner_overlay_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/update_password_infobar_banner_overlay_mediator_unittest.mm
@@ -9,7 +9,6 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/infobars/core/infobar.h"
 #include "components/infobars/core/infobar_feature.h"
 #include "ios/chrome/browser/infobars/infobar_ios.h"
diff --git a/ios/chrome/browser/ui/settings/README.md b/ios/chrome/browser/ui/settings/README.md
deleted file mode 100644
index 88c7ca047..0000000
--- a/ios/chrome/browser/ui/settings/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Settings
-
------
-**Some of the files in this directory are only used in the new iOS Chrome
-architecture:**
-
-* `settings_coordinator.h` and `.mm`
-
------
diff --git a/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.h b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.h
index 965066db..d9ca930 100644
--- a/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.h
+++ b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.h
@@ -5,13 +5,10 @@
 #ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_LEGACY_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_H_
 #define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_LEGACY_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_H_
 
+#include "components/password_manager/core/browser/password_form_forward.h"
 #import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_delegate.h"
 #import "ios/chrome/browser/ui/settings/settings_root_table_view_controller.h"
 
-namespace autofill {
-struct PasswordForm;
-}  // namespace autofill
-
 @protocol ReauthenticationProtocol;
 
 // TODO(crbug.com/1096986): Delete this view controller after Password Check
@@ -26,7 +23,7 @@
 
 // The designated initializer.
 - (nullable instancetype)
-      initWithPasswordForm:(const autofill::PasswordForm&)passwordForm
+      initWithPasswordForm:(const password_manager::PasswordForm&)passwordForm
                   delegate:
                       (nonnull
                            id<LegacyPasswordDetailsTableViewControllerDelegate>)
diff --git a/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.mm
index 4cc6f3ef..eeb601c4 100644
--- a/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.mm
@@ -13,7 +13,7 @@
 #include "base/mac/foundation_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/sys_string_conversions.h"
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/password_manager/core/browser/password_ui_utils.h"
@@ -80,7 +80,7 @@
   // Whether the password is shown in plain text form or in obscured form.
   BOOL _plainTextPasswordShown;
   // The password form.
-  autofill::PasswordForm _passwordForm;
+  password_manager::PasswordForm _passwordForm;
   // Module containing the reauthentication mechanism for viewing and copying
   // passwords.
   __weak id<ReauthenticationProtocol> _weakReauthenticationModule;
@@ -104,7 +104,7 @@
 @synthesize deleteConfirmation = _deleteConfirmation;
 
 - (instancetype)
-      initWithPasswordForm:(const autofill::PasswordForm&)passwordForm
+      initWithPasswordForm:(const password_manager::PasswordForm&)passwordForm
                   delegate:
                       (id<LegacyPasswordDetailsTableViewControllerDelegate>)
                           delegate
diff --git a/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_delegate.h b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_delegate.h
index d9c5e1a36..b456ad2 100644
--- a/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_delegate.h
+++ b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_delegate.h
@@ -7,9 +7,7 @@
 
 #import <Foundation/Foundation.h>
 
-namespace autofill {
-struct PasswordForm;
-}  // namespace autofill
+#include "components/password_manager/core/browser/password_form_forward.h"
 
 @class LegacyPasswordDetailsTableViewController;
 
@@ -20,7 +18,8 @@
 - (void)passwordDetailsTableViewController:
             (LegacyPasswordDetailsTableViewController*)controller
                             deletePassword:
-                                (const autofill::PasswordForm&)passwordForm;
+                                (const password_manager::PasswordForm&)
+                                    passwordForm;
 
 @end
 
diff --git a/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_unittest.mm
index 77b64ade..87b34785 100644
--- a/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_unittest.mm
@@ -6,7 +6,7 @@
 
 #include "base/mac/foundation_util.h"
 #include "base/strings/sys_string_conversions.h"
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 #import "ios/chrome/browser/ui/table_view/cells/table_view_text_item.h"
 #import "ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.h"
 #import "ios/chrome/browser/web/chrome_web_test.h"
@@ -76,7 +76,7 @@
   web::WebTaskEnvironment task_environment_;
   MockReauthenticationModule* reauthentication_module_;
   NSString* origin_;
-  autofill::PasswordForm form_;
+  password_manager::PasswordForm form_;
 };
 
 TEST_F(LegacyPasswordDetailsTableViewControllerTest,
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details.h b/ios/chrome/browser/ui/settings/password/password_details/password_details.h
index 7604402f9..500e7e58 100644
--- a/ios/chrome/browser/ui/settings/password/password_details/password_details.h
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details.h
@@ -7,12 +7,9 @@
 
 #import <Foundation/Foundation.h>
 
+#include "components/password_manager/core/browser/password_form_forward.h"
 #include "url/gurl.h"
 
-namespace autofill {
-struct PasswordForm;
-}
-
 // Object which is used by |PasswordDetailsViewController| to show
 // information about password.
 @interface PasswordDetails : NSObject
@@ -35,7 +32,7 @@
 // URL which allows to change the password of compromised credential.
 @property(nonatomic, readonly) GURL changePasswordURL;
 
-- (instancetype)initWithPasswordForm:(const autofill::PasswordForm&)form
+- (instancetype)initWithPasswordForm:(const password_manager::PasswordForm&)form
     NS_DESIGNATED_INITIALIZER;
 
 - (instancetype)init NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details.mm
index 2fc8814..a047939f 100644
--- a/ios/chrome/browser/ui/settings/password/password_details/password_details.mm
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details.mm
@@ -5,8 +5,8 @@
 #import "ios/chrome/browser/ui/settings/password/password_details/password_details.h"
 
 #include "base/strings/sys_string_conversions.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_ui_utils.h"
 #include "components/password_manager/core/browser/well_known_change_password_util.h"
 
@@ -16,7 +16,8 @@
 
 @implementation PasswordDetails
 
-- (instancetype)initWithPasswordForm:(const autofill::PasswordForm&)form {
+- (instancetype)initWithPasswordForm:
+    (const password_manager::PasswordForm&)form {
   self = [super init];
   if (self) {
     auto facetUri = password_manager::FacetURI::FromPotentiallyInvalidSpec(
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.h
index 8793faa..c6250b2 100644
--- a/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.h
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.h
@@ -5,6 +5,7 @@
 #ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_COORDINATOR_H_
 #define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_COORDINATOR_H_
 
+#include "components/password_manager/core/browser/password_form_forward.h"
 #import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
 
 @protocol ApplicationCommands;
@@ -13,10 +14,6 @@
 @protocol PasswordDetailsCoordinatorDelegate;
 @class ReauthenticationModule;
 
-namespace autofill {
-struct PasswordForm;
-}
-
 // This coordinator presents a password details for the user.
 @interface PasswordDetailsCoordinator : ChromeCoordinator
 
@@ -24,7 +21,8 @@
     initWithBaseNavigationController:
         (UINavigationController*)navigationController
                              browser:(Browser*)browser
-                            password:(const autofill::PasswordForm&)password
+                            password:
+                                (const password_manager::PasswordForm&)password
                         reauthModule:(ReauthenticationModule*)reauthModule
                 passwordCheckManager:(IOSChromePasswordCheckManager*)manager
     NS_DESIGNATED_INITIALIZER;
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm
index 0eb6bbe..bc93e0bc 100644
--- a/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm
@@ -7,7 +7,7 @@
 #include "base/mac/foundation_util.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/strings/sys_string_conversions.h"
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/main/browser.h"
@@ -31,7 +31,7 @@
 #endif
 
 @interface PasswordDetailsCoordinator () <PasswordDetailsHandler> {
-  autofill::PasswordForm _password;
+  password_manager::PasswordForm _password;
 
   // Manager responsible for password check feature.
   IOSChromePasswordCheckManager* _manager;
@@ -66,7 +66,8 @@
     initWithBaseNavigationController:
         (UINavigationController*)navigationController
                              browser:(Browser*)browser
-                            password:(const autofill::PasswordForm&)password
+                            password:
+                                (const password_manager::PasswordForm&)password
                         reauthModule:(ReauthenticationModule*)reauthModule
                 passwordCheckManager:(IOSChromePasswordCheckManager*)manager {
   self = [super initWithBaseViewController:navigationController
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator_delegate.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator_delegate.h
index 56e1c44a..adbd5b7 100644
--- a/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator_delegate.h
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator_delegate.h
@@ -5,11 +5,9 @@
 #ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_COORDINATOR_DELEGATE_H_
 #define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_COORDINATOR_DELEGATE_H_
 
-@class PasswordDetailsCoordinator;
+#include "components/password_manager/core/browser/password_form_forward.h"
 
-namespace autofill {
-struct PasswordForm;
-}
+@class PasswordDetailsCoordinator;
 
 // Delegate for PasswordIssuesCoordinator.
 @protocol PasswordDetailsCoordinatorDelegate
@@ -21,7 +19,8 @@
 // Called when user deleted password. This action should be handled
 // outside to update the list of passwords immediately.
 - (void)passwordDetailsCoordinator:(PasswordDetailsCoordinator*)coordinator
-                    deletePassword:(const autofill::PasswordForm&)password;
+                    deletePassword:
+                        (const password_manager::PasswordForm&)password;
 
 @end
 
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.h
index 60aefde..def0dd1 100644
--- a/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.h
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.h
@@ -7,21 +7,19 @@
 
 #import <Foundation/Foundation.h>
 
+#include "components/password_manager/core/browser/password_form_forward.h"
 #import "ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_delegate.h"
 
 class IOSChromePasswordCheckManager;
 @protocol PasswordDetailsConsumer;
 
-namespace autofill {
-struct PasswordForm;
-}
-
 // This mediator fetches and organises the credentials for its consumer.
 @interface PasswordDetailsMediator
     : NSObject <PasswordDetailsTableViewControllerDelegate>
 
 // PasswordForm is converted to the PasswordDetails and passed to a consumer.
-- (instancetype)initWithPassword:(const autofill::PasswordForm&)passwordForm
+- (instancetype)initWithPassword:
+                    (const password_manager::PasswordForm&)passwordForm
             passwordCheckManager:(IOSChromePasswordCheckManager*)manager
     NS_DESIGNATED_INITIALIZER;
 
@@ -31,7 +29,7 @@
 @property(nonatomic, weak) id<PasswordDetailsConsumer> consumer;
 
 // Password passed to the mediator.
-@property(nonatomic, readonly) autofill::PasswordForm password;
+@property(nonatomic, readonly) password_manager::PasswordForm password;
 
 // Disconnects the mediator from all observers.
 - (void)disconnect;
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.mm
index 6b155c2..fbc9ec7 100644
--- a/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.mm
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.mm
@@ -5,7 +5,7 @@
 #import "ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.h"
 
 #include "base/strings/sys_string_conversions.h"
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "ios/chrome/browser/passwords/password_check_observer_bridge.h"
 #import "ios/chrome/browser/ui/settings/password/password_details/password_details.h"
 #import "ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h"
@@ -35,7 +35,8 @@
 
 @implementation PasswordDetailsMediator
 
-- (instancetype)initWithPassword:(const autofill::PasswordForm&)passwordForm
+- (instancetype)initWithPassword:
+                    (const password_manager::PasswordForm&)passwordForm
             passwordCheckManager:(IOSChromePasswordCheckManager*)manager {
   self = [super init];
   if (self) {
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_unittest.mm
index 345027e..06f570d 100644
--- a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_unittest.mm
@@ -9,7 +9,7 @@
 #include "base/ios/ios_util.h"
 #include "base/mac/foundation_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #import "ios/chrome/browser/ui/commands/snackbar_commands.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_image_detail_text_item.h"
@@ -146,14 +146,14 @@
                    std::string username = kUsername,
                    std::string password = kPassword,
                    bool isCompromised = false) {
-    auto form = autofill::PasswordForm();
+    auto form = password_manager::PasswordForm();
     form.signon_realm = website;
     form.username_value = base::ASCIIToUTF16(username);
     form.password_value = base::ASCIIToUTF16(password);
     form.url = GURL(website);
     form.action = GURL(website + "/action");
     form.username_element = base::ASCIIToUTF16("email");
-    form.scheme = autofill::PasswordForm::Scheme::kHtml;
+    form.scheme = password_manager::PasswordForm::Scheme::kHtml;
 
     PasswordDetails* passwordDetails =
         [[PasswordDetails alloc] initWithPasswordForm:form];
@@ -165,7 +165,7 @@
   }
 
   void SetFederatedPassword() {
-    auto form = autofill::PasswordForm();
+    auto form = password_manager::PasswordForm();
     form.username_value = base::ASCIIToUTF16("test@egmail.com");
     form.url = GURL(base::ASCIIToUTF16("http://www.example.com/"));
     form.signon_realm = form.url.spec();
@@ -179,7 +179,7 @@
   }
 
   void SetBlockedOrigin() {
-    auto form = autofill::PasswordForm();
+    auto form = password_manager::PasswordForm();
     form.url = GURL("http://www.example.com/");
     form.blocked_by_user = true;
     form.signon_realm = form.url.spec();
diff --git a/ios/chrome/browser/ui/settings/password/password_exporter.h b/ios/chrome/browser/ui/settings/password/password_exporter.h
index c0b73ba7..bb0d9cc 100644
--- a/ios/chrome/browser/ui/settings/password/password_exporter.h
+++ b/ios/chrome/browser/ui/settings/password/password_exporter.h
@@ -10,9 +10,7 @@
 #include <memory>
 #include <vector>
 
-namespace autofill {
-struct PasswordForm;
-}  // namespace autofill
+#include "components/password_manager/core/browser/password_form_forward.h"
 
 enum class WriteToURLStatus {
   SUCCESS,
@@ -43,7 +41,8 @@
 // Posts task to serialize passwords and calls |serializedPasswordsHandler|
 // when serialization is finished.
 - (void)serializePasswords:
-            (std::vector<std::unique_ptr<autofill::PasswordForm>>)passwords
+            (std::vector<std::unique_ptr<password_manager::PasswordForm>>)
+                passwords
                    handler:(void (^)(std::string))serializedPasswordsHandler;
 
 @end
@@ -106,7 +105,7 @@
 // Method to be called in order to start the export flow. This initiates
 // the reauthentication procedure and asks for password serialization.
 - (void)startExportFlow:
-    (std::vector<std::unique_ptr<autofill::PasswordForm>>)passwords;
+    (std::vector<std::unique_ptr<password_manager::PasswordForm>>)passwords;
 
 // Called when the user cancels the export operation.
 - (void)cancelExport;
diff --git a/ios/chrome/browser/ui/settings/password/password_exporter.mm b/ios/chrome/browser/ui/settings/password/password_exporter.mm
index 93d12d33..840d288 100644
--- a/ios/chrome/browser/ui/settings/password/password_exporter.mm
+++ b/ios/chrome/browser/ui/settings/password/password_exporter.mm
@@ -14,8 +14,8 @@
 #include "base/task/thread_pool.h"
 #include "base/task_runner_util.h"
 #include "base/threading/scoped_blocking_call.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/password_manager/core/browser/export/password_csv_writer.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/common/passwords_directory_util_ios.h"
 #include "components/strings/grit/components_strings.h"
@@ -46,7 +46,8 @@
 @implementation PasswordSerializerBridge
 
 - (void)serializePasswords:
-            (std::vector<std::unique_ptr<autofill::PasswordForm>>)passwords
+            (std::vector<std::unique_ptr<password_manager::PasswordForm>>)
+                passwords
                    handler:(void (^)(std::string))serializedPasswordsHandler {
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
@@ -164,7 +165,7 @@
 }
 
 - (void)startExportFlow:
-    (std::vector<std::unique_ptr<autofill::PasswordForm>>)passwords {
+    (std::vector<std::unique_ptr<password_manager::PasswordForm>>)passwords {
   DCHECK(!passwords.empty());
   DCHECK(self.exportState == ExportState::IDLE);
   if ([_weakReauthenticationModule canAttemptReauth]) {
@@ -188,7 +189,7 @@
 }
 
 - (void)serializePasswords:
-    (std::vector<std::unique_ptr<autofill::PasswordForm>>)passwords {
+    (std::vector<std::unique_ptr<password_manager::PasswordForm>>)passwords {
   self.passwordCount = passwords.size();
 
   __weak PasswordExporter* weakSelf = self;
diff --git a/ios/chrome/browser/ui/settings/password/password_exporter_unittest.mm b/ios/chrome/browser/ui/settings/password/password_exporter_unittest.mm
index f57d6c3a..93aa3999 100644
--- a/ios/chrome/browser/ui/settings/password/password_exporter_unittest.mm
+++ b/ios/chrome/browser/ui/settings/password/password_exporter_unittest.mm
@@ -7,7 +7,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/strings/grit/components_strings.h"
 #include "ios/chrome/grit/ios_strings.h"
@@ -35,7 +35,8 @@
 }
 
 - (void)serializePasswords:
-            (std::vector<std::unique_ptr<autofill::PasswordForm>>)passwords
+            (std::vector<std::unique_ptr<password_manager::PasswordForm>>)
+                passwords
                    handler:(void (^)(std::string))serializedPasswordsHandler {
   _serializedPasswordsHandler = serializedPasswordsHandler;
 }
@@ -106,13 +107,14 @@
                               delegate:password_exporter_delegate_];
   }
 
-  std::vector<std::unique_ptr<autofill::PasswordForm>> CreatePasswordList() {
-    auto password_form = std::make_unique<autofill::PasswordForm>();
+  std::vector<std::unique_ptr<password_manager::PasswordForm>>
+  CreatePasswordList() {
+    auto password_form = std::make_unique<password_manager::PasswordForm>();
     password_form->url = GURL("http://accounts.google.com/a/LoginAuth");
     password_form->username_value = base::ASCIIToUTF16("test@testmail.com");
     password_form->password_value = base::ASCIIToUTF16("test1");
 
-    std::vector<std::unique_ptr<autofill::PasswordForm>> password_forms;
+    std::vector<std::unique_ptr<password_manager::PasswordForm>> password_forms;
     password_forms.push_back(std::move(password_form));
     return password_forms;
   }
diff --git a/ios/chrome/browser/ui/settings/password/password_issue_with_form.h b/ios/chrome/browser/ui/settings/password/password_issue_with_form.h
index c659bd4..abf89ff 100644
--- a/ios/chrome/browser/ui/settings/password/password_issue_with_form.h
+++ b/ios/chrome/browser/ui/settings/password/password_issue_with_form.h
@@ -5,19 +5,16 @@
 #ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_ISSUE_WITH_FORM_H_
 #define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_ISSUE_WITH_FORM_H_
 
+#include "components/password_manager/core/browser/password_form_forward.h"
 #import "ios/chrome/browser/ui/settings/password/password_issue.h"
 
-namespace autofill {
-struct PasswordForm;
-}
-
 // Class based on PasswordIssue which adds PasswordForm as a property.
 @interface PasswordIssueWithForm : NSObject <PasswordIssue>
 
 // Password form is used to display Password Details screen.
-@property(nonatomic, readonly) autofill::PasswordForm form;
+@property(nonatomic, readonly) password_manager::PasswordForm form;
 
-- (instancetype)initWithPasswordForm:(autofill::PasswordForm)form
+- (instancetype)initWithPasswordForm:(password_manager::PasswordForm)form
     NS_DESIGNATED_INITIALIZER;
 
 - (instancetype)init NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/ui/settings/password/password_issue_with_form.mm b/ios/chrome/browser/ui/settings/password/password_issue_with_form.mm
index 5ed2514b..6fc4540 100644
--- a/ios/chrome/browser/ui/settings/password/password_issue_with_form.mm
+++ b/ios/chrome/browser/ui/settings/password/password_issue_with_form.mm
@@ -5,7 +5,7 @@
 #import "ios/chrome/browser/ui/settings/password/password_issue_with_form.h"
 
 #include "base/strings/sys_string_conversions.h"
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_ui_utils.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -17,7 +17,7 @@
 @synthesize website = _website;
 @synthesize username = _username;
 
-- (instancetype)initWithPasswordForm:(autofill::PasswordForm)form {
+- (instancetype)initWithPasswordForm:(password_manager::PasswordForm)form {
   self = [super init];
   if (self) {
     _form = form;
diff --git a/ios/chrome/browser/ui/settings/password/password_issues_coordinator.h b/ios/chrome/browser/ui/settings/password/password_issues_coordinator.h
index 28be325..d34df58 100644
--- a/ios/chrome/browser/ui/settings/password/password_issues_coordinator.h
+++ b/ios/chrome/browser/ui/settings/password/password_issues_coordinator.h
@@ -5,6 +5,7 @@
 #ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_ISSUES_COORDINATOR_H_
 #define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_ISSUES_COORDINATOR_H_
 
+#include "components/password_manager/core/browser/password_form_forward.h"
 #import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
 
 @protocol ApplicationCommands;
@@ -13,10 +14,6 @@
 @class PasswordIssuesCoordinator;
 @class ReauthenticationModule;
 
-namespace autofill {
-struct PasswordForm;
-}
-
 // Delegate for PasswordIssuesCoordinator.
 @protocol PasswordIssuesCoordinatorDelegate
 
@@ -26,7 +23,8 @@
 
 // Called when the user deleted password. Returns whether presenter will
 // handle it or not.
-- (BOOL)willHandlePasswordDeletion:(const autofill::PasswordForm&)password;
+- (BOOL)willHandlePasswordDeletion:
+    (const password_manager::PasswordForm&)password;
 
 @end
 
diff --git a/ios/chrome/browser/ui/settings/password/password_issues_coordinator.mm b/ios/chrome/browser/ui/settings/password/password_issues_coordinator.mm
index f78819f5..6a6ebe4 100644
--- a/ios/chrome/browser/ui/settings/password/password_issues_coordinator.mm
+++ b/ios/chrome/browser/ui/settings/password/password_issues_coordinator.mm
@@ -104,7 +104,7 @@
 }
 
 - (void)presentPasswordIssueDetails:(id<PasswordIssue>)password {
-  autofill::PasswordForm form =
+  password_manager::PasswordForm form =
       base::mac::ObjCCastStrict<PasswordIssueWithForm>(password).form;
 
   DCHECK(!self.passwordDetails);
@@ -129,7 +129,8 @@
 }
 
 - (void)passwordDetailsCoordinator:(PasswordDetailsCoordinator*)coordinator
-                    deletePassword:(const autofill::PasswordForm&)password {
+                    deletePassword:
+                        (const password_manager::PasswordForm&)password {
   if (![self.delegate willHandlePasswordDeletion:password]) {
     [self.mediator deletePassword:password];
     [self.baseNavigationController popViewControllerAnimated:YES];
diff --git a/ios/chrome/browser/ui/settings/password/password_issues_mediator.h b/ios/chrome/browser/ui/settings/password/password_issues_mediator.h
index 93df5747..be888bf 100644
--- a/ios/chrome/browser/ui/settings/password/password_issues_mediator.h
+++ b/ios/chrome/browser/ui/settings/password/password_issues_mediator.h
@@ -7,15 +7,12 @@
 
 #import <Foundation/Foundation.h>
 
+#include "components/password_manager/core/browser/password_form_forward.h"
 #import "ios/chrome/common/ui/reauthentication/reauthentication_module.h"
 
 class IOSChromePasswordCheckManager;
 @protocol PasswordIssuesConsumer;
 
-namespace autofill {
-struct PasswordForm;
-}
-
 // This mediator fetches and organises the credentials for its consumer.
 @interface PasswordIssuesMediator : NSObject <SuccessfulReauthTimeAccessor>
 
@@ -27,7 +24,7 @@
 @property(nonatomic, weak) id<PasswordIssuesConsumer> consumer;
 
 // Deletes password from the password store.
-- (void)deletePassword:(const autofill::PasswordForm&)password;
+- (void)deletePassword:(const password_manager::PasswordForm&)password;
 
 @end
 
diff --git a/ios/chrome/browser/ui/settings/password/password_issues_mediator.mm b/ios/chrome/browser/ui/settings/password/password_issues_mediator.mm
index 46d70df..57d4dd1 100644
--- a/ios/chrome/browser/ui/settings/password/password_issues_mediator.mm
+++ b/ios/chrome/browser/ui/settings/password/password_issues_mediator.mm
@@ -49,7 +49,7 @@
   [self fetchPasswordIssues];
 }
 
-- (void)deletePassword:(const autofill::PasswordForm&)password {
+- (void)deletePassword:(const password_manager::PasswordForm&)password {
   for (const auto& credential : _compromisedCredentials) {
     if (std::tie(credential.signon_realm, credential.username,
                  credential.password) == std::tie(password.signon_realm,
@@ -82,7 +82,7 @@
   _compromisedCredentials = _manager->GetCompromisedCredentials();
   NSMutableArray* passwords = [[NSMutableArray alloc] init];
   for (auto credential : _compromisedCredentials) {
-    const autofill::PasswordForm form =
+    const password_manager::PasswordForm form =
         _manager->GetSavedPasswordsFor(credential)[0];
     [passwords
         addObject:[[PasswordIssueWithForm alloc] initWithPasswordForm:form]];
diff --git a/ios/chrome/browser/ui/settings/password/password_issues_mediator_unittest.mm b/ios/chrome/browser/ui/settings/password/password_issues_mediator_unittest.mm
index ea26a65..da0ab5e 100644
--- a/ios/chrome/browser/ui/settings/password/password_issues_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/settings/password/password_issues_mediator_unittest.mm
@@ -36,7 +36,7 @@
 
 constexpr char kPassword[] = "s3cre3t";
 
-using autofill::PasswordForm;
+using password_manager::PasswordForm;
 using password_manager::CompromisedCredentials;
 using password_manager::CompromiseType;
 using password_manager::TestPasswordStore;
diff --git a/ios/chrome/browser/ui/settings/password/password_issues_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/password/password_issues_table_view_controller_unittest.mm
index f045bac8..6a25a54 100644
--- a/ios/chrome/browser/ui/settings/password/password_issues_table_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/password/password_issues_table_view_controller_unittest.mm
@@ -59,7 +59,7 @@
 
   // Adds password issue to the view controller.
   void AddPasswordIssue() {
-    auto form = autofill::PasswordForm();
+    auto form = password_manager::PasswordForm();
     form.url = GURL("http://www.example.com/accounts/LoginAuth");
     form.action = GURL("http://www.example.com/accounts/Login");
     form.username_element = base::ASCIIToUTF16("Email");
@@ -68,7 +68,7 @@
     form.password_value = base::ASCIIToUTF16("test");
     form.submit_element = base::ASCIIToUTF16("signIn");
     form.signon_realm = "http://www.example.com/";
-    form.scheme = autofill::PasswordForm::Scheme::kHtml;
+    form.scheme = password_manager::PasswordForm::Scheme::kHtml;
     NSMutableArray* passwords = [[NSMutableArray alloc] init];
     [passwords
         addObject:[[PasswordIssueWithForm alloc] initWithPasswordForm:form]];
diff --git a/ios/chrome/browser/ui/settings/password/passwords_consumer.h b/ios/chrome/browser/ui/settings/password/passwords_consumer.h
index 2f5f689..141c2c4 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_consumer.h
+++ b/ios/chrome/browser/ui/settings/password/passwords_consumer.h
@@ -10,9 +10,7 @@
 #include <memory>
 #include <vector>
 
-namespace autofill {
-struct PasswordForm;
-}
+#include "components/password_manager/core/browser/password_form_forward.h"
 
 // Enum with all possible UI states of password check.
 typedef NS_ENUM(NSInteger, PasswordCheckUIState) {
@@ -39,7 +37,7 @@
 
 // Displays password and blocked forms.
 - (void)setPasswordsForms:
-    (std::vector<std::unique_ptr<autofill::PasswordForm>>)forms;
+    (std::vector<std::unique_ptr<password_manager::PasswordForm>>)forms;
 
 @end
 
diff --git a/ios/chrome/browser/ui/settings/password/passwords_coordinator.mm b/ios/chrome/browser/ui/settings/password/passwords_coordinator.mm
index a04abc1..37495f5 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_coordinator.mm
+++ b/ios/chrome/browser/ui/settings/password/passwords_coordinator.mm
@@ -151,7 +151,7 @@
   [self.passwordIssuesCoordinator start];
 }
 
-- (void)showDetailedViewForForm:(const autofill::PasswordForm&)form {
+- (void)showDetailedViewForForm:(const password_manager::PasswordForm&)form {
   if (base::FeatureList::IsEnabled(
           password_manager::features::kPasswordCheck)) {
     DCHECK(!self.passwordDetailsCoordinator);
@@ -190,7 +190,8 @@
   self.passwordIssuesCoordinator = nil;
 }
 
-- (BOOL)willHandlePasswordDeletion:(const autofill::PasswordForm&)password {
+- (BOOL)willHandlePasswordDeletion:
+    (const password_manager::PasswordForm&)password {
   [self.passwordsViewController deletePasswordForm:password];
   return YES;
 }
@@ -206,7 +207,8 @@
 }
 
 - (void)passwordDetailsCoordinator:(PasswordDetailsCoordinator*)coordinator
-                    deletePassword:(const autofill::PasswordForm&)password {
+                    deletePassword:
+                        (const password_manager::PasswordForm&)password {
   DCHECK_EQ(self.passwordDetailsCoordinator, coordinator);
   [self.passwordsViewController deletePasswordForm:password];
 }
@@ -215,7 +217,8 @@
 
 - (void)passwordDetailsTableViewController:
             (LegacyPasswordDetailsTableViewController*)controller
-                            deletePassword:(const autofill::PasswordForm&)form {
+                            deletePassword:
+                                (const password_manager::PasswordForm&)form {
   [self.passwordsViewController deletePasswordForm:form];
 }
 
diff --git a/ios/chrome/browser/ui/settings/password/passwords_mediator.mm b/ios/chrome/browser/ui/settings/password/passwords_mediator.mm
index 01d469b..e9e87c4 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_mediator.mm
+++ b/ios/chrome/browser/ui/settings/password/passwords_mediator.mm
@@ -303,7 +303,7 @@
 #pragma mark - SavePasswordsConsumerDelegate
 
 - (void)onGetPasswordStoreResults:
-    (std::vector<std::unique_ptr<autofill::PasswordForm>>)results {
+    (std::vector<std::unique_ptr<password_manager::PasswordForm>>)results {
   DCHECK(self.consumer);
   [self.consumer setPasswordsForms:std::move(results)];
 }
diff --git a/ios/chrome/browser/ui/settings/password/passwords_mediator_unittest.mm b/ios/chrome/browser/ui/settings/password/passwords_mediator_unittest.mm
index d01a9426..d3edffda 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/settings/password/passwords_mediator_unittest.mm
@@ -38,7 +38,7 @@
 
 namespace {
 
-using autofill::PasswordForm;
+using password_manager::PasswordForm;
 using password_manager::CompromisedCredentials;
 using password_manager::CompromiseType;
 using password_manager::TestPasswordStore;
@@ -77,7 +77,7 @@
 }
 
 - (void)setPasswordsForms:
-    (std::vector<std::unique_ptr<autofill::PasswordForm>>)form {
+    (std::vector<std::unique_ptr<password_manager::PasswordForm>>)form {
 }
 
 @end
diff --git a/ios/chrome/browser/ui/settings/password/passwords_settings_app_interface.mm b/ios/chrome/browser/ui/settings/password/passwords_settings_app_interface.mm
index 158f8c4..cc2c873 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_settings_app_interface.mm
+++ b/ios/chrome/browser/ui/settings/password/passwords_settings_app_interface.mm
@@ -9,8 +9,8 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #import "base/test/ios/wait_util.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/keyed_service/core/service_access_type.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/password_manager/core/browser/password_store_consumer.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
@@ -26,7 +26,7 @@
 #error "This file requires ARC support."
 #endif
 
-using autofill::PasswordForm;
+using password_manager::PasswordForm;
 using chrome_test_util::SetUpAndReturnMockReauthenticationModule;
 using chrome_test_util::SetUpAndReturnMockReauthenticationModuleForExport;
 
@@ -49,7 +49,8 @@
 class FakeStoreConsumer : public password_manager::PasswordStoreConsumer {
  public:
   void OnGetPasswordStoreResults(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> obtained) override {
+      std::vector<std::unique_ptr<password_manager::PasswordForm>> obtained)
+      override {
     obtained_ = std::move(obtained);
   }
 
@@ -66,7 +67,7 @@
     return responded;
   }
 
-  const std::vector<autofill::PasswordForm>& GetStoreResults() {
+  const std::vector<password_manager::PasswordForm>& GetStoreResults() {
     return results_;
   }
 
@@ -89,10 +90,10 @@
   }
 
   // Temporary cache of obtained store results.
-  std::vector<std::unique_ptr<autofill::PasswordForm>> obtained_;
+  std::vector<std::unique_ptr<password_manager::PasswordForm>> obtained_;
 
   // Combination of fillable and blacklisted credentials from the store.
-  std::vector<autofill::PasswordForm> results_;
+  std::vector<password_manager::PasswordForm> results_;
 };
 
 // Saves |form| to the password store and waits until the async processing is
@@ -100,8 +101,8 @@
 bool SaveToPasswordStore(const PasswordForm& form) {
   GetPasswordStore()->AddLogin(form);
   // When we retrieve the form from the store, |in_store| should be set.
-  autofill::PasswordForm expected_form = form;
-  expected_form.in_store = autofill::PasswordForm::Store::kProfileStore;
+  password_manager::PasswordForm expected_form = form;
+  expected_form.in_store = password_manager::PasswordForm::Store::kProfileStore;
   // Check the result and ensure PasswordStore processed this.
   FakeStoreConsumer consumer;
   if (!consumer.FetchStoreResults()) {
diff --git a/ios/chrome/browser/ui/settings/password/passwords_settings_commands.h b/ios/chrome/browser/ui/settings/password/passwords_settings_commands.h
index 02caa73..028dbb62 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_settings_commands.h
+++ b/ios/chrome/browser/ui/settings/password/passwords_settings_commands.h
@@ -14,7 +14,7 @@
 - (void)showCompromisedPasswords;
 
 // Shows passwords details.
-- (void)showDetailedViewForForm:(const autofill::PasswordForm&)form;
+- (void)showDetailedViewForForm:(const password_manager::PasswordForm&)form;
 
 @end
 
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h
index 7a98ab71..2c396f4 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h
+++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h
@@ -27,7 +27,7 @@
 - (instancetype)initWithStyle:(UITableViewStyle)style NS_UNAVAILABLE;
 
 // Deletes passed password form and updates list accordingly.
-- (void)deletePasswordForm:(const autofill::PasswordForm&)form;
+- (void)deletePasswordForm:(const password_manager::PasswordForm&)form;
 
 @property(nonatomic, weak) id<PasswordsSettingsCommands> handler;
 
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
index a0cc19b..1fb7c38 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
@@ -11,9 +11,9 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/user_metrics.h"
 #include "base/strings/sys_string_conversions.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/google/core/common/google_util.h"
 #include "components/keyed_service/core/service_access_type.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_list_sorter.h"
 #include "components/password_manager/core/browser/password_manager_constants.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
@@ -95,12 +95,14 @@
   ItemTypeExportPasswordsButton,
 };
 
-std::vector<std::unique_ptr<autofill::PasswordForm>> CopyOf(
-    const std::vector<std::unique_ptr<autofill::PasswordForm>>& password_list) {
-  std::vector<std::unique_ptr<autofill::PasswordForm>> password_list_copy;
+std::vector<std::unique_ptr<password_manager::PasswordForm>> CopyOf(
+    const std::vector<std::unique_ptr<password_manager::PasswordForm>>&
+        password_list) {
+  std::vector<std::unique_ptr<password_manager::PasswordForm>>
+      password_list_copy;
   for (const auto& form : password_list) {
     password_list_copy.push_back(
-        std::make_unique<autofill::PasswordForm>(*form));
+        std::make_unique<password_manager::PasswordForm>(*form));
   }
   return password_list_copy;
 }
@@ -108,7 +110,7 @@
 }  // namespace
 
 @interface PasswordFormContentItem : TableViewDetailTextItem
-@property(nonatomic) autofill::PasswordForm* form;
+@property(nonatomic) password_manager::PasswordForm* form;
 @end
 @implementation PasswordFormContentItem
 @end
@@ -189,9 +191,9 @@
   // The interface for getting and manipulating a user's saved passwords.
   scoped_refptr<password_manager::PasswordStore> _passwordStore;
   // The list of the user's saved passwords.
-  std::vector<std::unique_ptr<autofill::PasswordForm>> _savedForms;
+  std::vector<std::unique_ptr<password_manager::PasswordForm>> _savedForms;
   // The list of the user's blocked sites.
-  std::vector<std::unique_ptr<autofill::PasswordForm>> _blockedForms;
+  std::vector<std::unique_ptr<password_manager::PasswordForm>> _blockedForms;
   // Map containing duplicates of saved passwords.
   password_manager::DuplicatesMap _savedPasswordDuplicates;
   // Map containing duplicates of blocked passwords.
@@ -584,7 +586,8 @@
 
 - (SavedFormContentItem*)savedFormItemWithText:(NSString*)text
                                  andDetailText:(NSString*)detailText
-                                       forForm:(autofill::PasswordForm*)form {
+                                       forForm:(password_manager::PasswordForm*)
+                                                   form {
   SavedFormContentItem* passwordItem =
       [[SavedFormContentItem alloc] initWithType:ItemTypeSavedPassword];
   passwordItem.text = text;
@@ -595,9 +598,9 @@
   return passwordItem;
 }
 
-- (BlockedFormContentItem*)blockedFormItemWithText:(NSString*)text
-                                           forForm:
-                                               (autofill::PasswordForm*)form {
+- (BlockedFormContentItem*)
+    blockedFormItemWithText:(NSString*)text
+                    forForm:(password_manager::PasswordForm*)form {
   BlockedFormContentItem* passwordItem =
       [[BlockedFormContentItem alloc] initWithType:ItemTypeBlocked];
   passwordItem.text = text;
@@ -720,7 +723,7 @@
 }
 
 - (void)setPasswordsForms:
-    (std::vector<std::unique_ptr<autofill::PasswordForm>>)results {
+    (std::vector<std::unique_ptr<password_manager::PasswordForm>>)results {
   if (base::FeatureList::IsEnabled(
           password_manager::features::kPasswordCheck)) {
     _blockedForms.clear();
@@ -1256,18 +1259,20 @@
     auto& duplicates =
         blocked ? _blockedPasswordDuplicates : _savedPasswordDuplicates;
 
-    const autofill::PasswordForm& deletedForm = *item.form;
+    const password_manager::PasswordForm& deletedForm = *item.form;
     auto begin = blocked ? blockedIterator : passwordIterator;
     auto end = blocked ? blockedEndIterator : passwordEndIterator;
 
     auto formIterator = std::find_if(
         begin, end,
-        [&deletedForm](const std::unique_ptr<autofill::PasswordForm>& value) {
+        [&deletedForm](
+            const std::unique_ptr<password_manager::PasswordForm>& value) {
           return *value == deletedForm;
         });
     DCHECK(formIterator != end);
 
-    std::unique_ptr<autofill::PasswordForm> form = std::move(*formIterator);
+    std::unique_ptr<password_manager::PasswordForm> form =
+        std::move(*formIterator);
     std::string key = password_manager::CreateSortKey(*form);
     auto duplicatesRange = duplicates.equal_range(key);
     for (auto iterator = duplicatesRange.first;
@@ -1635,14 +1640,14 @@
 }
 
 // Deletes passed password form and updates list accordingly.
-- (void)deletePasswordForm:(const autofill::PasswordForm&)form {
+- (void)deletePasswordForm:(const password_manager::PasswordForm&)form {
   _passwordStore->RemoveLogin(form);
 
-  std::vector<std::unique_ptr<autofill::PasswordForm>>& forms =
+  std::vector<std::unique_ptr<password_manager::PasswordForm>>& forms =
       form.blocked_by_user ? _blockedForms : _savedForms;
   auto iterator = std::find_if(
       forms.begin(), forms.end(),
-      [&form](const std::unique_ptr<autofill::PasswordForm>& value) {
+      [&form](const std::unique_ptr<password_manager::PasswordForm>& value) {
         return *value == form;
       });
   DCHECK(iterator != forms.end());
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm
index c703455..1ef1032 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm
@@ -12,9 +12,9 @@
 #include "base/test/bind_test_util.h"
 #import "base/test/ios/wait_util.h"
 #include "base/test/scoped_feature_list.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/keyed_service/core/service_access_type.h"
 #include "components/password_manager/core/browser/mock_bulk_leak_check_service.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
 #include "components/password_manager/core/browser/test_password_store.h"
 #include "components/password_manager/core/common/password_manager_features.h"
@@ -172,7 +172,7 @@
   }
 
   // Adds a form to PasswordsTableViewController.
-  void AddPasswordForm(std::unique_ptr<autofill::PasswordForm> form) {
+  void AddPasswordForm(std::unique_ptr<password_manager::PasswordForm> form) {
     if (GetParam().password_check_enabled) {
       GetTestStore().AddLogin(*form);
       RunUntilIdle();
@@ -180,7 +180,7 @@
       PasswordsTableViewController* passwords_controller =
           static_cast<PasswordsTableViewController*>(controller());
       GetTestStore().AddLogin(*form);
-      std::vector<std::unique_ptr<autofill::PasswordForm>> passwords;
+      std::vector<std::unique_ptr<password_manager::PasswordForm>> passwords;
       passwords.push_back(std::move(form));
       [passwords_controller setPasswordsForms:std::move(passwords)];
     }
@@ -188,7 +188,7 @@
 
   // Creates and adds a saved password form.
   void AddSavedForm1() {
-    auto form = std::make_unique<autofill::PasswordForm>();
+    auto form = std::make_unique<password_manager::PasswordForm>();
     form->url = GURL("http://www.example.com/accounts/LoginAuth");
     form->action = GURL("http://www.example.com/accounts/Login");
     form->username_element = base::ASCIIToUTF16("Email");
@@ -197,14 +197,14 @@
     form->password_value = base::ASCIIToUTF16("test");
     form->submit_element = base::ASCIIToUTF16("signIn");
     form->signon_realm = "http://www.example.com/";
-    form->scheme = autofill::PasswordForm::Scheme::kHtml;
+    form->scheme = password_manager::PasswordForm::Scheme::kHtml;
     form->blocked_by_user = false;
     AddPasswordForm(std::move(form));
   }
 
   // Creates and adds a saved password form.
   void AddSavedForm2() {
-    auto form = std::make_unique<autofill::PasswordForm>();
+    auto form = std::make_unique<password_manager::PasswordForm>();
     form->url = GURL("http://www.example2.com/accounts/LoginAuth");
     form->action = GURL("http://www.example2.com/accounts/Login");
     form->username_element = base::ASCIIToUTF16("Email");
@@ -213,7 +213,7 @@
     form->password_value = base::ASCIIToUTF16("test");
     form->submit_element = base::ASCIIToUTF16("signIn");
     form->signon_realm = "http://www.example2.com/";
-    form->scheme = autofill::PasswordForm::Scheme::kHtml;
+    form->scheme = password_manager::PasswordForm::Scheme::kHtml;
     form->blocked_by_user = false;
     AddPasswordForm(std::move(form));
   }
@@ -221,7 +221,7 @@
   // Creates and adds a blocked site form to never offer to save
   // user's password to those sites.
   void AddBlockedForm1() {
-    auto form = std::make_unique<autofill::PasswordForm>();
+    auto form = std::make_unique<password_manager::PasswordForm>();
     form->url = GURL("http://www.secret.com/login");
     form->action = GURL("http://www.secret.com/action");
     form->username_element = base::ASCIIToUTF16("email");
@@ -230,7 +230,7 @@
     form->password_value = base::ASCIIToUTF16("cantsay");
     form->submit_element = base::ASCIIToUTF16("signIn");
     form->signon_realm = "http://www.secret.com/";
-    form->scheme = autofill::PasswordForm::Scheme::kHtml;
+    form->scheme = password_manager::PasswordForm::Scheme::kHtml;
     form->blocked_by_user = true;
     AddPasswordForm(std::move(form));
   }
@@ -238,7 +238,7 @@
   // Creates and adds another blocked site form to never offer to save
   // user's password to those sites.
   void AddBlockedForm2() {
-    auto form = std::make_unique<autofill::PasswordForm>();
+    auto form = std::make_unique<password_manager::PasswordForm>();
     form->url = GURL("http://www.secret2.com/login");
     form->action = GURL("http://www.secret2.com/action");
     form->username_element = base::ASCIIToUTF16("email");
@@ -247,7 +247,7 @@
     form->password_value = base::ASCIIToUTF16("cantsay");
     form->submit_element = base::ASCIIToUTF16("signIn");
     form->signon_realm = "http://www.secret2.com/";
-    form->scheme = autofill::PasswordForm::Scheme::kHtml;
+    form->scheme = password_manager::PasswordForm::Scheme::kHtml;
     form->blocked_by_user = true;
     AddPasswordForm(std::move(form));
   }
diff --git a/ios/chrome/browser/ui/settings/safety_check/safety_check_coordinator.mm b/ios/chrome/browser/ui/settings/safety_check/safety_check_coordinator.mm
index 061b7f6..c863c81ac 100644
--- a/ios/chrome/browser/ui/settings/safety_check/safety_check_coordinator.mm
+++ b/ios/chrome/browser/ui/settings/safety_check/safety_check_coordinator.mm
@@ -248,7 +248,8 @@
   self.passwordIssuesCoordinator = nil;
 }
 
-- (BOOL)willHandlePasswordDeletion:(const autofill::PasswordForm&)password {
+- (BOOL)willHandlePasswordDeletion:
+    (const password_manager::PasswordForm&)password {
   return NO;
 }
 
diff --git a/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator_unittest.mm b/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator_unittest.mm
index 1e00f8df..f83cec3 100644
--- a/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator_unittest.mm
@@ -179,7 +179,7 @@
 
   void RunUntilIdle() { environment_.RunUntilIdle(); }
 
-  void AddPasswordForm(std::unique_ptr<autofill::PasswordForm> form) {
+  void AddPasswordForm(std::unique_ptr<password_manager::PasswordForm> form) {
     GetTestStore().AddLogin(*form);
     RunUntilIdle();
   }
@@ -194,7 +194,7 @@
 
   // Creates and adds a saved password form.
   void AddSavedForm() {
-    auto form = std::make_unique<autofill::PasswordForm>();
+    auto form = std::make_unique<password_manager::PasswordForm>();
     form->url = GURL("http://www.example.com/accounts/LoginAuth");
     form->action = GURL("http://www.example.com/accounts/Login");
     form->username_element = base::ASCIIToUTF16("Email");
@@ -203,7 +203,7 @@
     form->password_value = base::ASCIIToUTF16("test");
     form->submit_element = base::ASCIIToUTF16("signIn");
     form->signon_realm = "http://www.example.com/";
-    form->scheme = autofill::PasswordForm::Scheme::kHtml;
+    form->scheme = password_manager::PasswordForm::Scheme::kHtml;
     form->blocked_by_user = false;
     AddPasswordForm(std::move(form));
   }
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm
index 9fe7b69..558af38 100644
--- a/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm
+++ b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm
@@ -95,6 +95,12 @@
     _snapshotView = snapshotView;
     _closeTapTargetButton = closeTapTargetButton;
 
+    self.layer.shadowColor = [UIColor blackColor].CGColor;
+    self.layer.shadowOffset = CGSizeMake(0, 0);
+    self.layer.shadowRadius = 4.0f;
+    self.layer.shadowOpacity = 0.5f;
+    self.layer.masksToBounds = NO;
+
     NSArray* constraints = @[
       [topBar.topAnchor constraintEqualToAnchor:contentView.topAnchor],
       [topBar.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor],
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm
index 55de58f..a95205b 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm
@@ -4,8 +4,10 @@
 
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.h"
 
+#import "ios/chrome/browser/ui/tab_grid/grid/grid_constants.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_constants.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_new_tab_button.h"
+#import "ios/chrome/browser/ui/thumb_strip/thumb_strip_feature.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -147,11 +149,15 @@
   _largeNewTabButton.translatesAutoresizingMaskIntoConstraints = NO;
   _largeNewTabButton.page = self.page;
 
+  CGFloat floatingButtonVerticalInset = kTabGridFloatingButtonVerticalInset;
+  if (IsThumbStripEnabled())
+    floatingButtonVerticalInset += kBVCHeightTabGrid;
+
   _floatingConstraints = @[
     [_largeNewTabButton.topAnchor constraintEqualToAnchor:self.topAnchor],
     [_largeNewTabButton.bottomAnchor
         constraintEqualToAnchor:self.safeAreaLayoutGuide.bottomAnchor
-                       constant:-kTabGridFloatingButtonVerticalInset],
+                       constant:-floatingButtonVerticalInset],
     [_largeNewTabButton.trailingAnchor
         constraintEqualToAnchor:self.trailingAnchor
                        constant:-kTabGridFloatingButtonHorizontalInset],
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
index a6b02c3..e5f4e4e 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -467,6 +467,7 @@
           0, [self hiddenTopToolbarYTranslation]);
       [self gridViewControllerForPage:self.currentPage].gridView.transform =
           CGAffineTransformMakeTranslation(0, kThumbStripSlideInHeight);
+      self.topToolbar.alpha = 0;
       break;
     case ViewRevealState::Peeked:
       self.foregroundView.alpha = 0;
@@ -474,6 +475,7 @@
           0, [self hiddenTopToolbarYTranslation]);
       [self gridViewControllerForPage:self.currentPage].gridView.transform =
           CGAffineTransformIdentity;
+      self.topToolbar.alpha = 0;
       break;
     case ViewRevealState::Revealed:
       self.foregroundView.alpha = 0;
@@ -482,6 +484,7 @@
           CGAffineTransformMakeTranslation(
               0, self.topToolbar.intrinsicContentSize.height);
       [self contentWillAppearAnimated:YES];
+      self.topToolbar.alpha = 1;
       break;
   }
 }
diff --git a/ios/chrome/browser/ui/toolbar/README.md b/ios/chrome/browser/ui/toolbar/README.md
deleted file mode 100644
index 0796d08..0000000
--- a/ios/chrome/browser/ui/toolbar/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Toolbar
-
------
-**Some of the files in this directory are only used in the new iOS Chrome
-architecture:**
-
-* `toolbar_coordinator.h` and `.mm`
-* `toolbar_view_controller.h` and `.mm`
-
------
diff --git a/ios/chrome/browser/ui/ui_feature_flags.cc b/ios/chrome/browser/ui/ui_feature_flags.cc
index 776ab11..87c45a6d 100644
--- a/ios/chrome/browser/ui/ui_feature_flags.cc
+++ b/ios/chrome/browser/ui/ui_feature_flags.cc
@@ -76,3 +76,12 @@
 
 const base::Feature kIncognitoAuthentication{
     "enable-incognito-authentication-ios", base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kLocationRemoveFirstRunPrompt{
+    "LocationRemoveFirstRunPrompt", base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kLocationStringChange{"LocationStringChange",
+                                          base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kLocationFirstRunModal{"LocationFirstRunModal",
+                                           base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ios/chrome/browser/ui/ui_feature_flags.h b/ios/chrome/browser/ui/ui_feature_flags.h
index 125efcc..0f0f68c 100644
--- a/ios/chrome/browser/ui/ui_feature_flags.h
+++ b/ios/chrome/browser/ui/ui_feature_flags.h
@@ -84,4 +84,14 @@
 // Adds a setting to enable biometric authentication for incognito tabs.
 extern const base::Feature kIncognitoAuthentication;
 
+// Feature flag that removes the location permissions prompt from First Run.
+extern const base::Feature kLocationRemoveFirstRunPrompt;
+
+// Feature flag that changes the string in the location permissions prompt.
+extern const base::Feature kLocationStringChange;
+
+// Feature flag that adds a modal in First Run that details Chrome location data
+// usage.
+extern const base::Feature kLocationFirstRunModal;
+
 #endif  // IOS_CHROME_BROWSER_UI_UI_FEATURE_FLAGS_H_
diff --git a/ios/chrome/browser/ui/util/pasteboard_util.mm b/ios/chrome/browser/ui/util/pasteboard_util.mm
index 38b61ea..a87726d5 100644
--- a/ios/chrome/browser/ui/util/pasteboard_util.mm
+++ b/ios/chrome/browser/ui/util/pasteboard_util.mm
@@ -37,18 +37,22 @@
     return;
   }
 
-  NSData* plainText = [text dataUsingEncoding:NSUTF8StringEncoding];
-  NSDictionary* copiedText = @{
-    (NSString*)kUTTypeText : text,
-    (NSString*)kUTTypeUTF8PlainText : plainText,
-  };
+  NSData* plainText = [base::SysUTF8ToNSString(URL.spec())
+      dataUsingEncoding:NSUTF8StringEncoding];
   NSDictionary* copiedURL = @{
     (NSString*)kUTTypeURL : net::NSURLWithGURL(URL),
+    (NSString*)kUTTypeUTF8PlainText : plainText,
   };
 
-  [[UIPasteboard generalPasteboard] setItems:@[ copiedText, copiedURL ]];
+  NSDictionary* copiedText = @{
+    (NSString*)kUTTypeText : text,
+    (NSString*)
+    kUTTypeUTF8PlainText : [text dataUsingEncoding:NSUTF8StringEncoding],
+  };
+
+  UIPasteboard.generalPasteboard.items = @[ copiedURL, copiedText ];
 }
 
 void ClearPasteboard() {
-  [UIPasteboard generalPasteboard].items = @[];
+  UIPasteboard.generalPasteboard.items = @[];
 }
diff --git a/ios/chrome/browser/ui/util/pasteboard_util_unittest.mm b/ios/chrome/browser/ui/util/pasteboard_util_unittest.mm
index 7cc9c19d..a1f9198 100644
--- a/ios/chrome/browser/ui/util/pasteboard_util_unittest.mm
+++ b/ios/chrome/browser/ui/util/pasteboard_util_unittest.mm
@@ -4,6 +4,8 @@
 
 #import "ios/chrome/browser/ui/util/pasteboard_util.h"
 
+#import <MobileCoreServices/MobileCoreServices.h>
+
 #import "base/strings/sys_string_conversions.h"
 #import "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
@@ -32,23 +34,44 @@
 // general pasteboard.
 TEST_F(PasteboardUtilTest, StoreInPasteboardWorks) {
   NSString* test_text = base::SysUTF8ToNSString(kTestText);
+  NSData* text_as_data = [test_text dataUsingEncoding:NSUTF8StringEncoding];
   GURL test_url(kTestURL);
-  NSURL* test_ns_url = [NSURL URLWithString:base::SysUTF8ToNSString(kTestURL)];
+  NSString* url_as_string = base::SysUTF8ToNSString(kTestURL);
+  NSData* url_as_data = [url_as_string dataUsingEncoding:NSUTF8StringEncoding];
+  NSURL* test_ns_url = [NSURL URLWithString:url_as_string];
 
   StoreInPasteboard(test_text, test_url);
 
-  // Additional text is stored as the first pasteboard item.
-  ASSERT_TRUE([UIPasteboard generalPasteboard].hasStrings);
-  EXPECT_TRUE(
-      [test_text isEqualToString:UIPasteboard.generalPasteboard.string]);
+  ASSERT_TRUE(UIPasteboard.generalPasteboard.hasStrings);
+  ASSERT_TRUE(UIPasteboard.generalPasteboard.hasURLs);
 
-  // URL is stored as the second pasteboard item, but can be accessed as the
-  // first (and only) URL item.
-  ASSERT_TRUE([UIPasteboard generalPasteboard].hasURLs);
-  EXPECT_TRUE([test_ns_url isEqual:UIPasteboard.generalPasteboard.URLs[0]]);
+  NSString* plainTextType = (NSString*)kUTTypeUTF8PlainText;
+
+  // URL is stored as the first pasteboard item as both URL and plain text; the
+  // latter being required on iOS 12 to be pasted in text boxes in other apps.
+  NSIndexSet* firstIndex = [NSIndexSet indexSetWithIndex:0];
+  EXPECT_TRUE(
+      [test_ns_url isEqual:[UIPasteboard.generalPasteboard
+                               valuesForPasteboardType:(NSString*)kUTTypeURL
+                                             inItemSet:firstIndex][0]]);
+  EXPECT_TRUE(
+      [url_as_data isEqualToData:[UIPasteboard.generalPasteboard
+                                     dataForPasteboardType:plainTextType
+                                                 inItemSet:firstIndex][0]]);
+
+  // The additional text is stored as the second item.
+  NSIndexSet* secondIndex = [NSIndexSet indexSetWithIndex:1];
+  EXPECT_TRUE(
+      [text_as_data isEqualToData:[UIPasteboard.generalPasteboard
+                                      dataForPasteboardType:plainTextType
+                                                  inItemSet:secondIndex][0]]);
+  EXPECT_TRUE([test_text
+      isEqualToString:[UIPasteboard.generalPasteboard
+                          valuesForPasteboardType:(NSString*)kUTTypeText
+                                        inItemSet:secondIndex][0]]);
 }
 
-// Tests that the minimum line height attribute is reflected in GetLineHeight().
+// Tests that clearing the pasteboard does remove pasteboard items.
 TEST_F(PasteboardUtilTest, ClearPasteboardWorks) {
   // Get something stored in the pasteboard.
   NSString* test_text = base::SysUTF8ToNSString(kTestText);
@@ -57,8 +80,8 @@
 
   // Clear and assert.
   ClearPasteboard();
-  EXPECT_FALSE([UIPasteboard generalPasteboard].hasURLs);
-  EXPECT_FALSE([UIPasteboard generalPasteboard].hasStrings);
+  EXPECT_FALSE(UIPasteboard.generalPasteboard.hasURLs);
+  EXPECT_FALSE(UIPasteboard.generalPasteboard.hasStrings);
 }
 
 }  // namespace
diff --git a/ios/chrome/browser/web/README.md b/ios/chrome/browser/web/README.md
deleted file mode 100644
index ff7c631..0000000
--- a/ios/chrome/browser/web/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Web
-
------
-**Some of the files in this directory are only used in the new iOS Chrome
-architecture:**
-
-* `web_mediator.h`
-* `web_mediator.mm`
-* `web_mediator+internal.h`
-
------
diff --git a/ios/public/provider/chrome/browser/user_feedback/BUILD.gn b/ios/public/provider/chrome/browser/user_feedback/BUILD.gn
index 60b685f..558a3a0 100644
--- a/ios/public/provider/chrome/browser/user_feedback/BUILD.gn
+++ b/ios/public/provider/chrome/browser/user_feedback/BUILD.gn
@@ -7,6 +7,7 @@
   sources = [
     "user_feedback_provider.h",
     "user_feedback_provider.mm",
+    "user_feedback_sender.h",
   ]
   deps = [ "//base" ]
 }
diff --git a/ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h b/ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h
index 4aef79b..2f45130 100644
--- a/ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h
+++ b/ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h
@@ -8,6 +8,7 @@
 #import <UIKit/UIKit.h>
 
 #include "base/macros.h"
+#include "ios/public/provider/chrome/browser/user_feedback/user_feedback_sender.h"
 
 @protocol ApplicationCommands;
 
@@ -60,6 +61,13 @@
   // parameters.
   virtual UIViewController* CreateViewController(
       id<UserFeedbackDataSource> data_source,
+      id<ApplicationCommands> handler,
+      UserFeedbackSender sender);
+  // TODO(crbug.com/1138523): Remove the method below, once
+  // CreateViewController(id<UserFeedbackDataSource>,
+  // id<ApplicationCommands>, CategoryTag) is implemented downstream.
+  virtual UIViewController* CreateViewController(
+      id<UserFeedbackDataSource> data_source,
       id<ApplicationCommands> handler);
   // Uploads collected feedback reports.
   virtual void Synchronize();
diff --git a/ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.mm b/ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.mm
index 19c3a100..c4fb05f 100644
--- a/ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.mm
+++ b/ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.mm
@@ -18,8 +18,16 @@
 
 UIViewController* UserFeedbackProvider::CreateViewController(
     id<UserFeedbackDataSource> data_source,
-    id<ApplicationCommands> handler) {
+    id<ApplicationCommands> handler,
+    UserFeedbackSender sender) {
   return nil;
 }
 
+UIViewController* UserFeedbackProvider::CreateViewController(
+    id<UserFeedbackDataSource> data_source,
+    id<ApplicationCommands> handler) {
+  return CreateViewController(data_source, handler,
+                              UserFeedbackSender::ToolsMenu);
+}
+
 void UserFeedbackProvider::Synchronize() {}
diff --git a/ios/public/provider/chrome/browser/user_feedback/user_feedback_sender.h b/ios/public/provider/chrome/browser/user_feedback/user_feedback_sender.h
new file mode 100644
index 0000000..74637da1bd
--- /dev/null
+++ b/ios/public/provider/chrome/browser/user_feedback/user_feedback_sender.h
@@ -0,0 +1,18 @@
+// 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 IOS_PUBLIC_PROVIDER_CHROME_BROWSER_USER_FEEDBACK_USER_FEEDBACK_SENDER_H_
+#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_USER_FEEDBACK_USER_FEEDBACK_SENDER_H_
+
+// Indicates where is this feedback coming from.
+enum class UserFeedbackSender {
+  // Set from tools overflow menu.
+  ToolsMenu = 0,
+  // Sent from a Sad Tab.
+  SadTab,
+  // Sent from Discover Feed.
+  Feed,
+};
+
+#endif  // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_USER_FEEDBACK_USER_FEEDBACK_SENDER_H_
diff --git a/ios/web_view/internal/autofill/cwv_autofill_controller.mm b/ios/web_view/internal/autofill/cwv_autofill_controller.mm
index cd6a4f0..6590b45 100644
--- a/ios/web_view/internal/autofill/cwv_autofill_controller.mm
+++ b/ios/web_view/internal/autofill/cwv_autofill_controller.mm
@@ -594,7 +594,8 @@
   __block std::unique_ptr<password_manager::PasswordFormManagerForUI> formPtr(
       std::move(formToSave));
 
-  const autofill::PasswordForm& credentials = formPtr->GetPendingCredentials();
+  const password_manager::PasswordForm& credentials =
+      formPtr->GetPendingCredentials();
   CWVPassword* password =
       [[CWVPassword alloc] initWithPasswordForm:credentials];
 
@@ -628,7 +629,8 @@
   __block std::unique_ptr<password_manager::PasswordFormManagerForUI> formPtr(
       std::move(formToUpdate));
 
-  const autofill::PasswordForm& credentials = formPtr->GetPendingCredentials();
+  const password_manager::PasswordForm& credentials =
+      formPtr->GetPendingCredentials();
   CWVPassword* password =
       [[CWVPassword alloc] initWithPasswordForm:credentials];
 
diff --git a/ios/web_view/internal/autofill/cwv_autofill_data_manager.mm b/ios/web_view/internal/autofill/cwv_autofill_data_manager.mm
index 458df42..3b5700e5 100644
--- a/ios/web_view/internal/autofill/cwv_autofill_data_manager.mm
+++ b/ios/web_view/internal/autofill/cwv_autofill_data_manager.mm
@@ -80,7 +80,8 @@
   explicit WebViewPasswordStoreConsumer(CWVAutofillDataManager* data_manager)
       : data_manager_(data_manager) {}
   void OnGetPasswordStoreResults(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> results) override {
+      std::vector<std::unique_ptr<password_manager::PasswordForm>> results)
+      override {
     NSMutableArray<CWVPassword*>* passwords = [NSMutableArray array];
     for (auto& form : results) {
       CWVPassword* password = [[CWVPassword alloc] initWithPasswordForm:*form];
diff --git a/ios/web_view/internal/autofill/cwv_autofill_data_manager_unittest.mm b/ios/web_view/internal/autofill/cwv_autofill_data_manager_unittest.mm
index 4340a72..d0e9c5e 100644
--- a/ios/web_view/internal/autofill/cwv_autofill_data_manager_unittest.mm
+++ b/ios/web_view/internal/autofill/cwv_autofill_data_manager_unittest.mm
@@ -14,7 +14,7 @@
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/test_password_store.h"
 #include "ios/web/public/test/web_task_environment.h"
 #import "ios/web_view/internal/autofill/cwv_autofill_profile_internal.h"
@@ -98,8 +98,8 @@
   }
 
   // Create a test password form for testing.
-  autofill::PasswordForm GetTestPassword() {
-    autofill::PasswordForm password_form;
+  password_manager::PasswordForm GetTestPassword() {
+    password_manager::PasswordForm password_form;
     password_form.url = GURL("http://www.example.com/accounts/LoginAuth");
     password_form.action = GURL("http://www.example.com/accounts/Login");
     password_form.username_element = base::SysNSStringToUTF16(@"Email");
@@ -108,7 +108,7 @@
     password_form.password_value = base::SysNSStringToUTF16(@"test");
     password_form.submit_element = base::SysNSStringToUTF16(@"signIn");
     password_form.signon_realm = "http://www.example.com/";
-    password_form.scheme = autofill::PasswordForm::Scheme::kHtml;
+    password_form.scheme = password_manager::PasswordForm::Scheme::kHtml;
     password_form.blocked_by_user = false;
     return password_form;
   }
@@ -214,7 +214,7 @@
 
 // Tests CWVAutofillDataManager properly returns passwords.
 TEST_F(CWVAutofillDataManagerTest, ReturnPassword) {
-  autofill::PasswordForm test_password = GetTestPassword();
+  password_manager::PasswordForm test_password = GetTestPassword();
   password_store_->AddLogin(test_password);
   NSArray<CWVPassword*>* fetched_passwords = FetchPasswords();
   EXPECT_EQ(1ul, fetched_passwords.count);
diff --git a/ios/web_view/internal/passwords/cwv_password.mm b/ios/web_view/internal/passwords/cwv_password.mm
index 57a0d39..1fa19b2 100644
--- a/ios/web_view/internal/passwords/cwv_password.mm
+++ b/ios/web_view/internal/passwords/cwv_password.mm
@@ -7,7 +7,7 @@
 #import <objc/runtime.h>
 
 #include "base/strings/sys_string_conversions.h"
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_ui_utils.h"
 #import "ios/web_view/internal/utils/nsobject_description_utils.h"
 
@@ -16,11 +16,11 @@
 #endif
 
 @implementation CWVPassword {
-  autofill::PasswordForm _passwordForm;
+  password_manager::PasswordForm _passwordForm;
 }
 
 - (instancetype)initWithPasswordForm:
-    (const autofill::PasswordForm&)passwordForm {
+    (const password_manager::PasswordForm&)passwordForm {
   self = [super init];
   if (self) {
     _passwordForm = passwordForm;
@@ -62,7 +62,7 @@
 
 #pragma mark - Internal
 
-- (autofill::PasswordForm*)internalPasswordForm {
+- (password_manager::PasswordForm*)internalPasswordForm {
   return &_passwordForm;
 }
 
diff --git a/ios/web_view/internal/passwords/cwv_password_internal.h b/ios/web_view/internal/passwords/cwv_password_internal.h
index e2f4b416..74b21bc 100644
--- a/ios/web_view/internal/passwords/cwv_password_internal.h
+++ b/ios/web_view/internal/passwords/cwv_password_internal.h
@@ -5,18 +5,19 @@
 #ifndef IOS_WEB_VIEW_INTERNAL_PASSWORDS_CWV_PASSWORD_INTERNAL_H_
 #define IOS_WEB_VIEW_INTERNAL_PASSWORDS_CWV_PASSWORD_INTERNAL_H_
 
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 #import "ios/web_view/public/cwv_password.h"
 
 @interface CWVPassword ()
 
-- (instancetype)initWithPasswordForm:(const autofill::PasswordForm&)passwordForm
+- (instancetype)initWithPasswordForm:
+    (const password_manager::PasswordForm&)passwordForm
     NS_DESIGNATED_INITIALIZER;
 
 // The internal autofill credit card that is wrapped by this object.
 // Intentionally not declared as a property to avoid issues when read by
 // -[NSObject valueForKey:].
-- (autofill::PasswordForm*)internalPasswordForm;
+- (password_manager::PasswordForm*)internalPasswordForm;
 
 @end
 
diff --git a/ios/web_view/internal/passwords/cwv_password_unittest.mm b/ios/web_view/internal/passwords/cwv_password_unittest.mm
index 63953f41..189898a3 100644
--- a/ios/web_view/internal/passwords/cwv_password_unittest.mm
+++ b/ios/web_view/internal/passwords/cwv_password_unittest.mm
@@ -5,7 +5,7 @@
 #import "ios/web_view/internal/passwords/cwv_password_internal.h"
 
 #include "base/strings/sys_string_conversions.h"
-#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_ui_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
@@ -21,7 +21,7 @@
 
 // Tests CWVPassword initialization for a blacklisted site.
 TEST_F(CWVPasswordTest, Blacklisted) {
-  autofill::PasswordForm password_form;
+  password_manager::PasswordForm password_form;
   password_form.url = GURL("http://www.example.com/accounts/LoginAuth");
   password_form.action = GURL("http://www.example.com/accounts/Login");
   password_form.username_element = base::SysNSStringToUTF16(@"Email");
@@ -30,7 +30,7 @@
   password_form.password_value = base::SysNSStringToUTF16(@"test");
   password_form.submit_element = base::SysNSStringToUTF16(@"signIn");
   password_form.signon_realm = "http://www.example.com/";
-  password_form.scheme = autofill::PasswordForm::Scheme::kHtml;
+  password_form.scheme = password_manager::PasswordForm::Scheme::kHtml;
   password_form.blocked_by_user = true;
   auto name_and_link =
       password_manager::GetShownOriginAndLinkUrl(password_form);
@@ -49,7 +49,7 @@
 
 // Tests CWVPassword initialization for a non-blacklisted site.
 TEST_F(CWVPasswordTest, NonBlacklisted) {
-  autofill::PasswordForm password_form;
+  password_manager::PasswordForm password_form;
   password_form.url = GURL("http://www.example.com/accounts/LoginAuth");
   password_form.action = GURL("http://www.example.com/accounts/Login");
   password_form.username_element = base::SysNSStringToUTF16(@"Email");
@@ -58,7 +58,7 @@
   password_form.password_value = base::SysNSStringToUTF16(@"test");
   password_form.submit_element = base::SysNSStringToUTF16(@"signIn");
   password_form.signon_realm = "http://www.example.com/";
-  password_form.scheme = autofill::PasswordForm::Scheme::kHtml;
+  password_form.scheme = password_manager::PasswordForm::Scheme::kHtml;
   password_form.blocked_by_user = false;
   auto name_and_link =
       password_manager::GetShownOriginAndLinkUrl(password_form);
diff --git a/ios/web_view/internal/passwords/web_view_password_feature_manager.h b/ios/web_view/internal/passwords/web_view_password_feature_manager.h
index b651ced5..63161d586 100644
--- a/ios/web_view/internal/passwords/web_view_password_feature_manager.h
+++ b/ios/web_view/internal/passwords/web_view_password_feature_manager.h
@@ -35,8 +35,9 @@
   bool ShouldShowAccountStorageBubbleUi() const override;
 
   void SetDefaultPasswordStore(
-      const autofill::PasswordForm::Store& store) override;
-  autofill::PasswordForm::Store GetDefaultPasswordStore() const override;
+      const password_manager::PasswordForm::Store& store) override;
+  password_manager::PasswordForm::Store GetDefaultPasswordStore()
+      const override;
 
   password_manager::metrics_util::PasswordAccountStorageUsageLevel
   ComputePasswordAccountStorageUsageLevel() const override;
diff --git a/ios/web_view/internal/passwords/web_view_password_feature_manager.mm b/ios/web_view/internal/passwords/web_view_password_feature_manager.mm
index 44bb6b8..753b9ee 100644
--- a/ios/web_view/internal/passwords/web_view_password_feature_manager.mm
+++ b/ios/web_view/internal/passwords/web_view_password_feature_manager.mm
@@ -52,14 +52,14 @@
   return false;
 }
 
-autofill::PasswordForm::Store
+password_manager::PasswordForm::Store
 WebViewPasswordFeatureManager::GetDefaultPasswordStore() const {
   // ios/web_view should never write to the profile password store.
-  return autofill::PasswordForm::Store::kAccountStore;
+  return password_manager::PasswordForm::Store::kAccountStore;
 }
 
 void WebViewPasswordFeatureManager::SetDefaultPasswordStore(
-    const autofill::PasswordForm::Store& store) {
+    const password_manager::PasswordForm::Store& store) {
   NOTREACHED();
 }
 
diff --git a/ios/web_view/internal/passwords/web_view_password_manager_client.h b/ios/web_view/internal/passwords/web_view_password_manager_client.h
index 7641d4d..fe29574d 100644
--- a/ios/web_view/internal/passwords/web_view_password_manager_client.h
+++ b/ios/web_view/internal/passwords/web_view_password_manager_client.h
@@ -68,7 +68,7 @@
       password_manager::PasswordManagerDriver* driver,
       autofill::mojom::FocusedFieldType focused_field_type) override;
   bool PromptUserToChooseCredentials(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms,
+      std::vector<std::unique_ptr<password_manager::PasswordForm>> local_forms,
       const url::Origin& origin,
       CredentialsCallback callback) override;
   void AutomaticPasswordSave(
@@ -83,10 +83,10 @@
   password_manager::PasswordStore* GetProfilePasswordStore() const override;
   password_manager::PasswordStore* GetAccountPasswordStore() const override;
   void NotifyUserAutoSignin(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms,
+      std::vector<std::unique_ptr<password_manager::PasswordForm>> local_forms,
       const url::Origin& origin) override;
   void NotifyUserCouldBeAutoSignedIn(
-      std::unique_ptr<autofill::PasswordForm> form) override;
+      std::unique_ptr<password_manager::PasswordForm> form) override;
   void NotifySuccessfulLoginWithExistingPassword(
       std::unique_ptr<password_manager::PasswordFormManagerForUI>
           submitted_manager) override;
diff --git a/ios/web_view/internal/passwords/web_view_password_manager_client.mm b/ios/web_view/internal/passwords/web_view_password_manager_client.mm
index 360e84b..b5cd2b6 100644
--- a/ios/web_view/internal/passwords/web_view_password_manager_client.mm
+++ b/ios/web_view/internal/passwords/web_view_password_manager_client.mm
@@ -8,8 +8,8 @@
 #include <utility>
 
 #include "components/autofill/core/browser/logging/log_manager.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/keyed_service/core/service_access_type.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/password_manager/ios/password_manager_ios_util.h"
@@ -97,7 +97,7 @@
 }
 
 bool WebViewPasswordManagerClient::PromptUserToChooseCredentials(
-    std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms,
+    std::vector<std::unique_ptr<password_manager::PasswordForm>> local_forms,
     const url::Origin& origin,
     CredentialsCallback callback) {
   NOTIMPLEMENTED();
@@ -182,7 +182,7 @@
 }
 
 void WebViewPasswordManagerClient::NotifyUserAutoSignin(
-    std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms,
+    std::vector<std::unique_ptr<password_manager::PasswordForm>> local_forms,
     const url::Origin& origin) {
   DCHECK(!local_forms.empty());
   helper_.NotifyUserAutoSignin();
@@ -190,7 +190,7 @@
 }
 
 void WebViewPasswordManagerClient::NotifyUserCouldBeAutoSignedIn(
-    std::unique_ptr<autofill::PasswordForm> form) {
+    std::unique_ptr<password_manager::PasswordForm> form) {
   helper_.NotifyUserCouldBeAutoSignedIn(std::move(form));
 }
 
diff --git a/ios/web_view/internal/passwords/web_view_password_manager_client_unittest.mm b/ios/web_view/internal/passwords/web_view_password_manager_client_unittest.mm
index a056cf1..ccb7e4c 100644
--- a/ios/web_view/internal/passwords/web_view_password_manager_client_unittest.mm
+++ b/ios/web_view/internal/passwords/web_view_password_manager_client_unittest.mm
@@ -9,8 +9,8 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/test/scoped_feature_list.h"
 #include "components/autofill/core/browser/logging/stub_log_manager.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/password_manager/core/browser/mock_password_form_manager_for_ui.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_form_manager_for_ui.h"
 #include "components/password_manager/core/browser/password_manager.h"
 #include "components/password_manager/core/browser/password_manager_features_util.h"
diff --git a/ios/web_view/internal/passwords/web_view_password_manager_driver.mm b/ios/web_view/internal/passwords/web_view_password_manager_driver.mm
index 6b16d59..01c29cd 100644
--- a/ios/web_view/internal/passwords/web_view_password_manager_driver.mm
+++ b/ios/web_view/internal/passwords/web_view_password_manager_driver.mm
@@ -5,8 +5,8 @@
 #import "ios/web_view/internal/passwords/web_view_password_manager_driver.h"
 
 #include "base/strings/string16.h"
-#include "components/autofill/core/common/password_form.h"
 #include "components/autofill/core/common/password_form_fill_data.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/web_view/internal/sync/cwv_sync_controller.mm b/ios/web_view/internal/sync/cwv_sync_controller.mm
index 90910593..c37f971 100644
--- a/ios/web_view/internal/sync/cwv_sync_controller.mm
+++ b/ios/web_view/internal/sync/cwv_sync_controller.mm
@@ -188,7 +188,8 @@
   autofill::prefs::SetUserOptedInWalletSyncTransport(_prefService, accountId,
                                                      /*opted_in=*/true);
   password_manager::features_util::SetDefaultPasswordStore(
-      _prefService, _syncService, autofill::PasswordForm::Store::kAccountStore);
+      _prefService, _syncService,
+      password_manager::PasswordForm::Store::kAccountStore);
   password_manager::features_util::OptInToAccountStorage(_prefService,
                                                          _syncService);
 }
diff --git a/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm b/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm
index 73cd4b1f..0bc41d7 100644
--- a/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm
+++ b/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm
@@ -106,7 +106,7 @@
       &pref_service_, primary_account_info.account_id));
   EXPECT_EQ(password_manager::features_util::GetDefaultPasswordStore(
                 &pref_service_, &sync_service_),
-            autofill::PasswordForm::Store::kAccountStore);
+            password_manager::PasswordForm::Store::kAccountStore);
   EXPECT_TRUE(password_manager::features_util::IsOptedInForAccountStorage(
       &pref_service_, &sync_service_));
 }
diff --git a/ios/web_view/tools/build.py b/ios/web_view/tools/build.py
index 819d554..38c323c4 100755
--- a/ios/web_view/tools/build.py
+++ b/ios/web_view/tools/build.py
@@ -27,7 +27,7 @@
   Args:
     build_config: A string describing the build configuration. Ex: 'Debug'
     target_device: A string describing the target device. Ex: 'simulator'
-    extra_gn_options: A string of gn args (space separated key=value items) to
+    extra_gn_options: A list of strings of gn args (key=value items) to
       be appended to the gn gen command.
     extra_ninja_options: A string of gn options to be appended to the ninja
       command.
@@ -36,27 +36,43 @@
     The return code of generating ninja if it is non-zero, else the return code
       of the ninja build command.
   """
+  gn_args = [
+      'target_os="ios"',
+      'enable_websockets=false',
+      'is_component_build=false',
+      'use_xcode_clang=false',
+      'disable_file_support=true',
+      'disable_ftp_support=true',
+      'disable_brotli_filter=true',
+      'ios_enable_code_signing=false',
+      'enable_dsyms=true',
+  ]
+
   if target_device == 'iphoneos':
-    target_cpu = 'arm64'
+    gn_args.extend([
+        'target_cpu="arm64"',
+        'target_environment="device"',
+    ])
   else:
-    target_cpu = 'x64'
+    gn_args.extend([
+        'target_cpu="x64"',
+        'target_environment="simulator"',
+    ])
 
   if build_config == 'Debug':
-    build_config_gn_args = 'is_debug=true'
+    gn_args.append('is_debug=true')
   else:
-    build_config_gn_args = ('is_debug=false enable_stripping=true '
-                            'is_official_build=true')
+    gn_args.extend([
+        'is_debug=false',
+        'enable_stripping=true',
+        'is_official_build=true',
+    ])
+
+  if extra_gn_options:
+    gn_args.extend(extra_gn_options)
 
   build_dir = os.path.join("out", target_dir_name(build_config, target_device))
-  gn_args = ('target_os="ios" enable_websockets=false '
-            'is_component_build=false use_xcode_clang=false '
-            'disable_file_support=true disable_ftp_support=true '
-            'disable_brotli_filter=true ios_enable_code_signing=false '
-            'enable_dsyms=true '
-            'target_cpu="%s" %s %s' %
-            (target_cpu, build_config_gn_args, extra_gn_options))
-
-  gn_command = 'gn gen %s --args=\'%s\'' % (build_dir, gn_args)
+  gn_command = 'gn gen %s --args=\'%s\'' % (build_dir, ' '.join(gn_args))
   print gn_command
   gn_result = os.system(gn_command)
   if gn_result != 0:
@@ -108,7 +124,7 @@
     build_config: A string describing the build configuration. Ex: 'Debug'
     target_device: A string describing the target device. Ex: 'simulator'
     out_dir: A string to the path which all build products will be copied.
-    extra_gn_options: A string of gn args (space separated key=value items) to
+    extra_gn_options: A list of strings of gn args (key=value items) to
       be appended to the gn gen command.
     extra_ninja_options: A string of gn options to be appended to the ninja
       command.
@@ -138,7 +154,7 @@
 
   Args:
     out_dir: A string to the path which all build products will be copied.
-    extra_gn_options: A string of gn args (space separated key=value items) to
+    extra_gn_options: A list of strings of gn args (key=value items) to
       be appended to the gn gen command.
     build_configs: A list of configs to build.
     target_devices: A list of devices to target.
@@ -209,18 +225,18 @@
     return 1
 
   output_name = 'ChromeWebView'
-  extra_gn_options = ''
+  extra_gn_options = []
   if not options.no_goma:
-    extra_gn_options += 'use_goma=true '
+    extra_gn_options.append('use_goma=true')
   if options.include_cronet:
-    extra_gn_options += 'ios_web_view_include_cronet=true '
+    extra_gn_options.append('ios_web_view_include_cronet=true')
     output_name = 'CronetChromeWebView'
   else:
-    extra_gn_options += 'ios_web_view_include_cronet=false '
-  extra_gn_options += 'ios_web_view_output_name="%s" ' % output_name
+    extra_gn_options.append('ios_web_view_include_cronet=false')
+  extra_gn_options.append('ios_web_view_output_name="%s"' % output_name)
   # This prevents Breakpad from being included in the final binary to avoid
   # duplicate symbols with the client app.
-  extra_gn_options += 'use_crash_key_stubs=true '
+  extra_gn_options.append('use_crash_key_stubs=true')
 
   return package_all_frameworks(out_dir, output_name, extra_gn_options,
                                 set(options.build_configs),
diff --git a/media/audio/BUILD.gn b/media/audio/BUILD.gn
index 5e4dc90..883e3e1 100644
--- a/media/audio/BUILD.gn
+++ b/media/audio/BUILD.gn
@@ -276,6 +276,8 @@
       sources += [
         "cras/audio_manager_cras.cc",
         "cras/audio_manager_cras.h",
+        "cras/cras_util.cc",
+        "cras/cras_util.h",
       ]
     }
   }
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc
index 0b8bf31..6016df8 100644
--- a/media/audio/cras/audio_manager_cras.cc
+++ b/media/audio/cras/audio_manager_cras.cc
@@ -24,6 +24,7 @@
 #include "media/audio/audio_features.h"
 #include "media/audio/cras/cras_input.h"
 #include "media/audio/cras/cras_unified.h"
+#include "media/audio/cras/cras_util.h"
 #include "media/base/channel_layout.h"
 #include "media/base/limits.h"
 #include "media/base/localized_strings.h"
@@ -47,7 +48,7 @@
 }
 
 bool AudioManagerCras::HasAudioInputDevices() {
-  return true;
+  return !CrasGetAudioDevices(DeviceType::kInput).empty();
 }
 
 AudioManagerCras::AudioManagerCras(
@@ -64,11 +65,17 @@
 void AudioManagerCras::GetAudioInputDeviceNames(
     AudioDeviceNames* device_names) {
   device_names->push_back(AudioDeviceName::CreateDefault());
+  for (const auto& device : CrasGetAudioDevices(DeviceType::kInput)) {
+    device_names->emplace_back(device.name, base::NumberToString(device.id));
+  }
 }
 
 void AudioManagerCras::GetAudioOutputDeviceNames(
     AudioDeviceNames* device_names) {
   device_names->push_back(AudioDeviceName::CreateDefault());
+  for (const auto& device : CrasGetAudioDevices(DeviceType::kOutput)) {
+    device_names->emplace_back(device.name, base::NumberToString(device.id));
+  }
 }
 
 AudioParameters AudioManagerCras::GetInputStreamParameters(
@@ -135,7 +142,7 @@
 }
 
 bool AudioManagerCras::IsDefault(const std::string& device_id, bool is_input) {
-  return true;
+  return device_id == AudioDeviceDescription::kDefaultDeviceId;
 }
 
 }  // namespace media
diff --git a/media/audio/cras/cras_util.cc b/media/audio/cras/cras_util.cc
new file mode 100644
index 0000000..bba670a
--- /dev/null
+++ b/media/audio/cras/cras_util.cc
@@ -0,0 +1,111 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/audio/cras/cras_util.h"
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/time/time.h"
+#include "media/audio/audio_device_description.h"
+#include "media/audio/cras/audio_manager_cras_base.h"
+
+namespace media {
+
+namespace {
+
+// Returns if that an input or output audio device is for simple usage like
+// playback or recording for user. In contrast, audio device such as loopback,
+// always on keyword recognition (HOTWORD), and keyboard mic are not for simple
+// usage.
+// One special case is ALSA loopback device, which will only exist under
+// testing. We want it visible to users for e2e tests.
+bool IsForSimpleUsage(uint32_t type) {
+  return type == CRAS_NODE_TYPE_INTERNAL_SPEAKER ||
+         type == CRAS_NODE_TYPE_HEADPHONE || type == CRAS_NODE_TYPE_HDMI ||
+         type == CRAS_NODE_TYPE_LINEOUT || type == CRAS_NODE_TYPE_MIC ||
+         type == CRAS_NODE_TYPE_BLUETOOTH_NB_MIC ||
+         type == CRAS_NODE_TYPE_USB || type == CRAS_NODE_TYPE_BLUETOOTH ||
+         type == CRAS_NODE_TYPE_ALSA_LOOPBACK;
+}
+
+// Connects to the CRAS server.
+cras_client* CrasConnect() {
+  cras_client* client;
+  if (cras_client_create(&client)) {
+    LOG(ERROR) << "Couldn't create CRAS client.\n";
+    return nullptr;
+  }
+  if (cras_client_connect(client)) {
+    LOG(ERROR) << "Couldn't connect CRAS client.\n";
+    cras_client_destroy(client);
+    return nullptr;
+  }
+  return client;
+}
+
+// Disconnects from the CRAS server.
+void CrasDisconnect(cras_client** client) {
+  if (*client) {
+    cras_client_stop(*client);
+    cras_client_destroy(*client);
+    *client = nullptr;
+  }
+}
+
+}  // namespace
+
+CrasDevice::CrasDevice() = default;
+
+CrasDevice::CrasDevice(const cras_ionode_info* node,
+                       const cras_iodev_info* dev,
+                       DeviceType type)
+    : type(type) {
+  id = cras_make_node_id(node->iodev_idx, node->ionode_idx);
+  name = std::string(node->name);
+  // If the name of node is not meaningful, use the device name instead.
+  if (name.empty() || name == "(default)")
+    name = dev->name;
+}
+
+std::vector<CrasDevice> CrasGetAudioDevices(DeviceType type) {
+  std::vector<CrasDevice> devices;
+
+  cras_client* client = CrasConnect();
+  if (!client)
+    return devices;
+
+  struct cras_iodev_info devs[CRAS_MAX_IODEVS];
+  struct cras_ionode_info nodes[CRAS_MAX_IONODES];
+  size_t num_devs = CRAS_MAX_IODEVS, num_nodes = CRAS_MAX_IONODES;
+  int rc;
+
+  if (type == DeviceType::kInput) {
+    rc = cras_client_get_input_devices(client, devs, nodes, &num_devs,
+                                       &num_nodes);
+  } else {
+    rc = cras_client_get_output_devices(client, devs, nodes, &num_devs,
+                                        &num_nodes);
+  }
+  if (rc < 0) {
+    LOG(ERROR) << "Failed to get devices: " << std::strerror(rc);
+    return devices;
+  }
+
+  for (size_t i = 0; i < num_nodes; i++) {
+    if (!nodes[i].plugged || !IsForSimpleUsage(nodes[i].type_enum))
+      continue;
+    for (size_t j = 0; j < num_devs; j++) {
+      if (nodes[i].iodev_idx == devs[j].idx) {
+        devices.emplace_back(&nodes[i], &devs[j], type);
+        break;
+      }
+    }
+  }
+
+  CrasDisconnect(&client);
+  return devices;
+}
+
+}  // namespace media
diff --git a/media/audio/cras/cras_util.h b/media/audio/cras/cras_util.h
new file mode 100644
index 0000000..130ac56
--- /dev/null
+++ b/media/audio/cras/cras_util.h
@@ -0,0 +1,33 @@
+// 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 MEDIA_AUDIO_CRAS_CRAS_UTIL_H_
+#define MEDIA_AUDIO_CRAS_CRAS_UTIL_H_
+
+#include <cras_client.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+namespace media {
+
+enum class DeviceType { kInput, kOutput };
+
+struct CrasDevice {
+  CrasDevice();
+  explicit CrasDevice(const cras_ionode_info* node,
+                      const cras_iodev_info* dev,
+                      DeviceType type);
+  DeviceType type;
+  uint64_t id;
+  std::string name;
+};
+
+// Enumerates all devices of |type|.
+std::vector<CrasDevice> CrasGetAudioDevices(DeviceType type);
+
+}  // namespace media
+
+#endif  // MEDIA_AUDIO_CRAS_CRAS_UTIL_H_
diff --git a/media/base/cdm_context.cc b/media/base/cdm_context.cc
index cbc0c9d..c91cb81 100644
--- a/media/base/cdm_context.cc
+++ b/media/base/cdm_context.cc
@@ -52,4 +52,10 @@
 }
 #endif
 
+#if defined(OS_CHROMEOS)
+chromeos::ChromeOsCdmContext* CdmContext::GetChromeOsCdmContext() {
+  return nullptr;
+}
+#endif
+
 }  // namespace media
diff --git a/media/base/cdm_context.h b/media/base/cdm_context.h
index d2d6965..92ca4dd 100644
--- a/media/base/cdm_context.h
+++ b/media/base/cdm_context.h
@@ -18,6 +18,12 @@
 struct IMFCdmProxy;
 #endif
 
+#if defined(OS_CHROMEOS)
+namespace chromeos {
+class ChromeOsCdmContext;
+}
+#endif
+
 namespace media {
 
 class CallbackRegistration;
@@ -115,6 +121,12 @@
   virtual FuchsiaCdmContext* GetFuchsiaCdmContext();
 #endif
 
+#if defined(OS_CHROMEOS)
+  // Returns a ChromeOsCdmContext interface when the context is backed by the
+  // ChromeOS CdmFactoryDaemon. Otherwise return nullptr.
+  virtual chromeos::ChromeOsCdmContext* GetChromeOsCdmContext();
+#endif
+
  protected:
   CdmContext();
 
diff --git a/media/base/user_input_monitor_linux.cc b/media/base/user_input_monitor_linux.cc
index 59e655f..13c373f 100644
--- a/media/base/user_input_monitor_linux.cc
+++ b/media/base/user_input_monitor_linux.cc
@@ -115,9 +115,10 @@
   DCHECK(io_task_runner_->BelongsToCurrentThread());
 
   auto* raw = event->As<x11::Input::RawDeviceEvent>();
-  DCHECK(raw);
-  DCHECK(raw->opcode == x11::Input::RawDeviceEvent::RawKeyPress ||
-         raw->opcode == x11::Input::RawDeviceEvent::RawKeyRelease);
+  if (!raw || (raw->opcode != x11::Input::RawDeviceEvent::RawKeyPress &&
+               raw->opcode != x11::Input::RawDeviceEvent::RawKeyRelease)) {
+    return;
+  }
 
   ui::EventType type = raw->opcode == x11::Input::RawDeviceEvent::RawKeyPress
                            ? ui::ET_KEY_PRESSED
diff --git a/net/dns/dns_server_iterator.h b/net/dns/dns_server_iterator.h
index 97c42f7..3a775ed 100644
--- a/net/dns/dns_server_iterator.h
+++ b/net/dns/dns_server_iterator.h
@@ -5,6 +5,7 @@
 #ifndef NET_DNS_DNS_SERVER_ITERATOR_H_
 #define NET_DNS_DNS_SERVER_ITERATOR_H_
 
+#include <stddef.h>
 #include <vector>
 
 #include "net/base/net_export.h"
diff --git a/net/dns/dns_test_util.cc b/net/dns/dns_test_util.cc
index 469be55..28a6333 100644
--- a/net/dns/dns_test_util.cc
+++ b/net/dns/dns_test_util.cc
@@ -80,7 +80,9 @@
   record.type = type;
   record.klass = dns_protocol::kClassIN;
   record.ttl = ttl.InSeconds();
-  record.SetOwnedRdata(std::move(rdata));
+
+  if (!rdata.empty())
+    record.SetOwnedRdata(std::move(rdata));
 
   return record;
 }
diff --git a/net/dns/dns_util.cc b/net/dns/dns_util.cc
index 2883a07..ac89983 100644
--- a/net/dns/dns_util.cc
+++ b/net/dns/dns_util.cc
@@ -291,6 +291,8 @@
       return dns_protocol::kTypeSRV;
     case DnsQueryType::INTEGRITY:
       return dns_protocol::kExperimentalTypeIntegrity;
+    case DnsQueryType::HTTPS:
+      return dns_protocol::kTypeHttps;
   }
 }
 
diff --git a/net/dns/host_resolver.h b/net/dns/host_resolver.h
index fb4aa68..fa21e0d 100644
--- a/net/dns/host_resolver.h
+++ b/net/dns/host_resolver.h
@@ -100,6 +100,8 @@
 
     // INTEGRITY results for an initial experiment related to HTTPSSVC. Each
     // boolean value indicates the intactness of an INTEGRITY record.
+    // TODO(crbug.com/1138620): Generalize to be used for other experimental
+    // records.
     NET_EXPORT virtual const base::Optional<std::vector<bool>>&
     GetIntegrityResultsForTesting() const;
 
diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc
index a6ce779..95363f8 100644
--- a/net/dns/host_resolver_manager.cc
+++ b/net/dns/host_resolver_manager.cc
@@ -1124,15 +1124,15 @@
       const bool is_httpssvc_control_domain =
           httpssvc_domain_cache_.IsControl(hostname);
       if (base::FeatureList::IsEnabled(features::kDnsHttpssvc) &&
-          features::kDnsHttpssvcUseIntegrity.Get() &&
           (secure_ || features::kDnsHttpssvcEnableQueryOverInsecure.Get()) &&
           (is_httpssvc_experiment_domain || is_httpssvc_control_domain)) {
-        // We should not be configured to query HTTPSSVC *and* INTEGRITY.
-        DCHECK(!features::kDnsHttpssvcUseHttpssvc.Get());
-
         httpssvc_metrics_.emplace(
             is_httpssvc_experiment_domain /* expect_intact */);
-        transactions_needed_.push(DnsQueryType::INTEGRITY);
+
+        if (features::kDnsHttpssvcUseIntegrity.Get())
+          transactions_needed_.push(DnsQueryType::INTEGRITY);
+        if (features::kDnsHttpssvcUseHttpssvc.Get())
+          transactions_needed_.push(DnsQueryType::HTTPS);
       }
     }
     num_needed_transactions_ = transactions_needed_.size();
@@ -1194,25 +1194,31 @@
     return trans;
   }
 
-  void OnExperimentalQueryTimeout(uint16_t qtype,
-                                  base::Optional<std::string> doh_provider_id) {
-    // The experimental query timer is only started when all other transactions
-    // have completed.
-    DCHECK(TaskIsCompleteOrOnlyQtypeTransactionsRemain(qtype));
+  void OnExperimentalQueryTimeout(base::Optional<std::string> doh_provider_id) {
+    for (std::unique_ptr<DnsTransaction>& transaction : transactions_started_) {
+      DCHECK(httpssvc_metrics_);
+      base::TimeDelta elapsed_time = tick_clock_->NowTicks() - task_start_time_;
+
+      switch (transaction->GetType()) {
+        case dns_protocol::kExperimentalTypeIntegrity:
+          httpssvc_metrics_->SaveForIntegrity(
+              doh_provider_id, HttpssvcDnsRcode::kTimedOut, {}, elapsed_time);
+          break;
+        case dns_protocol::kTypeHttps:
+          httpssvc_metrics_->SaveForHttps(
+              doh_provider_id, HttpssvcDnsRcode::kTimedOut, elapsed_time);
+          break;
+        default:
+          // The experimental query timer is only started when all other
+          // transactions have completed.
+          NOTREACHED();
+      }
+    }
 
     num_completed_transactions_ += transactions_started_.size();
     DCHECK(num_completed_transactions_ == num_needed_transactions());
     transactions_started_.clear();
 
-    if (qtype == dns_protocol::kExperimentalTypeIntegrity) {
-      DCHECK(httpssvc_metrics_);
-
-      // Record that this INTEGRITY query timed out in the metrics.
-      base::TimeDelta elapsed_time = tick_clock_->NowTicks() - task_start_time_;
-      httpssvc_metrics_->SaveForIntegrity(
-          doh_provider_id, HttpssvcDnsRcode::kTimedOut, {}, elapsed_time);
-    }
-
     ProcessResultsOnCompletion();
   }
 
@@ -1254,8 +1260,9 @@
 
     if (net_error != OK && !(net_error == ERR_NAME_NOT_RESOLVED && response &&
                              response->IsValid())) {
-      if (dns_query_type == DnsQueryType::INTEGRITY) {
-        // Do not allow an INTEGRITY query to fail the whole DnsTask.
+      if (dns_query_type == DnsQueryType::INTEGRITY ||
+          dns_query_type == DnsQueryType::HTTPS) {
+        // Do not allow an experimental query to fail the whole DnsTask.
         response = nullptr;
       } else {
         OnFailure(net_error, DnsResponse::DNS_PARSE_OK, base::nullopt);
@@ -1287,6 +1294,9 @@
         // Parse the INTEGRITY records, condensing them into a vector<bool>.
         parse_result = ParseIntegrityDnsResponse(response, &results);
         break;
+      case DnsQueryType::HTTPS:
+        parse_result = ParseHttpsDnsResponse(response, &results);
+        break;
     }
     DCHECK_LT(parse_result, DnsResponse::DNS_PARSE_RESULT_MAX);
 
@@ -1296,10 +1306,7 @@
     }
 
     if (httpssvc_metrics_) {
-      if (dns_query_type != DnsQueryType::INTEGRITY) {
-        httpssvc_metrics_->SaveForNonIntegrity(doh_provider_id, elapsed_time,
-                                               rcode_for_httpssvc);
-      } else {
+      if (dns_query_type == DnsQueryType::INTEGRITY) {
         const base::Optional<std::vector<bool>>& condensed =
             results.integrity_data();
         CHECK(condensed.has_value());
@@ -1307,6 +1314,12 @@
         // experimental query timer runs out (OnExperimentalQueryTimeout).
         httpssvc_metrics_->SaveForIntegrity(doh_provider_id, rcode_for_httpssvc,
                                             *condensed, elapsed_time);
+      } else if (dns_query_type == DnsQueryType::HTTPS) {
+        httpssvc_metrics_->SaveForHttps(doh_provider_id, rcode_for_httpssvc,
+                                        elapsed_time);
+      } else {
+        httpssvc_metrics_->SaveForNonIntegrity(doh_provider_id, elapsed_time,
+                                               rcode_for_httpssvc);
       }
     }
 
@@ -1332,6 +1345,9 @@
           results = HostCache::Entry::MergeEntries(
               std::move(results), std::move(saved_results_).value());
           break;
+        case DnsQueryType::HTTPS:
+          results = std::move(saved_results_).value();
+          break;
         default:
           // Only expect address query types with multiple transactions.
           NOTREACHED();
@@ -1534,6 +1550,14 @@
     return parse_result;
   }
 
+  DnsResponse::Result ParseHttpsDnsResponse(const DnsResponse* response,
+                                            HostCache::Entry* out_results) {
+    // TODO(crbug.com/1138620): Add actual parse implementation.
+    *out_results = HostCache::Entry(
+        ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS, base::nullopt);
+    return DnsResponse::Result::DNS_PARSE_OK;
+  }
+
   // Sort service targets per RFC2782.  In summary, sort first by |priority|,
   // lowest first.  For targets with the same priority, secondary sort randomly
   // using |weight| with higher weighted objects more likely to go first.
@@ -1705,7 +1729,8 @@
   // |qtype|. (In particular, this is the case if all transactions are
   // complete.) Used for logging and starting the experimental query timer (see
   // MaybeStartExperimentalQueryTimer).
-  bool TaskIsCompleteOrOnlyQtypeTransactionsRemain(uint16_t qtype) const {
+  bool TaskIsCompleteOrOnlyQtypeTransactionsRemain(
+      std::initializer_list<uint16_t> qtypes) const {
     // Since DoH runs all transactions concurrently and experimental types are
     // only queried over DoH, this method only needs to check the transactions
     // in transactions_started_ because transactions_needed_ is empty from the
@@ -1714,13 +1739,14 @@
 
     return std::all_of(
         transactions_started_.begin(), transactions_started_.end(),
-        [&](const std::unique_ptr<DnsTransaction>& p) {
-          DCHECK(p);
-          return p->GetType() == qtype;
+        [&](const std::unique_ptr<DnsTransaction>& transaction) {
+          DCHECK(transaction);
+          return std::any_of(qtypes.begin(), qtypes.end(), [&](uint16_t qtype) {
+            return transaction->GetType() == qtype;
+          });
         });
   }
 
-
   void MaybeStartExperimentalQueryTimer(
       base::Optional<std::string> doh_provider_id) {
     DCHECK(!transactions_started_.empty());
@@ -1734,7 +1760,8 @@
 
     if (!experimental_query_cancellation_timer_.IsRunning() &&
         TaskIsCompleteOrOnlyQtypeTransactionsRemain(
-            dns_protocol::kExperimentalTypeIntegrity)) {
+            {dns_protocol::kExperimentalTypeIntegrity,
+             dns_protocol::kTypeHttps})) {
       const base::TimeDelta kExtraTimeAbsolute =
           features::dns_httpssvc_experiment::GetExtraTimeAbsolute();
       const int kExtraTimePercent =
@@ -1744,14 +1771,16 @@
           tick_clock_->NowTicks() - task_start_time_;
       base::TimeDelta relative_timeout =
           total_time_for_other_transactions * kExtraTimePercent / 100;
+      // Use at least 1ms to ensure timeout doesn't occur immediately in tests.
+      relative_timeout =
+          std::max(relative_timeout, base::TimeDelta::FromMilliseconds(1));
 
       base::TimeDelta timeout = std::min(kExtraTimeAbsolute, relative_timeout);
 
       experimental_query_cancellation_timer_.Start(
           FROM_HERE, timeout,
-          base::BindOnce(
-              &DnsTask::OnExperimentalQueryTimeout, base::Unretained(this),
-              dns_protocol::kExperimentalTypeIntegrity, doh_provider_id));
+          base::BindOnce(&DnsTask::OnExperimentalQueryTimeout,
+                         base::Unretained(this), doh_provider_id));
     }
   }
 
diff --git a/net/dns/host_resolver_manager_unittest.cc b/net/dns/host_resolver_manager_unittest.cc
index d752872e..02e01f3 100644
--- a/net/dns/host_resolver_manager_unittest.cc
+++ b/net/dns/host_resolver_manager_unittest.cc
@@ -23,6 +23,7 @@
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/condition_variable.h"
@@ -3818,7 +3819,7 @@
  public:
   explicit HostResolverManagerDnsTest(
       base::test::TaskEnvironment::TimeSource time_source =
-          base::test::TaskEnvironment::TimeSource::SYSTEM_TIME)
+          base::test::TaskEnvironment::TimeSource::MOCK_TIME)
       : HostResolverManagerTest(time_source),
         notifier_task_runner_(
             base::MakeRefCounted<base::TestMockTimeTaskRunner>()),
@@ -8833,6 +8834,777 @@
                                             HostPortPair("google.com", 5)));
 }
 
+TEST_F(HostResolverManagerDnsTest, HttpsQuery) {
+  const std::string kName = "https.test";
+
+  MockDnsClientRuleList rules;
+  std::vector<DnsResourceRecord> records = {
+      BuildTestDnsRecord(kName, dns_protocol::kTypeHttps, "" /* rdata */)};
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, false /* secure */,
+                     MockDnsClientRule::Result(BuildTestDnsResponse(
+                         kName, dns_protocol::kTypeHttps, records)),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+  HostResolver::ResolveHostParameters parameters;
+  parameters.dns_query_type = DnsQueryType::HTTPS;
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      parameters, resolve_context_.get(), resolve_context_->host_cache()));
+  EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+  EXPECT_FALSE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsQuery_InvalidConfig) {
+  set_allow_fallback_to_proctask(false);
+  // Set empty DnsConfig.
+  InvalidateDnsConfig();
+
+  HostResolver::ResolveHostParameters parameters;
+  parameters.dns_query_type = DnsQueryType::HTTPS;
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair("https.test", 108), NetworkIsolationKey(),
+      NetLogWithSource(), parameters, resolve_context_.get(),
+      resolve_context_->host_cache()));
+  EXPECT_THAT(response.result_error(), IsError(ERR_DNS_CACHE_MISS));
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsQuery_NonexistentDomain) {
+  const std::string kName = "https.test";
+
+  // Setup fallback to confirm it is not used for non-address results.
+  set_allow_fallback_to_proctask(true);
+  proc_->AddRuleForAllFamilies(kName, "192.168.1.102");
+  proc_->SignalMultiple(1u);
+
+  MockDnsClientRuleList rules;
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, false /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::NODOMAIN),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+  HostResolver::ResolveHostParameters parameters;
+  parameters.dns_query_type = DnsQueryType::HTTPS;
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      parameters, resolve_context_.get(), resolve_context_->host_cache()));
+  EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+  EXPECT_FALSE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsQuery_Failure) {
+  const std::string kName = "https.test";
+
+  // Setup fallback to confirm it is not used for non-address results.
+  set_allow_fallback_to_proctask(true);
+  proc_->AddRuleForAllFamilies(kName, "192.168.1.102");
+  proc_->SignalMultiple(1u);
+
+  MockDnsClientRuleList rules;
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, false /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::FAIL),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+  HostResolver::ResolveHostParameters parameters;
+  parameters.dns_query_type = DnsQueryType::HTTPS;
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      parameters, resolve_context_.get(), resolve_context_->host_cache()));
+  EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+  EXPECT_FALSE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+
+  // Expect result not cached.
+  EXPECT_EQ(resolve_context_->host_cache()->size(), 0u);
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsQuery_Timeout) {
+  const std::string kName = "https.test";
+
+  // Setup fallback to confirm it is not used for non-address results.
+  set_allow_fallback_to_proctask(true);
+  proc_->AddRuleForAllFamilies(kName, "192.168.1.102");
+  proc_->SignalMultiple(1u);
+
+  MockDnsClientRuleList rules;
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, false /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::TIMEOUT),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+  HostResolver::ResolveHostParameters parameters;
+  parameters.dns_query_type = DnsQueryType::HTTPS;
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      parameters, resolve_context_.get(), resolve_context_->host_cache()));
+  // Experimental type, so expect errors to be ignored.
+  EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+  EXPECT_FALSE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+
+  // Expect result not cached.
+  EXPECT_EQ(resolve_context_->host_cache()->size(), 0u);
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsQuery_Empty) {
+  const std::string kName = "https.test";
+
+  // Setup fallback to confirm it is not used for non-address results.
+  set_allow_fallback_to_proctask(true);
+  proc_->AddRuleForAllFamilies(kName, "192.168.1.102");
+  proc_->SignalMultiple(1u);
+
+  MockDnsClientRuleList rules;
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, false /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::EMPTY),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+  HostResolver::ResolveHostParameters parameters;
+  parameters.dns_query_type = DnsQueryType::HTTPS;
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      parameters, resolve_context_.get(), resolve_context_->host_cache()));
+  EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+  EXPECT_FALSE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsQuery_Malformed) {
+  const std::string kName = "https.test";
+
+  // Setup fallback to confirm it is not used for non-address results.
+  set_allow_fallback_to_proctask(true);
+  proc_->AddRuleForAllFamilies(kName, "192.168.1.102");
+  proc_->SignalMultiple(1u);
+
+  MockDnsClientRuleList rules;
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, false /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::MALFORMED),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+  HostResolver::ResolveHostParameters parameters;
+  parameters.dns_query_type = DnsQueryType::HTTPS;
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      parameters, resolve_context_.get(), resolve_context_->host_cache()));
+  // Experimental type, so expect errors to be ignored.
+  EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+  EXPECT_FALSE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+
+  // Expect result not cached.
+  EXPECT_EQ(resolve_context_->host_cache()->size(), 0u);
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsQuery_MismatchedName) {
+  const std::string kName = "https.test";
+
+  MockDnsClientRuleList rules;
+  std::vector<DnsResourceRecord> records = {BuildTestDnsRecord(
+      "different.test", dns_protocol::kTypeHttps, "" /* rdata */)};
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, false /* secure */,
+                     MockDnsClientRule::Result(BuildTestDnsResponse(
+                         kName, dns_protocol::kTypeHttps, records)),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+  HostResolver::ResolveHostParameters parameters;
+  parameters.dns_query_type = DnsQueryType::HTTPS;
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      parameters, resolve_context_.get(), resolve_context_->host_cache()));
+  // Experimental type, so expect errors to be ignored.
+  EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+  EXPECT_FALSE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+
+  // Expect result not cached.
+  EXPECT_EQ(resolve_context_->host_cache()->size(), 0u);
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsQuery_WrongType) {
+  const std::string kName = "https.test";
+
+  // Respond to an HTTPS query with an A response.
+  MockDnsClientRuleList rules;
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, false /* secure */,
+                     MockDnsClientRule::Result(BuildTestDnsAddressResponse(
+                         kName, IPAddress(1, 2, 3, 4))),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+  HostResolver::ResolveHostParameters parameters;
+  parameters.dns_query_type = DnsQueryType::HTTPS;
+
+  // Responses for the wrong type should be ignored.
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      parameters, resolve_context_.get(), resolve_context_->host_cache()));
+  EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+  EXPECT_FALSE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+
+  // Expect result not cached.
+  EXPECT_EQ(resolve_context_->host_cache()->size(), 0u);
+}
+
+// Same as HttpsQuery except we specify DNS HostResolverSource instead of
+// relying on automatic determination.  Expect same results since DNS should be
+// what we automatically determine, but some slightly different logic paths are
+// involved.
+TEST_F(HostResolverManagerDnsTest, HttpsDnsQuery) {
+  const std::string kName = "https.test";
+
+  MockDnsClientRuleList rules;
+  std::vector<DnsResourceRecord> records = {
+      BuildTestDnsRecord(kName, dns_protocol::kTypeHttps, "" /* rdata */)};
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, false /* secure */,
+                     MockDnsClientRule::Result(BuildTestDnsResponse(
+                         kName, dns_protocol::kTypeHttps, records)),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+  HostResolver::ResolveHostParameters parameters;
+  parameters.source = HostResolverSource::DNS;
+  parameters.dns_query_type = DnsQueryType::HTTPS;
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      parameters, resolve_context_.get(), resolve_context_->host_cache()));
+  EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+  EXPECT_FALSE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery) {
+  const char kName[] = "combined.test";
+
+  base::test::ScopedFeatureList features;
+  features.InitAndEnableFeatureWithParameters(
+      features::kDnsHttpssvc, {{"DnsHttpssvcUseHttpssvc", "true"},
+                               {"DnsHttpssvcExperimentDomains", kName}});
+
+  MockDnsClientRuleList rules;
+  std::vector<DnsResourceRecord> records = {
+      BuildTestDnsRecord(kName, dns_protocol::kTypeHttps, "" /* rdata */)};
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, true /* secure */,
+                     MockDnsClientRule::Result(BuildTestDnsResponse(
+                         kName, dns_protocol::kTypeHttps, records)),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeAAAA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+  DnsConfigOverrides overrides;
+  overrides.secure_dns_mode = SecureDnsMode::kSecure;
+  resolver_->SetDnsConfigOverrides(overrides);
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      base::nullopt, resolve_context_.get(), resolve_context_->host_cache()));
+  EXPECT_THAT(response.result_error(), IsOk());
+  EXPECT_TRUE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_AddressesOnly) {
+  const char kName[] = "combined.test";
+
+  base::test::ScopedFeatureList features;
+  features.InitAndEnableFeatureWithParameters(
+      features::kDnsHttpssvc, {{"DnsHttpssvcUseHttpssvc", "true"},
+                               {"DnsHttpssvcExperimentDomains", kName}});
+
+  MockDnsClientRuleList rules;
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::EMPTY),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeAAAA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+  DnsConfigOverrides overrides;
+  overrides.secure_dns_mode = SecureDnsMode::kSecure;
+  resolver_->SetDnsConfigOverrides(overrides);
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      base::nullopt, resolve_context_.get(), resolve_context_->host_cache()));
+  EXPECT_THAT(response.result_error(), IsOk());
+  EXPECT_TRUE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_HttpsOnly) {
+  const char kName[] = "combined.test";
+
+  base::test::ScopedFeatureList features;
+  features.InitAndEnableFeatureWithParameters(
+      features::kDnsHttpssvc, {{"DnsHttpssvcUseHttpssvc", "true"},
+                               {"DnsHttpssvcExperimentDomains", kName}});
+
+  MockDnsClientRuleList rules;
+  std::vector<DnsResourceRecord> records = {
+      BuildTestDnsRecord(kName, dns_protocol::kTypeHttps, "" /* rdata */)};
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, true /* secure */,
+                     MockDnsClientRule::Result(BuildTestDnsResponse(
+                         kName, dns_protocol::kTypeHttps, records)),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::EMPTY),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeAAAA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::EMPTY),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+  DnsConfigOverrides overrides;
+  overrides.secure_dns_mode = SecureDnsMode::kSecure;
+  resolver_->SetDnsConfigOverrides(overrides);
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      base::nullopt, resolve_context_.get(), resolve_context_->host_cache()));
+  EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+  EXPECT_FALSE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_AddressError) {
+  const char kName[] = "combined.test";
+
+  base::test::ScopedFeatureList features;
+  features.InitAndEnableFeatureWithParameters(
+      features::kDnsHttpssvc, {{"DnsHttpssvcUseHttpssvc", "true"},
+                               {"DnsHttpssvcExperimentDomains", kName}});
+
+  MockDnsClientRuleList rules;
+  std::vector<DnsResourceRecord> records = {
+      BuildTestDnsRecord(kName, dns_protocol::kTypeHttps, "" /* rdata */)};
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, true /* secure */,
+                     MockDnsClientRule::Result(BuildTestDnsResponse(
+                         kName, dns_protocol::kTypeHttps, records)),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::FAIL),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeAAAA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::FAIL),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+  DnsConfigOverrides overrides;
+  overrides.secure_dns_mode = SecureDnsMode::kSecure;
+  resolver_->SetDnsConfigOverrides(overrides);
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      base::nullopt, resolve_context_.get(), resolve_context_->host_cache()));
+  EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+  EXPECT_FALSE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_HttpsError) {
+  const char kName[] = "combined.test";
+
+  base::test::ScopedFeatureList features;
+  features.InitAndEnableFeatureWithParameters(
+      features::kDnsHttpssvc, {{"DnsHttpssvcUseHttpssvc", "true"},
+                               {"DnsHttpssvcExperimentDomains", kName}});
+
+  MockDnsClientRuleList rules;
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::FAIL),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeAAAA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+  DnsConfigOverrides overrides;
+  overrides.secure_dns_mode = SecureDnsMode::kSecure;
+  resolver_->SetDnsConfigOverrides(overrides);
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      base::nullopt, resolve_context_.get(), resolve_context_->host_cache()));
+  EXPECT_THAT(response.result_error(), IsOk());
+  EXPECT_TRUE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_NoData) {
+  const char kName[] = "combined.test";
+
+  base::test::ScopedFeatureList features;
+  features.InitAndEnableFeatureWithParameters(
+      features::kDnsHttpssvc, {{"DnsHttpssvcUseHttpssvc", "true"},
+                               {"DnsHttpssvcExperimentDomains", kName}});
+
+  MockDnsClientRuleList rules;
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::EMPTY),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::EMPTY),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeAAAA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::EMPTY),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+  DnsConfigOverrides overrides;
+  overrides.secure_dns_mode = SecureDnsMode::kSecure;
+  resolver_->SetDnsConfigOverrides(overrides);
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      base::nullopt, resolve_context_.get(), resolve_context_->host_cache()));
+  EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+  EXPECT_FALSE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_HttpsLast) {
+  const char kName[] = "combined.test";
+
+  base::test::ScopedFeatureList features;
+  features.InitAndEnableFeatureWithParameters(
+      features::kDnsHttpssvc, {{"DnsHttpssvcUseHttpssvc", "true"},
+                               {"DnsHttpssvcExperimentDomains", kName}});
+
+  MockDnsClientRuleList rules;
+  std::vector<DnsResourceRecord> records = {
+      BuildTestDnsRecord(kName, dns_protocol::kTypeHttps, "" /* rdata */)};
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, true /* secure */,
+                     MockDnsClientRule::Result(BuildTestDnsResponse(
+                         kName, dns_protocol::kTypeHttps, records)),
+                     true /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeAAAA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+  DnsConfigOverrides overrides;
+  overrides.secure_dns_mode = SecureDnsMode::kSecure;
+  resolver_->SetDnsConfigOverrides(overrides);
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      base::nullopt, resolve_context_.get(), resolve_context_->host_cache()));
+
+  base::RunLoop().RunUntilIdle();
+  ASSERT_FALSE(response.complete());
+
+  ASSERT_TRUE(
+      dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::HTTPS));
+
+  EXPECT_THAT(response.result_error(), IsOk());
+  EXPECT_TRUE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_AddressesLast) {
+  const char kName[] = "combined.test";
+
+  base::test::ScopedFeatureList features;
+  features.InitAndEnableFeatureWithParameters(
+      features::kDnsHttpssvc, {{"DnsHttpssvcUseHttpssvc", "true"},
+                               {"DnsHttpssvcExperimentDomains", kName}});
+
+  MockDnsClientRuleList rules;
+  std::vector<DnsResourceRecord> records = {
+      BuildTestDnsRecord(kName, dns_protocol::kTypeHttps, "" /* rdata */)};
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, true /* secure */,
+                     MockDnsClientRule::Result(BuildTestDnsResponse(
+                         kName, dns_protocol::kTypeHttps, records)),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     true /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeAAAA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     true /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+  DnsConfigOverrides overrides;
+  overrides.secure_dns_mode = SecureDnsMode::kSecure;
+  resolver_->SetDnsConfigOverrides(overrides);
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      base::nullopt, resolve_context_.get(), resolve_context_->host_cache()));
+
+  base::RunLoop().RunUntilIdle();
+  ASSERT_FALSE(response.complete());
+
+  ASSERT_TRUE(
+      dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::A));
+  ASSERT_TRUE(
+      dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::AAAA));
+
+  EXPECT_THAT(response.result_error(), IsOk());
+  EXPECT_TRUE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_Insecure) {
+  const char kName[] = "combined.test";
+
+  base::test::ScopedFeatureList features;
+  features.InitAndEnableFeatureWithParameters(
+      features::kDnsHttpssvc, {{"DnsHttpssvcUseHttpssvc", "true"},
+                               {"DnsHttpssvcExperimentDomains", kName}});
+
+  MockDnsClientRuleList rules;
+  // No expected HTTPS request in insecure mode.
+  rules.emplace_back(kName, dns_protocol::kTypeA, false /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeAAAA, false /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+  DnsConfigOverrides overrides;
+  overrides.secure_dns_mode = SecureDnsMode::kOff;
+  resolver_->SetDnsConfigOverrides(overrides);
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      base::nullopt, resolve_context_.get(), resolve_context_->host_cache()));
+
+  EXPECT_THAT(response.result_error(), IsOk());
+  EXPECT_TRUE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_ExperimentalTimeout) {
+  const char kName[] = "combined.test";
+  const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(2);
+
+  base::test::ScopedFeatureList features;
+  features.InitAndEnableFeatureWithParameters(
+      features::kDnsHttpssvc,
+      {{"DnsHttpssvcUseHttpssvc", "true"},
+       {"DnsHttpssvcExperimentDomains", kName},
+       {"DnsHttpssvcExtraTimeMs",
+        base::NumberToString(kTimeout.InMilliseconds())}});
+
+  MockDnsClientRuleList rules;
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::FAIL),
+                     true /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeAAAA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+  DnsConfigOverrides overrides;
+  overrides.secure_dns_mode = SecureDnsMode::kSecure;
+  resolver_->SetDnsConfigOverrides(overrides);
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      base::nullopt, resolve_context_.get(), resolve_context_->host_cache()));
+
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(response.complete());
+
+  FastForwardBy(kTimeout);
+  EXPECT_TRUE(response.complete());
+
+  EXPECT_THAT(response.result_error(), IsOk());
+  EXPECT_TRUE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, MultipleExperimentalQueries) {
+  const char kName[] = "combined.test";
+
+  base::test::ScopedFeatureList features;
+  features.InitAndEnableFeatureWithParameters(
+      features::kDnsHttpssvc, {{"DnsHttpssvcUseHttpssvc", "true"},
+                               {"DnsHttpssvcUseIntegrity", "true"},
+                               {"DnsHttpssvcExperimentDomains", kName}});
+
+  MockDnsClientRuleList rules;
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::EMPTY),
+                     false /* delay */);
+  rules.emplace_back(
+      kName, dns_protocol::kExperimentalTypeIntegrity, true /* secure */,
+      MockDnsClientRule::Result(MockDnsClientRule::EMPTY), false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeAAAA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+  DnsConfigOverrides overrides;
+  overrides.secure_dns_mode = SecureDnsMode::kSecure;
+  resolver_->SetDnsConfigOverrides(overrides);
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      base::nullopt, resolve_context_.get(), resolve_context_->host_cache()));
+  EXPECT_THAT(response.result_error(), IsOk());
+  EXPECT_TRUE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_TRUE(response.request()->GetIntegrityResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, MultipleExperimentalQueries_Timeout) {
+  const char kName[] = "combined.test";
+  const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(2);
+
+  base::test::ScopedFeatureList features;
+  features.InitAndEnableFeatureWithParameters(
+      features::kDnsHttpssvc,
+      {{"DnsHttpssvcUseHttpssvc", "true"},
+       {"DnsHttpssvcUseIntegrity", "true"},
+       {"DnsHttpssvcExperimentDomains", kName},
+       {"DnsHttpssvcExtraTimeMs",
+        base::NumberToString(kTimeout.InMilliseconds())}});
+
+  MockDnsClientRuleList rules;
+  rules.emplace_back(kName, dns_protocol::kTypeHttps, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::EMPTY),
+                     true /* delay */);
+  rules.emplace_back(
+      kName, dns_protocol::kExperimentalTypeIntegrity, true /* secure */,
+      MockDnsClientRule::Result(MockDnsClientRule::EMPTY), true /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     false /* delay */);
+  rules.emplace_back(kName, dns_protocol::kTypeAAAA, true /* secure */,
+                     MockDnsClientRule::Result(MockDnsClientRule::OK),
+                     false /* delay */);
+
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+  DnsConfigOverrides overrides;
+  overrides.secure_dns_mode = SecureDnsMode::kSecure;
+  resolver_->SetDnsConfigOverrides(overrides);
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
+      base::nullopt, resolve_context_.get(), resolve_context_->host_cache()));
+
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(response.complete());
+
+  FastForwardBy(kTimeout);
+  EXPECT_TRUE(response.complete());
+
+  EXPECT_THAT(response.result_error(), IsOk());
+  EXPECT_TRUE(response.request()->GetAddressResults());
+  EXPECT_FALSE(response.request()->GetTextResults());
+  EXPECT_FALSE(response.request()->GetHostnameResults());
+  EXPECT_FALSE(response.request()->GetIntegrityResultsForTesting());
+}
+
 class HostResolverManagerDnsTestIntegrity : public HostResolverManagerDnsTest {
  public:
   HostResolverManagerDnsTestIntegrity()
diff --git a/net/dns/host_resolver_mdns_listener_impl.cc b/net/dns/host_resolver_mdns_listener_impl.cc
index 066cc63..0287be7 100644
--- a/net/dns/host_resolver_mdns_listener_impl.cc
+++ b/net/dns/host_resolver_mdns_listener_impl.cc
@@ -74,6 +74,7 @@
   switch (query_type_) {
     case DnsQueryType::UNSPECIFIED:
     case DnsQueryType::INTEGRITY:
+    case DnsQueryType::HTTPS:
       NOTREACHED();
       break;
     case DnsQueryType::A:
diff --git a/net/dns/host_resolver_mdns_task.cc b/net/dns/host_resolver_mdns_task.cc
index 745b847ee..687b957 100644
--- a/net/dns/host_resolver_mdns_task.cc
+++ b/net/dns/host_resolver_mdns_task.cc
@@ -198,6 +198,10 @@
   switch (query_type) {
     case DnsQueryType::UNSPECIFIED:
       // Should create two separate transactions with specified type.
+    case DnsQueryType::HTTPS:
+      // Not supported.
+      // TODO(ericorth@chromium.org): Consider support for HTTPS in mDNS if it
+      // is ever decided to support HTTPS via non-DoH.
     case DnsQueryType::INTEGRITY:
       // INTEGRITY queries are not expected to be useful in mDNS, so they're not
       // supported.
diff --git a/net/dns/httpssvc_metrics.cc b/net/dns/httpssvc_metrics.cc
index 58a033a..68e02192 100644
--- a/net/dns/httpssvc_metrics.cc
+++ b/net/dns/httpssvc_metrics.cc
@@ -116,6 +116,12 @@
   integrity_resolve_time_ = integrity_resolve_time;
 }
 
+void HttpssvcMetrics::SaveForHttps(base::Optional<std::string> doh_provider_id,
+                                   enum HttpssvcDnsRcode rcode,
+                                   base::TimeDelta https_resolve_time) {
+  // TODO(crbug.com/1138620): Implement.
+}
+
 void HttpssvcMetrics::set_doh_provider_id(
     base::Optional<std::string> new_doh_provider_id) {
   // "Other" never gets updated.
@@ -150,7 +156,8 @@
   // The HTTPSSVC experiment and its feature param indicating INTEGRITY must
   // both be enabled.
   DCHECK(base::FeatureList::IsEnabled(features::kDnsHttpssvc));
-  DCHECK(features::kDnsHttpssvcUseIntegrity.Get());
+  DCHECK(features::kDnsHttpssvcUseIntegrity.Get() ||
+         features::kDnsHttpssvcUseHttpssvc.Get());
 
   DCHECK(!already_recorded_);
   already_recorded_ = true;
diff --git a/net/dns/httpssvc_metrics.h b/net/dns/httpssvc_metrics.h
index 8594b7c..d6b632af 100644
--- a/net/dns/httpssvc_metrics.h
+++ b/net/dns/httpssvc_metrics.h
@@ -81,6 +81,9 @@
                         enum HttpssvcDnsRcode rcode,
                         const std::vector<bool>& condensed_records,
                         base::TimeDelta integrity_resolve_time);
+  void SaveForHttps(base::Optional<std::string> doh_provider_id,
+                    enum HttpssvcDnsRcode rcode,
+                    base::TimeDelta https_resolve_time);
 
  private:
   std::string BuildMetricName(base::StringPiece leaf_name) const;
diff --git a/net/dns/public/dns_protocol.h b/net/dns/public/dns_protocol.h
index c77dbaa..3c1757e 100644
--- a/net/dns/public/dns_protocol.h
+++ b/net/dns/public/dns_protocol.h
@@ -149,6 +149,7 @@
 static const uint16_t kTypeSRV = 33;
 static const uint16_t kTypeOPT = 41;
 static const uint16_t kTypeNSEC = 47;
+static const uint16_t kTypeHttps = 65;
 static const uint16_t kTypeANY = 255;
 
 // Experimental DNS record types pending IANA assignment.
diff --git a/net/dns/public/dns_query_type.h b/net/dns/public/dns_query_type.h
index ecc61ea..11aa0b69 100644
--- a/net/dns/public/dns_query_type.h
+++ b/net/dns/public/dns_query_type.h
@@ -21,14 +21,14 @@
   PTR,
   SRV,
   INTEGRITY,
-  MAX = INTEGRITY
+  HTTPS,
+  MAX = HTTPS
 };
 
 const DnsQueryType kDnsQueryTypes[] = {
-    DnsQueryType::UNSPECIFIED, DnsQueryType::A,   DnsQueryType::AAAA,
-    DnsQueryType::TXT,         DnsQueryType::PTR, DnsQueryType::SRV,
-    DnsQueryType::INTEGRITY,
-};
+    DnsQueryType::UNSPECIFIED, DnsQueryType::A,    DnsQueryType::AAAA,
+    DnsQueryType::TXT,         DnsQueryType::PTR,  DnsQueryType::SRV,
+    DnsQueryType::INTEGRITY,   DnsQueryType::HTTPS};
 
 static_assert(base::size(kDnsQueryTypes) ==
                   static_cast<unsigned>(DnsQueryType::MAX) + 1,
diff --git a/net/dns/record_rdata.cc b/net/dns/record_rdata.cc
index 08d89d4f..c25a253 100644
--- a/net/dns/record_rdata.cc
+++ b/net/dns/record_rdata.cc
@@ -35,6 +35,9 @@
       return data.size() == IPAddress::kIPv6AddressSize;
     case dns_protocol::kExperimentalTypeIntegrity:
       return data.size() >= kIntegrityMinimumSize;
+    case dns_protocol::kTypeHttps:
+      // TODO(crbug.com/1138620): Implement actual size minimum.
+      return data.size() == 0;
     case dns_protocol::kTypeCNAME:
     case dns_protocol::kTypePTR:
     case dns_protocol::kTypeTXT:
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 44104427..ed0d8fe 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -1340,7 +1340,9 @@
   if (IsCertStatusError(response_.ssl_info.cert_status))
     return;
 
-  service->ProcessHeader(url_.GetOrigin(), value);
+  // TODO(https://crbug.com/993805):  Pass in the NetworkIsolationKey.
+  service->ProcessHeader(url_.GetOrigin(), net::NetworkIsolationKey::Todo(),
+                         value);
 }
 
 void HttpNetworkTransaction::ProcessNetworkErrorLoggingHeader() {
diff --git a/net/network_error_logging/network_error_logging_service.cc b/net/network_error_logging/network_error_logging_service.cc
index c63d8e9..35bd88f8 100644
--- a/net/network_error_logging/network_error_logging_service.cc
+++ b/net/network_error_logging/network_error_logging_service.cc
@@ -460,8 +460,11 @@
              << ", status=" << details.status_code
              << ", depth=" << details.reporting_upload_depth << ") for "
              << details.uri;
+
+    // TODO(https://crbug.com/993805): Pass in a NetworkIsolationKey.
     reporting_service_->QueueReport(
-        details.uri, details.user_agent, policy->report_to, kReportType,
+        details.uri, NetworkIsolationKey::Todo(), details.user_agent,
+        policy->report_to, kReportType,
         CreateReportBody(phase_string, type_string, sampling_fraction.value(),
                          details),
         details.reporting_upload_depth);
@@ -505,8 +508,11 @@
                           : RequestOutcome::kDiscardedUnsampledFailure);
       return;
     }
+
+    // TODO(https://crbug.com/993805): Pass in a NetworkIsolationKey.
     reporting_service_->QueueReport(
-        details.outer_url, details.user_agent, policy->report_to, kReportType,
+        details.outer_url, NetworkIsolationKey::Todo(), details.user_agent,
+        policy->report_to, kReportType,
         CreateSignedExchangeReportBody(details, sampling_fraction.value()),
         0 /* depth */);
     RecordSignedExchangeRequestOutcome(RequestOutcome::kQueued);
diff --git a/net/nqe/network_quality_estimator_unittest.cc b/net/nqe/network_quality_estimator_unittest.cc
index 92a2076..84469b30 100644
--- a/net/nqe/network_quality_estimator_unittest.cc
+++ b/net/nqe/network_quality_estimator_unittest.cc
@@ -20,6 +20,7 @@
 #include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/task/thread_pool/thread_pool_instance.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "base/threading/platform_thread.h"
@@ -67,6 +68,20 @@
       << " expected_min_count_samples=" << expected_min_count_samples;
 }
 
+size_t GetHistogramCount(base::HistogramTester* histogram_tester,
+                         const std::string& histogram_name) {
+  base::ThreadPoolInstance::Get()->FlushForTesting();
+  base::RunLoop().RunUntilIdle();
+
+  const std::vector<base::Bucket> buckets =
+      histogram_tester->GetAllSamples(histogram_name);
+  size_t total_count = 0;
+  for (const auto& bucket : buckets) {
+    total_count += bucket.count;
+  }
+  return total_count;
+}
+
 }  // namespace
 
 namespace net {
@@ -3124,18 +3139,22 @@
   histogram_tester.ExpectTotalCount(histogram_name, 3);
 
   // Changing the connection type should make the signal strength available
-  // again.
+  // again. Verify that the signal strength is not queried too frequently
+  // (currently, the threshold is set to 5). This is partially indeterminsitic
+  // due to the indeterminism at the connection change.
   estimator.SimulateNetworkChange(
       NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test");
-  histogram_tester.ExpectTotalCount(histogram_name, 5);
+  size_t samples_count = GetHistogramCount(&histogram_tester, histogram_name);
+  EXPECT_LE(4u, samples_count);
+  EXPECT_GE(8u, samples_count);
 
   tick_clock.Advance(base::TimeDelta::FromMilliseconds(2));
   signal_strength = estimator.GetCurrentSignalStrengthWithThrottling();
-  histogram_tester.ExpectTotalCount(histogram_name, 6);
+  histogram_tester.ExpectTotalCount(histogram_name, samples_count + 1);
 
   tick_clock.Advance(base::TimeDelta::FromMilliseconds(2));
   signal_strength = estimator.GetCurrentSignalStrengthWithThrottling();
-  histogram_tester.ExpectTotalCount(histogram_name, 6);
+  histogram_tester.ExpectTotalCount(histogram_name, samples_count + 1);
 }
 
 TEST_F(NetworkQualityEstimatorTest, CheckSignalStrengthDisabledByDefault) {
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc
index 978011da..a5802a5 100644
--- a/net/quic/quic_chromium_client_session.cc
+++ b/net/quic/quic_chromium_client_session.cc
@@ -1868,6 +1868,8 @@
         "Net.QuicSession.ConnectionDuration",
         tick_clock_->NowTicks() - connect_timing_.connect_end);
     UMA_HISTOGRAM_COUNTS_100("Net.QuicSession.NumMigrations", num_migrations_);
+    base::UmaHistogramCounts100("Net.QuicSession.KeyUpdate.PerConnection",
+                                connection()->GetStats().key_update_count);
   } else {
     if (error == quic::QUIC_PUBLIC_RESET) {
       RecordHandshakeFailureReason(HANDSHAKE_FAILURE_PUBLIC_RESET);
diff --git a/net/reporting/reporting_service.cc b/net/reporting/reporting_service.cc
index ca44492..55332f9 100644
--- a/net/reporting/reporting_service.cc
+++ b/net/reporting/reporting_service.cc
@@ -52,6 +52,7 @@
   }
 
   void QueueReport(const GURL& url,
+                   const NetworkIsolationKey& network_isolation_key,
                    const std::string& user_agent,
                    const std::string& group,
                    const std::string& type,
@@ -72,8 +73,6 @@
 
     // base::Unretained is safe because the callback is stored in
     // |task_backlog_| which will not outlive |this|.
-    // TODO(chlily): Get NetworkIsolationKey from caller.
-    NetworkIsolationKey network_isolation_key = NetworkIsolationKey::Todo();
     DoOrBacklogTask(base::BindOnce(
         &ReportingServiceImpl::DoQueueReport, base::Unretained(this),
         network_isolation_key, std::move(sanitized_url), user_agent, group,
@@ -81,6 +80,7 @@
   }
 
   void ProcessHeader(const GURL& url,
+                     const NetworkIsolationKey& network_isolation_key,
                      const std::string& header_string) override {
     if (header_string.size() > kMaxJsonSize)
       return;
@@ -92,10 +92,9 @@
       return;
 
     DVLOG(1) << "Received Reporting policy for " << url.GetOrigin();
-    // TODO(chlily): Get the proper NetworkIsolationKey from the caller.
     DoOrBacklogTask(base::BindOnce(
         &ReportingServiceImpl::DoProcessHeader, base::Unretained(this),
-        NetworkIsolationKey::Todo(), url, std::move(header_value)));
+        network_isolation_key, url, std::move(header_value)));
   }
 
   void RemoveBrowsingData(uint64_t data_type_mask,
diff --git a/net/reporting/reporting_service.h b/net/reporting/reporting_service.h
index e215236..b32b3fd 100644
--- a/net/reporting/reporting_service.h
+++ b/net/reporting/reporting_service.h
@@ -21,6 +21,7 @@
 
 namespace net {
 
+class NetworkIsolationKey;
 class ReportingContext;
 struct ReportingPolicy;
 class URLRequestContext;
@@ -47,6 +48,8 @@
       std::unique_ptr<ReportingContext> reporting_context);
 
   // Queues a report for delivery. |url| is the URL that originated the report.
+  // |network_isolation_key| is used to restrict what reports can be merged, and
+  // for sending the report.
   // |user_agent| is the User-Agent header that was used for the request.
   // |group| is the endpoint group to which the report should be delivered.
   // |type| is the type of the report. |body| is the body of the report.
@@ -54,6 +57,7 @@
   // The Reporting system will take ownership of |body|; all other parameters
   // will be copied.
   virtual void QueueReport(const GURL& url,
+                           const NetworkIsolationKey& network_isolation_key,
                            const std::string& user_agent,
                            const std::string& group,
                            const std::string& type,
@@ -63,6 +67,7 @@
   // Processes a Report-To header. |url| is the URL that originated the header;
   // |header_value| is the normalized value of the Report-To header.
   virtual void ProcessHeader(const GURL& url,
+                             const NetworkIsolationKey& network_isolation_key,
                              const std::string& header_value) = 0;
 
   // Removes browsing data from the Reporting system. See
diff --git a/net/reporting/reporting_service_unittest.cc b/net/reporting/reporting_service_unittest.cc
index 0ac00ac44..614a7ee9 100644
--- a/net/reporting/reporting_service_unittest.cc
+++ b/net/reporting/reporting_service_unittest.cc
@@ -43,10 +43,12 @@
   const std::string kUserAgent_ = "Mozilla/1.0";
   const std::string kGroup_ = "group";
   const std::string kType_ = "type";
+  const NetworkIsolationKey kNik_ = NetworkIsolationKey(kOrigin_, kOrigin_);
+  const NetworkIsolationKey kNik2_ = NetworkIsolationKey(kOrigin2_, kOrigin2_);
   const ReportingEndpointGroupKey kGroupKey_ =
-      ReportingEndpointGroupKey(NetworkIsolationKey(), kOrigin_, kGroup_);
+      ReportingEndpointGroupKey(kNik_, kOrigin_, kGroup_);
   const ReportingEndpointGroupKey kGroupKey2_ =
-      ReportingEndpointGroupKey(NetworkIsolationKey(), kOrigin2_, kGroup_);
+      ReportingEndpointGroupKey(kNik2_, kOrigin2_, kGroup_);
 
   ReportingServiceTest() {
     if (GetParam())
@@ -82,7 +84,7 @@
 };
 
 TEST_P(ReportingServiceTest, QueueReport) {
-  service()->QueueReport(kUrl_, kUserAgent_, kGroup_, kType_,
+  service()->QueueReport(kUrl_, kNik_, kUserAgent_, kGroup_, kType_,
                          std::make_unique<base::DictionaryValue>(), 0);
   FinishLoading(true /* load_success */);
 
@@ -90,6 +92,7 @@
   context()->cache()->GetReports(&reports);
   ASSERT_EQ(1u, reports.size());
   EXPECT_EQ(kUrl_, reports[0]->url);
+  EXPECT_EQ(kNik_, reports[0]->network_isolation_key);
   EXPECT_EQ(kUserAgent_, reports[0]->user_agent);
   EXPECT_EQ(kGroup_, reports[0]->group);
   EXPECT_EQ(kType_, reports[0]->type);
@@ -98,7 +101,7 @@
 TEST_P(ReportingServiceTest, QueueReportSanitizeUrl) {
   // Same as kUrl_ but with username, password, and fragment.
   GURL url = GURL("https://username:password@origin/path#fragment");
-  service()->QueueReport(url, kUserAgent_, kGroup_, kType_,
+  service()->QueueReport(url, kNik_, kUserAgent_, kGroup_, kType_,
                          std::make_unique<base::DictionaryValue>(), 0);
   FinishLoading(true /* load_success */);
 
@@ -106,6 +109,7 @@
   context()->cache()->GetReports(&reports);
   ASSERT_EQ(1u, reports.size());
   EXPECT_EQ(kUrl_, reports[0]->url);
+  EXPECT_EQ(kNik_, reports[0]->network_isolation_key);
   EXPECT_EQ(kUserAgent_, reports[0]->user_agent);
   EXPECT_EQ(kGroup_, reports[0]->group);
   EXPECT_EQ(kType_, reports[0]->type);
@@ -115,7 +119,7 @@
   GURL url = GURL("https://");
   // This does not trigger an attempt to load from the store because the url
   // is immediately rejected as invalid.
-  service()->QueueReport(url, kUserAgent_, kGroup_, kType_,
+  service()->QueueReport(url, kNik_, kUserAgent_, kGroup_, kType_,
                          std::make_unique<base::DictionaryValue>(), 0);
 
   std::vector<const ReportingReport*> reports;
@@ -124,20 +128,20 @@
 }
 
 TEST_P(ReportingServiceTest, ProcessHeader) {
-  service()->ProcessHeader(kUrl_, "{\"endpoints\":[{\"url\":\"" +
-                                      kEndpoint_.spec() +
-                                      "\"}],"
-                                      "\"group\":\"" +
-                                      kGroup_ +
-                                      "\","
-                                      "\"max_age\":86400}");
+  service()->ProcessHeader(kUrl_, kNik_,
+                           "{\"endpoints\":[{\"url\":\"" + kEndpoint_.spec() +
+                               "\"}],"
+                               "\"group\":\"" +
+                               kGroup_ +
+                               "\","
+                               "\"max_age\":86400}");
   FinishLoading(true /* load_success */);
 
   EXPECT_EQ(1u, context()->cache()->GetEndpointCount());
 }
 
 TEST_P(ReportingServiceTest, ProcessHeaderPathAbsolute) {
-  service()->ProcessHeader(kUrl_,
+  service()->ProcessHeader(kUrl_, kNik_,
                            "{\"endpoints\":[{\"url\":\"/path-absolute\"}],"
                            "\"group\":\"" +
                                kGroup_ +
@@ -159,7 +163,7 @@
       "\"junk\":\"" + std::string(32 * 1024, 'a') + "\"}";
   // This does not trigger an attempt to load from the store because the header
   // is immediately rejected as invalid.
-  service()->ProcessHeader(kUrl_, header_too_long);
+  service()->ProcessHeader(kUrl_, kNik_, header_too_long);
 
   EXPECT_EQ(0u, context()->cache()->GetEndpointCount());
 }
@@ -175,7 +179,7 @@
                                       "\"junk\":[[[[[[[[[[]]]]]]]]]]}";
   // This does not trigger an attempt to load from the store because the header
   // is immediately rejected as invalid.
-  service()->ProcessHeader(kUrl_, header_too_deep);
+  service()->ProcessHeader(kUrl_, kNik_, header_too_deep);
 
   EXPECT_EQ(0u, context()->cache()->GetEndpointCount());
 }
@@ -188,13 +192,13 @@
 
   // This first call to any public method triggers a load. The load will block
   // until we call FinishLoading.
-  service()->ProcessHeader(kUrl_, "{\"endpoints\":[{\"url\":\"" +
-                                      kEndpoint_.spec() +
-                                      "\"}],"
-                                      "\"group\":\"" +
-                                      kGroup_ +
-                                      "\","
-                                      "\"max_age\":86400}");
+  service()->ProcessHeader(kUrl_, kNik_,
+                           "{\"endpoints\":[{\"url\":\"" + kEndpoint_.spec() +
+                               "\"}],"
+                               "\"group\":\"" +
+                               kGroup_ +
+                               "\","
+                               "\"max_age\":86400}");
   expected_commands.emplace_back(CommandType::LOAD_REPORTING_CLIENTS);
   EXPECT_THAT(store()->GetAllCommands(),
               testing::UnorderedElementsAreArray(expected_commands));
@@ -209,13 +213,13 @@
   EXPECT_THAT(store()->GetAllCommands(),
               testing::UnorderedElementsAreArray(expected_commands));
 
-  service()->ProcessHeader(kUrl2_, "{\"endpoints\":[{\"url\":\"" +
-                                       kEndpoint_.spec() +
-                                       "\"}],"
-                                       "\"group\":\"" +
-                                       kGroup_ +
-                                       "\","
-                                       "\"max_age\":86400}");
+  service()->ProcessHeader(kUrl2_, kNik2_,
+                           "{\"endpoints\":[{\"url\":\"" + kEndpoint_.spec() +
+                               "\"}],"
+                               "\"group\":\"" +
+                               kGroup_ +
+                               "\","
+                               "\"max_age\":86400}");
   expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT,
                                  kGroupKey2_, kEndpoint_);
   expected_commands.emplace_back(CommandType::ADD_REPORTING_ENDPOINT_GROUP,
@@ -223,7 +227,7 @@
   EXPECT_THAT(store()->GetAllCommands(),
               testing::UnorderedElementsAreArray(expected_commands));
 
-  service()->QueueReport(kUrl_, kUserAgent_, kGroup_, kType_,
+  service()->QueueReport(kUrl_, kNik_, kUserAgent_, kGroup_, kType_,
                          std::make_unique<base::DictionaryValue>(), 0);
   expected_commands.emplace_back(
       CommandType::UPDATE_REPORTING_ENDPOINT_GROUP_ACCESS_TIME, kGroupKey_);
@@ -261,28 +265,28 @@
 
   // This first call to any public method triggers a load. The load will block
   // until we call FinishLoading.
-  service()->ProcessHeader(kUrl_, "{\"endpoints\":[{\"url\":\"" +
-                                      kEndpoint_.spec() +
-                                      "\"}],"
-                                      "\"group\":\"" +
-                                      kGroup_ +
-                                      "\","
-                                      "\"max_age\":86400}");
+  service()->ProcessHeader(kUrl_, kNik_,
+                           "{\"endpoints\":[{\"url\":\"" + kEndpoint_.spec() +
+                               "\"}],"
+                               "\"group\":\"" +
+                               kGroup_ +
+                               "\","
+                               "\"max_age\":86400}");
   expected_commands.emplace_back(CommandType::LOAD_REPORTING_CLIENTS);
   EXPECT_THAT(store()->GetAllCommands(),
               testing::UnorderedElementsAreArray(expected_commands));
 
-  service()->ProcessHeader(kUrl2_, "{\"endpoints\":[{\"url\":\"" +
-                                       kEndpoint_.spec() +
-                                       "\"}],"
-                                       "\"group\":\"" +
-                                       kGroup_ +
-                                       "\","
-                                       "\"max_age\":86400}");
+  service()->ProcessHeader(kUrl2_, kNik2_,
+                           "{\"endpoints\":[{\"url\":\"" + kEndpoint_.spec() +
+                               "\"}],"
+                               "\"group\":\"" +
+                               kGroup_ +
+                               "\","
+                               "\"max_age\":86400}");
   EXPECT_THAT(store()->GetAllCommands(),
               testing::UnorderedElementsAreArray(expected_commands));
 
-  service()->QueueReport(kUrl_, kUserAgent_, kGroup_, kType_,
+  service()->QueueReport(kUrl_, kNik_, kUserAgent_, kGroup_, kType_,
                          std::make_unique<base::DictionaryValue>(), 0);
   EXPECT_THAT(store()->GetAllCommands(),
               testing::UnorderedElementsAreArray(expected_commands));
diff --git a/net/reporting/reporting_test_util.cc b/net/reporting/reporting_test_util.cc
index fc3b015..a3418fd 100644
--- a/net/reporting/reporting_test_util.cc
+++ b/net/reporting/reporting_test_util.cc
@@ -299,13 +299,16 @@
       body(std::move(other.body)),
       depth(other.depth) {}
 
-TestReportingService::Report::Report(const GURL& url,
-                                     const std::string& user_agent,
-                                     const std::string& group,
-                                     const std::string& type,
-                                     std::unique_ptr<const base::Value> body,
-                                     int depth)
+TestReportingService::Report::Report(
+    const GURL& url,
+    const NetworkIsolationKey& network_isolation_key,
+    const std::string& user_agent,
+    const std::string& group,
+    const std::string& type,
+    std::unique_ptr<const base::Value> body,
+    int depth)
     : url(url),
+      network_isolation_key(network_isolation_key),
       user_agent(user_agent),
       group(group),
       type(type),
@@ -318,18 +321,22 @@
 
 TestReportingService::~TestReportingService() = default;
 
-void TestReportingService::QueueReport(const GURL& url,
-                                       const std::string& user_agent,
-                                       const std::string& group,
-                                       const std::string& type,
-                                       std::unique_ptr<const base::Value> body,
-                                       int depth) {
-  reports_.push_back(
-      Report(url, user_agent, group, type, std::move(body), depth));
+void TestReportingService::QueueReport(
+    const GURL& url,
+    const NetworkIsolationKey& network_isolation_key,
+    const std::string& user_agent,
+    const std::string& group,
+    const std::string& type,
+    std::unique_ptr<const base::Value> body,
+    int depth) {
+  reports_.emplace_back(Report(url, network_isolation_key, user_agent, group,
+                               type, std::move(body), depth));
 }
 
-void TestReportingService::ProcessHeader(const GURL& url,
-                                         const std::string& header_value) {
+void TestReportingService::ProcessHeader(
+    const GURL& url,
+    const NetworkIsolationKey& network_isolation_key,
+    const std::string& header_value) {
   NOTREACHED();
 }
 
diff --git a/net/reporting/reporting_test_util.h b/net/reporting/reporting_test_util.h
index e58f4491..2c5c312 100644
--- a/net/reporting/reporting_test_util.h
+++ b/net/reporting/reporting_test_util.h
@@ -13,6 +13,7 @@
 #include "base/macros.h"
 #include "base/test/simple_test_clock.h"
 #include "base/test/simple_test_tick_clock.h"
+#include "net/base/network_isolation_key.h"
 #include "net/base/rand_callback.h"
 #include "net/reporting/reporting_cache.h"
 #include "net/reporting/reporting_context.h"
@@ -283,6 +284,7 @@
     Report(Report&& other);
 
     Report(const GURL& url,
+           const NetworkIsolationKey& network_isolation_key,
            const std::string& user_agent,
            const std::string& group,
            const std::string& type,
@@ -292,6 +294,7 @@
     ~Report();
 
     GURL url;
+    NetworkIsolationKey network_isolation_key;
     std::string user_agent;
     std::string group;
     std::string type;
@@ -311,13 +314,16 @@
   ~TestReportingService() override;
 
   void QueueReport(const GURL& url,
+                   const NetworkIsolationKey& network_isolation_key,
                    const std::string& user_agent,
                    const std::string& group,
                    const std::string& type,
                    std::unique_ptr<const base::Value> body,
                    int depth) override;
 
-  void ProcessHeader(const GURL& url, const std::string& header_value) override;
+  void ProcessHeader(const GURL& url,
+                     const NetworkIsolationKey& network_isolation_key,
+                     const std::string& header_value) override;
 
   void RemoveBrowsingData(
       uint64_t data_type_mask,
diff --git a/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java b/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java
index b47c142..79595fa 100644
--- a/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java
+++ b/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java
@@ -416,13 +416,13 @@
                 copyHeadersToResponse = false;
             }
         } else if (response.mIsNoContent) {
-            stream.println("HTTP/1.0 200 OK");
+            stream.println("HTTP/1.0 204 No Content");
             copyHeadersToResponse = false;
         } else if (response.mIsRedirect) {
             stream.println("HTTP/1.0 302 Found");
             textBody.append(String.format(bodyTemplate, "Found", "Found"));
         } else if (response.mIsEmptyResponse) {
-            stream.println("HTTP/1.0 403 Forbidden");
+            stream.println("HTTP/1.0 200 OK");
             copyHeadersToResponse = false;
         } else {
             if (response.mResponseAction != null) response.mResponseAction.run();
diff --git a/net/websockets/websocket_basic_stream_adapters.cc b/net/websockets/websocket_basic_stream_adapters.cc
index 5513a5d7..92efb7d 100644
--- a/net/websockets/websocket_basic_stream_adapters.cc
+++ b/net/websockets/websocket_basic_stream_adapters.cc
@@ -154,7 +154,12 @@
     const spdy::SpdyHeaderBlock& trailers) {}
 
 void WebSocketSpdyStreamAdapter::OnClose(int status) {
-  DCHECK_GT(ERR_IO_PENDING, status);
+  DCHECK_NE(ERR_IO_PENDING, status);
+  DCHECK_LE(status, 0);
+
+  if (status == OK) {
+    status = ERR_CONNECTION_CLOSED;
+  }
 
   stream_error_ = status;
   stream_ = nullptr;
diff --git a/net/websockets/websocket_basic_stream_adapters_test.cc b/net/websockets/websocket_basic_stream_adapters_test.cc
index a7be454..7f4fff0 100644
--- a/net/websockets/websocket_basic_stream_adapters_test.cc
+++ b/net/websockets/websocket_basic_stream_adapters_test.cc
@@ -963,6 +963,44 @@
   EXPECT_TRUE(data.AllWriteDataConsumed());
 }
 
+TEST_F(WebSocketSpdyStreamAdapterTest,
+       OnCloseOkShouldBeTranslatedToConnectionClose) {
+  spdy::SpdySerializedFrame response_headers(
+      spdy_util_.ConstructSpdyResponseHeaders(1, ResponseHeaders(), false));
+  spdy::SpdySerializedFrame close(
+      spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_NO_ERROR));
+  MockRead reads[] = {CreateMockRead(response_headers, 1),
+                      CreateMockRead(close, 2), MockRead(ASYNC, 0, 3)};
+  spdy::SpdySerializedFrame request_headers(spdy_util_.ConstructSpdyHeaders(
+      1, RequestHeaders(), DEFAULT_PRIORITY, false));
+  MockWrite writes[] = {CreateMockWrite(request_headers, 0)};
+  SequencedSocketData data(reads, writes);
+  AddSocketData(&data);
+  AddSSLSocketData();
+
+  EXPECT_CALL(mock_delegate_, OnHeadersSent());
+  EXPECT_CALL(mock_delegate_, OnHeadersReceived(_));
+
+  base::WeakPtr<SpdySession> session = CreateSpdySession();
+  base::WeakPtr<SpdyStream> stream = CreateSpdyStream(session);
+  WebSocketSpdyStreamAdapter adapter(stream, &mock_delegate_,
+                                     NetLogWithSource());
+  EXPECT_TRUE(adapter.is_initialized());
+
+  EXPECT_CALL(mock_delegate_, OnClose(ERR_CONNECTION_CLOSED));
+
+  int rv = stream->SendRequestHeaders(RequestHeaders(), MORE_DATA_TO_SEND);
+  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
+
+  const int kReadBufSize = 1024;
+  auto read_buf = base::MakeRefCounted<IOBuffer>(kReadBufSize);
+  TestCompletionCallback callback;
+  rv = adapter.Read(read_buf.get(), kReadBufSize, callback.callback());
+  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
+  rv = callback.WaitForResult();
+  ASSERT_EQ(ERR_CONNECTION_CLOSED, rv);
+}
+
 }  // namespace test
 
 }  // namespace net
diff --git a/remoting/host/file_transfer/file_chooser_linux.cc b/remoting/host/file_transfer/file_chooser_linux.cc
index 90d3641..be7ef13 100644
--- a/remoting/host/file_transfer/file_chooser_linux.cc
+++ b/remoting/host/file_transfer/file_chooser_linux.cc
@@ -159,8 +159,7 @@
 }
 
 void FileChooserLinux::Show() {
-  gtk_file_chooser_on_ui_thread_.Post(FROM_HERE,
-                                      &GtkFileChooserOnUiThread::Show);
+  gtk_file_chooser_on_ui_thread_.AsyncCall(&GtkFileChooserOnUiThread::Show);
 }
 
 void FileChooserLinux::RunCallback(FileChooser::Result result) {
diff --git a/remoting/resources/remoting_strings_iw.xtb b/remoting/resources/remoting_strings_iw.xtb
index 9354cbb..71e75cdf 100644
--- a/remoting/resources/remoting_strings_iw.xtb
+++ b/remoting/resources/remoting_strings_iw.xtb
@@ -10,7 +10,7 @@
 <translation id="1520828917794284345">שנה את גודל שולחן העבודה</translation>
 <translation id="1546934824884762070">אירעה שגיאה לא צפויה. דיווח על בעיה זו למפתחים.</translation>
 <translation id="1697532407822776718">הכל מוכן!</translation>
-<translation id="1742469581923031760">מתחבר…</translation>
+<translation id="1742469581923031760">ההתחברות מתבצעת…</translation>
 <translation id="177096447311351977">‏IP הערוץ של הלקוח: <ph name="CLIENT_GAIA_IDENTIFIER" /> ip='<ph name="CLIENT_IP_ADDRESS_AND_PORT" />' host_ip='<ph name="HOST_IP_ADDRESS_AND_PORT" />' ערוץ='<ph name="CHANNEL_TYPE" />' חיבור='<ph name="CONNECTION_TYPE" />'.</translation>
 <translation id="1897488610212723051">מחק</translation>
 <translation id="2009755455353575666">החיבור נכשל</translation>
@@ -109,7 +109,7 @@
 <translation id="6040143037577758943">סגור</translation>
 <translation id="6062854958530969723">אתחול המארח נכשל.</translation>
 <translation id="6099500228377758828">‏שירות Chrome Remote Desktop</translation>
-<translation id="6122191549521593678">מקוון</translation>
+<translation id="6122191549521593678">אונליין</translation>
 <translation id="6178645564515549384">מארח העברת הודעות ייעודי עבור סיוע מרוחק</translation>
 <translation id="618120821413932081">יש לעדכן את הפתרון המרוחק כך שיתאים לגודל החלון</translation>
 <translation id="6223301979382383752">פתיחת ההעדפות להקלטת מסך</translation>
@@ -129,7 +129,7 @@
 <translation id="7026930240735156896">יש להגדיר את המחשב לגישה מרחוק בהתאם להוראות</translation>
 <translation id="7067321367069083429">המסך פועל כמסך מגע</translation>
 <translation id="7116737094673640201">‏ברוך בואך אל Chrome Remote Desktop</translation>
-<translation id="7144878232160441200">נסה שוב</translation>
+<translation id="7144878232160441200">יש לנסות שוב</translation>
 <translation id="7312846573060934304">המארח אינו מקוון.</translation>
 <translation id="7319983568955948908">הפסק את השיתוף</translation>
 <translation id="7401733114166276557">Chrome Remote Desktop</translation>
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index 33f453f..4a63f35 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -862,9 +862,10 @@
   }
 
   // Send the crash report to the Reporting API.
-  reporting_service->QueueReport(url, reported_user_agent, group, type,
-                                 base::Value::ToUniquePtrValue(std::move(body)),
-                                 0 /* depth */);
+  // TODO(mmenke): Get a NetworkIsolationKey from the caller.
+  reporting_service->QueueReport(
+      url, net::NetworkIsolationKey::Todo(), reported_user_agent, group, type,
+      base::Value::ToUniquePtrValue(std::move(body)), 0 /* depth */);
 }
 
 void NetworkContext::QueueSignedExchangeReport(
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc
index 44c2049..532cb62d 100644
--- a/services/network/network_context_unittest.cc
+++ b/services/network/network_context_unittest.cc
@@ -2052,8 +2052,8 @@
       reporting_service.get());
 
   GURL domain("http://google.com");
-  reporting_service->QueueReport(domain, "Mozilla/1.0", "group", "type",
-                                 nullptr, 0);
+  reporting_service->QueueReport(domain, net::NetworkIsolationKey(),
+                                 "Mozilla/1.0", "group", "type", nullptr, 0);
 
   std::vector<const net::ReportingReport*> reports;
   reporting_cache->GetReports(&reports);
@@ -2081,12 +2081,12 @@
   network_context->url_request_context()->set_reporting_service(
       reporting_service.get());
 
-  GURL domain1("http://google.com");
-  reporting_service->QueueReport(domain1, "Mozilla/1.0", "group", "type",
-                                 nullptr, 0);
-  GURL domain2("http://chromium.org");
-  reporting_service->QueueReport(domain2, "Mozilla/1.0", "group", "type",
-                                 nullptr, 0);
+  GURL url1("http://google.com");
+  reporting_service->QueueReport(url1, net::NetworkIsolationKey(),
+                                 "Mozilla/1.0", "group", "type", nullptr, 0);
+  GURL url2("http://chromium.org");
+  reporting_service->QueueReport(url2, net::NetworkIsolationKey(),
+                                 "Mozilla/1.0", "group", "type", nullptr, 0);
 
   std::vector<const net::ReportingReport*> reports;
   reporting_cache->GetReports(&reports);
@@ -2103,7 +2103,7 @@
 
   reporting_cache->GetReports(&reports);
   EXPECT_EQ(1u, reports.size());
-  EXPECT_EQ(domain2, reports.front()->url);
+  EXPECT_EQ(url2, reports.front()->url);
 }
 
 TEST_F(NetworkContextTest,
@@ -2120,12 +2120,12 @@
   network_context->url_request_context()->set_reporting_service(
       reporting_service.get());
 
-  GURL domain1("http://192.168.0.1");
-  reporting_service->QueueReport(domain1, "Mozilla/1.0", "group", "type",
-                                 nullptr, 0);
-  GURL domain2("http://192.168.0.2");
-  reporting_service->QueueReport(domain2, "Mozilla/1.0", "group", "type",
-                                 nullptr, 0);
+  GURL url1("http://192.168.0.1");
+  reporting_service->QueueReport(url1, net::NetworkIsolationKey(),
+                                 "Mozilla/1.0", "group", "type", nullptr, 0);
+  GURL url2("http://192.168.0.2");
+  reporting_service->QueueReport(url2, net::NetworkIsolationKey(),
+                                 "Mozilla/1.0", "group", "type", nullptr, 0);
 
   std::vector<const net::ReportingReport*> reports;
   reporting_cache->GetReports(&reports);
@@ -2142,7 +2142,7 @@
 
   reporting_cache->GetReports(&reports);
   EXPECT_EQ(1u, reports.size());
-  EXPECT_EQ(domain2, reports.front()->url);
+  EXPECT_EQ(url2, reports.front()->url);
 }
 
 TEST_F(NetworkContextTest, ClearEmptyReportingCacheReports) {
diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc
index fe071ac36..040e67a 100644
--- a/services/network/public/cpp/features.cc
+++ b/services/network/public/cpp/features.cc
@@ -209,6 +209,12 @@
         TrustTokenOriginTrialSpec::kOriginTrialNotRequired,
         &kTrustTokenOriginTrialParamOptions};
 
+// Determines whether Trust Tokens issuance requests should be diverted, at the
+// corresponding issuers' request, to the operating system instead of sent
+// to the issuers' servers.
+const base::FeatureParam<bool> kPlatformProvidedTrustTokenIssuance{
+    &kTrustTokens, "PlatformProvidedTrustTokenIssuance", false};
+
 // Enables the Content Security Policy Embedded Enforcement check out of blink
 const base::Feature kOutOfBlinkCSPEE{"OutOfBlinkCSPEE",
                                      base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/services/network/public/cpp/features.h b/services/network/public/cpp/features.h
index 23f6d5c..1e602b3 100644
--- a/services/network/public/cpp/features.h
+++ b/services/network/public/cpp/features.h
@@ -82,6 +82,8 @@
 COMPONENT_EXPORT(NETWORK_CPP)
 extern const base::FeatureParam<TrustTokenOriginTrialSpec>
     kTrustTokenOperationsRequiringOriginTrial;
+COMPONENT_EXPORT(NETWORK_CPP)
+extern const base::FeatureParam<bool> kPlatformProvidedTrustTokenIssuance;
 
 COMPONENT_EXPORT(NETWORK_CPP)
 extern const base::Feature kOutOfBlinkCSPEE;
diff --git a/services/network/public/cpp/host_resolver_mojom_traits.cc b/services/network/public/cpp/host_resolver_mojom_traits.cc
index 7175738..37b8a86b 100644
--- a/services/network/public/cpp/host_resolver_mojom_traits.cc
+++ b/services/network/public/cpp/host_resolver_mojom_traits.cc
@@ -214,6 +214,8 @@
       return DnsQueryType::PTR;
     case net::DnsQueryType::SRV:
       return DnsQueryType::SRV;
+    case net::DnsQueryType::HTTPS:
+      return DnsQueryType::HTTPS;
     case net::DnsQueryType::INTEGRITY:
       NOTIMPLEMENTED();
       return DnsQueryType::UNSPECIFIED;
@@ -243,6 +245,9 @@
     case DnsQueryType::SRV:
       *output = net::DnsQueryType::SRV;
       return true;
+    case DnsQueryType::HTTPS:
+      *output = net::DnsQueryType::HTTPS;
+      return true;
   }
 }
 
diff --git a/services/network/public/mojom/host_resolver.mojom b/services/network/public/mojom/host_resolver.mojom
index b274cbe..6484008 100644
--- a/services/network/public/mojom/host_resolver.mojom
+++ b/services/network/public/mojom/host_resolver.mojom
@@ -163,6 +163,7 @@
   TXT,
   PTR,
   SRV,
+  HTTPS,
 };
 
 // Parameter-grouping struct for additional optional parameters for
diff --git a/services/network/public/mojom/trust_tokens.mojom b/services/network/public/mojom/trust_tokens.mojom
index a6e75a11..526ca38 100644
--- a/services/network/public/mojom/trust_tokens.mojom
+++ b/services/network/public/mojom/trust_tokens.mojom
@@ -52,6 +52,10 @@
 
   // The operation failed for some other reason.
   kUnknownError,
+
+  // The operation was executed by a means other than sending the resource
+  // request at hand, so there's no response to provide for the request.
+  kOperationSuccessfullyFulfilledLocally,
 };
 
 // Trust Tokens operation parameterization
@@ -218,3 +222,45 @@
   UnavailableLocalIssuanceFallback unavailable_local_issuance_fallback;
 };
 
+// Struct FulfillTrustTokenIssuanceRequest represents a Trust Tokens issuance
+// request intended to be satisfied in a manner other than the standard direct
+// resource request to the issuer's server. It contains "the same information"
+// as a Trust-Tokens-over-HTTP request.
+struct FulfillTrustTokenIssuanceRequest {
+  // |issuer| is the Trust Tokens issuer corresponding to this Trust Tokens
+  // issuance operation. Like all Trust Tokens issuer origins, this should be
+  // both
+  // - potentially trustworthy and
+  // - HTTP or HTTPS.
+  url.mojom.Origin issuer;
+  // |request| is a base64-encoded issuance request (in other words, a value
+  // that could serve as to the Sec-Trust-Token request header in a Trust
+  // Tokens-over-HTTP issuance request).
+  string request;
+};
+
+// Struct FulfillTrustTokenIssuanceAnswer represents a Trust Tokens issuance
+// response obtained in a manner other than the standard direct resource
+// request to the issuer's server. It contains "the same information" as a
+// Trust-Tokens-over-HTTP response.
+//
+// Note: We can't call this "FulfillTrustTokenIssuanceResponse" if we want a
+// "FulfillTrustTokenIssuance" method in C++-to-Java interfaces down the line,
+// because the Java bindings append the suffix "Response" when generating
+// callback names.
+struct FulfillTrustTokenIssuanceAnswer {
+  enum Status {
+    kOk,
+    // It wasn't possible to route the issuance operation to the specified
+    // token issuer.
+    kNotFound,
+    // Some other error occurred.
+    kUnknownError
+  };
+  Status status;
+
+  // If |status| is kOk, |response| will contain a value intended to be
+  // interpreted identically to a Trust Tokens-over-HTTP Sec-Trust-Token
+  // response header. Otherwise, its value is indeterminate.
+  string response;
+};
diff --git a/services/network/trust_tokens/BUILD.gn b/services/network/trust_tokens/BUILD.gn
index 2e10500..7f2b69a 100644
--- a/services/network/trust_tokens/BUILD.gn
+++ b/services/network/trust_tokens/BUILD.gn
@@ -30,6 +30,9 @@
     "has_trust_tokens_answerer.h",
     "in_memory_trust_token_persister.cc",
     "in_memory_trust_token_persister.h",
+    "local_trust_token_operation_delegate.h",
+    "operating_system_matching.cc",
+    "operating_system_matching.h",
     "operation_timing_request_helper_wrapper.cc",
     "operation_timing_request_helper_wrapper.h",
     "pending_trust_token_store.cc",
diff --git a/services/network/trust_tokens/local_trust_token_operation_delegate.h b/services/network/trust_tokens/local_trust_token_operation_delegate.h
new file mode 100644
index 0000000..2703779
--- /dev/null
+++ b/services/network/trust_tokens/local_trust_token_operation_delegate.h
@@ -0,0 +1,33 @@
+// 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 SERVICES_NETWORK_TRUST_TOKENS_LOCAL_TRUST_TOKEN_OPERATION_DELEGATE_H_
+#define SERVICES_NETWORK_TRUST_TOKENS_LOCAL_TRUST_TOKEN_OPERATION_DELEGATE_H_
+
+#include "base/callback.h"
+#include "services/network/public/mojom/trust_tokens.mojom-forward.h"
+
+namespace network {
+
+// LocalTrustTokenOperationDelegate provides an interface for executing
+// Trust Tokens "against the platform," i.e. via some kind of operating system
+// mediation rather than through the typical method of a direct HTTP request to
+// a counterparty.
+class LocalTrustTokenOperationDelegate {
+ public:
+  virtual ~LocalTrustTokenOperationDelegate() = default;
+
+  // FulfillIssuance attempts to execute the given Trust Tokens operation
+  // locally, on conclusion populating |done| with either a response or a
+  // suitable status as described in FulfillTrustTokenIssuanceAnswer's struct
+  // comments.
+  virtual void FulfillIssuance(
+      mojom::FulfillTrustTokenIssuanceRequestPtr request,
+      base::OnceCallback<void(mojom::FulfillTrustTokenIssuanceAnswerPtr)>
+          done) = 0;
+};
+
+}  // namespace network
+
+#endif  // SERVICES_NETWORK_TRUST_TOKENS_LOCAL_TRUST_TOKEN_OPERATION_DELEGATE_H_
diff --git a/services/network/trust_tokens/operating_system_matching.cc b/services/network/trust_tokens/operating_system_matching.cc
new file mode 100644
index 0000000..e850394ec
--- /dev/null
+++ b/services/network/trust_tokens/operating_system_matching.cc
@@ -0,0 +1,23 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/trust_tokens/operating_system_matching.h"
+
+#include "build/build_config.h"
+
+namespace network {
+
+bool IsCurrentOperatingSystem(mojom::TrustTokenKeyCommitmentResult::Os os) {
+  switch (os) {
+    case mojom::TrustTokenKeyCommitmentResult::Os::kAndroid:
+#if defined(OS_ANDROID)
+      return true;
+#endif  // defined(OS_ANDROID)
+      break;
+  }
+
+  return false;
+}
+
+}  // namespace network
diff --git a/services/network/trust_tokens/operating_system_matching.h b/services/network/trust_tokens/operating_system_matching.h
new file mode 100644
index 0000000..bc4c7d7
--- /dev/null
+++ b/services/network/trust_tokens/operating_system_matching.h
@@ -0,0 +1,24 @@
+// 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 SERVICES_NETWORK_TRUST_TOKENS_OPERATING_SYSTEM_MATCHING_H_
+#define SERVICES_NETWORK_TRUST_TOKENS_OPERATING_SYSTEM_MATCHING_H_
+
+#include "base/callback.h"
+#include "services/network/public/mojom/trust_tokens.mojom.h"
+
+namespace network {
+
+// Returns whether the given Os value corresponds to the operating system on
+// which this code is built.
+//
+// This information allows Trust Tokens logic to decide whether it should try to
+// execute certain operations locally, by comparing the current operating system
+// to an issuer-provided collection of operating systems on which to attempt
+// executing operations locally.
+bool IsCurrentOperatingSystem(mojom::TrustTokenKeyCommitmentResult::Os os);
+
+}  // namespace network
+
+#endif  // SERVICES_NETWORK_TRUST_TOKENS_OPERATING_SYSTEM_MATCHING_H_
diff --git a/services/network/trust_tokens/trust_token_key_commitments.cc b/services/network/trust_tokens/trust_token_key_commitments.cc
index 4b50e74..fcfd868 100644
--- a/services/network/trust_tokens/trust_token_key_commitments.cc
+++ b/services/network/trust_tokens/trust_token_key_commitments.cc
@@ -117,7 +117,7 @@
 
   if (!additional_commitments_from_command_line_.empty()) {
     auto it = additional_commitments_from_command_line_.find(*suitable_origin);
-    if (it != commitments_.end()) {
+    if (it != additional_commitments_from_command_line_.end()) {
       return FilterCommitments(it->second->Clone());
     }
   }
diff --git a/services/network/trust_tokens/trust_token_request_helper_factory.cc b/services/network/trust_tokens/trust_token_request_helper_factory.cc
index a1834de..9a482d2 100644
--- a/services/network/trust_tokens/trust_token_request_helper_factory.cc
+++ b/services/network/trust_tokens/trust_token_request_helper_factory.cc
@@ -21,6 +21,8 @@
 #include "services/network/trust_tokens/boringssl_trust_token_redemption_cryptographer.h"
 #include "services/network/trust_tokens/ed25519_key_pair_generator.h"
 #include "services/network/trust_tokens/ed25519_trust_token_request_signer.h"
+#include "services/network/trust_tokens/local_trust_token_operation_delegate.h"
+#include "services/network/trust_tokens/operating_system_matching.h"
 #include "services/network/trust_tokens/suitable_trust_token_origin.h"
 #include "services/network/trust_tokens/trust_token_http_headers.h"
 #include "services/network/trust_tokens/trust_token_key_commitment_controller.h"
@@ -127,6 +129,24 @@
       base::Passed(params.Clone()), request.net_log(), std::move(done)));
 }
 
+namespace {
+
+// TODO(crbug.com/1130272): Delete this upon adding a concrete instantiation
+// of the delegate.
+class NotImplementedLocalTrustTokenOperationDelegate
+    : public LocalTrustTokenOperationDelegate {
+  void FulfillIssuance(
+      mojom::FulfillTrustTokenIssuanceRequestPtr request,
+      base::OnceCallback<void(mojom::FulfillTrustTokenIssuanceAnswerPtr)> done)
+      override {
+    auto answer = mojom::FulfillTrustTokenIssuanceAnswer::New();
+    answer->status = mojom::FulfillTrustTokenIssuanceAnswer::Status::kNotFound;
+    std::move(done).Run(std::move(answer));
+  }
+};
+
+}  // namespace
+
 void TrustTokenRequestHelperFactory::ConstructHelperUsingStore(
     SuitableTrustTokenOrigin top_frame_origin,
     mojom::TrustTokenParamsPtr params,
@@ -143,6 +163,9 @@
           new TrustTokenRequestIssuanceHelper(
               std::move(top_frame_origin), store, key_commitment_getter_,
               std::make_unique<BoringsslTrustTokenIssuanceCryptographer>(),
+              std::make_unique<
+                  NotImplementedLocalTrustTokenOperationDelegate>(),
+              base::BindRepeating(&IsCurrentOperatingSystem),
               std::move(net_log))));
       return;
     }
diff --git a/services/network/trust_tokens/trust_token_request_issuance_helper.cc b/services/network/trust_tokens/trust_token_request_issuance_helper.cc
index 0c1b6ce..db24f3e 100644
--- a/services/network/trust_tokens/trust_token_request_issuance_helper.cc
+++ b/services/network/trust_tokens/trust_token_request_issuance_helper.cc
@@ -7,13 +7,16 @@
 #include <utility>
 
 #include "base/callback.h"
+#include "base/command_line.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/stl_util.h"
 #include "base/task/thread_pool.h"
 #include "net/base/load_flags.h"
 #include "net/http/http_response_headers.h"
 #include "net/log/net_log_event_type.h"
 #include "net/url_request/url_request.h"
+#include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/is_potentially_trustworthy.h"
-#include "services/network/public/mojom/trust_tokens.mojom-forward.h"
 #include "services/network/public/mojom/trust_tokens.mojom.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
 #include "services/network/trust_tokens/proto/public.pb.h"
@@ -82,11 +85,16 @@
     TrustTokenStore* token_store,
     const TrustTokenKeyCommitmentGetter* key_commitment_getter,
     std::unique_ptr<Cryptographer> cryptographer,
+    std::unique_ptr<LocalTrustTokenOperationDelegate> local_operation_delegate,
+    base::RepeatingCallback<bool(mojom::TrustTokenKeyCommitmentResult::Os)>
+        is_current_os_callback,
     net::NetLogWithSource net_log)
     : top_level_origin_(std::move(top_level_origin)),
       token_store_(token_store),
       key_commitment_getter_(std::move(key_commitment_getter)),
       cryptographer_(std::move(cryptographer)),
+      local_operation_delegate_(std::move(local_operation_delegate)),
+      is_current_os_callback_(std::move(is_current_os_callback)),
       net_log_(std::move(net_log)) {
   DCHECK(token_store_);
   DCHECK(key_commitment_getter_);
@@ -144,6 +152,25 @@
     return;
   }
 
+  if (features::kPlatformProvidedTrustTokenIssuance.Get() &&
+      !commitment_result->request_issuance_locally_on.empty()) {
+    should_divert_issuance_request_to_os_ = base::ranges::any_of(
+        commitment_result->request_issuance_locally_on,
+        [this](mojom::TrustTokenKeyCommitmentResult::Os os) {
+          return is_current_os_callback_.Run(os);
+        });
+    if (!should_divert_issuance_request_to_os_ &&
+        commitment_result->unavailable_local_issuance_fallback ==
+            mojom::TrustTokenKeyCommitmentResult::
+                UnavailableLocalIssuanceFallback::kReturnWithError) {
+      // If the issuer requests that issuance be mediated by the OS on at least
+      // one platform, and we aren't on that platform, and the issuer has
+      // configured that we should return with an error in this case, do so.
+      std::move(done).Run(mojom::TrustTokenOperationStatus::kUnavailable);
+      return;
+    }
+  }
+
   protocol_version_ = commitment_result->protocol_version;
   if (!commitment_result->batch_size ||
       !cryptographer_->Initialize(protocol_version_,
@@ -196,6 +223,23 @@
     std::move(done).Run(mojom::TrustTokenOperationStatus::kInternalError);
     return;
   }
+
+  if (should_divert_issuance_request_to_os_) {
+    LogOutcome(net_log_, kBegin,
+               "Passing operation to local issuance provider");
+    auto fulfill_request = mojom::FulfillTrustTokenIssuanceRequest::New();
+    fulfill_request->issuer = url::Origin::Create(request->url());
+    fulfill_request->request = std::move(*maybe_blinded_tokens);
+    local_operation_delegate_->FulfillIssuance(
+        std::move(fulfill_request),
+        base::BindOnce(&TrustTokenRequestIssuanceHelper::
+                           DoneRequestingLocallyFulfilledIssuance,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(done)));
+    // |this| may have been deleted and/or Finalize may have been called
+    // already.
+    return;
+  }
+
   request->SetExtraRequestHeaderByName(kTrustTokensSecTrustTokenHeader,
                                        std::move(*maybe_blinded_tokens),
                                        /*overwrite=*/true);
@@ -242,10 +286,16 @@
 
   response->headers->RemoveHeader(kTrustTokensSecTrustTokenHeader);
 
+  ConfirmIssuanceResponse(std::move(header_value), std::move(done));
+}
+
+void TrustTokenRequestIssuanceHelper::ConfirmIssuanceResponse(
+    std::string issuance_response,
+    base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done) {
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE,
       base::BindOnce(&ConfirmIssuanceOnPostedSequence,
-                     std::move(cryptographer_), std::move(header_value)),
+                     std::move(cryptographer_), std::move(issuance_response)),
       base::BindOnce(&TrustTokenRequestIssuanceHelper::
                          OnDelegateConfirmIssuanceCallComplete,
                      weak_ptr_factory_.GetWeakPtr(), std::move(done)));
@@ -282,4 +332,43 @@
   return;
 }
 
+void TrustTokenRequestIssuanceHelper::DoneRequestingLocallyFulfilledIssuance(
+    base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done,
+    mojom::FulfillTrustTokenIssuanceAnswerPtr answer) {
+  switch (answer->status) {
+    case mojom::FulfillTrustTokenIssuanceAnswer::Status::kNotFound: {
+      std::move(done).Run(mojom::TrustTokenOperationStatus::kUnavailable);
+      return;
+    }
+    case mojom::FulfillTrustTokenIssuanceAnswer::Status::kUnknownError: {
+      std::move(done).Run(mojom::TrustTokenOperationStatus::kUnknownError);
+      return;
+    }
+    case mojom::FulfillTrustTokenIssuanceAnswer::Status::kOk:
+      break;
+  }
+
+  // Log the beginning of the Finalize event here, since this is where we enter
+  // the main response processing logic when executing issuance locally:
+  net_log_.BeginEvent(
+      net::NetLogEventType::TRUST_TOKEN_OPERATION_FINALIZE_ISSUANCE);
+  ConfirmIssuanceResponse(
+      std::move(answer->response),
+      base::BindOnce(&TrustTokenRequestIssuanceHelper::
+                         DoneFinalizingLocallyFulfilledIssuance,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(done)));
+}
+
+void TrustTokenRequestIssuanceHelper::DoneFinalizingLocallyFulfilledIssuance(
+    base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done,
+    mojom::TrustTokenOperationStatus status) {
+  if (status == mojom::TrustTokenOperationStatus::kOk) {
+    std::move(done).Run(mojom::TrustTokenOperationStatus::
+                            kOperationSuccessfullyFulfilledLocally);
+    return;
+  }
+
+  std::move(done).Run(status);
+}
+
 }  // namespace network
diff --git a/services/network/trust_tokens/trust_token_request_issuance_helper.h b/services/network/trust_tokens/trust_token_request_issuance_helper.h
index dae62cd..44f06f6 100644
--- a/services/network/trust_tokens/trust_token_request_issuance_helper.h
+++ b/services/network/trust_tokens/trust_token_request_issuance_helper.h
@@ -6,6 +6,7 @@
 #define SERVICES_NETWORK_TRUST_TOKENS_TRUST_TOKEN_REQUEST_ISSUANCE_HELPER_H_
 
 #include <memory>
+#include <set>
 #include <string>
 #include <vector>
 
@@ -14,6 +15,7 @@
 #include "base/strings/string_piece_forward.h"
 #include "net/log/net_log_with_source.h"
 #include "services/network/public/mojom/trust_tokens.mojom-shared.h"
+#include "services/network/trust_tokens/local_trust_token_operation_delegate.h"
 #include "services/network/trust_tokens/proto/public.pb.h"
 #include "services/network/trust_tokens/suitable_trust_token_origin.h"
 #include "services/network/trust_tokens/trust_token_key_commitment_getter.h"
@@ -115,16 +117,25 @@
   //   2. potentially trustworthy origin to satisfy Web security requirements.
   // - |token_store| will be responsible for storing underlying Trust Tokens
   // state. It must outlive this object.
-  // - |key_commitment_getter| and |cryptographer| are delegates that
-  // help execute the protocol; see their class comments.
+  // - |key_commitment_getter|, |cryptographer|, and |local_operation_delegate|
+  // are delegates that help execute the protocol; see their class comments.
+  // They must live outlive this object.
+  // - |is_current_os_callback| should return whether, when the given Os is
+  // present in the issuer's "request_issuance_locally_on" field in its key
+  // commitment, the issuance helper should attempt to forward requests to the
+  // local operation delegate.
   //
-  // REQUIRES: |token_store|, |key_commitment_getter|, and |cryptographer| must
-  // be non-null.
+  // REQUIRES: |token_store|, |key_commitment_getter|, |cryptographer|,
+  // |local_operation_delegate|, and |is_current_os_callback| must be non-null.
   TrustTokenRequestIssuanceHelper(
       SuitableTrustTokenOrigin top_level_origin,
       TrustTokenStore* token_store,
       const TrustTokenKeyCommitmentGetter* key_commitment_getter,
       std::unique_ptr<Cryptographer> cryptographer,
+      std::unique_ptr<LocalTrustTokenOperationDelegate>
+          local_operation_delegate,
+      base::RepeatingCallback<bool(mojom::TrustTokenKeyCommitmentResult::Os)>
+          is_current_os_callback,
       net::NetLogWithSource net_log = net::NetLogWithSource());
   ~TrustTokenRequestIssuanceHelper() override;
 
@@ -198,6 +209,13 @@
       base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done,
       CryptographerAndBlindedTokens cryptographer_and_blinded_tokens);
 
+  // Continuation of |Finalize| after extracting the base64-encoded issuance
+  // response from a response header (or receiving it from a locally executed
+  // operation).
+  void ConfirmIssuanceResponse(
+      std::string issuance_response,
+      base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done);
+
   // Continuation of |Finalize| after a call to the cryptography delegate to
   // execute the bulk of the inbound half of the issuance operation.
   // Receives ownership of the cryptographer back from the asynchronous
@@ -206,6 +224,25 @@
       base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done,
       CryptographerAndUnblindedTokens cryptographer_and_unblinded_tokens);
 
+  // DoneRequestingLocallyFulfilledIssuance proceeds with a locally fulfilled
+  // issuance operation by handling the operation's response |answer|,
+  // either terminating the operation with an error passed to |done| (if
+  // |answer| contains an error) or continuing to finalize the operation (if
+  // |answer| contains an issuance response).
+  void DoneRequestingLocallyFulfilledIssuance(
+      base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done,
+      mojom::FulfillTrustTokenIssuanceAnswerPtr answer);
+
+  // DoneFinalizingLocallyFulfilledIssuance determines a final response status
+  // to pass to the caller via |done|, then calls the callback.
+  //
+  // If the operation succeeded, calls |done| with
+  // kOperationSuccessfullyFulfilledLocally. Otherwise, calls |done| with
+  // |status|.
+  void DoneFinalizingLocallyFulfilledIssuance(
+      base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done,
+      mojom::TrustTokenOperationStatus status);
+
   // |issuer_| needs to be a nullable type because it is initialized in |Begin|,
   // but, once initialized, it will never be empty over the course of the
   // operation's execution.
@@ -216,15 +253,31 @@
 
   mojom::TrustTokenProtocolVersion protocol_version_;
 
+  // Set once we read the issuer's key commitment,
+  // |should_divert_issuance_request_to_os_| specifies whether, at the time we
+  // would return from an otherwise successful Begin half of this issuance
+  // operation, we should pass the issuance request to
+  // |local_operation_delegate_| rather than returning to the caller.
+  bool should_divert_issuance_request_to_os_ = false;
+
   // Relinquishes ownership during posted tasks for the potentially
   // computationally intensive cryptographic operations
   // (Cryptographer::BeginIssuance, Cryptographer::ConfirmIssuance); repopulated
   // when regaining ownership upon receiving each operation's results.
   std::unique_ptr<Cryptographer> cryptographer_;
 
+  // |local_operation_delegate_| is responsible for attempting to satisfying
+  // "platform-provided" issuance operations (e.g. by talking to a system
+  // service capable of replying to an issuance request).
+  std::unique_ptr<LocalTrustTokenOperationDelegate> local_operation_delegate_;
+
+  base::RepeatingCallback<bool(mojom::TrustTokenKeyCommitmentResult::Os)>
+      is_current_os_callback_;
+
   net::NetLogWithSource net_log_;
   base::WeakPtrFactory<TrustTokenRequestIssuanceHelper> weak_ptr_factory_{this};
 };
+
 }  // namespace network
 
 #endif  // SERVICES_NETWORK_TRUST_TOKENS_TRUST_TOKEN_REQUEST_ISSUANCE_HELPER_H_
diff --git a/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc b/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc
index 451e82a..ad02963c 100644
--- a/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc
+++ b/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc
@@ -8,16 +8,21 @@
 
 #include "base/callback.h"
 #include "base/no_destructor.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
+#include "build/build_config.h"
 #include "net/base/load_flags.h"
 #include "net/base/request_priority.h"
 #include "net/http/http_response_headers.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_test_util.h"
+#include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/trust_token_parameterization.h"
 #include "services/network/public/mojom/trust_tokens.mojom.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
+#include "services/network/trust_tokens/operating_system_matching.h"
 #include "services/network/trust_tokens/proto/public.pb.h"
 #include "services/network/trust_tokens/test/trust_token_test_util.h"
 #include "services/network/trust_tokens/trust_token_http_headers.h"
@@ -35,9 +40,13 @@
 using ::testing::_;
 using ::testing::ByMove;
 using ::testing::ElementsAre;
+using ::testing::Invoke;
 using ::testing::Property;
 using ::testing::Return;
 using ::testing::ReturnNull;
+using ::testing::StrEq;
+using ::testing::StrictMock;
+using ::testing::WithArgs;
 
 using TrustTokenRequestIssuanceHelperTest = TrustTokenRequestHelperTest;
 using UnblindedTokens =
@@ -82,6 +91,38 @@
       std::unique_ptr<UnblindedTokens>(base::StringPiece response_header));
 };
 
+// MockLocalOperationDelegate mocks out executing a Trust Tokens operation
+// mediated by the OS.
+class MockLocalOperationDelegate : public LocalTrustTokenOperationDelegate {
+ public:
+  MOCK_METHOD2(
+      FulfillIssuance,
+      void(mojom::FulfillTrustTokenIssuanceRequestPtr request,
+           base::OnceCallback<void(mojom::FulfillTrustTokenIssuanceAnswerPtr)>
+               done));
+};
+
+// Returns a key commitment result with reasonable values for all parameters.
+mojom::TrustTokenKeyCommitmentResultPtr ReasonableKeyCommitmentResult() {
+  auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New();
+  key_commitment_result->keys.push_back(mojom::TrustTokenVerificationKey::New(
+      "key", /*expiry=*/base::Time::Max()));
+  key_commitment_result->batch_size =
+      static_cast<int>(kMaximumTrustTokenIssuanceBatchSize);
+  key_commitment_result->protocol_version =
+      mojom::TrustTokenProtocolVersion::kTrustTokenV1;
+  key_commitment_result->id = 1;
+  return key_commitment_result;
+}
+
+FixedKeyCommitmentGetter* ReasonableKeyCommitmentGetter() {
+  static base::NoDestructor<FixedKeyCommitmentGetter>
+      reasonable_key_commitment_getter{
+          *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")),
+          ReasonableKeyCommitmentResult()};
+  return reasonable_key_commitment_getter.get();
+}
+
 }  // namespace
 
 // Check that issuance fails if it would result in too many issuers being
@@ -103,9 +144,11 @@
         toplevel));
   }
 
-  TrustTokenRequestIssuanceHelper helper(toplevel, store.get(),
-                                         g_fixed_key_commitment_getter.get(),
-                                         std::make_unique<MockCryptographer>());
+  TrustTokenRequestIssuanceHelper helper(
+      toplevel, store.get(), g_fixed_key_commitment_getter.get(),
+      std::make_unique<MockCryptographer>(),
+      std::make_unique<MockLocalOperationDelegate>(),
+      base::BindRepeating(&IsCurrentOperatingSystem));
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -129,7 +172,9 @@
   TrustTokenRequestIssuanceHelper helper(
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
       store.get(), g_fixed_key_commitment_getter.get(),
-      std::make_unique<MockCryptographer>());
+      std::make_unique<MockCryptographer>(),
+      std::make_unique<MockLocalOperationDelegate>(),
+      base::BindRepeating(&IsCurrentOperatingSystem));
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -149,7 +194,9 @@
   auto getter = std::make_unique<FixedKeyCommitmentGetter>(issuer, nullptr);
   TrustTokenRequestIssuanceHelper helper(
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
-      store.get(), getter.get(), std::make_unique<MockCryptographer>());
+      store.get(), getter.get(), std::make_unique<MockCryptographer>(),
+      std::make_unique<MockLocalOperationDelegate>(),
+      base::BindRepeating(&IsCurrentOperatingSystem));
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(
@@ -167,23 +214,14 @@
   SuitableTrustTokenOrigin issuer =
       *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
 
-  auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New();
-  key_commitment_result->keys.push_back(
-      mojom::TrustTokenVerificationKey::New());
-  key_commitment_result->protocol_version =
-      mojom::TrustTokenProtocolVersion::kTrustTokenV1;
-  key_commitment_result->id = 1;
-  key_commitment_result->batch_size =
-      static_cast<int>(kMaximumTrustTokenIssuanceBatchSize);
-  auto getter = std::make_unique<FixedKeyCommitmentGetter>(
-      issuer, std::move(key_commitment_result));
-
   auto cryptographer = std::make_unique<MockCryptographer>();
   EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(false));
 
   TrustTokenRequestIssuanceHelper helper(
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
-      store.get(), getter.get(), std::move(cryptographer));
+      store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
+      std::make_unique<MockLocalOperationDelegate>(),
+      base::BindRepeating(&IsCurrentOperatingSystem));
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -199,24 +237,15 @@
   SuitableTrustTokenOrigin issuer =
       *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
 
-  auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New();
-  key_commitment_result->keys.push_back(
-      mojom::TrustTokenVerificationKey::New());
-  key_commitment_result->protocol_version =
-      mojom::TrustTokenProtocolVersion::kTrustTokenV1;
-  key_commitment_result->id = 1;
-  key_commitment_result->batch_size =
-      static_cast<int>(kMaximumTrustTokenIssuanceBatchSize);
-  auto getter = std::make_unique<FixedKeyCommitmentGetter>(
-      issuer, std::move(key_commitment_result));
-
   auto cryptographer = std::make_unique<MockCryptographer>();
   EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true));
   EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(false));
 
   TrustTokenRequestIssuanceHelper helper(
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
-      store.get(), getter.get(), std::move(cryptographer));
+      store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
+      std::make_unique<MockLocalOperationDelegate>(),
+      base::BindRepeating(&IsCurrentOperatingSystem));
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -233,17 +262,6 @@
   SuitableTrustTokenOrigin issuer =
       *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
 
-  auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New();
-  key_commitment_result->keys.push_back(
-      mojom::TrustTokenVerificationKey::New());
-  key_commitment_result->protocol_version =
-      mojom::TrustTokenProtocolVersion::kTrustTokenV1;
-  key_commitment_result->id = 1;
-  key_commitment_result->batch_size =
-      static_cast<int>(kMaximumTrustTokenIssuanceBatchSize);
-  auto getter = std::make_unique<FixedKeyCommitmentGetter>(
-      issuer, std::move(key_commitment_result));
-
   auto cryptographer = std::make_unique<MockCryptographer>();
   EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true));
   EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true));
@@ -253,7 +271,9 @@
 
   TrustTokenRequestIssuanceHelper helper(
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
-      store.get(), getter.get(), std::move(cryptographer));
+      store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
+      std::make_unique<MockLocalOperationDelegate>(),
+      base::BindRepeating(&IsCurrentOperatingSystem));
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -273,17 +293,6 @@
   SuitableTrustTokenOrigin issuer =
       *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
 
-  auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New();
-  key_commitment_result->keys.push_back(
-      mojom::TrustTokenVerificationKey::New());
-  key_commitment_result->protocol_version =
-      mojom::TrustTokenProtocolVersion::kTrustTokenV1;
-  key_commitment_result->id = 1;
-  key_commitment_result->batch_size =
-      static_cast<int>(kMaximumTrustTokenIssuanceBatchSize);
-  auto getter = std::make_unique<FixedKeyCommitmentGetter>(
-      issuer, std::move(key_commitment_result));
-
   // The result of providing blinded, unsigned tokens should be the exact value
   // of the Sec-Trust-Token header attached to the request.
   auto cryptographer = std::make_unique<MockCryptographer>();
@@ -295,7 +304,9 @@
 
   TrustTokenRequestIssuanceHelper helper(
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
-      store.get(), getter.get(), std::move(cryptographer));
+      store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
+      std::make_unique<MockLocalOperationDelegate>(),
+      base::BindRepeating(&IsCurrentOperatingSystem));
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -322,17 +333,6 @@
   SuitableTrustTokenOrigin issuer =
       *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
 
-  auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New();
-  key_commitment_result->keys.push_back(
-      mojom::TrustTokenVerificationKey::New());
-  key_commitment_result->protocol_version =
-      mojom::TrustTokenProtocolVersion::kTrustTokenV1;
-  key_commitment_result->id = 1;
-  key_commitment_result->batch_size =
-      static_cast<int>(kMaximumTrustTokenIssuanceBatchSize);
-  auto getter = std::make_unique<FixedKeyCommitmentGetter>(
-      issuer, std::move(key_commitment_result));
-
   // The result of providing blinded, unsigned tokens should be the exact value
   // of the Sec-Trust-Token header attached to the request.
   auto cryptographer = std::make_unique<MockCryptographer>();
@@ -344,7 +344,9 @@
 
   TrustTokenRequestIssuanceHelper helper(
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
-      store.get(), getter.get(), std::move(cryptographer));
+      store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
+      std::make_unique<MockLocalOperationDelegate>(),
+      base::BindRepeating(&IsCurrentOperatingSystem));
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -362,17 +364,6 @@
   SuitableTrustTokenOrigin issuer =
       *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
 
-  auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New();
-  key_commitment_result->keys.push_back(
-      mojom::TrustTokenVerificationKey::New());
-  key_commitment_result->protocol_version =
-      mojom::TrustTokenProtocolVersion::kTrustTokenV1;
-  key_commitment_result->id = 1;
-  key_commitment_result->batch_size =
-      static_cast<int>(kMaximumTrustTokenIssuanceBatchSize);
-  auto getter = std::make_unique<FixedKeyCommitmentGetter>(
-      issuer, std::move(key_commitment_result));
-
   auto cryptographer = std::make_unique<MockCryptographer>();
   EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true));
   EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true));
@@ -382,7 +373,9 @@
 
   TrustTokenRequestIssuanceHelper helper(
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
-      store.get(), getter.get(), std::move(cryptographer));
+      store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
+      std::make_unique<MockLocalOperationDelegate>(),
+      base::BindRepeating(&IsCurrentOperatingSystem));
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -405,17 +398,6 @@
   SuitableTrustTokenOrigin issuer =
       *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
 
-  auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New();
-  key_commitment_result->keys.push_back(
-      mojom::TrustTokenVerificationKey::New());
-  key_commitment_result->protocol_version =
-      mojom::TrustTokenProtocolVersion::kTrustTokenV1;
-  key_commitment_result->id = 1;
-  key_commitment_result->batch_size =
-      static_cast<int>(kMaximumTrustTokenIssuanceBatchSize);
-  auto getter = std::make_unique<FixedKeyCommitmentGetter>(
-      issuer, std::move(key_commitment_result));
-
   auto cryptographer = std::make_unique<MockCryptographer>();
   EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true));
   EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true));
@@ -428,7 +410,9 @@
 
   TrustTokenRequestIssuanceHelper helper(
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
-      store.get(), getter.get(), std::move(cryptographer));
+      store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
+      std::make_unique<MockLocalOperationDelegate>(),
+      base::BindRepeating(&IsCurrentOperatingSystem));
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -459,17 +443,6 @@
   SuitableTrustTokenOrigin issuer =
       *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
 
-  auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New();
-  key_commitment_result->keys.push_back(
-      mojom::TrustTokenVerificationKey::New());
-  key_commitment_result->protocol_version =
-      mojom::TrustTokenProtocolVersion::kTrustTokenV1;
-  key_commitment_result->id = 1;
-  key_commitment_result->batch_size =
-      static_cast<int>(kMaximumTrustTokenIssuanceBatchSize);
-  auto getter = std::make_unique<FixedKeyCommitmentGetter>(
-      issuer, std::move(key_commitment_result));
-
   auto cryptographer = std::make_unique<MockCryptographer>();
   EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true));
   EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true));
@@ -481,7 +454,9 @@
 
   TrustTokenRequestIssuanceHelper helper(
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
-      store.get(), getter.get(), std::move(cryptographer));
+      store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
+      std::make_unique<MockLocalOperationDelegate>(),
+      base::BindRepeating(&IsCurrentOperatingSystem));
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -512,17 +487,6 @@
   SuitableTrustTokenOrigin issuer =
       *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
 
-  auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New();
-  key_commitment_result->keys.push_back(
-      mojom::TrustTokenVerificationKey::New());
-  key_commitment_result->protocol_version =
-      mojom::TrustTokenProtocolVersion::kTrustTokenV1;
-  key_commitment_result->id = 1;
-  key_commitment_result->batch_size =
-      static_cast<int>(kMaximumTrustTokenIssuanceBatchSize);
-  auto getter = std::make_unique<FixedKeyCommitmentGetter>(
-      issuer, std::move(key_commitment_result));
-
   auto cryptographer = std::make_unique<MockCryptographer>();
   EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true));
   EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true));
@@ -532,7 +496,9 @@
 
   TrustTokenRequestIssuanceHelper helper(
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
-      store.get(), getter.get(), std::move(cryptographer));
+      store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
+      std::make_unique<MockLocalOperationDelegate>(),
+      base::BindRepeating(&IsCurrentOperatingSystem));
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -554,22 +520,12 @@
   SuitableTrustTokenOrigin issuer =
       *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
 
-  auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New();
-  key_commitment_result->keys.push_back(
-      mojom::TrustTokenVerificationKey::New("key", /*expiry=*/base::Time()));
-  key_commitment_result->protocol_version =
-      mojom::TrustTokenProtocolVersion::kTrustTokenV1;
-  key_commitment_result->id = 1;
-  key_commitment_result->batch_size =
-      static_cast<int>(kMaximumTrustTokenIssuanceBatchSize);
-  auto getter = std::make_unique<FixedKeyCommitmentGetter>(
-      issuer, std::move(key_commitment_result));
-
   // Have the Trust Tokens issuance conclude by the underlying cryptographic
   // library returning one signed, unblinded token associated with the same
   // returned from the key commitment.
   auto unblinded_tokens = std::make_unique<UnblindedTokens>();
-  unblinded_tokens->body_of_verifying_key = "key";
+  unblinded_tokens->body_of_verifying_key =
+      ReasonableKeyCommitmentResult()->keys.front()->body;
   unblinded_tokens->tokens.push_back("a signed, unblinded token");
 
   auto cryptographer = std::make_unique<MockCryptographer>();
@@ -583,7 +539,9 @@
 
   TrustTokenRequestIssuanceHelper helper(
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
-      store.get(), getter.get(), std::move(cryptographer));
+      store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
+      std::make_unique<MockLocalOperationDelegate>(),
+      base::BindRepeating(&IsCurrentOperatingSystem));
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -615,7 +573,9 @@
   TrustTokenRequestIssuanceHelper helper(
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
       store.get(), g_fixed_key_commitment_getter.get(),
-      std::make_unique<MockCryptographer>());
+      std::make_unique<MockCryptographer>(),
+      std::make_unique<MockLocalOperationDelegate>(),
+      base::BindRepeating(&IsCurrentOperatingSystem));
 
   auto request = MakeURLRequest("http://insecure-issuer.com/");
 
@@ -629,7 +589,9 @@
   TrustTokenRequestIssuanceHelper helper(
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
       store.get(), g_fixed_key_commitment_getter.get(),
-      std::make_unique<MockCryptographer>());
+      std::make_unique<MockCryptographer>(),
+      std::make_unique<MockLocalOperationDelegate>(),
+      base::BindRepeating(&IsCurrentOperatingSystem));
 
   auto request = MakeURLRequest("file:///non-https-issuer.txt");
 
@@ -643,17 +605,6 @@
   SuitableTrustTokenOrigin issuer =
       *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
 
-  auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New();
-  key_commitment_result->keys.push_back(
-      mojom::TrustTokenVerificationKey::New("key", /*expiry=*/base::Time()));
-  key_commitment_result->protocol_version =
-      mojom::TrustTokenProtocolVersion::kTrustTokenV1;
-  key_commitment_result->id = 1;
-  key_commitment_result->batch_size =
-      static_cast<int>(kMaximumTrustTokenIssuanceBatchSize + 1);
-  auto getter = std::make_unique<FixedKeyCommitmentGetter>(
-      issuer, std::move(key_commitment_result));
-
   auto cryptographer = std::make_unique<MockCryptographer>();
   EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true));
   EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true));
@@ -666,7 +617,9 @@
 
   TrustTokenRequestIssuanceHelper helper(
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
-      store.get(), getter.get(), std::move(cryptographer));
+      store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
+      std::make_unique<MockLocalOperationDelegate>(),
+      base::BindRepeating(&IsCurrentOperatingSystem));
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -675,4 +628,297 @@
             mojom::TrustTokenOperationStatus::kOk);
 }
 
+class TrustTokenRequestIssuanceHelperTestWithPlatformIssuance
+    : public TrustTokenRequestIssuanceHelperTest {
+ public:
+  TrustTokenRequestIssuanceHelperTestWithPlatformIssuance() {
+    // This assertion helps safeguard against the brittleness of deserializing
+    // "true".
+    static_assert(
+        std::is_same<decltype(features::kPlatformProvidedTrustTokenIssuance
+                                  .default_value),
+                     const bool>::value,
+        "Need to update this initializaiton logic if the type of the param "
+        "changes.");
+    features_.InitAndEnableFeatureWithParameters(
+        features::kTrustTokens,
+        {{features::kPlatformProvidedTrustTokenIssuance.name, "true"}});
+  }
+
+ private:
+  base::test::ScopedFeatureList features_;
+};
+
+TEST_F(TrustTokenRequestIssuanceHelperTestWithPlatformIssuance,
+       DiversionToOsSuccess) {
+  // When an operation's diverted to the operating system and succeeds, we
+  // should report kOperationSuccessfullyFulfilledLocally.
+  std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting();
+
+  SuitableTrustTokenOrigin issuer =
+      *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
+
+  auto key_commitment_result = ReasonableKeyCommitmentResult();
+  key_commitment_result->request_issuance_locally_on.push_back(
+      mojom::TrustTokenKeyCommitmentResult::Os::kAndroid);
+  key_commitment_result->unavailable_local_issuance_fallback =
+      mojom::TrustTokenKeyCommitmentResult::UnavailableLocalIssuanceFallback::
+          kReturnWithError;
+  auto getter = std::make_unique<FixedKeyCommitmentGetter>(
+      issuer, std::move(key_commitment_result));
+
+  // Have the Trust Tokens issuance conclude by the underlying cryptographic
+  // library returning one signed, unblinded token associated with the same
+  // returned from the key commitment.
+  auto unblinded_tokens = std::make_unique<UnblindedTokens>();
+  unblinded_tokens->body_of_verifying_key =
+      ReasonableKeyCommitmentResult()->keys.front()->body;
+  unblinded_tokens->tokens.push_back("a signed, unblinded token");
+
+  auto cryptographer = std::make_unique<MockCryptographer>();
+  EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true));
+  EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true));
+  EXPECT_CALL(*cryptographer, BeginIssuance(_))
+      .WillOnce(
+          Return(std::string("this string contains some blinded tokens")));
+  EXPECT_CALL(*cryptographer, ConfirmIssuance(StrEq("response from issuer")))
+      .WillOnce(Return(ByMove(std::move((unblinded_tokens)))));
+
+  auto local_operation_delegate =
+      std::make_unique<MockLocalOperationDelegate>();
+  auto answer = mojom::FulfillTrustTokenIssuanceAnswer::New();
+  answer->status = mojom::FulfillTrustTokenIssuanceAnswer::Status::kOk;
+  answer->response = "response from issuer";
+  auto receive_answer =
+      [&answer](
+          base::OnceCallback<void(mojom::FulfillTrustTokenIssuanceAnswerPtr)>
+              callback) { std::move(callback).Run(std::move(answer)); };
+  EXPECT_CALL(*local_operation_delegate, FulfillIssuance(_, _))
+      .WillOnce(WithArgs<1>(Invoke(receive_answer)));
+
+  TrustTokenRequestIssuanceHelper helper(
+      *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
+      store.get(), getter.get(), std::move(cryptographer),
+      std::move(local_operation_delegate),
+      base::BindRepeating([](mojom::TrustTokenKeyCommitmentResult::Os os) {
+        return os == mojom::TrustTokenKeyCommitmentResult::Os::kAndroid;
+      }));
+
+  auto request = MakeURLRequest("https://issuer.com/");
+  request->set_initiator(issuer);
+
+  ASSERT_EQ(
+      ExecuteBeginOperationAndWaitForResult(&helper, request.get()),
+      mojom::TrustTokenOperationStatus::kOperationSuccessfullyFulfilledLocally);
+
+  // After the operation has successfully finished, the trust tokens parsed from
+  // the server response should be in the store.
+  auto match_all_keys =
+      base::BindRepeating([](const std::string&) { return true; });
+  EXPECT_THAT(
+      store->RetrieveMatchingTokens(issuer, std::move(match_all_keys)),
+      ElementsAre(Property(&TrustToken::body, "a signed, unblinded token")));
+}
+
+TEST_F(TrustTokenRequestIssuanceHelperTestWithPlatformIssuance,
+       ErrorDivertingToOs) {
+  // When an operation's diverted to the operating system and fails because the
+  // operation can't be executed in the current environment, but *not* because
+  // we're on the wrong OS, we should report kUnavailable (no matter the
+  // issuer's configured fallback).
+  std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting();
+
+  SuitableTrustTokenOrigin issuer =
+      *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
+
+  auto key_commitment_result = ReasonableKeyCommitmentResult();
+  key_commitment_result->request_issuance_locally_on.push_back(
+      mojom::TrustTokenKeyCommitmentResult::Os::kAndroid);
+  key_commitment_result->unavailable_local_issuance_fallback =
+      mojom::TrustTokenKeyCommitmentResult::UnavailableLocalIssuanceFallback::
+          kWebIssuance;
+  auto getter = std::make_unique<FixedKeyCommitmentGetter>(
+      issuer, std::move(key_commitment_result));
+
+  auto cryptographer = std::make_unique<MockCryptographer>();
+  EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true));
+  EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true));
+  EXPECT_CALL(*cryptographer, BeginIssuance(_))
+      .WillOnce(
+          Return(std::string("this string contains some blinded tokens")));
+
+  // Respond to the local issuance request with kNotFound, indicating that there
+  // was no way to execute the operation locally:
+  auto local_operation_delegate =
+      std::make_unique<MockLocalOperationDelegate>();
+  auto answer = mojom::FulfillTrustTokenIssuanceAnswer::New();
+  answer->status = mojom::FulfillTrustTokenIssuanceAnswer::Status::kNotFound;
+  auto receive_answer =
+      [&answer](
+          base::OnceCallback<void(mojom::FulfillTrustTokenIssuanceAnswerPtr)>
+              callback) { std::move(callback).Run(std::move(answer)); };
+  EXPECT_CALL(*local_operation_delegate, FulfillIssuance(_, _))
+      .WillOnce(WithArgs<1>(Invoke(receive_answer)));
+
+  TrustTokenRequestIssuanceHelper helper(
+      *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
+      store.get(), getter.get(), std::move(cryptographer),
+      std::move(local_operation_delegate),
+      base::BindRepeating([](mojom::TrustTokenKeyCommitmentResult::Os os) {
+        return os == mojom::TrustTokenKeyCommitmentResult::Os::kAndroid;
+      }));
+
+  auto request = MakeURLRequest("https://issuer.com/");
+  request->set_initiator(issuer);
+
+  ASSERT_EQ(ExecuteBeginOperationAndWaitForResult(&helper, request.get()),
+            mojom::TrustTokenOperationStatus::kUnavailable);
+}
+
+TEST_F(TrustTokenRequestIssuanceHelperTestWithPlatformIssuance,
+       DiversionToOsWrongOsWithFallbackConfiguredToReturnWithError) {
+  // When an operation can't be diverted to the operating system because the
+  // current platform wasn't among those specified by the issuer for local
+  // execution, and the issuer specified a fallback behavior of
+  // "return_with_error" in its key commitment, we should return kUnavailable.
+  std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting();
+
+  SuitableTrustTokenOrigin issuer =
+      *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
+
+  auto key_commitment_result = ReasonableKeyCommitmentResult();
+  key_commitment_result->request_issuance_locally_on.push_back(
+      mojom::TrustTokenKeyCommitmentResult::Os::kAndroid);
+  key_commitment_result->unavailable_local_issuance_fallback =
+      mojom::TrustTokenKeyCommitmentResult::UnavailableLocalIssuanceFallback::
+          kReturnWithError;
+  auto getter = std::make_unique<FixedKeyCommitmentGetter>(
+      issuer, std::move(key_commitment_result));
+
+  TrustTokenRequestIssuanceHelper helper(
+      *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
+      store.get(), getter.get(), std::make_unique<MockCryptographer>(),
+      std::make_unique<MockLocalOperationDelegate>(),
+      // Fail to match to the current OS...
+      base::BindLambdaForTesting(
+          [](mojom::TrustTokenKeyCommitmentResult::Os) { return false; }));
+
+  auto request = MakeURLRequest("https://issuer.com/");
+  request->set_initiator(issuer);
+
+  // ... and the operation should fail.
+  ASSERT_EQ(ExecuteBeginOperationAndWaitForResult(&helper, request.get()),
+            mojom::TrustTokenOperationStatus::kUnavailable);
+}
+
+TEST_F(TrustTokenRequestIssuanceHelperTestWithPlatformIssuance,
+       DiversionToOsWrongOsWithFallbackConfiguredToRequestWebIssuance) {
+  // When an operation can't be diverted to the operating system because the
+  // current platform wasn't among those specified by the issuer for local
+  // execution, and the issuer specified a fallback behavior of
+  // "web_issuance" in its key commitment, we should attempt a web issuance.
+  std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting();
+
+  SuitableTrustTokenOrigin issuer =
+      *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
+
+  auto key_commitment_result = ReasonableKeyCommitmentResult();
+  key_commitment_result->request_issuance_locally_on.push_back(
+      mojom::TrustTokenKeyCommitmentResult::Os::kAndroid);
+  key_commitment_result->unavailable_local_issuance_fallback =
+      mojom::TrustTokenKeyCommitmentResult::UnavailableLocalIssuanceFallback::
+          kWebIssuance;
+  auto getter = std::make_unique<FixedKeyCommitmentGetter>(
+      issuer, std::move(key_commitment_result));
+
+  auto cryptographer = std::make_unique<MockCryptographer>();
+  EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true));
+  EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true));
+  EXPECT_CALL(*cryptographer, BeginIssuance(_))
+      .WillOnce(
+          Return(std::string("this string contains some blinded tokens")));
+
+  TrustTokenRequestIssuanceHelper helper(
+      *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
+      store.get(), getter.get(), std::move(cryptographer),
+      std::make_unique<MockLocalOperationDelegate>(),
+      // Fail to match to the current OS...
+      base::BindLambdaForTesting(
+          [](mojom::TrustTokenKeyCommitmentResult::Os) { return false; }));
+
+  auto request = MakeURLRequest("https://issuer.com/");
+  request->set_initiator(issuer);
+
+  // ... and the helper should finish beginning a standard Web issuance, because
+  // the issuer configured a fallback of |kWebIssuance|.
+  ASSERT_EQ(ExecuteBeginOperationAndWaitForResult(&helper, request.get()),
+            mojom::TrustTokenOperationStatus::kOk);
+}
+
+TEST_F(TrustTokenRequestIssuanceHelperTestWithPlatformIssuance,
+       DivertsToAndroidOnAndroid) {
+  // Test that, when an issuer specifies that we should attempt issuance locally
+  // on Android, we do so.
+  std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting();
+
+  SuitableTrustTokenOrigin issuer =
+      *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
+
+  auto key_commitment_result = ReasonableKeyCommitmentResult();
+  // Specify that we should request issuance locally on Android...
+  key_commitment_result->request_issuance_locally_on.push_back(
+      mojom::TrustTokenKeyCommitmentResult::Os::kAndroid);
+  key_commitment_result->unavailable_local_issuance_fallback =
+      mojom::TrustTokenKeyCommitmentResult::UnavailableLocalIssuanceFallback::
+          kReturnWithError;
+
+  auto getter = std::make_unique<FixedKeyCommitmentGetter>(
+      issuer, std::move(key_commitment_result));
+
+  auto cryptographer = std::make_unique<MockCryptographer>();
+
+  // Use a strict mock to make the test fail if the delegate gets called on
+  // non-Android platforms:
+  auto local_operation_delegate =
+      std::make_unique<StrictMock<MockLocalOperationDelegate>>();
+#if defined(OS_ANDROID)
+  EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true));
+  EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true));
+  EXPECT_CALL(*cryptographer, BeginIssuance(_))
+      .WillOnce(
+          Return(std::string("this string contains some blinded tokens")));
+
+  // If we're on Android, respond to the local issuance request with an error.
+  auto answer = mojom::FulfillTrustTokenIssuanceAnswer::New();
+  answer->status =
+      mojom::FulfillTrustTokenIssuanceAnswer::Status::kUnknownError;
+  auto receive_answer =
+      [&answer](
+          base::OnceCallback<void(mojom::FulfillTrustTokenIssuanceAnswerPtr)>
+              callback) { std::move(callback).Run(std::move(answer)); };
+  EXPECT_CALL(*local_operation_delegate, FulfillIssuance(_, _))
+      .WillOnce(WithArgs<1>(Invoke(receive_answer)));
+#endif  // defined(OS_ANDROID)
+
+  TrustTokenRequestIssuanceHelper helper(
+      *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
+      store.get(), getter.get(), std::move(cryptographer),
+      std::move(local_operation_delegate),
+      base::BindRepeating(&IsCurrentOperatingSystem));
+
+  auto request = MakeURLRequest("https://issuer.com/");
+  request->set_initiator(issuer);
+
+  // If we're on Android, we should observe the error returned by the delegate;
+  // if we're not on Android, we should observe error saying we couldn't execute
+  // issuance locally.
+  ASSERT_EQ(ExecuteBeginOperationAndWaitForResult(&helper, request.get()),
+#if defined(OS_ANDROID)
+            mojom::TrustTokenOperationStatus::kUnknownError
+#else
+            mojom::TrustTokenOperationStatus::kUnavailable
+#endif  // defined(OS_ANDROID)
+  );
+}
+
 }  // namespace network
diff --git a/services/tracing/perfetto/consumer_host.cc b/services/tracing/perfetto/consumer_host.cc
index 716e101..daa226d 100644
--- a/services/tracing/perfetto/consumer_host.cc
+++ b/services/tracing/perfetto/consumer_host.cc
@@ -495,8 +495,8 @@
                                                    bool has_more) {
   auto slice = std::make_unique<StreamWriter::Slice>();
   slice->swap(json);
-  read_buffers_stream_writer_.Post(FROM_HERE, &StreamWriter::WriteToStream,
-                                   std::move(slice), has_more);
+  read_buffers_stream_writer_.AsyncCall(&StreamWriter::WriteToStream)
+      .WithArgs(std::move(slice), has_more);
 
   if (!has_more) {
     read_buffers_stream_writer_.Reset();
@@ -559,8 +559,8 @@
       chunk->append(static_cast<const char*>(slice.start), slice.size);
     }
   }
-  read_buffers_stream_writer_.Post(FROM_HERE, &StreamWriter::WriteToStream,
-                                   std::move(chunk), has_more);
+  read_buffers_stream_writer_.AsyncCall(&StreamWriter::WriteToStream)
+      .WithArgs(std::move(chunk), has_more);
   if (!has_more) {
     read_buffers_stream_writer_.Reset();
   }
diff --git a/sql/database.cc b/sql/database.cc
index 59f1959d..bb23163 100644
--- a/sql/database.cc
+++ b/sql/database.cc
@@ -240,17 +240,7 @@
 Database::Database() : Database({.exclusive_locking = false}) {}
 
 Database::Database(DatabaseOptions options)
-    : db_(nullptr),
-      options_(options),
-      transaction_nesting_(0),
-      needs_rollback_(false),
-      in_memory_(false),
-      poisoned_(false),
-      mmap_alt_status_(false),
-      mmap_disabled_(!enable_mmap_by_default_),
-      mmap_enabled_(false),
-      total_changes_at_last_release_(0),
-      stats_histogram_(nullptr) {
+    : options_(options), mmap_disabled_(!enable_mmap_by_default_) {
   DCHECK_GE(options.page_size, 512);
   DCHECK_LE(options.page_size, 65536);
   DCHECK(!(options.page_size & (options.page_size - 1)))
diff --git a/sql/database.h b/sql/database.h
index c8f365e..b4eeb9b 100644
--- a/sql/database.h
+++ b/sql/database.h
@@ -779,7 +779,7 @@
 
   // The actual sqlite database. Will be null before Init has been called or if
   // Init resulted in an error.
-  sqlite3* db_;
+  sqlite3* db_ = nullptr;
 
   // TODO(shuagga@microsoft.com): Make `options_` const after removing all
   // setters.
@@ -798,36 +798,36 @@
   std::set<StatementRef*> open_statements_;
 
   // Number of currently-nested transactions.
-  int transaction_nesting_;
+  int transaction_nesting_ = 0;
 
   // True if any of the currently nested transactions have been rolled back.
   // When we get to the outermost transaction, this will determine if we do
   // a rollback instead of a commit.
-  bool needs_rollback_;
+  bool needs_rollback_ = false;
 
   // True if database is open with OpenInMemory(), False if database is open
   // with Open().
-  bool in_memory_;
+  bool in_memory_ = false;
 
   // |true| if the Database was closed using RazeAndClose().  Used
   // to enable diagnostics to distinguish calls to never-opened
   // databases (incorrect use of the API) from calls to once-valid
   // databases.
-  bool poisoned_;
+  bool poisoned_ = false;
 
   // |true| to use alternate storage for tracking mmap status.
-  bool mmap_alt_status_;
+  bool mmap_alt_status_ = false;
 
   // |true| if SQLite memory-mapped I/O is not desired for this database.
   bool mmap_disabled_;
 
   // |true| if SQLite memory-mapped I/O was enabled for this database.
   // Used by ReleaseCacheMemoryIfNeeded().
-  bool mmap_enabled_;
+  bool mmap_enabled_ = false;
 
   // Used by ReleaseCacheMemoryIfNeeded() to track if new changes have happened
   // since memory was last released.
-  int total_changes_at_last_release_;
+  int total_changes_at_last_release_ = 0;
 
   ErrorCallback error_callback_;
 
@@ -835,7 +835,7 @@
   std::string histogram_tag_;
 
   // Linear histogram for RecordEvent().
-  base::HistogramBase* stats_histogram_;
+  base::HistogramBase* stats_histogram_ = nullptr;
 
   // Stores the dump provider object when db is open.
   std::unique_ptr<DatabaseMemoryDumpProvider> memory_dump_provider_;
diff --git a/sql/meta_table.cc b/sql/meta_table.cc
index 6bf0cff..03bd25a 100644
--- a/sql/meta_table.cc
+++ b/sql/meta_table.cc
@@ -55,7 +55,7 @@
 
 namespace sql {
 
-MetaTable::MetaTable() : db_(nullptr) {}
+MetaTable::MetaTable() = default;
 
 MetaTable::~MetaTable() = default;
 
diff --git a/sql/meta_table.h b/sql/meta_table.h
index 9b4acfe..02aa88b 100644
--- a/sql/meta_table.h
+++ b/sql/meta_table.h
@@ -113,7 +113,7 @@
   void PrepareSetStatement(Statement* statement, const char* key);
   bool PrepareGetStatement(Statement* statement, const char* key);
 
-  Database* db_;
+  Database* db_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(MetaTable);
 };
diff --git a/sql/statement.cc b/sql/statement.cc
index aba466d..e953caf4 100644
--- a/sql/statement.cc
+++ b/sql/statement.cc
@@ -22,12 +22,10 @@
 Statement::Statement()
     : ref_(base::MakeRefCounted<Database::StatementRef>(nullptr,
                                                         nullptr,
-                                                        false)),
-      stepped_(false),
-      succeeded_(false) {}
+                                                        false)) {}
 
 Statement::Statement(scoped_refptr<Database::StatementRef> ref)
-    : ref_(std::move(ref)), stepped_(false), succeeded_(false) {}
+    : ref_(std::move(ref)) {}
 
 Statement::~Statement() {
   // Free the resources associated with this statement. We assume there's only
diff --git a/sql/statement.h b/sql/statement.h
index ba31163..c609610 100644
--- a/sql/statement.h
+++ b/sql/statement.h
@@ -190,10 +190,10 @@
   // Set after Step() or Run() are called, reset by Reset().  Used to
   // prevent accidental calls to API functions which would not work
   // correctly after stepping has started.
-  bool stepped_;
+  bool stepped_ = false;
 
   // See Succeeded() for what this holds.
-  bool succeeded_;
+  bool succeeded_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(Statement);
 };
diff --git a/sql/transaction.cc b/sql/transaction.cc
index 4abc410..c5319002 100644
--- a/sql/transaction.cc
+++ b/sql/transaction.cc
@@ -9,8 +9,7 @@
 
 namespace sql {
 
-Transaction::Transaction(Database* database)
-    : database_(database), is_open_(false) {}
+Transaction::Transaction(Database* database) : database_(database) {}
 
 Transaction::~Transaction() {
   if (is_open_)
diff --git a/sql/transaction.h b/sql/transaction.h
index 0b9af69f..27e8dfb 100644
--- a/sql/transaction.h
+++ b/sql/transaction.h
@@ -50,7 +50,7 @@
 
   // True when the transaction is open, false when it's already been committed
   // or rolled back.
-  bool is_open_;
+  bool is_open_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(Transaction);
 };
diff --git a/storage/browser/BUILD.gn b/storage/browser/BUILD.gn
index 80edabe..f082ddb 100644
--- a/storage/browser/BUILD.gn
+++ b/storage/browser/BUILD.gn
@@ -284,6 +284,8 @@
     "file_system/file_stream_reader_test.h",
     "file_system/file_stream_test_utils.cc",
     "file_system/file_stream_test_utils.h",
+    "file_system/file_stream_writer_test.cc",
+    "file_system/file_stream_writer_test.h",
     "file_system/file_system_context_unittest.cc",
     "file_system/file_system_file_stream_reader_unittest.cc",
     "file_system/file_system_operation_impl_unittest.cc",
@@ -307,6 +309,7 @@
     "file_system/quota/quota_reservation_manager_unittest.cc",
     "file_system/recursive_operation_delegate_unittest.cc",
     "file_system/sandbox_directory_database_unittest.cc",
+    "file_system/sandbox_file_stream_writer_unittest.cc",
     "file_system/sandbox_file_system_backend_delegate_unittest.cc",
     "file_system/sandbox_file_system_backend_unittest.cc",
     "file_system/sandbox_isolated_origin_database_unittest.cc",
diff --git a/storage/browser/file_system/file_stream_writer_test.cc b/storage/browser/file_system/file_stream_writer_test.cc
new file mode 100644
index 0000000..62f15b89
--- /dev/null
+++ b/storage/browser/file_system/file_stream_writer_test.cc
@@ -0,0 +1,11 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "storage/browser/file_system/file_stream_writer_test.h"
+
+namespace storage {
+
+const base::StringPiece FileStreamWriterTest::kTestFileName;
+
+}  // namespace storage
\ No newline at end of file
diff --git a/storage/browser/file_system/file_stream_writer_test.h b/storage/browser/file_system/file_stream_writer_test.h
new file mode 100644
index 0000000..004ea72
--- /dev/null
+++ b/storage/browser/file_system/file_stream_writer_test.h
@@ -0,0 +1,237 @@
+// 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 STORAGE_BROWSER_FILE_SYSTEM_FILE_STREAM_WRITER_TEST_H_
+#define STORAGE_BROWSER_FILE_SYSTEM_FILE_STREAM_WRITER_TEST_H_
+
+#include <cstdio>
+#include "base/bind_helpers.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/single_thread_task_runner.h"
+#include "base/test/task_environment.h"
+#include "base/threading/thread.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
+#include "storage/browser/file_system/file_stream_test_utils.h"
+#include "storage/browser/file_system/file_stream_writer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace storage {
+
+// An interface for derived FileStreamWriter to implement. This allows multiple
+// FileStreamWriter implementations can share the same test framework. Tests
+// should implement CreateFileWithContent, CreateWriter, FilePathExists, and
+// GetFileContent to manipulate files for their particular implementation.
+class FileStreamWriterTest : public testing::Test {
+ public:
+  static constexpr base::StringPiece kTestFileName = "file_a";
+
+  virtual bool CreateFileWithContent(const std::string& name,
+                                     const std::string& data) = 0;
+  virtual std::unique_ptr<FileStreamWriter> CreateWriter(
+      const std::string& name,
+      int64_t offset) = 0;
+  virtual bool FilePathExists(const std::string& name) = 0;
+  virtual std::string GetFileContent(const std::string& name) = 0;
+
+  static void NeverCalled(int unused) { ADD_FAILURE(); }
+
+ private:
+  base::test::SingleThreadTaskEnvironment task_environment_{
+      base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
+};
+
+template <class SubClass>
+class FileStreamWriterTypedTest : public SubClass {
+ public:
+  void SetUp() override { SubClass::SetUp(); }
+};
+
+TYPED_TEST_SUITE_P(FileStreamWriterTypedTest);
+
+TYPED_TEST_P(FileStreamWriterTypedTest, Write) {
+  EXPECT_TRUE(
+      this->CreateFileWithContent(std::string(this->kTestFileName), "foobar"));
+
+  std::unique_ptr<FileStreamWriter> writer(
+      this->CreateWriter(std::string(this->kTestFileName), 0));
+  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "foo"));
+  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "bar"));
+
+  EXPECT_TRUE(this->FilePathExists(std::string(this->kTestFileName)));
+  EXPECT_EQ("foobar", this->GetFileContent(std::string(this->kTestFileName)));
+}
+
+TYPED_TEST_P(FileStreamWriterTypedTest, WriteMiddle) {
+  EXPECT_TRUE(
+      this->CreateFileWithContent(std::string(this->kTestFileName), "foobar"));
+
+  std::unique_ptr<FileStreamWriter> writer(
+      this->CreateWriter(std::string(this->kTestFileName), 2));
+  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "xxx"));
+
+  EXPECT_TRUE(this->FilePathExists(std::string(this->kTestFileName)));
+  EXPECT_EQ("foxxxr", this->GetFileContent(std::string(this->kTestFileName)));
+}
+
+TYPED_TEST_P(FileStreamWriterTypedTest, WriteNearEnd) {
+  EXPECT_TRUE(
+      this->CreateFileWithContent(std::string(this->kTestFileName), "foobar"));
+
+  std::unique_ptr<FileStreamWriter> writer(
+      this->CreateWriter(std::string(this->kTestFileName), 5));
+  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "xxx"));
+
+  EXPECT_TRUE(this->FilePathExists(std::string(this->kTestFileName)));
+  EXPECT_EQ("foobaxxx", this->GetFileContent(std::string(this->kTestFileName)));
+}
+
+TYPED_TEST_P(FileStreamWriterTypedTest, WriteEnd) {
+  EXPECT_TRUE(
+      this->CreateFileWithContent(std::string(this->kTestFileName), "foobar"));
+
+  std::unique_ptr<FileStreamWriter> writer(
+      this->CreateWriter(std::string(this->kTestFileName), 6));
+  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "xxx"));
+
+  EXPECT_TRUE(this->FilePathExists(std::string(this->kTestFileName)));
+  EXPECT_EQ("foobarxxx",
+            this->GetFileContent(std::string(this->kTestFileName)));
+}
+
+TYPED_TEST_P(FileStreamWriterTypedTest, WriteAfterEnd) {
+  EXPECT_TRUE(
+      this->CreateFileWithContent(std::string(this->kTestFileName), "foobar"));
+
+  std::unique_ptr<FileStreamWriter> writer(
+      this->CreateWriter(std::string(this->kTestFileName), 7));
+  EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE,
+            WriteStringToWriter(writer.get(), "xxx"));
+
+  EXPECT_TRUE(this->FilePathExists(std::string(this->kTestFileName)));
+  EXPECT_EQ("foobar", this->GetFileContent(std::string(this->kTestFileName)));
+}
+
+TYPED_TEST_P(FileStreamWriterTypedTest, WriteFailForNonexistingFile) {
+  ASSERT_FALSE(this->FilePathExists(std::string(this->kTestFileName)));
+
+  std::unique_ptr<FileStreamWriter> writer(
+      this->CreateWriter(std::string(this->kTestFileName), 0));
+  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, WriteStringToWriter(writer.get(), "foo"));
+
+  EXPECT_FALSE(this->FilePathExists(std::string(this->kTestFileName)));
+}
+
+TYPED_TEST_P(FileStreamWriterTypedTest, CancelBeforeOperation) {
+  std::unique_ptr<FileStreamWriter> writer(
+      this->CreateWriter(std::string(this->kTestFileName), 0));
+  // Cancel immediately fails when there's no in-flight operation.
+  EXPECT_EQ(net::ERR_UNEXPECTED, writer->Cancel(base::DoNothing()));
+}
+
+TYPED_TEST_P(FileStreamWriterTypedTest, CancelAfterFinishedOperation) {
+  EXPECT_TRUE(
+      this->CreateFileWithContent(std::string(this->kTestFileName), "foobar"));
+  std::unique_ptr<FileStreamWriter> writer(
+      this->CreateWriter(std::string(this->kTestFileName), 0));
+  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "foo"));
+
+  // Cancel immediately fails when there's no in-flight operation.
+  EXPECT_EQ(net::ERR_UNEXPECTED, writer->Cancel(base::DoNothing()));
+
+  // Write operation is already completed.
+  EXPECT_TRUE(this->FilePathExists(std::string(this->kTestFileName)));
+  EXPECT_EQ("foobar", this->GetFileContent(std::string(this->kTestFileName)));
+}
+
+TYPED_TEST_P(FileStreamWriterTypedTest, CancelWrite) {
+  EXPECT_TRUE(
+      this->CreateFileWithContent(std::string(this->kTestFileName), "foobar"));
+  std::unique_ptr<FileStreamWriter> writer(
+      this->CreateWriter(std::string(this->kTestFileName), 0));
+
+  scoped_refptr<net::StringIOBuffer> buffer(
+      base::MakeRefCounted<net::StringIOBuffer>("xxx"));
+  int result =
+      writer->Write(buffer.get(), buffer->size(),
+                    base::BindOnce(&FileStreamWriterTest::NeverCalled));
+  ASSERT_EQ(net::ERR_IO_PENDING, result);
+
+  net::TestCompletionCallback callback;
+  writer->Cancel(callback.callback());
+  int cancel_result = writer->Cancel(callback.callback());
+  EXPECT_EQ(net::OK, callback.GetResult(cancel_result));
+}
+
+TYPED_TEST_P(FileStreamWriterTypedTest, CancelFlush) {
+  EXPECT_TRUE(
+      this->CreateFileWithContent(std::string(this->kTestFileName), ""));
+  std::unique_ptr<FileStreamWriter> writer(
+      this->CreateWriter(std::string(this->kTestFileName), 0));
+
+  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "foo"));
+
+  int cancel_expectation = net::OK;
+  int result = writer->Flush(base::DoNothing());
+  // Flush can run synchronously or asynchronously.
+  if (result == net::OK) {
+    // Cancel() should error if called when there is no in-flight operation.
+    cancel_expectation = net::ERR_UNEXPECTED;
+  } else {
+    EXPECT_EQ(net::ERR_IO_PENDING, result);
+  }
+  net::TestCompletionCallback callback;
+  int cancel_result = writer->Cancel(callback.callback());
+  EXPECT_EQ(cancel_expectation, callback.GetResult(cancel_result));
+
+  EXPECT_EQ("foo", this->GetFileContent(std::string(this->kTestFileName)));
+}
+
+TYPED_TEST_P(FileStreamWriterTypedTest, FlushBeforeWriting) {
+  EXPECT_TRUE(
+      this->CreateFileWithContent(std::string(this->kTestFileName), ""));
+  std::unique_ptr<FileStreamWriter> writer(
+      this->CreateWriter(std::string(this->kTestFileName), 0));
+
+  EXPECT_EQ(net::OK, writer->Flush(base::DoNothing()));
+  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "foo"));
+  EXPECT_EQ("foo", this->GetFileContent(std::string(this->kTestFileName)));
+}
+
+TYPED_TEST_P(FileStreamWriterTypedTest, FlushAfterWriting) {
+  EXPECT_TRUE(
+      this->CreateFileWithContent(std::string(this->kTestFileName), ""));
+  std::unique_ptr<FileStreamWriter> writer(
+      this->CreateWriter(std::string(this->kTestFileName), 0));
+
+  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "foo"));
+
+  net::TestCompletionCallback callback;
+  int result =
+      writer->Flush(base::OnceCallback<void(int)>(callback.callback()));
+  ASSERT_EQ(net::OK, callback.GetResult(result));
+
+  EXPECT_EQ("foo", this->GetFileContent(std::string(this->kTestFileName)));
+}
+
+REGISTER_TYPED_TEST_SUITE_P(FileStreamWriterTypedTest,
+                            Write,
+                            WriteMiddle,
+                            WriteNearEnd,
+                            WriteEnd,
+                            WriteAfterEnd,
+                            WriteFailForNonexistingFile,
+                            CancelBeforeOperation,
+                            CancelAfterFinishedOperation,
+                            CancelWrite,
+                            CancelFlush,
+                            FlushBeforeWriting,
+                            FlushAfterWriting);
+
+}  // namespace storage
+
+#endif  // STORAGE_BROWSER_FILE_SYSTEM_FILE_STREAM_WRITER_TEST_H_
\ No newline at end of file
diff --git a/storage/browser/file_system/local_file_stream_writer_unittest.cc b/storage/browser/file_system/local_file_stream_writer_unittest.cc
index 704fe4f1..37df4f07 100644
--- a/storage/browser/file_system/local_file_stream_writer_unittest.cc
+++ b/storage/browser/file_system/local_file_stream_writer_unittest.cc
@@ -10,33 +10,26 @@
 #include <string>
 
 #include "base/bind.h"
-#include "base/callback.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/test/task_environment.h"
-#include "base/threading/thread.h"
 #include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
 #include "net/base/test_completion_callback.h"
 #include "storage/browser/file_system/file_stream_test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
+#include "storage/browser/file_system/file_stream_writer_test.h"
 
 namespace storage {
 
-namespace {
-void NeverCalled(int unused) {
-  ADD_FAILURE();
-}
-}  // namespace
-
-class LocalFileStreamWriterTest : public testing::Test {
+class LocalFileStreamWriterTest : public FileStreamWriterTest {
  public:
   LocalFileStreamWriterTest() : file_thread_("TestFileThread") {}
 
   void SetUp() override {
     ASSERT_TRUE(file_thread_.Start());
-    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+    ASSERT_TRUE(file_system_directory_.CreateUniqueTempDir());
   }
 
   void TearDown() override {
@@ -44,143 +37,47 @@
     base::RunLoop().RunUntilIdle();
     file_thread_.Stop();
     base::RunLoop().RunUntilIdle();
+    ASSERT_TRUE(file_system_directory_.Delete());
+  }
+
+  base::FilePath Path(const std::string& name) {
+    return file_system_directory_.GetPath().AppendASCII(name);
   }
 
  protected:
-  base::FilePath Path(const std::string& name) {
-    return temp_dir_.GetPath().AppendASCII(name);
+  bool CreateFileWithContent(const std::string& name,
+                             const std::string& data) override {
+    return base::WriteFile(Path(name), data);
   }
 
-  std::string GetFileContent(const base::FilePath& path) {
+  std::unique_ptr<FileStreamWriter> CreateWriter(const std::string& name,
+                                                 int64_t offset) override {
+    return base::WrapUnique(
+        new LocalFileStreamWriter(file_task_runner(), Path(name), offset,
+                                  FileStreamWriter::OPEN_EXISTING_FILE));
+  }
+
+  bool FilePathExists(const std::string& name) override {
+    return base::PathExists(Path(name));
+  }
+
+  std::string GetFileContent(const std::string& name) override {
     std::string content;
-    base::ReadFileToString(path, &content);
+    base::ReadFileToString(Path(name), &content);
     return content;
   }
 
-  base::FilePath CreateFileWithContent(const std::string& name,
-                                       const std::string& data) {
-    base::FilePath path = Path(name);
-    base::WriteFile(path, data);
-    return path;
-  }
-
   base::SingleThreadTaskRunner* file_task_runner() const {
     return file_thread_.task_runner().get();
   }
 
-  LocalFileStreamWriter* CreateWriter(const base::FilePath& path,
-                                      int64_t offset) {
-    return new LocalFileStreamWriter(file_task_runner(), path, offset,
-                                     FileStreamWriter::OPEN_EXISTING_FILE);
-  }
-
  private:
-  base::test::SingleThreadTaskEnvironment task_environment_{
-      base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
+  base::ScopedTempDir file_system_directory_;
   base::Thread file_thread_;
-  base::ScopedTempDir temp_dir_;
 };
 
-TEST_F(LocalFileStreamWriterTest, Write) {
-  base::FilePath path = CreateFileWithContent("file_a", std::string());
-  std::unique_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 0));
-  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "foo"));
-  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "bar"));
-  writer.reset();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(base::PathExists(path));
-  EXPECT_EQ("foobar", GetFileContent(path));
-}
-
-TEST_F(LocalFileStreamWriterTest, WriteMiddle) {
-  base::FilePath path = CreateFileWithContent("file_a", "foobar");
-  std::unique_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 2));
-  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "xxx"));
-  writer.reset();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(base::PathExists(path));
-  EXPECT_EQ("foxxxr", GetFileContent(path));
-}
-
-TEST_F(LocalFileStreamWriterTest, WriteNearEnd) {
-  base::FilePath path = CreateFileWithContent("file_a", "foobar");
-  std::unique_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 5));
-  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "xxx"));
-  writer.reset();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(base::PathExists(path));
-  EXPECT_EQ("foobaxxx", GetFileContent(path));
-}
-
-TEST_F(LocalFileStreamWriterTest, WriteEnd) {
-  base::FilePath path = CreateFileWithContent("file_a", "foobar");
-  std::unique_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 6));
-  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "xxx"));
-  writer.reset();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(base::PathExists(path));
-  EXPECT_EQ("foobarxxx", GetFileContent(path));
-}
-
-TEST_F(LocalFileStreamWriterTest, WriteAfterEnd) {
-  base::FilePath path = CreateFileWithContent("file_a", "foobar");
-  std::unique_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 7));
-  EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE,
-            WriteStringToWriter(writer.get(), "xxx"));
-  writer.reset();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(base::PathExists(path));
-  EXPECT_EQ("foobar", GetFileContent(path));
-}
-
-TEST_F(LocalFileStreamWriterTest, WriteFailForNonexistingFile) {
-  base::FilePath path = Path("file_a");
-  ASSERT_FALSE(base::PathExists(path));
-  std::unique_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 0));
-  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, WriteStringToWriter(writer.get(), "foo"));
-  writer.reset();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(base::PathExists(path));
-}
-
-TEST_F(LocalFileStreamWriterTest, CancelBeforeOperation) {
-  base::FilePath path = Path("file_a");
-  std::unique_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 0));
-  // Cancel immediately fails when there's no in-flight operation.
-  int cancel_result = writer->Cancel(base::BindOnce(&NeverCalled));
-  EXPECT_EQ(net::ERR_UNEXPECTED, cancel_result);
-}
-
-TEST_F(LocalFileStreamWriterTest, CancelAfterFinishedOperation) {
-  base::FilePath path = CreateFileWithContent("file_a", std::string());
-  std::unique_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 0));
-  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "foo"));
-
-  // Cancel immediately fails when there's no in-flight operation.
-  int cancel_result = writer->Cancel(base::BindOnce(&NeverCalled));
-  EXPECT_EQ(net::ERR_UNEXPECTED, cancel_result);
-
-  writer.reset();
-  base::RunLoop().RunUntilIdle();
-  // Write operation is already completed.
-  EXPECT_TRUE(base::PathExists(path));
-  EXPECT_EQ("foo", GetFileContent(path));
-}
-
-TEST_F(LocalFileStreamWriterTest, CancelWrite) {
-  base::FilePath path = CreateFileWithContent("file_a", "foobar");
-  std::unique_ptr<LocalFileStreamWriter> writer(CreateWriter(path, 0));
-
-  scoped_refptr<net::StringIOBuffer> buffer(
-      base::MakeRefCounted<net::StringIOBuffer>("xxx"));
-  int result =
-      writer->Write(buffer.get(), buffer->size(), base::BindOnce(&NeverCalled));
-  ASSERT_EQ(net::ERR_IO_PENDING, result);
-
-  net::TestCompletionCallback callback;
-  writer->Cancel(callback.callback());
-  int cancel_result = callback.WaitForResult();
-  EXPECT_EQ(net::OK, cancel_result);
-}
+INSTANTIATE_TYPED_TEST_SUITE_P(Local,
+                               FileStreamWriterTypedTest,
+                               LocalFileStreamWriterTest);
 
 }  // namespace storage
diff --git a/storage/browser/file_system/memory_file_stream_writer_unittest.cc b/storage/browser/file_system/memory_file_stream_writer_unittest.cc
index f15892c..d60e5b4 100644
--- a/storage/browser/file_system/memory_file_stream_writer_unittest.cc
+++ b/storage/browser/file_system/memory_file_stream_writer_unittest.cc
@@ -13,26 +13,18 @@
 #include "base/bind_helpers.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/test/task_environment.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
-#include "net/base/test_completion_callback.h"
 #include "storage/browser/file_system/file_stream_test_utils.h"
 #include "storage/browser/file_system/file_stream_writer.h"
+#include "storage/browser/file_system/file_stream_writer_test.h"
 #include "storage/browser/file_system/obfuscated_file_util_memory_delegate.h"
-#include "testing/gtest/include/gtest/gtest.h"
 
 namespace storage {
 
-namespace {
-void NeverCalled(int unused) {
-  ADD_FAILURE();
-}
-}  // namespace
-
-class MemoryFileStreamWriterTest : public testing::Test {
+class MemoryFileStreamWriterTest : public FileStreamWriterTest {
  public:
-  MemoryFileStreamWriterTest() {}
+  MemoryFileStreamWriterTest() = default;
 
   void SetUp() override {
     ASSERT_TRUE(file_system_directory_.CreateUniqueTempDir());
@@ -48,12 +40,30 @@
 
   ObfuscatedFileUtilMemoryDelegate* file_util() { return file_util_.get(); }
 
- protected:
   base::FilePath Path(const std::string& name) {
     return file_system_directory_.GetPath().AppendASCII(name);
   }
 
-  std::string GetFileContent(const base::FilePath& path) {
+ protected:
+  bool CreateFileWithContent(const std::string& name,
+                             const std::string& data) override {
+    return file_util()->CreateFileForTesting(Path(name), data) ==
+           base::File::FILE_OK;
+  }
+
+  std::unique_ptr<FileStreamWriter> CreateWriter(const std::string& name,
+                                                 int64_t offset) override {
+    return FileStreamWriter::CreateForMemoryFile(
+        base::ThreadTaskRunnerHandle::Get(), file_util_->GetWeakPtr(),
+        Path(name), offset);
+  }
+
+  bool FilePathExists(const std::string& name) override {
+    return file_util()->PathExists(Path(name));
+  }
+
+  std::string GetFileContent(const std::string& name) override {
+    base::FilePath path = Path(name);
     base::File::Info info;
     EXPECT_EQ(base::File::FILE_OK, file_util()->GetFileInfo(path, &info));
 
@@ -65,148 +75,13 @@
     return std::string(content->data(), info.size);
   }
 
-  std::unique_ptr<FileStreamWriter> CreateWriter(const base::FilePath& path,
-                                                 int64_t offset) {
-    return FileStreamWriter::CreateForMemoryFile(
-        base::ThreadTaskRunnerHandle::Get(), file_util_->GetWeakPtr(), path,
-        offset);
-  }
-
  private:
-  base::test::TaskEnvironment task_environment_;
   base::ScopedTempDir file_system_directory_;
   std::unique_ptr<ObfuscatedFileUtilMemoryDelegate> file_util_;
 };
 
-TEST_F(MemoryFileStreamWriterTest, Write) {
-  base::FilePath path = Path("file_a");
-  bool created;
-  EXPECT_EQ(base::File::FILE_OK, file_util()->EnsureFileExists(path, &created));
-
-  std::unique_ptr<FileStreamWriter> writer(CreateWriter(path, 0));
-  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "foo"));
-  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "bar"));
-  EXPECT_TRUE(file_util()->PathExists(path));
-  EXPECT_EQ("foobar", GetFileContent(path));
-}
-
-TEST_F(MemoryFileStreamWriterTest, WriteMiddle) {
-  base::FilePath path = Path("file_a");
-  EXPECT_EQ(base::File::FILE_OK,
-            file_util()->CreateFileForTesting(path, std::string("foobar")));
-
-  std::unique_ptr<FileStreamWriter> writer(CreateWriter(path, 2));
-  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "xxx"));
-  EXPECT_TRUE(file_util()->PathExists(path));
-  EXPECT_EQ("foxxxr", GetFileContent(path));
-}
-
-TEST_F(MemoryFileStreamWriterTest, WriteNearEnd) {
-  base::FilePath path = Path("file_a");
-  EXPECT_EQ(base::File::FILE_OK,
-            file_util()->CreateFileForTesting(path, std::string("foobar")));
-
-  std::unique_ptr<FileStreamWriter> writer(CreateWriter(path, 5));
-  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "xxx"));
-  EXPECT_TRUE(file_util()->PathExists(path));
-  EXPECT_EQ("foobaxxx", GetFileContent(path));
-}
-
-TEST_F(MemoryFileStreamWriterTest, WriteEnd) {
-  base::FilePath path = Path("file_a");
-  EXPECT_EQ(base::File::FILE_OK,
-            file_util()->CreateFileForTesting(path, std::string("foobar")));
-
-  std::unique_ptr<FileStreamWriter> writer(CreateWriter(path, 6));
-  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "xxx"));
-  EXPECT_TRUE(file_util()->PathExists(path));
-  EXPECT_EQ("foobarxxx", GetFileContent(path));
-}
-
-TEST_F(MemoryFileStreamWriterTest, WriteAfterEnd) {
-  base::FilePath path = Path("file_a");
-  EXPECT_EQ(base::File::FILE_OK,
-            file_util()->CreateFileForTesting(path, std::string("foobar")));
-
-  std::unique_ptr<FileStreamWriter> writer(CreateWriter(path, 7));
-  EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE,
-            WriteStringToWriter(writer.get(), "xxx"));
-  EXPECT_TRUE(file_util()->PathExists(path));
-  EXPECT_EQ("foobar", GetFileContent(path));
-}
-
-TEST_F(MemoryFileStreamWriterTest, WriteFailForNonexistingFile) {
-  base::FilePath path = Path("file_a");
-  ASSERT_FALSE(file_util()->PathExists(path));
-  std::unique_ptr<FileStreamWriter> writer(CreateWriter(path, 0));
-  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, WriteStringToWriter(writer.get(), "foo"));
-  EXPECT_FALSE(file_util()->PathExists(path));
-}
-
-TEST_F(MemoryFileStreamWriterTest, CancelBeforeOperation) {
-  base::FilePath path = Path("file_a");
-  std::unique_ptr<FileStreamWriter> writer(CreateWriter(path, 0));
-  // Cancel immediately fails when there's no in-flight operation.
-  EXPECT_EQ(net::ERR_UNEXPECTED, writer->Cancel(base::DoNothing()));
-}
-
-TEST_F(MemoryFileStreamWriterTest, CancelAfterFinishedOperation) {
-  base::FilePath path = Path("file_a");
-  bool created;
-  EXPECT_EQ(base::File::FILE_OK, file_util()->EnsureFileExists(path, &created));
-
-  std::unique_ptr<FileStreamWriter> writer(CreateWriter(path, 0));
-  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "foo"));
-
-  // Cancel immediately fails when there's no in-flight operation.
-  EXPECT_EQ(net::ERR_UNEXPECTED, writer->Cancel(base::DoNothing()));
-
-  // Write operation is already completed.
-  EXPECT_TRUE(file_util()->PathExists(path));
-  EXPECT_EQ("foo", GetFileContent(path));
-}
-
-TEST_F(MemoryFileStreamWriterTest, CancelWrite) {
-  base::FilePath path = Path("file_a");
-  bool created;
-  EXPECT_EQ(base::File::FILE_OK, file_util()->EnsureFileExists(path, &created));
-
-  std::unique_ptr<FileStreamWriter> writer(CreateWriter(path, 0));
-
-  scoped_refptr<net::StringIOBuffer> buffer(
-      base::MakeRefCounted<net::StringIOBuffer>("xxx"));
-  int result =
-      writer->Write(buffer.get(), buffer->size(), base::BindOnce(&NeverCalled));
-  ASSERT_EQ(net::ERR_IO_PENDING, result);
-
-  net::TestCompletionCallback callback;
-  writer->Cancel(callback.callback());
-  int cancel_result = callback.WaitForResult();
-  EXPECT_EQ(net::OK, cancel_result);
-}
-
-TEST_F(MemoryFileStreamWriterTest, FlushBeforeWriting) {
-  base::FilePath path = Path("file_a");
-  bool created;
-  EXPECT_EQ(base::File::FILE_OK, file_util()->EnsureFileExists(path, &created));
-
-  std::unique_ptr<FileStreamWriter> writer(CreateWriter(path, 0));
-
-  EXPECT_EQ(net::OK, writer->Flush(base::DoNothing()));
-  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "foo"));
-  EXPECT_EQ("foo", GetFileContent(path));
-}
-
-TEST_F(MemoryFileStreamWriterTest, FlushAfterWriting) {
-  base::FilePath path = Path("file_a");
-  bool created;
-  EXPECT_EQ(base::File::FILE_OK, file_util()->EnsureFileExists(path, &created));
-
-  std::unique_ptr<FileStreamWriter> writer(CreateWriter(path, 0));
-
-  EXPECT_EQ(net::OK, WriteStringToWriter(writer.get(), "foo"));
-  EXPECT_EQ(net::OK, writer->Flush(base::DoNothing()));
-  EXPECT_EQ("foo", GetFileContent(path));
-}
+INSTANTIATE_TYPED_TEST_SUITE_P(Memory,
+                               FileStreamWriterTypedTest,
+                               MemoryFileStreamWriterTest);
 
 }  // namespace storage
diff --git a/storage/browser/file_system/sandbox_file_stream_writer_unittest.cc b/storage/browser/file_system/sandbox_file_stream_writer_unittest.cc
new file mode 100644
index 0000000..fdd9b5e
--- /dev/null
+++ b/storage/browser/file_system/sandbox_file_stream_writer_unittest.cc
@@ -0,0 +1,134 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "storage/browser/file_system/sandbox_file_stream_writer.h"
+#include "storage/browser/file_system/file_stream_writer_test.h"
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/time/time.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "storage/browser/file_system/file_stream_reader.h"
+#include "storage/browser/file_system/file_stream_test_utils.h"
+#include "storage/browser/file_system/file_stream_writer.h"
+#include "storage/browser/file_system/file_system_context.h"
+#include "storage/browser/test/async_file_test_helper.h"
+#include "storage/browser/test/test_file_system_context.h"
+#include "storage/common/file_system/file_system_types.h"
+
+namespace storage {
+
+namespace {
+const char kURLOrigin[] = "http://remote/";
+}  // namespace
+
+class SandboxFileStreamWriterTest : public FileStreamWriterTest {
+ public:
+  SandboxFileStreamWriterTest() = default;
+
+  void SetUp() override {
+    ASSERT_TRUE(dir_.CreateUniqueTempDir());
+
+    file_system_context_ = CreateFileSystemContext(dir_);
+
+    file_system_context_->OpenFileSystem(
+        url::Origin::Create(GURL(kURLOrigin)), kFileSystemTypeTemporary,
+        OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+        base::BindOnce([](const GURL& root_url, const std::string& name,
+                          base::File::Error result) {
+          ASSERT_EQ(base::File::FILE_OK, result);
+        }));
+    base::RunLoop().RunUntilIdle();
+  }
+
+  void TearDown() override { base::RunLoop().RunUntilIdle(); }
+
+ protected:
+  base::ScopedTempDir dir_;
+  scoped_refptr<FileSystemContext> file_system_context_;
+
+  virtual FileSystemContext* CreateFileSystemContext(
+      const base::ScopedTempDir& dir) {
+    return CreateFileSystemContextForTesting(nullptr, dir.GetPath());
+  }
+
+  FileSystemURL GetFileSystemURL(const std::string& file_name) {
+    return file_system_context_->CreateCrackedFileSystemURL(
+        url::Origin::Create(GURL(kURLOrigin)), kFileSystemTypeTemporary,
+        base::FilePath().AppendASCII(file_name));
+  }
+
+  bool CreateFileWithContent(const std::string& name,
+                             const std::string& data) override {
+    return AsyncFileTestHelper::CreateFileWithData(
+               file_system_context_.get(), GetFileSystemURL(name), data.data(),
+               data.size()) == base::File::FILE_OK;
+  }
+
+  std::unique_ptr<FileStreamWriter> CreateWriter(const std::string& name,
+                                                 int64_t offset) override {
+    auto writer = std::make_unique<SandboxFileStreamWriter>(
+        file_system_context_.get(), GetFileSystemURL(name), offset,
+        *file_system_context_->GetUpdateObservers(kFileSystemTypeTemporary));
+    return writer;
+  }
+
+  bool FilePathExists(const std::string& name) override {
+    return AsyncFileTestHelper::FileExists(file_system_context_.get(),
+                                           GetFileSystemURL(name),
+                                           AsyncFileTestHelper::kDontCheckSize);
+  }
+
+  std::string GetFileContent(const std::string& name) override {
+    base::File::Info info;
+    const FileSystemURL url = GetFileSystemURL(name);
+
+    EXPECT_EQ(base::File::FILE_OK, AsyncFileTestHelper::GetMetadata(
+                                       file_system_context_.get(), url, &info));
+
+    std::unique_ptr<FileStreamReader> reader(
+        file_system_context_.get()->CreateFileStreamReader(url, 0, info.size,
+                                                           base::Time()));
+
+    int result = 0;
+    std::string content;
+    ReadFromReader(reader.get(), &content, info.size, &result);
+    EXPECT_EQ(net::OK, result);
+    EXPECT_EQ(info.size, long(content.length()));
+
+    return content;
+  }
+};
+
+INSTANTIATE_TYPED_TEST_SUITE_P(Sandbox,
+                               FileStreamWriterTypedTest,
+                               SandboxFileStreamWriterTest);
+
+class SandboxFileStreamWriterIncognitoTest
+    : public SandboxFileStreamWriterTest {
+ public:
+  SandboxFileStreamWriterIncognitoTest() = default;
+
+ protected:
+  FileSystemContext* CreateFileSystemContext(
+      const base::ScopedTempDir& dir) override {
+    return CreateIncognitoFileSystemContextForTesting(
+        base::ThreadTaskRunnerHandle::Get(),
+        base::ThreadTaskRunnerHandle::Get(), nullptr, dir.GetPath());
+  }
+};
+
+INSTANTIATE_TYPED_TEST_SUITE_P(SandboxIncognito,
+                               FileStreamWriterTypedTest,
+                               SandboxFileStreamWriterIncognitoTest);
+
+}  // namespace storage
\ No newline at end of file
diff --git a/storage/browser/test/test_file_system_context.cc b/storage/browser/test/test_file_system_context.cc
index c861028e1..6ef7a0b 100644
--- a/storage/browser/test/test_file_system_context.cc
+++ b/storage/browser/test/test_file_system_context.cc
@@ -66,6 +66,8 @@
     QuotaManagerProxy* quota_manager_proxy,
     const base::FilePath& base_path) {
   std::vector<std::unique_ptr<FileSystemBackend>> additional_providers;
+  additional_providers.push_back(std::make_unique<TestFileSystemBackend>(
+      base::ThreadTaskRunnerHandle::Get().get(), base_path));
   return CreateIncognitoFileSystemContextWithAdditionalProvidersForTesting(
       io_task_runner, file_task_runner, quota_manager_proxy,
       std::move(additional_providers), base_path);
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 9bf59fb..a8438524 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -3328,7 +3328,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M87",
-              "revision": "version:87.0.4280.20"
+              "revision": "version:87.0.4280.27"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -3402,7 +3402,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M87",
-              "revision": "version:87.0.4280.20"
+              "revision": "version:87.0.4280.27"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -3836,7 +3836,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M87",
-              "revision": "version:87.0.4280.20"
+              "revision": "version:87.0.4280.27"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -3910,7 +3910,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M87",
-              "revision": "version:87.0.4280.20"
+              "revision": "version:87.0.4280.27"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 4b925d9..4d24548a 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -72,11 +72,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "aura_unittests",
@@ -91,11 +105,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "base_unittests",
@@ -114,11 +142,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "capture_unittests",
@@ -133,11 +175,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "cc_unittests",
@@ -155,12 +211,26 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
           "idempotent": false,
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "chrome_all_tast_tests",
@@ -178,11 +248,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "cros_browser_sanity_test",
@@ -197,11 +281,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "crypto_unittests",
@@ -252,11 +350,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "display_unittests",
@@ -271,11 +383,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "google_apis_unittests",
@@ -295,11 +421,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "interactive_ui_tests",
@@ -314,11 +454,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "ipc_tests",
@@ -333,11 +487,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "jingle_unittests",
@@ -352,11 +520,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "latency_unittests",
@@ -371,11 +553,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "libcups_unittests",
@@ -393,11 +589,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "media_unittests",
@@ -412,11 +622,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "midi_unittests",
@@ -431,11 +655,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "mojo_unittests",
@@ -460,11 +698,25 @@
           ],
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
           "shards": 3
         },
@@ -483,11 +735,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "ozone_gl_unittests",
@@ -502,11 +768,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "ozone_unittests",
@@ -521,11 +801,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "pdf_unittests",
@@ -540,11 +834,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "printing_unittests",
@@ -559,11 +867,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "profile_provider_unittest",
@@ -578,11 +900,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "sandbox_linux_unittests",
@@ -597,11 +933,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "sql_unittests",
@@ -665,11 +1015,25 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "vaapi_unittest",
@@ -694,12 +1058,26 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
           "idempotent": false,
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
           "shards": 6
         },
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index 810bc5a0..efd68cd 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -62,19 +62,22 @@
     "isolated_scripts": [
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
           "--gtest-benchmark-name=angle_perftests",
           "-v",
           "--one-frame-only",
+          "--test-timeout=100",
           "--test-launcher-batch-limit=1"
         ],
-        "isolate_name": "angle_perftests",
+        "isolate_name": "standalone_angle_perftests",
         "merge": {
           "args": [
             "--smoke-test-mode"
           ],
           "script": "//tools/perf/process_perf_results.py"
         },
-        "name": "angle_perftests",
+        "name": "standalone_angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "containment_type": "AUTO",
@@ -87,9 +90,9 @@
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 3
+          "shards": 6
         },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
       },
       {
         "args": [
@@ -284,34 +287,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "gpu": "8086:5912-19.0.2",
-              "os": "Ubuntu-19.04",
-              "pool": "chromium.tests.gpu"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "--test-machine-name",
           "${buildername}",
           "--git-revision=${got_angle_revision}"
@@ -378,6 +353,41 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--batch-size=1",
+          "--bot-mode",
+          "--max-processes=1",
+          "--print-test-stdout"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-19.0.2",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=release",
@@ -700,34 +710,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "gpu": "10de:1cb3-418.56",
-              "os": "Ubuntu-19.04",
-              "pool": "chromium.tests.gpu"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "--test-machine-name",
           "${buildername}",
           "--git-revision=${got_angle_revision}"
@@ -794,6 +776,41 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--batch-size=1",
+          "--bot-mode",
+          "--max-processes=1",
+          "--print-test-stdout"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=release",
@@ -1898,34 +1915,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "gpu": "8086:5912-24.20.100.6286|8086:5912-26.20.100.8141|8086:3e92-26.20.100.8141",
-              "os": "Windows-10",
-              "pool": "chromium.tests.gpu"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "--test-machine-name",
           "${buildername}",
           "--git-revision=${got_angle_revision}"
@@ -1994,6 +1983,41 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--batch-size=1",
+          "--bot-mode",
+          "--max-processes=1",
+          "--print-test-stdout"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-24.20.100.6286|8086:5912-26.20.100.8141|8086:3e92-26.20.100.8141",
+              "os": "Windows-10",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "webgl_conformance",
           "--show-stdout",
           "--browser=release_x64",
@@ -2343,34 +2367,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "gpu": "10de:1cb3-27.21.14.5148",
-              "os": "Windows-10-18363",
-              "pool": "chromium.tests.gpu"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "--test-machine-name",
           "${buildername}",
           "--git-revision=${got_angle_revision}"
@@ -2437,6 +2433,41 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--batch-size=1",
+          "--bot-mode",
+          "--max-processes=1",
+          "--print-test-stdout"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-27.21.14.5148",
+              "os": "Windows-10-18363",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "webgl_conformance",
           "--show-stdout",
           "--browser=release_x64",
@@ -2702,38 +2733,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only",
-          "--test-launcher-batch-limit=1"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "device_os": "Q",
-              "device_os_type": "userdebug",
-              "device_type": "walleye",
-              "os": "Android",
-              "pool": "chromium.tests.gpu"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 3
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "--test-machine-name",
           "${buildername}",
           "-v",
@@ -2765,6 +2764,41 @@
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test_id_prefix": "ninja://third_party/angle/src/tests/restricted_traces:angle_restricted_trace_gold_tests/"
+      },
+      {
+        "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--test-launcher-batch-limit=1"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "device_os": "Q",
+              "device_os_type": "userdebug",
+              "device_type": "walleye",
+              "os": "Android",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 6
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
       }
     ]
   },
@@ -2992,15 +3026,18 @@
     "isolated_scripts": [
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
           "--gtest-benchmark-name=angle_perftests",
           "-v",
+          "--test-timeout=100",
           "--test-launcher-batch-limit=1"
         ],
-        "isolate_name": "angle_perftests",
+        "isolate_name": "standalone_angle_perftests",
         "merge": {
           "script": "//tools/perf/process_perf_results.py"
         },
-        "name": "angle_perftests",
+        "name": "standalone_angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "containment_type": "AUTO",
@@ -3014,9 +3051,9 @@
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 4
+          "shards": 6
         },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
       }
     ]
   },
@@ -3086,38 +3123,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only",
-          "--test-launcher-batch-limit=1"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "device_os": "Q",
-              "device_os_type": "userdebug",
-              "device_type": "walleye",
-              "os": "Android",
-              "pool": "chromium.tests.gpu"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 3
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "--test-machine-name",
           "${buildername}",
           "-v",
@@ -3149,6 +3154,41 @@
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test_id_prefix": "ninja://third_party/angle/src/tests/restricted_traces:angle_restricted_trace_gold_tests/"
+      },
+      {
+        "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--test-launcher-batch-limit=1"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "device_os": "Q",
+              "device_os_type": "userdebug",
+              "device_type": "walleye",
+              "os": "Android",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 6
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
       }
     ]
   },
@@ -3566,38 +3606,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only",
-          "--test-launcher-batch-limit=1"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "device_os": "N",
-              "device_os_type": "user",
-              "device_type": "foster",
-              "os": "Android",
-              "pool": "chromium.tests.gpu"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 3
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "context_lost",
           "--show-stdout",
           "--browser=android-chromium",
@@ -3885,6 +3893,41 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--test-launcher-batch-limit=1"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "device_os": "N",
+              "device_os_type": "user",
+              "device_type": "foster",
+              "os": "Android",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 6
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=android-chromium",
@@ -4590,37 +4633,6 @@
       },
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only",
-          "--test-launcher-batch-limit=1"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 3
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "context_lost",
           "--show-stdout",
           "--browser=android-chromium",
@@ -4927,6 +4939,40 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--test-launcher-batch-limit=1"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_os_type": "userdebug",
+              "device_type": "bullhead",
+              "os": "Android"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 6
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=android-chromium",
@@ -6259,38 +6305,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only",
-          "--test-launcher-batch-limit=1"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "device_os": "M",
-              "device_os_type": "userdebug",
-              "device_type": "flounder",
-              "os": "Android",
-              "pool": "chromium.tests.gpu"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 3
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "context_lost",
           "--show-stdout",
           "--browser=android-chromium",
@@ -6578,6 +6592,41 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--test-launcher-batch-limit=1"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "device_os": "M",
+              "device_os_type": "userdebug",
+              "device_type": "flounder",
+              "os": "Android",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 6
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=android-chromium",
@@ -7063,12 +7112,26 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
           "idempotent": false,
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
@@ -7096,12 +7159,26 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
           "idempotent": false,
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
@@ -7129,12 +7206,26 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
           "idempotent": false,
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
@@ -7162,12 +7253,26 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
           "idempotent": false,
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
@@ -7199,12 +7304,26 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
           "idempotent": false,
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
@@ -7241,12 +7360,26 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
           "idempotent": false,
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
@@ -7283,12 +7416,26 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
           "idempotent": false,
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
@@ -7317,12 +7464,26 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
           "idempotent": false,
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
@@ -7350,12 +7511,26 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
           "idempotent": false,
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
@@ -7384,12 +7559,26 @@
           "containment_type": "AUTO",
           "dimension_sets": [
             {
+              "cpu": "x86",
               "kvm": "1",
               "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.cros.vm"
+              "pool": "chromium.tests"
             }
           ],
           "idempotent": false,
+          "named_caches": [
+            {
+              "name": "cros_vm",
+              "path": "magic_cros_vm_cache"
+            }
+          ],
+          "optional_dimensions": {
+            "60": [
+              {
+                "caches": "cros_vm"
+              }
+            ]
+          },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
           "shards": 2
         },
@@ -8858,35 +9047,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "gpu": "10de:2184",
-              "os": "Ubuntu",
-              "pool": "chromium.tests.gpu.experimental"
-            }
-          ],
-          "expiration": 21600,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "context_lost",
           "--show-stdout",
           "--browser=release",
@@ -9313,6 +9473,42 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--batch-size=1",
+          "--bot-mode",
+          "--max-processes=1",
+          "--print-test-stdout"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:2184",
+              "os": "Ubuntu",
+              "pool": "chromium.tests.gpu.experimental"
+            }
+          ],
+          "expiration": 21600,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=release",
@@ -12229,34 +12425,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "gpu": "10de:1cb3-418.56",
-              "os": "Ubuntu-19.04",
-              "pool": "chromium.tests.gpu"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "context_lost",
           "--show-stdout",
           "--browser=release",
@@ -12671,6 +12839,41 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--batch-size=1",
+          "--bot-mode",
+          "--max-processes=1",
+          "--print-test-stdout"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=release",
@@ -21901,34 +22104,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "gpu": "10de:1cb3-418.56",
-              "os": "Ubuntu-19.04",
-              "pool": "chromium.tests.gpu"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "info_collection",
           "--show-stdout",
           "--browser=release",
@@ -21964,6 +22139,41 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--batch-size=1",
+          "--bot-mode",
+          "--max-processes=1",
+          "--print-test-stdout"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=release",
@@ -23584,34 +23794,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "gpu": "8086:5912-24.20.100.6286|8086:5912-26.20.100.8141|8086:3e92-26.20.100.8141",
-              "os": "Windows-10",
-              "pool": "chromium.tests.gpu"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "info_collection",
           "--show-stdout",
           "--browser=release_x64",
@@ -23680,6 +23862,41 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--batch-size=1",
+          "--bot-mode",
+          "--max-processes=1",
+          "--print-test-stdout"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-24.20.100.6286|8086:5912-26.20.100.8141|8086:3e92-26.20.100.8141",
+              "os": "Windows-10",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=release_x64",
@@ -24097,34 +24314,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "gpu": "10de:1cb3-27.21.14.5148",
-              "os": "Windows-10-18363",
-              "pool": "chromium.tests.gpu"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "info_collection",
           "--show-stdout",
           "--browser=release_x64",
@@ -24191,6 +24380,41 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--batch-size=1",
+          "--bot-mode",
+          "--max-processes=1",
+          "--print-test-stdout"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-27.21.14.5148",
+              "os": "Windows-10-18363",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=release_x64",
@@ -25565,35 +25789,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "gpu": "8086:5912-26.20.100.7870|8086:5912-26.20.100.8141|8086:3e92-26.20.100.8141",
-              "os": "Windows-10",
-              "pool": "chromium.tests.gpu.experimental"
-            }
-          ],
-          "expiration": 21600,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "context_lost",
           "--show-stdout",
           "--browser=release_x64",
@@ -25934,6 +26129,42 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--batch-size=1",
+          "--bot-mode",
+          "--max-processes=1",
+          "--print-test-stdout"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-26.20.100.7870|8086:5912-26.20.100.8141|8086:3e92-26.20.100.8141",
+              "os": "Windows-10",
+              "pool": "chromium.tests.gpu.experimental"
+            }
+          ],
+          "expiration": 21600,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=release_x64",
@@ -26529,35 +26760,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "gpu": "10de:1cb3-27.21.14.5148",
-              "os": "Windows-10-18363",
-              "pool": "chromium.tests.gpu.experimental"
-            }
-          ],
-          "expiration": 21600,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "context_lost",
           "--show-stdout",
           "--browser=release_x64",
@@ -26896,6 +27098,42 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--batch-size=1",
+          "--bot-mode",
+          "--max-processes=1",
+          "--print-test-stdout"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-27.21.14.5148",
+              "os": "Windows-10-18363",
+              "pool": "chromium.tests.gpu.experimental"
+            }
+          ],
+          "expiration": 21600,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=release_x64",
@@ -28231,34 +28469,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "gpu": "8086:5912-24.20.100.6286|8086:5912-26.20.100.8141|8086:3e92-26.20.100.8141",
-              "os": "Windows-10",
-              "pool": "chromium.tests.gpu"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "context_lost",
           "--show-stdout",
           "--browser=release_x64",
@@ -28589,6 +28799,41 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--batch-size=1",
+          "--bot-mode",
+          "--max-processes=1",
+          "--print-test-stdout"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-24.20.100.6286|8086:5912-26.20.100.8141|8086:3e92-26.20.100.8141",
+              "os": "Windows-10",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=release_x64",
@@ -29177,35 +29422,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "gpu": "8086:3e92-24.20.100.6286",
-              "os": "Windows-10",
-              "pool": "chromium.tests.gpu"
-            }
-          ],
-          "expiration": 14400,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "context_lost",
           "--show-stdout",
           "--browser=release_x64",
@@ -29544,6 +29760,42 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--batch-size=1",
+          "--bot-mode",
+          "--max-processes=1",
+          "--print-test-stdout"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:3e92-24.20.100.6286",
+              "os": "Windows-10",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 14400,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=release_x64",
@@ -30999,34 +31251,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "gpu": "10de:1cb3-27.21.14.5148",
-              "os": "Windows-10-18363",
-              "pool": "chromium.tests.gpu"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "context_lost",
           "--show-stdout",
           "--browser=release_x64",
@@ -31355,6 +31579,41 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--batch-size=1",
+          "--bot-mode",
+          "--max-processes=1",
+          "--print-test-stdout"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-27.21.14.5148",
+              "os": "Windows-10-18363",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=release_x64",
@@ -32528,34 +32787,6 @@
     "isolated_scripts": [
       {
         "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "gpu": "10de:1cb3-27.21.14.5148",
-              "os": "Windows-10-18363",
-              "pool": "chromium.tests.gpu"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/"
-      },
-      {
-        "args": [
           "context_lost",
           "--show-stdout",
           "--browser=release",
@@ -32883,6 +33114,41 @@
       },
       {
         "args": [
+          "standalone_angle_perftests",
+          "--non-telemetry=true",
+          "--gtest-benchmark-name=angle_perftests",
+          "-v",
+          "--one-frame-only",
+          "--test-timeout=100",
+          "--batch-size=1",
+          "--bot-mode",
+          "--max-processes=1",
+          "--print-test-stdout"
+        ],
+        "isolate_name": "standalone_angle_perftests",
+        "merge": {
+          "args": [
+            "--smoke-test-mode"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "standalone_angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-27.21.14.5148",
+              "os": "Windows-10-18363",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://third_party/angle/src/tests:standalone_angle_perftests/"
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=release",
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index dbf3ddcd6..aaf4f0fe 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -1576,6 +1576,11 @@
     "script": "//third_party/angle/scripts/run_gtest_angle_test.py",
     "type": "script",
   },
+  "standalone_angle_perftests": {
+    "label": "//third_party/angle/src/tests:standalone_angle_perftests",
+    "script": "//testing/scripts/run_performance_tests.py",
+    "type": "script",
+  },
   "standalone_angle_unittests": {
     "label": "//third_party/angle/src/tests:standalone_angle_unittests",
     "script": "//third_party/angle/scripts/run_gtest_angle_test.py",
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl
index efa68703..d5131ca 100644
--- a/testing/buildbot/mixins.pyl
+++ b/testing/buildbot/mixins.pyl
@@ -217,11 +217,27 @@
   },
   'chromeos-amd64-generic': {
     'swarming': {
-      'dimensions': {
-        'kvm': '1',
-        'os': 'Ubuntu-16.04',
-        'pool': 'chromium.tests.cros.vm',
+      'dimension_sets': [
+        {
+          'cpu': 'x86',
+          'kvm': '1',
+          'os': 'Ubuntu-16.04',
+          'pool': 'chromium.tests',
+        }
+      ],
+      'optional_dimensions': {
+        '60': [
+          {
+            'caches': 'cros_vm',
+          }
+        ],
       },
+      'named_caches': [
+        {
+          'name': 'cros_vm',
+          'path': 'magic_cros_vm_cache',
+        },
+      ],
     },
   },
   'chromeos-kevin': {
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 5b90aa3..388bfff 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -74,21 +74,6 @@
       },
     },
   },
-  'angle_perftests': {
-    'modifications': {
-     'Android FYI 64 Perf (Pixel 2)': { # crbug.com/1140626
-       'swarming': {
-         'shards': 4,
-       },
-     },
-    },
-    'remove_from': [
-      'Android FYI Release (Nexus 5)',  # crbug.com/915429
-      'Android FYI Release (Nexus 6)',  # anglebug.com/2433
-      'Android FYI Release (Nexus 6P)', # anglebug.com/4909
-      'Linux FYI GPU TSAN Release',  # crbug.com/950542
-    ],
-  },
   'blink_platform_unittests': {
     'modifications': {
       # TODO(crbug.com/1108121): Remove this filter
@@ -1231,33 +1216,6 @@
     ],
   },
   'disk_usage_tast_test': {
-    'modifications': {
-      # TODO(crbug.com/1132206): Apply this to all of the bot's tests if the
-      # cache affinity works.
-      'chromeos-amd64-generic-rel': {
-        'swarming': {
-          'dimension_sets': [
-            {
-              'cpu': 'x86',
-              'pool': 'chromium.tests',
-            }
-          ],
-          'optional_dimensions': {
-            '60': [
-              {
-                'caches': 'cros_vm',
-              }
-            ],
-          },
-          'named_caches': [
-            {
-              'name': 'cros_vm',
-              'path': 'magic_cros_vm_cache',
-            },
-          ],
-        },
-      },
-    },
     # TODO(crbug.com/1077659): Add the test back after it's fixed.
     'remove_from': [
       'chromeos-kevin-rel',
@@ -2533,6 +2491,14 @@
       'Linux FYI Debug (NVIDIA)',
     ],
   },
+  'standalone_angle_perftests': {
+    'remove_from': [
+      'Android FYI Release (Nexus 5)',  # crbug.com/915429
+      'Android FYI Release (Nexus 6)',  # anglebug.com/2433
+      'Android FYI Release (Nexus 6P)', # anglebug.com/4909
+      'Linux FYI GPU TSAN Release',  # crbug.com/950542
+    ],
+  },
   'standalone_angle_unittests': {
     'remove_from': [
       # On Android, these are already run on the main waterfall.
@@ -2798,31 +2764,6 @@
       'Win10 Tests x64 (dbg)': {
         'experiment_percentage': 100,  # crbug.com/870673
       },
-      # TODO(crbug.com/1132206): Apply this to all of the bot's tests if the
-      # cache affinity works.
-      'chromeos-amd64-generic-rel': {
-        'swarming': {
-          'dimension_sets': [
-            {
-              'cpu': 'x86',
-              'pool': 'chromium.tests',
-            }
-          ],
-          'optional_dimensions': {
-            '60': [
-              {
-                'caches': 'cros_vm',
-              }
-            ],
-          },
-          'named_caches': [
-            {
-              'name': 'cros_vm',
-              'path': 'magic_cros_vm_cache',
-            },
-          ],
-        },
-      },
     },
     'remove_from': [
       # crbug.com/936540
@@ -2923,33 +2864,6 @@
     },
   },
   'url_unittests': {
-    'modifications': {
-      # TODO(crbug.com/1132206): Apply this to all of the bot's tests if the
-      # cache affinity works.
-      'chromeos-amd64-generic-rel': {
-        'swarming': {
-          'dimension_sets': [
-            {
-              'cpu': 'x86',
-              'pool': 'chromium.tests',
-            }
-          ],
-          'optional_dimensions': {
-            '60': [
-              {
-                'caches': 'cros_vm',
-              }
-            ],
-          },
-          'named_caches': [
-            {
-              'name': 'cros_vm',
-              'path': 'magic_cros_vm_cache',
-            },
-          ],
-        },
-      },
-    },
     'remove_from': [
       # crbug.com/1054240
       'Fuchsia ARM64',
@@ -3101,30 +3015,9 @@
           'shards': 6,
         },
       },
-      # TODO(crbug.com/1132206): Apply this to all of the bot's tests if the
-      # cache affinity works.
       'chromeos-amd64-generic-rel': {
         'swarming': {
           'shards': 12,
-          'dimension_sets': [
-            {
-              'cpu': 'x86',
-              'pool': 'chromium.tests',
-            }
-          ],
-          'optional_dimensions': {
-            '60': [
-              {
-                'caches': 'cros_vm',
-              }
-            ],
-          },
-          'named_caches': [
-            {
-              'name': 'cros_vm',
-              'path': 'magic_cros_vm_cache',
-            },
-          ],
         },
       },
     },
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index c2f4632..026b7a8 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -2019,19 +2019,28 @@
 
     # Actually uploads results to the perf dashboard
     'gpu_angle_perf_isolated_scripts': {
-      'angle_perftests': {
+      'standalone_angle_perftests': {
         'args': [
+          'standalone_angle_perftests',
+          '--non-telemetry=true',
           '--gtest-benchmark-name=angle_perftests',
           '-v',
+          '--test-timeout=100',
         ],
         'android_args': [
           '--test-launcher-batch-limit=1',
         ],
+        'desktop_args': [
+          '--batch-size=1',
+          '--bot-mode',
+          '--max-processes=1',
+          '--print-test-stdout',
+        ],
         'merge': {
           'script': '//tools/perf/process_perf_results.py',
         },
         'android_swarming': {
-          'shards': 3,
+          'shards': 6,
         },
       },
     },
@@ -2039,16 +2048,25 @@
     # The angle perf tests should eventually be run on every platform
     # ANGLE supports. Currently they run on Windows, Linux and Android.
     'gpu_angle_perf_smoke_isolated_scripts': {
-      'angle_perftests': {
+      'standalone_angle_perftests': {
         'args': [
+          'standalone_angle_perftests',
+          '--non-telemetry=true',
           '--gtest-benchmark-name=angle_perftests',
           '-v',
           # Tell the tests to exit after one frame for faster iteration.
           '--one-frame-only',
+          '--test-timeout=100',
         ],
         'android_args': [
           '--test-launcher-batch-limit=1',
         ],
+        'desktop_args': [
+          '--batch-size=1',
+          '--bot-mode',
+          '--max-processes=1',
+          '--print-test-stdout',
+        ],
         'merge': {
           'script': '//tools/perf/process_perf_results.py',
           # Does not upload to the perf dashboard
@@ -2057,7 +2075,7 @@
           ],
         },
         'android_swarming': {
-          'shards': 3,
+          'shards': 6,
         },
       },
     },
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 62074a5..7fb625b 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -325,7 +325,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M87',
-          'revision': 'version:87.0.4280.20',
+          'revision': 'version:87.0.4280.27',
         }
       ],
     },
@@ -394,7 +394,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M87',
-          'revision': 'version:87.0.4280.20',
+          'revision': 'version:87.0.4280.27',
         }
       ],
     },
diff --git a/testing/scripts/run_performance_tests.py b/testing/scripts/run_performance_tests.py
index 15696cb..a79d638 100755
--- a/testing/scripts/run_performance_tests.py
+++ b/testing/scripts/run_performance_tests.py
@@ -105,6 +105,8 @@
   'net_perftests',
   'browser_tests',
   'services_perftests',
+  # TODO(jmadill): Remove once migrated. http://anglebug.com/5124
+  'standalone_angle_perftests',
   'sync_performance_tests',
   'tracing_perftests',
   'views_perftests',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index c9ff9827..b0b7f3a8 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -4794,10 +4794,40 @@
             ],
             "experiments": [
                 {
-                    "name": "ButtonRowWithPedals",
+                    "name": "ButtonRowWithPedalsAndKeywordButton",
+                    "params": {
+                        "PedalSuggestionsCounterfactualArm": "false"
+                    },
+                    "enable_features": [
+                        "OmniboxKeywordSearchButton",
+                        "OmniboxPedalSuggestions",
+                        "OmniboxSuggestionButtonRow"
+                    ]
+                },
+                {
+                    "name": "ButtonRowWithPedals_Experiment",
+                    "params": {
+                        "PedalSuggestionsCounterfactualArm": "false"
+                    },
                     "enable_features": [
                         "OmniboxPedalSuggestions",
                         "OmniboxSuggestionButtonRow"
+                    ],
+                    "disable_features": [
+                        "OmniboxKeywordSearchButton"
+                    ]
+                },
+                {
+                    "name": "ButtonRowWithPedals_Counterfactual",
+                    "params": {
+                        "PedalSuggestionsCounterfactualArm": "true"
+                    },
+                    "enable_features": [
+                        "OmniboxPedalSuggestions",
+                        "OmniboxSuggestionButtonRow"
+                    ],
+                    "disable_features": [
+                        "OmniboxKeywordSearchButton"
                     ]
                 },
                 {
@@ -4806,6 +4836,7 @@
                         "OmniboxSuggestionButtonRow"
                     ],
                     "disable_features": [
+                        "OmniboxKeywordSearchButton",
                         "OmniboxPedalSuggestions"
                     ]
                 }
@@ -4830,24 +4861,6 @@
             ]
         }
     ],
-    "OmniboxEnableClipboardProviderImageSuggestions": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "params": {
-                        "ImageSearchSuggestionThumbnail": "true"
-                    },
-                    "enable_features": [
-                        "OmniboxEnableClipboardProviderImageSuggestions"
-                    ]
-                }
-            ]
-        }
-    ],
     "OmniboxLocalEntities": [
         {
             "platforms": [
diff --git a/third_party/androidx/fetch_all_androidx.py b/third_party/androidx/fetch_all_androidx.py
index bd3fa7e..10efbdc 100755
--- a/third_party/androidx/fetch_all_androidx.py
+++ b/third_party/androidx/fetch_all_androidx.py
@@ -17,10 +17,11 @@
 import json
 import os
 import re
-import requests
 import shutil
 import subprocess
 import tempfile
+import urllib
+from urllib import request
 
 _ANDROIDX_PATH = os.path.normpath(os.path.join(__file__, '..'))
 
@@ -90,15 +91,16 @@
 def _download_and_parse_build_info():
     """Downloads and parses BUILD_INFO file."""
     with _build_dir() as build_dir:
-        androidx_build_info_response = requests.get(
+        androidx_build_info_response = request.urlopen(
             _ANDROIDX_LATEST_SNAPSHOT_BUILD_INFO_URL)
         androidx_build_info_path = os.path.join(build_dir, 'BUILD_INFO')
         with open(androidx_build_info_path, 'w') as f:
-            f.write(androidx_build_info_response.text)
+            f.write(androidx_build_info_response.read().decode('utf-8'))
 
         # Compute repository URL from resolved BUILD_INFO url in case 'latest' redirect changes.
-        androidx_snapshot_repository_url = androidx_build_info_response.url.rsplit(
-            '/', 1)[0] + '/repository'
+        androidx_snapshot_repository_url = (
+            androidx_build_info_response.geturl().rsplit('/', 1)[0] +
+            '/repository')
 
         with open(androidx_build_info_path, 'r') as f:
             build_info_dict = json.loads(f.read())
diff --git a/third_party/blink/PRESUBMIT.py b/third_party/blink/PRESUBMIT.py
index ae7388c5..09e59f1d 100644
--- a/third_party/blink/PRESUBMIT.py
+++ b/third_party/blink/PRESUBMIT.py
@@ -61,6 +61,7 @@
     # boundary between Blink and non-Blink.
     allowed_interfaces = ('services/network/public/mojom/cross_origin_embedder_policy', 'services/network/public/mojom/fetch_api',
                           'services/network/public/mojom/load_timing_info', 'services/network/public/mojom/url_response_head',
+                          'third_party/blink/public/mojom/blob/serialized_blob',
                           'third_party/blink/public/mojom/loader/resource_load_info',
                           'third_party/blink/public/mojom/loader/resource_load_info_notifier',
                           'third_party/blink/public/mojom/worker/subresource_loader_updater', 'media/mojo/mojom/interface_factory',
diff --git a/third_party/blink/common/BUILD.gn b/third_party/blink/common/BUILD.gn
index 24bddcc..b1c7584 100644
--- a/third_party/blink/common/BUILD.gn
+++ b/third_party/blink/common/BUILD.gn
@@ -150,6 +150,8 @@
     "peerconnection/peer_connection_tracker_mojom_traits.cc",
     "peerconnection/webrtc_ip_handling_policy.cc",
     "permissions/permission_utils.cc",
+    "renderer_preferences/renderer_preferences.cc",
+    "renderer_preferences/renderer_preferences_mojom_traits.cc",
     "scheduler/web_scheduler_tracked_feature.cc",
     "service_worker/service_worker_scope_match.cc",
     "service_worker/service_worker_status_code.cc",
diff --git a/third_party/blink/common/renderer_preferences/OWNERS b/third_party/blink/common/renderer_preferences/OWNERS
new file mode 100644
index 0000000..d5fefd8
--- /dev/null
+++ b/third_party/blink/common/renderer_preferences/OWNERS
@@ -0,0 +1,2 @@
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/common/renderer_preferences/renderer_preferences.cc b/third_party/blink/common/renderer_preferences/renderer_preferences.cc
new file mode 100644
index 0000000..5df219c
--- /dev/null
+++ b/third_party/blink/common/renderer_preferences/renderer_preferences.cc
@@ -0,0 +1,26 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
+
+#include "build/build_config.h"
+
+namespace blink {
+
+RendererPreferences::RendererPreferences() = default;
+
+RendererPreferences::RendererPreferences(const RendererPreferences& other) =
+    default;
+
+RendererPreferences::RendererPreferences(RendererPreferences&& other) = default;
+
+RendererPreferences::~RendererPreferences() = default;
+
+RendererPreferences& RendererPreferences::operator=(
+    const RendererPreferences& other) = default;
+
+RendererPreferences& RendererPreferences::operator=(
+    RendererPreferences&& other) = default;
+
+}  // namespace blink
diff --git a/third_party/blink/common/renderer_preferences/renderer_preferences_mojom_traits.cc b/third_party/blink/common/renderer_preferences/renderer_preferences_mojom_traits.cc
new file mode 100644
index 0000000..0e5fa7a
--- /dev/null
+++ b/third_party/blink/common/renderer_preferences/renderer_preferences_mojom_traits.cc
@@ -0,0 +1,112 @@
+// 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.
+
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences_mojom_traits.h"
+
+#include <string>
+
+#include "build/build_config.h"
+#include "third_party/blink/public/mojom/renderer_preferences.mojom-shared.h"
+
+namespace mojo {
+
+bool StructTraits<blink::mojom::RendererPreferencesDataView,
+                  ::blink::RendererPreferences>::
+    Read(blink::mojom::RendererPreferencesDataView data,
+         ::blink::RendererPreferences* out) {
+  out->can_accept_load_drops = data.can_accept_load_drops();
+  out->should_antialias_text = data.should_antialias_text();
+
+  if (!data.ReadHinting(&out->hinting))
+    return false;
+  out->use_autohinter = data.use_autohinter();
+
+  out->use_bitmaps = data.use_bitmaps();
+
+  if (!data.ReadSubpixelRendering(&out->subpixel_rendering))
+    return false;
+  out->use_subpixel_positioning = data.use_subpixel_positioning();
+
+  out->focus_ring_color = data.focus_ring_color();
+  out->active_selection_bg_color = data.active_selection_bg_color();
+  out->active_selection_fg_color = data.active_selection_fg_color();
+  out->inactive_selection_bg_color = data.inactive_selection_bg_color();
+  out->inactive_selection_fg_color = data.inactive_selection_fg_color();
+
+  out->browser_handles_all_top_level_requests =
+      data.browser_handles_all_top_level_requests();
+
+  if (!data.ReadCaretBlinkInterval(&out->caret_blink_interval))
+    return false;
+
+  out->use_custom_colors = data.use_custom_colors();
+  out->enable_referrers = data.enable_referrers();
+  out->allow_cross_origin_auth_prompt = data.allow_cross_origin_auth_prompt();
+  out->enable_do_not_track = data.enable_do_not_track();
+  out->enable_encrypted_media = data.enable_encrypted_media();
+
+  if (!data.ReadWebrtcIpHandlingPolicy(&out->webrtc_ip_handling_policy))
+    return false;
+
+  out->webrtc_udp_min_port = data.webrtc_udp_min_port();
+  out->webrtc_udp_max_port = data.webrtc_udp_max_port();
+
+  if (!data.ReadWebrtcLocalIpsAllowedUrls(&out->webrtc_local_ips_allowed_urls))
+    return false;
+
+  out->webrtc_allow_legacy_tls_protocols =
+      data.webrtc_allow_legacy_tls_protocols();
+
+  if (!data.ReadUserAgentOverride(&out->user_agent_override))
+    return false;
+
+  if (!data.ReadAcceptLanguages(&out->accept_languages))
+    return false;
+
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+  if (!data.ReadSystemFontFamilyName(&out->system_font_family_name))
+    return false;
+#endif
+#if defined(OS_WIN)
+  if (!data.ReadCaptionFontFamilyName(&out->caption_font_family_name))
+    return false;
+  out->caption_font_height = data.caption_font_height();
+
+  if (!data.ReadSmallCaptionFontFamilyName(
+          &out->small_caption_font_family_name))
+    return false;
+  out->small_caption_font_height = data.small_caption_font_height();
+
+  if (!data.ReadMenuFontFamilyName(&out->menu_font_family_name))
+    return false;
+  out->menu_font_height = data.menu_font_height();
+
+  if (!data.ReadStatusFontFamilyName(&out->status_font_family_name))
+    return false;
+  out->status_font_height = data.status_font_height();
+
+  if (!data.ReadMessageFontFamilyName(&out->message_font_family_name))
+    return false;
+  out->message_font_height = data.message_font_height();
+
+  out->vertical_scroll_bar_width_in_dips =
+      data.vertical_scroll_bar_width_in_dips();
+  out->horizontal_scroll_bar_height_in_dips =
+      data.horizontal_scroll_bar_height_in_dips();
+  out->arrow_bitmap_height_vertical_scroll_bar_in_dips =
+      data.arrow_bitmap_height_vertical_scroll_bar_in_dips();
+  out->arrow_bitmap_width_horizontal_scroll_bar_in_dips =
+      data.arrow_bitmap_width_horizontal_scroll_bar_in_dips();
+#endif
+#if defined(USE_X11) || defined(USE_OZONE)
+  out->selection_clipboard_buffer_available =
+      data.selection_clipboard_buffer_available();
+#endif
+  out->plugin_fullscreen_allowed = data.plugin_fullscreen_allowed();
+  out->caret_browsing_enabled = data.caret_browsing_enabled();
+
+  return true;
+}
+
+}  // namespace mojo
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn
index 0bd86dd..3320efd 100644
--- a/third_party/blink/public/BUILD.gn
+++ b/third_party/blink/public/BUILD.gn
@@ -152,6 +152,7 @@
     "platform/scheduler/web_scoped_virtual_time_pauser.h",
     "platform/scheduler/web_thread_scheduler.h",
     "platform/scheduler/web_widget_scheduler.h",
+    "platform/sync_load_response.h",
     "platform/task_type.h",
     "platform/url_conversion.h",
     "platform/user_metrics_action.h",
@@ -196,7 +197,6 @@
     "platform/web_encrypted_media_types.h",
     "platform/web_fetch_client_settings_object.h",
     "platform/web_file_system_type.h",
-    "platform/web_float_rect.h",
     "platform/web_font.h",
     "platform/web_font_description.h",
     "platform/web_font_render_style.h",
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn
index 1c0897e..609e7ec 100644
--- a/third_party/blink/public/common/BUILD.gn
+++ b/third_party/blink/public/common/BUILD.gn
@@ -171,6 +171,7 @@
     "peerconnection/peer_connection_tracker_mojom_traits.h",
     "peerconnection/webrtc_ip_handling_policy.h",
     "permissions/permission_utils.h",
+    "renderer_preferences/renderer_preferences.h",
     "scheduler/web_scheduler_tracked_feature.h",
     "security/security_style.h",
     "security_context/insecure_request_policy.h",
diff --git a/third_party/blink/public/common/feature_policy/feature_policy.h b/third_party/blink/public/common/feature_policy/feature_policy.h
index ea5c224c..3911624 100644
--- a/third_party/blink/public/common/feature_policy/feature_policy.h
+++ b/third_party/blink/public/common/feature_policy/feature_policy.h
@@ -28,7 +28,7 @@
 // HTTP header, or can be set by the |allow| attributes on the iframe element
 // which embeds the document.
 //
-// See https://wicg.github.io/FeaturePolicy/
+// See https://w3c.github.io/webappsec-permissions-policy/
 //
 // Key concepts:
 //
diff --git a/third_party/blink/public/common/privacy_budget/identifiable_surface.h b/third_party/blink/public/common/privacy_budget/identifiable_surface.h
index fe9f337..8f27edd 100644
--- a/third_party/blink/public/common/privacy_budget/identifiable_surface.h
+++ b/third_party/blink/public/common/privacy_budget/identifiable_surface.h
@@ -217,6 +217,14 @@
     // configuration provided.
     kMediaCapabilities_DecodingInfo = 25,
 
+    // Represents determining that a local font exists or does not, based on a
+    // name lookup that is only allowed to match a unique name. This occurs in
+    // @font-face CSS rules with a src:local attribute, as well as calls to
+    // FontFace.load() for a FontFace object with a src:local attribute. The
+    // latter can reveal whether a font exists before the full font data are
+    // obtained. Input is the lookup name. Output is a bool.
+    kLocalFontExistenceByUniqueNameOnly = 26,
+
     // Represents a call to Navigator.getUserMedia. Input is the set of
     // constraints.
     kNavigator_GetUserMedia = 27,
diff --git a/third_party/blink/public/common/renderer_preferences/DEPS b/third_party/blink/public/common/renderer_preferences/DEPS
new file mode 100644
index 0000000..8b17823
--- /dev/null
+++ b/third_party/blink/public/common/renderer_preferences/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+    "+ui/gfx/font_render_params.h",
+    "+ui/gfx/mojom/font_render_params_mojom_traits.h"
+]
diff --git a/third_party/blink/public/common/renderer_preferences/OWNERS b/third_party/blink/public/common/renderer_preferences/OWNERS
new file mode 100644
index 0000000..d5fefd8
--- /dev/null
+++ b/third_party/blink/public/common/renderer_preferences/OWNERS
@@ -0,0 +1,2 @@
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/common/renderer_preferences/renderer_preferences.h b/third_party/blink/public/common/renderer_preferences/renderer_preferences.h
new file mode 100644
index 0000000..1cc39de
--- /dev/null
+++ b/third_party/blink/public/common/renderer_preferences/renderer_preferences.h
@@ -0,0 +1,87 @@
+// 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 THIRD_PARTY_BLINK_PUBLIC_COMMON_RENDERER_PREFERENCES_RENDERER_PREFERENCES_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_RENDERER_PREFERENCES_RENDERER_PREFERENCES_H_
+
+#include <string>
+#include <vector>
+
+#include "base/optional.h"
+#include "base/strings/string16.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
+#include "ui/gfx/font_render_params.h"
+
+namespace blink {
+
+// User preferences passed between the browser and renderer processes.
+// See //third_party/blink/public/mojom/renderer_preferences.mojom for a
+// description of what each field is about.
+struct BLINK_COMMON_EXPORT RendererPreferences {
+  bool can_accept_load_drops{true};
+  bool should_antialias_text{true};
+  gfx::FontRenderParams::Hinting hinting{gfx::FontRenderParams::HINTING_MEDIUM};
+  bool use_autohinter{false};
+  bool use_bitmaps{false};
+  gfx::FontRenderParams::SubpixelRendering subpixel_rendering{
+      gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE};
+  bool use_subpixel_positioning{false};
+  uint32_t focus_ring_color{0xFFE59700};
+  uint32_t active_selection_bg_color{0xFF1E90FF};
+  uint32_t active_selection_fg_color{0xFFFFFFFF};
+  uint32_t inactive_selection_bg_color{0xFFC8C8C8};
+  uint32_t inactive_selection_fg_color{0xFF323232};
+  bool browser_handles_all_top_level_requests{false};
+  base::Optional<base::TimeDelta> caret_blink_interval;
+  bool use_custom_colors{true};
+  bool enable_referrers{true};
+  bool allow_cross_origin_auth_prompt{false};
+  bool enable_do_not_track{false};
+  bool enable_encrypted_media{true};
+  std::string webrtc_ip_handling_policy;
+  uint16_t webrtc_udp_min_port{0};
+  uint16_t webrtc_udp_max_port{0};
+  std::vector<std::string> webrtc_local_ips_allowed_urls;
+  bool webrtc_allow_legacy_tls_protocols{false};
+  UserAgentOverride user_agent_override;
+  std::string accept_languages;
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+  std::string system_font_family_name;
+#endif
+#if defined(OS_WIN)
+  base::string16 caption_font_family_name;
+  int32_t caption_font_height{0};
+  base::string16 small_caption_font_family_name;
+  int32_t small_caption_font_height{0};
+  base::string16 menu_font_family_name;
+  int32_t menu_font_height{0};
+  base::string16 status_font_family_name;
+  int32_t status_font_height{0};
+  base::string16 message_font_family_name;
+  int32_t message_font_height{0};
+  int32_t vertical_scroll_bar_width_in_dips{0};
+  int32_t horizontal_scroll_bar_height_in_dips{0};
+  int32_t arrow_bitmap_height_vertical_scroll_bar_in_dips{0};
+  int32_t arrow_bitmap_width_horizontal_scroll_bar_in_dips{0};
+#endif
+#if defined(USE_X11) || defined(USE_OZONE)
+  bool selection_clipboard_buffer_available{false};
+#endif
+  bool plugin_fullscreen_allowed{true};
+  bool caret_browsing_enabled{false};
+
+  RendererPreferences();
+  RendererPreferences(const RendererPreferences& other);
+  RendererPreferences(RendererPreferences&& other);
+  ~RendererPreferences();
+  RendererPreferences& operator=(const RendererPreferences& other);
+  RendererPreferences& operator=(RendererPreferences&& other);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_RENDERER_PREFERENCES_RENDERER_PREFERENCES_H_
diff --git a/third_party/blink/public/common/renderer_preferences/renderer_preferences_mojom_traits.h b/third_party/blink/public/common/renderer_preferences/renderer_preferences_mojom_traits.h
new file mode 100644
index 0000000..cd59b71
--- /dev/null
+++ b/third_party/blink/public/common/renderer_preferences/renderer_preferences_mojom_traits.h
@@ -0,0 +1,246 @@
+// 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 THIRD_PARTY_BLINK_PUBLIC_COMMON_RENDERER_PREFERENCES_RENDERER_PREFERENCES_MOJOM_TRAITS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_RENDERER_PREFERENCES_RENDERER_PREFERENCES_MOJOM_TRAITS_H_
+
+#include <string>
+
+#include "build/build_config.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
+#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
+#include "third_party/blink/public/common/user_agent/user_agent_mojom_traits.h"
+#include "third_party/blink/public/mojom/renderer_preferences.mojom-shared.h"
+#include "ui/gfx/mojom/font_render_params_mojom_traits.h"
+
+#if defined(OS_WIN)
+#include "mojo/public/cpp/base/string16_mojom_traits.h"
+#endif
+
+namespace mojo {
+
+template <>
+struct BLINK_COMMON_EXPORT
+    StructTraits<blink::mojom::RendererPreferencesDataView,
+                 ::blink::RendererPreferences> {
+  static const bool& can_accept_load_drops(
+      const ::blink::RendererPreferences& data) {
+    return data.can_accept_load_drops;
+  }
+
+  static const bool& should_antialias_text(
+      const ::blink::RendererPreferences& data) {
+    return data.should_antialias_text;
+  }
+
+  static const gfx::FontRenderParams::Hinting& hinting(
+      const ::blink::RendererPreferences& data) {
+    return data.hinting;
+  }
+
+  static const bool& use_autohinter(const ::blink::RendererPreferences& data) {
+    return data.use_autohinter;
+  }
+
+  static const bool& use_bitmaps(const ::blink::RendererPreferences& data) {
+    return data.use_bitmaps;
+  }
+
+  static const gfx::FontRenderParams::SubpixelRendering& subpixel_rendering(
+      const ::blink::RendererPreferences& data) {
+    return data.subpixel_rendering;
+  }
+
+  static const bool& use_subpixel_positioning(
+      const ::blink::RendererPreferences& data) {
+    return data.use_subpixel_positioning;
+  }
+
+  static const uint32_t& focus_ring_color(
+      const ::blink::RendererPreferences& data) {
+    return data.focus_ring_color;
+  }
+
+  static const uint32_t& active_selection_bg_color(
+      const ::blink::RendererPreferences& data) {
+    return data.active_selection_bg_color;
+  }
+
+  static const uint32_t& active_selection_fg_color(
+      const ::blink::RendererPreferences& data) {
+    return data.active_selection_fg_color;
+  }
+
+  static const uint32_t& inactive_selection_bg_color(
+      const ::blink::RendererPreferences& data) {
+    return data.inactive_selection_bg_color;
+  }
+
+  static const uint32_t& inactive_selection_fg_color(
+      const ::blink::RendererPreferences& data) {
+    return data.inactive_selection_fg_color;
+  }
+
+  static const bool& browser_handles_all_top_level_requests(
+      const ::blink::RendererPreferences& data) {
+    return data.browser_handles_all_top_level_requests;
+  }
+
+  static base::Optional<base::TimeDelta> caret_blink_interval(
+      const ::blink::RendererPreferences& data) {
+    return data.caret_blink_interval;
+  }
+
+  static const bool& use_custom_colors(
+      const ::blink::RendererPreferences& data) {
+    return data.use_custom_colors;
+  }
+
+  static const bool& enable_referrers(
+      const ::blink::RendererPreferences& data) {
+    return data.enable_referrers;
+  }
+
+  static const bool& allow_cross_origin_auth_prompt(
+      const ::blink::RendererPreferences& data) {
+    return data.allow_cross_origin_auth_prompt;
+  }
+
+  static const bool& enable_do_not_track(
+      const ::blink::RendererPreferences& data) {
+    return data.enable_do_not_track;
+  }
+
+  static const bool& enable_encrypted_media(
+      const ::blink::RendererPreferences& data) {
+    return data.enable_encrypted_media;
+  }
+
+  static const std::string& webrtc_ip_handling_policy(
+      const ::blink::RendererPreferences& data) {
+    return data.webrtc_ip_handling_policy;
+  }
+
+  static const uint16_t& webrtc_udp_min_port(
+      const ::blink::RendererPreferences& data) {
+    return data.webrtc_udp_min_port;
+  }
+
+  static const uint16_t& webrtc_udp_max_port(
+      const ::blink::RendererPreferences& data) {
+    return data.webrtc_udp_max_port;
+  }
+
+  static const std::vector<std::string>& webrtc_local_ips_allowed_urls(
+      const ::blink::RendererPreferences& data) {
+    return data.webrtc_local_ips_allowed_urls;
+  }
+
+  static const bool& webrtc_allow_legacy_tls_protocols(
+      const ::blink::RendererPreferences& data) {
+    return data.webrtc_allow_legacy_tls_protocols;
+  }
+
+  static const ::blink::UserAgentOverride& user_agent_override(
+      const ::blink::RendererPreferences& data) {
+    return data.user_agent_override;
+  }
+
+  static const std::string& accept_languages(
+      const ::blink::RendererPreferences& data) {
+    return data.accept_languages;
+  }
+
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+  static const std::string& system_font_family_name(
+      const ::blink::RendererPreferences& data) {
+    return data.system_font_family_name;
+  }
+#endif
+
+#if defined(USE_X11) || defined(USE_OZONE)
+  static const bool& selection_clipboard_buffer_available(
+      const ::blink::RendererPreferences& data) {
+    return data.selection_clipboard_buffer_available;
+  }
+#endif
+
+#if defined(OS_WIN)
+  static const base::string16& caption_font_family_name(
+      const ::blink::RendererPreferences& data) {
+    return data.caption_font_family_name;
+  }
+  static const int32_t& caption_font_height(
+      const ::blink::RendererPreferences& data) {
+    return data.caption_font_height;
+  }
+  static const base::string16& small_caption_font_family_name(
+      const ::blink::RendererPreferences& data) {
+    return data.small_caption_font_family_name;
+  }
+  static const int32_t& small_caption_font_height(
+      const ::blink::RendererPreferences& data) {
+    return data.small_caption_font_height;
+  }
+  static const base::string16& menu_font_family_name(
+      const ::blink::RendererPreferences& data) {
+    return data.menu_font_family_name;
+  }
+  static const int32_t& menu_font_height(
+      const ::blink::RendererPreferences& data) {
+    return data.menu_font_height;
+  }
+  static const base::string16& status_font_family_name(
+      const ::blink::RendererPreferences& data) {
+    return data.status_font_family_name;
+  }
+  static const int32_t& status_font_height(
+      const ::blink::RendererPreferences& data) {
+    return data.status_font_height;
+  }
+  static const base::string16& message_font_family_name(
+      const ::blink::RendererPreferences& data) {
+    return data.message_font_family_name;
+  }
+  static const int32_t& message_font_height(
+      const ::blink::RendererPreferences& data) {
+    return data.message_font_height;
+  }
+  static const int32_t& vertical_scroll_bar_width_in_dips(
+      const ::blink::RendererPreferences& data) {
+    return data.vertical_scroll_bar_width_in_dips;
+  }
+  static const int32_t& horizontal_scroll_bar_height_in_dips(
+      const ::blink::RendererPreferences& data) {
+    return data.horizontal_scroll_bar_height_in_dips;
+  }
+  static const int32_t& arrow_bitmap_height_vertical_scroll_bar_in_dips(
+      const ::blink::RendererPreferences& data) {
+    return data.arrow_bitmap_height_vertical_scroll_bar_in_dips;
+  }
+  static const int32_t& arrow_bitmap_width_horizontal_scroll_bar_in_dips(
+      const ::blink::RendererPreferences& data) {
+    return data.arrow_bitmap_width_horizontal_scroll_bar_in_dips;
+  }
+#endif
+
+  static const bool& plugin_fullscreen_allowed(
+      const ::blink::RendererPreferences& data) {
+    return data.plugin_fullscreen_allowed;
+  }
+
+  static const bool& caret_browsing_enabled(
+      const ::blink::RendererPreferences& data) {
+    return data.caret_browsing_enabled;
+  }
+
+  static bool Read(blink::mojom::RendererPreferencesDataView,
+                   ::blink::RendererPreferences* out);
+};
+
+}  // namespace mojo
+
+#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_RENDERER_PREFERENCES_RENDERER_PREFERENCES_MOJOM_TRAITS_H_
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
index ac4cb395..83010f7 100644
--- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl
+++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -8255,6 +8255,11 @@
       # Client To Authenticator Protocol 2.
       ctap2
 
+  type Ctap2Version extends string
+    enum
+      ctap2_0
+      ctap2_1
+
   type AuthenticatorTransport extends string
     enum
       # Cross-Platform authenticator attachments:
@@ -8268,6 +8273,8 @@
   type VirtualAuthenticatorOptions extends object
     properties
       AuthenticatorProtocol protocol
+      # Defaults to ctap2_0. Ignored if |protocol| == u2f.
+      optional Ctap2Version ctap2Version
       AuthenticatorTransport transport
       # Defaults to false.
       optional boolean hasResidentKey
@@ -8300,6 +8307,9 @@
       # assertion.
       # See https://w3c.github.io/webauthn/#signature-counter
       integer signCount
+      # The large blob associated with the credential.
+      # See https://w3c.github.io/webauthn/#sctn-large-blob-extension
+      optional binary largeBlob
 
   # Enable the WebAuthn domain and start intercepting credential storage and
   # retrieval with a virtual authenticator.
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index 8d89812..d95e7e7 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -401,6 +401,15 @@
     {
       types = [
         {
+          mojom = "blink.mojom.RendererPreferences"
+          cpp = "::blink::RendererPreferences"
+        },
+      ]
+      traits_headers = [ "//third_party/blink/public/common/renderer_preferences/renderer_preferences_mojom_traits.h" ]
+    },
+    {
+      types = [
+        {
           mojom = "blink.mojom.WebPreferences"
           cpp = "::blink::web_pref::WebPreferences"
         },
diff --git a/third_party/blink/public/mojom/page/widget.mojom b/third_party/blink/public/mojom/page/widget.mojom
index fbf9609..ee14c4c 100644
--- a/third_party/blink/public/mojom/page/widget.mojom
+++ b/third_party/blink/public/mojom/page/widget.mojom
@@ -260,3 +260,12 @@
   // frame is generated and presented in the display compositor.
   VisualStateRequest() => ();
 };
+
+// Implemented in Browser, this interface defines popup-widget-specific methods
+// that will be invoked from the render process (e.g. RenderWidgetHostImpl).
+// Popup widgets in the renderer are owned by the PopupWidgetHost in the browser
+// process, so the PopupWidgetHost channel disconnecting indicates that the
+// widget in the renderer should be destroyed.
+interface PopupWidgetHost {
+  // TODO(dtapuska): Add ShowPopup method that will replace ViewHostMsg_ShowWidget
+};
\ No newline at end of file
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom
index f3230a2..873d7df 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -3036,6 +3036,7 @@
   kNewLayoutOverflowDifferentAndAlreadyScrollsFlex = 3705,
   kUnicodeBidiPlainText = 3706,
   kColorSchemeDarkSupportedOnRoot = 3707,
+  kWebBluetoothGetAvailability = 3708,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/platform/DEPS b/third_party/blink/public/platform/DEPS
index 23fb529..515cba8 100644
--- a/third_party/blink/public/platform/DEPS
+++ b/third_party/blink/public/platform/DEPS
@@ -53,7 +53,9 @@
     "+services/network/public/mojom/ip_address_space.mojom-shared.h",
     "+services/network/public/mojom/referrer_policy.mojom-shared.h",
     "+services/network/public/mojom/trust_tokens.mojom-shared.h",
+    "+services/network/public/mojom/url_loader.mojom-forward.h",
     "+services/network/public/mojom/url_loader_factory.mojom-shared.h",
+    "+services/network/public/mojom/url_response_head.mojom.h",
     "+services/network/public/mojom/url_response_head.mojom-forward.h",
     "+services/network/public/mojom/web_client_hints_types.mojom-shared.h",
 
diff --git a/content/renderer/loader/sync_load_response.h b/third_party/blink/public/platform/sync_load_response.h
similarity index 69%
rename from content/renderer/loader/sync_load_response.h
rename to third_party/blink/public/platform/sync_load_response.h
index 6435a957..70239dd 100644
--- a/content/renderer/loader/sync_load_response.h
+++ b/third_party/blink/public/platform/sync_load_response.h
@@ -2,27 +2,26 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_RENDERER_LOADER_SYNC_LOAD_RESPONSE_H_
-#define CONTENT_RENDERER_LOADER_SYNC_LOAD_RESPONSE_H_
-
-#include <string>
+#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_SYNC_LOAD_RESPONSE_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_SYNC_LOAD_RESPONSE_H_
 
 #include "base/optional.h"
-#include "content/common/content_export.h"
 #include "net/dns/public/resolve_error_info.h"
 #include "services/network/public/cpp/cors/cors_error_status.h"
 #include "services/network/public/mojom/url_loader.mojom-forward.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
 #include "third_party/blink/public/mojom/blob/serialized_blob.mojom.h"
-#include "url/gurl.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_data.h"
+#include "third_party/blink/public/platform/web_url.h"
 
-namespace content {
-
-class SyncLoadContext;
+namespace blink {
 
 // See the SyncLoad method. (The name of this struct is not
 // suffixed with "Info" because it also contains the response data.)
-struct CONTENT_EXPORT SyncLoadResponse {
+// TODO(crbug.com/1110032): Move this class to
+// blink/renderer/platform/loader/fetch/url_loader.
+struct BLINK_PLATFORM_EXPORT SyncLoadResponse {
   SyncLoadResponse();
   SyncLoadResponse(SyncLoadResponse&& other);
   ~SyncLoadResponse();
@@ -30,7 +29,6 @@
   SyncLoadResponse& operator=(SyncLoadResponse&& other);
 
   base::Optional<net::RedirectInfo> redirect_info;
-  SyncLoadContext* context_for_redirect = nullptr;
 
   network::mojom::URLResponseHeadPtr head =
       network::mojom::URLResponseHead::New();
@@ -49,15 +47,15 @@
 
   // The final URL of the response.  This may differ from the request URL in
   // the case of a server redirect.
-  GURL url;
+  WebURL url;
 
   // The response data.
-  std::string data;
+  WebData data;
 
   // Used for blob response type XMLHttpRequest.
-  blink::mojom::SerializedBlobPtr downloaded_blob;
+  mojom::SerializedBlobPtr downloaded_blob;
 };
 
-}  // namespace content
+}  // namespace blink
 
-#endif  // CONTENT_RENDERER_LOADER_SYNC_LOAD_RESPONSE_H_
+#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_SYNC_LOAD_RESPONSE_H_
diff --git a/third_party/blink/public/platform/web_float_rect.h b/third_party/blink/public/platform/web_float_rect.h
deleted file mode 100644
index 430b169..0000000
--- a/third_party/blink/public/platform/web_float_rect.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_FLOAT_RECT_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_FLOAT_RECT_H_
-
-#include "third_party/blink/public/platform/web_common.h"
-
-#if INSIDE_BLINK
-#include "third_party/blink/renderer/platform/geometry/float_rect.h"  // nogncheck
-#else
-#include <algorithm>
-#include <cmath>
-#include <ui/gfx/geometry/rect_f.h>
-#endif
-
-namespace blink {
-
-struct WebFloatRect {
-  float x;
-  float y;
-  float width;
-  float height;
-
-  bool IsEmpty() const { return width <= 0 || height <= 0; }
-
-  WebFloatRect() : x(0), y(0), width(0), height(0) {}
-
-  WebFloatRect(float x, float y, float width, float height)
-      : x(x), y(y), width(width), height(height) {}
-
-#if INSIDE_BLINK
-  WebFloatRect(const FloatRect& r)
-      : x(r.X()), y(r.Y()), width(r.Width()), height(r.Height()) {}
-
-  WebFloatRect& operator=(const FloatRect& r) {
-    x = r.X();
-    y = r.Y();
-    width = r.Width();
-    height = r.Height();
-    return *this;
-  }
-
-  operator FloatRect() const { return FloatRect(x, y, width, height); }
-#else
-  WebFloatRect(const gfx::RectF& r)
-      : x(r.x()), y(r.y()), width(r.width()), height(r.height()) {}
-
-  WebFloatRect& operator=(const gfx::RectF& r) {
-    x = r.x();
-    y = r.y();
-    width = r.width();
-    height = r.height();
-    return *this;
-  }
-
-  operator gfx::RectF() const {
-    return gfx::RectF(x, y, std::max(0.0f, width), std::max(0.0f, height));
-  }
-#endif
-};
-
-inline bool operator==(const WebFloatRect& a, const WebFloatRect& b) {
-  return a.x == b.x && a.y == b.y && a.width == b.width && a.height == b.height;
-}
-
-inline bool operator!=(const WebFloatRect& a, const WebFloatRect& b) {
-  return !(a == b);
-}
-
-}  // namespace blink
-
-#endif
diff --git a/third_party/blink/public/strings/translations/blink_strings_iw.xtb b/third_party/blink/public/strings/translations/blink_strings_iw.xtb
index 1590307..a50b292 100644
--- a/third_party/blink/public/strings/translations/blink_strings_iw.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_iw.xtb
@@ -94,7 +94,7 @@
 <translation id="3808586225841795776">מונח</translation>
 <translation id="3822383571486410024">הארך טקסט זה ל-<ph name="MIN_CHARACTERS" /> תווים או יותר (אתה משתמש כרגע ב-<ph name="CURRENT_LENGTH" /> תווים).</translation>
 <translation id="383465348367842624">חלק ולאחריו '<ph name="ATSIGN" />' לא אמור לכלול את הסמל '<ph name="INVALIDCHARACTER" />'.</translation>
-<translation id="3846214748874656680">צא ממסך מלא</translation>
+<translation id="3846214748874656680">יציאה ממסך מלא</translation>
 <translation id="3920932319529768807">סיכום</translation>
 <translation id="3924558731517983934">אפליקציה</translation>
 <translation id="3944740393230681990">פרולוג</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_pa.xtb b/third_party/blink/public/strings/translations/blink_strings_pa.xtb
index 3886b18..fd2c4728 100644
--- a/third_party/blink/public/strings/translations/blink_strings_pa.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_pa.xtb
@@ -106,7 +106,7 @@
 <translation id="4201051445878709314">ਪਿਛਲਾ ਮਹੀਨਾ ਦਿਖਾਓ</translation>
 <translation id="421884353938374759">ਰੰਗ ਚੋਣਕਾਰ</translation>
 <translation id="4248100235867064564">ਮੀਨੂ ਬਾਰ</translation>
-<translation id="4293574643247337246">ਪੰਨਾ ਸਿਰਲੇਖ</translation>
+<translation id="4293574643247337246">ਪੰਨੇ ਦਾ ਸਿਰਲੇਖ</translation>
 <translation id="4360991593054037559">ਕਿਰਪਾ ਕਰਕੇ ਇੱਕ ਪ੍ਰਮਾਣਿਕ ਵੈਲਯੂ ਦਰਜ ਕਰੋ। ਦੋ ਲਗਭਗ ਵੈਲਯੂਜ <ph name="VALID_VALUE_LOW" /> ਅਤੇ <ph name="VALID_VALUE_HIGHER" /> ਹਨ।</translation>
 <translation id="4384583879834880242">ਸਵਾਲ-ਜਵਾਬ</translation>
 <translation id="4444765639179266822">ਲੱਗਦਾ ਹੈ ਕਿ ਇਹ ਕਿਹਾ ਜਾ ਰਿਹਾ ਹੈ: <ph name="OCR_TEXT" /></translation>
diff --git a/third_party/blink/public/web/web_page_popup.h b/third_party/blink/public/web/web_page_popup.h
index 28cbc9a..5871604 100644
--- a/third_party/blink/public/web/web_page_popup.h
+++ b/third_party/blink/public/web/web_page_popup.h
@@ -49,6 +49,10 @@
   // WebWidget will be closed asynchronously as a result of this
   // request.
   virtual void ClosePopupWidgetSoon() = 0;
+
+  // Request to destroy the WebPagePopupClient immediately given that the
+  // browser has closed the associated mojom connection.
+  virtual void BrowserClosedIpcChannelForPopupWidget() = 0;
 };
 
 class WebPagePopup : public WebWidget {
@@ -57,6 +61,8 @@
   // be released when the popup is closed via Close().
   BLINK_EXPORT static WebPagePopup* Create(
       WebPagePopupClient*,
+      CrossVariantMojoAssociatedRemote<mojom::PopupWidgetHostInterfaceBase>
+          popup_widget_host,
       CrossVariantMojoAssociatedRemote<mojom::WidgetHostInterfaceBase>
           widget_host,
       CrossVariantMojoAssociatedReceiver<mojom::WidgetInterfaceBase> widget);
diff --git a/third_party/blink/renderer/bindings/core/v8/BUILD.gn b/third_party/blink/renderer/bindings/core/v8/BUILD.gn
index 90e4e5d..e3df5db0 100644
--- a/third_party/blink/renderer/bindings/core/v8/BUILD.gn
+++ b/third_party/blink/renderer/bindings/core/v8/BUILD.gn
@@ -62,6 +62,7 @@
   deps = [
     ":generated",
     ":testing_internal",
+    "//third_party/blink/renderer/core",
     "//third_party/blink/renderer/platform",
     "//v8",
   ]
@@ -74,8 +75,10 @@
     "//third_party/blink/renderer/core/*",
   ]
 
-  public_deps =
-      [ "//third_party/blink/renderer/bindings:generate_bindings_all" ]
+  public_deps = [
+    ":bindings_core_v8_generated",
+    "//third_party/blink/renderer/bindings:generate_bindings_all",
+  ]
 }
 
 if (use_blink_v8_binding_new_idl_interface) {
diff --git a/third_party/blink/renderer/bindings/modules/v8/BUILD.gn b/third_party/blink/renderer/bindings/modules/v8/BUILD.gn
index 2f311abd..3a7ae90e 100644
--- a/third_party/blink/renderer/bindings/modules/v8/BUILD.gn
+++ b/third_party/blink/renderer/bindings/modules/v8/BUILD.gn
@@ -60,6 +60,8 @@
 
   deps = [
     ":generated",
+    "//third_party/blink/renderer/core",
+    "//third_party/blink/renderer/modules",
     "//third_party/blink/renderer/platform",
     "//v8",
   ]
@@ -75,8 +77,10 @@
     "//third_party/blink/renderer/modules/*",
   ]
 
-  public_deps =
-      [ "//third_party/blink/renderer/bindings:generate_bindings_all" ]
+  public_deps = [
+    ":bindings_modules_v8_generated",
+    "//third_party/blink/renderer/bindings:generate_bindings_all",
+  ]
 }
 
 group("bindings_modules_v8_generated") {
@@ -87,6 +91,7 @@
     ":generate_bindings_modules_v8_partial_interfaces",
     ":generate_bindings_modules_v8_partial_interfaces_for_testing",
     ":generate_v8_context_snapshot_external_references",
+    "//third_party/blink/renderer/bindings/core/v8:bindings_core_v8_generated",
   ]
 }
 
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl b/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl
index c1bd8f2d..2b57b4c 100644
--- a/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl
+++ b/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl
@@ -218,6 +218,8 @@
     {% set animation = 'Animation' if property.style_builder_template == 'animation' else 'Transition' %}
     {% set vector = attribute + "List()" %}
     {% call(property) apply_initial(property) %}
+  if (!state.Style()->{{animation}}s())
+    return;
   CSS{{animation}}Data& data = state.Style()->Access{{animation}}s();
   data.{{vector}}.clear();
   data.{{vector}}.push_back(CSS{{animation}}Data::Initial{{attribute}}());
diff --git a/third_party/blink/renderer/core/clipboard/data_transfer.cc b/third_party/blink/renderer/core/clipboard/data_transfer.cc
index c95d50e..7d772a26 100644
--- a/third_party/blink/renderer/core/clipboard/data_transfer.cc
+++ b/third_party/blink/renderer/core/clipboard/data_transfer.cc
@@ -147,7 +147,6 @@
 
     return DataTransfer::CreateDragImageForFrame(
         *local_frame_, 1.0f,
-        LayoutObject::ShouldRespectImageOrientation(dragged_layout_object),
         bounding_box.Size(), paint_offset, builder, border_box_properties);
   }
 
@@ -392,7 +391,6 @@
 std::unique_ptr<DragImage> DataTransfer::CreateDragImageForFrame(
     LocalFrame& frame,
     float opacity,
-    RespectImageOrientationEnum image_orientation,
     const FloatSize& css_size,
     const FloatPoint& paint_offset,
     PaintRecordBuilder& builder,
@@ -425,7 +423,10 @@
   float screen_device_scale_factor =
       chrome_client.GetScreenInfo(frame).device_scale_factor;
 
-  return DragImage::Create(image.get(), image_orientation,
+  // There is no orientation information in the image, so pass
+  // kDoNotRespectImageOrientation in order to avoid wasted work looking
+  // at orientation.
+  return DragImage::Create(image.get(), kDoNotRespectImageOrientation,
                            screen_device_scale_factor, kInterpolationDefault,
                            opacity);
 }
diff --git a/third_party/blink/renderer/core/clipboard/data_transfer.h b/third_party/blink/renderer/core/clipboard/data_transfer.h
index 5887f8a..278e7ce 100644
--- a/third_party/blink/renderer/core/clipboard/data_transfer.h
+++ b/third_party/blink/renderer/core/clipboard/data_transfer.h
@@ -148,7 +148,6 @@
   static std::unique_ptr<DragImage> CreateDragImageForFrame(
       LocalFrame&,
       float,
-      RespectImageOrientationEnum,
       const FloatSize& css_size,
       const FloatPoint& paint_offset,
       PaintRecordBuilder&,
diff --git a/third_party/blink/renderer/core/editing/dom_selection.cc b/third_party/blink/renderer/core/editing/dom_selection.cc
index 7d5f0b5..188d1906 100644
--- a/third_party/blink/renderer/core/editing/dom_selection.cc
+++ b/third_party/blink/renderer/core/editing/dom_selection.cc
@@ -43,6 +43,7 @@
 #include "third_party/blink/renderer/core/editing/set_selection_options.h"
 #include "third_party/blink/renderer/core/editing/visible_selection.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/inspector/console_message.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -52,68 +53,52 @@
 
 namespace blink {
 
-static Node* SelectionShadowAncestor(LocalFrame* frame) {
-  Node* node = frame->Selection()
-                   .ComputeVisibleSelectionInDOMTreeDeprecated()
-                   .Base()
-                   .AnchorNode();
-  if (!node)
-    return nullptr;
-
-  if (!node->IsInShadowTree())
-    return nullptr;
-
-  return frame->GetDocument()->AncestorInThisScope(node);
-}
-
 DOMSelection::DOMSelection(const TreeScope* tree_scope)
-    : ExecutionContextClient(tree_scope->RootNode().GetDocument().GetFrame()),
+    : ExecutionContextClient(tree_scope->RootNode().GetExecutionContext()),
       tree_scope_(tree_scope) {}
 
 void DOMSelection::ClearTreeScope() {
   tree_scope_ = nullptr;
 }
 
+FrameSelection& DOMSelection::Selection() const {
+  DCHECK(DomWindow());
+  return DomWindow()->GetFrame()->Selection();
+}
+
 // TODO(editing-dev): The behavior after loosing browsing context is not
 // specified. https://github.com/w3c/selection-api/issues/82
 bool DOMSelection::IsAvailable() const {
-  return GetFrame() && GetFrame()->Selection().IsAvailable();
+  return DomWindow() && Selection().IsAvailable();
 }
 
 void DOMSelection::UpdateFrameSelection(
     const SelectionInDOMTree& selection,
     Range* new_cached_range,
     const SetSelectionOptions& passed_options) const {
-  DCHECK(GetFrame());
-  FrameSelection& frame_selection = GetFrame()->Selection();
+  DCHECK(DomWindow());
   SetSelectionOptions::Builder builder(passed_options);
   builder.SetShouldCloseTyping(true).SetShouldClearTypingStyle(true);
   SetSelectionOptions options = builder.Build();
   // TODO(tkent): Specify FrameSelection::DoNotSetFocus. crbug.com/690272
-  const bool did_set =
-      frame_selection.SetSelectionDeprecated(selection, options);
+  const bool did_set = Selection().SetSelectionDeprecated(selection, options);
   CacheRangeIfSelectionOfDocument(new_cached_range);
   if (!did_set)
     return;
-  Element* focused_element = GetFrame()->GetDocument()->FocusedElement();
-  frame_selection.DidSetSelectionDeprecated(selection, options);
-  if (GetFrame() && GetFrame()->GetDocument() &&
-      focused_element != GetFrame()->GetDocument()->FocusedElement()) {
-    UseCounter::Count(GetFrame()->GetDocument(),
-                      WebFeature::kSelectionFuncionsChangeFocus);
+  Element* focused_element = DomWindow()->document()->FocusedElement();
+  Selection().DidSetSelectionDeprecated(selection, options);
+  if (DomWindow() &&
+      focused_element != DomWindow()->document()->FocusedElement()) {
+    UseCounter::Count(DomWindow(), WebFeature::kSelectionFuncionsChangeFocus);
   }
 }
 
 VisibleSelection DOMSelection::GetVisibleSelection() const {
-  DCHECK(GetFrame());
-  return GetFrame()->Selection().ComputeVisibleSelectionInDOMTreeDeprecated();
+  return Selection().ComputeVisibleSelectionInDOMTreeDeprecated();
 }
 
 bool DOMSelection::IsBaseFirstInSelection() const {
-  DCHECK(GetFrame());
-  const SelectionInDOMTree& selection =
-      GetFrame()->Selection().GetSelectionInDOMTree();
-  return selection.IsBaseFirst();
+  return Selection().GetSelectionInDOMTree().IsBaseFirst();
 }
 
 // TODO(tkent): Following four functions based on VisibleSelection should be
@@ -132,7 +117,7 @@
 
 Node* DOMSelection::anchorNode() const {
   if (Range* range = PrimaryRangeOrNull()) {
-    if (!GetFrame() || IsBaseFirstInSelection())
+    if (!DomWindow() || IsBaseFirstInSelection())
       return range->startContainer();
     return range->endContainer();
   }
@@ -141,7 +126,7 @@
 
 unsigned DOMSelection::anchorOffset() const {
   if (Range* range = PrimaryRangeOrNull()) {
-    if (!GetFrame() || IsBaseFirstInSelection())
+    if (!DomWindow() || IsBaseFirstInSelection())
       return range->startOffset();
     return range->endOffset();
   }
@@ -150,7 +135,7 @@
 
 Node* DOMSelection::focusNode() const {
   if (Range* range = PrimaryRangeOrNull()) {
-    if (!GetFrame() || IsBaseFirstInSelection())
+    if (!DomWindow() || IsBaseFirstInSelection())
       return range->endContainer();
     return range->startContainer();
   }
@@ -159,7 +144,7 @@
 
 unsigned DOMSelection::focusOffset() const {
   if (Range* range = PrimaryRangeOrNull()) {
-    if (!GetFrame() || IsBaseFirstInSelection())
+    if (!DomWindow() || IsBaseFirstInSelection())
       return range->endOffset();
     return range->startOffset();
   }
@@ -183,8 +168,17 @@
 }
 
 bool DOMSelection::isCollapsed() const {
-  if (!IsAvailable() || SelectionShadowAncestor(GetFrame()))
+  if (!IsAvailable())
     return true;
+  Node* node = Selection()
+                   .ComputeVisibleSelectionInDOMTreeDeprecated()
+                   .Base()
+                   .AnchorNode();
+  if (node && node->IsInShadowTree() &&
+      DomWindow()->document()->AncestorInThisScope(node)) {
+    return true;
+  }
+
   if (Range* range = PrimaryRangeOrNull())
     return range->collapsed();
   return true;
@@ -200,7 +194,7 @@
     return "None";
   // Do not use isCollapsed() here. We'd like to return "Range" for
   // range-selection in text control elements.
-  if (GetFrame()->Selection().GetSelectionInDOMTree().IsCaret())
+  if (Selection().GetSelectionInDOMTree().IsCaret())
     return "Caret";
   return "Range";
 }
@@ -210,10 +204,7 @@
     return 0;
   if (DocumentCachedRange())
     return 1;
-  if (GetFrame()
-          ->Selection()
-          .ComputeVisibleSelectionInDOMTreeDeprecated()
-          .IsNone())
+  if (Selection().ComputeVisibleSelectionInDOMTreeDeprecated().IsNone())
     return 0;
   // Any selection can be adjusted to Range for Document.
   if (IsSelectionOfDocument())
@@ -234,9 +225,8 @@
   // 1. If node is null, this method must behave identically as
   // removeAllRanges() and abort these steps.
   if (!node) {
-    UseCounter::Count(GetFrame()->GetDocument(),
-                      WebFeature::kSelectionCollapseNull);
-    GetFrame()->Selection().Clear();
+    UseCounter::Count(DomWindow(), WebFeature::kSelectionCollapseNull);
+    Selection().Clear();
     return;
   }
 
@@ -252,7 +242,7 @@
     return;
 
   // 4. Otherwise, let newRange be a new range.
-  Range* new_range = Range::Create(*GetFrame()->GetDocument());
+  Range* new_range = Range::Create(*DomWindow()->document());
 
   // 5. Set ([DOM4]) the start and the end of newRange to (node, offset).
   new_range->setStart(node, offset, exception_state);
@@ -268,12 +258,10 @@
 
   // 6. Set the context object's range to newRange.
   UpdateFrameSelection(
-      SelectionInDOMTree::Builder()
-          .Collapse(Position(node, offset))
-          .Build(),
+      SelectionInDOMTree::Builder().Collapse(Position(node, offset)).Build(),
       new_range,
       SetSelectionOptions::Builder()
-          .SetIsDirectional(GetFrame()->Selection().IsDirectional())
+          .SetIsDirectional(Selection().IsDirectional())
           .Build());
 }
 
@@ -304,8 +292,7 @@
     // TODO(tkent): The Selection API doesn't define this behavior. We should
     // discuss this on https://github.com/w3c/selection-api/issues/83.
     SelectionInDOMTree::Builder builder;
-    builder.Collapse(
-        GetFrame()->Selection().GetSelectionInDOMTree().ComputeEndPosition());
+    builder.Collapse(Selection().GetSelectionInDOMTree().ComputeEndPosition());
     UpdateFrameSelection(builder.Build(), nullptr, SetSelectionOptions());
   }
 }
@@ -338,15 +325,14 @@
     // discuss this on https://github.com/w3c/selection-api/issues/83.
     SelectionInDOMTree::Builder builder;
     builder.Collapse(
-        GetFrame()->Selection().GetSelectionInDOMTree().ComputeStartPosition());
+        Selection().GetSelectionInDOMTree().ComputeStartPosition());
     UpdateFrameSelection(builder.Build(), nullptr, SetSelectionOptions());
   }
 }
 
 void DOMSelection::empty() {
-  if (!IsAvailable())
-    return;
-  GetFrame()->Selection().Clear();
+  if (IsAvailable())
+    Selection().Clear();
 }
 
 void DOMSelection::setBaseAndExtent(Node* base_node,
@@ -360,14 +346,12 @@
   // TODO(editing-dev): Behavior on where base or extent is null is still
   // under discussion: https://github.com/w3c/selection-api/issues/72
   if (!base_node) {
-    UseCounter::Count(GetFrame()->GetDocument(),
-                      WebFeature::kSelectionSetBaseAndExtentNull);
-    GetFrame()->Selection().Clear();
+    UseCounter::Count(DomWindow(), WebFeature::kSelectionSetBaseAndExtentNull);
+    Selection().Clear();
     return;
   }
   if (!extent_node) {
-    UseCounter::Count(GetFrame()->GetDocument(),
-                      WebFeature::kSelectionSetBaseAndExtentNull);
+    UseCounter::Count(DomWindow(), WebFeature::kSelectionSetBaseAndExtentNull);
     extent_offset = 0;
   }
 
@@ -455,16 +439,14 @@
 
   // TODO(editing-dev): The use of UpdateStyleAndLayout
   // needs to be audited.  See http://crbug.com/590369 for more details.
-  GetFrame()->GetDocument()->UpdateStyleAndLayout(
+  DomWindow()->document()->UpdateStyleAndLayout(
       DocumentUpdateReason::kSelection);
 
-  Element* focused_element = GetFrame()->GetDocument()->FocusedElement();
-  GetFrame()->Selection().Modify(alter, direction, granularity,
-                                 SetSelectionBy::kSystem);
-  if (GetFrame() && GetFrame()->GetDocument() &&
-      focused_element != GetFrame()->GetDocument()->FocusedElement()) {
-    UseCounter::Count(GetFrame()->GetDocument(),
-                      WebFeature::kSelectionFuncionsChangeFocus);
+  Element* focused_element = DomWindow()->document()->FocusedElement();
+  Selection().Modify(alter, direction, granularity, SetSelectionBy::kSystem);
+  if (DomWindow() &&
+      focused_element != DomWindow()->document()->FocusedElement()) {
+    UseCounter::Count(DomWindow(), WebFeature::kSelectionFuncionsChangeFocus);
   }
 }
 
@@ -503,7 +485,7 @@
   ClearCachedRangeIfSelectionOfDocument();
 
   // 4. Let newRange be a new range.
-  Range* new_range = Range::Create(*GetFrame()->GetDocument());
+  Range* new_range = Range::Create(*DomWindow()->document());
 
   // 5. If node's root is not the same as the context object's range's root, set
   // newRange's start and end to newFocus.
@@ -592,35 +574,29 @@
 void DOMSelection::CacheRangeIfSelectionOfDocument(Range* range) const {
   if (!IsSelectionOfDocument())
     return;
-  if (!GetFrame())
+  if (!DomWindow())
     return;
-  GetFrame()->Selection().CacheRangeOfDocument(range);
+  Selection().CacheRangeOfDocument(range);
 }
 
 Range* DOMSelection::DocumentCachedRange() const {
-  if (!IsSelectionOfDocument())
-    return nullptr;
-  return GetFrame()->Selection().DocumentCachedRange();
+  return IsSelectionOfDocument() ? Selection().DocumentCachedRange() : nullptr;
 }
 
 void DOMSelection::ClearCachedRangeIfSelectionOfDocument() {
-  if (!IsSelectionOfDocument())
-    return;
-  GetFrame()->Selection().ClearDocumentCachedRange();
+  if (IsSelectionOfDocument())
+    Selection().ClearDocumentCachedRange();
 }
 
 void DOMSelection::removeRange(Range* range) {
   DCHECK(range);
-  if (!IsAvailable())
-    return;
-  if (range == PrimaryRangeOrNull())
-    GetFrame()->Selection().Clear();
+  if (IsAvailable() && range == PrimaryRangeOrNull())
+    Selection().Clear();
 }
 
 void DOMSelection::removeAllRanges() {
-  if (!IsAvailable())
-    return;
-  GetFrame()->Selection().Clear();
+  if (IsAvailable())
+    Selection().Clear();
 }
 
 void DOMSelection::addRange(Range* new_range) {
@@ -629,7 +605,7 @@
   if (!IsAvailable())
     return;
 
-  if (new_range->OwnerDocument() != GetFrame()->GetDocument())
+  if (new_range->OwnerDocument() != DomWindow()->document())
     return;
 
   if (!new_range->IsConnected()) {
@@ -637,9 +613,7 @@
     return;
   }
 
-  FrameSelection& selection = GetFrame()->Selection();
-
-  if (new_range->OwnerDocument() != selection.GetDocument()) {
+  if (new_range->OwnerDocument() != Selection().GetDocument()) {
     // "editing/selection/selection-in-iframe-removed-crash.html" goes here.
     return;
   }
@@ -691,7 +665,7 @@
 
   // TODO(editing-dev): The use of UpdateStyleAndLayout
   // needs to be audited.  See http://crbug.com/590369 for more details.
-  GetFrame()->GetDocument()->UpdateStyleAndLayout(
+  DomWindow()->document()->UpdateStyleAndLayout(
       DocumentUpdateReason::kSelection);
 
   // The following code is necessary for
@@ -699,14 +673,12 @@
   // deleteFromDocument() for text selection in a TEXTAREA deletes the TEXTAREA
   // value.
 
-  FrameSelection& selection = GetFrame()->Selection();
-
-  if (selection.ComputeVisibleSelectionInDOMTree().IsNone())
+  if (Selection().ComputeVisibleSelectionInDOMTree().IsNone())
     return;
 
-  Range* selected_range =
-      CreateRange(selection.ComputeVisibleSelectionInDOMTree()
-                      .ToNormalizedEphemeralRange());
+  Range* selected_range = CreateRange(Selection()
+                                          .ComputeVisibleSelectionInDOMTree()
+                                          .ToNormalizedEphemeralRange());
   if (!selected_range)
     return;
 
@@ -720,7 +692,7 @@
   if (!IsAvailable())
     return false;
 
-  if (GetFrame()->GetDocument() != n->GetDocument())
+  if (DomWindow()->document() != n->GetDocument())
     return false;
 
   unsigned node_index = n->NodeIndex();
@@ -728,12 +700,12 @@
   // TODO(editing-dev): The use of UpdateStyleAndLayout
   // needs to be audited.  See http://crbug.com/590369 for more details.
   // |VisibleSelection::toNormalizedEphemeralRange| requires clean layout.
-  GetFrame()->GetDocument()->UpdateStyleAndLayout(
+  DomWindow()->document()->UpdateStyleAndLayout(
       DocumentUpdateReason::kSelection);
 
-  FrameSelection& selection = GetFrame()->Selection();
   const EphemeralRange selected_range =
-      selection.ComputeVisibleSelectionInDOMTreeDeprecated()
+      Selection()
+          .ComputeVisibleSelectionInDOMTreeDeprecated()
           .ToNormalizedEphemeralRange();
   if (selected_range.IsNull())
     return false;
@@ -789,14 +761,13 @@
 
   // TODO(editing-dev): The use of UpdateStyleAndLayout
   // needs to be audited.  See http://crbug.com/590369 for more details.
-  GetFrame()->GetDocument()->UpdateStyleAndLayout(
+  DomWindow()->document()->UpdateStyleAndLayout(
       DocumentUpdateReason::kSelection);
 
   DocumentLifecycle::DisallowTransitionScope disallow_transition(
-      GetFrame()->GetDocument()->Lifecycle());
+      DomWindow()->document()->Lifecycle());
 
-  const EphemeralRange range = GetFrame()
-                                   ->Selection()
+  const EphemeralRange range = Selection()
                                    .ComputeVisibleSelectionInDOMTreeDeprecated()
                                    .ToNormalizedEphemeralRange();
   return PlainText(
@@ -838,11 +809,10 @@
 }
 
 bool DOMSelection::IsValidForPosition(Node* node) const {
-  DCHECK(GetFrame());
+  DCHECK(DomWindow());
   if (!node)
     return true;
-  return node->GetDocument() == GetFrame()->GetDocument() &&
-         node->isConnected();
+  return node->GetDocument() == DomWindow()->document() && node->isConnected();
 }
 
 void DOMSelection::AddConsoleWarning(const String& message) {
diff --git a/third_party/blink/renderer/core/editing/dom_selection.h b/third_party/blink/renderer/core/editing/dom_selection.h
index aa4c11a..59aa4f122 100644
--- a/third_party/blink/renderer/core/editing/dom_selection.h
+++ b/third_party/blink/renderer/core/editing/dom_selection.h
@@ -40,6 +40,7 @@
 namespace blink {
 
 class ExceptionState;
+class FrameSelection;
 class Node;
 class Range;
 class SetSelectionOptions;
@@ -102,6 +103,7 @@
   void Trace(Visitor*) const override;
 
  private:
+  FrameSelection& Selection() const;
   bool IsAvailable() const;
 
   void UpdateFrameSelection(const SelectionInDOMTree&,
diff --git a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
index a33944c..d2a3d81 100644
--- a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
@@ -248,11 +248,14 @@
 
 WebPagePopupImpl::WebPagePopupImpl(
     WebPagePopupClient* client,
+    CrossVariantMojoAssociatedRemote<mojom::blink::PopupWidgetHostInterfaceBase>
+        popup_widget_host,
     CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
         widget_host,
     CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
         widget)
     : web_page_popup_client_(client),
+      popup_widget_host_(std::move(popup_widget_host)),
       widget_base_(
           std::make_unique<WidgetBase>(this,
                                        std::move(widget_host),
@@ -261,6 +264,8 @@
                                        /*never_composited=*/false,
                                        /*is_for_child_local_root=*/false)) {
   DCHECK(client);
+  popup_widget_host_.set_disconnect_handler(WTF::Bind(
+      &WebPagePopupImpl::WidgetHostDisconnected, WTF::Unretained(this)));
 }
 
 WebPagePopupImpl::~WebPagePopupImpl() {
@@ -809,6 +814,12 @@
   return {};
 }
 
+void WebPagePopupImpl::WidgetHostDisconnected() {
+  DCHECK(web_page_popup_client_);
+  web_page_popup_client_->BrowserClosedIpcChannelForPopupWidget();
+  // Careful, this is now destroyed.
+}
+
 void WebPagePopupImpl::Close(
     scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner) {
   // If the popup is closed from the renderer via Cancel(), then ClosePopup()
@@ -945,6 +956,8 @@
 
 WebPagePopup* WebPagePopup::Create(
     WebPagePopupClient* client,
+    CrossVariantMojoAssociatedRemote<mojom::blink::PopupWidgetHostInterfaceBase>
+        popup_widget_host,
     CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
         widget_host,
     CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
@@ -957,7 +970,8 @@
   // We need them because the closing operation is asynchronous and the widget
   // can be closed while the WebViewImpl is unaware of it.
   auto popup = base::AdoptRef(
-      new WebPagePopupImpl(client, std::move(widget_host), std::move(widget)));
+      new WebPagePopupImpl(client, std::move(popup_widget_host),
+                           std::move(widget_host), std::move(widget)));
   popup->AddRef();
   return popup.get();
 }
diff --git a/third_party/blink/renderer/core/exported/web_page_popup_impl.h b/third_party/blink/renderer/core/exported/web_page_popup_impl.h
index 8debb93..00b97978 100644
--- a/third_party/blink/renderer/core/exported/web_page_popup_impl.h
+++ b/third_party/blink/renderer/core/exported/web_page_popup_impl.h
@@ -33,6 +33,7 @@
 
 #include "base/macros.h"
 #include "build/build_config.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
 #include "third_party/blink/public/mojom/input/pointer_lock_context.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/input/pointer_lock_result.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/page/widget.mojom-blink.h"
@@ -210,6 +211,8 @@
 
   WebPagePopupImpl(
       WebPagePopupClient*,
+      CrossVariantMojoAssociatedRemote<
+          mojom::blink::PopupWidgetHostInterfaceBase> popup_widget_host,
       CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
           widget_host,
       CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
@@ -226,6 +229,8 @@
                                 cc::ElementId scrollable_area_element_id,
                                 WebInputEvent::Type injected_type);
 
+  void WidgetHostDisconnected();
+
   WebPagePopupClient* web_page_popup_client_;
   WebViewImpl* web_view_ = nullptr;
   // WebPagePopupImpl wraps its own Page that renders the content in the popup.
@@ -252,6 +257,10 @@
   gfx::Point opener_original_widget_screen_origin_;
   float opener_emulator_scale_ = 0;
 
+  // The channel associated with the browser. When this is closed the popup will
+  // be destroyed.
+  mojo::AssociatedRemote<mojom::blink::PopupWidgetHost> popup_widget_host_;
+
   // Base functionality all widgets have. This is a member as to avoid
   // complicated inheritance structures.
   std::unique_ptr<WidgetBase> widget_base_;
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
index 88cacb46..ec409c8 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -3491,16 +3491,18 @@
 }
 
 void WebViewImpl::SendUpdatedTargetURLToBrowser(const KURL& target_url) {
+  // Note: WTF::Unretained() usage below is safe, since `this` owns both
+  // `mojo::Remote` objects.
   if (GetPage()->MainFrame()->IsLocalFrame()) {
     DCHECK(local_main_frame_host_remote_);
     local_main_frame_host_remote_->UpdateTargetURL(
         target_url, WTF::Bind(&WebViewImpl::TargetURLUpdatedInBrowser,
-                              weak_ptr_factory_.GetWeakPtr()));
+                              WTF::Unretained(this)));
   } else {
     DCHECK(remote_main_frame_host_remote_);
     remote_main_frame_host_remote_->UpdateTargetURL(
         target_url, WTF::Bind(&WebViewImpl::TargetURLUpdatedInBrowser,
-                              weak_ptr_factory_.GetWeakPtr()));
+                              WTF::Unretained(this)));
   }
 }
 
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc
index 9d2afe74..2d1ca3a 100644
--- a/third_party/blink/renderer/core/exported/web_view_test.cc
+++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -282,6 +282,32 @@
     return detector;
   }
 
+  // Helper function that creates a widget for a main frame.
+  // Copy the steps done from WebViewHelper::InitializeWithOpener() to set up
+  // the appropriate pointers!
+  WebFrameWidget* CreateWidgetForMainFrame(WebWidgetClient* client,
+                                           WebLocalFrame* frame) {
+    mojo::AssociatedRemote<mojom::blink::FrameWidget> frame_widget;
+    mojo::PendingAssociatedReceiver<mojom::blink::FrameWidget>
+        frame_widget_receiver =
+            frame_widget.BindNewEndpointAndPassDedicatedReceiver();
+
+    mojo::AssociatedRemote<mojom::blink::FrameWidgetHost> frame_widget_host;
+    ignore_result(frame_widget_host.BindNewEndpointAndPassDedicatedReceiver());
+
+    mojo::AssociatedRemote<mojom::blink::Widget> widget_remote;
+    mojo::PendingAssociatedReceiver<mojom::blink::Widget> widget_receiver =
+        widget_remote.BindNewEndpointAndPassDedicatedReceiver();
+
+    mojo::AssociatedRemote<mojom::blink::WidgetHost> widget_host_remote;
+    ignore_result(widget_host_remote.BindNewEndpointAndPassDedicatedReceiver());
+
+    return blink::WebFrameWidget::CreateForMainFrame(
+        client, frame, frame_widget_host.Unbind(),
+        std::move(frame_widget_receiver), widget_host_remote.Unbind(),
+        std::move(widget_receiver));
+  }
+
   std::string base_url_;
   frame_test_helpers::WebViewHelper web_view_helper_;
   scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_;
@@ -496,12 +522,8 @@
   {
     // Copy the steps done from WebViewHelper::InitializeWithOpener() to set up
     // the appropriate pointers!
-    WebFrameWidget* widget = blink::WebFrameWidget::CreateForMainFrame(
-        &web_widget_client, frame,
-        CrossVariantMojoAssociatedRemote<mojom::FrameWidgetHostInterfaceBase>(),
-        CrossVariantMojoAssociatedReceiver<mojom::FrameWidgetInterfaceBase>(),
-        CrossVariantMojoAssociatedRemote<mojom::WidgetHostInterfaceBase>(),
-        CrossVariantMojoAssociatedReceiver<mojom::WidgetInterfaceBase>());
+    WebFrameWidget* widget =
+        CreateWidgetForMainFrame(&web_widget_client, frame);
     cc::LayerTreeSettings layer_tree_settings =
         frame_test_helpers::GetSynchronousSingleThreadLayerTreeSettings();
     web_widget_client.set_layer_tree_host(widget->InitializeCompositing(
@@ -2722,12 +2744,7 @@
       WebLocalFrame::CreateMainFrame(web_view, &web_frame_client, nullptr,
                                      base::UnguessableToken::Create(), nullptr);
   web_frame_client.Bind(local_frame);
-  blink::WebFrameWidget::CreateForMainFrame(
-      &web_widget_client, local_frame,
-      CrossVariantMojoAssociatedRemote<mojom::FrameWidgetHostInterfaceBase>(),
-      CrossVariantMojoAssociatedReceiver<mojom::FrameWidgetInterfaceBase>(),
-      CrossVariantMojoAssociatedRemote<mojom::WidgetHostInterfaceBase>(),
-      CrossVariantMojoAssociatedReceiver<mojom::WidgetInterfaceBase>());
+  CreateWidgetForMainFrame(&web_widget_client, local_frame);
 
   WebGestureEvent event(WebInputEvent::Type::kGestureTap,
                         WebInputEvent::kNoModifiers,
@@ -4186,13 +4203,24 @@
       frame_widget_host.BindNewFrameWidgetInterfaces();
 
   {
+    mojo::AssociatedRemote<mojom::blink::FrameWidget> frame_widget;
+    mojo::PendingAssociatedReceiver<mojom::blink::FrameWidget>
+        frame_widget_receiver =
+            frame_widget.BindNewEndpointAndPassDedicatedReceiver();
+
+    mojo::AssociatedRemote<mojom::blink::Widget> widget_remote;
+    mojo::PendingAssociatedReceiver<mojom::blink::Widget> widget_receiver =
+        widget_remote.BindNewEndpointAndPassDedicatedReceiver();
+
+    mojo::AssociatedRemote<mojom::blink::WidgetHost> widget_host_remote;
+    ignore_result(widget_host_remote.BindNewEndpointAndPassDedicatedReceiver());
+
     // Copy the steps done from WebViewHelper::InitializeWithOpener() to set up
     // the appropriate pointers!
     WebFrameWidget* widget = blink::WebFrameWidget::CreateForMainFrame(
         &web_widget_client, frame, std::move(blink_frame_widget_host),
-        CrossVariantMojoAssociatedReceiver<mojom::FrameWidgetInterfaceBase>(),
-        CrossVariantMojoAssociatedRemote<mojom::WidgetHostInterfaceBase>(),
-        CrossVariantMojoAssociatedReceiver<mojom::WidgetInterfaceBase>());
+        std::move(frame_widget_receiver), widget_host_remote.Unbind(),
+        std::move(widget_receiver));
     cc::LayerTreeSettings layer_tree_settings =
         frame_test_helpers::GetSynchronousSingleThreadLayerTreeSettings();
     web_widget_client.set_layer_tree_host(widget->InitializeCompositing(
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
index bfc940d..2e8c3d4 100644
--- a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
+++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
@@ -413,12 +413,13 @@
   }
 }
 
-void ContentSecurityPolicy::ReportAccumulatedHeaders(LocalFrame* frame) const {
+void ContentSecurityPolicy::ReportAccumulatedHeaders() const {
   WTF::Vector<network::mojom::blink::ContentSecurityPolicyPtr> policies;
   for (const auto& policy : policies_)
     policies.push_back(policy->ExposeForNavigationalChecks());
-  frame->GetLocalFrameHostRemote().DidAddContentSecurityPolicies(
-      std::move(policies));
+
+  DCHECK(delegate_);
+  delegate_->DidAddContentSecurityPolicies(std::move(policies));
 }
 
 void ContentSecurityPolicy::AddAndReportPolicyFromHeaderValue(
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.h b/third_party/blink/renderer/core/frame/csp/content_security_policy.h
index 86a296c2..fa1c31d 100644
--- a/third_party/blink/renderer/core/frame/csp/content_security_policy.h
+++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.h
@@ -231,7 +231,7 @@
   void AddPolicyFromHeaderValue(const String&,
                                 network::mojom::ContentSecurityPolicyType,
                                 network::mojom::ContentSecurityPolicySource);
-  void ReportAccumulatedHeaders(LocalFrame*) const;
+  void ReportAccumulatedHeaders() const;
 
   Vector<CSPHeaderAndType> Headers() const;
 
diff --git a/third_party/blink/renderer/core/html/canvas/image_element_base.cc b/third_party/blink/renderer/core/html/canvas/image_element_base.cc
index 33a77ea..a17230f 100644
--- a/third_party/blink/renderer/core/html/canvas/image_element_base.cc
+++ b/third_party/blink/renderer/core/html/canvas/image_element_base.cc
@@ -170,9 +170,4 @@
   return decoding_mode_;
 }
 
-RespectImageOrientationEnum ImageElementBase::RespectImageOrientation() const {
-  return LayoutObject::ShouldRespectImageOrientation(
-      GetElement().GetLayoutObject());
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/canvas/image_element_base.h b/third_party/blink/renderer/core/html/canvas/image_element_base.h
index 88f23ca..b88e837d 100644
--- a/third_party/blink/renderer/core/html/canvas/image_element_base.h
+++ b/third_party/blink/renderer/core/html/canvas/image_element_base.h
@@ -60,11 +60,6 @@
   // Used with HTMLImageElement and SVGImageElement types.
   Image::ImageDecodingMode GetDecodingModeForPainting(PaintImage::Id);
 
-  // Return the image orientation setting from the layout object, if available.
-  // In the absence of a layout object, kRespectImageOrientation will be
-  // returned.
-  RespectImageOrientationEnum RespectImageOrientation() const;
-
  protected:
   Image::ImageDecodingMode decoding_mode_ =
       Image::ImageDecodingMode::kUnspecifiedDecode;
diff --git a/third_party/blink/renderer/core/html/forms/form_controller.cc b/third_party/blink/renderer/core/html/forms/form_controller.cc
index bdec179..8ad94f8e 100644
--- a/third_party/blink/renderer/core/html/forms/form_controller.cc
+++ b/third_party/blink/renderer/core/html/forms/form_controller.cc
@@ -629,7 +629,7 @@
 }
 
 void FormController::RestoreAllControlsInDocumentOrder() {
-  if (!document_->IsActive())
+  if (!document_->IsActive() || did_restore_all_)
     return;
   HeapHashSet<Member<HTMLFormElement>> finished_forms;
   EventQueueScope scope;
diff --git a/third_party/blink/renderer/core/html/forms/image_input_type.cc b/third_party/blink/renderer/core/html/forms/image_input_type.cc
index 152d42f..b3806a2 100644
--- a/third_party/blink/renderer/core/html/forms/image_input_type.cc
+++ b/third_party/blink/renderer/core/html/forms/image_input_type.cc
@@ -188,7 +188,7 @@
     HTMLImageLoader* image_loader = GetElement().ImageLoader();
     if (image_loader && image_loader->GetContent()) {
       return image_loader->GetContent()
-          ->IntrinsicSize(LayoutObject::ShouldRespectImageOrientation(nullptr))
+          ->IntrinsicSize(kRespectImageOrientation)
           .Height();
     }
   }
@@ -214,7 +214,7 @@
     HTMLImageLoader* image_loader = GetElement().ImageLoader();
     if (image_loader && image_loader->GetContent()) {
       return image_loader->GetContent()
-          ->IntrinsicSize(LayoutObject::ShouldRespectImageOrientation(nullptr))
+          ->IntrinsicSize(kRespectImageOrientation)
           .Width();
     }
   }
diff --git a/third_party/blink/renderer/core/html/html_image_element.cc b/third_party/blink/renderer/core/html/html_image_element.cc
index 87b52ac..9003050 100644
--- a/third_party/blink/renderer/core/html/html_image_element.cc
+++ b/third_party/blink/renderer/core/html/html_image_element.cc
@@ -487,9 +487,7 @@
 
     // if the image is available, use its width
     if (ImageResourceContent* image_content = GetImageLoader().GetContent()) {
-      return image_content
-          ->IntrinsicSize(LayoutObject::ShouldRespectImageOrientation(nullptr))
-          .Width();
+      return image_content->IntrinsicSize(kRespectImageOrientation).Width();
     }
   }
 
@@ -511,9 +509,7 @@
 
     // if the image is available, use its height
     if (ImageResourceContent* image_content = GetImageLoader().GetContent()) {
-      return image_content
-          ->IntrinsicSize(LayoutObject::ShouldRespectImageOrientation(nullptr))
-          .Height();
+      return image_content->IntrinsicSize(kRespectImageOrientation).Height();
     }
   }
 
diff --git a/third_party/blink/renderer/core/html/resources/controls_refresh.css b/third_party/blink/renderer/core/html/resources/controls_refresh.css
index 9582988a..4f2dc364 100644
--- a/third_party/blink/renderer/core/html/resources/controls_refresh.css
+++ b/third_party/blink/renderer/core/html/resources/controls_refresh.css
@@ -125,7 +125,7 @@
   grid-row-start: line1;
   grid-row-end: line2;
   border-style: solid;
-  border-color: rgba(118, 118, 118, 0.3);
+  border-color: -internal-light-dark(rgba(118, 118, 118, 0.3), #858585);
   border-radius: 20px;
   box-sizing: border-box;
   overflow: hidden;
@@ -220,7 +220,7 @@
   /* TODO(crbug.com/1129658): The dark mode color here should be handled
      within LayoutTheme::ActiveListBoxSelectionBackgroundColor(). */
   background-color: -internal-light-dark(-internal-active-list-box-selection, #99C8FF) !important;
-  color: -internal-light-dark(-internal-active-list-box-selection-text, #FFFFFF) !important;
+  color: -internal-light-dark(-internal-active-list-box-selection-text, #3B3B3B) !important;
 }
 
 select:-internal-list-box:focus option:checked:disabled {
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc
index 4507939..f31c1ff 100644
--- a/third_party/blink/renderer/core/layout/layout_text.cc
+++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -1851,10 +1851,11 @@
     FloatRect glyph_bounds;
     float text_width =
         style_to_use->GetFont().Width(text_run, nullptr, &glyph_bounds);
-    // If the text is not wrapping we don't care if it fits or not in the
-    // container as it's not going to be split in multiple lines.
-    if (!style_to_use->AutoWrap() ||
-        (text_width <= ContainingBlock()->ContentLogicalWidth())) {
+    // TODO(rego): Ideally we could avoid measuring text width in some specific
+    // situations (e.g. if "white-space" property is "pre" and "overflow-wrap"
+    // is "normal"). However we tried that on the past and it caused a
+    // regression (crbug.com/985723).
+    if (text_width <= ContainingBlock()->ContentLogicalWidth()) {
       FirstTextBox()->ManuallySetStartLenAndLogicalWidth(
           offset, text->length(), LayoutUnit(text_width));
       SetFirstTextBoxLogicalLeft(text_width);
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
index 10fa50d..fe51053 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
@@ -521,7 +521,7 @@
     const NGInlineItem& item = items[item_index_];
     if (item.Type() == NGInlineItem::kText) {
       if (item.Length())
-        HandleText(item, line_info);
+        HandleText(item, *item.TextShapeResult(), line_info);
       else
         HandleEmptyText(item, line_info);
 #if DCHECK_IS_ON()
@@ -633,11 +633,12 @@
   DCHECK(item.Type() == NGInlineItem::kText ||
          (item.Type() == NGInlineItem::kControl &&
           Text()[item.StartOffset()] == kTabulationCharacter));
+  DCHECK(&shape_result);
   DCHECK_EQ(auto_wrap_, item.Style()->AutoWrap());
 
   // If we're trailing, only trailing spaces can be included in this line.
   if (UNLIKELY(state_ == LineBreakState::kTrailing)) {
-    HandleTrailingSpaces(item, shape_result, line_info);
+    HandleTrailingSpaces(item, &shape_result, line_info);
     return;
   }
 
@@ -669,7 +670,7 @@
     // rewind, but in most cases it will rewind.
     const String& text = Text();
     if (auto_wrap_ && IsBreakableSpace(text[offset_])) {
-      HandleTrailingSpaces(item, shape_result, line_info);
+      HandleTrailingSpaces(item, &shape_result, line_info);
       if (state_ != LineBreakState::kDone) {
         state_ = LineBreakState::kContinue;
         return;
@@ -717,7 +718,7 @@
       // items follow, only trailable spaces if any. This is very common that
       // shortcut to handling trailing spaces.
       if (item_result->EndOffset() < item.EndOffset())
-        return HandleTrailingSpaces(item, shape_result, line_info);
+        return HandleTrailingSpaces(item, &shape_result, line_info);
 
       // The break point found at the end of this text item. Continue looking
       // next items, because the next item maybe trailable, or can prohibit
@@ -1154,29 +1155,26 @@
   item_result->inline_size = item_result->shape_result->SnappedWidth();
 }
 
-void NGLineBreaker::HandleTrailingSpacesIfNeeded(NGLineInfo* line_info) {
+void NGLineBreaker::HandleTrailingSpaces(NGLineInfo* line_info) {
   const Vector<NGInlineItem>& items = Items();
-  if (item_index_ >= items.size())
-    return;
-  const NGInlineItem& item = items[item_index_];
-  if (const ShapeResult* shape_result = item.TextShapeResult())
-    HandleTrailingSpaces(item, *shape_result, line_info);
+  if (item_index_ < items.size())
+    HandleTrailingSpaces(items[item_index_], line_info);
 }
 
 inline void NGLineBreaker::HandleTrailingSpaces(const NGInlineItem& item,
                                                 NGLineInfo* line_info) {
   const ShapeResult* shape_result = item.TextShapeResult();
-  DCHECK(shape_result);
-  HandleTrailingSpaces(item, *shape_result, line_info);
+  // Call |HandleTrailingSpaces| even if |item| does not have |ShapeResult|, so
+  // that we skip spaces.
+  HandleTrailingSpaces(item, shape_result, line_info);
 }
 
 void NGLineBreaker::HandleTrailingSpaces(const NGInlineItem& item,
-                                         const ShapeResult& shape_result,
+                                         const ShapeResult* shape_result,
                                          NGLineInfo* line_info) {
   DCHECK(item.Type() == NGInlineItem::kText ||
          (item.Type() == NGInlineItem::kControl &&
           Text()[item.StartOffset()] == kTabulationCharacter));
-  DCHECK(&shape_result);
   bool is_control_tab = item.Type() == NGInlineItem::kControl &&
                         Text()[item.StartOffset()] == kTabulationCharacter;
   DCHECK(item.Type() == NGInlineItem::kText || is_control_tab);
@@ -1227,10 +1225,11 @@
     // Probably we can (koji). We would need to review usage of these
     // item results, and change them to use "non_hangable_run_end"
     // instead.
+    DCHECK(shape_result);
     NGInlineItemResult* item_result = AddItem(item, end, line_info);
     item_result->non_hangable_run_end = offset_;
     item_result->has_only_trailing_spaces = true;
-    item_result->shape_result = ShapeResultView::Create(&shape_result);
+    item_result->shape_result = ShapeResultView::Create(shape_result);
     if (item_result->StartOffset() == item.StartOffset() &&
         item_result->EndOffset() == item.EndOffset()) {
       item_result->inline_size = item_result->shape_result
@@ -2088,7 +2087,7 @@
           // and break there.
           // TODO: optimize more?
           Rewind(index, line_info);
-          HandleTrailingSpacesIfNeeded(line_info);
+          HandleTrailingSpaces(line_info);
 #if DCHECK_IS_ON()
           item_results.back().CheckConsistency(false);
 #endif
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h
index 89f3a162..dde29be9 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h
@@ -133,10 +133,6 @@
     kContinue,
   };
 
-  inline void HandleText(const NGInlineItem& item, NGLineInfo* line_info) {
-    DCHECK(item.TextShapeResult());
-    HandleText(item, *item.TextShapeResult(), line_info);
-  }
   void HandleText(const NGInlineItem& item, const ShapeResult&, NGLineInfo*);
   enum BreakResult { kSuccess, kOverflow };
   BreakResult BreakText(NGInlineItemResult*,
@@ -161,10 +157,10 @@
                                        unsigned start,
                                        unsigned end);
 
-  void HandleTrailingSpacesIfNeeded(NGLineInfo*);
+  void HandleTrailingSpaces(NGLineInfo*);
   void HandleTrailingSpaces(const NGInlineItem&, NGLineInfo*);
   void HandleTrailingSpaces(const NGInlineItem&,
-                            const ShapeResult&,
+                            const ShapeResult*,
                             NGLineInfo*);
   void RemoveTrailingCollapsibleSpace(NGLineInfo*);
   LayoutUnit TrailingCollapsibleSpaceWidth(NGLineInfo*);
diff --git a/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc b/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc
index d6b2f06d..457ad1f 100644
--- a/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc
+++ b/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc
@@ -190,10 +190,14 @@
     WritingMode writing_mode,
     float margin) const {
   DCHECK(!style_image->IsPendingImage());
+
+  RespectImageOrientationEnum respect_orientation =
+      style_image->ForceOrientationIfNecessary(
+          LayoutObject::ShouldRespectImageOrientation(layout_box_));
+
   const LayoutSize& image_size = RoundedLayoutSize(style_image->ImageSize(
       layout_box_->GetDocument(), layout_box_->StyleRef().EffectiveZoom(),
-      FloatSize(reference_box_logical_size_),
-      LayoutObject::ShouldRespectImageOrientation(layout_box_)));
+      FloatSize(reference_box_logical_size_), respect_orientation));
 
   const LayoutRect& margin_rect =
       GetShapeImageMarginRect(*layout_box_, reference_box_logical_size_);
@@ -206,9 +210,9 @@
       style_image->GetImage(*layout_box_, layout_box_->GetDocument(),
                             layout_box_->StyleRef(), FloatSize(image_size));
 
-  return Shape::CreateRasterShape(
-      image.get(), shape_image_threshold, image_rect, margin_rect, writing_mode,
-      margin, LayoutObject::ShouldRespectImageOrientation(layout_box_));
+  return Shape::CreateRasterShape(image.get(), shape_image_threshold,
+                                  image_rect, margin_rect, writing_mode, margin,
+                                  respect_orientation);
 }
 
 const Shape& ShapeOutsideInfo::ComputedShape() const {
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc
index 00e3be6..e0aea5e 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc
@@ -160,8 +160,7 @@
   viewport_size_ = FloatSize(width, height);
 
   SVGTransformChangeDetector change_detector(local_to_parent_transform_);
-  local_to_parent_transform_ = marker->ViewBoxToViewTransform(
-      viewport_size_.Width(), viewport_size_.Height());
+  local_to_parent_transform_ = marker->ViewBoxToViewTransform(viewport_size_);
 
   needs_transform_update_ = false;
   return change_detector.ComputeChange(local_to_parent_transform_);
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc
index 13bf83a..9b08665e 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc
@@ -115,7 +115,7 @@
       return pattern_data;
     tile_transform = SVGFitToViewBox::ViewBoxToViewTransform(
         attributes.ViewBox(), attributes.PreserveAspectRatio(),
-        tile_bounds.Width(), tile_bounds.Height());
+        tile_bounds.Size());
   } else {
     // A viewBox overrides patternContentUnits, per spec.
     if (attributes.PatternContentUnits() ==
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
index f08d9e5..5702776a 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
@@ -481,8 +481,8 @@
   auto* svg = To<SVGSVGElement>(GetNode());
   DCHECK(svg);
   float scale = StyleRef().EffectiveZoom();
-  local_to_border_box_transform_ = svg->ViewBoxToViewTransform(
-      ContentWidth() / scale, ContentHeight() / scale);
+  FloatSize content_size(ContentWidth() / scale, ContentHeight() / scale);
+  local_to_border_box_transform_ = svg->ViewBoxToViewTransform(content_size);
 
   FloatPoint translate = svg->CurrentTranslate();
   LayoutSize border_and_padding(BorderLeft() + PaddingLeft(),
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc
index 7ebed3c..e0185c1 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc
@@ -77,7 +77,7 @@
   SVGTransformChangeDetector change_detector(local_to_parent_transform_);
   local_to_parent_transform_ =
       AffineTransform::Translation(viewport_.X(), viewport_.Y()) *
-      svg->ViewBoxToViewTransform(viewport_.Width(), viewport_.Height());
+      svg->ViewBoxToViewTransform(viewport_.Size());
   needs_transform_update_ = false;
   return change_detector.ComputeChange(local_to_parent_transform_);
 }
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index 6f77a88..72fffa3 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -1320,8 +1320,7 @@
   //
   // It is important to forward all the CSP data before loading the response
   // body, otherwise some loaded content might not be blocked.
-  frame_->DomWindow()->GetContentSecurityPolicy()->ReportAccumulatedHeaders(
-      frame_);
+  frame_->DomWindow()->GetContentSecurityPolicy()->ReportAccumulatedHeaders();
 
   CreateParserPostCommit();
 
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
index 9f6432a..4b0f9af 100644
--- a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
+++ b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
@@ -226,7 +226,16 @@
     RespectImageOrientationEnum should_respect_image_orientation) const {
   if (!image_)
     return IntSize();
-  return image_->Size(should_respect_image_orientation);
+  RespectImageOrientationEnum respect_orientation =
+      ForceOrientationIfNecessary(should_respect_image_orientation);
+  return image_->Size(respect_orientation);
+}
+
+RespectImageOrientationEnum ImageResourceContent::ForceOrientationIfNecessary(
+    RespectImageOrientationEnum default_orientation) const {
+  if (image_ && image_->IsBitmapImage() && !IsAccessAllowed())
+    return kRespectImageOrientation;
+  return default_orientation;
 }
 
 void ImageResourceContent::NotifyObservers(
@@ -566,7 +575,7 @@
   NotifyObservers(kDoNotNotifyFinish, CanDeferInvalidation::kYes);
 }
 
-bool ImageResourceContent::IsAccessAllowed() {
+bool ImageResourceContent::IsAccessAllowed() const {
   return info_->IsAccessAllowed(
       GetImage()->CurrentFrameHasSingleSecurityOrigin()
           ? ImageResourceInfo::kHasSingleSecurityOrigin
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_content.h b/third_party/blink/renderer/core/loader/resource/image_resource_content.h
index dd9df748..51b6869 100644
--- a/third_party/blink/renderer/core/loader/resource/image_resource_content.h
+++ b/third_party/blink/renderer/core/loader/resource/image_resource_content.h
@@ -80,6 +80,11 @@
     return size_available_ != Image::kSizeUnavailable;
   }
 
+  // Correct the image orientation preference for potentially cross-origin
+  // content.
+  RespectImageOrientationEnum ForceOrientationIfNecessary(
+      RespectImageOrientationEnum default_orientation) const;
+
   void Trace(Visitor*) const override;
 
   // Content status and deriving predicates.
@@ -104,7 +109,7 @@
   // Redirecting methods to Resource.
   const KURL& Url() const;
   base::TimeTicks LoadResponseEnd() const;
-  bool IsAccessAllowed();
+  bool IsAccessAllowed() const;
   const ResourceResponse& GetResponse() const;
   base::Optional<ResourceError> GetResourceError() const;
   // DEPRECATED: ImageResourceContents consumers shouldn't need to worry about
diff --git a/third_party/blink/renderer/core/page/drag_controller.cc b/third_party/blink/renderer/core/page/drag_controller.cc
index 256eeeb..9d8c730 100644
--- a/third_party/blink/renderer/core/page/drag_controller.cc
+++ b/third_party/blink/renderer/core/page/drag_controller.cc
@@ -1092,17 +1092,24 @@
       interpolation_quality = kInterpolationNone;
   }
 
-  RespectImageOrientationEnum respect_image_orientation =
+  // Always respect the orientation of opaque origin images to avoid leaking
+  // image data. Otherwise pull orientation from the layout object's style.
+  ImageResourceContent* image_content = GetImageResource(element);
+  RespectImageOrientationEnum respect_orientation =
       LayoutObject::ShouldRespectImageOrientation(element->GetLayoutObject());
+  if (image_content) {
+    respect_orientation =
+        image_content->ForceOrientationIfNecessary(respect_orientation);
+  }
 
-  IntSize image_size = image->Size(respect_image_orientation);
+  IntSize image_size = image->Size(respect_orientation);
   FloatSize image_scale =
       DragImage::ClampedImageScale(image_size, image_element_size_in_pixels,
                                    MaxDragImageSize(device_scale_factor));
 
   if (image_size.Area() <= kMaxOriginalImageArea &&
       (drag_image = DragImage::Create(
-           image, respect_image_orientation, device_scale_factor,
+           image, respect_orientation, device_scale_factor,
            interpolation_quality, kDragImageAlpha, image_scale))) {
     IntSize original_size = image_element_size_in_pixels;
     origin = image_element_location;
@@ -1180,8 +1187,8 @@
                                  .LocalBorderBoxProperties()
                                  .Unalias();
   return DataTransfer::CreateDragImageForFrame(
-      frame, opacity, kRespectImageOrientation, painting_rect.Size(),
-      painting_rect.Location(), builder, property_tree_state);
+      frame, opacity, painting_rect.Size(), painting_rect.Location(), builder,
+      property_tree_state);
 }
 
 bool DragController::StartDrag(LocalFrame* src,
diff --git a/third_party/blink/renderer/core/paint/box_model_object_painter.cc b/third_party/blink/renderer/core/paint/box_model_object_painter.cc
index e6faa86..3d646b36 100644
--- a/third_party/blink/renderer/core/paint/box_model_object_painter.cc
+++ b/third_party/blink/renderer/core/paint/box_model_object_painter.cc
@@ -132,11 +132,16 @@
   PhysicalBoxSides sides_to_include;
   if (flow_box_)
     sides_to_include = flow_box_->SidesToInclude();
+  RespectImageOrientationEnum respect_orientation =
+      LayoutObject::ShouldRespectImageOrientation(&box_model_);
+  if (auto* style_image = bg_layer.GetImage()) {
+    respect_orientation =
+        style_image->ForceOrientationIfNecessary(respect_orientation);
+  }
   return BoxPainterBase::FillLayerInfo(
       box_model_.GetDocument(), box_model_.StyleRef(),
       box_model_.IsScrollContainer(), color, bg_layer, bleed_avoidance,
-      LayoutObject::ShouldRespectImageOrientation(&box_model_),
-      sides_to_include, box_model_.IsLayoutInline(),
+      respect_orientation, sides_to_include, box_model_.IsLayoutInline(),
       is_painting_scrolling_background);
 }
 
diff --git a/third_party/blink/renderer/core/paint/image_painter.cc b/third_party/blink/renderer/core/paint/image_painter.cc
index f2e5450..d972029 100644
--- a/third_party/blink/renderer/core/paint/image_painter.cc
+++ b/third_party/blink/renderer/core/paint/image_painter.cc
@@ -251,13 +251,22 @@
     }
   }
 
-  context.DrawImage(
-      image.get(), decode_mode, FloatRect(pixel_snapped_dest_rect), &src_rect,
-      layout_image_.StyleRef().HasFilterInducingProperty(),
-      SkBlendMode::kSrcOver,
-      LayoutObject::ShouldRespectImageOrientation(&layout_image_));
-
   ImageResourceContent* image_content = image_resource.CachedImage();
+
+  // Always respect the orientation of opaque origin images to avoid leaking
+  // image data. Otherwise pull orientation from the layout object's style.
+  RespectImageOrientationEnum respect_orientation =
+      LayoutObject::ShouldRespectImageOrientation(&layout_image_);
+  if (image_content) {
+    respect_orientation =
+        image_content->ForceOrientationIfNecessary(respect_orientation);
+  }
+
+  context.DrawImage(image.get(), decode_mode,
+                    FloatRect(pixel_snapped_dest_rect), &src_rect,
+                    layout_image_.StyleRef().HasFilterInducingProperty(),
+                    SkBlendMode::kSrcOver, respect_orientation);
+
   if ((IsA<HTMLImageElement>(node) || IsA<HTMLVideoElement>(node)) &&
       image_content && image_content->IsLoaded()) {
     LocalDOMWindow* window = layout_image_.GetDocument().domWindow();
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
index ca98300e..8c3bec8 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -1820,11 +1820,16 @@
     BackgroundBleedAvoidance bleed_avoidance,
     bool is_painting_scrolling_background) const {
   const NGPhysicalBoxFragment& fragment = PhysicalFragment();
+  RespectImageOrientationEnum respect_orientation =
+      LayoutObject::ShouldRespectImageOrientation(fragment.GetLayoutObject());
+  if (auto* style_image = bg_layer.GetImage()) {
+    respect_orientation =
+        style_image->ForceOrientationIfNecessary(respect_orientation);
+  }
   return BoxPainterBase::FillLayerInfo(
       fragment.GetLayoutObject()->GetDocument(), fragment.Style(),
       fragment.IsScrollContainer(), color, bg_layer, bleed_avoidance,
-      LayoutObject::ShouldRespectImageOrientation(fragment.GetLayoutObject()),
-      box_fragment_.SidesToInclude(),
+      respect_orientation, box_fragment_.SidesToInclude(),
       fragment.GetLayoutObject()->IsLayoutInline(),
       is_painting_scrolling_background);
 }
diff --git a/third_party/blink/renderer/core/paint/svg_image_painter.cc b/third_party/blink/renderer/core/paint/svg_image_painter.cc
index 7cb6aa59..6b4370d3 100644
--- a/third_party/blink/renderer/core/paint/svg_image_painter.cc
+++ b/third_party/blink/renderer/core/paint/svg_image_painter.cc
@@ -65,8 +65,15 @@
   FloatRect dest_rect = layout_svg_image_.ObjectBoundingBox();
 
   auto* image_element = To<SVGImageElement>(layout_svg_image_.GetElement());
+
+  ImageResourceContent* image_content = image_resource->CachedImage();
+
+  // Always respect the orientation of opaque origin images to avoid leaking
+  // image data. Otherwise pull orientation from the layout object's style.
   RespectImageOrientationEnum respect_orientation =
-      LayoutObject::ShouldRespectImageOrientation(&layout_svg_image_);
+      image_content->ForceOrientationIfNecessary(
+          LayoutObject::ShouldRespectImageOrientation(&layout_svg_image_));
+
   FloatRect src_rect(FloatPoint(), image->SizeAsFloat(respect_orientation));
   if (respect_orientation && !image->HasDefaultOrientation()) {
     // We need the oriented source rect for adjusting the aspect ratio
@@ -91,19 +98,18 @@
       image.get(), decode_mode, dest_rect, &src_rect,
       layout_svg_image_.StyleRef().HasFilterInducingProperty(),
       SkBlendMode::kSrcOver, respect_orientation);
-  if (image_resource->CachedImage() &&
-      image_resource->CachedImage()->IsLoaded()) {
+  if (image_content && image_content->IsLoaded()) {
     LocalDOMWindow* window = layout_svg_image_.GetDocument().domWindow();
     DCHECK(window);
     DCHECK(paint_info.PaintContainer());
     ImageElementTiming::From(*window).NotifyImagePainted(
-        &layout_svg_image_, image_resource->CachedImage(),
+        &layout_svg_image_, image_content,
         paint_info.context.GetPaintController().CurrentPaintChunkProperties(),
         EnclosingIntRect(dest_rect));
   }
 
   PaintTimingDetector::NotifyImagePaint(
-      layout_svg_image_, image->Size(), image_resource->CachedImage(),
+      layout_svg_image_, image->Size(), image_content,
       paint_info.context.GetPaintController().CurrentPaintChunkProperties(),
       EnclosingIntRect(dest_rect));
   PaintTiming& timing = PaintTiming::From(
diff --git a/third_party/blink/renderer/core/streams/transform_stream.idl b/third_party/blink/renderer/core/streams/transform_stream.idl
index ad26ffa..bb3e386 100644
--- a/third_party/blink/renderer/core/streams/transform_stream.idl
+++ b/third_party/blink/renderer/core/streams/transform_stream.idl
@@ -9,6 +9,6 @@
     [CallWith=ScriptState, RaisesException] constructor(optional any transformer,
                 optional any writableStrategy,
                 optional any readableStrategy);
-    [NotEnumerable] readonly attribute ReadableStream readable;
-    [NotEnumerable] readonly attribute WritableStream writable;
+    readonly attribute ReadableStream readable;
+    readonly attribute WritableStream writable;
 };
diff --git a/third_party/blink/renderer/core/streams/transform_stream_default_controller.idl b/third_party/blink/renderer/core/streams/transform_stream_default_controller.idl
index 02fc1802..68f466af 100644
--- a/third_party/blink/renderer/core/streams/transform_stream_default_controller.idl
+++ b/third_party/blink/renderer/core/streams/transform_stream_default_controller.idl
@@ -6,9 +6,9 @@
 
 // https://streams.spec.whatwg.org/#rs-default-controller-class-definition
 interface TransformStreamDefaultController {
-    [NotEnumerable] readonly attribute double? desiredSize;
-    [CallWith=ScriptState, NotEnumerable, RaisesException] void enqueue(
+    readonly attribute double? desiredSize;
+    [CallWith=ScriptState, RaisesException] void enqueue(
         optional any chunk);
-    [CallWith=ScriptState, NotEnumerable] void error(optional any reason);
-    [CallWith=ScriptState, NotEnumerable] void terminate();
+    [CallWith=ScriptState] void error(optional any reason);
+    [CallWith=ScriptState] void terminate();
 };
diff --git a/third_party/blink/renderer/core/streams/writable_stream.idl b/third_party/blink/renderer/core/streams/writable_stream.idl
index 8cb0ff8..bb61c20 100644
--- a/third_party/blink/renderer/core/streams/writable_stream.idl
+++ b/third_party/blink/renderer/core/streams/writable_stream.idl
@@ -7,9 +7,9 @@
     Exposed=(Window,Worker,Worklet)
 ] interface WritableStream {
     [CallWith=ScriptState, RaisesException, MeasureAs=WritableStreamConstructor] constructor(optional any underlyingSink, optional any strategy);
-    [NotEnumerable] readonly attribute boolean locked;
-    [RaisesException, CallWith=ScriptState, NotEnumerable] Promise<void> abort(
+    readonly attribute boolean locked;
+    [RaisesException, CallWith=ScriptState] Promise<void> abort(
         optional any reason);
-    [RaisesException, CallWith=ScriptState, NotEnumerable] Promise<void> close();
-    [RaisesException, CallWith=ScriptState, NotEnumerable] WritableStreamDefaultWriter getWriter();
+    [RaisesException, CallWith=ScriptState] Promise<void> close();
+    [RaisesException, CallWith=ScriptState] WritableStreamDefaultWriter getWriter();
 };
diff --git a/third_party/blink/renderer/core/streams/writable_stream_default_controller.idl b/third_party/blink/renderer/core/streams/writable_stream_default_controller.idl
index f301939..c7bc87a 100644
--- a/third_party/blink/renderer/core/streams/writable_stream_default_controller.idl
+++ b/third_party/blink/renderer/core/streams/writable_stream_default_controller.idl
@@ -6,5 +6,5 @@
 
 // https://streams.spec.whatwg.org/#ws-default-controller-class-definition
 interface WritableStreamDefaultController {
-    [CallWith=ScriptState, NotEnumerable] void error(optional any e);
+    [CallWith=ScriptState] void error(optional any e);
 };
diff --git a/third_party/blink/renderer/core/streams/writable_stream_default_writer.idl b/third_party/blink/renderer/core/streams/writable_stream_default_writer.idl
index 0b59cdf3..8ebf59da 100644
--- a/third_party/blink/renderer/core/streams/writable_stream_default_writer.idl
+++ b/third_party/blink/renderer/core/streams/writable_stream_default_writer.idl
@@ -9,17 +9,17 @@
     Exposed=(Window,Worker,Worklet)
 ] interface WritableStreamDefaultWriter {
     [CallWith=ScriptState, RaisesException] constructor(WritableStream stream);
-    [CallWith=ScriptState, NotEnumerable] readonly attribute Promise<void>
+    [CallWith=ScriptState] readonly attribute Promise<void>
         closed;
-    [RaisesException, CallWith=ScriptState, NotEnumerable] readonly attribute
+    [RaisesException, CallWith=ScriptState] readonly attribute
         any desiredSize;
-    [CallWith=ScriptState, NotEnumerable] readonly attribute Promise<void>
+    [CallWith=ScriptState] readonly attribute Promise<void>
         ready;
 
-    [CallWith=ScriptState, RaisesException, NotEnumerable] Promise<void> abort(
+    [CallWith=ScriptState, RaisesException] Promise<void> abort(
         optional any reason);
-    [CallWith=ScriptState, RaisesException, NotEnumerable] Promise<void> close();
-    [CallWith=ScriptState, NotEnumerable] void releaseLock();
-    [CallWith=ScriptState, RaisesException, NotEnumerable] Promise<void> write(
+    [CallWith=ScriptState, RaisesException] Promise<void> close();
+    [CallWith=ScriptState] void releaseLock();
+    [CallWith=ScriptState, RaisesException] Promise<void> write(
         optional any chunk);
 };
diff --git a/third_party/blink/renderer/core/style/computed_style_test.cc b/third_party/blink/renderer/core/style/computed_style_test.cc
index 62d3bb47..8df2985 100644
--- a/third_party/blink/renderer/core/style/computed_style_test.cc
+++ b/third_party/blink/renderer/core/style/computed_style_test.cc
@@ -1096,4 +1096,24 @@
   EXPECT_EQ(1u, style->Transitions()->PropertyList().size());
 }
 
+TEST(ComputedStyleTest, ApplyInitialAnimationNameAndTransitionProperty) {
+  std::unique_ptr<DummyPageHolder> dummy_page_holder_ =
+      std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
+
+  const ComputedStyle* initial = &ComputedStyle::InitialStyle();
+  StyleResolverState state(dummy_page_holder_->GetDocument(),
+                           *dummy_page_holder_->GetDocument().documentElement(),
+                           initial, initial);
+
+  scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
+  state.SetStyle(style);
+  EXPECT_FALSE(style->Animations());
+  EXPECT_FALSE(style->Transitions());
+
+  To<Longhand>(GetCSSPropertyAnimationName()).ApplyInitial(state);
+  To<Longhand>(GetCSSPropertyTransitionProperty()).ApplyInitial(state);
+  EXPECT_FALSE(style->Animations());
+  EXPECT_FALSE(style->Transitions());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/style/style_fetched_image.cc b/third_party/blink/renderer/core/style/style_fetched_image.cc
index 90f227b..e56d9df 100644
--- a/third_party/blink/renderer/core/style/style_fetched_image.cc
+++ b/third_party/blink/renderer/core/style/style_fetched_image.cc
@@ -118,7 +118,7 @@
   if (auto* svg_image = DynamicTo<SVGImage>(image)) {
     return ImageSizeForSVGImage(svg_image, multiplier, default_object_size);
   }
-
+  respect_orientation = ForceOrientationIfNecessary(respect_orientation);
   FloatSize size(image->Size(respect_orientation));
   return ApplyZoom(size, multiplier);
 }
@@ -187,6 +187,19 @@
   image_->LoadDeferredImage(document_->Fetcher());
 }
 
+RespectImageOrientationEnum StyleFetchedImage::ForceOrientationIfNecessary(
+    RespectImageOrientationEnum default_orientation) const {
+  // SVG Images don't have orientation and assert on loading when
+  // IsAccessAllowed is called.
+  if (image_->GetImage()->IsSVGImage())
+    return default_orientation;
+  // Cross-origin images must always respect orientation to prevent
+  // potentially private data leakage.
+  if (!image_->IsAccessAllowed())
+    return kRespectImageOrientation;
+  return default_orientation;
+}
+
 bool StyleFetchedImage::GetImageAnimationPolicy(
     mojom::blink::ImageAnimationPolicy& policy) {
   if (!document_ || !document_->GetSettings()) {
diff --git a/third_party/blink/renderer/core/style/style_fetched_image.h b/third_party/blink/renderer/core/style/style_fetched_image.h
index 6559658..97548e66 100644
--- a/third_party/blink/renderer/core/style/style_fetched_image.h
+++ b/third_party/blink/renderer/core/style/style_fetched_image.h
@@ -74,6 +74,9 @@
 
   void LoadDeferredImage(const Document& document);
 
+  RespectImageOrientationEnum ForceOrientationIfNecessary(
+      RespectImageOrientationEnum default_orientation) const override;
+
   void Trace(Visitor*) const override;
 
  private:
diff --git a/third_party/blink/renderer/core/style/style_fetched_image_set.cc b/third_party/blink/renderer/core/style/style_fetched_image_set.cc
index 288d471..0fe22a0 100644
--- a/third_party/blink/renderer/core/style/style_fetched_image_set.cc
+++ b/third_party/blink/renderer/core/style/style_fetched_image_set.cc
@@ -102,6 +102,7 @@
   if (auto* svg_image = DynamicTo<SVGImage>(image)) {
     return ImageSizeForSVGImage(svg_image, multiplier, default_object_size);
   }
+  respect_orientation = ForceOrientationIfNecessary(respect_orientation);
   FloatSize natural_size(image->Size(respect_orientation));
   FloatSize scaled_image_size(ApplyZoom(natural_size, multiplier));
   scaled_image_size.Scale(1 / image_scale_factor_);
@@ -143,6 +144,19 @@
   return best_fit_image_->GetImage()->CurrentFrameKnownToBeOpaque();
 }
 
+RespectImageOrientationEnum StyleFetchedImageSet::ForceOrientationIfNecessary(
+    RespectImageOrientationEnum default_orientation) const {
+  // SVG Images don't have orientation and assert on loading when
+  // IsAccessAllowed is called.
+  if (best_fit_image_->GetImage()->IsSVGImage())
+    return default_orientation;
+  // Cross-origin images must always respect orientation to prevent
+  // potentially private data leakage.
+  if (!best_fit_image_->IsAccessAllowed())
+    return kRespectImageOrientation;
+  return default_orientation;
+}
+
 void StyleFetchedImageSet::Trace(Visitor* visitor) const {
   visitor->Trace(best_fit_image_);
   visitor->Trace(image_set_value_);
diff --git a/third_party/blink/renderer/core/style/style_fetched_image_set.h b/third_party/blink/renderer/core/style/style_fetched_image_set.h
index 24ed414..5eb6f5f 100644
--- a/third_party/blink/renderer/core/style/style_fetched_image_set.h
+++ b/third_party/blink/renderer/core/style/style_fetched_image_set.h
@@ -80,6 +80,9 @@
   bool KnownToBeOpaque(const Document&, const ComputedStyle&) const override;
   ImageResourceContent* CachedImage() const override;
 
+  RespectImageOrientationEnum ForceOrientationIfNecessary(
+      RespectImageOrientationEnum default_orientation) const override;
+
   void Trace(Visitor*) const override;
 
  private:
diff --git a/third_party/blink/renderer/core/style/style_image.h b/third_party/blink/renderer/core/style/style_image.h
index a6eedc7..2ca275b5 100644
--- a/third_party/blink/renderer/core/style/style_image.h
+++ b/third_party/blink/renderer/core/style/style_image.h
@@ -133,6 +133,13 @@
   // underlying ImageResourceContent, or otherwise nullptr.
   virtual ImageResourceContent* CachedImage() const { return nullptr; }
 
+  // Correct the image orientation preference for potentially cross-origin
+  // content.
+  virtual RespectImageOrientationEnum ForceOrientationIfNecessary(
+      RespectImageOrientationEnum default_orientation) const {
+    return default_orientation;
+  }
+
   ALWAYS_INLINE bool IsImageResource() const { return is_image_resource_; }
   ALWAYS_INLINE bool IsPendingImage() const { return is_pending_image_; }
   ALWAYS_INLINE bool IsGeneratedImage() const { return is_generated_image_; }
diff --git a/third_party/blink/renderer/core/svg/svg_fit_to_view_box.cc b/third_party/blink/renderer/core/svg/svg_fit_to_view_box.cc
index abe6276..2ddd2c9 100644
--- a/third_party/blink/renderer/core/svg/svg_fit_to_view_box.cc
+++ b/third_party/blink/renderer/core/svg/svg_fit_to_view_box.cc
@@ -81,15 +81,10 @@
 AffineTransform SVGFitToViewBox::ViewBoxToViewTransform(
     const FloatRect& view_box_rect,
     const SVGPreserveAspectRatio* preserve_aspect_ratio,
-    float view_width,
-    float view_height) {
-  if (!view_box_rect.Width() || !view_box_rect.Height() || !view_width ||
-      !view_height)
+    const FloatSize& viewport_size) {
+  if (view_box_rect.IsEmpty() || viewport_size.IsEmpty())
     return AffineTransform();
-
-  return preserve_aspect_ratio->ComputeTransform(
-      view_box_rect.X(), view_box_rect.Y(), view_box_rect.Width(),
-      view_box_rect.Height(), view_width, view_height);
+  return preserve_aspect_ratio->ComputeTransform(view_box_rect, viewport_size);
 }
 
 bool SVGFitToViewBox::IsKnownAttribute(const QualifiedName& attr_name) {
diff --git a/third_party/blink/renderer/core/svg/svg_fit_to_view_box.h b/third_party/blink/renderer/core/svg/svg_fit_to_view_box.h
index e49701e..0eec0809 100644
--- a/third_party/blink/renderer/core/svg/svg_fit_to_view_box.h
+++ b/third_party/blink/renderer/core/svg/svg_fit_to_view_box.h
@@ -28,6 +28,7 @@
 
 class AffineTransform;
 class FloatRect;
+class FloatSize;
 class QualifiedName;
 class SVGAnimatedPreserveAspectRatio;
 class SVGAnimatedRect;
@@ -38,8 +39,7 @@
  public:
   static AffineTransform ViewBoxToViewTransform(const FloatRect& view_box_rect,
                                                 const SVGPreserveAspectRatio*,
-                                                float view_width,
-                                                float view_height);
+                                                const FloatSize& viewport_size);
 
   static bool IsKnownAttribute(const QualifiedName&);
 
diff --git a/third_party/blink/renderer/core/svg/svg_marker_element.cc b/third_party/blink/renderer/core/svg/svg_marker_element.cc
index 41d62a2..8c7ea5e9 100644
--- a/third_party/blink/renderer/core/svg/svg_marker_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_marker_element.cc
@@ -99,11 +99,10 @@
 }
 
 AffineTransform SVGMarkerElement::ViewBoxToViewTransform(
-    float view_width,
-    float view_height) const {
+    const FloatSize& viewport_size) const {
   return SVGFitToViewBox::ViewBoxToViewTransform(
       viewBox()->CurrentValue()->Value(), preserveAspectRatio()->CurrentValue(),
-      view_width, view_height);
+      viewport_size);
 }
 
 void SVGMarkerElement::SvgAttributeChanged(const QualifiedName& attr_name) {
diff --git a/third_party/blink/renderer/core/svg/svg_marker_element.h b/third_party/blink/renderer/core/svg/svg_marker_element.h
index b3a3f1f..69c3a29c 100644
--- a/third_party/blink/renderer/core/svg/svg_marker_element.h
+++ b/third_party/blink/renderer/core/svg/svg_marker_element.h
@@ -59,8 +59,7 @@
 
   explicit SVGMarkerElement(Document&);
 
-  AffineTransform ViewBoxToViewTransform(float view_width,
-                                         float view_height) const;
+  AffineTransform ViewBoxToViewTransform(const FloatSize& viewport_size) const;
 
   void setOrientToAuto();
   void setOrientToAngle(SVGAngleTearOff*);
diff --git a/third_party/blink/renderer/core/svg/svg_preserve_aspect_ratio.cc b/third_party/blink/renderer/core/svg/svg_preserve_aspect_ratio.cc
index aecb15d..6facb8bc 100644
--- a/third_party/blink/renderer/core/svg/svg_preserve_aspect_ratio.cc
+++ b/third_party/blink/renderer/core/svg/svg_preserve_aspect_ratio.cc
@@ -284,30 +284,20 @@
 }
 
 AffineTransform SVGPreserveAspectRatio::ComputeTransform(
-    float logical_x,
-    float logical_y,
-    float logical_width,
-    float logical_height,
-    float physical_width,
-    float physical_height) const {
-  DCHECK(logical_width);
-  DCHECK(logical_height);
-  DCHECK(physical_width);
-  DCHECK(physical_height);
+    const FloatRect& view_box,
+    const FloatSize& viewport_size) const {
+  DCHECK(!view_box.IsEmpty());
+  DCHECK(!viewport_size.IsEmpty());
+  DCHECK_NE(align_, kSvgPreserveaspectratioUnknown);
+
+  double extended_logical_x = view_box.X();
+  double extended_logical_y = view_box.Y();
+  double extended_logical_width = view_box.Width();
+  double extended_logical_height = view_box.Height();
+  double extended_physical_width = viewport_size.Width();
+  double extended_physical_height = viewport_size.Height();
 
   AffineTransform transform;
-  if (align_ == kSvgPreserveaspectratioUnknown)
-    return transform;
-
-  double extended_logical_x = logical_x;
-  double extended_logical_y = logical_y;
-  double extended_logical_width = logical_width;
-  double extended_logical_height = logical_height;
-  double extended_physical_width = physical_width;
-  double extended_physical_height = physical_height;
-  double logical_ratio = extended_logical_width / extended_logical_height;
-  double physical_ratio = extended_physical_width / extended_physical_height;
-
   if (align_ == kSvgPreserveaspectratioNone) {
     transform.ScaleNonUniform(
         extended_physical_width / extended_logical_width,
@@ -316,6 +306,8 @@
     return transform;
   }
 
+  double logical_ratio = extended_logical_width / extended_logical_height;
+  double physical_ratio = extended_physical_width / extended_physical_height;
   if ((logical_ratio < physical_ratio &&
        (meet_or_slice_ == kSvgMeetorsliceMeet)) ||
       (logical_ratio >= physical_ratio &&
diff --git a/third_party/blink/renderer/core/svg/svg_preserve_aspect_ratio.h b/third_party/blink/renderer/core/svg/svg_preserve_aspect_ratio.h
index 9d09acea..559d3a31 100644
--- a/third_party/blink/renderer/core/svg/svg_preserve_aspect_ratio.h
+++ b/third_party/blink/renderer/core/svg/svg_preserve_aspect_ratio.h
@@ -28,6 +28,7 @@
 
 class AffineTransform;
 class FloatRect;
+class FloatSize;
 class SVGPreserveAspectRatioTearOff;
 
 class SVGPreserveAspectRatio final
@@ -74,12 +75,8 @@
 
   void TransformRect(FloatRect& dest_rect, FloatRect& src_rect) const;
 
-  AffineTransform ComputeTransform(float logical_x,
-                                   float logical_y,
-                                   float logical_width,
-                                   float logical_height,
-                                   float physical_width,
-                                   float physical_height) const;
+  AffineTransform ComputeTransform(const FloatRect& view_box,
+                                   const FloatSize& viewport_size) const;
 
   String ValueAsString() const override;
   SVGParsingError SetValueAsString(const String&);
diff --git a/third_party/blink/renderer/core/svg/svg_svg_element.cc b/third_party/blink/renderer/core/svg/svg_svg_element.cc
index a7caa91..4800519 100644
--- a/third_party/blink/renderer/core/svg/svg_svg_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_svg_element.cc
@@ -483,10 +483,8 @@
       return matrix.ToAffineTransform();
     }
   }
-  if (!HasEmptyViewBox()) {
-    FloatSize size = CurrentViewportSize();
-    transform.Multiply(ViewBoxToViewTransform(size.Width(), size.Height()));
-  }
+  if (!HasEmptyViewBox())
+    transform.Multiply(ViewBoxToViewTransform(CurrentViewportSize()));
   return transform;
 }
 
@@ -669,11 +667,10 @@
   return height()->CurrentValue()->Value(length_context);
 }
 
-AffineTransform SVGSVGElement::ViewBoxToViewTransform(float view_width,
-                                                      float view_height) const {
+AffineTransform SVGSVGElement::ViewBoxToViewTransform(
+    const FloatSize& viewport_size) const {
   AffineTransform ctm = SVGFitToViewBox::ViewBoxToViewTransform(
-      CurrentViewBoxRect(), CurrentPreserveAspectRatio(), view_width,
-      view_height);
+      CurrentViewBoxRect(), CurrentPreserveAspectRatio(), viewport_size);
   if (!view_spec_ || !view_spec_->Transform())
     return ctm;
   const SVGTransformList* transform_list = view_spec_->Transform();
diff --git a/third_party/blink/renderer/core/svg/svg_svg_element.h b/third_party/blink/renderer/core/svg/svg_svg_element.h
index 8fb5b00..1ac47848 100644
--- a/third_party/blink/renderer/core/svg/svg_svg_element.h
+++ b/third_party/blink/renderer/core/svg/svg_svg_element.h
@@ -93,8 +93,7 @@
   static SVGTransformTearOff* createSVGTransform();
   static SVGTransformTearOff* createSVGTransformFromMatrix(SVGMatrixTearOff*);
 
-  AffineTransform ViewBoxToViewTransform(float view_width,
-                                         float view_height) const;
+  AffineTransform ViewBoxToViewTransform(const FloatSize& viewport_size) const;
 
   void SetupInitialView(const String& fragment_identifier,
                         Element* anchor_node);
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index dd15c70c..f9e681b 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -4612,6 +4612,32 @@
       string_builder = string_builder + ">";
     }
 
+    // Add properties of interest that often contribute to errors:
+    if (SupportsARIAOwns())
+      string_builder = string_builder + " @aria-owns";
+    if (GetAOMPropertyOrARIAAttribute(AOMRelationProperty::kActiveDescendant))
+      string_builder = string_builder + " @aria-activedescendant";
+    if (IsFocused())
+      string_builder = string_builder + " focused";
+    if (AXObjectCache().IsAriaOwned(this))
+      string_builder = string_builder + " isAriaOwned";
+    if (AccessibilityIsIgnored()) {
+      string_builder = string_builder + " isIgnored";
+      if (!AccessibilityIsIncludedInTree())
+        string_builder = string_builder + " isRemovedFromTree";
+    }
+    if (GetNode() &&
+        DisplayLockUtilities::ShouldIgnoreNodeDueToDisplayLock(
+            *GetNode(), DisplayLockActivationReason::kAccessibility)) {
+      string_builder = string_builder + " isDisplayLocked";
+    }
+    if (AriaHiddenRoot())
+      string_builder = string_builder + " isAriaHidden";
+    if (IsHiddenViaStyle())
+      string_builder = string_builder + " isHiddenViaCSS";
+    if (GetNode() && GetNode()->IsInert())
+      string_builder = string_builder + " isInert";
+
     string_builder = string_builder + " name=";
   } else {
     string_builder = string_builder + ": ";
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth.idl b/third_party/blink/renderer/modules/bluetooth/bluetooth.idl
index 1dbb1ff2..92f55cb 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth.idl
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth.idl
@@ -9,7 +9,7 @@
     RuntimeEnabled=WebBluetooth,
     SecureContext
 ] interface Bluetooth : EventTarget {
-    [CallWith=ScriptState, RaisesException] Promise<boolean> getAvailability();
+    [CallWith=ScriptState, RaisesException, MeasureAs=WebBluetoothGetAvailability] Promise<boolean> getAvailability();
     [RuntimeEnabled=WebBluetoothGetDevices, CallWith=ScriptState, RaisesException, MeasureAs=WebBluetoothGetDevices] Promise<sequence<BluetoothDevice>> getDevices();
     [CallWith=ScriptState, RaisesException, MeasureAs=WebBluetoothRequestDevice] Promise<BluetoothDevice> requestDevice (optional RequestDeviceOptions options = {});
 
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
index 8821d05e..617befa 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
@@ -192,6 +192,14 @@
   }
 }
 
+RespectImageOrientationEnum
+BaseRenderingContext2D::RespectImageOrientationInternal(
+    CanvasImageSource* image_source) {
+  if (image_source->WouldTaintOrigin())
+    return kRespectImageOrientation;
+  return RespectImageOrientation();
+}
+
 void BaseRenderingContext2D::strokeStyle(
     StringOrCanvasGradientOrCanvasPattern& return_value) const {
   ConvertCanvasStyleToUnionType(GetState().StrokeStyle(), return_value);
@@ -1034,7 +1042,8 @@
       ToImageSourceInternal(image_source, exception_state);
   if (!image_source_internal)
     return;
-  RespectImageOrientationEnum respect_orientation = RespectImageOrientation();
+  RespectImageOrientationEnum respect_orientation =
+      RespectImageOrientationInternal(image_source_internal);
   FloatSize default_object_size(Width(), Height());
   FloatSize source_rect_size = image_source_internal->ElementSize(
       default_object_size, respect_orientation);
@@ -1059,7 +1068,8 @@
     return;
   FloatSize default_object_size(this->Width(), this->Height());
   FloatSize source_rect_size = image_source_internal->ElementSize(
-      default_object_size, RespectImageOrientation());
+      default_object_size,
+      RespectImageOrientationInternal(image_source_internal));
   drawImage(script_state, image_source_internal, 0, 0, source_rect_size.Width(),
             source_rect_size.Height(), x, y, width, height, exception_state);
 }
@@ -1161,7 +1171,8 @@
     // We always use the image-orientation property on the canvas element
     // because the alternative would result in complex rules depending on
     // the source of the image.
-    RespectImageOrientationEnum respect_orientation = RespectImageOrientation();
+    RespectImageOrientationEnum respect_orientation =
+        RespectImageOrientationInternal(image_source);
     FloatRect corrected_src_rect = src_rect;
     if (respect_orientation == kRespectImageOrientation &&
         !image->HasDefaultOrientation()) {
@@ -1247,8 +1258,8 @@
 
   FloatRect src_rect = NormalizeRect(FloatRect(fsx, fsy, fsw, fsh));
   FloatRect dst_rect = NormalizeRect(FloatRect(fdx, fdy, fdw, fdh));
-  FloatSize image_size =
-      image_source->ElementSize(default_object_size, RespectImageOrientation());
+  FloatSize image_size = image_source->ElementSize(
+      default_object_size, RespectImageOrientationInternal(image_source));
 
   ClipRectsToImageRect(FloatRect(FloatPoint(), image_size), &src_rect,
                        &dst_rect);
@@ -1467,7 +1478,8 @@
           String::Format("The canvas %s is 0.",
                          image_source
                                  ->ElementSize(default_object_size,
-                                               RespectImageOrientation())
+                                               RespectImageOrientationInternal(
+                                                   image_source))
                                  .Width()
                              ? "height"
                              : "width"));
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h
index bf4ced6..f7cf4a08 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h
@@ -470,6 +470,9 @@
   void IdentifiabilityMaybeUpdateForStyleUnion(
       const StringOrCanvasGradientOrCanvasPattern& style);
 
+  RespectImageOrientationEnum RespectImageOrientationInternal(
+      CanvasImageSource*);
+
   bool origin_tainted_by_content_;
 
   DISALLOW_COPY_AND_ASSIGN(BaseRenderingContext2D);
diff --git a/third_party/blink/renderer/modules/font_access/font_manager.h b/third_party/blink/renderer/modules/font_access/font_manager.h
index 3448adc..e99b919 100644
--- a/third_party/blink/renderer/modules/font_access/font_manager.h
+++ b/third_party/blink/renderer/modules/font_access/font_manager.h
@@ -20,9 +20,13 @@
 
  public:
   FontManager() = default;
+
+  // Disallow copy and assign.
+  FontManager(const FontManager&) = delete;
+  FontManager operator=(const FontManager&) = delete;
+
   ScriptValue query(ScriptState*, ExceptionState&);
 
-  DISALLOW_COPY_AND_ASSIGN(FontManager);
   void Trace(blink::Visitor*) const override;
 };
 
diff --git a/third_party/blink/renderer/modules/mediasource/media_source.cc b/third_party/blink/renderer/modules/mediasource/media_source.cc
index 28311b69..9c200df 100644
--- a/third_party/blink/renderer/modules/mediasource/media_source.cc
+++ b/third_party/blink/renderer/modules/mediasource/media_source.cc
@@ -420,6 +420,14 @@
   return result;
 }
 
+// static
+bool MediaSource::canConstructInDedicatedWorker() {
+  // This method's visibility in IDL is restricted to MSE-in-Workers feature
+  // being enabled.
+  DCHECK(RuntimeEnabledFeatures::MediaSourceInWorkersEnabled());
+  return true;
+}
+
 void MediaSource::RecordIdentifiabilityMetric(ExecutionContext* context,
                                               const String& type,
                                               bool result) {
diff --git a/third_party/blink/renderer/modules/mediasource/media_source.h b/third_party/blink/renderer/modules/mediasource/media_source.h
index ed8d46d..1159c58 100644
--- a/third_party/blink/renderer/modules/mediasource/media_source.h
+++ b/third_party/blink/renderer/modules/mediasource/media_source.h
@@ -86,6 +86,7 @@
       LOCKS_EXCLUDED(attachment_link_lock_);
 
   static bool isTypeSupported(ExecutionContext* context, const String& type);
+  static bool canConstructInDedicatedWorker();
 
   // Methods needed by a MediaSourceAttachmentSupplement to service operations
   // proxied from an HTMLMediaElement.
diff --git a/third_party/blink/renderer/modules/mediasource/media_source.idl b/third_party/blink/renderer/modules/mediasource/media_source.idl
index abada11..b09078e 100644
--- a/third_party/blink/renderer/modules/mediasource/media_source.idl
+++ b/third_party/blink/renderer/modules/mediasource/media_source.idl
@@ -59,4 +59,12 @@
     [RaisesException] void clearLiveSeekableRange();
 
     [CallWith=ExecutionContext] static boolean isTypeSupported (DOMString type);
+
+    // Enables proactive feature-detection of MSE-in-Workers support from the
+    // main thread (or anywhere this interface is exposed.) If the attribute is
+    // available, and if it is true, then the implementation claims it can
+    // support usage of the MSE API from dedicated worker contexts. See also
+    // https://github.com/w3c/media-source/issues/175 and
+    // https://crbug.com/878133.
+    [RuntimeEnabled=MediaSourceInWorkers] static readonly attribute boolean canConstructInDedicatedWorker;
 };
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
index d06e145..aa9ceb3 100644
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
@@ -13,6 +13,7 @@
 #include <vector>
 
 #include "base/power_monitor/power_observer.h"
+#include "base/stl_util.h"
 #include "base/values.h"
 #include "third_party/blink/public/common/peerconnection/peer_connection_tracker_mojom_traits.h"
 #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
@@ -705,9 +706,20 @@
 
 void PeerConnectionTracker::OnSuspend() {
   DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
-  for (auto it = peer_connection_local_id_map_.begin();
-       it != peer_connection_local_id_map_.end(); ++it) {
-    it->key->CloseClientPeerConnection();
+  // Closing peer connections fires events. If JavaScript triggers the creation
+  // or garbage collection of more peer connections, this would invalidate the
+  // |peer_connection_local_id_map_| iterator. Therefor we iterate on a copy.
+  PeerConnectionLocalIdMap peer_connection_map_copy =
+      peer_connection_local_id_map_;
+  for (const auto& pair : peer_connection_map_copy) {
+    RTCPeerConnectionHandler* peer_connection_handler = pair.key;
+    if (!base::Contains(peer_connection_local_id_map_,
+                        peer_connection_handler)) {
+      // Skip peer connections that have been unregistered during this method
+      // call. Avoids use-after-free.
+      continue;
+    }
+    peer_connection_handler->CloseClientPeerConnection();
   }
 }
 
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index ddb3eaf4..d39cbed 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -501,6 +501,7 @@
     "exported/mediastream/web_platform_media_stream_source.cc",
     "exported/platform.cc",
     "exported/resource_load_info_notifier_wrapper.cc",
+    "exported/sync_load_response.cc",
     "exported/url_conversion.cc",
     "exported/video_capture/web_video_capture_impl_manager.cc",
     "exported/weak_wrapper_resource_load_info_notifier.cc",
diff --git a/content/renderer/loader/sync_load_response.cc b/third_party/blink/renderer/platform/exported/sync_load_response.cc
similarity index 61%
rename from content/renderer/loader/sync_load_response.cc
rename to third_party/blink/renderer/platform/exported/sync_load_response.cc
index d3a5ef8..45e2064f 100644
--- a/content/renderer/loader/sync_load_response.cc
+++ b/third_party/blink/renderer/platform/exported/sync_load_response.cc
@@ -2,17 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/renderer/loader/sync_load_response.h"
+#include "third_party/blink/public/platform/sync_load_response.h"
 
-namespace content {
+namespace blink {
 
-SyncLoadResponse::SyncLoadResponse() {}
+SyncLoadResponse::SyncLoadResponse() = default;
 
 SyncLoadResponse::SyncLoadResponse(SyncLoadResponse&& other) = default;
 
-SyncLoadResponse::~SyncLoadResponse() {}
+SyncLoadResponse::~SyncLoadResponse() = default;
 
 SyncLoadResponse& SyncLoadResponse::operator=(SyncLoadResponse&& other) =
     default;
 
-}  // namespace content
+}  // namespace blink
diff --git a/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc b/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc
index efce7b3..42ad9d6 100644
--- a/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc
+++ b/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc
@@ -91,11 +91,25 @@
 void FontMatchingMetrics::ReportSuccessfulLocalFontMatch(
     const AtomicString& font_name) {
   local_fonts_succeeded_.insert(font_name);
+  ReportLocalFontExistenceByUniqueNameOnly(font_name, /*font_exists=*/true);
 }
 
 void FontMatchingMetrics::ReportFailedLocalFontMatch(
     const AtomicString& font_name) {
   local_fonts_failed_.insert(font_name);
+  ReportLocalFontExistenceByUniqueNameOnly(font_name, /*font_exists=*/false);
+}
+
+void FontMatchingMetrics::ReportLocalFontExistenceByUniqueNameOnly(
+    const AtomicString& font_name,
+    bool font_exists) {
+  if (!IdentifiabilityStudySettings::Get()->IsTypeAllowed(
+          IdentifiableSurface::Type::kLocalFontExistenceByUniqueNameOnly)) {
+    return;
+  }
+  IdentifiableTokenKey input_key(
+      IdentifiabilityBenignCaseFoldingStringToken(font_name));
+  local_font_existence_by_unique_name_only_.insert(input_key, font_exists);
 }
 
 void FontMatchingMetrics::InsertFontHashIntoMap(IdentifiableTokenKey input_key,
@@ -263,6 +277,8 @@
            IdentifiableSurface::Type::kGenericFontLookup},
           {&font_load_postscript_name_,
            IdentifiableSurface::Type::kLocalFontLoadPostScriptName},
+          {&local_font_existence_by_unique_name_only_,
+           IdentifiableSurface::Type::kLocalFontExistenceByUniqueNameOnly},
       };
 
   for (const auto& surface_entry : hash_maps_with_corresponding_surface_types) {
diff --git a/third_party/blink/renderer/platform/fonts/font_matching_metrics.h b/third_party/blink/renderer/platform/fonts/font_matching_metrics.h
index 7c934861..e49edc4 100644
--- a/third_party/blink/renderer/platform/fonts/font_matching_metrics.h
+++ b/third_party/blink/renderer/platform/fonts/font_matching_metrics.h
@@ -200,6 +200,13 @@
                              SimpleFontData* font_data,
                              TokenToTokenHashMap hash_map);
 
+  // Reports a local font's existence was looked up by a name, but its actual
+  // font data may or may not have been loaded. This only includes lookups where
+  // the name is allowed to match PostScript names and full font names, but not
+  // family names.
+  void ReportLocalFontExistenceByUniqueNameOnly(const AtomicString& font_name,
+                                                bool font_exists);
+
   // Constructs a builder with a hash of the FontSelectionRequest already added.
   IdentifiableTokenBuilder GetTokenBuilderWithFontSelectionRequest(
       const FontDescription& font_description);
@@ -243,6 +250,7 @@
   TokenToTokenHashMap font_lookups_as_last_resort_;
   TokenToTokenHashMap generic_font_lookups_;
   TokenToTokenHashMap font_load_postscript_name_;
+  TokenToTokenHashMap local_font_existence_by_unique_name_only_;
 
   ukm::UkmRecorder* const ukm_recorder_;
   const ukm::SourceId source_id_;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
index 69053325..06484ff7 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
@@ -820,10 +820,10 @@
       MakeBridge(IntSize(300, 300), RasterMode::kGPU, color_params);
   gfx::ColorSpace expected_color_space = gfx::ColorSpace::CreateSRGB();
   Vector<cc::DrawImage> images = {
-      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
+      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)), false,
                     SkIRect::MakeWH(10, 10), kNone_SkFilterQuality,
                     SkMatrix::I(), 0u, expected_color_space),
-      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)),
+      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)), false,
                     SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkMatrix::I(),
                     0u, expected_color_space)};
 
@@ -843,10 +843,10 @@
   std::unique_ptr<Canvas2DLayerBridge> bridge =
       MakeBridge(IntSize(300, 300), RasterMode::kGPU, color_params);
   Vector<cc::DrawImage> images = {
-      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
+      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)), false,
                     SkIRect::MakeWH(10, 10), kNone_SkFilterQuality,
                     SkMatrix::I(), 0u, color_params.GetStorageGfxColorSpace()),
-      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)),
+      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)), false,
                     SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkMatrix::I(),
                     0u, color_params.GetStorageGfxColorSpace())};
 
@@ -866,13 +866,13 @@
       MakeBridge(IntSize(300, 300), RasterMode::kGPU, color_params);
 
   Vector<cc::DrawImage> images = {
-      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
+      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)), false,
                     SkIRect::MakeWH(10, 10), kNone_SkFilterQuality,
                     SkMatrix::I(), 0u, color_params.GetStorageGfxColorSpace()),
-      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)),
+      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)), false,
                     SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkMatrix::I(),
                     0u, color_params.GetStorageGfxColorSpace()),
-      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)),
+      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)), false,
                     SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkMatrix::I(),
                     0u, color_params.GetStorageGfxColorSpace())};
 
@@ -901,7 +901,7 @@
       MakeBridge(IntSize(300, 300), RasterMode::kGPU, color_params);
 
   auto image =
-      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
+      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)), false,
                     SkIRect::MakeWH(10, 10), kNone_SkFilterQuality,
                     SkMatrix::I(), 0u, color_params.GetStorageGfxColorSpace());
   bridge->GetPaintCanvas()->drawImage(image.paint_image(), 0u, 0u, nullptr);
@@ -920,10 +920,10 @@
       MakeBridge(IntSize(300, 300), RasterMode::kGPU, color_params);
   PaintFlags flags;
   Vector<cc::DrawImage> images = {
-      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
+      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)), false,
                     SkIRect::MakeWH(10, 10), kNone_SkFilterQuality,
                     SkMatrix::I(), 0u, color_params.GetStorageGfxColorSpace()),
-      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)),
+      cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)), false,
                     SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkMatrix::I(),
                     0u, color_params.GetStorageGfxColorSpace())};
   bridge->GetPaintCanvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr);
diff --git a/third_party/blink/renderer/platform/heap/heap.cc b/third_party/blink/renderer/platform/heap/heap.cc
index e550136..8c65c256 100644
--- a/third_party/blink/renderer/platform/heap/heap.cc
+++ b/third_party/blink/renderer/platform/heap/heap.cc
@@ -59,6 +59,24 @@
 
 namespace blink {
 
+void WeakContainersWorklist::Push(const HeapObjectHeader* object) {
+  DCHECK(object);
+  WTF::MutexLocker locker(lock_);
+  objects_.insert(object);
+}
+
+void WeakContainersWorklist::Erase(const HeapObjectHeader* object) {
+  // This method is called only during atomic pause, so lock is not needed.
+  DCHECK(object);
+  objects_.erase(object);
+}
+
+bool WeakContainersWorklist::Contains(const HeapObjectHeader* object) {
+  // This method is called only during atomic pause, so lock is not needed.
+  DCHECK(object);
+  return objects_.find(object) != objects_.end();
+}
+
 HeapAllocHooks::AllocationHook* HeapAllocHooks::allocation_hook_ = nullptr;
 HeapAllocHooks::FreeHook* HeapAllocHooks::free_hook_ = nullptr;
 
@@ -180,6 +198,7 @@
   v8_references_worklist_ = std::make_unique<V8ReferencesWorklist>();
   not_safe_to_concurrently_trace_worklist_ =
       std::make_unique<NotSafeToConcurrentlyTraceWorklist>();
+  weak_containers_worklist_ = std::make_unique<WeakContainersWorklist>();
   if (should_initialize_compaction_worklists) {
     movable_reference_worklist_ = std::make_unique<MovableReferenceWorklist>();
   }
@@ -193,6 +212,7 @@
   ephemeron_pairs_to_process_worklist_.reset();
   v8_references_worklist_.reset();
   not_safe_to_concurrently_trace_worklist_.reset();
+  weak_containers_worklist_.reset();
   // The fixed point iteration may have found not-fully-constructed objects.
   // Such objects should have already been found through the stack scan though
   // and should thus already be marked.
diff --git a/third_party/blink/renderer/platform/heap/heap.h b/third_party/blink/renderer/platform/heap/heap.h
index cc62ead..9610e8ba 100644
--- a/third_party/blink/renderer/platform/heap/heap.h
+++ b/third_party/blink/renderer/platform/heap/heap.h
@@ -33,6 +33,7 @@
 
 #include <limits>
 #include <memory>
+#include <unordered_set>
 
 #include "base/macros.h"
 #include "build/build_config.h"
@@ -49,6 +50,7 @@
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/sanitizers.h"
+#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
 
 namespace blink {
 
@@ -102,6 +104,17 @@
 using NotSafeToConcurrentlyTraceWorklist =
     Worklist<NotSafeToConcurrentlyTraceItem, 64 /* local entries */>;
 
+class WeakContainersWorklist {
+ public:
+  void Push(const HeapObjectHeader*);
+  void Erase(const HeapObjectHeader*);
+  bool Contains(const HeapObjectHeader*);
+
+ private:
+  WTF::Mutex lock_;
+  std::unordered_set<const HeapObjectHeader*> objects_;
+};
+
 class PLATFORM_EXPORT HeapAllocHooks {
   STATIC_ONLY(HeapAllocHooks);
 
@@ -242,6 +255,11 @@
       const {
     return not_safe_to_concurrently_trace_worklist_.get();
   }
+
+  WeakContainersWorklist* GetWeakContainersWorklist() const {
+    return weak_containers_worklist_.get();
+  }
+
   // Register an ephemeron table for fixed-point iteration.
   void RegisterWeakTable(void* container_object,
                          EphemeronCallback);
@@ -446,6 +464,8 @@
   std::unique_ptr<NotSafeToConcurrentlyTraceWorklist>
       not_safe_to_concurrently_trace_worklist_;
 
+  std::unique_ptr<WeakContainersWorklist> weak_containers_worklist_;
+
   std::unique_ptr<HeapCompact> compaction_;
 
   LastAllocatedRegion last_allocated_region_;
diff --git a/third_party/blink/renderer/platform/heap/marking_visitor.cc b/third_party/blink/renderer/platform/heap/marking_visitor.cc
index 931c814..38a8176 100644
--- a/third_party/blink/renderer/platform/heap/marking_visitor.cc
+++ b/third_party/blink/renderer/platform/heap/marking_visitor.cc
@@ -28,6 +28,7 @@
       ephemeron_pairs_to_process_worklist_(
           Heap().GetEphemeronPairsToProcessWorklist(),
           task_id),
+      weak_containers_worklist_(Heap().GetWeakContainersWorklist()),
       marking_mode_(marking_mode),
       task_id_(task_id) {}
 
@@ -115,6 +116,7 @@
   //   non-empty/deleted buckets have been moved to the new backing store.
   MarkHeaderNoTracing(header);
   AccountMarkedBytes(header);
+  weak_containers_worklist_->Push(header);
 
   // Register final weak processing of the backing store.
   RegisterWeakCallback(weak_callback, weak_callback_parameter);
@@ -242,8 +244,24 @@
           ? static_cast<LargeObjectPage*>(page)->ObjectHeader()
           : static_cast<NormalPage*>(page)->ConservativelyFindHeaderFromAddress(
                 address);
-  if (!header || header->IsMarked())
+  if (!header)
     return;
+  if (header->IsMarked()) {
+    // Weak containers found through conservative GC need to be strongified. In
+    // case the container was previously marked and weakly traced, it should be
+    // retraced strongly now. Previously marked/traced weak containers are
+    // marked using the |weak_containers_worklist_|. Other marked object can be
+    // skipped.
+    if (weak_containers_worklist_->Contains(header)) {
+      DCHECK(!header->IsInConstruction());
+      // Remove from the set so multiple iterators don't cause multiple
+      // retracings of the backing store.
+      weak_containers_worklist_->Erase(header);
+      marking_worklist_.Push(
+          {header->Payload(), GCInfo::From(header->GcInfoIndex()).trace});
+    }
+    return;
+  }
 
   // Simple case for fully constructed objects. This just adds the object to the
   // regular marking worklist.
diff --git a/third_party/blink/renderer/platform/heap/marking_visitor.h b/third_party/blink/renderer/platform/heap/marking_visitor.h
index 0936bf4..944dffe 100644
--- a/third_party/blink/renderer/platform/heap/marking_visitor.h
+++ b/third_party/blink/renderer/platform/heap/marking_visitor.h
@@ -86,6 +86,7 @@
   MovableReferenceWorklist::View movable_reference_worklist_;
   EphemeronPairsWorklist::View discovered_ephemeron_pairs_worklist_;
   EphemeronPairsWorklist::View ephemeron_pairs_to_process_worklist_;
+  WeakContainersWorklist* const weak_containers_worklist_;
   size_t marked_bytes_ = 0;
   const MarkingMode marking_mode_;
   int task_id_;
diff --git a/third_party/blink/renderer/platform/heap/test/incremental_marking_test.cc b/third_party/blink/renderer/platform/heap/test/incremental_marking_test.cc
index a180315..74d7f717 100644
--- a/third_party/blink/renderer/platform/heap/test/incremental_marking_test.cc
+++ b/third_party/blink/renderer/platform/heap/test/incremental_marking_test.cc
@@ -1826,5 +1826,53 @@
   EXPECT_EQ(10u, Destructed::n_destructed);
 }
 
+class DestructedAndTraced final : public GarbageCollected<DestructedAndTraced> {
+ public:
+  ~DestructedAndTraced() { n_destructed++; }
+
+  void Trace(Visitor*) const { n_traced++; }
+
+  static size_t n_destructed;
+  static size_t n_traced;
+};
+
+size_t DestructedAndTraced::n_destructed = 0;
+size_t DestructedAndTraced::n_traced = 0;
+
+TEST_F(IncrementalMarkingTest, ConservativeGCOfWeakContainer) {
+  // Regression test: https://crbug.com/1108676
+  //
+  // Test ensures that on-stack references to weak containers (e.g. iterators)
+  // force re-tracing of the entire container. Otherwise, if the container was
+  // previously traced and is not re-traced, some bucket might be deleted which
+  // will make existing iterators invalid.
+
+  using WeakContainer = HeapHashMap<WeakMember<DestructedAndTraced>, size_t>;
+  Persistent<WeakContainer> map = MakeGarbageCollected<WeakContainer>();
+  static constexpr size_t kNumObjects = 10u;
+  for (size_t i = 0; i < kNumObjects; ++i) {
+    map->insert(MakeGarbageCollected<DestructedAndTraced>(), i);
+  }
+  DestructedAndTraced::n_destructed = 0;
+
+  for (auto it = map->begin(); it != map->end(); ++it) {
+    size_t value = it->value;
+    DestructedAndTraced::n_traced = 0;
+    IncrementalMarkingTestDriver driver(ThreadState::Current());
+    driver.Start();
+    driver.FinishSteps();
+    // map should now be marked, but has not been traced since it's weak.
+    EXPECT_EQ(0u, DestructedAndTraced::n_traced);
+    ConservativelyCollectGarbage();
+    // map buckets were traced (at least once).
+    EXPECT_NE(kNumObjects, DestructedAndTraced::n_traced);
+    // Check that iterator is still valid.
+    EXPECT_EQ(value, it->value);
+  }
+
+  // All buckets were kept alive.
+  EXPECT_EQ(0u, DestructedAndTraced::n_destructed);
+}
+
 }  // namespace incremental_marking_test
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/widget/compositing/widget_compositor_unittest.cc b/third_party/blink/renderer/platform/widget/compositing/widget_compositor_unittest.cc
index a0c3b05..607fba7 100644
--- a/third_party/blink/renderer/platform/widget/compositing/widget_compositor_unittest.cc
+++ b/third_party/blink/renderer/platform/widget/compositing/widget_compositor_unittest.cc
@@ -70,12 +70,15 @@
   using CompositorMode = cc::CompositorMode;
 
   void BeginTest() override {
+    mojo::AssociatedRemote<mojom::blink::Widget> widget_remote;
+    mojo::PendingAssociatedReceiver<mojom::blink::Widget> widget_receiver =
+        widget_remote.BindNewEndpointAndPassDedicatedReceiver();
+
+    mojo::AssociatedRemote<mojom::blink::WidgetHost> widget_host_remote;
+    ignore_result(widget_host_remote.BindNewEndpointAndPassDedicatedReceiver());
+
     widget_base_ = std::make_unique<WidgetBase>(
-        &client_,
-        blink::CrossVariantMojoAssociatedRemote<
-            blink::mojom::WidgetHostInterfaceBase>(),
-        blink::CrossVariantMojoAssociatedReceiver<
-            blink::mojom::WidgetInterfaceBase>(),
+        &client_, widget_host_remote.Unbind(), std::move(widget_receiver),
         /*is_hidden=*/false,
         /*never_composited=*/false,
         /*is_for_child_local_root=*/false);
diff --git a/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier.cc b/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier.cc
index 7608a44..c4dd90d 100644
--- a/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier.cc
+++ b/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier.cc
@@ -55,17 +55,27 @@
 }
 }  // namespace
 
+// Scale one of the control points of the Cubic Bezier curve based on the
+// initial_velocity (which is expressed in terms of pixels / ms).
+gfx::CubicBezier InitialVelocityBasedBezierCurve(const double initial_velocity,
+                                                 const double x1,
+                                                 const double y1,
+                                                 const double x2,
+                                                 const double y2) {
+  const double velocity = std::abs(initial_velocity);
+  double x = x1, y = y1;
+  if (x1 * velocity < y1) {
+    y = x1 * velocity;
+  } else {
+    x = y1 / velocity;
+  }
+
+  return gfx::CubicBezier(x, y, x2, y2);
+}
+
 ElasticOverscrollControllerBezier::ElasticOverscrollControllerBezier(
     cc::ScrollElasticityHelper* helper)
-    : ElasticOverscrollController(helper),
-      bounce_forwards_curve_(gfx::CubicBezier(kBounceForwardsX1,
-                                              kBounceForwardsY1,
-                                              kBounceForwardsX2,
-                                              kBounceForwardsY2)),
-      bounce_backwards_curve_(gfx::CubicBezier(kBounceBackwardsX1,
-                                               kBounceBackwardsY1,
-                                               kBounceBackwardsX2,
-                                               kBounceBackwardsY2)) {}
+    : ElasticOverscrollController(helper) {}
 
 // Returns the maximum amount to be overscrolled.
 gfx::Vector2dF ElasticOverscrollControllerBezier::OverscrollBoundary(
@@ -85,6 +95,8 @@
           ? scroll_velocity().y() / 1000.f
           : 0.f);
 
+  residual_velocity_ = velocity;
+
   gfx::Vector2dF bounce_forwards_delta(gfx::Vector2dF(
       sqrt(std::abs(velocity.x())), sqrt(std::abs(velocity.y()))));
   bounce_forwards_delta.Scale(kOverbounceDistanceMultiplier);
@@ -124,6 +136,7 @@
 }
 
 double ElasticOverscrollControllerBezier::StretchAmountForForwardBounce(
+    const gfx::CubicBezier bounce_forwards_curve,
     const base::TimeDelta& delta,
     const base::TimeDelta& bounce_forwards_duration,
     const double velocity,
@@ -135,7 +148,7 @@
     if (delta < bounce_forwards_duration) {
       double curve_progress =
           delta.InMillisecondsF() / bounce_forwards_duration.InMillisecondsF();
-      double progress = bounce_forwards_curve_.Solve(curve_progress);
+      double progress = bounce_forwards_curve.Solve(curve_progress);
       return initial_stretch * (1 - progress) +
              bounce_forwards_distance * progress;
     }
@@ -144,13 +157,14 @@
 }
 
 double ElasticOverscrollControllerBezier::StretchAmountForBackwardBounce(
+    const gfx::CubicBezier bounce_backwards_curve,
     const base::TimeDelta& delta,
     const base::TimeDelta& bounce_backwards_duration,
     const double bounce_forwards_distance) const {
   if (delta < bounce_backwards_duration) {
     double curve_progress =
         delta.InMillisecondsF() / bounce_backwards_duration.InMillisecondsF();
-    double progress = bounce_backwards_curve_.Solve(curve_progress);
+    double progress = bounce_backwards_curve.Solve(curve_progress);
     return bounce_forwards_distance * (1 - progress);
   }
   return 0.f;
@@ -163,15 +177,23 @@
   // if the velocity isn't 0, a bounce forwards animation will need to be
   // played.
   base::TimeDelta time_delta = delta;
+  const gfx::CubicBezier bounce_forwards_curve_x =
+      InitialVelocityBasedBezierCurve(residual_velocity_.x(), kBounceForwardsX1,
+                                      kBounceForwardsY1, kBounceForwardsX2,
+                                      kBounceForwardsY2);
+  const gfx::CubicBezier bounce_forwards_curve_y =
+      InitialVelocityBasedBezierCurve(residual_velocity_.y(), kBounceForwardsX1,
+                                      kBounceForwardsY1, kBounceForwardsX2,
+                                      kBounceForwardsY2);
   const gfx::Vector2d forward_animation(gfx::ToRoundedVector2d(gfx::Vector2dF(
-      StretchAmountForForwardBounce(time_delta, bounce_forwards_duration_x_,
-                                    scroll_velocity().x(),
-                                    momentum_animation_initial_stretch_.x(),
-                                    bounce_forwards_distance_.x()),
-      StretchAmountForForwardBounce(time_delta, bounce_forwards_duration_y_,
-                                    scroll_velocity().y(),
-                                    momentum_animation_initial_stretch_.y(),
-                                    bounce_forwards_distance_.y()))));
+      StretchAmountForForwardBounce(
+          bounce_forwards_curve_x, time_delta, bounce_forwards_duration_x_,
+          scroll_velocity().x(), momentum_animation_initial_stretch_.x(),
+          bounce_forwards_distance_.x()),
+      StretchAmountForForwardBounce(
+          bounce_forwards_curve_y, time_delta, bounce_forwards_duration_y_,
+          scroll_velocity().y(), momentum_animation_initial_stretch_.y(),
+          bounce_forwards_distance_.y()))));
 
   if (!forward_animation.IsZero())
     return forward_animation;
@@ -180,10 +202,20 @@
   time_delta -= bounce_forwards_duration_x_;
   time_delta -= bounce_forwards_duration_y_;
 
+  const gfx::CubicBezier bounce_backwards_curve_x =
+      InitialVelocityBasedBezierCurve(residual_velocity_.x(),
+                                      kBounceBackwardsX1, kBounceBackwardsY1,
+                                      kBounceBackwardsX2, kBounceBackwardsY2);
+  const gfx::CubicBezier bounce_backwards_curve_y =
+      InitialVelocityBasedBezierCurve(residual_velocity_.y(),
+                                      kBounceBackwardsX1, kBounceBackwardsY1,
+                                      kBounceBackwardsX2, kBounceBackwardsY2);
   return gfx::ToRoundedVector2d(gfx::Vector2dF(
-      StretchAmountForBackwardBounce(time_delta, bounce_backwards_duration_x_,
+      StretchAmountForBackwardBounce(bounce_backwards_curve_x, time_delta,
+                                     bounce_backwards_duration_x_,
                                      bounce_forwards_distance_.x()),
-      StretchAmountForBackwardBounce(time_delta, bounce_backwards_duration_y_,
+      StretchAmountForBackwardBounce(bounce_backwards_curve_y, time_delta,
+                                     bounce_backwards_duration_y_,
                                      bounce_forwards_distance_.y())));
 }
 
diff --git a/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier.h b/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier.h
index 3886b7c..d6dcf98 100644
--- a/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier.h
+++ b/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier.h
@@ -34,12 +34,14 @@
       const gfx::Vector2dF& delta) const override;
   gfx::Vector2dF OverscrollBoundary(const gfx::Size& scroller_bounds) const;
   double StretchAmountForForwardBounce(
+      const gfx::CubicBezier bounce_forwards_curve,
       const base::TimeDelta& delta,
       const base::TimeDelta& bounce_forwards_duration,
       const double velocity,
       const double initial_stretch,
       const double bounce_forwards_distance) const;
   double StretchAmountForBackwardBounce(
+      const gfx::CubicBezier bounce_backwards_curve,
       const base::TimeDelta& delta,
       const base::TimeDelta& bounce_backwards_duration,
       const double bounce_forwards_distance) const;
@@ -50,12 +52,15 @@
   FRIEND_TEST_ALL_PREFIXES(ElasticOverscrollControllerBezierTest,
                            VerifyForwardAnimationIsNotPlayed);
 
-  const gfx::CubicBezier bounce_forwards_curve_;
+  // This is the velocity (in px/ms) of the fling at the moment the scroller
+  // reaches its bounds. This is useful to tweak the Cubic Bezier curve for the
+  // bounce animation that is about to get played.
+  gfx::Vector2dF residual_velocity_;
+
   base::TimeDelta bounce_forwards_duration_x_;
   base::TimeDelta bounce_forwards_duration_y_;
   gfx::Vector2dF bounce_forwards_distance_;
 
-  const gfx::CubicBezier bounce_backwards_curve_;
   base::TimeDelta bounce_backwards_duration_x_;
   base::TimeDelta bounce_backwards_duration_y_;
   DISALLOW_COPY_AND_ASSIGN(ElasticOverscrollControllerBezier);
diff --git a/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier_unittest.cc b/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier_unittest.cc
index c5a8a37..36516ef5 100644
--- a/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier_unittest.cc
+++ b/third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller_bezier_unittest.cc
@@ -222,11 +222,11 @@
   controller_.Animate(now + base::TimeDelta::FromMilliseconds(32));
   EXPECT_EQ(controller_.state_,
             ElasticOverscrollController::kStateMomentumAnimated);
-  ASSERT_FLOAT_EQ(helper_.StretchAmount().y(), -8);
+  ASSERT_FLOAT_EQ(helper_.StretchAmount().y(), -14);
 
   // Frame 5. The stretch amount moving closer to 0 proves that we're animating.
   controller_.Animate(now + base::TimeDelta::FromMilliseconds(80));
-  ASSERT_FLOAT_EQ(helper_.StretchAmount().y(), -4);
+  ASSERT_FLOAT_EQ(helper_.StretchAmount().y(), -8);
 
   // Frame 15. StretchAmount < abs(1), so snap to 0. state_ is kStateInactive.
   controller_.Animate(now + base::TimeDelta::FromMilliseconds(240));
@@ -242,13 +242,13 @@
 
   // Frame 2.
   controller_.Animate(now + base::TimeDelta::FromMilliseconds(32));
-  ASSERT_FLOAT_EQ(helper_.StretchAmount().x(), -6);
+  ASSERT_FLOAT_EQ(helper_.StretchAmount().x(), -10);
 
   // Frame 5. The stretch amount moving closer to 0 proves that we're animating.
   controller_.Animate(now + base::TimeDelta::FromMilliseconds(80));
   EXPECT_EQ(controller_.state_,
             ElasticOverscrollController::kStateMomentumAnimated);
-  ASSERT_FLOAT_EQ(helper_.StretchAmount().x(), -2);
+  ASSERT_FLOAT_EQ(helper_.StretchAmount().x(), -5);
 
   // Frame 15. StretchAmount < abs(1), so snap to 0. state_ is kStateInactive.
   controller_.Animate(now + base::TimeDelta::FromMilliseconds(240));
@@ -269,10 +269,10 @@
   const base::TimeTicks now = base::TimeTicks::Now();
   SendGestureScrollEnd(now);
 
-  const int TOTAL_FRAMES = 26;
+  const int TOTAL_FRAMES = 28;
   const int stretch_amount_y[TOTAL_FRAMES] = {
-      -19, -41, -55, -65, -72, -78, -82, -85, -88, -89, -64, -45, -34,
-      -26, -20, -16, -13, -10, -8,  -6,  -4,  -3,  -2,  -1,  -1,  0};
+      -19, -41, -55, -65, -72, -78, -82, -85, -88, -89, -78, -64, -53, -44,
+      -37, -30, -25, -20, -16, -13, -10, -7,  -5,  -4,  -2,  -1,  -1,  0};
 
   for (int i = 0; i < TOTAL_FRAMES; i++) {
     controller_.Animate(now + base::TimeDelta::FromMilliseconds(i * 16));
@@ -290,8 +290,8 @@
   SendGestureScrollEnd(now);
 
   const int stretch_amount_x[TOTAL_FRAMES] = {
-      -9,  -28, -40, -49, -55, -60, -64, -66, -68, -69, -50, -35, -26,
-      -20, -16, -12, -10, -8,  -6,  -5,  -3,  -2,  -2,  -1,  -1,  0};
+      -9,  -24, -34, -42, -48, -54, -58, -62, -66, -69, -62, -52, -43, -36,
+      -30, -25, -20, -17, -13, -10, -8,  -6,  -4,  -3,  -2,  -1,  0,   0};
 
   for (int i = 0; i < TOTAL_FRAMES; i++) {
     controller_.Animate(now + base::TimeDelta::FromMilliseconds(i * 16));
@@ -345,16 +345,16 @@
 
   // Frame 2.
   controller_.Animate(now + base::TimeDelta::FromMilliseconds(32));
-  ASSERT_FLOAT_EQ(helper_.StretchAmount().y(), -8);
+  ASSERT_FLOAT_EQ(helper_.StretchAmount().y(), -14);
 
   // Frame 5. The stretch amount moving closer to 0 proves that we're animating.
   controller_.Animate(now + base::TimeDelta::FromMilliseconds(80));
-  ASSERT_FLOAT_EQ(helper_.StretchAmount().y(), -4);
+  ASSERT_FLOAT_EQ(helper_.StretchAmount().y(), -8);
 
   // While the animation is still ticking, initiate a scroll.
   SendGestureScrollBegin(PhaseState::kNonMomentum);
   SendGestureScrollUpdate(PhaseState::kNonMomentum, Vector2dF(0, -50));
-  ASSERT_FLOAT_EQ(helper_.StretchAmount().y(), -13);
+  ASSERT_FLOAT_EQ(helper_.StretchAmount().y(), -17);
 }
 
 // Tests that animation doesn't get created when unused_delta is 0.
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
index 8e76ea1..6ef8c2e 100755
--- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
+++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -508,6 +508,10 @@
             'base::mac::(CFToNSCast|NSToCFCast)',
             'base::mac::Is(AtMost|AtLeast)?OS.+',
             'base::(scoped_nsobject|ScopedCFTypeRef)',
+
+            # absl::variant and getters:
+            'absl::variant',
+            'absl::get_if',
         ],
         'disallowed': [
             ('base::Bind(|Once|Repeating)',
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
index 65fb52cf..846c23c 100644
--- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
+++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -17,6 +17,9 @@
 crbug.com/591099 accessibility/presentation-owned-elements.html [ Failure ]
 crbug.com/591099 accessibility/role-attribute.html [ Failure ]
 
+### editing/pasteboard/
+crbug.com/591099 editing/pasteboard/mathml-sanitizer-bypass.html [ Failure ]
+
 ### editing/selection/mouse/
 crbug.com/591099 editing/selection/mouse/drag_over_text_transform.html [ Crash ]
 
@@ -50,6 +53,12 @@
 ### external/wpt/css/CSS2/text/
 crbug.com/591099 external/wpt/css/CSS2/text/white-space-mixed-003.xht [ Failure ]
 
+### external/wpt/css/css-flexbox/
+crbug.com/591099 external/wpt/css/css-flexbox/image-as-flexitem-size-003.html [ Failure ]
+crbug.com/591099 external/wpt/css/css-flexbox/image-as-flexitem-size-003v.html [ Failure ]
+crbug.com/591099 external/wpt/css/css-flexbox/image-as-flexitem-size-004.html [ Failure ]
+crbug.com/591099 external/wpt/css/css-flexbox/image-as-flexitem-size-004v.html [ Failure ]
+
 ### external/wpt/css/css-fonts/
 crbug.com/591099 external/wpt/css/css-fonts/font-features-across-space-1.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-fonts/font-features-across-space-3.html [ Failure ]
@@ -96,6 +105,9 @@
 crbug.com/1012289 external/wpt/css/css-pseudo/marker-unicode-bidi-default.html [ Failure ]
 crbug.com/1012289 external/wpt/css/css-pseudo/marker-unicode-bidi-normal.html [ Failure ]
 
+### external/wpt/css/css-ruby/
+crbug.com/591099 external/wpt/css/css-ruby/ruby-line-breaking-002.html [ Failure ]
+
 ### external/wpt/css/css-shapes/shape-outside/shape-box/
 crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-box/shape-outside-border-box-border-radius-003.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-shapes/shape-outside/shape-box/shape-outside-border-box-border-radius-004.html [ Failure ]
@@ -214,6 +226,15 @@
 crbug.com/964181 external/wpt/css/css-text/word-break/word-break-break-all-inline-006.html [ Failure ]
 crbug.com/1017164 external/wpt/css/css-text/word-break/word-break-break-all-inline-008.html [ Failure ]
 
+### external/wpt/css/css-text-decor/
+crbug.com/591099 external/wpt/css/css-text-decor/text-decoration-skip-ink-vertical-001.html [ Failure ]
+crbug.com/591099 external/wpt/css/css-text-decor/text-decoration-skip-ink-vertical-002.html [ Failure ]
+crbug.com/591099 external/wpt/css/css-text-decor/text-decoration-thickness-overline-001.html [ Failure ]
+crbug.com/591099 external/wpt/css/css-text-decor/text-decoration-thickness-scroll-001.html [ Failure ]
+crbug.com/591099 external/wpt/css/css-text-decor/text-decoration-thickness-underline-001.html [ Failure ]
+crbug.com/591099 external/wpt/css/css-text-decor/text-decoration-thickness-vertical-001.html [ Failure ]
+crbug.com/591099 external/wpt/css/css-text-decor/text-underline-offset-scroll-001.html [ Failure ]
+
 ### external/wpt/css/css-ui/
 crbug.com/591099 external/wpt/css/css-ui/text-overflow-010.html [ Failure ]
 crbug.com/1063319 external/wpt/css/css-ui/text-overflow-028.html [ Failure ]
@@ -362,6 +383,7 @@
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/sizing/hori-block-size-small-or-larger-than-container-with-min-or-max-content-2a.html [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/sizing/hori-block-size-small-or-larger-than-container-with-min-or-max-content-2b.html [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/sizing/vert-block-size-small-or-larger-than-container-with-min-or-max-content-2a.html [ Failure ]
+crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/sizing/vert-block-size-small-or-larger-than-container-with-min-or-max-content-2b.html [ Failure ]
 
 ### external/wpt/quirks/
 crbug.com/591099 external/wpt/quirks/line-height-trailing-collapsable-whitespace.html [ Failure ]
@@ -373,6 +395,13 @@
 crbug.com/591099 fast/css/absolute-inline-alignment-2.html [ Failure ]
 crbug.com/591099 fast/css/text-overflow-ellipsis-button.html [ Failure ]
 
+### fast/forms/color-scheme/href/
+crbug.com/591099 fast/forms/color-scheme/href/href-appearance-basic.html [ Failure ]
+
+### fast/replaced/
+crbug.com/591099 fast/replaced/border-radius-clip-content-edge.html [ Failure ]
+crbug.com/591099 fast/replaced/outline-replaced-elements.html [ Failure ]
+
 ### fast/writing-mode/
 crbug.com/591099 fast/writing-mode/flipped-blocks-inline-map-local-to-container.html [ Failure ]
 
@@ -385,15 +414,29 @@
 ### virtual/text-antialias/
 crbug.com/591099 virtual/text-antialias/justify-ideograph-simple.html [ Failure ]
 crbug.com/591099 virtual/text-antialias/apply-start-width-after-skipped-text.html [ Failure ]
+crbug.com/870219 virtual/text-antialias/hyphens/hyphens-auto-mock.html [ Failure ]
 crbug.com/591099 virtual/text-antialias/hyphens/hyphens-auto-nowrap.html [ Failure ]
 crbug.com/639223 virtual/text-antialias/line-break-between-text-nodes-latin1.html [ Failure ]
 
 ### http/tests/
 crbug.com/591099 http/tests/devtools/elements/highlight/highlight-node-vertical-rl.js [ Failure ]
 
+### http/tests/images/
+crbug.com/591099 http/tests/images/png-partial-load-as-document.html [ Failure ]
+
+### http/tests/misc/
+crbug.com/591099 http/tests/misc/favicon-as-image.html [ Failure ]
+
+### images/
+crbug.com/591099 images/favicon-as-image.html [ Failure ]
+
 ### inspector-protocol/
 crbug.com/591099 inspector-protocol/layout-fonts/languages-emoji-rare-glyphs.js [ Failure ]
 
+### media/
+crbug.com/591099 media/controls-layout-direction.html [ Failure ]
+crbug.com/591099 media/media-controls-clone.html [ Failure ]
+
 # Newline painting difference with LayoutNG disabled.
 crbug.com/591099 external/wpt/forced-colors-mode/forced-colors-mode-14.html [ Failure ]
 crbug.com/591099 external/wpt/forced-colors-mode/forced-colors-mode-15.html [ Failure ]
@@ -409,12 +452,29 @@
 ### virtual/controls-refresh-hc/
 virtual/controls-refresh-hc/* [ Skip ]
 
+### virtual/dark-color-scheme/fast/forms/color-scheme/href/
+crbug.com/591099 virtual/dark-color-scheme/fast/forms/color-scheme/href/href-appearance-basic.html [ Failure ]
+
+### virtual/dark-color-scheme/media/
+crbug.com/591099 virtual/dark-color-scheme/media/audio-controls-rendering.html [ Failure ]
+crbug.com/591099 virtual/dark-color-scheme/media/audio-focus-ring.html [ Failure ]
+
+### virtual/exotic-color-space/images/
+crbug.com/591099 virtual/exotic-color-space/images/favicon-as-image.html [ Failure ]
+
+### virtual/gpu-rasterization/images/
+crbug.com/591099 virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Slow Failure ]
+crbug.com/591099 virtual/gpu-rasterization/images/favicon-as-image.html [ Failure ]
+
 ### virtual/layout_ng_block_frag/
 virtual/layout_ng_block_frag/* [ Skip ]
 
 ### virtual/layout_ng_fragment_traversal/
 virtual/layout_ng_fragment_traversal/* [ Skip ]
 
+### virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/
+crbug.com/591099 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-descendants-001.html [ Failure ]
+
 ### virtual/layout_ng_printing/
 virtual/layout_ng_printing/* [ Skip ]
 
@@ -673,6 +733,9 @@
 ### virtual/stable/compositing/filters/
 crbug.com/591099 virtual/stable/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow.html [ Failure ]
 
+### webcodecs/
+crbug.com/591099 webcodecs/basic_video_encoding.html [ Failure ]
+
 # broken by https://chromium-review.googlesource.com/c/chromium/src/+/2392444
 crbug.com/958381 external/wpt/css/css-flexbox/table-as-item-wide-content.html [ Failure ]
 crbug.com/958381 external/wpt/css/css-flexbox/table-as-item-fixed-min-width.html [ Failure ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index bf76c91..1d5824d9 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -396,10 +396,6 @@
 crbug.com/1076121 external/wpt/css/css-images/image-orientation/image-orientation-border-image.html [ Failure ]
 crbug.com/1076121 external/wpt/css/css-images/image-orientation/image-orientation-background-image.html [ Failure ]
 
-# Cross origin failures
-crbug.com/1110330 external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin.html [ Failure ]
-crbug.com/1110330 external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin-canvas.html [ Failure ]
-
 crbug.com/1042783 external/wpt/css/css-backgrounds/background-size/background-size-near-zero-png.html [ Failure ]
 crbug.com/1042783 external/wpt/css/css-backgrounds/background-size/background-size-near-zero-svg.html [ Failure ]
 
@@ -1634,7 +1630,6 @@
 crbug.com/1024331 external/wpt/css/css-text/hyphens/hyphens-out-of-flow-001.html [ Failure ]
 crbug.com/1024331 external/wpt/css/css-text/hyphens/hyphens-out-of-flow-002.html [ Failure ]
 crbug.com/1140728 external/wpt/css/css-text/hyphens/hyphens-span-002.html [ Failure ]
-crbug.com/870219 virtual/text-antialias/hyphens/hyphens-auto-mock.html [ Failure ]
 crbug.com/1139693 virtual/text-antialias/hyphens/midword-break-priority.html [ Failure ]
 
 crbug.com/626703 external/wpt/css/css-text/letter-spacing/letter-spacing-control-chars-001.html [ Failure ]
@@ -4224,10 +4219,6 @@
 
 crbug.com/664450 http/tests/devtools/console/console-on-animation-worklet.js [ Skip ]
 
-# Disabled to land DevTools changes https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2436646
-crbug.com/1133060 http/tests/devtools/console/console-revoke-error.js [ Pass Failure ]
-crbug.com/1133060 http/tests/devtools/console/console-revoke-error-in-worker.js [ Pass Failure ]
-
 crbug.com/826419 external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-remove-track-inband.html [ Skip ]
 
 crbug.com/825798 external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-non-snap-to-lines.html [ Failure ]
@@ -6416,3 +6407,6 @@
 crbug.com/1123116 external/wpt/permissions-policy/permissions-policy-frame-policy-disallowed-for-all.https.sub.html [ Failure ]
 crbug.com/1140329 http/tests/devtools/network/network-filter-service-worker.js [ Pass Timeout Failure ]
 crbug.com/1140329 virtual/threaded/external/wpt/web-animations/timing-model/animations/updating-the-finished-state.html [ Pass Failure Timeout ]
+
+#Sheriff 2020-10-21
+crbug.com/1141206 scrollbars/overflow-scrollbar-combinations.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/WebDriverExpectations b/third_party/blink/web_tests/WebDriverExpectations
index 3d91586..a0bc811 100644
--- a/third_party/blink/web_tests/WebDriverExpectations
+++ b/third_party/blink/web_tests/WebDriverExpectations
@@ -31,6 +31,7 @@
 crbug.com/977228 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_default[alert-None] [ Failure Pass ]
 crbug.com/977228 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure Pass ]
 crbug.com/977228 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure Pass ]
+crbug.com/977228 [ Linux ] external/wpt/webdriver/tests/maximize_window/maximize.py>>test_fully_exit_fullscreen [ Failure Pass ]
 crbug.com/977228 [ Linux ] external/wpt/webdriver/tests/maximize_window/maximize.py>>test_restore_the_window [ Failure Pass ]
 crbug.com/977228 [ Linux ] external/wpt/webdriver/tests/minimize_window/minimize.py>>test_minimize [ Failure Pass ]
 crbug.com/977228 [ Linux ] external/wpt/webdriver/tests/minimize_window/minimize.py>>test_minimize_twice_is_idempotent [ Failure Pass ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/svg-root-as-flex-item-006.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/svg-root-as-flex-item-006.html
new file mode 100644
index 0000000..73406c8
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/svg-root-as-flex-item-006.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>SVG root as flex item</title>
+<link rel="author" title="David Grogan" href="mailto:dgrogan@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#algo-main-item" title="Part E">
+<link rel="help" href="https://crbug.com/965672">
+<meta name="assert" content="When SVG has aspect ratio and no intrinsic height its flex-basis is available width * ratio, not 150px, when in a column flexbox." />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+The test passes if you see a 600x300 blue rectangle.
+
+<div style="display: flex; flex-direction: column; width: 600px;">
+  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" data-expected-width=600 data-expected-height=300>
+    <rect x="0" y="0" width="200" height="100" fill="blue" />
+  </svg>
+</div>
+
+<script>
+checkLayout('svg');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin-canvas.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin-canvas.html
index 4d370e8e..d6123be 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin-canvas.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin-canvas.html
@@ -6,13 +6,13 @@
 <script src=/common/get-host-info.sub.js></script>
 <link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org">
 <link rel="help" href="https://github.com/w3c/csswg-drafts/issues/5165">
-<link rel="match" href="reference/image-orientation-none-cross-origin-ref.html">
+<link rel="match" href="reference/image-orientation-none-cross-origin-canvas-ref.html">
 <meta name=fuzzy content="10;100">
 <style>
     img {display: none}
     canvas {
-        width: 100px;
-        height: 100px;
+        width: 20px;
+        height: 20px;
         margin: 10px;
     }
 </style>
@@ -36,13 +36,13 @@
 
     window.onload = () => {
         const images = [
-            createImage({cors: true, src: src2, orientation: 'from-image', shouldBeRotated: true}),
-            createImage({cors: true, src: src2, orientation: 'none', shouldBeRotated: true}),
-            createImage({cors: false, src: src2, orientation: 'from-image', shouldBeRotated: true}),
             createImage({cors: true, src: src1, orientation: 'from-image', shouldBeRotated: false}),
             createImage({cors: true, src: src1, orientation: 'none', shouldBeRotated: false}),
+            createImage({cors: true, src: src2, orientation: 'from-image', shouldBeRotated: true}),
+            createImage({cors: true, src: src2, orientation: 'none', shouldBeRotated: true}),
             createImage({cors: false, src: src1, orientation: 'from-image', shouldBeRotated: false}),
             createImage({cors: false, src: src1, orientation: 'none', shouldBeRotated: false}),
+            createImage({cors: false, src: src2, orientation: 'from-image', shouldBeRotated: true}),
             createImage({cors: false, src: src2, orientation: 'none', shouldBeRotated: false}),
         ]
 
@@ -51,13 +51,16 @@
         images.forEach(image => {
             const canvas = document.createElement('canvas')
             canvas.width = canvas.height = dimension
+            // The source of image-orientation preference for canvas drawImage
+            // is currently not standardized.
+            // See https://github.com/w3c/csswg-drafts/issues/4666
+            canvas.style.imageOrientation = image.style.imageOrientation
+            document.body.appendChild(canvas)
             const ctx = canvas.getContext('2d')
             const sx = image.dataset.shouldBeRotated === 'true' ? image.width * .8 : 0
             const sy = image.dataset.shouldBeRotated === 'true' ? image.height * .8 : 0
             ctx.drawImage(image, sx, sy, 1, 1, 0, 0, dimension, dimension)
-            document.body.appendChild(canvas)
         })
-
     }
 
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/reference/image-orientation-none-cross-origin-canvas-ref.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/reference/image-orientation-none-cross-origin-canvas-ref.html
index 4f9bc74..1bd6910 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/reference/image-orientation-none-cross-origin-canvas-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/reference/image-orientation-none-cross-origin-canvas-ref.html
@@ -13,11 +13,10 @@
     }
     img {display: none}
     canvas {
-        width: 100px;
-        height: 100px;
+        width: 20px;
+        height: 20px;
         margin: 10px;
     }
-    .no-orient { image-orientation: none; }
 </style>
 <body>
     <p>You should see 8 green rectangles, no red.</p>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/crashtests/trailing-space-with-cr-crash.html b/third_party/blink/web_tests/external/wpt/css/css-text/crashtests/trailing-space-with-cr-crash.html
new file mode 100644
index 0000000..48c223e3
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/crashtests/trailing-space-with-cr-crash.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-text-3/#white-space-property">
+<link rel="author" title="Koji Ishii" href="mailto:kojii@chromium.org">
+<style>
+div {
+  width: 100px;
+  white-space: pre-wrap;
+  word-break: break-word;
+  border: 1px solid blue;
+}
+.atomic {
+  display: inline-block;
+  width: 99px;
+  height: 1em;
+  background: orange;
+}
+</style>
+<div><span class="atomic"></span>&#x0D; <span class="atomic"></span></div>
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/virtual_authenticator.html b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/virtual_authenticator.html
index 204c956..04c1471 100644
--- a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/virtual_authenticator.html
+++ b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/virtual_authenticator.html
@@ -8,6 +8,13 @@
 <script>
 "use strict";
 
+// Encodes |data| into a base64url string. There is no '=' padding, and the
+// characters '-' and '_' must be used instead of '+' and '/', respectively.
+function base64urlEncode(data) {
+  let result = btoa(data);
+  return result.replaceAll("=", "").replaceAll("+", "-").replaceAll("/", "_");
+}
+
 // The example attestation private key from the U2F spec at
 // https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html#registration-example
 // PKCS.8 encoded without encryption, as a base64url string.
@@ -15,7 +22,7 @@
     "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q"
   + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU"
   + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB";
-let credential_id = btoa("cred-1");
+let credential_id = base64urlEncode("cred-1");
 let credential = {
   credentialId: credential_id,
   rpId: window.location.hostname,
@@ -58,7 +65,7 @@
 promise_test(async t => {
   let credential1 = credential;
   let credential2 =
-    Object.assign({}, credential, {credentialId: btoa("cred-2")});
+    Object.assign({}, credential, {credentialId: base64urlEncode("cred-2")});
   await test_driver.add_credential(authenticator_id, credential1);
   await test_driver.add_credential(authenticator_id, credential2);
 
diff --git a/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-must-fail-if-unsupported.js b/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-must-fail-if-unsupported.js
new file mode 100644
index 0000000..69c65f6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-must-fail-if-unsupported.js
@@ -0,0 +1,18 @@
+importScripts("/resources/testharness.js");
+
+test(t => {
+  // The Window test html conditionally fetches and runs these tests only if the
+  // implementation does not have a true-valued static
+  // canConstructInDedicatedWorker property on MediaSource in the Window
+  // context. So, the implementation must agree on lack of support here in the
+  // dedicated worker context.
+
+  // Ensure we're executing in a dedicated worker context.
+  assert_true(self instanceof DedicatedWorkerGlobalScope, "self instanceof DedicatedWorkerGlobalScope");
+  assert_true(self.MediaSource === undefined, "MediaSource is undefined in DedicatedWorker");
+  assert_throws_js(ReferenceError,
+                   function() { var ms = new MediaSource(); },
+                   "MediaSource construction in DedicatedWorker throws exception");
+}, "MediaSource construction in DedicatedWorker context must fail if Window context did not claim MSE supported in DedicatedWorker");
+
+done();
diff --git a/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-objecturl.html b/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-objecturl.html
index 382a9a4f..378bd9f 100644
--- a/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-objecturl.html
+++ b/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-objecturl.html
@@ -5,9 +5,13 @@
 <script src="/resources/testharnessreport.js"></script>
 <script>
 
-async_test((t) => {
+async_test(t => {
+  // Fail fast if MSE-in-Workers is not supported.
+  assert_true(MediaSource.hasOwnProperty("canConstructInDedicatedWorker"), "MediaSource hasOwnProperty 'canConstructInDedicatedWorker'");
+  assert_true(MediaSource.canConstructInDedicatedWorker, "MediaSource.canConstructInDedicatedWorker");
+
   let worker = new Worker("mediasource-worker-util.js");
-  worker.onmessage = t.step_func((e) => {
+  worker.onmessage = t.step_func(e => {
     if (e.data.substr(0,6) == "Error:") {
       assert_unreached("Worker error: " + e.data);
     } else {
@@ -17,11 +21,18 @@
       t.done();
     }
   });
-}, "Test main context revocation of worker MediaSource object URL");
+}, "Test main context revocation of DedicatedWorker MediaSource object URL");
 
-// Run some tests directly in another dedicated worker and get their results
-// merged into those from this page.
-fetch_tests_from_worker(new Worker("mediasource-worker-objecturl.js"));
+if (MediaSource.hasOwnProperty("canConstructInDedicatedWorker") && MediaSource.canConstructInDedicatedWorker === true) {
+  // If implementation claims support for MSE-in-Workers, then fetch and run
+  // some tests directly in another dedicated worker and get their results
+  // merged into those from this page.
+  fetch_tests_from_worker(new Worker("mediasource-worker-objecturl.js"));
+} else {
+  // Otherwise, fetch and run a test that verifies lack of support of
+  // MediaSource construction in another dedicated worker.
+  fetch_tests_from_worker(new Worker("mediasource-worker-must-fail-if-unsupported.js"));
+}
 
 </script>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-objecturl.js b/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-objecturl.js
index db47da0..9a7195f 100644
--- a/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-objecturl.js
+++ b/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-objecturl.js
@@ -1,23 +1,35 @@
 importScripts("/resources/testharness.js");
 
-test((t) => {
+test(t => {
+  // The Window test html conditionally fetches and runs these tests only if the
+  // implementation exposes a true-valued static canConstructInDedicatedWorker
+  // attribute on MediaSource in the Window context. So, the implementation must
+  // agree on support here in the dedicated worker context.
+
+  // Ensure we're executing in a dedicated worker context.
+  assert_true(self instanceof DedicatedWorkerGlobalScope, "self instanceof DedicatedWorkerGlobalScope");
+  assert_true(MediaSource.hasOwnProperty("canConstructInDedicatedWorker", "DedicatedWorker MediaSource hasOwnProperty 'canConstructInDedicatedWorker'"));
+  assert_true(MediaSource.canConstructInDedicatedWorker, "DedicatedWorker MediaSource.canConstructInDedicatedWorker");
+}, "MediaSource in DedicatedWorker context must have true-valued canConstructInDedicatedWorker if Window context had it");
+
+test(t => {
   const ms = new MediaSource();
   assert_equals(ms.readyState, "closed");
-}, "MediaSource construction succeeds with initial closed readyState in dedicated worker");
+}, "MediaSource construction succeeds with initial closed readyState in DedicatedWorker");
 
-test((t) => {
+test(t => {
   const ms = new MediaSource();
   const url = URL.createObjectURL(ms);
   assert_true(url != null);
   assert_true(url.match(/^blob:.+/) != null);
-}, "URL.createObjectURL(mediaSource) in dedicated worker returns a Blob URI");
+}, "URL.createObjectURL(mediaSource) in DedicatedWorker returns a Blob URI");
 
-test((t) => {
+test(t => {
   const ms = new MediaSource();
   const url1 = URL.createObjectURL(ms);
   const url2 = URL.createObjectURL(ms);
   URL.revokeObjectURL(url1);
   URL.revokeObjectURL(url2);
-}, "URL.revokeObjectURL(mediaSource) in dedicated worker with two url for same MediaSource");
+}, "URL.revokeObjectURL(mediaSource) in DedicatedWorker with two url for same MediaSource");
 
 done();
diff --git a/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-play-terminate-worker.html b/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-play-terminate-worker.html
index 69f2cba..138e9ec 100644
--- a/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-play-terminate-worker.html
+++ b/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-play-terminate-worker.html
@@ -18,13 +18,10 @@
 }
 
 function startWorkerAndTerminateWorker(test, when_to_start_timeouts, timeouts_to_await) {
-  // TODO(https://crbug.com/878133): Enable main-thread feature detection of
-  // whether or not the implementation supports MSE-in-Workers, and fail the
-  // test rapidly here rather than flakily pass/failing the test on those
-  // implementations. If the timeout occurs near to when the worker's report
-  // of lack of MSE support reaches the main thread, then the test could
-  // pass in some cases (when timeout occurs prior to handling that error)
-  // and fail in others (when worker.onerror dispatch occurs first).
+  // Fail fast if MSE-in-Workers is not supported.
+  assert_true(MediaSource.hasOwnProperty("canConstructInDedicatedWorker"), "MediaSource hasOwnProperty 'canConstructInDedicatedWorker'");
+  assert_true(MediaSource.canConstructInDedicatedWorker, "MediaSource.canConstructInDedicatedWorker");
+
   const worker = new Worker("mediasource-worker-util.js");
   worker.onerror = test.unreached_func("worker error");
 
@@ -46,7 +43,7 @@
     terminateWorkerAfterMultipleSetTimeouts(test, worker, timeouts_to_await);
   }
 
-  worker.onmessage = test.step_func((e) => {
+  worker.onmessage = test.step_func(e => {
     if (e.data.substr(0,6) == "Error:") {
       assert_unreached("Worker error: " + e.data);
     } else {
@@ -68,9 +65,9 @@
   });
 }
 
-[ "before setting src", "after setting src", "after first ended event" ].forEach((when) => {
+[ "before setting src", "after setting src", "after first ended event" ].forEach(when => {
   for (let timeouts = 0; timeouts < 10; ++timeouts) {
-    async_test((test) => { startWorkerAndTerminateWorker(test, when, timeouts); },
+    async_test(test => { startWorkerAndTerminateWorker(test, when, timeouts); },
         "Test worker MediaSource termination after at least " + timeouts +
           " main thread setTimeouts, starting counting " + when);
   }
diff --git a/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-play.html b/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-play.html
index 200f8a8..336cb8f 100644
--- a/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-play.html
+++ b/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-play.html
@@ -6,15 +6,19 @@
 <body>
 <script>
 
-async_test((t) => {
-  const video = document.createElement('video');
+async_test(t => {
+  // Fail fast if MSE-in-Workers is not supported.
+  assert_true(MediaSource.hasOwnProperty("canConstructInDedicatedWorker"), "MediaSource hasOwnProperty 'canConstructInDedicatedWorker'");
+  assert_true(MediaSource.canConstructInDedicatedWorker, "MediaSource.canConstructInDedicatedWorker");
+
+  const video = document.createElement("video");
   document.body.appendChild(video);
   video.onerror = t.unreached_func("video element error");
   video.onended = t.step_func_done();
 
   let worker = new Worker("mediasource-worker-util.js");
   worker.onerror = t.unreached_func("worker error");
-  worker.onmessage = t.step_func((e) => {
+  worker.onmessage = t.step_func(e => {
     if (e.data.substr(0,6) == "Error:") {
       assert_unreached("Worker error: " + e.data);
     } else {
diff --git a/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-util.js b/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-util.js
index 4cee486..7688a40 100644
--- a/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-util.js
+++ b/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-util.js
@@ -33,8 +33,8 @@
   return new Promise((resolve, reject) => {
     let request = new XMLHttpRequest();
     request.open("GET", url, true);
-    request.responseType = 'arraybuffer';
-    request.onerror = (event) => { reject(event); };
+    request.responseType = "arraybuffer";
+    request.onerror = event => { reject(event); };
     request.onload = () => {
       if (request.status != 200) {
         reject("Unexpected loadData_ status code : " + request.status);
@@ -76,6 +76,6 @@
       mediaSource.endOfStream();
     };
   };
-  mediaLoad.then( (mediaData) => { sourceBuffer.appendBuffer(mediaData); },
-                  (err) => { postMessage("Error: " + err) } );
+  mediaLoad.then( mediaData => { sourceBuffer.appendBuffer(mediaData); },
+                  err => { postMessage("Error: " + err) } );
 }, { once : true });
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/registration-scope-module-static-import.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/registration-scope-module-static-import.https-expected.txt
new file mode 100644
index 0000000..7a29e1e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/registration-scope-module-static-import.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+PASS imported-module-script.js works when used as top-level
+FAIL static imports to outside path restriction should be allowed promise_test: Unhandled rejection with value: object "AbortError: Failed to register a ServiceWorker for scope ('https://web-platform.test:8444/service-workers/service-worker/resources/scope1/') with script ('https://web-platform.test:8444/service-workers/service-worker/resources/scope1/module-worker-importing-scope2.js'): ServiceWorker cannot be started"
+FAIL static imports redirecting to outside path restriction should be allowed promise_test: Unhandled rejection with value: object "AbortError: Failed to register a ServiceWorker for scope ('https://web-platform.test:8444/service-workers/service-worker/resources/scope1/') with script ('https://web-platform.test:8444/service-workers/service-worker/resources/scope1/module-worker-importing-redirect-to-scope2.js'): ServiceWorker cannot be started"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/registration-scope-module-static-import.https.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/registration-scope-module-static-import.https.html
new file mode 100644
index 0000000..5c75295
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/registration-scope-module-static-import.https.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>Service Worker: Static imports from module top-level scripts shouldn't be affected by the service worker script path restriction</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/test-helpers.sub.js"></script>
+<script>
+// https://w3c.github.io/ServiceWorker/#path-restriction
+// is applied to top-level scripts in
+// https://w3c.github.io/ServiceWorker/#update-algorithm
+// but not to submodules imported from top-level scripts.
+async function runTest(t, script, scope) {
+  const script_url = new URL(script, location.href);
+  await service_worker_unregister(t, scope);
+  const registration = await
+      navigator.serviceWorker.register(script, {type: 'module'});
+  t.add_cleanup(_ => registration.unregister());
+  const msg = await new Promise(resolve => {
+    registration.installing.postMessage('ping');
+    navigator.serviceWorker.onmessage = resolve;
+  });
+  assert_equals(msg.data, 'pong');
+}
+
+promise_test(async t => {
+    await runTest(t,
+        'resources/scope2/imported-module-script.js',
+        'resources/scope2/');
+  }, 'imported-module-script.js works when used as top-level');
+
+promise_test(async t => {
+    await runTest(t,
+        'resources/scope1/module-worker-importing-scope2.js',
+        'resources/scope1/');
+  }, 'static imports to outside path restriction should be allowed');
+
+promise_test(async t => {
+    await runTest(t,
+       'resources/scope1/module-worker-importing-redirect-to-scope2.js',
+       'resources/scope1/');
+  }, 'static imports redirecting to outside path restriction should be allowed');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/scope1/module-worker-importing-redirect-to-scope2.js b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/scope1/module-worker-importing-redirect-to-scope2.js
new file mode 100644
index 0000000..ae681ba
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/scope1/module-worker-importing-redirect-to-scope2.js
@@ -0,0 +1 @@
+import * as module from './redirect.py?Redirect=/service-workers/service-worker/resources/scope2/imported-module-script.js';
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/scope1/module-worker-importing-scope2.js b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/scope1/module-worker-importing-scope2.js
new file mode 100644
index 0000000..e285052
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/scope1/module-worker-importing-scope2.js
@@ -0,0 +1 @@
+import * as module from '../scope2/imported-module-script.js';
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/scope2/imported-module-script.js b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/scope2/imported-module-script.js
new file mode 100644
index 0000000..a18e704
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/scope2/imported-module-script.js
@@ -0,0 +1,4 @@
+export const imported = 'A module script.';
+onmessage = msg => {
+    msg.source.postMessage('pong');
+};
diff --git a/third_party/blink/web_tests/external/wpt/streams/idlharness.any-expected.txt b/third_party/blink/web_tests/external/wpt/streams/idlharness.any-expected.txt
index 542c62c..bf60a89 100644
--- a/third_party/blink/web_tests/external/wpt/streams/idlharness.any-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/streams/idlharness.any-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 224 tests; 126 PASS, 98 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 224 tests; 139 PASS, 85 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS idl_test validation
 PASS ReadableStreamDefaultReader includes ReadableStreamGenericReader: member names are unique
@@ -124,10 +124,10 @@
 PASS WritableStream interface: existence and properties of interface prototype object
 PASS WritableStream interface: existence and properties of interface prototype object's "constructor" property
 PASS WritableStream interface: existence and properties of interface prototype object's @@unscopables property
-FAIL WritableStream interface: attribute locked assert_true: property should be enumerable expected true got false
-FAIL WritableStream interface: operation abort(optional any) assert_true: property should be enumerable expected true got false
-FAIL WritableStream interface: operation close() assert_true: property should be enumerable expected true got false
-FAIL WritableStream interface: operation getWriter() assert_true: property should be enumerable expected true got false
+PASS WritableStream interface: attribute locked
+PASS WritableStream interface: operation abort(optional any)
+PASS WritableStream interface: operation close()
+PASS WritableStream interface: operation getWriter()
 PASS WritableStream must be primary interface of new WritableStream()
 PASS Stringification of new WritableStream()
 PASS WritableStream interface: new WritableStream() must inherit property "locked" with the proper type
@@ -141,13 +141,13 @@
 PASS WritableStreamDefaultWriter interface: existence and properties of interface prototype object
 PASS WritableStreamDefaultWriter interface: existence and properties of interface prototype object's "constructor" property
 PASS WritableStreamDefaultWriter interface: existence and properties of interface prototype object's @@unscopables property
-FAIL WritableStreamDefaultWriter interface: attribute closed assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: attribute desiredSize assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: attribute ready assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: operation abort(optional any) assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: operation close() assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: operation releaseLock() assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: operation write(optional any) assert_true: property should be enumerable expected true got false
+PASS WritableStreamDefaultWriter interface: attribute closed
+PASS WritableStreamDefaultWriter interface: attribute desiredSize
+PASS WritableStreamDefaultWriter interface: attribute ready
+PASS WritableStreamDefaultWriter interface: operation abort(optional any)
+PASS WritableStreamDefaultWriter interface: operation close()
+PASS WritableStreamDefaultWriter interface: operation releaseLock()
+PASS WritableStreamDefaultWriter interface: operation write(optional any)
 PASS WritableStreamDefaultWriter must be primary interface of (new WritableStream()).getWriter()
 PASS Stringification of (new WritableStream()).getWriter()
 PASS WritableStreamDefaultWriter interface: (new WritableStream()).getWriter() must inherit property "closed" with the proper type
@@ -176,8 +176,8 @@
 PASS TransformStream interface: existence and properties of interface prototype object
 PASS TransformStream interface: existence and properties of interface prototype object's "constructor" property
 PASS TransformStream interface: existence and properties of interface prototype object's @@unscopables property
-FAIL TransformStream interface: attribute readable assert_true: property should be enumerable expected true got false
-FAIL TransformStream interface: attribute writable assert_true: property should be enumerable expected true got false
+PASS TransformStream interface: attribute readable
+PASS TransformStream interface: attribute writable
 PASS TransformStream must be primary interface of new TransformStream()
 PASS Stringification of new TransformStream()
 PASS TransformStream interface: new TransformStream() must inherit property "readable" with the proper type
diff --git a/third_party/blink/web_tests/external/wpt/streams/idlharness.any.serviceworker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/idlharness.any.serviceworker-expected.txt
index 542c62c..bf60a89 100644
--- a/third_party/blink/web_tests/external/wpt/streams/idlharness.any.serviceworker-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/streams/idlharness.any.serviceworker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 224 tests; 126 PASS, 98 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 224 tests; 139 PASS, 85 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS idl_test validation
 PASS ReadableStreamDefaultReader includes ReadableStreamGenericReader: member names are unique
@@ -124,10 +124,10 @@
 PASS WritableStream interface: existence and properties of interface prototype object
 PASS WritableStream interface: existence and properties of interface prototype object's "constructor" property
 PASS WritableStream interface: existence and properties of interface prototype object's @@unscopables property
-FAIL WritableStream interface: attribute locked assert_true: property should be enumerable expected true got false
-FAIL WritableStream interface: operation abort(optional any) assert_true: property should be enumerable expected true got false
-FAIL WritableStream interface: operation close() assert_true: property should be enumerable expected true got false
-FAIL WritableStream interface: operation getWriter() assert_true: property should be enumerable expected true got false
+PASS WritableStream interface: attribute locked
+PASS WritableStream interface: operation abort(optional any)
+PASS WritableStream interface: operation close()
+PASS WritableStream interface: operation getWriter()
 PASS WritableStream must be primary interface of new WritableStream()
 PASS Stringification of new WritableStream()
 PASS WritableStream interface: new WritableStream() must inherit property "locked" with the proper type
@@ -141,13 +141,13 @@
 PASS WritableStreamDefaultWriter interface: existence and properties of interface prototype object
 PASS WritableStreamDefaultWriter interface: existence and properties of interface prototype object's "constructor" property
 PASS WritableStreamDefaultWriter interface: existence and properties of interface prototype object's @@unscopables property
-FAIL WritableStreamDefaultWriter interface: attribute closed assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: attribute desiredSize assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: attribute ready assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: operation abort(optional any) assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: operation close() assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: operation releaseLock() assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: operation write(optional any) assert_true: property should be enumerable expected true got false
+PASS WritableStreamDefaultWriter interface: attribute closed
+PASS WritableStreamDefaultWriter interface: attribute desiredSize
+PASS WritableStreamDefaultWriter interface: attribute ready
+PASS WritableStreamDefaultWriter interface: operation abort(optional any)
+PASS WritableStreamDefaultWriter interface: operation close()
+PASS WritableStreamDefaultWriter interface: operation releaseLock()
+PASS WritableStreamDefaultWriter interface: operation write(optional any)
 PASS WritableStreamDefaultWriter must be primary interface of (new WritableStream()).getWriter()
 PASS Stringification of (new WritableStream()).getWriter()
 PASS WritableStreamDefaultWriter interface: (new WritableStream()).getWriter() must inherit property "closed" with the proper type
@@ -176,8 +176,8 @@
 PASS TransformStream interface: existence and properties of interface prototype object
 PASS TransformStream interface: existence and properties of interface prototype object's "constructor" property
 PASS TransformStream interface: existence and properties of interface prototype object's @@unscopables property
-FAIL TransformStream interface: attribute readable assert_true: property should be enumerable expected true got false
-FAIL TransformStream interface: attribute writable assert_true: property should be enumerable expected true got false
+PASS TransformStream interface: attribute readable
+PASS TransformStream interface: attribute writable
 PASS TransformStream must be primary interface of new TransformStream()
 PASS Stringification of new TransformStream()
 PASS TransformStream interface: new TransformStream() must inherit property "readable" with the proper type
diff --git a/third_party/blink/web_tests/external/wpt/streams/idlharness.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/idlharness.any.sharedworker-expected.txt
index 542c62c..bf60a89 100644
--- a/third_party/blink/web_tests/external/wpt/streams/idlharness.any.sharedworker-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/streams/idlharness.any.sharedworker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 224 tests; 126 PASS, 98 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 224 tests; 139 PASS, 85 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS idl_test validation
 PASS ReadableStreamDefaultReader includes ReadableStreamGenericReader: member names are unique
@@ -124,10 +124,10 @@
 PASS WritableStream interface: existence and properties of interface prototype object
 PASS WritableStream interface: existence and properties of interface prototype object's "constructor" property
 PASS WritableStream interface: existence and properties of interface prototype object's @@unscopables property
-FAIL WritableStream interface: attribute locked assert_true: property should be enumerable expected true got false
-FAIL WritableStream interface: operation abort(optional any) assert_true: property should be enumerable expected true got false
-FAIL WritableStream interface: operation close() assert_true: property should be enumerable expected true got false
-FAIL WritableStream interface: operation getWriter() assert_true: property should be enumerable expected true got false
+PASS WritableStream interface: attribute locked
+PASS WritableStream interface: operation abort(optional any)
+PASS WritableStream interface: operation close()
+PASS WritableStream interface: operation getWriter()
 PASS WritableStream must be primary interface of new WritableStream()
 PASS Stringification of new WritableStream()
 PASS WritableStream interface: new WritableStream() must inherit property "locked" with the proper type
@@ -141,13 +141,13 @@
 PASS WritableStreamDefaultWriter interface: existence and properties of interface prototype object
 PASS WritableStreamDefaultWriter interface: existence and properties of interface prototype object's "constructor" property
 PASS WritableStreamDefaultWriter interface: existence and properties of interface prototype object's @@unscopables property
-FAIL WritableStreamDefaultWriter interface: attribute closed assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: attribute desiredSize assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: attribute ready assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: operation abort(optional any) assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: operation close() assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: operation releaseLock() assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: operation write(optional any) assert_true: property should be enumerable expected true got false
+PASS WritableStreamDefaultWriter interface: attribute closed
+PASS WritableStreamDefaultWriter interface: attribute desiredSize
+PASS WritableStreamDefaultWriter interface: attribute ready
+PASS WritableStreamDefaultWriter interface: operation abort(optional any)
+PASS WritableStreamDefaultWriter interface: operation close()
+PASS WritableStreamDefaultWriter interface: operation releaseLock()
+PASS WritableStreamDefaultWriter interface: operation write(optional any)
 PASS WritableStreamDefaultWriter must be primary interface of (new WritableStream()).getWriter()
 PASS Stringification of (new WritableStream()).getWriter()
 PASS WritableStreamDefaultWriter interface: (new WritableStream()).getWriter() must inherit property "closed" with the proper type
@@ -176,8 +176,8 @@
 PASS TransformStream interface: existence and properties of interface prototype object
 PASS TransformStream interface: existence and properties of interface prototype object's "constructor" property
 PASS TransformStream interface: existence and properties of interface prototype object's @@unscopables property
-FAIL TransformStream interface: attribute readable assert_true: property should be enumerable expected true got false
-FAIL TransformStream interface: attribute writable assert_true: property should be enumerable expected true got false
+PASS TransformStream interface: attribute readable
+PASS TransformStream interface: attribute writable
 PASS TransformStream must be primary interface of new TransformStream()
 PASS Stringification of new TransformStream()
 PASS TransformStream interface: new TransformStream() must inherit property "readable" with the proper type
diff --git a/third_party/blink/web_tests/external/wpt/streams/idlharness.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/idlharness.any.worker-expected.txt
index 542c62c..bf60a89 100644
--- a/third_party/blink/web_tests/external/wpt/streams/idlharness.any.worker-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/streams/idlharness.any.worker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 224 tests; 126 PASS, 98 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 224 tests; 139 PASS, 85 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS idl_test validation
 PASS ReadableStreamDefaultReader includes ReadableStreamGenericReader: member names are unique
@@ -124,10 +124,10 @@
 PASS WritableStream interface: existence and properties of interface prototype object
 PASS WritableStream interface: existence and properties of interface prototype object's "constructor" property
 PASS WritableStream interface: existence and properties of interface prototype object's @@unscopables property
-FAIL WritableStream interface: attribute locked assert_true: property should be enumerable expected true got false
-FAIL WritableStream interface: operation abort(optional any) assert_true: property should be enumerable expected true got false
-FAIL WritableStream interface: operation close() assert_true: property should be enumerable expected true got false
-FAIL WritableStream interface: operation getWriter() assert_true: property should be enumerable expected true got false
+PASS WritableStream interface: attribute locked
+PASS WritableStream interface: operation abort(optional any)
+PASS WritableStream interface: operation close()
+PASS WritableStream interface: operation getWriter()
 PASS WritableStream must be primary interface of new WritableStream()
 PASS Stringification of new WritableStream()
 PASS WritableStream interface: new WritableStream() must inherit property "locked" with the proper type
@@ -141,13 +141,13 @@
 PASS WritableStreamDefaultWriter interface: existence and properties of interface prototype object
 PASS WritableStreamDefaultWriter interface: existence and properties of interface prototype object's "constructor" property
 PASS WritableStreamDefaultWriter interface: existence and properties of interface prototype object's @@unscopables property
-FAIL WritableStreamDefaultWriter interface: attribute closed assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: attribute desiredSize assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: attribute ready assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: operation abort(optional any) assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: operation close() assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: operation releaseLock() assert_true: property should be enumerable expected true got false
-FAIL WritableStreamDefaultWriter interface: operation write(optional any) assert_true: property should be enumerable expected true got false
+PASS WritableStreamDefaultWriter interface: attribute closed
+PASS WritableStreamDefaultWriter interface: attribute desiredSize
+PASS WritableStreamDefaultWriter interface: attribute ready
+PASS WritableStreamDefaultWriter interface: operation abort(optional any)
+PASS WritableStreamDefaultWriter interface: operation close()
+PASS WritableStreamDefaultWriter interface: operation releaseLock()
+PASS WritableStreamDefaultWriter interface: operation write(optional any)
 PASS WritableStreamDefaultWriter must be primary interface of (new WritableStream()).getWriter()
 PASS Stringification of (new WritableStream()).getWriter()
 PASS WritableStreamDefaultWriter interface: (new WritableStream()).getWriter() must inherit property "closed" with the proper type
@@ -176,8 +176,8 @@
 PASS TransformStream interface: existence and properties of interface prototype object
 PASS TransformStream interface: existence and properties of interface prototype object's "constructor" property
 PASS TransformStream interface: existence and properties of interface prototype object's @@unscopables property
-FAIL TransformStream interface: attribute readable assert_true: property should be enumerable expected true got false
-FAIL TransformStream interface: attribute writable assert_true: property should be enumerable expected true got false
+PASS TransformStream interface: attribute readable
+PASS TransformStream interface: attribute writable
 PASS TransformStream must be primary interface of new TransformStream()
 PASS Stringification of new TransformStream()
 PASS TransformStream interface: new TransformStream() must inherit property "readable" with the proper type
diff --git a/third_party/blink/web_tests/fast/css/containment/change-text-node-data-nowrap-expected.html b/third_party/blink/web_tests/fast/css/containment/change-text-node-data-nowrap-expected.html
index 0b5e76bd..d2120c5b 100644
--- a/third_party/blink/web_tests/fast/css/containment/change-text-node-data-nowrap-expected.html
+++ b/third_party/blink/web_tests/fast/css/containment/change-text-node-data-nowrap-expected.html
@@ -20,12 +20,18 @@
 <div>baar</div>
 <div>baarbaar baarbaar</div>
 <div>baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar</div>
+<div>baar</div>
+<div>baarbaar baarbaar</div>
+<div>baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar</div>
 <div>baar baar baar baar</div>
 <div>baar</div>
 <div>b &#x55e8;</div>
 <div class="first-line">baar</div>
 <div class="first-line">baarbaar baarbaar</div>
 <div class="first-line">baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar</div>
+<div class="first-line">baar</div>
+<div class="first-line">baarbaar baarbaar</div>
+<div class="first-line">baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar</div>
 <div class="first-line">baar baar baar baar</div>
 <div class="first-line">baar</div>
 <div class="first-line">b &#x55e8;</div>
diff --git a/third_party/blink/web_tests/fast/css/containment/change-text-node-data-nowrap.html b/third_party/blink/web_tests/fast/css/containment/change-text-node-data-nowrap.html
index a11bcbff..9fd4ff6 100644
--- a/third_party/blink/web_tests/fast/css/containment/change-text-node-data-nowrap.html
+++ b/third_party/blink/web_tests/fast/css/containment/change-text-node-data-nowrap.html
@@ -24,6 +24,9 @@
     "foo",
     "foofoo foofoo",
     "foofoofoo foofoofoo foofoofoo foofoofoo foofoofoo",
+    "foofoofoo foofoofoo foofoofoo foofoofoo foofoofoo",
+    "foofoo foofoo",
+    "foo",
     "foo",
     "foo foo foo foo foo",
     "foo",
@@ -32,6 +35,9 @@
     "baar",
     "baarbaar baarbaar",
     "baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar",
+    "baar",
+    "baarbaar baarbaar",
+    "baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar",
     "baar baar baar baar",
     "baar",
     "b \u55e8",
diff --git a/third_party/blink/web_tests/fast/forms/resources/state-restore-dynamic-controls-frame.html b/third_party/blink/web_tests/fast/forms/resources/state-restore-dynamic-controls-frame.html
index a87c14e6..4d9c05c5 100644
--- a/third_party/blink/web_tests/fast/forms/resources/state-restore-dynamic-controls-frame.html
+++ b/third_party/blink/web_tests/fast/forms/resources/state-restore-dynamic-controls-frame.html
@@ -4,4 +4,23 @@
 <input type=text disabled>
 <script>
 document.querySelector('div').innerHTML = '<input type=checkbox><input type=text>'
+window.addEventListener('pageshow', () => {
+  // This checkbox produces a FormControlState on leaving the document.
+  // However, its state is never restored because it is added after 'pageshow'.
+  // See crbug.com/1138598.
+  let checkbox = document.createElement('input');
+  checkbox.type = 'checkbox';
+  checkbox.checked = false;
+  document.body.appendChild(checkbox);
+
+  parent.promiseResolver();
+}, {once:true});
+
+// This document produces FormControlStates like:
+//    type        name value
+// 1. "checkbox", "",  "on"
+// 2. "text",     "",  "z"
+// 3. "checkbox", "",  "off" (for the disabled one)
+// 4. "text",     "",  "" (for the disabled one)
+// 5. "checkbox", "",  "off" (for one added in the 'pageshow' handler)
 </script>
diff --git a/third_party/blink/web_tests/fast/forms/state-restore-dynamic-controls.html b/third_party/blink/web_tests/fast/forms/state-restore-dynamic-controls.html
index af57ac4..d7254917 100644
--- a/third_party/blink/web_tests/fast/forms/state-restore-dynamic-controls.html
+++ b/third_party/blink/web_tests/fast/forms/state-restore-dynamic-controls.html
@@ -5,8 +5,14 @@
 <body>
 <iframe src="resources/state-restore-dynamic-controls-frame.html"></iframe>
 <script>
+// A Promise for this function is resolved when the child frame dispatches
+// a 'pageshow' event.
+let promiseResolver = null;
+
 promise_test(async t => {
-  await waitForEvent(window, 'load', {once:true});
+  await new Promise((resolve, reject) => {
+    window.promiseResolver = resolve;
+  });
   const iframe = document.querySelector('iframe');
   const container = iframe.contentDocument.querySelector('div');
   // Change states of controls
@@ -21,9 +27,12 @@
   await waitForEvent(iframe, 'load', {once:true});
 
   // Navigate back
-  history.back();
-  await waitForEvent(iframe, 'load', {once:true});
-  // Wait until finishing the restore task.
+  await new Promise((resolve, reject) => {
+    window.promiseResolver = resolve;
+    history.back();
+  });
+
+  // Wait until finishing the scheduled restore task.
   await timeOut(t, 0);
   const inputs = iframe.contentDocument.querySelectorAll('input');
   assert_true(inputs[0].checked, 'Checkbox state should be restored.');
diff --git a/third_party/blink/web_tests/http/tests/devtools/console/console-revoke-error-expected.txt b/third_party/blink/web_tests/http/tests/devtools/console/console-revoke-error-expected.txt
index d58f540..b6bab57 100644
--- a/third_party/blink/web_tests/http/tests/devtools/console/console-revoke-error-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/console/console-revoke-error-expected.txt
@@ -5,17 +5,17 @@
 Message added: error log
 Message added: error log
 
-3 errors
+Open Console to view 3 errors
 console-message-wrapper console-error-level
 console-message-wrapper console-error-level
 console-message-wrapper console-error-level
 
 Handling promise
-1 error
+Open Console to view 1 error
 console-message-wrapper console-error-level
 
 Enable verbose filter
-1 error
+Open Console to view 1 error
 console-message-wrapper console-verbose-level
 console-message-wrapper console-error-level
 console-message-wrapper console-verbose-level
diff --git a/third_party/blink/web_tests/http/tests/devtools/console/console-revoke-error-in-worker-expected.txt b/third_party/blink/web_tests/http/tests/devtools/console/console-revoke-error-in-worker-expected.txt
index 8188a64..2e721907 100644
--- a/third_party/blink/web_tests/http/tests/devtools/console/console-revoke-error-in-worker-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/console/console-revoke-error-in-worker-expected.txt
@@ -3,11 +3,13 @@
 Creating worker with promise
 
 Message added: error log
-1 error
+Open Console to view 1 error
 console-message-wrapper console-error-level
 
 Handling promise
+Open Console to view 
 
 Enable verbose filter
+Open Console to view 
 console-message-wrapper console-verbose-level
 
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/resources/webauthn-test.https.html b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/resources/webauthn-test.https.html
index efc7843..2961f9c 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/resources/webauthn-test.https.html
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/resources/webauthn-test.https.html
@@ -58,14 +58,19 @@
 
   try {
     const credential = await navigator.credentials.create({publicKey: options});
-    return {
+    let result = {
       status: "OK",
       credential: {
         id: credential.id,
         rawId: Array.from(new Uint8Array(credential.rawId)),
         transports: credential.response.getTransports(),
-      }
+      },
     };
+    if (credential.getClientExtensionResults().largeBlob) {
+      result.largeBlobSupported =
+          credential.getClientExtensionResults().largeBlob.supported;
+    }
+    return result;
   } catch (error) {
     return {status: error.toString()};
   }
@@ -81,10 +86,15 @@
 
   try {
     const attestation = await navigator.credentials.get({publicKey: options});
-    return {
+    let result =  {
       status: "OK",
       attestation,
     };
+    if (attestation.getClientExtensionResults().largeBlob) {
+      result.blob = new TextDecoder().decode(
+        attestation.getClientExtensionResults().largeBlob.blob);
+    }
+    return result;
   } catch (error) {
     return {status: error.toString()};
   }
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-add-credential-errors-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-add-credential-errors-expected.txt
index ed34b4f..1e60304 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-add-credential-errors-expected.txt
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-add-credential-errors-expected.txt
@@ -55,4 +55,12 @@
     id : <number>
     sessionId : <string>
 }
+{
+    error : {
+        code : -32602
+        message : Large blob requires resident key support
+    }
+    id : <number>
+    sessionId : <string>
+}
 
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-add-credential-errors.js b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-add-credential-errors.js
index 1725e9c..6d8b5c2 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-add-credential-errors.js
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-add-credential-errors.js
@@ -59,5 +59,12 @@
   credentialOptions.credential.userHandle = btoa("nina");
   testRunner.log(await dp.WebAuthn.addCredential(credentialOptions));
 
+  // Try with a large blob on a non resident credential.
+  credentialOptions.credential.privateKey =
+      await session.evaluateAsync("generateBase64Key()");
+  credentialOptions.credential.largeBlob = btoa("large blob");
+  credentialOptions.credential.isResidentCredential = false;
+  testRunner.log(await dp.WebAuthn.addCredential(credentialOptions));
+
   testRunner.completeTest();
 })
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-add-virtual-authenticator-errors-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-add-virtual-authenticator-errors-expected.txt
index f604f8d9..8d72020 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-add-virtual-authenticator-errors-expected.txt
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-add-virtual-authenticator-errors-expected.txt
@@ -18,6 +18,14 @@
 {
     error : {
         code : -32602
+        message : Invalid CTAP version. Valid values are "ctap2_0" and "ctap2_1"
+    }
+    id : <number>
+    sessionId : <string>
+}
+{
+    error : {
+        code : -32602
         message : The transport is not valid
     }
     id : <number>
@@ -31,4 +39,28 @@
     id : <number>
     sessionId : <string>
 }
+{
+    error : {
+        code : -32602
+        message : Large blob requires resident key support
+    }
+    id : <number>
+    sessionId : <string>
+}
+{
+    error : {
+        code : -32602
+        message : Large blob requires a CTAP 2.1 authenticator
+    }
+    id : <number>
+    sessionId : <string>
+}
+{
+    error : {
+        code : -32602
+        message : Large blob requires a CTAP 2.1 authenticator
+    }
+    id : <number>
+    sessionId : <string>
+}
 
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-add-virtual-authenticator-errors.js b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-add-virtual-authenticator-errors.js
index 1e47622..5438aa33 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-add-virtual-authenticator-errors.js
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-add-virtual-authenticator-errors.js
@@ -25,6 +25,17 @@
   });
   testRunner.log(protocolError);
 
+  const ctapVersionError = await dp.WebAuthn.addVirtualAuthenticator({
+    options: {
+      protocol: "ctap2",
+      ctap2Version: "nonsense",
+      transport: "usb",
+      hasResidentKey: false,
+      hasUserVerification: false,
+    },
+  });
+  testRunner.log(ctapVersionError);
+
   const transportError = await dp.WebAuthn.addVirtualAuthenticator({
     options: {
       protocol: "ctap2",
@@ -45,5 +56,41 @@
   });
   testRunner.log(u2fCableError);
 
+  const largeBlobRequiresRKError = await dp.WebAuthn.addVirtualAuthenticator({
+    options: {
+      protocol: "ctap2",
+      ctap2Version: "ctap2_0",
+      transport: "usb",
+      hasResidentKey: false,
+      hasUserVerification: false,
+      hasLargeBlob: true
+    },
+  });
+  testRunner.log(largeBlobRequiresRKError);
+
+  const largeBlobRequiresCtapError = await dp.WebAuthn.addVirtualAuthenticator({
+    options: {
+      protocol: "u2f",
+      ctap2Version: "ctap2_1",
+      transport: "usb",
+      hasResidentKey: true,
+      hasUserVerification: false,
+      hasLargeBlob: true
+    },
+  });
+  testRunner.log(largeBlobRequiresCtapError);
+
+  const largeBlobRequiresCtap2_1Error = await dp.WebAuthn.addVirtualAuthenticator({
+    options: {
+      protocol: "ctap2",
+      ctap2Version: "ctap2_0",
+      transport: "usb",
+      hasResidentKey: true,
+      hasUserVerification: false,
+      hasLargeBlob: true
+    },
+  });
+  testRunner.log(largeBlobRequiresCtap2_1Error);
+
   testRunner.completeTest();
 })
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-large-blob-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-large-blob-expected.txt
new file mode 100644
index 0000000..bcd0109
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-large-blob-expected.txt
@@ -0,0 +1,13 @@
+Check that WebAuthn large blob operations work
+Create credential result: OK
+Large blob support: true
+{
+    id : <number>
+    result : {
+    }
+    sessionId : <string>
+}
+Assertion result: OK
+Got I'm Commander Shepard, and this is my favorite blob on the Citadel!
+Got I'm Commander Shepard, and this is my favorite blob on the Citadel!
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-large-blob.js b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-large-blob.js
new file mode 100644
index 0000000..f4ce859
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-large-blob.js
@@ -0,0 +1,73 @@
+(async function(testRunner) {
+  const {page, session, dp} =
+      await testRunner.startURL(
+          "https://devtools.test:8443/inspector-protocol/webauthn/resources/webauthn-test.https.html",
+          "Check that WebAuthn large blob operations work");
+
+  // Create an authenticator.
+  await dp.WebAuthn.enable();
+  const authenticatorId = (await dp.WebAuthn.addVirtualAuthenticator({
+    options: {
+      protocol: "ctap2",
+      ctap2Version: "ctap2_1",
+      transport: "usb",
+      hasResidentKey: true,
+      hasUserVerification: true,
+      hasLargeBlob: true,
+      isUserVerified: true,
+    },
+  })).result.authenticatorId;
+
+  // Register a credential with a large blob through webauthn.
+  let result = await session.evaluateAsync(`registerCredential({
+    extensions: {
+      largeBlob: {
+        support: "preferred",
+      },
+    },
+    authenticatorSelection: {
+      requireResidentKey: true,
+    },
+  })`);
+  testRunner.log(`Create credential result: ${result.status}`);
+  testRunner.log(`Large blob support: ${result.largeBlobSupported}`);
+
+  // Register a credential with a large blob through devtools.
+  const credentialId = btoa("cred-1");
+  const largeBlob =
+      "I'm Commander Shepard, and this is my favorite blob on the Citadel!";
+  testRunner.log(await dp.WebAuthn.addCredential({
+    authenticatorId,
+    credential: {
+      credentialId,
+      userHandle: btoa("isabelle"),
+      rpId: "devtools.test",
+      privateKey: await session.evaluateAsync("generateBase64Key()"),
+      signCount: 0,
+      isResidentCredential: true,
+      largeBlob: btoa(largeBlob),
+    }
+  }));
+
+  // Read the large blob through the WebAuthn API.
+  result = await session.evaluateAsync(`getCredential({
+    type: "public-key",
+    id: new TextEncoder().encode("cred-1"),
+    transports: ["usb", "ble", "nfc"],
+  }, {
+    extensions: {
+      largeBlob: {
+        read: true,
+      },
+    },
+  })`);
+  testRunner.log(`Assertion result: ${result.status}`);
+  testRunner.log(`Got ${result.blob}`);
+
+  // Read the large blob through Devtools.
+  let credential =
+      (await dp.WebAuthn.getCredential({authenticatorId, credentialId})).result.credential;
+  testRunner.log(`Got ${atob(credential.largeBlob)}`);
+
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/platform/fuchsia/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/fuchsia/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
deleted file mode 100644
index cebd4dc..0000000
--- a/third_party/blink/web_tests/platform/fuchsia/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/button/button-focus-ring-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/button/button-focus-ring-expected.png
index 992c990f..36655f3 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/button/button-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/button/button-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/button/button-hover-state-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/button/button-hover-state-expected.png
index 68a8d42..ecdd2d4 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/button/button-hover-state-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/button/button-hover-state-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/color/color-picker-focus-ring-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/color/color-picker-focus-ring-expected.png
index 20a6049..408d657 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/color/color-picker-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/color/color-picker-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-appearance-basic-expected.png
index e47b2370f..dafec595 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-pressed-state-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-pressed-state-expected.png
index 25e602c..3b0c4d2 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-pressed-state-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-pressed-state-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
index b9dcce2..33f9e8f 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/file/file-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/file/file-appearance-basic-expected.png
index 5ecc34d..b6223da 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/file/file-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/file/file-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/meter/meter-appearance-basic-expected.png
index 74de975..db7fd22 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/meter/meter-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
index 02a03cb..609719f 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
index fcb5861..1343a2bc 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
index 0ac5521..213b3a64 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
deleted file mode 100644
index 019dd0b..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
deleted file mode 100644
index 31247e2..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
deleted file mode 100644
index 019dd0b..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
index f71fe18..40d09db4 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
deleted file mode 100644
index 31247e2..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
deleted file mode 100644
index 019dd0b..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
deleted file mode 100644
index 31247e2..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.15/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
deleted file mode 100644
index 019dd0b..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.15/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png b/third_party/blink/web_tests/platform/mac-mac10.15/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
deleted file mode 100644
index 31247e2..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.15/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/button/button-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/button/button-focus-ring-expected.png
index 2ed770e..0d36da1e 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/button/button-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/button/button-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/button/button-hover-state-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/button/button-hover-state-expected.png
index f0bfb98c..c93e3f4 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/button/button-hover-state-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/button/button-hover-state-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/color/color-picker-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/color/color-picker-focus-ring-expected.png
index 5ba7db6b..30868ce 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/color/color-picker-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/color/color-picker-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-appearance-basic-expected.png
index 0311158..6bd8000e 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-pressed-state-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-pressed-state-expected.png
index 0216d66..730e6ce 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-pressed-state-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-pressed-state-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
index 019dd0b..df1a0ab 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/file/file-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/file/file-appearance-basic-expected.png
index 3b064750..ccadd37 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/file/file-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/file/file-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/meter/meter-appearance-basic-expected.png
index cde305b..fcc6683 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/meter/meter-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
index 2c47b41..b8ef11d 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
index bc125be..5d56400d 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
index 31247e2..5678a6bc 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/button/button-focus-ring-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/button/button-focus-ring-expected.png
index 8b4da72..4a84427b 100644
--- a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/button/button-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/button/button-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/button/button-hover-state-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/button/button-hover-state-expected.png
index fef02b4..7d26978 100644
--- a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/button/button-hover-state-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/button/button-hover-state-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/color/color-picker-focus-ring-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/color/color-picker-focus-ring-expected.png
index 83311a8..d4a3a324 100644
--- a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/color/color-picker-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/color/color-picker-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-appearance-basic-expected.png
index b704cd3d..dfd4716 100644
--- a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-pressed-state-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-pressed-state-expected.png
index a70c271b..f4b24cdf 100644
--- a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-pressed-state-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/button/button-pressed-state-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
index 64b6e3d7..57e34db 100644
--- a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/file/file-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/file/file-appearance-basic-expected.png
index f457c29..c71139f 100644
--- a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/file/file-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/file/file-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/meter/meter-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/meter/meter-appearance-basic-expected.png
index e0cc4a35..c46c2973 100644
--- a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/meter/meter-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/meter/meter-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
index 42acba01..8c714af4 100644
--- a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
index f7baa5da..3596821d 100644
--- a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
index 8f10ce92..81108b9 100644
--- a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/win7/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
deleted file mode 100644
index 64b6e3d7..0000000
--- a/third_party/blink/web_tests/platform/win7/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png b/third_party/blink/web_tests/platform/win7/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
deleted file mode 100644
index 8f10ce92..0000000
--- a/third_party/blink/web_tests/platform/win7/virtual/dark-color-scheme/virtual/eye-dropper/color-picker-show-eye-dropper-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/text-antialias/hyphens/hyphens-auto-mock-expected.html b/third_party/blink/web_tests/virtual/text-antialias/hyphens/hyphens-auto-mock-expected.html
index 5dbdf0d..017451d 100644
--- a/third_party/blink/web_tests/virtual/text-antialias/hyphens/hyphens-auto-mock-expected.html
+++ b/third_party/blink/web_tests/virtual/text-antialias/hyphens/hyphens-auto-mock-expected.html
@@ -25,9 +25,9 @@
 </script>
 <div lang="en-us">
   <div>
-    <span style="width: 2ch;">hyphenation<img></span>
-    <span style="width: 3.1ch;">hy-<br>phenation<img></span>
-    <span style="width: 4ch;">hy-<br>phenation<img></span>
+    <span style="width: 2ch;">hy-<br>phen-<br>ation<img></span>
+    <span style="width: 3.1ch;">hy-<br>phen-<br>ation<img></span>
+    <span style="width: 4ch;">hy-<br>phen-<br>ation<img></span>
     <span style="width: 5.1ch;">hy-<br>phen-<br>ation<img></span>
     <span style="width: 6ch;">hy-<br>phen-<br>ation<img></span>
     <span style="width: 7.1ch;">hyphen-<br>ation<img></span>
@@ -37,9 +37,9 @@
     <span style="width: 11ch;">hyphenation<img></span>
   </div>
   <div>
-    <span style="width: 2ch;">hyphenation test</span>
-    <span style="width: 3.1ch;">hy-<br>phenation test</span>
-    <span style="width: 4ch;">hy-<br>phenation test</span>
+    <span style="width: 2ch;">hy-<br>phen-<br>ation test</span>
+    <span style="width: 3.1ch;">hy-<br>phen-<br>ation test</span>
+    <span style="width: 4ch;">hy-<br>phen-<br>ation test</span>
     <span style="width: 5.1ch;">hy-<br>phen-<br>ation test</span>
     <span style="width: 6ch;">hy-<br>phen-<br>ation test</span>
     <span style="width: 7.1ch;">hyphen-<br>ation test</span>
@@ -49,9 +49,9 @@
     <span style="width: 11ch;">hyphenation test</span>
   </div>
   <div>
-    <span style="width: 2ch;">a hyphenation test</span>
-    <span style="width: 3.1ch;">a hy-<br>phenation test</span>
-    <span style="width: 4ch;">a hy-<br>phenation test</span>
+    <span style="width: 2ch;">a hy-<br>phen-<br>ation test</span>
+    <span style="width: 3.1ch;">a hy-<br>phen-<br>ation test</span>
+    <span style="width: 4ch;">a hy-<br>phen-<br>ation test</span>
     <span style="width: 5.1ch;">a hy-<br>phen-<br>ation test</span>
     <span style="width: 6ch;">a hy-<br>phen-<br>ation test</span>
     <span style="width: 7.1ch;">a hy-<br>phen-<br>ation test</span>
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 3f2c189..d771389 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -787,6 +787,7 @@
 [Worker]     method decodingInfo
 [Worker]     method encodingInfo
 [Worker] interface MediaSource : EventTarget
+[Worker]     static getter canConstructInDedicatedWorker
 [Worker]     static method isTypeSupported
 [Worker]     attribute @@toStringTag
 [Worker]     getter activeSourceBuffers
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index 8abd1b2..084c7be2 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -5142,6 +5142,7 @@
     setter metadata
     setter playbackState
 interface MediaSource : EventTarget
+    static getter canConstructInDedicatedWorker
     static method isTypeSupported
     attribute @@toStringTag
     getter activeSourceBuffers
diff --git a/third_party/bspatch/OWNERS b/third_party/bspatch/OWNERS
index 4fa623e..c11ac94 100644
--- a/third_party/bspatch/OWNERS
+++ b/third_party/bspatch/OWNERS
@@ -1 +1 @@
-# COMPONENT: Internal>Installer
+# COMPONENT: Internals>Installer
diff --git a/third_party/closure_compiler/externs/file_manager_private.js b/third_party/closure_compiler/externs/file_manager_private.js
index 7046857..d1ae009 100644
--- a/third_party/closure_compiler/externs/file_manager_private.js
+++ b/third_party/closure_compiler/externs/file_manager_private.js
@@ -365,7 +365,8 @@
  *   mountContext: (!chrome.fileManagerPrivate.MountContext|undefined),
  *   diskFileSystemType: (string|undefined),
  *   iconSet: !chrome.fileManagerPrivate.IconSet,
- *   driveLabel: (string|undefined)
+ *   driveLabel: (string|undefined),
+ *   remoteMountPath: (string|undefined)
  * }}
  */
 chrome.fileManagerPrivate.VolumeMetadata;
diff --git a/third_party/closure_compiler/externs/management.js b/third_party/closure_compiler/externs/management.js
index e8bb94e..7900492 100644
--- a/third_party/closure_compiler/externs/management.js
+++ b/third_party/closure_compiler/externs/management.js
@@ -1,4 +1,4 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
+// 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.
 
@@ -11,9 +11,7 @@
 
 /** @fileoverview Externs generated from namespace: management */
 
-/**
- * @const
- */
+/** @const */
 chrome.management = {};
 
 /**
@@ -103,6 +101,15 @@
 chrome.management.ExtensionInfo;
 
 /**
+ * Information about an icon belonging to an extension, app, or theme.
+ * @typedef {{
+ *   showConfirmDialog: (boolean|undefined)
+ * }}
+ * @see https://developer.chrome.com/extensions/management#type-UninstallOptions
+ */
+chrome.management.UninstallOptions;
+
+/**
  * Returns a list of information about installed extensions and apps.
  * @param {function(!Array<!chrome.management.ExtensionInfo>): void=} callback
  * @see https://developer.chrome.com/extensions/management#method-getAll
@@ -163,9 +170,7 @@
  * Uninstalls a currently installed app or extension.
  * @param {string} id This should be the id from an item of
  *     $(ref:management.ExtensionInfo).
- * @param {{
- *   showConfirmDialog: (boolean|undefined)
- * }=} options
+ * @param {!chrome.management.UninstallOptions=} options
  * @param {function(): void=} callback
  * @see https://developer.chrome.com/extensions/management#method-uninstall
  */
@@ -174,9 +179,7 @@
 /**
  * Uninstalls the calling extension. Note: This function can be used without
  * requesting the 'management' permission in the manifest.
- * @param {{
- *   showConfirmDialog: (boolean|undefined)
- * }=} options
+ * @param {!chrome.management.UninstallOptions=} options
  * @param {function(): void=} callback
  * @see https://developer.chrome.com/extensions/management#method-uninstallSelf
  */
diff --git a/third_party/closure_compiler/externs/windows.js b/third_party/closure_compiler/externs/windows.js
index a551a2e..c675085e 100644
--- a/third_party/closure_compiler/externs/windows.js
+++ b/third_party/closure_compiler/externs/windows.js
@@ -71,6 +71,15 @@
 };
 
 /**
+ * @typedef {{
+ *   populate: (boolean|undefined),
+ *   windowTypes: (!Array<!chrome.windows.WindowType>|undefined)
+ * }}
+ * @see https://developer.chrome.com/extensions/windows#type-GetInfo
+ */
+chrome.windows.GetInfo;
+
+/**
  * The windowId value that represents the absence of a chrome browser window.
  * @type {number}
  * @see https://developer.chrome.com/extensions/windows#type-WINDOW_ID_NONE
@@ -87,24 +96,16 @@
 /**
  * Gets details about a window.
  * @param {number} windowId
- * @param {?{
-  populate: (boolean|undefined),
-  windowTypes: (!Array<!chrome.windows.WindowType>|undefined)
-}|undefined}
- *     getInfo
- * @param {function(!chrome.windows.Window):void} callback
+ * @param {?chrome.windows.GetInfo|undefined} getInfo
+ * @param {function(!chrome.windows.Window): void} callback
  * @see https://developer.chrome.com/extensions/windows#method-get
  */
 chrome.windows.get = function(windowId, getInfo, callback) {};
 
 /**
  * Gets the <a href='#current-window'>current window</a>.
- * @param {?{
-  populate: (boolean|undefined),
-  windowTypes: (!Array<!chrome.windows.WindowType>|undefined)
-}|undefined}
- *     getInfo
- * @param {function(!chrome.windows.Window):void} callback
+ * @param {?chrome.windows.GetInfo|undefined} getInfo
+ * @param {function(!chrome.windows.Window): void} callback
  * @see https://developer.chrome.com/extensions/windows#method-getCurrent
  */
 chrome.windows.getCurrent = function(getInfo, callback) {};
@@ -112,24 +113,16 @@
 /**
  * Gets the window that was most recently focused &mdash; typically the window
  * 'on top'.
- * @param {?{
-  populate: (boolean|undefined),
-  windowTypes: (!Array<!chrome.windows.WindowType>|undefined)
-}|undefined}
- *     getInfo
- * @param {function(!chrome.windows.Window):void} callback
+ * @param {?chrome.windows.GetInfo|undefined} getInfo
+ * @param {function(!chrome.windows.Window): void} callback
  * @see https://developer.chrome.com/extensions/windows#method-getLastFocused
  */
 chrome.windows.getLastFocused = function(getInfo, callback) {};
 
 /**
  * Gets all windows.
- * @param {?{
-  populate: (boolean|undefined),
-  windowTypes: (!Array<!chrome.windows.WindowType>|undefined)
-}|undefined}
- *     getInfo
- * @param {function(!Array<!chrome.windows.Window>):void} callback
+ * @param {?chrome.windows.GetInfo|undefined} getInfo
+ * @param {function(!Array<!chrome.windows.Window>): void} callback
  * @see https://developer.chrome.com/extensions/windows#method-getAll
  */
 chrome.windows.getAll = function(getInfo, callback) {};
@@ -150,7 +143,7 @@
  *   state: (!chrome.windows.WindowState|undefined),
  *   setSelfAsOpener: (boolean|undefined)
  * }=} createData
- * @param {function((!chrome.windows.Window|undefined)):void=} callback
+ * @param {function((!chrome.windows.Window|undefined)): void=} callback
  * @see https://developer.chrome.com/extensions/windows#method-create
  */
 chrome.windows.create = function(createData, callback) {};
@@ -168,7 +161,7 @@
  *   drawAttention: (boolean|undefined),
  *   state: (!chrome.windows.WindowState|undefined)
  * }} updateInfo
- * @param {function(!chrome.windows.Window):void=} callback
+ * @param {function(!chrome.windows.Window): void=} callback
  * @see https://developer.chrome.com/extensions/windows#method-update
  */
 chrome.windows.update = function(windowId, updateInfo, callback) {};
@@ -176,7 +169,7 @@
 /**
  * Removes (closes) a window and all the tabs inside it.
  * @param {number} windowId
- * @param {function():void=} callback
+ * @param {function(): void=} callback
  * @see https://developer.chrome.com/extensions/windows#method-remove
  */
 chrome.windows.remove = function(windowId, callback) {};
@@ -205,3 +198,11 @@
  * @see https://developer.chrome.com/extensions/windows#event-onFocusChanged
  */
 chrome.windows.onFocusChanged;
+
+/**
+ * Fired when a window has been resized; this event is only dispatched when the
+ * new bounds are committed, and not for in-progress changes.
+ * @type {!ChromeEvent}
+ * @see https://developer.chrome.com/extensions/windows#event-onBoundsChanged
+ */
+chrome.windows.onBoundsChanged;
diff --git a/third_party/leveldatabase/port/port_chromium.cc b/third_party/leveldatabase/port/port_chromium.cc
index 570035d2..aa77a639 100644
--- a/third_party/leveldatabase/port/port_chromium.cc
+++ b/third_party/leveldatabase/port/port_chromium.cc
@@ -4,6 +4,8 @@
 
 #include "port/port_chromium.h"
 
+#include <cstddef>
+#include <cstdint>
 #include <string>
 
 #include "third_party/crc32c/src/include/crc32c/crc32c.h"
diff --git a/third_party/leveldatabase/port/port_chromium.h b/third_party/leveldatabase/port/port_chromium.h
index 6050fa3..9dcf30b 100644
--- a/third_party/leveldatabase/port/port_chromium.h
+++ b/third_party/leveldatabase/port/port_chromium.h
@@ -7,15 +7,14 @@
 #ifndef STORAGE_LEVELDB_PORT_PORT_CHROMIUM_H_
 #define STORAGE_LEVELDB_PORT_PORT_CHROMIUM_H_
 
-#include <cassert>
-#include <condition_variable>  // NOLINT
-#include <cstring>
-#include <mutex>  // NOLINT
+#include <cstddef>
+#include <cstdint>
 #include <string>
 
-#include "base/macros.h"
+#include "base/check.h"
+#include "base/synchronization/condition_variable.h"
+#include "base/synchronization/lock.h"
 #include "base/thread_annotations.h"
-#include "build/build_config.h"
 
 namespace leveldb {
 namespace port {
@@ -28,35 +27,30 @@
   Mutex(const Mutex&) = delete;
   Mutex& operator=(const Mutex&) = delete;
 
-  void Lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.lock(); }
-  void Unlock() UNLOCK_FUNCTION() { mu_.unlock(); }
-  void AssertHeld() ASSERT_EXCLUSIVE_LOCK() {}
+  void Lock() EXCLUSIVE_LOCK_FUNCTION() { lock_.Acquire(); }
+  void Unlock() UNLOCK_FUNCTION() { lock_.Release(); }
+  void AssertHeld() ASSERT_EXCLUSIVE_LOCK() { lock_.AssertAcquired(); }
 
  private:
   friend class CondVar;
-  std::mutex mu_;
+  base::Lock lock_;
 };
 
 // Thinly wraps std::condition_variable.
 class CondVar {
  public:
-  explicit CondVar(Mutex* mu) : mu_(mu) { assert(mu != nullptr); }
+  explicit CondVar(Mutex* mu) : cv_(&mu->lock_) { DCHECK(mu); }
   ~CondVar() = default;
 
   CondVar(const CondVar&) = delete;
   CondVar& operator=(const CondVar&) = delete;
 
-  void Wait() {
-    std::unique_lock<std::mutex> lock(mu_->mu_, std::adopt_lock);
-    cv_.wait(lock);
-    lock.release();
-  }
-  void Signal() { cv_.notify_one(); }
-  void SignalAll() { cv_.notify_all(); }
+  void Wait() { cv_.Wait(); }
+  void Signal() { cv_.Signal(); }
+  void SignalAll() { cv_.Broadcast(); }
 
  private:
-  std::condition_variable cv_;
-  Mutex* const mu_;
+  base::ConditionVariable cv_;
 };
 
 bool Snappy_Compress(const char* input, size_t input_length,
diff --git a/third_party/libaddressinput/chromium/resources/address_input_strings_iw.xtb b/third_party/libaddressinput/chromium/resources/address_input_strings_iw.xtb
index ab52cf3..4fa6675 100644
--- a/third_party/libaddressinput/chromium/resources/address_input_strings_iw.xtb
+++ b/third_party/libaddressinput/chromium/resources/address_input_strings_iw.xtb
@@ -41,7 +41,7 @@
 <translation id="820600307078153032">פורמט המיקוד הזה אינו מוכר. דוגמה למיקוד חוקי: <ph name="EXAMPLE" />.</translation>
 <translation id="8446364922515257065">דו/סי</translation>
 <translation id="8449204988444194299">מיקוד עיר (בריטניה)</translation>
-<translation id="8471101563037901452">נראה שהמיקוד הזה לא תואם לשאר הכתובת. אינך יודע מה המיקוד? תוכל לגלות <ph name="BEGIN_LINK" />כאן<ph name="END_LINK" />.</translation>
+<translation id="8471101563037901452">נראה שהמיקוד הזה לא תואם לשאר הכתובת. לא ידוע לך מה המיקוד? אפשר למצוא אותו <ph name="BEGIN_LINK" />כאן<ph name="END_LINK" />.</translation>
 <translation id="9104066683700680171">נראה שהמיקוד הזה לא תואם לשאר הכתובת.</translation>
 <translation id="9207002871037636573">עליך לספק מיקוד, לדוגמה <ph name="EXAMPLE" />.</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/third_party/libvpx/BUILD.gn b/third_party/libvpx/BUILD.gn
index df54bc90..165be63f 100644
--- a/third_party/libvpx/BUILD.gn
+++ b/third_party/libvpx/BUILD.gn
@@ -375,63 +375,15 @@
     configs += [ "//build/config/compiler:optimize_max" ]
   }
 
-  if (is_nacl) {
-    sources = libvpx_srcs_generic
-  } else if (current_cpu == "x86") {
-    sources = libvpx_srcs_x86
-  } else if (current_cpu == "x64") {
-    if (is_msan) {
-      sources = libvpx_srcs_generic
-    } else {
-      sources = libvpx_srcs_x86_64
-    }
-  } else if (current_cpu == "mipsel" || current_cpu == "mips64el") {
-    sources = libvpx_srcs_mips
-  } else if (current_cpu == "arm") {
-    if (is_chromeos) {
-      sources = libvpx_srcs_arm_neon_highbd
-    } else if (arm_use_neon) {
-      sources = libvpx_srcs_arm_neon
-    } else if (is_android) {
-      sources = libvpx_srcs_arm_neon_cpu_detect
-    } else {
-      sources = libvpx_srcs_arm
-    }
-  } else if (current_cpu == "arm64") {
-    if (is_chromeos || is_win) {
-      sources = libvpx_srcs_arm64_highbd
-    } else {
-      sources = libvpx_srcs_arm64
-    }
-  }
-  sources += [ "//third_party/libvpx/source/libvpx/vp9/ratectrl_rtc.cc" ]
-  sources += [ "//third_party/libvpx/source/libvpx/vp9/ratectrl_rtc.h" ]
+  sources = [
+    "//third_party/libvpx/source/libvpx/vp9/ratectrl_rtc.cc",
+    "//third_party/libvpx/source/libvpx/vp9/ratectrl_rtc.h",
+  ]
 
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [ "//build/config/compiler:no_chromium_code" ]
   configs += [ ":libvpx_config" ]
-  deps = []
-  if (current_cpu == "x86" || (current_cpu == "x64" && !is_msan)) {
-    deps += [
-      ":libvpx_asm",
-      ":libvpx_intrinsics_avx",
-      ":libvpx_intrinsics_avx2",
-      ":libvpx_intrinsics_avx512",
-      ":libvpx_intrinsics_mmx",
-      ":libvpx_intrinsics_sse2",
-      ":libvpx_intrinsics_sse4_1",
-      ":libvpx_intrinsics_ssse3",
-    ]
-  }
-  if (cpu_arch_full == "arm-neon-cpu-detect") {
-    deps += [ ":libvpx_intrinsics_neon" ]
-  }
-  if (is_android) {
-    deps += [ "//third_party/android_ndk:cpu_features" ]
-  }
-  if (current_cpu == "arm" && arm_assembly_sources != []) {
-    deps += [ ":libvpx_assembly_arm" ]
-  }
+  public_deps = [ ":libvpx" ]
 
   public_configs = [ ":libvpx_external_config" ]
 }
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium
index e7a2b74..b898781f 100644
--- a/third_party/libvpx/README.chromium
+++ b/third_party/libvpx/README.chromium
@@ -6,9 +6,9 @@
 License File: source/libvpx/LICENSE
 Security Critical: yes
 
-Date: Friday October 02 2020
+Date: Tuesday October 20 2020
 Branch: master
-Commit: 7e8ea22e4056a3da04b139fcc812a3f6937bbed7
+Commit: 94384b5c685ad3baac8989f19ee587eb72093a7f
 
 Description:
 Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/libvpx_srcs.gni b/third_party/libvpx/libvpx_srcs.gni
index 24450c41..b78d739 100644
--- a/third_party/libvpx/libvpx_srcs.gni
+++ b/third_party/libvpx/libvpx_srcs.gni
@@ -209,6 +209,8 @@
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_encoder.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.h",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.c",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.h",
@@ -270,6 +272,7 @@
   "//third_party/libvpx/source/libvpx/vpx/vpx_codec.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_decoder.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_encoder.h",
+  "//third_party/libvpx/source/libvpx/vpx/vpx_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_frame_buffer.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_image.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_integer.h",
@@ -683,6 +686,8 @@
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_encoder.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.h",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.c",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.h",
@@ -744,6 +749,7 @@
   "//third_party/libvpx/source/libvpx/vpx/vpx_codec.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_decoder.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_encoder.h",
+  "//third_party/libvpx/source/libvpx/vpx/vpx_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_frame_buffer.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_image.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_integer.h",
@@ -1160,6 +1166,8 @@
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_encoder.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.h",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.c",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.h",
@@ -1221,6 +1229,7 @@
   "//third_party/libvpx/source/libvpx/vpx/vpx_codec.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_decoder.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_encoder.h",
+  "//third_party/libvpx/source/libvpx/vpx/vpx_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_frame_buffer.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_image.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_integer.h",
@@ -1527,6 +1536,8 @@
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_encoder.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.h",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.c",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.h",
@@ -1588,6 +1599,7 @@
   "//third_party/libvpx/source/libvpx/vpx/vpx_codec.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_decoder.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_encoder.h",
+  "//third_party/libvpx/source/libvpx/vpx/vpx_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_frame_buffer.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_image.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_integer.h",
@@ -1923,6 +1935,8 @@
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_encoder.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.h",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.c",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.h",
@@ -1984,6 +1998,7 @@
   "//third_party/libvpx/source/libvpx/vpx/vpx_codec.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_decoder.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_encoder.h",
+  "//third_party/libvpx/source/libvpx/vpx/vpx_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_frame_buffer.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_image.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_integer.h",
@@ -2368,6 +2383,8 @@
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_encoder.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.h",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.c",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.h",
@@ -2429,6 +2446,7 @@
   "//third_party/libvpx/source/libvpx/vpx/vpx_codec.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_decoder.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_encoder.h",
+  "//third_party/libvpx/source/libvpx/vpx/vpx_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_frame_buffer.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_image.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_integer.h",
@@ -2775,6 +2793,8 @@
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_encoder.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.h",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.c",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.h",
@@ -2836,6 +2856,7 @@
   "//third_party/libvpx/source/libvpx/vpx/vpx_codec.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_decoder.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_encoder.h",
+  "//third_party/libvpx/source/libvpx/vpx/vpx_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_frame_buffer.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_image.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_integer.h",
@@ -3211,6 +3232,8 @@
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_encoder.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.h",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.c",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.h",
@@ -3272,6 +3295,7 @@
   "//third_party/libvpx/source/libvpx/vpx/vpx_codec.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_decoder.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_encoder.h",
+  "//third_party/libvpx/source/libvpx/vpx/vpx_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_frame_buffer.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_image.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_integer.h",
@@ -3603,6 +3627,8 @@
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_encoder.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.h",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.c",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.h",
@@ -3664,6 +3690,7 @@
   "//third_party/libvpx/source/libvpx/vpx/vpx_codec.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_decoder.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_encoder.h",
+  "//third_party/libvpx/source/libvpx/vpx/vpx_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_frame_buffer.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_image.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_integer.h",
@@ -3944,6 +3971,8 @@
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_encoder.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.h",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.c",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.h",
@@ -4005,6 +4034,7 @@
   "//third_party/libvpx/source/libvpx/vpx/vpx_codec.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_decoder.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_encoder.h",
+  "//third_party/libvpx/source/libvpx/vpx/vpx_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_frame_buffer.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_image.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_integer.h",
@@ -4282,6 +4312,8 @@
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_encoder.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ethread.h",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.c",
+  "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.c",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_extend.h",
   "//third_party/libvpx/source/libvpx/vp9/encoder/vp9_firstpass.h",
@@ -4343,6 +4375,7 @@
   "//third_party/libvpx/source/libvpx/vpx/vpx_codec.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_decoder.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_encoder.h",
+  "//third_party/libvpx/source/libvpx/vpx/vpx_ext_ratectrl.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_frame_buffer.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_image.h",
   "//third_party/libvpx/source/libvpx/vpx/vpx_integer.h",
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h
index 23c120a65..e558144d 100644
--- a/third_party/libvpx/source/config/vpx_version.h
+++ b/third_party/libvpx/source/config/vpx_version.h
@@ -2,8 +2,8 @@
 #define VERSION_MAJOR 1
 #define VERSION_MINOR 9
 #define VERSION_PATCH 0
-#define VERSION_EXTRA "75-g7e8ea22e4"
+#define VERSION_EXTRA "86-g94384b5c6"
 #define VERSION_PACKED \
   ((VERSION_MAJOR << 16) | (VERSION_MINOR << 8) | (VERSION_PATCH))
-#define VERSION_STRING_NOSP "v1.9.0-75-g7e8ea22e4"
-#define VERSION_STRING " v1.9.0-75-g7e8ea22e4"
+#define VERSION_STRING_NOSP "v1.9.0-86-g94384b5c6"
+#define VERSION_STRING " v1.9.0-86-g94384b5c6"
diff --git a/third_party/wayland-protocols/OWNERS b/third_party/wayland-protocols/OWNERS
index 116dfbbc..24e689858 100644
--- a/third_party/wayland-protocols/OWNERS
+++ b/third_party/wayland-protocols/OWNERS
@@ -1,4 +1,4 @@
 oshima@chromium.org
 dcastagna@chromium.org
 
-# COMPONENT: Internal>Exosphere
+# COMPONENT: Internals>Exosphere
diff --git a/tools/clang/blink_gc_plugin/BadPatternFinder.cpp b/tools/clang/blink_gc_plugin/BadPatternFinder.cpp
index f3cdb86..e081cf3c 100644
--- a/tools/clang/blink_gc_plugin/BadPatternFinder.cpp
+++ b/tools/clang/blink_gc_plugin/BadPatternFinder.cpp
@@ -9,6 +9,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchersMacros.h"
 
 using namespace clang::ast_matchers;
 
@@ -42,7 +43,7 @@
     match_finder.addDynamicMatcher(make_unique_matcher, this);
   }
 
-  void run(const MatchFinder::MatchResult& result) {
+  void run(const MatchFinder::MatchResult& result) override {
     auto* bad_use = result.Nodes.getNodeAs<clang::Expr>("bad");
     auto* bad_function = result.Nodes.getNodeAs<clang::FunctionDecl>("badfunc");
     auto* gc_type = result.Nodes.getNodeAs<clang::CXXRecordDecl>("gctype");
@@ -72,7 +73,7 @@
     match_finder.addDynamicMatcher(optional_construction, this);
   }
 
-  void run(const MatchFinder::MatchResult& result) {
+  void run(const MatchFinder::MatchResult& result) override {
     auto* bad_use = result.Nodes.getNodeAs<clang::Expr>("bad");
     auto* optional = result.Nodes.getNodeAs<clang::CXXRecordDecl>("optional");
     auto* gc_type = result.Nodes.getNodeAs<clang::CXXRecordDecl>("gctype");
@@ -83,6 +84,60 @@
   DiagnosticsReporter& diagnostics_;
 };
 
+// For the absl::variant checker, we need to match the inside of a variadic
+// template class, which doesn't seem easy with the built-in matchers: define a
+// custom matcher to go through the template parameter list.
+AST_MATCHER_P(clang::TemplateArgument,
+              parameterPackHasAnyElement,
+              // Clang exports other instantiations of Matcher via
+              // using-declarations in public headers, e.g. `using TypeMatcher =
+              // Matcher<QualType>`.
+              //
+              // Once https://reviews.llvm.org/D89920, a Clang patch adding a
+              // similar alias for template arguments, lands, this can be
+              // changed to TemplateArgumentMatcher and won't need to use the
+              // internal namespace any longer.
+              clang::ast_matchers::internal::Matcher<clang::TemplateArgument>,
+              InnerMatcher) {
+  if (Node.getKind() != clang::TemplateArgument::Pack)
+    return false;
+  return llvm::any_of(Node.pack_elements(),
+                      [&](const clang::TemplateArgument& Arg) {
+                        return InnerMatcher.matches(Arg, Finder, Builder);
+                      });
+}
+
+class VariantGarbageCollectedMatcher : public MatchFinder::MatchCallback {
+ public:
+  explicit VariantGarbageCollectedMatcher(DiagnosticsReporter& diagnostics)
+      : diagnostics_(diagnostics) {}
+
+  void Register(MatchFinder& match_finder) {
+    // Matches any constructed absl::variant where a template argument is
+    // known to refer to a garbage-collected type.
+    auto variant_construction =
+        cxxConstructExpr(
+            hasDeclaration(cxxConstructorDecl(
+                ofClass(classTemplateSpecializationDecl(
+                            hasName("::absl::variant"),
+                            hasAnyTemplateArgument(parameterPackHasAnyElement(
+                                refersToType(GarbageCollectedType()))))
+                            .bind("variant")))))
+            .bind("bad");
+    match_finder.addDynamicMatcher(variant_construction, this);
+  }
+
+  void run(const MatchFinder::MatchResult& result) override {
+    auto* bad_use = result.Nodes.getNodeAs<clang::Expr>("bad");
+    auto* variant = result.Nodes.getNodeAs<clang::CXXRecordDecl>("variant");
+    auto* gc_type = result.Nodes.getNodeAs<clang::CXXRecordDecl>("gctype");
+    diagnostics_.VariantUsedWithGC(bad_use, variant, gc_type);
+  }
+
+ private:
+  DiagnosticsReporter& diagnostics_;
+};
+
 }  // namespace
 
 void FindBadPatterns(clang::ASTContext& ast_context,
@@ -95,5 +150,8 @@
   OptionalGarbageCollectedMatcher optional_gc(diagnostics);
   optional_gc.Register(match_finder);
 
+  VariantGarbageCollectedMatcher variant_gc(diagnostics);
+  variant_gc.Register(match_finder);
+
   match_finder.matchAST(ast_context);
 }
diff --git a/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp b/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp
index 88f2ab4..4a6d9dd 100644
--- a/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp
+++ b/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp
@@ -145,6 +145,10 @@
     "[blink-gc] Disallowed construction of %0 found; %1 is a garbage-collected "
     "type. optional cannot hold garbage-collected objects.";
 
+const char kVariantUsedWithGC[] =
+    "[blink-gc] Disallowed construction of %0 found; %1 is a garbage-collected "
+    "type. absl::variant cannot hold garbage-collected objects.";
+
 } // namespace
 
 DiagnosticBuilder DiagnosticsReporter::ReportDiagnostic(
@@ -246,6 +250,8 @@
       diagnostic_.getCustomDiagID(getErrorLevel(), kUniquePtrUsedWithGC);
   diag_optional_used_with_gc_ =
       diagnostic_.getCustomDiagID(getErrorLevel(), kOptionalUsedWithGC);
+  diag_variant_used_with_gc_ =
+      diagnostic_.getCustomDiagID(getErrorLevel(), kVariantUsedWithGC);
 }
 
 bool DiagnosticsReporter::hasErrorOccurred() const
@@ -541,3 +547,11 @@
   ReportDiagnostic(expr->getBeginLoc(), diag_optional_used_with_gc_)
       << optional << gc_type << expr->getSourceRange();
 }
+
+void DiagnosticsReporter::VariantUsedWithGC(
+    const clang::Expr* expr,
+    const clang::CXXRecordDecl* variant,
+    const clang::CXXRecordDecl* gc_type) {
+  ReportDiagnostic(expr->getBeginLoc(), diag_variant_used_with_gc_)
+      << variant << gc_type << expr->getSourceRange();
+}
diff --git a/tools/clang/blink_gc_plugin/DiagnosticsReporter.h b/tools/clang/blink_gc_plugin/DiagnosticsReporter.h
index fea2d877..24cf7a1b 100644
--- a/tools/clang/blink_gc_plugin/DiagnosticsReporter.h
+++ b/tools/clang/blink_gc_plugin/DiagnosticsReporter.h
@@ -82,6 +82,10 @@
   void OptionalUsedWithGC(const clang::Expr* expr,
                           const clang::CXXRecordDecl* optional,
                           const clang::CXXRecordDecl* gc_type);
+  void VariantUsedWithGC(const clang::Expr* expr,
+                         const clang::CXXRecordDecl* variant,
+                         const clang::CXXRecordDecl* gc_type);
+
  private:
   clang::DiagnosticBuilder ReportDiagnostic(
       clang::SourceLocation location,
@@ -139,6 +143,7 @@
 
   unsigned diag_unique_ptr_used_with_gc_;
   unsigned diag_optional_used_with_gc_;
+  unsigned diag_variant_used_with_gc_;
 };
 
 #endif // TOOLS_BLINK_GC_PLUGIN_DIAGNOSTICS_REPORTER_H_
diff --git a/tools/clang/blink_gc_plugin/tests/heap/stubs.h b/tools/clang/blink_gc_plugin/tests/heap/stubs.h
index 9d5fc9a..b36bf93 100644
--- a/tools/clang/blink_gc_plugin/tests/heap/stubs.h
+++ b/tools/clang/blink_gc_plugin/tests/heap/stubs.h
@@ -174,6 +174,13 @@
 
 }  // namespace base
 
+namespace absl {
+
+template <class... Ts>
+class variant {};
+
+}  // namespace absl
+
 namespace blink {
 
 using namespace WTF;
diff --git a/tools/clang/blink_gc_plugin/tests/stack_allocated.txt b/tools/clang/blink_gc_plugin/tests/stack_allocated.txt
index de5836a..ced10d1 100644
--- a/tools/clang/blink_gc_plugin/tests/stack_allocated.txt
+++ b/tools/clang/blink_gc_plugin/tests/stack_allocated.txt
@@ -23,7 +23,7 @@
 ./stack_allocated.h:44:3: warning: [blink-gc] Garbage collected class 'DerivedHeapObject2' is not permitted to override its new operator.
   STACK_ALLOCATED();
   ^
-./heap/stubs.h:188:5: note: expanded from macro 'STACK_ALLOCATED'
+./heap/stubs.h:195:5: note: expanded from macro 'STACK_ALLOCATED'
     __attribute__((annotate("blink_stack_allocated")))      \
     ^
 In file included from stack_allocated.cpp:5:
diff --git a/tools/clang/blink_gc_plugin/tests/variant_of_gced_type.cpp b/tools/clang/blink_gc_plugin/tests/variant_of_gced_type.cpp
new file mode 100644
index 0000000..6db1991
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/variant_of_gced_type.cpp
@@ -0,0 +1,25 @@
+// Copyright 2017 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 "variant_of_gced_type.h"
+
+namespace blink {
+
+void ForbidsVariantsOfGcedTypes() {
+  absl::variant<Base> not_ok;
+  (void)not_ok;
+
+  absl::variant<Base, Base> similarly_not_ok;
+  (void)similarly_not_ok;
+
+  absl::variant<int, Base> not_ok_either;
+  (void)not_ok_either;
+
+  absl::variant<int, Derived> ditto;
+  (void)ditto;
+
+  new absl::variant<Mixin>;
+}
+
+}  // namespace blink
diff --git a/tools/clang/blink_gc_plugin/tests/variant_of_gced_type.h b/tools/clang/blink_gc_plugin/tests/variant_of_gced_type.h
new file mode 100644
index 0000000..0f0a73e
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/variant_of_gced_type.h
@@ -0,0 +1,29 @@
+// 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 TOOLS_CLANG_BLINK_GC_PLUGIN_TESTS_VARIANT_OF_GCED_TYPE_H_
+#define TOOLS_CLANG_BLINK_GC_PLUGIN_TESTS_VARIANT_OF_GCED_TYPE_H_
+
+#include "heap/stubs.h"
+
+namespace blink {
+
+class Base : public GarbageCollected<Base> {
+ public:
+  virtual void Trace(Visitor*) const {}
+};
+
+class Derived : public Base {
+ public:
+  void Trace(Visitor* visitor) const override { Base::Trace(visitor); }
+};
+
+class Mixin : public GarbageCollectedMixin {
+ public:
+  void Trace(Visitor*) const {}
+};
+
+}  // namespace blink
+
+#endif  // TOOLS_CLANG_BLINK_GC_PLUGIN_TESTS_VARIANT_OF_GCED_TYPE_H_
diff --git a/tools/clang/blink_gc_plugin/tests/variant_of_gced_type.txt b/tools/clang/blink_gc_plugin/tests/variant_of_gced_type.txt
new file mode 100644
index 0000000..fe7121f1
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/variant_of_gced_type.txt
@@ -0,0 +1,16 @@
+variant_of_gced_type.cpp:10:23: warning: [blink-gc] Disallowed construction of 'variant<blink::Base>' found; 'Base' is a garbage-collected type. absl::variant cannot hold garbage-collected objects.
+  absl::variant<Base> not_ok;
+                      ^~~~~~
+variant_of_gced_type.cpp:13:29: warning: [blink-gc] Disallowed construction of 'variant<blink::Base, blink::Base>' found; 'Base' is a garbage-collected type. absl::variant cannot hold garbage-collected objects.
+  absl::variant<Base, Base> similarly_not_ok;
+                            ^~~~~~~~~~~~~~~~
+variant_of_gced_type.cpp:16:28: warning: [blink-gc] Disallowed construction of 'variant<int, blink::Base>' found; 'Base' is a garbage-collected type. absl::variant cannot hold garbage-collected objects.
+  absl::variant<int, Base> not_ok_either;
+                           ^~~~~~~~~~~~~
+variant_of_gced_type.cpp:19:31: warning: [blink-gc] Disallowed construction of 'variant<int, blink::Derived>' found; 'Derived' is a garbage-collected type. absl::variant cannot hold garbage-collected objects.
+  absl::variant<int, Derived> ditto;
+                              ^~~~~
+variant_of_gced_type.cpp:22:7: warning: [blink-gc] Disallowed construction of 'variant<blink::Mixin>' found; 'Mixin' is a garbage-collected type. absl::variant cannot hold garbage-collected objects.
+  new absl::variant<Mixin>;
+      ^~~~
+5 warnings generated.
diff --git a/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp b/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
index 61836c6..e9dad109 100644
--- a/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
+++ b/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
@@ -853,16 +853,11 @@
   //     int (*func_ptr)();
   //     int (MyStruct::* member_func_ptr)(char);
   //     int (*ptr_to_array_of_ints)[123]
-  //     StructOrClassWithDeletedOperatorNew* stack_or_gc_ptr;
   //   };
   // matches |int*|, but not the other types.
-  auto record_with_deleted_allocation_operator_type_matcher =
-      recordType(hasDeclaration(cxxRecordDecl(
-          hasMethod(allOf(hasOverloadedOperatorName("new"), isDeleted())))));
   auto supported_pointer_types_matcher =
       pointerType(unless(pointee(hasUnqualifiedDesugaredType(
-          anyOf(record_with_deleted_allocation_operator_type_matcher,
-                functionType(), memberPointerType(), arrayType())))));
+          anyOf(functionType(), memberPointerType(), arrayType())))));
 
   // Implicit field declarations =========
   // Matches field declarations that do not explicitly appear in the source
@@ -898,7 +893,7 @@
       fieldDecl(
           allOf(hasType(supported_pointer_types_matcher),
                 unless(anyOf(isExpansionInSystemHeader(), isInExternCContext(),
-                             isInThirdPartyLocation(), isInGeneratedLocation(),
+                             isInThirdPartyLocation(),
                              isInLocationListedInFilterFile(&paths_to_exclude),
                              isFieldDeclListedInFilterFile(&fields_to_exclude),
                              implicit_field_decl_matcher))))
@@ -1063,6 +1058,46 @@
                                               "global-destructor");
   match_finder.addMatcher(global_destructor_matcher, &global_destructor_writer);
 
+  // Matches rewritable fields in generated code - see the testcase in
+  // tests/gen-generated-code-test.cc
+  auto field_in_generated_code_matcher =
+      fieldDecl(allOf(field_decl_matcher, isInGeneratedLocation()));
+  FilteredExprWriter field_in_generated_code_writer(&output_helper,
+                                                    "generated-code");
+  match_finder.addMatcher(field_in_generated_code_matcher,
+                          &field_in_generated_code_writer);
+
+  // Matches CXXRecordDecls with a deleted operator new - e.g.
+  // StructWithNoOperatorNew below:
+  //     struct StructWithNoOperatorNew {
+  //       void* operator new(size_t) = delete;
+  //     };
+  auto record_with_deleted_allocation_operator_type_matcher = cxxRecordDecl(
+      hasMethod(allOf(hasOverloadedOperatorName("new"), isDeleted())));
+  // Matches rewritable fields inside structs with no operator new.  See the
+  // testcase in tests/gen-deleted-operator-new-test.cc
+  auto field_in_record_with_deleted_operator_new_matcher = fieldDecl(
+      allOf(field_decl_matcher,
+            hasParent(record_with_deleted_allocation_operator_type_matcher)));
+  FilteredExprWriter field_in_record_with_deleted_operator_new_writer(
+      &output_helper, "embedder-has-no-operator-new");
+  match_finder.addMatcher(field_in_record_with_deleted_operator_new_matcher,
+                          &field_in_record_with_deleted_operator_new_writer);
+  // Matches rewritable fields that contain a pointer, pointing to a pointee
+  // with no operator new.  See the testcase in
+  // tests/gen-deleted-operator-new-test.cc
+  auto field_pointing_to_record_with_deleted_operator_new_matcher =
+      fieldDecl(allOf(
+          field_decl_matcher,
+          hasType(pointerType(
+              pointee(hasUnqualifiedDesugaredType(recordType(hasDeclaration(
+                  record_with_deleted_allocation_operator_type_matcher))))))));
+  FilteredExprWriter field_pointing_to_record_with_deleted_operator_new_writer(
+      &output_helper, "pointee-has-no-operator-new");
+  match_finder.addMatcher(
+      field_pointing_to_record_with_deleted_operator_new_matcher,
+      &field_pointing_to_record_with_deleted_operator_new_writer);
+
   // Matches fields in unions - see the testcases in tests/gen-unions-test.cc.
   auto union_field_decl_matcher = fieldDecl(
       allOf(field_decl_matcher, hasParent(decl(recordDecl(isUnion())))));
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-expected.cc b/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-expected.cc
index 4444513..c5351b20 100644
--- a/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-expected.cc
+++ b/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-expected.cc
@@ -8,7 +8,6 @@
 #include <utility>  // for std::swap
 
 #include "base/memory/checked_ptr.h"
-#include "gen/generated_header.h"
 
 class SomeClass {};
 class DerivedClass : public SomeClass {};
@@ -173,20 +172,6 @@
 
 }  // namespace ternary_operator_tests
 
-namespace generated_code_tests {
-
-void MyPrintf(const char* fmt, ...) {}
-
-void foo() {
-  GeneratedStruct s;
-
-  // No rewrite expected below (i.e. no |.get()| appended), because the field
-  // dereferenced below comes from (simulated) generated code.
-  MyPrintf("%p", s.ptr_field);
-}
-
-}  // namespace generated_code_tests
-
 namespace templated_functions {
 
 template <typename T>
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-original.cc b/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-original.cc
index efa8857..a042ae90 100644
--- a/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-original.cc
+++ b/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-original.cc
@@ -7,8 +7,6 @@
 #include <tuple>    // for std::tie
 #include <utility>  // for std::swap
 
-#include "gen/generated_header.h"
-
 class SomeClass {};
 class DerivedClass : public SomeClass {};
 
@@ -172,20 +170,6 @@
 
 }  // namespace ternary_operator_tests
 
-namespace generated_code_tests {
-
-void MyPrintf(const char* fmt, ...) {}
-
-void foo() {
-  GeneratedStruct s;
-
-  // No rewrite expected below (i.e. no |.get()| appended), because the field
-  // dereferenced below comes from (simulated) generated code.
-  MyPrintf("%p", s.ptr_field);
-}
-
-}  // namespace generated_code_tests
-
 namespace templated_functions {
 
 template <typename T>
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/gen-deleted-operator-new-expected.txt b/tools/clang/rewrite_raw_ptr_fields/tests/gen-deleted-operator-new-expected.txt
new file mode 100644
index 0000000..2c91790
--- /dev/null
+++ b/tools/clang/rewrite_raw_ptr_fields/tests/gen-deleted-operator-new-expected.txt
@@ -0,0 +1,9 @@
+==== BEGIN EDITS ====
+include-user-header:::/usr/local/google/home/lukasza/src/chromium4/src/tools/clang/rewrite_raw_ptr_fields/tests/gen-deleted-operator-new-actual.cc:::-1:::-1:::base/memory/checked_ptr.h
+r:::/usr/local/google/home/lukasza/src/chromium4/src/tools/clang/rewrite_raw_ptr_fields/tests/gen-deleted-operator-new-actual.cc:::1837:::5:::CheckedPtr<int> 
+r:::/usr/local/google/home/lukasza/src/chromium4/src/tools/clang/rewrite_raw_ptr_fields/tests/gen-deleted-operator-new-actual.cc:::2313:::15:::CheckedPtr<NoNewOperator> 
+==== END EDITS ====
+==== BEGIN FIELD FILTERS ====
+MyStruct::pointer_to_pointee_with_no_operator_new  # pointee-has-no-operator-new
+NoNewOperator::field_in_struct_with_no_operator_new  # embedder-has-no-operator-new
+==== END FIELD FILTERS ====
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/gen-deleted-operator-new-test.cc b/tools/clang/rewrite_raw_ptr_fields/tests/gen-deleted-operator-new-test.cc
new file mode 100644
index 0000000..70f862a
--- /dev/null
+++ b/tools/clang/rewrite_raw_ptr_fields/tests/gen-deleted-operator-new-test.cc
@@ -0,0 +1,46 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+
+// This file (and other gen-*-test.cc files) tests generation of output for
+// --field-filter-file and therefore the expectations file
+// (gen-char-expected.txt) needs to be compared against the raw output of the
+// rewriter (rather than against the actual edits result).  This makes the test
+// incompatible with other tests, which require passing --apply-edits switch to
+// test_tool.py and so to disable the test it is named *-test.cc rather than
+// *-original.cc.
+//
+// To run the test use tools/clang/rewrite_raw_ptr_fields/tests/run_all_tests.py
+
+// The class below deletes the |operator new| - this simulate's Blink's
+// STACK_ALLOCATED macro and/or OilPan / GarbageCollected<T> classes.
+//
+// We assume that NoNewOperator classes are never allocated on the heap (i.e.
+// are never managed by PartitionAlloc) and therefore would not benefit from
+// the protection of CheckedPtr.  This assumption/heuristic is generally true,
+// but not always - for details how WTF::Vector can allocate elements without
+// operator new, see (Google-internal)
+// https://groups.google.com/a/google.com/g/chrome-memory-safety/c/GybWkNGqSyk/m/pUOjMvK5CQAJ
+class NoNewOperator {
+  void* operator new(size_t) = delete;
+
+  // Based on the deleted-oparator-new assumption/heuristic above, we assume
+  // that NoNewOperator will always be allocated on the stack or in OilPan and
+  // therefore doesn't need CheckedPtr protection (since it will be protected
+  // either by StackScanning or by OilPan's tracing and GC).  Therefore,
+  // |no_operator_new_struct| should be emitted as candidates for the
+  // --field-filter-file with "embedder-has-no-operator-new" tag.
+  int* field_in_struct_with_no_operator_new;
+};
+
+struct MyStruct {
+  // Based on the deleted-oparator-new assumption/heuristic above, we assume
+  // that NoNewOperator is never allocated on the PartitionAlloc-managed heap.
+  // This means that CheckedPtr would always be disabled for the field below and
+  // therefore the test below checks that |no_operator_new_pointee| is emitted
+  // as a candidate for the --field-filter-file with
+  // "pointee-has-no-operator-new" tag.
+  NoNewOperator* pointer_to_pointee_with_no_operator_new;
+};
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/gen-generated-code-expected.txt b/tools/clang/rewrite_raw_ptr_fields/tests/gen-generated-code-expected.txt
new file mode 100644
index 0000000..0399cfd1
--- /dev/null
+++ b/tools/clang/rewrite_raw_ptr_fields/tests/gen-generated-code-expected.txt
@@ -0,0 +1,9 @@
+==== BEGIN EDITS ====
+include-user-header:::/usr/local/google/home/lukasza/src/chromium4/src/tools/clang/rewrite_raw_ptr_fields/tests/gen/generated_header.h:::-1:::-1:::base/memory/checked_ptr.h
+r:::/usr/local/google/home/lukasza/src/chromium4/src/tools/clang/rewrite_raw_ptr_fields/tests/gen/generated_header.h:::552:::5:::CheckedPtr<int> 
+r:::/usr/local/google/home/lukasza/src/chromium4/src/tools/clang/rewrite_raw_ptr_fields/tests/gen/generated_header.h:::570:::11:::CheckedPtr<SomeClass> 
+==== END EDITS ====
+==== BEGIN FIELD FILTERS ====
+GeneratedStruct::ptr_field  # generated-code
+GeneratedStruct::ptr_field2  # generated-code
+==== END FIELD FILTERS ====
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/gen-generated-code-test.cc b/tools/clang/rewrite_raw_ptr_fields/tests/gen-generated-code-test.cc
new file mode 100644
index 0000000..5770ddb
--- /dev/null
+++ b/tools/clang/rewrite_raw_ptr_fields/tests/gen-generated-code-test.cc
@@ -0,0 +1,17 @@
+// 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.
+
+// This file (and other gen-*-test.cc files) tests generation of output for
+// --field-filter-file and therefore the expectations file
+// (gen-char-expected.txt) needs to be compared against the raw output of the
+// rewriter (rather than against the actual edits result).  This makes the test
+// incompatible with other tests, which require passing --apply-edits switch to
+// test_tool.py and so to disable the test it is named *-test.cc rather than
+// *-original.cc.
+//
+// To run the test use tools/clang/rewrite_raw_ptr_fields/tests/run_all_tests.py
+
+// Fields in "gen/generated_header.h" should be emitted be emitted as candidates
+// for the --field-filter-file.
+#include "gen/generated_header.h"
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/various-types-expected.cc b/tools/clang/rewrite_raw_ptr_fields/tests/various-types-expected.cc
index d96ac5a..190b6b9f 100644
--- a/tools/clang/rewrite_raw_ptr_fields/tests/various-types-expected.cc
+++ b/tools/clang/rewrite_raw_ptr_fields/tests/various-types-expected.cc
@@ -23,16 +23,7 @@
   T t;
 };
 
-// The class below deletes the |operator new| - this simulate's Blink's
-// STACK_ALLOCATED macro and/or OilPan / GarbageCollected<T> classes.
-class NoNewOperator {
-  void* operator new(size_t) = delete;
-};
-
 struct MyStruct {
-  // No rewrite expected for classes with no |operator new|.
-  NoNewOperator* no_new_ptr;
-
   // Expected rewrite: CheckedPtr<CheckedPtr<SomeClass>> double_ptr;
   // TODO(lukasza): Handle recursion/nesting.
   CheckedPtr<SomeClass*> double_ptr;
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/various-types-original.cc b/tools/clang/rewrite_raw_ptr_fields/tests/various-types-original.cc
index 935ba32c..c8494fc 100644
--- a/tools/clang/rewrite_raw_ptr_fields/tests/various-types-original.cc
+++ b/tools/clang/rewrite_raw_ptr_fields/tests/various-types-original.cc
@@ -21,16 +21,7 @@
   T t;
 };
 
-// The class below deletes the |operator new| - this simulate's Blink's
-// STACK_ALLOCATED macro and/or OilPan / GarbageCollected<T> classes.
-class NoNewOperator {
-  void* operator new(size_t) = delete;
-};
-
 struct MyStruct {
-  // No rewrite expected for classes with no |operator new|.
-  NoNewOperator* no_new_ptr;
-
   // Expected rewrite: CheckedPtr<CheckedPtr<SomeClass>> double_ptr;
   // TODO(lukasza): Handle recursion/nesting.
   SomeClass** double_ptr;
diff --git a/tools/clang/scripts/test_tool.py b/tools/clang/scripts/test_tool.py
index 00190937..1980441 100755
--- a/tools/clang/scripts/test_tool.py
+++ b/tools/clang/scripts/test_tool.py
@@ -97,6 +97,7 @@
           os.path.join(tools_clang_scripts_directory, 'apply_edits.py'), '-p',
           test_directory_for_tool
       ]
+      args.extend(actual_files)  # Limit edits to the test files.
       processes.append(subprocess.Popen(
           args, stdin=processes[-1].stdout, stdout=subprocess.PIPE))
 
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec
index 212a8e60..9a1bce9 100644
--- a/tools/gritsettings/resource_ids.spec
+++ b/tools/gritsettings/resource_ids.spec
@@ -225,12 +225,9 @@
   "chrome/browser/resources/bluetooth_internals/resources.grd": {
     "includes": [2020],
   },
-    "chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources.grd": {
+  "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources.grd": {
+    "META": {"sizes": {"includes": [10],}},
     "includes": [2030],
-    "structures": [2050],
-  },
-  "chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources_vulcanized.grd": {
-    "includes": [2070],
   },
   "chrome/browser/resources/gaia_auth_host/gaia_auth_host_resources.grd": {
     "includes": [2080],
@@ -259,12 +256,9 @@
   "chrome/browser/resources/webapks/webapks_ui_resources.grd": {
     "includes": [2220],
   },
-  "chrome/browser/resources/webui_js_exception/webui_js_exception_resources.grd": {
+  "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/webui_js_exception/webui_js_exception_resources.grd": {
+    "META": {"sizes": {"includes": [10],}},
     "includes": [2230],
-    "structures": [2231],
-  },
-  "chrome/browser/resources/webui_js_exception/webui_js_exception_resources_vulcanized.grd": {
-    "includes": [2232],
   },
   "components/sync/driver/resources.grd": {
     "includes": [2240],
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 5d497ca..2bb93c0 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -126,7 +126,7 @@
 
     'chromium.android.fyi': {
       'Android WebView P FYI (rel)': 'android_release_bot_minimal_symbols_arm64_webview_google',
-      'android-inverse-fieldtrials-pie-x86-fyi-rel': 'android_release_bot_minimal_symbols_x86_fastbuild_webview_google',
+      'android-inverse-fieldtrials-pie-x86-fyi-rel': 'android_release_bot_minimal_symbols_x86_fastbuild_webview_google_invert_fieldtrials',
       'android-pie-arm64-wpt-rel-non-cq': 'android_release_bot_minimal_symbols_arm64_webview_google',
       'android-weblayer-x86-fyi-rel': 'android_release_bot_minimal_symbols_x86_fastbuild_webview_google',
       'android-weblayer-pie-x86-fyi-rel': 'android_release_bot_minimal_symbols_x86_fastbuild_webview_google',
@@ -755,7 +755,7 @@
       # shared library loading is fixed.
       'android-cronet-arm-dbg': 'android_cronet_debug_static_bot_arm_no_neon',
       'android-cronet-marshmallow-arm64-rel': 'android_cronet_release_trybot_arm64',
-      'android-inverse-fieldtrials-pie-x86-fyi-rel': 'android_release_trybot_x86_fastbuild_webview_google',
+      'android-inverse-fieldtrials-pie-x86-fyi-rel': 'android_release_trybot_x86_fastbuild_webview_google_invert_fieldtrials',
       'android-lollipop-arm-rel': 'android_release_trybot_webview_google',
       'android-marshmallow-arm64-rel': 'gpu_tests_android_release_trybot_arm64_resource_whitelisting_fastbuild_java_coverage',
       'android-marshmallow-x86-rel': 'android_release_trybot_x86_fastbuild_resource_whitelisting_webview_google',
@@ -1330,6 +1330,12 @@
       'strip_debug_info', 'android_fastbuild', 'webview_google',
     ],
 
+    'android_release_bot_minimal_symbols_x86_fastbuild_webview_google_invert_fieldtrials': [
+      'android', 'release_bot', 'minimal_symbols', 'x86',
+      'strip_debug_info', 'android_fastbuild', 'webview_google',
+      'invert_fieldtrials',
+    ],
+
     'android_release_trybot': [
       'android', 'release_trybot', 'strip_debug_info',
     ],
@@ -1374,6 +1380,11 @@
       'android_fastbuild', 'webview_google',
     ],
 
+    'android_release_trybot_x86_fastbuild_webview_google_invert_fieldtrials': [
+      'android', 'release_trybot', 'strip_debug_info', 'x86',
+      'android_fastbuild', 'webview_google', 'invert_fieldtrials'
+    ],
+
     'android_webview_google_debug_static_bot': [
       'android', 'debug_static_bot', 'webview_google',
     ],
@@ -2029,45 +2040,44 @@
     'ios_error': [ 'error'],
 
     'ios_clang_tot_xctest': [
-      'clang_tot', 'ios_simulator', 'ios_disable_code_signing', 'release', 'static', 'xctest',
+      'clang_tot', 'ios', 'ios_simulator', 'ios_cpu_x64', 'ios_disable_code_signing', 'release', 'static', 'xctest',
     ],
 
     'ios_clang_device_tot_xctest': [
-      'clang_tot', 'ios_device', 'release', 'ios_chromium_cert', 'xctest',
+      'clang_tot', 'ios', 'ios_device', 'ios_cpu_arm64', 'release', 'ios_chromium_cert', 'xctest',
     ],
 
     'ios_cronet_xctest': [
-      'additional_target_cpus_x86', 'cronet_ios', 'debug_static_bot',
-      'ios_deployment_target_10_0', 'ios_simulator', 'xctest',
+      'additional_target_cpus_x86', 'cronet_ios', 'debug_static_bot', 'ios_deployment_target_10_0', 'ios', 'ios_simulator', 'ios_cpu_x64', 'xctest',
     ],
 
     'ios_device_release_compile_only': [
-        'compile_only', 'ios_device', 'ios_google_cert', 'ios_disable_code_signing', 'release_bot'
+        'compile_only', 'ios', 'ios_device', 'ios_cpu_arm64', 'ios_google_cert', 'ios_disable_code_signing', 'release_bot'
     ],
 
     'ios_device_release_rbe_compile_only': [
-        'compile_only', 'ios_device', 'ios_google_cert', 'ios_disable_code_signing', 'ios_use_goma_rbe', 'release_bot'
+        'compile_only', 'ios', 'ios_device', 'ios_cpu_arm64', 'ios_google_cert', 'ios_disable_code_signing', 'ios_use_goma_rbe', 'release_bot'
     ],
 
     # doesn't have symbol_level=0
     'ios_device_release_static_rbe_bot_xctest': [
-        'ios_device', 'ios_disable_code_signing', 'ios_use_goma_rbe', 'release_bot', 'xctest',
+        'ios', 'ios_device', 'ios_cpu_arm64', 'ios_disable_code_signing', 'ios_use_goma_rbe', 'release_bot', 'xctest',
     ],
 
     'ios_simulator_debug_static_bot_xctest': [
-        'debug_static_bot', 'ios_simulator', 'xctest',
+        'debug_static_bot', 'ios', 'ios_simulator', 'ios_cpu_x64', 'xctest',
     ],
 
     'ios_simulator_debug_static_bot_multi_window_xctest': [
-        'debug_static_bot', 'ios_enable_multi_window', 'ios_simulator', 'xctest',
+        'debug_static_bot', 'ios_enable_multi_window', 'ios', 'ios_simulator', 'ios_cpu_x64', 'xctest',
     ],
 
     'ios_simulator_debug_static_rbe_bot_xctest': [
-        'debug_static_bot', 'ios_simulator', 'ios_use_goma_rbe', 'xctest',
+        'debug_static_bot', 'ios', 'ios_simulator', 'ios_cpu_x64', 'ios_use_goma_rbe', 'xctest',
     ],
 
     'ios_simulator_release_static_asan_bot_xctest': [
-        'ios_simulator', 'release_bot', 'asan', 'xctest',
+        'ios', 'ios_simulator', 'ios_cpu_x64', 'release_bot', 'asan', 'xctest',
     ],
 
     'lacros_on_linux_release_bot': [
@@ -2761,8 +2771,7 @@
     },
 
     'fuzzer': {
-      # TODO(crbug.com/1140770): Remove use_vaapi=false once fixed.
-      'gn_args': 'enable_ipc_fuzzer=true use_vaapi=false',
+      'gn_args': 'enable_ipc_fuzzer=true',
     },
 
     'gn_linux_upload': {
@@ -2826,11 +2835,22 @@
       'gn_args': 'ios_deployment_target=\"10.0\"',
     },
 
-    'ios_device': {
-      'mixins': ['ios'],
+    'ios_cpu_x64': {
+      'gn_args': 'target_cpu="x64"',
+    },
+
+    'ios_cpu_arm64': {
       'gn_args': 'target_cpu="arm64"',
     },
 
+    'ios_device': {
+      'gn_args': 'target_environment="device"',
+    },
+
+    'ios_simulator': {
+      'gn_args': 'target_environment="simulator"',
+    },
+
     'ios_disable_code_signing': {
       # defaults to true under ios_sdk.gni
       'gn_args': 'ios_enable_code_signing=false'
@@ -2840,11 +2860,6 @@
       'gn_args': 'ios_enable_multi_window=true'
     },
 
-    'ios_simulator': {
-      'mixins': ['ios'],
-      'gn_args': 'target_cpu="x64"',
-    },
-
     'ios_use_goma_rbe': {
       'gn_args': 'ios_use_goma_rbe=true'
     },
diff --git a/tools/mb/mb_config_expectations/chromium.android.fyi.json b/tools/mb/mb_config_expectations/chromium.android.fyi.json
index a933bea..4dfff764 100644
--- a/tools/mb/mb_config_expectations/chromium.android.fyi.json
+++ b/tools/mb/mb_config_expectations/chromium.android.fyi.json
@@ -17,6 +17,7 @@
     "gn_args": {
       "disable_android_lint": true,
       "ffmpeg_branding": "Chrome",
+      "invert_fieldtrials": true,
       "is_component_build": false,
       "is_debug": false,
       "proprietary_codecs": true,
diff --git a/tools/mb/mb_config_expectations/chromium.clang.json b/tools/mb/mb_config_expectations/chromium.clang.json
index 0d5e3d6..7dd3c5c 100644
--- a/tools/mb/mb_config_expectations/chromium.clang.json
+++ b/tools/mb/mb_config_expectations/chromium.clang.json
@@ -35,7 +35,6 @@
       "is_debug": false,
       "llvm_force_head_revision": true,
       "symbol_level": 1,
-      "use_vaapi": false,
       "v8_enable_verify_heap": true
     }
   },
@@ -410,6 +409,7 @@
       "is_debug": false,
       "llvm_force_head_revision": true,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios"
     }
   },
@@ -421,6 +421,7 @@
       "is_debug": false,
       "llvm_force_head_revision": true,
       "target_cpu": "arm64",
+      "target_environment": "device",
       "target_os": "ios"
     }
   },
diff --git a/tools/mb/mb_config_expectations/chromium.fuzz.json b/tools/mb/mb_config_expectations/chromium.fuzz.json
index 96fbdc4..cc24799 100644
--- a/tools/mb/mb_config_expectations/chromium.fuzz.json
+++ b/tools/mb/mb_config_expectations/chromium.fuzz.json
@@ -17,7 +17,6 @@
       "is_debug": false,
       "is_lsan": true,
       "use_goma": true,
-      "use_vaapi": false,
       "v8_enable_verify_heap": true
     }
   },
@@ -55,7 +54,6 @@
       "is_debug": false,
       "target_cpu": "x86",
       "use_goma": true,
-      "use_vaapi": false,
       "v8_enable_verify_heap": true,
       "v8_target_cpu": "arm"
     }
@@ -71,7 +69,6 @@
       "proprietary_codecs": true,
       "target_cpu": "x86",
       "use_goma": true,
-      "use_vaapi": false,
       "v8_enable_verify_heap": true,
       "v8_target_cpu": "arm"
     }
@@ -100,7 +97,6 @@
       "is_lsan": true,
       "target_os": "chromeos",
       "use_goma": true,
-      "use_vaapi": false,
       "v8_enable_verify_heap": true
     }
   },
@@ -344,7 +340,6 @@
       "is_component_build": false,
       "is_debug": false,
       "use_goma": true,
-      "use_vaapi": false,
       "v8_enable_verify_heap": true
     }
   },
@@ -358,7 +353,6 @@
       "is_debug": false,
       "proprietary_codecs": true,
       "use_goma": true,
-      "use_vaapi": false,
       "v8_enable_verify_heap": true
     }
   },
@@ -406,7 +400,6 @@
       "is_component_build": false,
       "is_debug": false,
       "use_goma": true,
-      "use_vaapi": false,
       "v8_enable_verify_heap": true
     }
   },
@@ -420,7 +413,6 @@
       "is_debug": false,
       "proprietary_codecs": true,
       "use_goma": true,
-      "use_vaapi": false,
       "v8_enable_verify_heap": true
     }
   }
diff --git a/tools/mb/mb_config_expectations/chromium.fyi.json b/tools/mb/mb_config_expectations/chromium.fyi.json
index c591e96..c82b1d0 100644
--- a/tools/mb/mb_config_expectations/chromium.fyi.json
+++ b/tools/mb/mb_config_expectations/chromium.fyi.json
@@ -354,6 +354,7 @@
       "is_component_build": false,
       "is_debug": false,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
@@ -378,6 +379,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
@@ -400,6 +402,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_allocator_shim": false,
       "use_crash_key_stubs": true,
@@ -415,6 +418,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
@@ -427,6 +431,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
@@ -438,6 +443,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
@@ -450,6 +456,7 @@
       "is_component_build": false,
       "is_debug": false,
       "target_cpu": "arm64",
+      "target_environment": "device",
       "target_os": "ios",
       "use_goma": true
     }
@@ -462,6 +469,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
@@ -473,6 +481,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
@@ -485,6 +494,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
diff --git a/tools/mb/mb_config_expectations/chromium.goma.fyi.json b/tools/mb/mb_config_expectations/chromium.goma.fyi.json
index 82b6a9d..318e43b 100644
--- a/tools/mb/mb_config_expectations/chromium.goma.fyi.json
+++ b/tools/mb/mb_config_expectations/chromium.goma.fyi.json
@@ -319,6 +319,7 @@
       "is_debug": false,
       "symbol_level": 0,
       "target_cpu": "arm64",
+      "target_environment": "device",
       "target_os": "ios",
       "use_goma": true
     }
@@ -331,6 +332,7 @@
       "is_debug": false,
       "symbol_level": 0,
       "target_cpu": "arm64",
+      "target_environment": "device",
       "target_os": "ios",
       "use_goma": true
     }
@@ -344,6 +346,7 @@
       "is_debug": false,
       "symbol_level": 0,
       "target_cpu": "arm64",
+      "target_environment": "device",
       "target_os": "ios",
       "use_goma": true
     }
@@ -357,6 +360,7 @@
       "is_debug": false,
       "symbol_level": 0,
       "target_cpu": "arm64",
+      "target_environment": "device",
       "target_os": "ios",
       "use_goma": true
     }
diff --git a/tools/mb/mb_config_expectations/chromium.goma.json b/tools/mb/mb_config_expectations/chromium.goma.json
index 7b5d3eda..d9b484f8 100644
--- a/tools/mb/mb_config_expectations/chromium.goma.json
+++ b/tools/mb/mb_config_expectations/chromium.goma.json
@@ -157,6 +157,7 @@
       "is_debug": false,
       "symbol_level": 0,
       "target_cpu": "arm64",
+      "target_environment": "device",
       "target_os": "ios",
       "use_goma": true
     }
diff --git a/tools/mb/mb_config_expectations/chromium.mac.json b/tools/mb/mb_config_expectations/chromium.mac.json
index a11fd1f..1a31f22 100644
--- a/tools/mb/mb_config_expectations/chromium.mac.json
+++ b/tools/mb/mb_config_expectations/chromium.mac.json
@@ -29,6 +29,7 @@
       "is_debug": false,
       "symbol_level": 0,
       "target_cpu": "arm64",
+      "target_environment": "device",
       "target_os": "ios",
       "use_goma": true
     }
@@ -41,6 +42,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
@@ -52,6 +54,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
@@ -64,6 +67,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
diff --git a/tools/mb/mb_config_expectations/chromium.memory.json b/tools/mb/mb_config_expectations/chromium.memory.json
index 4e746ab3..a683fab 100644
--- a/tools/mb/mb_config_expectations/chromium.memory.json
+++ b/tools/mb/mb_config_expectations/chromium.memory.json
@@ -142,7 +142,6 @@
       "is_debug": false,
       "symbol_level": 1,
       "use_goma": true,
-      "use_vaapi": false,
       "v8_enable_verify_heap": true
     }
   }
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.android.json b/tools/mb/mb_config_expectations/tryserver.chromium.android.json
index adfd41c..10fa0a3 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.android.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.android.json
@@ -137,6 +137,7 @@
       "dcheck_always_on": true,
       "disable_android_lint": true,
       "ffmpeg_branding": "Chrome",
+      "invert_fieldtrials": true,
       "is_component_build": false,
       "is_debug": false,
       "proprietary_codecs": true,
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
index c185068d..302eeb7 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
@@ -216,6 +216,7 @@
       "is_debug": false,
       "symbol_level": 0,
       "target_cpu": "arm64",
+      "target_environment": "device",
       "target_os": "ios",
       "use_goma": true
     }
@@ -228,6 +229,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
@@ -253,6 +255,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
@@ -275,6 +278,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_allocator_shim": false,
       "use_crash_key_stubs": true,
@@ -289,6 +293,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
@@ -301,6 +306,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
@@ -313,6 +319,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
@@ -325,6 +332,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
@@ -337,6 +345,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
@@ -349,6 +358,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
@@ -361,6 +371,7 @@
       "is_debug": true,
       "symbol_level": 1,
       "target_cpu": "x64",
+      "target_environment": "simulator",
       "target_os": "ios",
       "use_goma": true
     }
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.win.json b/tools/mb/mb_config_expectations/tryserver.chromium.win.json
index c8dfff1..fd8ab91e 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.win.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.win.json
@@ -241,7 +241,6 @@
       "is_debug": false,
       "symbol_level": 1,
       "use_goma": true,
-      "use_vaapi": false,
       "v8_enable_verify_heap": true
     }
   },
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index e3bb4ed..59bbacc 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -1653,7 +1653,7 @@
 
 <action name="Android.BookmarkPage.RemoveItem">
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     User removed an item on the native Android bookmark page by clicking
     &quot;delete&quot; from the &quot;more&quot; menu.
@@ -1662,7 +1662,7 @@
 
 <action name="Android.BookmarkPage.SelectFromMenu">
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     User selected an item on the native Android bookmark page by clicking
     &quot;select&quot; from the &quot;more&quot; menu.
@@ -1903,7 +1903,7 @@
 
 <action name="Android.DarkTheme.Preference">
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     User changed preference to use system default, light, or dark theme.
   </description>
@@ -2402,7 +2402,7 @@
 
 <action name="Android.LifeCycle.HasPausedActivities">
   <owner>ssid@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     Chrome application has at least one paused and no running activites.
     Recorded when the state of the application changes.
@@ -2411,7 +2411,7 @@
 
 <action name="Android.LifeCycle.HasRunningActivities">
   <owner>ssid@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     Chrome application has at least one activity in running state. Recorded when
     the state of the application changes.
@@ -2420,7 +2420,7 @@
 
 <action name="Android.LifeCycle.HasStoppedActivities">
   <owner>ssid@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     Chrome application has at least one activity in stopped state, and none
     running or paused. Recorded when the state of the application changes.
@@ -12971,7 +12971,7 @@
 <action name="MobileBookmarkManagerClose">
   <owner>twellington@google.com</owner>
   <owner>sczs@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     Recorded when a user closes bookmark manager on iOS or Android.
   </description>
@@ -12979,7 +12979,7 @@
 
 <action name="MobileBookmarkManagerDeleteBulk">
   <owner>twellington@google.com</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     Recorded when a user deletes all selected bookmarks in the Android bookmark
     manager.
@@ -12997,7 +12997,7 @@
 
 <action name="MobileBookmarkManagerEditBookmark">
   <owner>twellington@google.com</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     Recorded when a user edits a bookmark in the Android bookmark manager.
   </description>
@@ -13005,7 +13005,7 @@
 
 <action name="MobileBookmarkManagerEditFolder">
   <owner>twellington@google.com</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     Recorded when a user edits a folder in the Android bookmark manager.
   </description>
@@ -13033,7 +13033,7 @@
 
 <action name="MobileBookmarkManagerEntryOpenedInIncognito">
   <owner>twellington@google.com</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     Recorded when all selected bookmarks are opened in new incognito tabs from
     the Android bookmarks manager.
@@ -13042,7 +13042,7 @@
 
 <action name="MobileBookmarkManagerEntryOpenedInNewTab">
   <owner>twellington@google.com</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     Recorded when all selected bookmarks are opened in new tabs from the Android
     bookmarks manager.
@@ -13051,7 +13051,7 @@
 
 <action name="MobileBookmarkManagerLongPressToggleSelect">
   <owner>twellington@google.com</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     Recorded when a user long presses on a bookmark item to toggle selection in
     the Android bookmark manager.
@@ -13069,7 +13069,7 @@
 
 <action name="MobileBookmarkManagerMoveToFolder">
   <owner>twellington@google.com</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     Recorded when a user moves one bookmark to a new folder in the Android
     bookmark manager.
@@ -13078,7 +13078,7 @@
 
 <action name="MobileBookmarkManagerMoveToFolderBulk">
   <owner>twellington@google.com</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     Recorded when a user moves all selected bookmark items to a new folder in
     the Android bookmark manager.
@@ -13104,7 +13104,7 @@
 
 <action name="MobileBookmarkManagerOpenFolder">
   <owner>twellington@google.com</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     Recorded when a user opens a folder in the Android bookmark manager.
   </description>
@@ -13129,7 +13129,7 @@
 
 <action name="MobileBookmarkManagerShowInFolder">
   <owner>twellington@google.com</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     Recorded when a user uses the &quot;Show in folder&quot; button from Android
     bookmark search in order to see the bookmark of interest inside of its
@@ -13139,7 +13139,7 @@
 
 <action name="MobileBookmarkManagerTapToggleSelect">
   <owner>twellington@google.com</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     Recorded when a user taps on an item in order to select it from the Android
     bookmark manager (this can only occur while in selection mode).
@@ -13149,7 +13149,7 @@
 <action name="MobileBottomToolbarHomeButton">
   <obsolete>Removed as of 2020/09/09.</obsolete>
   <owner>mdjones@chromium.org</owner>
-  <owner>chrome-android-apps@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     The user tapped on the bottom toolbar's home button.
   </description>
@@ -13157,7 +13157,7 @@
 
 <action name="MobileBottomToolbarNewTabButton">
   <owner>mdjones@chromium.org</owner>
-  <owner>chrome-android-apps@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     The user tapped on the bottom toolbar's new tab button.
   </description>
@@ -13165,7 +13165,7 @@
 
 <action name="MobileBottomToolbarShareButton">
   <owner>mdjones@chromium.org</owner>
-  <owner>chrome-android-apps@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     The user tapped on the bottom toolbar's share button.
   </description>
@@ -13174,13 +13174,13 @@
 <action name="MobileBottomToolbarShowMenu">
   <obsolete>Removed as of 5/2020</obsolete>
   <owner>mdjones@chromium.org</owner>
-  <owner>chrome-android-apps@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>The bottom toolbar's overflow menu was shown.</description>
 </action>
 
 <action name="MobileBottomToolbarTabSwitcherButtonInBrowsingView">
   <owner>mdjones@chromium.org</owner>
-  <owner>chrome-android-apps@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     The user tapped on the bottom toolbar's tab switcher button.
   </description>
@@ -15330,7 +15330,7 @@
 
 <action name="MobileToolbarCloseAllIncognitoTabsButtonTap">
   <owner>mdjones@chromium.org</owner>
-  <owner>chrome-android-apps@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     User tapped the close all incognito tabs button in the tab switcher bottom
     toolbar.
@@ -15339,7 +15339,7 @@
 
 <action name="MobileToolbarCloseAllRegularTabsButtonTap">
   <owner>mdjones@chromium.org</owner>
-  <owner>chrome-android-apps@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     User tapped the close all regular tabs button in the tab switcher bottom
     toolbar.
@@ -15360,7 +15360,7 @@
 
 <action name="MobileToolbarIdentityDiscTap">
   <owner>pavely@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>User tapped on IdentityDisc button on toolbar.</description>
 </action>
 
@@ -15380,7 +15380,7 @@
 
 <action name="MobileToolbarOmniboxAcceleratorTap">
   <owner>mdjones@chromium.org</owner>
-  <owner>chrome-android-apps@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     User tapped the omnibox accelerator button in the bottom toolbar.
   </description>
@@ -15470,7 +15470,7 @@
 
 <action name="MobileToolbarStackViewButtonInBrowsingView">
   <owner>mdjones@chromium.org</owner>
-  <owner>chrome-android-apps@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     User in the Android browsing mode tapped the tab switcher button on the
     toolbar to enter the tab switcher.
@@ -15518,13 +15518,13 @@
 <action name="MobileTopToolbarHomeButton">
   <obsolete>Removed as of 2020/09/09.</obsolete>
   <owner>mdjones@chromium.org</owner>
-  <owner>chrome-android-apps@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>The user tapped on the top toolbar's home button.</description>
 </action>
 
 <action name="MobileTopToolbarNewTabButton">
   <owner>mdjones@chromium.org</owner>
-  <owner>chrome-android-apps@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     The user tapped on the top toolbar's new tab button.
   </description>
@@ -15539,7 +15539,7 @@
 <action name="MobileTopToolbarShowMenu">
   <obsolete>Removed as of 5/2020</obsolete>
   <owner>mdjones@chromium.org</owner>
-  <owner>chrome-android-apps@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     Action indicating the top toolbar's overflow menu was shown.
   </description>
@@ -24485,7 +24485,7 @@
 
 <action name="Suggestions.ExpandableHeader.Collapsed">
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     The suggestions section is collapsed through the section header.
   </description>
@@ -24493,7 +24493,7 @@
 
 <action name="Suggestions.ExpandableHeader.Expanded">
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <description>
     The suggestions section is expanded through the section header.
   </description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index e67e687c..5f6b888 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -18949,6 +18949,11 @@
   <int value="2" label="ERROR_OPTION"/>
 </enum>
 
+<enum name="DownloadLocationSuggestionEvent">
+  <int value="0" label="LOCATION_SUGGESTION_SHOWN"/>
+  <int value="1" label="NOT_ENOUGH_SPACE_SHOWN"/>
+</enum>
+
 <enum name="DownloadMimeTypeResult">
   <int value="0" label="Other">MIME type other than those listed below.</int>
   <int value="1" label="PK pass">application/vnd.apple.pkpass MIME type.</int>
@@ -29954,6 +29959,7 @@
   <int value="3705" label="NewLayoutOverflowDifferentAndAlreadyScrollsFlex"/>
   <int value="3706" label="UnicodeBidiPlainText"/>
   <int value="3707" label="ColorSchemeDarkSupportedOnRoot"/>
+  <int value="3708" label="WebBluetoothGetAvailability"/>
 </enum>
 
 <enum name="FeaturePolicyAllowlistType">
@@ -42876,6 +42882,7 @@
   <int value="-850821337" label="WebContentsForceDark:enabled"/>
   <int value="-848691867" label="DesktopPWAWindowing:enabled"/>
   <int value="-847216521" label="ChromeDuplex:enabled"/>
+  <int value="-844786349" label="ClipboardHistoryNudgeSessionReset:enabled"/>
   <int value="-844537521" label="HttpFormWarning:disabled"/>
   <int value="-844381918" label="ArcNativeBridgeExperiment:disabled"/>
   <int value="-843496368" label="AutofillRejectCompanyBirthyear:disabled"/>
@@ -43601,6 +43608,7 @@
   <int value="-99781021" label="disable-roboto-font-ui"/>
   <int value="-97145978" label="DesktopPWAsStayInWindow:enabled"/>
   <int value="-94335249" label="UseAAudioDriver:enabled"/>
+  <int value="-93619449" label="video-tutorials-instant-fetch"/>
   <int value="-92116820" label="InlineUpdateFlow:enabled"/>
   <int value="-91767554" label="enable-de-jelly"/>
   <int value="-91370149" label="UseSerialBusEnumerator:enabled"/>
@@ -43667,6 +43675,7 @@
   <int value="-36234530" label="PluginVmShowMicrophonePermissions:enabled"/>
   <int value="-35745997" label="TabSearch:enabled"/>
   <int value="-35388407" label="AshNewSystemMenu:disabled"/>
+  <int value="-32385086" label="NtpRecipeTasksModule:disabled"/>
   <int value="-31444029" label="MediaInspectorLogging:disabled"/>
   <int value="-30966385" label="enable-hardware-overlays"/>
   <int value="-29877377" label="TabHoverCardImages:disabled"/>
@@ -43733,6 +43742,7 @@
   <int value="29212695" label="OfflineIndicator:enabled"/>
   <int value="31848187" label="ViewsTaskManager:disabled"/>
   <int value="32057053" label="EnterpriseReportingInBrowser:disabled"/>
+  <int value="32242305" label="NtpRecipeTasksModule:enabled"/>
   <int value="32348093" label="DiagnosticsApp:disabled"/>
   <int value="32488630" label="EphemeralTab:enabled"/>
   <int value="32557641" label="HTTPAuthCommittedInterstitials:disabled"/>
@@ -44963,6 +44973,7 @@
   <int value="1283956865" label="force-tablet-mode"/>
   <int value="1283960113" label="disable-fixed-position-compositing"/>
   <int value="1284910808" label="disable-checker-imaging"/>
+  <int value="1285169797" label="ClipboardHistoryNudgeSessionReset:disabled"/>
   <int value="1285905715" label="WebXRHitTest:enabled"/>
   <int value="1287625114" label="EnableIncognitoShortcutOnDesktop:disabled"/>
   <int value="1289433604" label="RecoverFromNeverSaveAndroid:enabled"/>
@@ -72852,7 +72863,7 @@
 
 <enum name="UnderlayDamageRect">
   <int value="0" label="Zero Damage Rect"/>
-  <int value="1" label="Non-Occluding Damage Only"/>
+  <int value="1" label="Non-Occluding Damage Only (deprecated)"/>
   <int value="2" label="Occluding Damage Only"/>
   <int value="3" label="Occluding and Non-Occluding Damages"/>
 </enum>
diff --git a/tools/metrics/histograms/histograms_xml/accessibility/histograms.xml b/tools/metrics/histograms/histograms_xml/accessibility/histograms.xml
index 722dc7c..ab65d06 100644
--- a/tools/metrics/histograms/histograms_xml/accessibility/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/accessibility/histograms.xml
@@ -101,7 +101,7 @@
 </histogram>
 
 <histogram name="Accessibility.ATK-APIs" enum="AccessibilityATKAPIEnum"
-    expires_after="M88">
+    expires_after="M95">
   <owner>dmazzoni@chromium.org</owner>
   <owner>jkim@igalia.com</owner>
   <owner>chrome-a11y-core@google.com</owner>
diff --git a/tools/metrics/histograms/histograms_xml/android/histograms.xml b/tools/metrics/histograms/histograms_xml/android/histograms.xml
index 9ebdeb09..820b2bb 100644
--- a/tools/metrics/histograms/histograms_xml/android/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/android/histograms.xml
@@ -400,7 +400,7 @@
     expires_after="2021-06-01">
   <owner>wylieb@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Records if Chrome altered a google homepage/search request to include the
     dark theme. Recorded only when navigating to google or google search.
@@ -412,7 +412,7 @@
 <histogram name="Android.DarkTheme.EnabledReason" enum="DarkThemeEnabledReason"
     expires_after="M90">
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Records the reason why dark theme is enabled when dark theme is visible to
     user.
@@ -422,7 +422,7 @@
 <histogram name="Android.DarkTheme.EnabledState" enum="BooleanEnabled"
     expires_after="M90">
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Records whether dark theme is enabled or not on cold start and when the
     enabled state changes.
@@ -432,7 +432,7 @@
 <histogram name="Android.DarkTheme.Preference.State"
     enum="DarkThemePreferences" expires_after="M90">
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Records user theme preference of system default, light or dark theme on cold
     start and when the theme preference changes.
@@ -526,7 +526,7 @@
     expires_after="2021-04-04">
   <owner>twellington@chromium.org</owner>
   <owner>tedchoc@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Records the largest display dimension in dp during deferred startup. The
     display size is not affected by Android N multi-window mode. Clamped at
@@ -538,7 +538,7 @@
     expires_after="2021-04-04">
   <owner>twellington@chromium.org</owner>
   <owner>tedchoc@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Records the smallest display dimension in dp during deferred startup. The
     display size is not affected by Android N multi-window mode. Clamped at 0 to
@@ -1241,7 +1241,7 @@
 <histogram name="Android.ModalDialog.SecurityFilteredTouchResult"
     enum="SecurityFilteredTouchResult" expires_after="2021-04-01">
   <owner>pavely@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Records the action taken on a security sensitive touch event in modal
     dialog. As of M84 it is used for site premission dialogs.
@@ -1265,7 +1265,7 @@
 
   <owner>twellington@chromium.org</owner>
   <owner>tedchoc@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Records on every metrics upload whether the activity is running in Android N
     multi-window mode or not.
@@ -1960,7 +1960,7 @@
 <histogram name="Android.Survey.DownloadRequested" enum="BooleanRequested"
     expires_after="2021-06-01">
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Recorded when a survey download is requested. If the client already has
     successfully downloaded a survey, 'not requested' is recorded.
@@ -1970,14 +1970,14 @@
 <histogram name="Android.Survey.DownloadResponseCode"
     enum="SurveyDownloadResponseCodes" expires_after="2021-06-01">
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>The response code of the completed survey download request.</summary>
 </histogram>
 
 <histogram name="Android.Survey.InfoBarClosingState"
     enum="InfoBarClosingStates" expires_after="2021-06-01">
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     If the infobar was visible when it was closed and if it was closed directly
     or not.
@@ -1987,7 +1987,7 @@
 <histogram name="Android.Survey.ShowSurvey" enum="BooleanSuccess"
     expires_after="2021-06-01">
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Whether or not the survey was successfully shown after its download.
   </summary>
@@ -1996,7 +1996,7 @@
 <histogram name="Android.Survey.SurveyFilteringResults"
     enum="SurveyFilteringResult" expires_after="2021-06-01">
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     The result of the survey filtering process. Each enum represents a different
     filter that caught the user. This is recorded on cold starts when we check
diff --git a/tools/metrics/histograms/histograms_xml/back_forward_cache/histograms.xml b/tools/metrics/histograms/histograms_xml/back_forward_cache/histograms.xml
index 01eaf98..2d60ae2 100644
--- a/tools/metrics/histograms/histograms_xml/back_forward_cache/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/back_forward_cache/histograms.xml
@@ -23,7 +23,7 @@
 
 <histogram name="BackForwardCache.AllSites.EvictedAfterDocumentRestoredReason"
     enum="BackForwardCacheEvictedAfterDocumentRestoredReason"
-    expires_after="2020-10-01">
+    expires_after="2021-10-01">
   <owner>hajimehoshi@chromium.org</owner>
   <owner>bfcache-dev@chromium.org</owner>
   <summary>
@@ -85,7 +85,7 @@
 <histogram
     name="BackForwardCache.AllSites.HistoryNavigationOutcome.DisabledForRenderFrameHostReason"
     enum="BackForwardCacheDisabledForRenderFrameHostReason"
-    expires_after="2020-10-01">
+    expires_after="2021-10-01">
   <owner>carlscab@chromium.org</owner>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>bfcache-dev@chromium.org</owner>
@@ -139,7 +139,7 @@
 </histogram>
 
 <histogram name="BackForwardCache.Eviction.TimeUntilProcessKilled" units="ms"
-    expires_after="2020-10-01">
+    expires_after="2021-10-01">
   <owner>hajimehoshi@chromium.org</owner>
   <owner>bfcache-dev@chromium.org</owner>
   <summary>
@@ -183,7 +183,7 @@
 </histogram>
 
 <histogram name="BackForwardCache.HistoryNavigationOutcome"
-    enum="BackForwardCacheHistoryNavigationOutcome" expires_after="2020-10-01">
+    enum="BackForwardCacheHistoryNavigationOutcome" expires_after="2021-10-01">
   <owner>hajimehoshi@chromium.org</owner>
   <owner>bfcache-dev@chromium.org</owner>
   <summary>
@@ -329,7 +329,7 @@
 
 <histogram name="BackForwardCache.ReloadsAfterHistoryNavigation"
     enum="BackForwardCacheReloadsAfterHistoryNavigation"
-    expires_after="2020-10-01">
+    expires_after="2021-10-01">
   <owner>sreejakshetty@chromium.org</owner>
   <owner>altimin@chromium.org</owner>
   <owner>bfcache-dev@chromium.org</owner>
@@ -345,7 +345,7 @@
 
 <histogram name="BackForwardCache.ReloadsAndHistoryNavigations"
     enum="BackForwardCacheReloadsAndHistoryNavigations"
-    expires_after="2020-10-01">
+    expires_after="2021-10-01">
   <owner>sreejakshetty@chromium.org</owner>
   <owner>altimin@chromium.org</owner>
   <owner>bfcache-dev@chromium.org</owner>
@@ -359,7 +359,7 @@
 </histogram>
 
 <histogram name="BackForwardCache.Restore.NavigationToFirstPaint" units="ms"
-    expires_after="2020-12-06">
+    expires_after="2021-10-01">
   <owner>sreejakshetty@chromium.org</owner>
   <owner>altimin@chromium.org</owner>
   <owner>bfcache-dev@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
index 7e08171..3b91c27c 100644
--- a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
+++ b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
@@ -11127,6 +11127,7 @@
   <suffix name="dummy" label="Module ID for a dummy module"/>
   <suffix name="dummy2" label="Module ID for another dummy module"/>
   <suffix name="kaleidoscope" label="Module ID for Kaleidoscope"/>
+  <suffix name="recipe_tasks" label="Module ID for Recipe Tasks"/>
   <suffix name="shopping_tasks" label="Module ID for Shopping Tasks"/>
   <affected-histogram name="NewTabPage.Modules.Dismissed"/>
   <affected-histogram name="NewTabPage.Modules.Impression"/>
diff --git a/tools/metrics/histograms/histograms_xml/mobile/histograms.xml b/tools/metrics/histograms/histograms_xml/mobile/histograms.xml
index 601445a..23d067d 100644
--- a/tools/metrics/histograms/histograms_xml/mobile/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/mobile/histograms.xml
@@ -579,6 +579,13 @@
   </summary>
 </histogram>
 
+<histogram name="MobileDownload.Location.Dialog.Suggestion.Events"
+    enum="DownloadLocationSuggestionEvent" expires_after="2021-03-01">
+  <owner>xingliu@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
+  <summary>Records the download location suggestion event.</summary>
+</histogram>
+
 <histogram name="MobileDownload.Location.Dialog.SuggestionSelected"
     enum="BooleanSelected" expires_after="2021-03-01">
   <owner>xingliu@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/net/histograms.xml b/tools/metrics/histograms/histograms_xml/net/histograms.xml
index 53ed646..04637ac 100644
--- a/tools/metrics/histograms/histograms_xml/net/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/net/histograms.xml
@@ -2927,6 +2927,16 @@
   </summary>
 </histogram>
 
+<histogram name="Net.QuicSession.KeyUpdate.PerConnection" units="count"
+    expires_after="2021-05-11">
+  <owner>mattm@chromium.org</owner>
+  <owner>src/net/quic/OWNERS</owner>
+  <summary>
+    The number of key updates processed per connection, recorded on connection
+    close. Only logged for connections which reached the 1-RTT level.
+  </summary>
+</histogram>
+
 <histogram
     name="Net.QuicSession.LastInFlightPacketSentTimeFromHandshakeCompletionWithPublicReset"
     units="ms" expires_after="2021-05-11">
diff --git a/tools/metrics/histograms/histograms_xml/new_tab_page/histograms.xml b/tools/metrics/histograms/histograms_xml/new_tab_page/histograms.xml
index 6741453e..d892a24a 100644
--- a/tools/metrics/histograms/histograms_xml/new_tab_page/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/new_tab_page/histograms.xml
@@ -1037,6 +1037,28 @@
   </summary>
 </histogram>
 
+<histogram name="NewTabPage.RecipeTasks.RecipeClick" units="index"
+    expires_after="2021-01-01">
+  <owner>tiborg@chromium.org</owner>
+  <owner>yyushkina@chromium.org</owner>
+  <owner>chrome-desktop-ntp@google.com</owner>
+  <summary>
+    Logged when a user clicked on a recipe in the recipe tasks module. The value
+    is equal to the index of the recipe.
+  </summary>
+</histogram>
+
+<histogram name="NewTabPage.RecipeTasks.RelatedSearchClick" units="index"
+    expires_after="2021-01-01">
+  <owner>tiborg@chromium.org</owner>
+  <owner>yyushkina@chromium.org</owner>
+  <owner>chrome-desktop-ntp@google.com</owner>
+  <summary>
+    Logged when a user clicked on a related search pill in the recipe tasks
+    module. The value is equal to the index of the pill.
+  </summary>
+</histogram>
+
 <histogram name="NewTabPage.RequestThrottler.PerDay" units="requests"
     expires_after="2021-07-01">
   <owner>freedjm@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/notifications/histograms.xml b/tools/metrics/histograms/histograms_xml/notifications/histograms.xml
index 8ac8abb..0d368ba 100644
--- a/tools/metrics/histograms/histograms_xml/notifications/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/notifications/histograms.xml
@@ -53,6 +53,9 @@
 
 <histogram name="Notifications.Announcement.Events"
     enum="AnnouncementNotificationEvent" expires_after="2020-10-30">
+  <obsolete>
+    Deprecated as of 10/2020
+  </obsolete>
   <owner>dtrainor@chromium.org</owner>
   <owner>xingliu@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/obsolete_histograms.xml b/tools/metrics/histograms/histograms_xml/obsolete_histograms.xml
index eaa2d6c..8f0e623 100644
--- a/tools/metrics/histograms/histograms_xml/obsolete_histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/obsolete_histograms.xml
@@ -1676,7 +1676,7 @@
     Removed in July, 2020
   </obsolete>
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Records the number of other devices listed in recent tabs page when recent
     tabs page is loaded.
@@ -1689,7 +1689,7 @@
     Removed in July, 2020
   </obsolete>
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Records the number of recently-closed tabs shown in recent tabs page when
     recent tabs page is loaded.
@@ -1702,7 +1702,7 @@
     Removed in July, 2020
   </obsolete>
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Records the total number of tabs listed in recent tabs page (sum of all tab
     from other devices plus recently-closed tabs) when recent tabs page is
@@ -25403,7 +25403,7 @@
     Removed 2020/02. Replaced by Cancelled.
   </obsolete>
   <owner>jinsukkim@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Overscroll gestures that were abandoned before they were completed.
     Implemented for Android.
@@ -25416,7 +25416,7 @@
     Removed 2020/02.
   </obsolete>
   <owner>jinsukkim@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Overscroll gesture was made beyond a threshold that, upon release, would
     trigger navigation. Users can swipe back below the threshold but this event
@@ -25430,7 +25430,7 @@
     Removed 2020/02. Replaced by Activated.
   </obsolete>
   <owner>jinsukkim@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Overscroll gestures initiated by the user. Note that not all overscroll
     gestures triggered are completed (e.g. the overscroll gesture is aborted if
diff --git a/tools/metrics/histograms/histograms_xml/others/histograms.xml b/tools/metrics/histograms/histograms_xml/others/histograms.xml
index f4dc48b..5fcf4919 100644
--- a/tools/metrics/histograms/histograms_xml/others/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/others/histograms.xml
@@ -1483,7 +1483,7 @@
 <histogram name="Bookmarks.Count.OpenInIncognito" units="bookmarks"
     expires_after="M82">
   <owner>twellington@google.com</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Records the number of bookmarks which are opened using the &quot;Open in
     incognito tab&quot; button from selection mode in the Android bookmark
@@ -1494,7 +1494,7 @@
 <histogram name="Bookmarks.Count.OpenInNewTab" units="bookmarks"
     expires_after="M82">
   <owner>twellington@google.com</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Records the number of bookmarks which are opened using the &quot;Open in new
     tab&quot; button from selection mode in the Android bookmark manager.
@@ -2806,7 +2806,7 @@
 <histogram name="ContextMenu.ThumbnailFetched" enum="BooleanSuccess"
     expires_after="2020-06-30">
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Logged when the callback to fetch the thumbnail returns a result: Success
     (bitmap data received) or Failure (null bitmap). Android only.
@@ -2816,7 +2816,7 @@
 <histogram name="ContextMenu.TimeToTakeAction.Abandoned" units="ms"
     expires_after="2021-03-28">
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     The time it takes for the user to abandon the context menu after it's shown
     by pressing back or touching outside the menu. This is only logged if the
@@ -2829,7 +2829,7 @@
 <histogram name="ContextMenu.TimeToTakeAction.SelectedItem" units="ms"
     expires_after="2021-03-28">
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     The time it takes for the user to select an item. This is only logged if the
     menu is closed as a result of the user clicking a menu item or a DirectShare
@@ -2841,7 +2841,7 @@
 <histogram name="ContextMenu.URLClicked" enum="BooleanClicked"
     expires_after="2021-06-30">
   <owner>twellington@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>Logged when the URL is clicked. Android only.</summary>
 </histogram>
 
@@ -4995,7 +4995,10 @@
 </histogram>
 
 <histogram name="FCMInvalidations.ResetClientIDStatus" enum="InstanceIDResult"
-    expires_after="M88">
+    expires_after="2020-10-19">
+  <obsolete>
+    Removed 2020-10.
+  </obsolete>
   <owner>tschumann@chromium.org</owner>
   <owner>treib@chromium.org</owner>
   <summary>
@@ -5468,7 +5471,7 @@
 <histogram name="GestureNavigation.Activated" enum="GestureNavigationDirection"
     expires_after="2021-12-28">
   <owner>jinsukkim@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Overscroll gesture was made beyond a threshold big enough to regard it as a
     valid gesture navigation i.e. at least 1/3 of the arrow puck is visible.
@@ -5480,7 +5483,7 @@
 <histogram name="GestureNavigation.Cancelled" enum="GestureNavigationDirection"
     expires_after="2021-12-28">
   <owner>jinsukkim@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Overscroll gestures that were cancelled before they were completed. Similar
     to 'Abandoned' but is used in pair with 'Activated' on M81 forward to
@@ -5491,7 +5494,7 @@
 <histogram name="GestureNavigation.Completed" enum="GestureNavigationDirection"
     expires_after="2021-12-28">
   <owner>jinsukkim@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Navigations that were triggered due to completed overscroll gesture.
     Implemented for Android.
@@ -5501,7 +5504,7 @@
 <histogram name="GestureNavigation.Reversed" enum="GestureNavigationDirection"
     expires_after="2021-12-28">
   <owner>jinsukkim@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Overscroll gesture was made to trigger navigation, but within 3 seconds user
     used overscroll gesture to navigate back to the page. Implemented for
@@ -5512,7 +5515,7 @@
 <histogram name="GestureNavigation.Sheet.Peeked"
     enum="GestureNavigationDirection" expires_after="2020-09-23">
   <owner>jinsukkim@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Overscroll gesture was made to trigger navigation bottom sheet to peeked
     state. Peek state can be entered and exited more than once in a sequence of
@@ -5524,7 +5527,7 @@
 <histogram name="GestureNavigation.Sheet.Selected" units="units"
     expires_after="2020-09-23">
   <owner>jinsukkim@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Index of the entries in the navigation bottom sheet that user tapped.
     Negative means navigating backward, positive forward. Zero index means that
@@ -5535,7 +5538,7 @@
 <histogram name="GestureNavigation.Sheet.Used"
     enum="GestureNavigationDirection" expires_after="2020-09-23">
   <owner>jinsukkim@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     User tapped one of the entries in the expanded navigation bottom sheet to
     navigate to other page. Implemented for Android.
@@ -5545,7 +5548,7 @@
 <histogram name="GestureNavigation.Sheet.Viewed"
     enum="GestureNavigationDirection" expires_after="2020-09-23">
   <owner>jinsukkim@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Overscroll gesture was made to trigger navigation bottom sheet to expanded
     state where the whole list of history items are presented.
@@ -5555,7 +5558,7 @@
 <histogram name="GestureNavigation.Type" enum="GestureNavigationType"
     expires_after="2021-12-28">
   <owner>jinsukkim@chromium.org</owner>
-  <owner>chrome-android-app@chromium.org</owner>
+  <owner>clank-app-team@google.com</owner>
   <summary>
     Gesture navigation type. It can be either Chrome's own gesture UI that
     supports back and forward navigation or OS-provided default system gesture
diff --git a/tools/metrics/histograms/histograms_xml/uma/histograms.xml b/tools/metrics/histograms/histograms_xml/uma/histograms.xml
index db0ad45..7e0f9a82 100644
--- a/tools/metrics/histograms/histograms_xml/uma/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/uma/histograms.xml
@@ -590,6 +590,20 @@
   </summary>
 </histogram>
 
+<histogram name="UMA.UnsentLogs.DroppedSize" units="bytes"
+    expires_after="2021-08-30">
+  <owner>akirabaruah@chromium.org</owner>
+  <owner>rkaplow@chromium.org</owner>
+  <owner>asvitkine@chromium.org</owner>
+  <owner>src/base/metrics/OWNERS</owner>
+  <summary>
+    Size of unsent logs removed from persistent storage due to exceeding the
+    individual log size limit. Unsent log trimming occurs immediately after
+    initial logs creation, upon successful log upload, or whenever
+    MetricsService stops recording.
+  </summary>
+</histogram>
+
 <histogram name="UMA.UnsentLogs.PersistedSizeInKB" units="KB"
     expires_after="2021-05-30">
   <owner>michaelbai@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/web_rtc/histograms.xml b/tools/metrics/histograms/histograms_xml/web_rtc/histograms.xml
index dc4e2938..3db1340 100644
--- a/tools/metrics/histograms/histograms_xml/web_rtc/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/web_rtc/histograms.xml
@@ -344,6 +344,9 @@
 
 <histogram name="WebRTC.Audio.EchoCanceller.ActiveRender" enum="Boolean"
     expires_after="2020-12-01">
+  <obsolete>
+    No longer in use. Removed on 2020-10-19.
+  </obsolete>
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
@@ -354,7 +357,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.BufferDelay" units="Blocks"
-    expires_after="2020-12-01">
+    expires_after="2021-10-19">
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
@@ -365,7 +368,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.CaptureSaturation" enum="Boolean"
-    expires_after="2020-12-01">
+    expires_after="2021-10-19">
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
@@ -377,7 +380,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.Clockdrift" enum="ClockdriftLevel"
-    expires_after="2021-01-31">
+    expires_after="2021-10-19">
   <owner>gustaf@chromium.org</owner>
   <owner>peah@chromium.org</owner>
   <summary>
@@ -387,7 +390,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.DelayChanges"
-    enum="WebRTCEventFrequency" expires_after="2021-04-04">
+    enum="WebRTCEventFrequency" expires_after="2021-10-19">
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
@@ -399,7 +402,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.EchoPathDelay" units="Blocks"
-    expires_after="2021-04-18">
+    expires_after="2021-10-19">
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
@@ -411,7 +414,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.Erl" units="dB (shifted)"
-    expires_after="2020-12-01">
+    expires_after="2021-10-19">
   <owner>gustaf@chromium.org</owner>
   <owner>peah@chromium.org</owner>
   <summary>
@@ -423,6 +426,10 @@
 
 <histogram name="WebRTC.Audio.EchoCanceller.ErlBand0" units="dB (shifted)"
     expires_after="2020-12-01">
+  <obsolete>
+    No longer in use, EchoCanceller.Erl considered sufficient. Removed on
+    2020-10-19.
+  </obsolete>
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
@@ -433,6 +440,10 @@
 
 <histogram name="WebRTC.Audio.EchoCanceller.ErlBand1" units="dB (shifted)"
     expires_after="2020-12-01">
+  <obsolete>
+    No longer in use, EchoCanceller.Erl considered sufficient. Removed on
+    2020-10-19.
+  </obsolete>
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
@@ -442,7 +453,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.Erle" units="dB"
-    expires_after="2020-12-01">
+    expires_after="2021-10-19">
   <owner>gustaf@chromium.org</owner>
   <owner>peah@chromium.org</owner>
   <summary>
@@ -454,6 +465,10 @@
 
 <histogram name="WebRTC.Audio.EchoCanceller.ErleBand0" units="dB (shifted)"
     expires_after="2020-12-01">
+  <obsolete>
+    No longer in use, EchoCanceller.Erle considered sufficient. Removed on
+    2020-10-19.
+  </obsolete>
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
@@ -464,6 +479,10 @@
 
 <histogram name="WebRTC.Audio.EchoCanceller.ErleBand1" units="dB (shifted)"
     expires_after="2020-12-01">
+  <obsolete>
+    No longer in use, EchoCanceller.Erle considered sufficient. Removed on
+    2020-10-19.
+  </obsolete>
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
@@ -473,7 +492,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.FilterDelay" units="Blocks"
-    expires_after="2020-12-01">
+    expires_after="2021-10-19">
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
@@ -487,7 +506,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.MaxCaptureJitter"
-    units="frames (10 ms)" expires_after="2020-12-01">
+    units="frames (10 ms)" expires_after="2021-10-19">
   <owner>peah@chromium.org</owner>
   <owner>gustaf@chromium.org</owner>
   <summary>
@@ -497,7 +516,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.MaxRenderJitter"
-    units="frames (10 ms)" expires_after="2020-12-01">
+    units="frames (10 ms)" expires_after="2021-10-19">
   <owner>peah@chromium.org</owner>
   <owner>gustaf@chromium.org</owner>
   <summary>
@@ -507,7 +526,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.MaxSkewShiftCount"
-    units="events/minute" expires_after="2020-12-01">
+    units="events/minute" expires_after="2021-10-19">
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
@@ -524,7 +543,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.MinCaptureJitter"
-    units="frames (10 ms)" expires_after="2020-12-01">
+    units="frames (10 ms)" expires_after="2021-10-19">
   <owner>peah@chromium.org</owner>
   <owner>gustaf@chromium.org</owner>
   <summary>
@@ -534,7 +553,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.MinRenderJitter"
-    units="frames (10 ms)" expires_after="2020-12-01">
+    units="frames (10 ms)" expires_after="2021-10-19">
   <owner>peah@chromium.org</owner>
   <owner>gustaf@chromium.org</owner>
   <summary>
@@ -545,6 +564,9 @@
 
 <histogram name="WebRTC.Audio.EchoCanceller.ModelBasedAecFeasible"
     enum="Boolean" expires_after="2020-12-01">
+  <obsolete>
+    No longer reported. Removed on 2020-10-19.
+  </obsolete>
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
@@ -556,7 +578,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.ReliableDelayEstimates"
-    enum="WebRTCAecDelayEstimateReliability" expires_after="2020-12-01">
+    enum="WebRTCAecDelayEstimateReliability" expires_after="2021-10-19">
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
@@ -568,7 +590,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.RenderOverruns"
-    enum="WebRTCEventFrequency" expires_after="2021-04-04">
+    enum="WebRTCEventFrequency" expires_after="2021-10-19">
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
@@ -579,7 +601,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.RenderUnderruns"
-    enum="WebRTCEventFrequency" expires_after="2021-04-04">
+    enum="WebRTCEventFrequency" expires_after="2021-10-19">
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
@@ -590,7 +612,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.UsableLinearEstimate"
-    enum="Boolean" expires_after="2020-12-01">
+    enum="Boolean" expires_after="2021-10-19">
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 8dfea9b1..e9764441 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,12 +5,12 @@
             "remote_path": "perfetto_binaries/trace_processor_shell/win/7411aeba4d3b11872828b8b15ac9bfddd63f4e6c/trace_processor_shell.exe"
         },
         "mac": {
-            "hash": "e77496c8966fa19fab26e6004a57d6eb119421db",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/be6747613d78aa1a7d88423b063d7a74fa3899e0/trace_processor_shell"
+            "hash": "80ee67472902d956c6234e59ef3967ceef11f5d8",
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/c4af5cd3397ddef15ef32e09847715c1ead0118a/trace_processor_shell"
         },
         "linux": {
-            "hash": "ffc8f91e15cd30c405b48b566f4fe03e0b6ff011",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/be6747613d78aa1a7d88423b063d7a74fa3899e0/trace_processor_shell"
+            "hash": "83ddbc26cbd48fefb31d8c494ef7cd7e89163b02",
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/c4af5cd3397ddef15ef32e09847715c1ead0118a/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 69851f9..bf01684f 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -263,6 +263,7 @@
  <item id="ranker_url_fetcher" added_in_milestone="62" hash_code="95682324" type="0" content_hash_code="45958626" os_list="linux,windows" file_path="components/assist_ranker/ranker_url_fetcher.cc"/>
  <item id="rappor_report" added_in_milestone="62" hash_code="44606780" type="0" content_hash_code="111287826" os_list="linux,windows" file_path="components/rappor/log_uploader.cc"/>
  <item id="receive_messages_express" added_in_milestone="85" hash_code="29506140" type="0" deprecated="2020-09-21" content_hash_code="38581365" file_path=""/>
+ <item id="recipe_tasks_service" added_in_milestone="88" hash_code="73597231" type="0" content_hash_code="31830923" os_list="linux,windows" file_path="chrome/browser/search/recipe_tasks/recipe_tasks_service.cc"/>
  <item id="refresh_token_annotation_request" added_in_milestone="62" hash_code="7433837" type="1" second_id="29188932" deprecated="2018-01-17" content_hash_code="137103383" file_path=""/>
  <item id="remote_copy_message_handler" added_in_milestone="80" hash_code="80255301" type="0" content_hash_code="117673331" os_list="linux,windows" file_path="chrome/browser/sharing/shared_clipboard/remote_copy_message_handler.cc"/>
  <item id="remote_suggestions_provider" added_in_milestone="62" hash_code="49544361" type="0" content_hash_code="126329742" os_list="linux,windows" file_path="components/ntp_snippets/remote/cached_image_fetcher.cc"/>
@@ -301,13 +302,14 @@
  <item id="save_file_manager" added_in_milestone="62" hash_code="56275203" type="0" content_hash_code="56692339" os_list="linux,windows" file_path="content/browser/download/save_file_manager.cc"/>
  <item id="sct_auditing" added_in_milestone="87" hash_code="48603483" type="0" content_hash_code="43567503" os_list="linux,windows" file_path="chrome/browser/ssl/sct_reporting_service.cc"/>
  <item id="sdch_dictionary_fetch" added_in_milestone="62" hash_code="47152935" type="0" deprecated="2017-09-16" content_hash_code="16764294" file_path=""/>
+ <item id="search_prefetch_service" added_in_milestone="88" hash_code="108986091" type="0" content_hash_code="125257414" os_list="linux,windows" file_path="chrome/browser/prefetch/search_prefetch/search_prefetch_service.cc"/>
  <item id="search_suggest_service" added_in_milestone="73" hash_code="57785193" type="0" content_hash_code="132247652" os_list="linux,windows" file_path="chrome/browser/search/search_suggest/search_suggest_loader_impl.cc"/>
  <item id="security_key_socket" added_in_milestone="66" hash_code="31074955" type="0" content_hash_code="13741232" os_list="linux,windows" file_path="remoting/host/security_key/security_key_socket.cc"/>
  <item id="send_message_express" added_in_milestone="85" hash_code="23527666" type="0" deprecated="2020-09-21" content_hash_code="96850228" file_path=""/>
  <item id="service_worker_navigation_preload" added_in_milestone="63" hash_code="129872904" type="0" content_hash_code="79473248" os_list="linux,windows" file_path="content/browser/service_worker/service_worker_fetch_dispatcher.cc"/>
  <item id="service_worker_update_checker" added_in_milestone="71" hash_code="130931413" type="0" content_hash_code="46608086" os_list="linux,windows" file_path="content/browser/service_worker/service_worker_single_script_update_checker.cc"/>
  <item id="services_http_server_error_response" added_in_milestone="68" hash_code="59302801" type="0" content_hash_code="127774041" os_list="linux,windows" file_path="services/network/public/cpp/server/http_server.cc"/>
- <item id="shopping_tasks_service" added_in_milestone="87" hash_code="90297622" type="0" content_hash_code="133566501" os_list="linux,windows" file_path="chrome/browser/search/shopping_tasks/shopping_tasks_service.cc"/>
+ <item id="shopping_tasks_service" added_in_milestone="87" hash_code="90297622" type="0" content_hash_code="133566501" os_list="windows,linux" file_path="chrome/browser/search/shopping_tasks/shopping_tasks_service.cc"/>
  <item id="sigined_exchange_cert_fetcher" added_in_milestone="66" hash_code="79442849" type="0" content_hash_code="8138156" os_list="linux,windows" file_path="content/browser/web_package/signed_exchange_cert_fetcher.cc"/>
  <item id="sigined_exchange_validity_pinger" added_in_milestone="75" hash_code="57114284" type="0" content_hash_code="119482488" os_list="linux,windows" file_path="content/browser/web_package/signed_exchange_validity_pinger.cc"/>
  <item id="signed_in_profile_avatar" added_in_milestone="62" hash_code="108903331" type="0" content_hash_code="72850619" os_list="linux,windows" file_path="chrome/browser/profiles/profile_downloader.cc"/>
diff --git a/tools/traffic_annotation/summary/grouping.xml b/tools/traffic_annotation/summary/grouping.xml
index 817a718..818122df 100644
--- a/tools/traffic_annotation/summary/grouping.xml
+++ b/tools/traffic_annotation/summary/grouping.xml
@@ -321,6 +321,7 @@
       <traffic_annotation unique_id="omnibox_documentsuggest"/>
       <traffic_annotation unique_id="omnibox_zerosuggest"/>
       <traffic_annotation unique_id="one_google_bar_service"/>
+      <traffic_annotation unique_id="search_prefetch_service"/>
     </sender>
   </group>
   <group name="Updates, Recovery, and Crash Reports">
@@ -391,6 +392,7 @@
       <traffic_annotation unique_id="search_suggest_service"/>
       <traffic_annotation unique_id="remote_suggestions_provider"/>
       <traffic_annotation unique_id="promo_service"/>
+      <traffic_annotation unique_id="recipe_tasks_service"/>
       <traffic_annotation unique_id="shopping_tasks_service"/>
     </sender>
     <sender name="Speech Recognition">
diff --git a/ui/accessibility/ax_node.cc b/ui/accessibility/ax_node.cc
index deb2076..e24a25f 100644
--- a/ui/accessibility/ax_node.cc
+++ b/ui/accessibility/ax_node.cc
@@ -1310,4 +1310,9 @@
   return nullptr;
 }
 
+bool AXNode::IsDescendantOfPlainTextField() const {
+  AXNode* textfield_node = GetTextFieldAncestor();
+  return textfield_node && textfield_node->data().IsPlainTextField();
+}
+
 }  // namespace ui
diff --git a/ui/accessibility/ax_node.h b/ui/accessibility/ax_node.h
index abf89edd..3d2585f3 100644
--- a/ui/accessibility/ax_node.h
+++ b/ui/accessibility/ax_node.h
@@ -460,6 +460,9 @@
   // Returns the text field ancestor of this current node if any.
   AXNode* GetTextFieldAncestor() const;
 
+  // Returns true if the ancestor of the current node is a plain text field.
+  bool IsDescendantOfPlainTextField() const;
+
   // Finds and returns a pointer to ordered set containing node.
   AXNode* GetOrderedSet() const;
 
diff --git a/ui/accessibility/ax_node_position.cc b/ui/accessibility/ax_node_position.cc
index 84d4c38..798bc67 100644
--- a/ui/accessibility/ax_node_position.cc
+++ b/ui/accessibility/ax_node_position.cc
@@ -261,6 +261,7 @@
       // nodes and nodes that are invisible to platform APIs. Textual nodes are
       // represented by their actual text.
       return !IsNullPosition() && !GetAnchor()->IsText() &&
+             !GetAnchor()->IsDescendantOfPlainTextField() &&
              GetAnchor()->IsChildOfLeaf();
   }
 }
diff --git a/ui/accessibility/ax_node_position_unittest.cc b/ui/accessibility/ax_node_position_unittest.cc
index 2bfe7139..fc666ebc 100644
--- a/ui/accessibility/ax_node_position_unittest.cc
+++ b/ui/accessibility/ax_node_position_unittest.cc
@@ -8063,6 +8063,64 @@
   }
 }
 
+TEST_F(AXPositionTest, TextPositionComparisonTextField) {
+  // ++1 kRootWebArea
+  // ++++2 kTextField editable
+  // ++++++3 kGenericContainer editable
+  // ++++++++4 kStaticText editable "Hello"
+  // ++++++++++5 kInlineTextBox "Hello"
+  AXNodeData root_1;
+  AXNodeData text_field_2;
+  AXNodeData generic_container_3;
+  AXNodeData static_text_4;
+  AXNodeData inline_box_5;
+
+  root_1.id = 1;
+  text_field_2.id = 2;
+  generic_container_3.id = 3;
+  static_text_4.id = 4;
+  inline_box_5.id = 5;
+
+  root_1.role = ax::mojom::Role::kRootWebArea;
+  root_1.child_ids = {text_field_2.id};
+
+  text_field_2.role = ax::mojom::Role::kTextField;
+  text_field_2.AddState(ax::mojom::State::kEditable);
+  text_field_2.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot, true);
+  text_field_2.child_ids = {generic_container_3.id};
+
+  generic_container_3.role = ax::mojom::Role::kGenericContainer;
+  generic_container_3.AddState(ax::mojom::State::kEditable);
+  generic_container_3.child_ids = {static_text_4.id};
+
+  static_text_4.role = ax::mojom::Role::kStaticText;
+  static_text_4.SetName("Hello");
+  static_text_4.child_ids = {inline_box_5.id};
+
+  inline_box_5.role = ax::mojom::Role::kInlineTextBox;
+  inline_box_5.SetName("Hello");
+
+  SetTree(CreateAXTree({root_1, text_field_2, generic_container_3,
+                        static_text_4, inline_box_5}));
+
+  // TextPosition anchor_id=5 anchor_role=inlineTextBox text_offset=4
+  // annotated_text=hell<o>
+  TestPositionType inline_text_position = AXNodePosition::CreateTextPosition(
+      GetTreeID(), inline_box_5.id, 4, ax::mojom::TextAffinity::kDownstream);
+  ASSERT_NE(nullptr, inline_text_position);
+
+  // TextPosition anchor_id=2 anchor_role=textField text_offset=4
+  // annotated_text=hell<o>
+  TestPositionType text_field_position = AXNodePosition::CreateTextPosition(
+      GetTreeID(), text_field_2.id, 4, ax::mojom::TextAffinity::kDownstream);
+  ASSERT_NE(nullptr, text_field_position);
+
+  // Validate that two positions in the text field with the same text offsets
+  // but different anchors are logically equal.
+  EXPECT_EQ(*inline_text_position, *text_field_position);
+  EXPECT_EQ(*text_field_position, *inline_text_position);
+}
+
 //
 // Instantiations of parameterized tests.
 //
diff --git a/ui/accessibility/ax_tree_serializer.h b/ui/accessibility/ax_tree_serializer.h
index 1b4a2b4..558f5f75 100644
--- a/ui/accessibility/ax_tree_serializer.h
+++ b/ui/accessibility/ax_tree_serializer.h
@@ -8,10 +8,13 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <ostream>
 #include <unordered_map>
 #include <unordered_set>
 #include <vector>
 
+#include "base/debug/crash_logging.h"
+#include "base/debug/dump_without_crashing.h"
 #include "base/logging.h"
 #include "ui/accessibility/ax_common.h"
 #include "ui/accessibility/ax_export.h"
@@ -393,11 +396,25 @@
 AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::GetClientTreeNodeParent(
     ClientTreeNode* obj) {
   ClientTreeNode* parent = obj->parent;
-#if defined(AX_FAIL_FAST_BUILD)
   if (!parent)
     return nullptr;
-  DCHECK(ClientTreeNodeById(parent->id)) << "Parent not in id map.";
+  if (!ClientTreeNodeById(parent->id)) {
+    std::ostringstream error;
+    error << "Parent not in id map. Child was: "
+          << tree_->GetDebugString(tree_->GetFromId(obj->id))
+          << "\n  Parent was: "
+          << tree_->GetDebugString(tree_->GetFromId(parent->id));
+    static auto* ax_tree_serializer_missing_parent_id_error =
+        base::debug::AllocateCrashKeyString(
+            "ax_tree_serializer_missing_parent_id_error",
+            base::debug::CrashKeySize::Size64);
+    base::debug::SetCrashKeyString(ax_tree_serializer_missing_parent_id_error,
+                                   error.str());
+#if defined(AX_FAIL_FAST_BUILD)
+    CHECK(false);
 #endif  // defined(AX_FAIL_FAST_BUILD)
+    base::debug::DumpWithoutCrashing();
+  }
   return parent;
 }
 
@@ -580,21 +597,26 @@
 
     ClientTreeNode* client_child = ClientTreeNodeById(new_child_id);
     if (client_child && GetClientTreeNodeParent(client_child) != client_node) {
-#if defined(AX_FAIL_FAST_BUILD)
-      // TODO(accessibility) Remove all cases where this occurs and re-add
-      // NOTREACHED(), or add a histogram.
       // This condition leads to performance problems. It will
       // also reset virtual buffers, causing users to lose their place.
-      NOTREACHED()
-#else
-      LOG(ERROR)
+      std::ostringstream error;
+      error << "Illegal reparenting detected: "
+            << "\nPassed-in parent: "
+            << tree_->GetDebugString(tree_->GetFromId(client_node->id))
+            << "\nChild: " << tree_->GetDebugString(child)
+            << "\nChild's parent: "
+            << tree_->GetDebugString(tree_->GetFromId(client_child->parent->id))
+            << "\n-----------------------------------------\n\n\n";
+      static auto* ax_tree_serializer_illegal_reparenting_error =
+          base::debug::AllocateCrashKeyString(
+              "ax_tree_serializer_illegal_reparenting_error",
+              base::debug::CrashKeySize::Size64);
+      base::debug::SetCrashKeyString(
+          ax_tree_serializer_illegal_reparenting_error, error.str());
+#if defined(AX_FAIL_FAST_BUILD)
+      CHECK(false);
 #endif  // defined(AX_FAIL_FAST_BUILD)
-          << "Illegal reparenting detected: "
-          << "\nPassed-in parent: "
-          << tree_->GetDebugString(tree_->GetFromId(client_node->id))
-          << "\nChild: " << tree_->GetDebugString(child) << "\nChild's parent: "
-          << tree_->GetDebugString(tree_->GetFromId(client_child->parent->id))
-          << "\n-----------------------------------------\n\n\n";
+      base::debug::DumpWithoutCrashing();
       Reset();
       return false;
     }
@@ -674,22 +696,27 @@
       new_child->invalid = false;
       client_node->children.push_back(new_child);
       if (ClientTreeNodeById(child_id)) {
-#if defined(AX_FAIL_FAST_BUILD)
         // TODO(accessibility) Remove all cases where this occurs and re-add
-        // NOTREACHED(), or add a histogram.
         // This condition leads to performance problems. It will
         // also reset virtual buffers, causing users to lose their place.
-        NOTREACHED()
-#else
-        LOG(ERROR)
+        std::ostringstream error;
+        error << "Child id " << child_id << " already exists in map."
+              << "\nChild is "
+              << tree_->GetDebugString(tree_->GetFromId(child_id))
+              << "\nWanted as child of parent " << tree_->GetDebugString(node)
+              << "\nAlready had parent "
+              << tree_->GetDebugString(tree_->GetFromId(
+                     ClientTreeNodeById(child_id)->parent->id));
+        static auto* ax_tree_serializer_duplicate_id_error =
+            base::debug::AllocateCrashKeyString(
+                "ax_tree_serializer_duplicate_id_error",
+                base::debug::CrashKeySize::Size64);
+        base::debug::SetCrashKeyString(ax_tree_serializer_duplicate_id_error,
+                                       error.str());
+#if defined(AX_FAIL_FAST_BUILD)
+        CHECK(false);
 #endif  // defined(AX_FAIL_FAST_BUILD)
-            << "Child id " << child_id << " already exists in map."
-            << "\nChild is "
-            << tree_->GetDebugString(tree_->GetFromId(child_id))
-            << "\nWanted as child of parent " << tree_->GetDebugString(node)
-            << "\nAlready had parent "
-            << tree_->GetDebugString(
-                   tree_->GetFromId(ClientTreeNodeById(child_id)->parent->id));
+        base::debug::DumpWithoutCrashing();
         Reset();
         return false;
       }
diff --git a/ui/accessibility/platform/ax_platform_node_delegate.h b/ui/accessibility/platform/ax_platform_node_delegate.h
index 391d8a3f..acbf7f2e3 100644
--- a/ui/accessibility/platform/ax_platform_node_delegate.h
+++ b/ui/accessibility/platform/ax_platform_node_delegate.h
@@ -145,7 +145,7 @@
 
   // Returns true if this current node is editable and the root editable node is
   // a plain text field.
-  virtual bool IsChildOfPlainTextField() const = 0;
+  virtual bool IsDescendantOfPlainTextField() const = 0;
 
   // Returns true if this is a leaf node, meaning all its
   // children should not be exposed to any platform's native accessibility
diff --git a/ui/accessibility/platform/ax_platform_node_delegate_base.cc b/ui/accessibility/platform/ax_platform_node_delegate_base.cc
index 0b9afafb..ba49fe98 100644
--- a/ui/accessibility/platform/ax_platform_node_delegate_base.cc
+++ b/ui/accessibility/platform/ax_platform_node_delegate_base.cc
@@ -164,7 +164,7 @@
   return false;
 }
 
-bool AXPlatformNodeDelegateBase::IsChildOfPlainTextField() const {
+bool AXPlatformNodeDelegateBase::IsDescendantOfPlainTextField() const {
   return false;
 }
 
diff --git a/ui/accessibility/platform/ax_platform_node_delegate_base.h b/ui/accessibility/platform/ax_platform_node_delegate_base.h
index 5fba10f0..43459f18 100644
--- a/ui/accessibility/platform/ax_platform_node_delegate_base.h
+++ b/ui/accessibility/platform/ax_platform_node_delegate_base.h
@@ -72,7 +72,7 @@
   gfx::NativeViewAccessible GetPreviousSibling() override;
 
   bool IsChildOfLeaf() const override;
-  bool IsChildOfPlainTextField() const override;
+  bool IsDescendantOfPlainTextField() const override;
   bool IsLeaf() const override;
   bool IsToplevelBrowserWindow() override;
   gfx::NativeViewAccessible GetClosestPlatformObject() const override;
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
index 2629570..00f29e0 100644
--- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
@@ -1390,7 +1390,7 @@
   if (delegate && delegate->HasVisibleCaretOrSelection()) {
     if (!delegate->GetData().HasState(ax::mojom::State::kEditable) ||
         (delegate->GetData().IsPlainTextField() ||
-         delegate->IsChildOfPlainTextField())) {
+         delegate->IsDescendantOfPlainTextField())) {
       return true;
     }
   }
diff --git a/ui/android/java/src/org/chromium/ui/modaldialog/DIR_METADATA b/ui/android/java/src/org/chromium/ui/modaldialog/DIR_METADATA
index cf26ac97..549f1c28 100644
--- a/ui/android/java/src/org/chromium/ui/modaldialog/DIR_METADATA
+++ b/ui/android/java/src/org/chromium/ui/modaldialog/DIR_METADATA
@@ -9,5 +9,4 @@
 monorail {
   component: "UI>Browser>Mobile>Messages"
 }
-team_email: "chrome-android-app@chromium.org"
-os: ANDROID
\ No newline at end of file
+os: ANDROID
diff --git a/ui/base/clipboard/BUILD.gn b/ui/base/clipboard/BUILD.gn
index 7862fc5..e2d3d53 100644
--- a/ui/base/clipboard/BUILD.gn
+++ b/ui/base/clipboard/BUILD.gn
@@ -107,6 +107,7 @@
     "//mojo/public/cpp/base",
     "//net",
     "//skia",
+    "//ui/base:features",
     "//ui/gfx",
     "//ui/gfx/geometry",
   ]
diff --git a/ui/base/clipboard/clipboard.cc b/ui/base/clipboard/clipboard.cc
index 901aa3e0..76f9580 100644
--- a/ui/base/clipboard/clipboard.cc
+++ b/ui/base/clipboard/clipboard.cc
@@ -15,9 +15,37 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/geometry/size.h"
 
+#if defined(USE_OZONE)
+#include "ui/base/ui_base_features.h"
+#endif
+
 namespace ui {
 
 // static
+bool Clipboard::IsSupportedClipboardBuffer(ClipboardBuffer buffer) {
+  switch (buffer) {
+    case ClipboardBuffer::kCopyPaste:
+      return true;
+    case ClipboardBuffer::kSelection:
+#if defined(USE_OZONE) && !defined(OS_CHROMEOS)
+      if (features::IsUsingOzonePlatform()) {
+        ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
+        CHECK(clipboard);
+        return clipboard->IsSelectionBufferAvailable();
+      }
+#endif
+#if !defined(OS_WIN) && !defined(OS_APPLE) && !defined(OS_CHROMEOS)
+      return true;
+#else
+      return false;
+#endif
+    case ClipboardBuffer::kDrag:
+      return false;
+  }
+  NOTREACHED();
+}
+
+// static
 void Clipboard::SetAllowedThreads(
     const std::vector<base::PlatformThreadId>& allowed_threads) {
   base::AutoLock lock(ClipboardMapLock());
diff --git a/ui/base/clipboard/clipboard.h b/ui/base/clipboard/clipboard.h
index c5cf15c4..65b4bf61 100644
--- a/ui/base/clipboard/clipboard.h
+++ b/ui/base/clipboard/clipboard.h
@@ -47,21 +47,7 @@
 class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard
     : public base::ThreadChecker {
  public:
-  static bool IsSupportedClipboardBuffer(ClipboardBuffer buffer) {
-    switch (buffer) {
-      case ClipboardBuffer::kCopyPaste:
-        return true;
-      case ClipboardBuffer::kSelection:
-#if !defined(OS_WIN) && !defined(OS_APPLE) && !defined(OS_CHROMEOS)
-        return true;
-#else
-        return false;
-#endif
-      case ClipboardBuffer::kDrag:
-        return false;
-    }
-    NOTREACHED();
-  }
+  static bool IsSupportedClipboardBuffer(ClipboardBuffer buffer);
 
   // Sets the list of threads that are allowed to access the clipboard.
   static void SetAllowedThreads(
@@ -203,12 +189,6 @@
   // Resets the clipboard last modified time to Time::Time().
   virtual void ClearLastModifiedTime();
 
-#if defined(USE_OZONE)
-  // Returns whether the selection buffer is available.  This is true for some
-  // Linux platforms.
-  virtual bool IsSelectionBufferAvailable() const = 0;
-#endif  // defined(USE_OZONE)
-
  protected:
   // PortableFormat designates the type of data to be stored in the clipboard.
   // This designation is shared across all OSes. The system-specific designation
@@ -338,6 +318,12 @@
 
   static base::PlatformThreadId GetAndValidateThreadID();
 
+#if defined(USE_OZONE)
+  // Returns whether the selection buffer is available.  This is true for some
+  // Linux platforms.
+  virtual bool IsSelectionBufferAvailable() const = 0;
+#endif  // defined(USE_OZONE)
+
   // A list of allowed threads. By default, this is empty and no thread checking
   // is done (in the unit test case), but a user (like content) can set which
   // threads are allowed to call this method.
diff --git a/ui/base/clipboard/clipboard_non_backed.cc b/ui/base/clipboard/clipboard_non_backed.cc
index a53ca0a..a1f6261 100644
--- a/ui/base/clipboard/clipboard_non_backed.cc
+++ b/ui/base/clipboard/clipboard_non_backed.cc
@@ -649,7 +649,11 @@
 }
 
 bool ClipboardNonBacked::IsSelectionBufferAvailable() const {
+#if defined(OS_CHROMEOS)
   return false;
+#else
+  return true;
+#endif
 }
 
 void ClipboardNonBacked::WritePortableRepresentations(
diff --git a/ui/base/clipboard/clipboard_test_template.h b/ui/base/clipboard/clipboard_test_template.h
index e5093f4..b1b3048 100644
--- a/ui/base/clipboard/clipboard_test_template.h
+++ b/ui/base/clipboard/clipboard_test_template.h
@@ -262,10 +262,10 @@
 
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
 TYPED_TEST(ClipboardTest, MultipleBufferTest) {
-#if defined(USE_OZONE)
-  if (!this->clipboard().IsSelectionBufferAvailable())
+  if (!ui::Clipboard::IsSupportedClipboardBuffer(
+          ui::ClipboardBuffer::kSelection)) {
     return;
-#endif
+  }
 
   base::string16 text(ASCIIToUTF16("Standard")), text_result;
   base::string16 markup(ASCIIToUTF16("<string>Selection</string>"));
diff --git a/ui/base/clipboard/test/test_clipboard.cc b/ui/base/clipboard/test/test_clipboard.cc
index 85b76797..7875725 100644
--- a/ui/base/clipboard/test/test_clipboard.cc
+++ b/ui/base/clipboard/test/test_clipboard.cc
@@ -255,7 +255,7 @@
 
 #if defined(USE_OZONE)
 bool TestClipboard::IsSelectionBufferAvailable() const {
-  return false;
+  return true;
 }
 #endif  // defined(USE_OZONE)
 
diff --git a/ui/base/cursor/DIR_METADATA b/ui/base/cursor/DIR_METADATA
index b05aeb7e..198db49 100644
--- a/ui/base/cursor/DIR_METADATA
+++ b/ui/base/cursor/DIR_METADATA
@@ -7,5 +7,5 @@
 #   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
 
 monorail {
-  component: "Internal>Input"
-}
\ No newline at end of file
+  component: "Internals>Input"
+}
diff --git a/ui/base/emoji/DIR_METADATA b/ui/base/emoji/DIR_METADATA
index b05aeb7e..198db49 100644
--- a/ui/base/emoji/DIR_METADATA
+++ b/ui/base/emoji/DIR_METADATA
@@ -7,5 +7,5 @@
 #   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
 
 monorail {
-  component: "Internal>Input"
-}
\ No newline at end of file
+  component: "Internals>Input"
+}
diff --git a/ui/base/pointer/DIR_METADATA b/ui/base/pointer/DIR_METADATA
index b05aeb7e..198db49 100644
--- a/ui/base/pointer/DIR_METADATA
+++ b/ui/base/pointer/DIR_METADATA
@@ -7,5 +7,5 @@
 #   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
 
 monorail {
-  component: "Internal>Input"
-}
\ No newline at end of file
+  component: "Internals>Input"
+}
diff --git a/ui/chromeos/translations/ui_chromeos_strings_af.xtb b/ui/chromeos/translations/ui_chromeos_strings_af.xtb
index e5dc36e..9446f416 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_af.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_af.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Goedjaratse sleutelbord (foneties)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">VSA-sleutelbord</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> items is uitgevee</translation>
 <translation id="2542049655219295786">Google-tabel</translation>
 <translation id="2547921442987553570">Voeg by <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">VSA internasionaal</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serwies</translation>
 <translation id="385051799172605136">Terug</translation>
 <translation id="3855472144336161447">Duitse Neo 2</translation>
-<translation id="3856075812838139784">Leesalleen</translation>
 <translation id="3858678421048828670">Italiaanse sleutelbord</translation>
 <translation id="386548886866354912">Verpak saam met <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Beskrywing</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Google-kaart</translation>
 <translation id="7419631653042041064">Katalaanse sleutelbord</translation>
 <translation id="7434823369735508263">VK Dvorak-sleutelbord</translation>
-<translation id="7447678886297481665">Lêers in hierdie vouer is leesalleen. Sommige aktiwiteite word nie gesteun nie.</translation>
 <translation id="7460898608667578234">Oekraïens</translation>
 <translation id="7474889694310679759">Kanadese Engels-sleutelbord</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> gevind
diff --git a/ui/chromeos/translations/ui_chromeos_strings_am.xtb b/ui/chromeos/translations/ui_chromeos_strings_am.xtb
index deec9ca9..e0925c3b 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_am.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_am.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">የጉጃራቲ ቁልፍ ሰሌዳ (ፎነቲክ)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">የአሜሪካ ቁልፍ ሰሌዳ</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> ንጥሎች ተሰርዟል</translation>
 <translation id="2542049655219295786">Google ሠንጠረዥ</translation>
 <translation id="2547921442987553570">ወደ <ph name="EXTENSION_NAME" /> አክል</translation>
 <translation id="255937426064304553">አሜሪካ ዓለምአቀፍ</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">ሰርቢኛ</translation>
 <translation id="385051799172605136">ተመለስ</translation>
 <translation id="3855472144336161447">ጀርመንኛ ኒዮ 2</translation>
-<translation id="3856075812838139784">ተነባቢ ብቻ</translation>
 <translation id="3858678421048828670">የጣሊያንኛ ቁልፍ ሰሌዳ</translation>
 <translation id="386548886866354912">በ<ph name="EXTENSION_NAME" /> ጋር ጠቅልል</translation>
 <translation id="3866249974567520381">ማብራሪያ</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Google ካርታ</translation>
 <translation id="7419631653042041064">የካታላን ቁልፍ ሰሌዳ</translation>
 <translation id="7434823369735508263">የዩናይትድ ኪንግደም ድቮራክ ቁልፍ ሰሌዳ</translation>
-<translation id="7447678886297481665">በዚህ አቃፊ ውስጥ ያሉ ፋይሎች ተነባቢ ብቻ ናቸው። አንዳንድ እንቅስቃሴዎች አይደገፉም።</translation>
 <translation id="7460898608667578234">ዩክረኒኛ</translation>
 <translation id="7474889694310679759">የካናዳ እንግሊዝኛ ቁልፍ ሰሌዳ</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> ተገኝቷል
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ar.xtb b/ui/chromeos/translations/ui_chromeos_strings_ar.xtb
index 8b45f411..c9d5a1cc 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ar.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ar.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">لوحة المفاتيح الغوغاراتية (صوتية)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">لوحة المفاتيح الأمريكية</translation>
+<translation id="2534155362429831547">تم حذف <ph name="NUMBER_OF_ITEMS" /> من العناصر</translation>
 <translation id="2542049655219295786">‏جدول من Google</translation>
 <translation id="2547921442987553570">إضافة إلى <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">الأمريكية الدولية</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">الصربية</translation>
 <translation id="385051799172605136">رجوع</translation>
 <translation id="3855472144336161447">‏الألمانية Neo 2</translation>
-<translation id="3856075812838139784">للقراءة فقط</translation>
 <translation id="3858678421048828670">لوحة المفاتيح الإيطالية</translation>
 <translation id="386548886866354912">تجميع مع <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">الوصف</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">‏خريطة Google</translation>
 <translation id="7419631653042041064">لوحة المفاتيح الكتالانية</translation>
 <translation id="7434823369735508263">‏لوحة المفاتيح البريطانية Dvorak</translation>
-<translation id="7447678886297481665">إنّ الملفات في هذا المجلد للقراءة فقط. وبعض النشاطات غير متاحة فيها.</translation>
 <translation id="7460898608667578234">الأوكرانية</translation>
 <translation id="7474889694310679759">لوحة المفاتيح الكندية الإنجليزية</translation>
 <translation id="7489215562877293245">‏تم العثور على <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_as.xtb b/ui/chromeos/translations/ui_chromeos_strings_as.xtb
index 082141a..425faf21 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_as.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_as.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">গুজৰাটী কীব’ৰ্ড (উচ্চাৰণগত)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">ইউএছ কীব'র্ড</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> টা সমল মচা হ’ল</translation>
 <translation id="2542049655219295786">Google তালিকা</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" />ত যোগ কৰক</translation>
 <translation id="255937426064304553">US আন্তৰ্জাতিক</translation>
@@ -266,7 +267,6 @@
 <translation id="383652340667548381">ছার্বিয়ান</translation>
 <translation id="385051799172605136">উভতি যাওক</translation>
 <translation id="3855472144336161447">জার্মান NEO 2 কীব’র্ড</translation>
-<translation id="3856075812838139784">কেৱল পঢ়িব পৰা</translation>
 <translation id="3858678421048828670">ইটালীয়ান কীব’র্ড</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> জৰিয়তে পেক কৰক</translation>
 <translation id="3866249974567520381">বিৱৰণ</translation>
@@ -595,7 +595,6 @@
 <translation id="7417705661718309329">Google মেপ</translation>
 <translation id="7419631653042041064">কেটালান কীব’ৰ্ড</translation>
 <translation id="7434823369735508263">গ্ৰে‘ট ব্ৰিটেইন ড‘ভৰাক কীব’ৰ্ড</translation>
-<translation id="7447678886297481665">এই ফ’ল্ডাৰটোৰ ফাইলসমূহ কেৱল পঢ়িব পৰা। কিছুমান কার্যকলাপ সমৰ্থিত নহয়।</translation>
 <translation id="7460898608667578234">ইউক্ৰেনিয়ান</translation>
 <translation id="7474889694310679759">কানাডিয়ান ইংৰাজী কীব'ৰ্ড</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> বিচাৰি পোৱা গৈছে
diff --git a/ui/chromeos/translations/ui_chromeos_strings_az.xtb b/ui/chromeos/translations/ui_chromeos_strings_az.xtb
index a1cbe7b2..ecc5b50 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_az.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_az.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Qucarat klaviaturası (Fonetik)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">ABŞ klaviaturası</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> element silindi</translation>
 <translation id="2542049655219295786">Google cədvəl</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" /> atırmasına əlavə edin</translation>
 <translation id="255937426064304553">ABŞ Beynəlxalq</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serb</translation>
 <translation id="385051799172605136">Geri</translation>
 <translation id="3855472144336161447">Alman Neo 2</translation>
-<translation id="3856075812838139784">Yalnız oxu</translation>
 <translation id="3858678421048828670">İtalyan klaviaturası</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> ilə qablaşdırın</translation>
 <translation id="3866249974567520381">Təsvir</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Google xəritə</translation>
 <translation id="7419631653042041064">Katalan klaviaturası</translation>
 <translation id="7434823369735508263">Böyük Britaniya Dvorak klaviaturası</translation>
-<translation id="7447678886297481665">Bu qovluqdakı fayllar ancaq oxuna bilər. Bəzi fəaliyyətlər dəstəklənmir.</translation>
 <translation id="7460898608667578234">Ukrayna</translation>
 <translation id="7474889694310679759">Kanada İngiliscəsi klaviaturası</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> nəticə
diff --git a/ui/chromeos/translations/ui_chromeos_strings_be.xtb b/ui/chromeos/translations/ui_chromeos_strings_be.xtb
index f6029f4..681bdc59e 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_be.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_be.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Клавіятура гуджараці (фанетычная)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Клавіятура ЗША</translation>
+<translation id="2534155362429831547">Выдалена элементаў: <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2542049655219295786">Табліца Google</translation>
 <translation id="2547921442987553570">Дадаць у пашырэнне "<ph name="EXTENSION_NAME" />"</translation>
 <translation id="255937426064304553">ЗША, міжнародная</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Сербская</translation>
 <translation id="385051799172605136">Назад</translation>
 <translation id="3855472144336161447">Нямецкая (Neo 2)</translation>
-<translation id="3856075812838139784">Толькі чытанне</translation>
 <translation id="3858678421048828670">Італьянская клавіятура</translation>
 <translation id="386548886866354912">Запакаваць з дапамогай <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Апісанне</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Карта Google</translation>
 <translation id="7419631653042041064">Каталанская клавіятура</translation>
 <translation id="7434823369735508263">Клавіятура Дворака для Вялікабрытаніі</translation>
-<translation id="7447678886297481665">Файлы ў гэтай папцы – толькі для чытання. Некаторыя дзеянні не падтрымліваюцца.</translation>
 <translation id="7460898608667578234">Украінская</translation>
 <translation id="7474889694310679759">Англійская (канадская) клавіятура</translation>
 <translation id="7489215562877293245">Знойдзена: <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_bg.xtb b/ui/chromeos/translations/ui_chromeos_strings_bg.xtb
index 4eb3ec3..8786c46 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_bg.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_bg.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Гуджарати клавиатура (фонетична)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Американска клавиатура</translation>
+<translation id="2534155362429831547">Изтрихте <ph name="NUMBER_OF_ITEMS" /> елемента</translation>
 <translation id="2542049655219295786">Таблица в Google</translation>
 <translation id="2547921442987553570">Добавяне към <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Американска международна клавиатура</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">сръбски</translation>
 <translation id="385051799172605136">Назад</translation>
 <translation id="3855472144336161447">Немска (Neo 2) клавиатура</translation>
-<translation id="3856075812838139784">Само за четене</translation>
 <translation id="3858678421048828670">Италианска клавиатура</translation>
 <translation id="386548886866354912">Пакетиране с/ъс <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Описание</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Карта на Google</translation>
 <translation id="7419631653042041064">Каталонска клавиатура</translation>
 <translation id="7434823369735508263">Британска (Дворак) клавиатура</translation>
-<translation id="7447678886297481665">Файловете в тази папка са само за четене. Някои действия не се поддържат.</translation>
 <translation id="7460898608667578234">украински</translation>
 <translation id="7474889694310679759">Канадска (английски) клавиатура</translation>
 <translation id="7489215562877293245">Намерихме <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_bn.xtb b/ui/chromeos/translations/ui_chromeos_strings_bn.xtb
index c4e93ab..646da06 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_bn.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_bn.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">গুজরাটি কীবোর্ড (ফোনেটিক)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">ইউএস কীবোর্ড</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" />টি আইটেম মোছা হয়েছে</translation>
 <translation id="2542049655219295786">Google টেবিল</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" /> এ যোগ করুন</translation>
 <translation id="255937426064304553">মার্কিন আন্তর্জাতিক</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">সার্বিয়</translation>
 <translation id="385051799172605136">ফিরুন</translation>
 <translation id="3855472144336161447">জার্মান নিও ২</translation>
-<translation id="3856075812838139784">কেবল পঠনযোগ্য</translation>
 <translation id="3858678421048828670">ইতালিয় কীবোর্ড</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> দিয়ে প্যাক করুন</translation>
 <translation id="3866249974567520381">বর্ণনা</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Google ম্যাপ</translation>
 <translation id="7419631653042041064">ক্যাটালান কীবোর্ড</translation>
 <translation id="7434823369735508263">ইউকে দভোরাক কীবোর্ড</translation>
-<translation id="7447678886297481665">এই ফোল্ডারের ফাইল শুধু পড়া যায়। কিছু অ্যাক্টিভিটি এখানে কাজ করবে না।</translation>
 <translation id="7460898608667578234">ইউক্রেনীয়</translation>
 <translation id="7474889694310679759">কানাডিয় ইংরাজি কীবোর্ড</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" />টি পাওয়া গেছে
diff --git a/ui/chromeos/translations/ui_chromeos_strings_bs.xtb b/ui/chromeos/translations/ui_chromeos_strings_bs.xtb
index a1baca02..e2fa3a3 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_bs.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_bs.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Gudžaratska tastatura (fonetska)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">SAD tastatura</translation>
+<translation id="2534155362429831547">Broj izbrisanih stavki: <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2542049655219295786">Google tabela</translation>
 <translation id="2547921442987553570">Dodaj u proširenje <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">SAD međunarodna</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Srpska</translation>
 <translation id="385051799172605136">Nazad</translation>
 <translation id="3855472144336161447">Njemačka Neo 2</translation>
-<translation id="3856075812838139784">Samo za čitanje</translation>
 <translation id="3858678421048828670">Italijanska tastatura</translation>
 <translation id="386548886866354912">Zapakiraj ekstenzijom <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Opis</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google Mapa</translation>
 <translation id="7419631653042041064">Katalonska tastatura</translation>
 <translation id="7434823369735508263">Tastatura UK Dvorak</translation>
-<translation id="7447678886297481665">Fajlovi u ovom folderu su samo za čitanje. Neke aktivnosti nisu podržane.</translation>
 <translation id="7460898608667578234">Ukrajinska</translation>
 <translation id="7474889694310679759">Kanadsko-engleska tipkovnica</translation>
 <translation id="7489215562877293245">Broj pronađenih fajlova: <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ca.xtb b/ui/chromeos/translations/ui_chromeos_strings_ca.xtb
index 2e03938..9720949 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ca.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ca.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Teclat gujarati (fonètic)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Teclat nord-americà</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> elements suprimits</translation>
 <translation id="2542049655219295786">Taula de Google</translation>
 <translation id="2547921442987553570">Afegeix a <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Teclat internacional d'Estats Units</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbi</translation>
 <translation id="385051799172605136">Enrere</translation>
 <translation id="3855472144336161447">Neo 2 alemany</translation>
-<translation id="3856075812838139784">Només de lectura</translation>
 <translation id="3858678421048828670">Teclat italià</translation>
 <translation id="386548886866354912">Crea un paquet amb l'extensió <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Descripció</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Mapa de Google</translation>
 <translation id="7419631653042041064">Teclat català</translation>
 <translation id="7434823369735508263">Teclat Dvorak anglès</translation>
-<translation id="7447678886297481665">Els fitxers d'aquesta carpeta són només de lectura. Algunes activitats no s'admeten.</translation>
 <translation id="7460898608667578234">Ucraïnès</translation>
 <translation id="7474889694310679759">Teclat anglès del Canadà</translation>
 <translation id="7489215562877293245">S'han trobat <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_cs.xtb b/ui/chromeos/translations/ui_chromeos_strings_cs.xtb
index 7ef88172..f2db8ac 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_cs.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_cs.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Gudžarátská klávesnice (fonetická)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Americká klávesnice</translation>
+<translation id="2534155362429831547">Byly smazány položky (celkem <ph name="NUMBER_OF_ITEMS" />)</translation>
 <translation id="2542049655219295786">Tabulka Google</translation>
 <translation id="2547921442987553570">Přidat do rozšíření <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Americká klávesnice (mezinárodní)</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">srbština</translation>
 <translation id="385051799172605136">Zpět</translation>
 <translation id="3855472144336161447">Německá klávesnice Neo 2</translation>
-<translation id="3856075812838139784">Pouze ke čtení</translation>
 <translation id="3858678421048828670">Italská klávesnice</translation>
 <translation id="386548886866354912">Zabalit pomocí rozšíření <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Popis</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Mapa Google</translation>
 <translation id="7419631653042041064">Katalánská klávesnice</translation>
 <translation id="7434823369735508263">Britská klávesnice s rozložením Dvorak</translation>
-<translation id="7447678886297481665">Soubory v této složce jsou pouze ke čtení. Některé aktivity nejsou podporovány.</translation>
 <translation id="7460898608667578234">ukrajinština</translation>
 <translation id="7474889694310679759">Kanadská anglická klávesnice</translation>
 <translation id="7489215562877293245">Nalezeno: <ph name="FILE_COUNT" />.
diff --git a/ui/chromeos/translations/ui_chromeos_strings_da.xtb b/ui/chromeos/translations/ui_chromeos_strings_da.xtb
index 3d229e85..323a506 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_da.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_da.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Gujarati-tastatur (fonetisk)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Amerikansk tastatur</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> elementer blev slettet</translation>
 <translation id="2542049655219295786">Google-tabel</translation>
 <translation id="2547921442987553570">Føj til <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Amerikansk (internationalt)</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbisk</translation>
 <translation id="385051799172605136">Tilbage</translation>
 <translation id="3855472144336161447">Tysk (Neo 2)</translation>
-<translation id="3856075812838139784">Skrivebeskyttet</translation>
 <translation id="3858678421048828670">Italiensk tastatur</translation>
 <translation id="386548886866354912">Pak sammen med <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Beskrivelse</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google-kort</translation>
 <translation id="7419631653042041064">Catalansk tastatur</translation>
 <translation id="7434823369735508263">Britisk (Dvorak) tastatur</translation>
-<translation id="7447678886297481665">Filer i denne mappe er skrivebeskyttet. Det er ikke alle aktiviteter, der understøttes.</translation>
 <translation id="7460898608667578234">ukrainsk</translation>
 <translation id="7474889694310679759">Canadisk (engelsk) tastatur</translation>
 <translation id="7489215562877293245">Der blev fundet <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_de.xtb b/ui/chromeos/translations/ui_chromeos_strings_de.xtb
index 7b1ee0a..2632210 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_de.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_de.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Gujarati-Tastatur (phonetisch)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">US-amerikanische Tastatur</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> Einträge gelöscht</translation>
 <translation id="2542049655219295786">Google-Tabelle</translation>
 <translation id="2547921442987553570">Zu <ph name="EXTENSION_NAME" /> hinzufügen</translation>
 <translation id="255937426064304553">USA – international</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbisch</translation>
 <translation id="385051799172605136">Zurück</translation>
 <translation id="3855472144336161447">Deutsch – Neo 2</translation>
-<translation id="3856075812838139784">Schreibgeschützt</translation>
 <translation id="3858678421048828670">Italienische Tastatur</translation>
 <translation id="386548886866354912">Mit <ph name="EXTENSION_NAME" /> packen</translation>
 <translation id="3866249974567520381">Beschreibung</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google-Karte</translation>
 <translation id="7419631653042041064">Katalanische Tastatur</translation>
 <translation id="7434823369735508263">Englische Dvorak-Tastatur</translation>
-<translation id="7447678886297481665">Dateien in diesem Ordner sind schreibgeschützt. Einige Aktivitäten werden nicht unterstützt.</translation>
 <translation id="7460898608667578234">Ukrainisch</translation>
 <translation id="7474889694310679759">Kanadisch-englische Tastatur</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> gefunden
diff --git a/ui/chromeos/translations/ui_chromeos_strings_el.xtb b/ui/chromeos/translations/ui_chromeos_strings_el.xtb
index f913c8da..1fab8cd 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_el.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_el.xtb
@@ -144,6 +144,7 @@
 <translation id="2494837236724268445">Πληκτρολόγιο Γκουγιαράτι (Φωνητικό)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Πληκτρολόγιο με αγγλικούς χαρακτήρες (ΗΠΑ)</translation>
+<translation id="2534155362429831547">Διαγράφηκαν <ph name="NUMBER_OF_ITEMS" /> στοιχεία</translation>
 <translation id="2542049655219295786">Πίνακας Google</translation>
 <translation id="2547921442987553570">Προσθήκη στην επέκταση <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Διεθνές ΗΠΑ</translation>
@@ -275,7 +276,6 @@
 </translation>
 <translation id="385051799172605136">Πίσω</translation>
 <translation id="3855472144336161447">Γερμανικά Neo 2</translation>
-<translation id="3856075812838139784">Μόνο για ανάγνωση</translation>
 <translation id="3858678421048828670">Πληκτρολόγιο με ιταλικούς χαρακτήρες</translation>
 <translation id="386548886866354912">Συμπίεση με <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Περιγραφή</translation>
@@ -615,7 +615,6 @@
 <translation id="7417705661718309329">Χάρτης Google</translation>
 <translation id="7419631653042041064">Πληκτρολόγιο με καταλανικούς χαρακτήρες</translation>
 <translation id="7434823369735508263">Πληκτρολόγιο Dvorak ΗΒ</translation>
-<translation id="7447678886297481665">Τα αρχεία σε αυτόν τον φάκελο είναι μόνο για ανάγνωση. Δεν υποστηρίζονται ορισμένες δραστηριότητες.</translation>
 <translation id="7460898608667578234">Ουκρανικά
 </translation>
 <translation id="7474889694310679759">Πληκτρολόγιο με αγγλικούς χαρακτήρες (Καναδά)</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_en-GB.xtb b/ui/chromeos/translations/ui_chromeos_strings_en-GB.xtb
index e3da91ea..7726fef5 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_en-GB.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_en-GB.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Gujarati keyboard (Phonetic)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">US keyboard</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> items deleted</translation>
 <translation id="2542049655219295786">Google table</translation>
 <translation id="2547921442987553570">Add to <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">US international</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbian</translation>
 <translation id="385051799172605136">Back</translation>
 <translation id="3855472144336161447">German Neo 2</translation>
-<translation id="3856075812838139784">Read only</translation>
 <translation id="3858678421048828670">Italian keyboard</translation>
 <translation id="386548886866354912">Pack with <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Description</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google map</translation>
 <translation id="7419631653042041064">Catalan keyboard</translation>
 <translation id="7434823369735508263">UK Dvorak keyboard</translation>
-<translation id="7447678886297481665">Files in this folder are read-only. Some activities are not supported.</translation>
 <translation id="7460898608667578234">Ukrainian</translation>
 <translation id="7474889694310679759">Canadian English keyboard</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> found
diff --git a/ui/chromeos/translations/ui_chromeos_strings_es-419.xtb b/ui/chromeos/translations/ui_chromeos_strings_es-419.xtb
index 6fb49c2..ffcfcb2 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_es-419.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_es-419.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Teclado guyaratí (fonético)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Teclado en inglés de EE.UU.</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> elementos borrados</translation>
 <translation id="2542049655219295786">Tabla de Google</translation>
 <translation id="2547921442987553570">Agregar a <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Inglés (Estados Unidos; internacional)</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbio</translation>
 <translation id="385051799172605136">Atrás</translation>
 <translation id="3855472144336161447">Alemán (Neo 2)</translation>
-<translation id="3856075812838139784">Solo lectura</translation>
 <translation id="3858678421048828670">Teclado italiano</translation>
 <translation id="386548886866354912">Paquete con <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Descripción</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Mapa de Google</translation>
 <translation id="7419631653042041064">Teclado catalán</translation>
 <translation id="7434823369735508263">Teclado Dvorak en inglés del Reino Unido</translation>
-<translation id="7447678886297481665">Como los archivos que se encuentran en esta carpeta son de solo lectura, no se pueden realizar algunas acciones.</translation>
 <translation id="7460898608667578234">Ucraniano</translation>
 <translation id="7474889694310679759">Teclado en inglés de Canadá</translation>
 <translation id="7489215562877293245">Se encontró un total de <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_es.xtb b/ui/chromeos/translations/ui_chromeos_strings_es.xtb
index b5febbc..005015d 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_es.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_es.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Teclado gujarati (fonético)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Teclado de EE. UU.</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> elementos eliminados</translation>
 <translation id="2542049655219295786">Tabla de Google</translation>
 <translation id="2547921442987553570">Añadir a <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Estados Unidos (internacional)</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbio</translation>
 <translation id="385051799172605136">Volver</translation>
 <translation id="3855472144336161447">Alemán (Neo 2)</translation>
-<translation id="3856075812838139784">Solo lectura</translation>
 <translation id="3858678421048828670">Teclado italiano</translation>
 <translation id="386548886866354912">Comprimir con <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Descripción</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Mapa de Google</translation>
 <translation id="7419631653042041064">Teclado catalán</translation>
 <translation id="7434823369735508263">Teclado de Reino Unido Dvorak</translation>
-<translation id="7447678886297481665">Los archivos de esta carpeta son de solo lectura. Algunas actividades no son compatibles.</translation>
 <translation id="7460898608667578234">Ucraniano</translation>
 <translation id="7474889694310679759">Teclado inglés canadiense</translation>
 <translation id="7489215562877293245">Archivos encontrados: <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_et.xtb b/ui/chromeos/translations/ui_chromeos_strings_et.xtb
index ab6ce69d..ca1eb6f 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_et.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_et.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Gujarati klaviatuur (foneetiline)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">USA klaviatuur</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> üksust kustutati</translation>
 <translation id="2542049655219295786">Google'i tabel</translation>
 <translation id="2547921442987553570">Lisa laiendusse <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">USA rahvusvaheline</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">serbia keel</translation>
 <translation id="385051799172605136">Tagasi</translation>
 <translation id="3855472144336161447">Saksa Neo 2</translation>
-<translation id="3856075812838139784">Kirjutuskaitstud</translation>
 <translation id="3858678421048828670">Itaalia klaviatuur</translation>
 <translation id="386548886866354912">Paki laiendusega <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Kirjeldus</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google'i kaart</translation>
 <translation id="7419631653042041064">Katalaani klaviatuur</translation>
 <translation id="7434823369735508263">Ühendkuningriigi Dvoraki klaviatuur</translation>
-<translation id="7447678886297481665">Failid selles kaustas on kirjutuskaitsega. Mõnda toimingut ei toetata.</translation>
 <translation id="7460898608667578234">ukraina keel</translation>
 <translation id="7474889694310679759">Kanada inglise klaviatuur</translation>
 <translation id="7489215562877293245">Leiti <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_eu.xtb b/ui/chromeos/translations/ui_chromeos_strings_eu.xtb
index 42a20136..c6ad94f 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_eu.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_eu.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Teklatu gujaratarra (fonetikoa)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">AEBko teklatua</translation>
+<translation id="2534155362429831547">Ezabatu dira <ph name="NUMBER_OF_ITEMS" /> elementu</translation>
 <translation id="2542049655219295786">Google taula</translation>
 <translation id="2547921442987553570">Gehitu <ph name="EXTENSION_NAME" /> luzapenean</translation>
 <translation id="255937426064304553">AEBko nazioarteko teklatu-diseinua</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbiarra</translation>
 <translation id="385051799172605136">Atzera</translation>
 <translation id="3855472144336161447">Neo 2 alemana</translation>
-<translation id="3856075812838139784">Irakurtzeko soilik</translation>
 <translation id="3858678421048828670">Teklatu italiarra</translation>
 <translation id="386548886866354912">Paketatu <ph name="EXTENSION_NAME" /> luzapenarekin</translation>
 <translation id="3866249974567520381">Azalpena</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Google mapa</translation>
 <translation id="7419631653042041064">Teklatu katalana</translation>
 <translation id="7434823369735508263">Erresuma Batuko Dvorak teklatua</translation>
-<translation id="7447678886297481665">Karpeta honetako fitxategiak irakurtzeko soilik dira. Jarduera batzuk ez dira onartzen.</translation>
 <translation id="7460898608667578234">Ukrainarra</translation>
 <translation id="7474889694310679759">Teklatu ingeles kanadarra</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> aurkitu dira
diff --git a/ui/chromeos/translations/ui_chromeos_strings_fa.xtb b/ui/chromeos/translations/ui_chromeos_strings_fa.xtb
index fe8d0bb..0885e18 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_fa.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_fa.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">صفحه‌کلید گجراتی (آوایی)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">صفحه‌کلید آمریکایی</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> مورد حذف شد</translation>
 <translation id="2542049655219295786">‏جدول Google </translation>
 <translation id="2547921442987553570">افزودن به <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">بین‌المللی آمریکایی</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">صربستانی</translation>
 <translation id="385051799172605136">بازگشت</translation>
 <translation id="3855472144336161447">نئو آلمان ۲</translation>
-<translation id="3856075812838139784">فقط خوانده شده</translation>
 <translation id="3858678421048828670">صفحه‌کلید ایتالیایی</translation>
 <translation id="386548886866354912">بسته‌بندی با <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">توضیح</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">‏نقشه Google</translation>
 <translation id="7419631653042041064">صفحه‌کلید کاتالان</translation>
 <translation id="7434823369735508263">صفحه‌کلید دووراک انگلیسی</translation>
-<translation id="7447678886297481665">فایل‌های این پوشه فقط خواندنی هستند. برخی از فعالیت‌ها پشتیبانی نمی‌شوند.</translation>
 <translation id="7460898608667578234">اوکراینی</translation>
 <translation id="7474889694310679759">صفحه‌کلید کانادایی انگلیسی</translation>
 <translation id="7489215562877293245">‏<ph name="FILE_COUNT" /> مورد پیدا شد
diff --git a/ui/chromeos/translations/ui_chromeos_strings_fi.xtb b/ui/chromeos/translations/ui_chromeos_strings_fi.xtb
index d4794fd..6cbe19c 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_fi.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_fi.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Gudžaratinkielinen näppäimistö (foneettinen)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Näppäimistö: US</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> kohdetta poistettu</translation>
 <translation id="2542049655219295786">Google-taulukko</translation>
 <translation id="2547921442987553570">Lisää laajennukseen <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">USA (kansainvälinen)</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">serbia</translation>
 <translation id="385051799172605136">Takaisin</translation>
 <translation id="3855472144336161447">saksa, Neo 2</translation>
-<translation id="3856075812838139784">Vain luku</translation>
 <translation id="3858678421048828670">Näppäimistö: italia</translation>
 <translation id="386548886866354912">Pakkaa laajennuksella <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Kuvaus</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google-kartta</translation>
 <translation id="7419631653042041064">Näppäimistö: katalaani</translation>
 <translation id="7434823369735508263">Näppäimistö: UK, Dvorak</translation>
-<translation id="7447678886297481665">Tämän kansion tiedostoja voi vain lukea. Joitain toimintoja ei tueta.</translation>
 <translation id="7460898608667578234">ukraina</translation>
 <translation id="7474889694310679759">Näppäimistö: englanti (Kanada)</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> löytyi
diff --git a/ui/chromeos/translations/ui_chromeos_strings_fil.xtb b/ui/chromeos/translations/ui_chromeos_strings_fil.xtb
index 935dceb..83246f7 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_fil.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_fil.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Gujarati keyboard (Phonetic)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">US keyboard</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> (na) item ang na-delete</translation>
 <translation id="2542049655219295786">Talahanayan ng Google</translation>
 <translation id="2547921442987553570">Idagdag sa <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">US international</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbian</translation>
 <translation id="385051799172605136">Bumalik</translation>
 <translation id="3855472144336161447">German Neo 2</translation>
-<translation id="3856075812838139784">Read only</translation>
 <translation id="3858678421048828670">Italian na keyboard</translation>
 <translation id="386548886866354912">I-pack kasama ng <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Paglalarawan</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google map</translation>
 <translation id="7419631653042041064">Catalan na keyboard</translation>
 <translation id="7434823369735508263">UK Dvorak na keyboard</translation>
-<translation id="7447678886297481665">Read only ang mga file sa folder na ito. Hindi sinusuportahan ang ilang aktibidad.</translation>
 <translation id="7460898608667578234">Ukrainian</translation>
 <translation id="7474889694310679759">Canadian English na keyboard</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> ang nakita
diff --git a/ui/chromeos/translations/ui_chromeos_strings_fr-CA.xtb b/ui/chromeos/translations/ui_chromeos_strings_fr-CA.xtb
index f9e8122..283010d 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_fr-CA.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_fr-CA.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Clavier gujarati (phonétique)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Clavier américain</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> éléments supprimés</translation>
 <translation id="2542049655219295786">Tableau Google</translation>
 <translation id="2547921442987553570">Ajouter à <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">États-Unis international</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbe</translation>
 <translation id="385051799172605136">Retour</translation>
 <translation id="3855472144336161447">Allemand (Neo 2)</translation>
-<translation id="3856075812838139784">Lecture seule</translation>
 <translation id="3858678421048828670">Clavier italien</translation>
 <translation id="386548886866354912">Archiver avec <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Description</translation>
@@ -602,7 +602,6 @@
 <translation id="7417705661718309329">Carte Google</translation>
 <translation id="7419631653042041064">Clavier catalan</translation>
 <translation id="7434823369735508263">Clavier Dvorak britannique</translation>
-<translation id="7447678886297481665">Les fichiers dans ce dossier sont en lecture seule. Certaines activités ne sont pas prises en charge.</translation>
 <translation id="7460898608667578234">Ukrainien</translation>
 <translation id="7474889694310679759">Clavier anglais canadien</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> trouvées
diff --git a/ui/chromeos/translations/ui_chromeos_strings_fr.xtb b/ui/chromeos/translations/ui_chromeos_strings_fr.xtb
index 5a0437a..610c92a 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_fr.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_fr.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Clavier gujarati (phonétique)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Clavier américain</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> éléments supprimés</translation>
 <translation id="2542049655219295786">Tableau Google</translation>
 <translation id="2547921442987553570">Ajouter à <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">États-Unis international</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbe</translation>
 <translation id="385051799172605136">Retour</translation>
 <translation id="3855472144336161447">Neo 2 allemand</translation>
-<translation id="3856075812838139784">Lecture seule</translation>
 <translation id="3858678421048828670">Clavier italien</translation>
 <translation id="386548886866354912">Empaqueter avec <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Description</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Carte Google</translation>
 <translation id="7419631653042041064">Clavier catalan</translation>
 <translation id="7434823369735508263">Clavier Dvorak britannique</translation>
-<translation id="7447678886297481665">Les fichiers de ce dossier sont en lecture seule. Certaines opérations ne sont donc pas possibles.</translation>
 <translation id="7460898608667578234">Ukrainien</translation>
 <translation id="7474889694310679759">Clavier anglais canadien</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> trouvées
diff --git a/ui/chromeos/translations/ui_chromeos_strings_gl.xtb b/ui/chromeos/translations/ui_chromeos_strings_gl.xtb
index a003715f..d4b2107 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_gl.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_gl.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Teclado guxaratí (fonético)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Teclado estadounidense</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> elementos eliminados</translation>
 <translation id="2542049655219295786">Táboa de Google</translation>
 <translation id="2547921442987553570">Engadir a <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Internacional de EUA</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbio</translation>
 <translation id="385051799172605136">Atrás</translation>
 <translation id="3855472144336161447">Neo 2 alemán</translation>
-<translation id="3856075812838139784">Só lectura</translation>
 <translation id="3858678421048828670">Teclado italiano</translation>
 <translation id="386548886866354912">Comprimir con <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Descrición</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Mapa de Google</translation>
 <translation id="7419631653042041064">Teclado catalán</translation>
 <translation id="7434823369735508263">Teclado Dvorak do Reino Unido</translation>
-<translation id="7447678886297481665">O ficheiros deste cartafol son só de lectura. Non se admiten algunhas actividades.</translation>
 <translation id="7460898608667578234">Ucraíno</translation>
 <translation id="7474889694310679759">Teclado inglés canadense</translation>
 <translation id="7489215562877293245">Atopáronse <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_gu.xtb b/ui/chromeos/translations/ui_chromeos_strings_gu.xtb
index f8b0f7d..7b8ff02 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_gu.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_gu.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">ગુજરાતી કીબોર્ડ (ધ્વન્યાત્મક)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">યુએસ કીબોર્ડ</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> આઇટમ કાઢી નાખી</translation>
 <translation id="2542049655219295786">Google કોષ્ટક</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" /> માં ઉમેરો</translation>
 <translation id="255937426064304553">યુએસ આંતરરાષ્ટ્રીય</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">સર્બિયન</translation>
 <translation id="385051799172605136">પાછળ</translation>
 <translation id="3855472144336161447">જર્મન નીઓ 2</translation>
-<translation id="3856075812838139784">ફક્ત વાંચવા માટે</translation>
 <translation id="3858678421048828670">ઇટાલિયન કીબોર્ડ</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> સાથે પૅક કરો</translation>
 <translation id="3866249974567520381">વર્ણન</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google નકશો</translation>
 <translation id="7419631653042041064">કતલાન કીબોર્ડ</translation>
 <translation id="7434823369735508263">યુકે ડ્વોરેક કીબોર્ડ</translation>
-<translation id="7447678886297481665">આ ફોલ્ડરમાંની ફાઇલો ફક્ત વાંચી શકાય છે. કેટલીક પ્રવૃત્તિઓને સપોર્ટ આપવામાં આવતો નથી.</translation>
 <translation id="7460898608667578234">યુક્રેનિયન</translation>
 <translation id="7474889694310679759">કેનેડિયન અંગ્રેજી કીબોર્ડ</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> મળ્યા
diff --git a/ui/chromeos/translations/ui_chromeos_strings_hi.xtb b/ui/chromeos/translations/ui_chromeos_strings_hi.xtb
index d2f6616..3f5916085 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_hi.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_hi.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">गुजराती कीबोर्ड (फ़ोनेटिक)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">यूएस कीबोर्ड</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> आइटम मिटाए गए</translation>
 <translation id="2542049655219295786">Google टेबल</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" /> में जोड़ें</translation>
 <translation id="255937426064304553">यूएस अंतर्राष्ट्रीय</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">सर्बियाई</translation>
 <translation id="385051799172605136">वापस जाएं</translation>
 <translation id="3855472144336161447">जर्मन नियो 2</translation>
-<translation id="3856075812838139784">केवल पढ़ने के लिए</translation>
 <translation id="3858678421048828670">इटैलियन कीबोर्ड</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> के साथ पैक करें</translation>
 <translation id="3866249974567520381">वर्णन</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google मैप</translation>
 <translation id="7419631653042041064">कतालान कीबोर्ड</translation>
 <translation id="7434823369735508263">यूके ड्वोराक कीबोर्ड</translation>
-<translation id="7447678886297481665">इस फ़ोल्डर में मौजूद फ़ाइलें सिर्फ़ पढ़ी जा सकती हैं. कुछ काम नहीं किए जा सकते.</translation>
 <translation id="7460898608667578234">उक्रेनियाई</translation>
 <translation id="7474889694310679759">कनाडाई अंग्रेज़ी कीबोर्ड</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> मिलीं
diff --git a/ui/chromeos/translations/ui_chromeos_strings_hr.xtb b/ui/chromeos/translations/ui_chromeos_strings_hr.xtb
index be41f10..3129a8c 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_hr.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_hr.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">gudžaratska tipkovnica (fonetska)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">SAD tipkovnica</translation>
+<translation id="2534155362429831547">Broj izbrisanih stavki: <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2542049655219295786">Googleova tablica</translation>
 <translation id="2547921442987553570">Dodaj u proširenje <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">američka (međunarodna)</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Srpski</translation>
 <translation id="385051799172605136">Natrag</translation>
 <translation id="3855472144336161447">njemačka (Neo 2)</translation>
-<translation id="3856075812838139784">Samo za čitanje</translation>
 <translation id="3858678421048828670">Talijanska tipkovnica</translation>
 <translation id="386548886866354912">Zapakiraj proširenjem <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Opis</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google karta</translation>
 <translation id="7419631653042041064">Katalonska tipkovnica</translation>
 <translation id="7434823369735508263">UK Dvorak tipkovnica</translation>
-<translation id="7447678886297481665">Datoteke u ovoj mapi dostupne su samo za čitanje. Neke aktivnosti nisu podržane.</translation>
 <translation id="7460898608667578234">Ukrajinski</translation>
 <translation id="7474889694310679759">Kanadsko-engleska tipkovnica</translation>
 <translation id="7489215562877293245">Pronađene su datoteke (ukupno <ph name="FILE_COUNT" />)
diff --git a/ui/chromeos/translations/ui_chromeos_strings_hu.xtb b/ui/chromeos/translations/ui_chromeos_strings_hu.xtb
index eaa4db6..e972a4ed 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_hu.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_hu.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Gudzsaráti billentyűzet (fonetikus)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">USA billentyűzet</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> elem törölve</translation>
 <translation id="2542049655219295786">Google-tábla</translation>
 <translation id="2547921442987553570">Hozzáadás a következőhöz: <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">USA nemzetközi</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">szerb</translation>
 <translation id="385051799172605136">Vissza</translation>
 <translation id="3855472144336161447">német Neo 2</translation>
-<translation id="3856075812838139784">Csak olvasható</translation>
 <translation id="3858678421048828670">Olasz billentyűzet</translation>
 <translation id="386548886866354912">Csomagolás a következővel: <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Leírás</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google-térkép</translation>
 <translation id="7419631653042041064">Katalán billentyűzet</translation>
 <translation id="7434823369735508263">Brit Dvorak billentyűzet</translation>
-<translation id="7447678886297481665">Az ebben a mappában található fájlok írásvédettek. Bizonyos műveletek nem hajthatók végre velük.</translation>
 <translation id="7460898608667578234">ukrán</translation>
 <translation id="7474889694310679759">Kanadai angol billentyűzet</translation>
 <translation id="7489215562877293245">A következőket találtuk: <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_hy.xtb b/ui/chromeos/translations/ui_chromeos_strings_hy.xtb
index d8caf7d..2dafea2 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_hy.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_hy.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Գուջարաթիի ստեղնաշար (հնչյունաբանական)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">ԱՄՆ ստեղնաշար</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> տարր ջնջվեց</translation>
 <translation id="2542049655219295786">Google աղյուսակ</translation>
 <translation id="2547921442987553570">Ավելացնել <ph name="EXTENSION_NAME" />-ում</translation>
 <translation id="255937426064304553">ԱՄՆ (միջազգային)</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Սերբական</translation>
 <translation id="385051799172605136">Հետ</translation>
 <translation id="3855472144336161447">Գերմանական (Neo 2)</translation>
-<translation id="3856075812838139784">Միայն դիտում</translation>
 <translation id="3858678421048828670">Իտալերենի ստեղնաշար</translation>
 <translation id="386548886866354912">Արխիվացնել <ph name="EXTENSION_NAME" /> ընդլայնման միջոցով</translation>
 <translation id="3866249974567520381">Նկարագրություն</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Google քարտեզ</translation>
 <translation id="7419631653042041064">Կատալոներենի ստեղնաշար</translation>
 <translation id="7434823369735508263">ՄԹ Դվորակի ստեղնաշար</translation>
-<translation id="7447678886297481665">Այս պանակի ֆայլերը հասանելի են միայն կարդալու համար։ Որոշ գործողություններ չեն աջակցվում։</translation>
 <translation id="7460898608667578234">Ուկրաինական</translation>
 <translation id="7474889694310679759">Կանադական անգլերենի ստեղնաշար</translation>
 <translation id="7489215562877293245">Գտնվել է <ph name="FILE_COUNT" /> ֆայլ
diff --git a/ui/chromeos/translations/ui_chromeos_strings_id.xtb b/ui/chromeos/translations/ui_chromeos_strings_id.xtb
index a872ed87..cf815a7 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_id.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_id.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Keyboard Gujarati (Fonetik)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Keyboard AS</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> item dihapus</translation>
 <translation id="2542049655219295786">Tabel Google</translation>
 <translation id="2547921442987553570">Tambahkan ke <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Internasional AS</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serb</translation>
 <translation id="385051799172605136">Kembali</translation>
 <translation id="3855472144336161447">Neo 2 Jerman</translation>
-<translation id="3856075812838139784">Hanya baca</translation>
 <translation id="3858678421048828670">Keyboard untuk bahasa Italia</translation>
 <translation id="386548886866354912">Paketkan dengan <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Deskripsi</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Peta Google</translation>
 <translation id="7419631653042041064">Keyboard untuk bahasa Katalana</translation>
 <translation id="7434823369735508263">Keyboard Dvorak Inggris</translation>
-<translation id="7447678886297481665">File dalam folder ini bersifat hanya baca. Beberapa aktivitas tidak didukung.</translation>
 <translation id="7460898608667578234">Ukraina</translation>
 <translation id="7474889694310679759">Keyboard untuk bahasa Inggris Kanada</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> ditemukan
diff --git a/ui/chromeos/translations/ui_chromeos_strings_is.xtb b/ui/chromeos/translations/ui_chromeos_strings_is.xtb
index e3aad10..f0f1f5b 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_is.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_is.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Gujarati-lyklaborð (hljóðritun)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Bandarískt lyklaborð</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> atriðum eytt</translation>
 <translation id="2542049655219295786">Google tafla</translation>
 <translation id="2547921442987553570">Bæta við <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Bandarískt (alþjóðlegt)</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbneskt</translation>
 <translation id="385051799172605136">Til baka</translation>
 <translation id="3855472144336161447">Þýskt Neo 2</translation>
-<translation id="3856075812838139784">Skrifvarið</translation>
 <translation id="3858678421048828670">Ítalskt lyklaborð</translation>
 <translation id="386548886866354912">Pakki með <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Lýsing</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Google kort</translation>
 <translation id="7419631653042041064">Katalónskt lyklaborð</translation>
 <translation id="7434823369735508263">Breskt Dvorak-lyklaborð</translation>
-<translation id="7447678886297481665">Skrár í þessari möppu eru skrifvarðar. Sumar aðgerðir eru ekki studdar.</translation>
 <translation id="7460898608667578234">Úkraínskt</translation>
 <translation id="7474889694310679759">Kanadískt enskt lyklaborð</translation>
 <translation id="7489215562877293245">Fann <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_it.xtb b/ui/chromeos/translations/ui_chromeos_strings_it.xtb
index 19970ef..9a539a0 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_it.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_it.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Tastiera Gujarati (fonetica)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Tastiera USA</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> elementi eliminati</translation>
 <translation id="2542049655219295786">Tabella Google</translation>
 <translation id="2547921442987553570">Aggiungi all'estensione <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Internazionale USA</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbo</translation>
 <translation id="385051799172605136">Indietro</translation>
 <translation id="3855472144336161447">Tastiera Neo 2 tedesca</translation>
-<translation id="3856075812838139784">Sola lettura</translation>
 <translation id="3858678421048828670">Tastiera italiana</translation>
 <translation id="386548886866354912">Comprimi tramite l'estensione <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Descrizione</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Mappa Google</translation>
 <translation id="7419631653042041064">Tastiera catalana</translation>
 <translation id="7434823369735508263">Tastiera Dvorak britannica</translation>
-<translation id="7447678886297481665">I file in questa cartella sono di sola lettura. Alcune attività non sono supportate.</translation>
 <translation id="7460898608667578234">Ucraino</translation>
 <translation id="7474889694310679759">Tastiera inglese canadese</translation>
 <translation id="7489215562877293245">Elementi trovati: <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_iw.xtb b/ui/chromeos/translations/ui_chromeos_strings_iw.xtb
index 6123615..399dacd1 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_iw.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_iw.xtb
@@ -23,7 +23,7 @@
 <translation id="1155759005174418845">קטלאנית</translation>
 <translation id="1172970565351728681">נותרו כ-<ph name="REMAINING_TIME" /></translation>
 <translation id="1173894706177603556">שנה שם</translation>
-<translation id="117624967391683467">מעתיק את <ph name="FILE_NAME" />...</translation>
+<translation id="117624967391683467">העתקת <ph name="FILE_NAME" /> מתבצעת...</translation>
 <translation id="1178581264944972037">השהיה</translation>
 <translation id="1190144681599273207">הבאת קובץ זה תשתמש בערך ב-<ph name="FILE_SIZE" /> מחבילת הגלישה.</translation>
 <translation id="1201402288615127009">הבא</translation>
@@ -133,7 +133,7 @@
 <translation id="2384596874640104496">מקלדת סינהלה</translation>
 <translation id="240770291734945588"><ph name="SPACE_AVAILABLE" /> זמין</translation>
 <translation id="2425665904502185219">גודל הקובץ הכולל</translation>
-<translation id="2428749644083375155">מעתיק <ph name="NUMBER_OF_ITEMS" /> פריטים אל <ph name="FOLDER_NAME" /></translation>
+<translation id="2428749644083375155">העתקת <ph name="NUMBER_OF_ITEMS" /> פריטים אל <ph name="FOLDER_NAME" /> מתבצעת</translation>
 <translation id="2448312741937722512">סוג</translation>
 <translation id="2453576648990281505">הקובץ כבר קיים</translation>
 <translation id="2464079411014186876">גלידה</translation>
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">מקלדת גוג'אראטי (פונטית)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">מקלדת אנגלית (ארה"ב)</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> פריטים נמחקו</translation>
 <translation id="2542049655219295786">‏טבלה של Google</translation>
 <translation id="2547921442987553570">הוספה אל <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">ארה"ב - בינלאומית</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">סרבית</translation>
 <translation id="385051799172605136">חזרה</translation>
 <translation id="3855472144336161447">‏גרמנית - Neo 2</translation>
-<translation id="3856075812838139784">קריאה בלבד</translation>
 <translation id="3858678421048828670">מקלדת איטלקית</translation>
 <translation id="386548886866354912">הוסף לחבילה יחד עם <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">תיאור</translation>
@@ -291,7 +291,7 @@
 <translation id="4197674956721858839">כיווץ הקבצים שנבחרו</translation>
 <translation id="421017592316736757">עליך להיות במצב מקוון כדי לגשת לקובץ זה.</translation>
 <translation id="4212740939091998969">כבר קיימת תיקייה בשם "<ph name="FOLDER_NAME" />". יש לבחור שם אחר.</translation>
-<translation id="4215448920900139318">מגבה <ph name="FILE_COUNT" /></translation>
+<translation id="4215448920900139318">הגיבוי של <ph name="FILE_COUNT" /> מתבצע</translation>
 <translation id="426015154560005552">מקלדת ערבית</translation>
 <translation id="4261901459838235729">‏מצגת Google</translation>
 <translation id="4290535918735525311">‏תיקייה אחת שותפה עם Linux</translation>
@@ -523,7 +523,7 @@
 <translation id="6505918941256367791">‏מקלדת טמילית (InScript)</translation>
 <translation id="6509122719576673235">נורווגית</translation>
 <translation id="6527303717912515753">שיתוף</translation>
-<translation id="653019979737152879">מסנכרן את <ph name="FILE_NAME" />...</translation>
+<translation id="653019979737152879">הסנכרון של <ph name="FILE_NAME" /> מתבצע...</translation>
 <translation id="6549689063733911810">מהזמן האחרון</translation>
 <translation id="6556866813142980365">ביצוע מחדש</translation>
 <translation id="6558280019477628686">אירעה שגיאה. ייתכן שפריטים מסוימים לא נמחקו.</translation>
@@ -575,7 +575,7 @@
 <translation id="6998711733709403587"><ph name="SELCTED_FOLDERS_COUNT" /> תיקיות נבחרו</translation>
 <translation id="7012943028104619157"><ph name="ROOT_TITLE" /> (<ph name="ROOT_SUMMARY" />)</translation>
 <translation id="7014174261166285193">ההתקנה נכשלה.</translation>
-<translation id="7040138676081995583">פתח באמצעות...</translation>
+<translation id="7040138676081995583">פתיחה באמצעות...</translation>
 <translation id="7100897339030255923">נבחרו <ph name="COUNT" /> פריטים</translation>
 <translation id="7106346894903675391">קנה שטח אחסון נוסף...</translation>
 <translation id="7126604456862387217">‏'&lt;b&gt;<ph name="SEARCH_STRING" />&lt;/b&gt;' – &lt;em&gt;חיפוש ב-‏Drive‏&lt;/em‏&gt;</translation>
@@ -602,7 +602,6 @@
 <translation id="7417705661718309329">‏מפת Google</translation>
 <translation id="7419631653042041064">מקלדת קטלאנית</translation>
 <translation id="7434823369735508263">‏מקלדת Dvorak אנגלית (בריטניה)</translation>
-<translation id="7447678886297481665">הקבצים בתיקייה הזו הם לקריאה בלבד. לא ניתן לבצע פעולות מסוימות.</translation>
 <translation id="7460898608667578234">אוקראינית</translation>
 <translation id="7474889694310679759">מקלדת אנגלית (קנדה)</translation>
 <translation id="7489215562877293245">‏נמצאו <ph name="FILE_COUNT" />
@@ -620,7 +619,7 @@
 <translation id="7627790789328695202">אופס, <ph name="FILE_NAME" /> כבר קיים. שנה את השם שלו ונסה שוב.</translation>
 <translation id="7628656427739290098">‏‎<ph name="PERCENT" />%‎ הושלמו.</translation>
 <translation id="7649070708921625228">עזרה</translation>
-<translation id="7654209398114106148">מתבצעת העברה של<ph name="NUMBER_OF_ITEMS" /> פריטים…</translation>
+<translation id="7654209398114106148">מתבצעת העברה של <ph name="NUMBER_OF_ITEMS" /> פריטים…</translation>
 <translation id="7658239707568436148">ביטול</translation>
 <translation id="7693909743393669729">פירמוט של התקן אחסון ימחק את כל הנתונים המאוחסנים בו ויסיר את כל המחיצות הקיימות, כולל מחיצות שאינן גלויות. לא ניתן לבטל פעולה זו.</translation>
 <translation id="7695430100978772476">לא ניתן לפרמט את <ph name="DRIVE_NAME" /></translation>
@@ -656,7 +655,7 @@
 <translation id="78946041517601018">‏כונני Drive משותפים</translation>
 <translation id="7896906914454843592">מקלדת מורחבת של ארה"ב</translation>
 <translation id="7898607018410277265">מקלדת גוג'אראטי (פונטית חדשה)</translation>
-<translation id="7908793776359722643">פירמוט מחיצה ימחק את כל הנתונים המאוחסנים בה. לא ניתן לבטל פעולה זו.</translation>
+<translation id="7908793776359722643">פרמוט מחיצה ימחק את כל הנתונים המאוחסנים בה. לא ניתן לבטל פעולה זו.</translation>
 <translation id="7917972308273378936">מקלדת ליטאית </translation>
 <translation id="7925686952655276919">אין להשתמש בנתונים ניידים עבור סנכרון</translation>
 <translation id="7928710562641958568">הוצא את המכשיר</translation>
@@ -708,7 +707,7 @@
 <translation id="8342318071240498787">קובץ או ספריה עם אותו שם כבר קיימים.</translation>
 <translation id="8382450452152102026">בתיקייה <ph name="FOLDER_NAME" /></translation>
 <translation id="8391950649760071442">‏תעתוק (emandi → ఏమండీ)</translation>
-<translation id="8395901698320285466">מימדים</translation>
+<translation id="8395901698320285466">מידות</translation>
 <translation id="8412586565681117057">‏שיטת קלט Quick</translation>
 <translation id="8418113698656761985">מקלדת רומנית</translation>
 <translation id="8432745813735585631">‏מקלדת Colemak אנגלית (ארה"ב)</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ja.xtb b/ui/chromeos/translations/ui_chromeos_strings_ja.xtb
index 1ab6110..02c262a 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ja.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ja.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">グジャラト語キーボード(表音)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">英語(米国)のキーボード</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" />件の項目を削除しました</translation>
 <translation id="2542049655219295786">Google Table</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" /> に追加</translation>
 <translation id="255937426064304553">US インターナショナル</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">セルビア語</translation>
 <translation id="385051799172605136">戻る</translation>
 <translation id="3855472144336161447">ドイツ語(Neo 2)</translation>
-<translation id="3856075812838139784">読み取り専用</translation>
 <translation id="3858678421048828670">イタリア語のキーボード</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> を同梱</translation>
 <translation id="3866249974567520381">説明</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google マップ</translation>
 <translation id="7419631653042041064">カタロニア語のキーボード</translation>
 <translation id="7434823369735508263">Dvorak 配列キーボード(英国)</translation>
-<translation id="7447678886297481665">このフォルダ内のファイルは読み取り専用です。一部の操作は行えません。</translation>
 <translation id="7460898608667578234">ウクライナ語</translation>
 <translation id="7474889694310679759">英語(カナダ)のキーボード</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" />が見つかりました
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ka.xtb b/ui/chromeos/translations/ui_chromeos_strings_ka.xtb
index a609c29..f980647 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ka.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ka.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">გუჯარათის კლავიატურა (ფონეტიკური)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">შეერთებული შტატების კლავიატურა</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> ერთეული წაიშალა</translation>
 <translation id="2542049655219295786">Google ცხრილი</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" />-ში დამატება</translation>
 <translation id="255937426064304553">აშშ საერთაშორისო</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">სერბული</translation>
 <translation id="385051799172605136">უკან</translation>
 <translation id="3855472144336161447">გერმანული Neo 2</translation>
-<translation id="3856075812838139784">მხოლოდ კითხვადი</translation>
 <translation id="3858678421048828670">იტალიური კლავიატურა</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" />-ით შეფუთვა</translation>
 <translation id="3866249974567520381">აღწერა</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Google რუკა</translation>
 <translation id="7419631653042041064">კატალანური კლავიატურა</translation>
 <translation id="7434823369735508263">დიდი ბრიტანეთის Dvorak კლავიატურა</translation>
-<translation id="7447678886297481665">ამ საქაღალდეში არსებული ფაილები მხოლოდ კითხვადია. ზოგიერთი მოქმედება მხარდაუჭერელია.</translation>
 <translation id="7460898608667578234">უკრაინული</translation>
 <translation id="7474889694310679759">კანადურ ინგლისური კლავიატურა</translation>
 <translation id="7489215562877293245">მოიძებნა <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_kk.xtb b/ui/chromeos/translations/ui_chromeos_strings_kk.xtb
index 2e475ca..a70010f 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_kk.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_kk.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Гуджарати пернетақтасы (Фонетикалық)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">АҚШ пернетақтасы</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> элемент жойылды.</translation>
 <translation id="2542049655219295786">Google кестесі</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" /> кеңейтіміне қосу</translation>
 <translation id="255937426064304553">АҚШ халықаралық</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">серб</translation>
 <translation id="385051799172605136">Артқа</translation>
 <translation id="3855472144336161447">Неміс (Neo 2)</translation>
-<translation id="3856075812838139784">Тек оқуға арналған</translation>
 <translation id="3858678421048828670">Итальян пернетақтасы</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> кеңейтімді пакет</translation>
 <translation id="3866249974567520381">Сипаттама</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Google картасы</translation>
 <translation id="7419631653042041064">Каталан пернетақтасы</translation>
 <translation id="7434823369735508263">Ұлыбритания Дворак пернетақтасы</translation>
-<translation id="7447678886297481665">Бұл қалталардағы файлдарды тек оқуға болады. Кейбір әрекеттерге қолдау көрсетілмейді.</translation>
 <translation id="7460898608667578234">украин</translation>
 <translation id="7474889694310679759">Ағылшын пернетақтасы (Канадалық)</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> файл табылды
diff --git a/ui/chromeos/translations/ui_chromeos_strings_km.xtb b/ui/chromeos/translations/ui_chromeos_strings_km.xtb
index 3e5409b..53957b5a 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_km.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_km.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">ក្តារចុចគូចារ៉ាទី (Phonetic)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">ក្តារចុចអាមេរិក</translation>
+<translation id="2534155362429831547">បានលុបធាតុ <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2542049655219295786">តារាង Google</translation>
 <translation id="2547921442987553570">បន្ថែមទៅ <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">US អន្តរជាតិ</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">ភាសាស៊ែប</translation>
 <translation id="385051799172605136">ថយក្រោយ</translation>
 <translation id="3855472144336161447">German Neo 2</translation>
-<translation id="3856075812838139784">អានប៉ុណ្ណោះ</translation>
 <translation id="3858678421048828670">ក្តារចុចអ៊ីតាលី</translation>
 <translation id="386548886866354912">ដាក់ក្នុងកញ្ចប់ជាមួយ <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">ការពិពណ៌នា</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Google ផែនទី</translation>
 <translation id="7419631653042041064">ក្តារចុចកាតាឡាន</translation>
 <translation id="7434823369735508263">ក្តារចុចចក្រភពអស់គ្លេស Dvorak</translation>
-<translation id="7447678886297481665">ឯកសារ​នៅក្នុង​ថតនេះគឺសម្រាប់​តែអានប៉ុណ្ណោះ។ មិនអាច​ប្រើសកម្មភាព​មួយចំនួន​បានទេ។</translation>
 <translation id="7460898608667578234">ភាសាអ៊ុយក្រែន</translation>
 <translation id="7474889694310679759">ក្តារចុចភាសាអស់គ្លេសកាណាដា</translation>
 <translation id="7489215562877293245">បានរកឃើញ <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_kn.xtb b/ui/chromeos/translations/ui_chromeos_strings_kn.xtb
index 90b0bc1..581ac10 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_kn.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_kn.xtb
@@ -138,6 +138,7 @@
 <translation id="2494837236724268445">ಗುಜರಾತಿ ಕೀಬೋರ್ಡ್ (ಫೋನೆಟಿಕ್)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">US ಕೀಬೋರ್ಡ್</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> ಐಟಂಗಳನ್ನು ಅಳಿಸಲಾಗಿದೆ</translation>
 <translation id="2542049655219295786">Google ಕೋಷ್ಟಕ</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" /> ಗೆ ಸೇರಿಸಿ</translation>
 <translation id="255937426064304553">US ಇಂಟರ್‌ನ್ಯಾಷನಲ್</translation>
@@ -263,7 +264,6 @@
 <translation id="383652340667548381">ಸೆರ್ಬಿಯನ್</translation>
 <translation id="385051799172605136">ಹಿಂದೆ</translation>
 <translation id="3855472144336161447">ಜರ್ಮನ್ ನಿಯೊ 2</translation>
-<translation id="3856075812838139784">ಓದಲು ಮಾತ್ರ</translation>
 <translation id="3858678421048828670">ಇಟಾಲಿಯನ್ ಕೀಬೋರ್ಡ್</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> ಜೊತೆಗೆ ಪ್ಯಾಕ್</translation>
 <translation id="3866249974567520381">ವಿವರಣೆ</translation>
@@ -595,7 +595,6 @@
 <translation id="7417705661718309329">Google ನಕ್ಷೆ</translation>
 <translation id="7419631653042041064">ಕೆಟಲಾನ್ ಕೀಬೋರ್ಡ್</translation>
 <translation id="7434823369735508263">ಯುಕೆ ಡಿವೊರಾಕ್ ಕೀಬೋರ್ಡ್</translation>
-<translation id="7447678886297481665">ಈ ಫೋಲ್ಡರ್‌ನಲ್ಲಿರುವ ಫೈಲ್‌ಗಳು ಓದಲು ಮಾತ್ರ. ಕೆಲವು ಚಟುವಟಿಕೆಗಳು ಬೆಂಬಲಿತವಾಗಿರುವುದಿಲ್ಲ.</translation>
 <translation id="7460898608667578234">ಉಕ್ರೇನಿಯನ್</translation>
 <translation id="7474889694310679759">ಕೆನಡಿಯನ್ ಇಂಗ್ಲಿಷ್ ಕೀಬೋರ್ಡ್</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> ಕಂಡುಬಂದಿವೆ <ph name="LINE_BREAK1" /> <ph name="BEGIN_LINK" />Google ಡ್ರೈವ್<ph name="END_LINK" /> ಗೆ ಬ್ಯಾಕಪ್ ಮಾಡಲು ಸಿದ್ಧವಾಗಿದೆ</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ko.xtb b/ui/chromeos/translations/ui_chromeos_strings_ko.xtb
index c12b970..68563cb0 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ko.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ko.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">구자라트어 키보드(음역)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">영어(미국식) 키보드</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" />개 항목 삭제함</translation>
 <translation id="2542049655219295786">Google 표</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" />에 추가</translation>
 <translation id="255937426064304553">영어(미국 국제)</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">세르비아어</translation>
 <translation id="385051799172605136">뒤로</translation>
 <translation id="3855472144336161447">독일어 Neo 2</translation>
-<translation id="3856075812838139784">읽기 전용</translation>
 <translation id="3858678421048828670">이탈리아어 키보드</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" />(으)로 보관처리</translation>
 <translation id="3866249974567520381">설명</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google 지도</translation>
 <translation id="7419631653042041064">카탈로니아어 키보드</translation>
 <translation id="7434823369735508263">영어(영국식) 드보락 키보드</translation>
-<translation id="7447678886297481665">이 폴더의 파일은 읽기 전용입니다. 일부 활동이 지원되지 않습니다.</translation>
 <translation id="7460898608667578234">우크라이나어</translation>
 <translation id="7474889694310679759">캐나다 영어 키보드</translation>
 <translation id="7489215562877293245">파일 <ph name="FILE_COUNT" />개 있음
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ky.xtb b/ui/chromeos/translations/ui_chromeos_strings_ky.xtb
index db6781a7..f33bedf 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ky.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ky.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Гужарати баскычтобу (Фонетикалык)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">АКШ баскычтобу</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> нерсе өчүрүлдү</translation>
 <translation id="2542049655219295786">Google жадыбалы</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" /> кеңейтүүсүнө кошуу</translation>
 <translation id="255937426064304553">АКШ эл аралык</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Сербче</translation>
 <translation id="385051799172605136">Артка</translation>
 <translation id="3855472144336161447">German Neo 2</translation>
-<translation id="3856075812838139784">Окуганга гана</translation>
 <translation id="3858678421048828670">Итальянча баскычтоп</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> кеңейтүүсү менен таңгактоо</translation>
 <translation id="3866249974567520381">Сүрөттөлүшү</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Google карта</translation>
 <translation id="7419631653042041064">Каталан баскычтобу</translation>
 <translation id="7434823369735508263">БК Dvorak баскычтобу</translation>
-<translation id="7447678886297481665">Бул папкадагы файлдарды көрүүгө гана болот. Айрым аракеттерге уруксат берилген эмес.</translation>
 <translation id="7460898608667578234">Украинче</translation>
 <translation id="7474889694310679759">Англисче баскычтобу (Канада)</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> табылды
diff --git a/ui/chromeos/translations/ui_chromeos_strings_lo.xtb b/ui/chromeos/translations/ui_chromeos_strings_lo.xtb
index 67deb217..cfb8522 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_lo.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_lo.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">ຄີບອດພາສາກູຈາຣາຕີ (ການອອກສຽງ​)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">ຄີບອດສະ​ຫະ​ລັດ</translation>
+<translation id="2534155362429831547">ລຶບ <ph name="NUMBER_OF_ITEMS" /> ລາຍ​ການ​​ແລ້ວ</translation>
 <translation id="2542049655219295786">ຕາ​ຕະ​ລາງ​ Google</translation>
 <translation id="2547921442987553570">ເພີ່ມໃສ່ <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">US ສາ​ກົນ</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">ພາສາເຊີ​ເບຍ</translation>
 <translation id="385051799172605136">ກັບ​ຄືນ​</translation>
 <translation id="3855472144336161447">ພາສາເຢຍລະັມນ Neo 2</translation>
-<translation id="3856075812838139784">ອ່ານເທົ່ານັ້ນ</translation>
 <translation id="3858678421048828670">ຄີບອດພາສາອີຕາລີ</translation>
 <translation id="386548886866354912">ເກັບຮວມກັນກັບ <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">ລາຍ​ລະ​ອຽດ</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">ແຜນ​ທີ່ Google</translation>
 <translation id="7419631653042041064">ຄີບອດພາສາກາຕາລັນ</translation>
 <translation id="7434823369735508263">ຄີບອດດີວໍຣັກສະ​ຫະ​ລາດຊະອານາຈັກ</translation>
-<translation id="7447678886297481665">ໄຟລ໌ໃນໂຟນເດີນີ້ເປັນແບບອ່ານເທົ່ານັ້ນ. ບໍ່ຮອງຮັບບາງກິດຈະກຳ.</translation>
 <translation id="7460898608667578234">ພາສາຢູ​ເຄຣນ</translation>
 <translation id="7474889694310679759">ຄີບອດພາສາອັງກິດການາດາ</translation>
 <translation id="7489215562877293245">ພົບ <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_lt.xtb b/ui/chromeos/translations/ui_chromeos_strings_lt.xtb
index cd463dd..39b98fb1 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_lt.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_lt.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Gudžarati klaviatūra (fonetinė)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">JAV klaviatūra</translation>
+<translation id="2534155362429831547">Ištrinta elementų: <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2542049655219295786">„Google“ lentelė</translation>
 <translation id="2547921442987553570">Pridėti prie „<ph name="EXTENSION_NAME" />“</translation>
 <translation id="255937426064304553">JAV tarptautinė</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbų</translation>
 <translation id="385051799172605136">Atgal</translation>
 <translation id="3855472144336161447">Vokiečių „Neo 2“</translation>
-<translation id="3856075812838139784">Tik skaitoma</translation>
 <translation id="3858678421048828670">Itališka klaviatūra</translation>
 <translation id="386548886866354912">Supakuoti naudojant <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Aprašas</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">„Google“ žemėlapis</translation>
 <translation id="7419631653042041064">Kataloniška klaviatūra</translation>
 <translation id="7434823369735508263">JK Dvorako klaviatūra</translation>
-<translation id="7447678886297481665">Failai šiame aplanke tik skaitomi. Tam tikra veikla nepalaikoma.</translation>
 <translation id="7460898608667578234">Ukrainiečių</translation>
 <translation id="7474889694310679759">Kanados angliška klaviatūra</translation>
 <translation id="7489215562877293245">Rasta: <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_lv.xtb b/ui/chromeos/translations/ui_chromeos_strings_lv.xtb
index 01e8eff..a1305da 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_lv.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_lv.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Gudžaratu valodas tastatūra (fonētiskā)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">ASV tastatūra</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> vienumi tika izdzēsti</translation>
 <translation id="2542049655219295786">Google tabula</translation>
 <translation id="2547921442987553570">Pievienot paplašinājumam <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">ASV starptautiskā</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbu valoda</translation>
 <translation id="385051799172605136">Atpakaļ</translation>
 <translation id="3855472144336161447">Vācu Neo 2</translation>
-<translation id="3856075812838139784">Tikai lasāms</translation>
 <translation id="3858678421048828670">Itāļu valodas tastatūra</translation>
 <translation id="386548886866354912">Sapakot kā: <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Apraksts</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google karte</translation>
 <translation id="7419631653042041064">Katalāņu valodas tastatūra</translation>
 <translation id="7434823369735508263">AK Dvoraka tastatūra</translation>
-<translation id="7447678886297481665">Faili šajās mapēs ir tikai lasāmi. Noteiktas darbības netiek atbalstītas.</translation>
 <translation id="7460898608667578234">Ukraiņu valoda</translation>
 <translation id="7474889694310679759">Kanādas angļu valodas tastatūra</translation>
 <translation id="7489215562877293245">Atrasts: <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_mk.xtb b/ui/chromeos/translations/ui_chromeos_strings_mk.xtb
index f338e3e1..2df7f61 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_mk.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_mk.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">гуџарати тастатура (Phonetic)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">САД тастатура</translation>
+<translation id="2534155362429831547">Избришани се <ph name="NUMBER_OF_ITEMS" /> ставки</translation>
 <translation id="2542049655219295786">Табела на Google</translation>
 <translation id="2547921442987553570">Додајте во <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Меѓународен англиски (САД)</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">српска</translation>
 <translation id="385051799172605136">Назад</translation>
 <translation id="3855472144336161447">Германска Neo 2</translation>
-<translation id="3856075812838139784">Само за читање</translation>
 <translation id="3858678421048828670">италијанска тастатура</translation>
 <translation id="386548886866354912">Спакувајте со <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Опис</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Карта на Google</translation>
 <translation id="7419631653042041064">каталонска тастатура</translation>
 <translation id="7434823369735508263">ОК тастатура Dvorak</translation>
-<translation id="7447678886297481665">Датотеките во папкава се само за читање. Некои активности не се поддржани.</translation>
 <translation id="7460898608667578234">украинска</translation>
 <translation id="7474889694310679759">тастатура на канадски англиски</translation>
 <translation id="7489215562877293245">Најдени се <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ml.xtb b/ui/chromeos/translations/ui_chromeos_strings_ml.xtb
index 54a0292b..3445115 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ml.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ml.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">ഗുജറാത്തി കീബോർഡ് (സ്വരസൂചകം)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">യുഎസ് കീബോര്‍ഡ്</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> ഇനങ്ങൾ ഇല്ലാതാക്കി</translation>
 <translation id="2542049655219295786">Google പട്ടിക</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" />-ൽ ചേർക്കുക</translation>
 <translation id="255937426064304553">യുഎസ് ഇന്റർനാഷണൽ</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">സെര്‍ബിയന്‍</translation>
 <translation id="385051799172605136">പിന്നോട്ട്</translation>
 <translation id="3855472144336161447">ജർമ്മൻ നിയോ 2</translation>
-<translation id="3856075812838139784">വായനമാത്രം</translation>
 <translation id="3858678421048828670">ഇറ്റാലിയന്‍ കീബോര്‍ഡ്</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> ഉപയോഗിച്ച് പായ്‌ക്കുചെയ്യുക</translation>
 <translation id="3866249974567520381">വിവരണം</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google മാപ്പ്</translation>
 <translation id="7419631653042041064">കാറ്റലൻ കീബോര്‍ഡ്</translation>
 <translation id="7434823369735508263">യുകെ ഡൊറാക്ക് കീബോര്‍ഡ്</translation>
-<translation id="7447678886297481665">ഈ ഫോൾഡറിലെ ഫയലുകൾ വായിക്കാൻ മാത്രമുള്ളവയാണ്. ചില ആക്റ്റിവിറ്റികൾക്ക് പിന്തുണയില്ല.</translation>
 <translation id="7460898608667578234">ഉക്രേനിയന്‍</translation>
 <translation id="7474889694310679759">കനേഡിയന്‍ ഇംഗ്ലീഷ് കീബോര്‍ഡ്</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> കണ്ടെത്തി
diff --git a/ui/chromeos/translations/ui_chromeos_strings_mn.xtb b/ui/chromeos/translations/ui_chromeos_strings_mn.xtb
index 0673a49..87b89883 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_mn.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_mn.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Гужарати хэлний гар (дуудлагын)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">АНУ-ын хэлний гар</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> зүйлийг устгасан</translation>
 <translation id="2542049655219295786">Google-ийн хүснэгт</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" />-д нэмэх</translation>
 <translation id="255937426064304553">АНУ олон улсын</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Серби</translation>
 <translation id="385051799172605136">Буцах</translation>
 <translation id="3855472144336161447">Герман Neo 2</translation>
-<translation id="3856075812838139784">Зөвхөн уншуулах</translation>
 <translation id="3858678421048828670">Итали хэлний гар</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" />-р багцлах</translation>
 <translation id="3866249974567520381">Тодорхойлолт</translation>
@@ -598,7 +598,6 @@
 <translation id="7417705661718309329">Google-ийн газрын зураг</translation>
 <translation id="7419631653042041064">Каталан хэлний гар</translation>
 <translation id="7434823369735508263">Их Британийн Dvorak гар</translation>
-<translation id="7447678886297481665">Энэ фолдерын файлуудыг зөвхөн унших боломжтой. Зарим үйл ажиллагааг дэмждэггүй.</translation>
 <translation id="7460898608667578234">Украйн</translation>
 <translation id="7474889694310679759">Канадын Англи хэлний гар</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> олдсон
diff --git a/ui/chromeos/translations/ui_chromeos_strings_mr.xtb b/ui/chromeos/translations/ui_chromeos_strings_mr.xtb
index fe3076d..5cc317b1 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_mr.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_mr.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">गुजराती कीबोर्ड (Phonetic)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">यूएस कीबोर्ड</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> आयटम हटवले</translation>
 <translation id="2542049655219295786">Google सारणी</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" /> मध्ये जोडा</translation>
 <translation id="255937426064304553">यूएस आंतरराष्ट्रीय</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">सर्बियन</translation>
 <translation id="385051799172605136">मागील</translation>
 <translation id="3855472144336161447">जर्मन निओ 2</translation>
-<translation id="3856075812838139784">केवळ वाचनीय</translation>
 <translation id="3858678421048828670">इटालियन कीबोर्ड</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> सह पॅक</translation>
 <translation id="3866249974567520381">वर्णन</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google नकाशा</translation>
 <translation id="7419631653042041064">कॅटलान कीबोर्ड</translation>
 <translation id="7434823369735508263">यूके दवोराक कीबोर्ड</translation>
-<translation id="7447678886297481665">या फोल्डरमधील फाइल फक्त वाचता येणार्‍या आहेत. काही अ‍ॅक्टिव्हिटींना सपोर्ट नाही.</translation>
 <translation id="7460898608667578234">यूक्रेनियन</translation>
 <translation id="7474889694310679759">कॅनेडियन इंग्रजी कीबोर्ड</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> आढळले
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ms.xtb b/ui/chromeos/translations/ui_chromeos_strings_ms.xtb
index c2b22db..a74770c 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ms.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ms.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Papan kekunci bahasa Gujarati (Fonetik)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Papan kekunci AS</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> item dipadamkan</translation>
 <translation id="2542049655219295786">Jadual Google</translation>
 <translation id="2547921442987553570">Tambahkan pada <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Antarabangsa AS</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Bahasa Serbia</translation>
 <translation id="385051799172605136">Kembali</translation>
 <translation id="3855472144336161447">Bahasa Jerman Neo 2</translation>
-<translation id="3856075812838139784">Baca sahaja</translation>
 <translation id="3858678421048828670">Papan kekunci Itali</translation>
 <translation id="386548886866354912">Dipek dengan <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Huraian</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Peta Google</translation>
 <translation id="7419631653042041064">Papan kekunci Catalonia</translation>
 <translation id="7434823369735508263">Papan kekunci Dvorak UK</translation>
-<translation id="7447678886297481665">Fail dalam folder ini bersifat baca sahaja. Sesetengah aktiviti tidak disokong.</translation>
 <translation id="7460898608667578234">Bahasa Ukraine</translation>
 <translation id="7474889694310679759">Papan kekunci Inggeris Kanada</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> ditemui
diff --git a/ui/chromeos/translations/ui_chromeos_strings_my.xtb b/ui/chromeos/translations/ui_chromeos_strings_my.xtb
index dbe61b7..6b804be 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_my.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_my.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">ဂူဂျရာသီ ကီးဘုတ် (Phonetic)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">US ကီးဘုတ်</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> ခုဖျက်ပြီးပြီ</translation>
 <translation id="2542049655219295786">Google ဇယား</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" /> သို့ထည့်ပါ</translation>
 <translation id="255937426064304553">US international</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">စာဘီယန်</translation>
 <translation id="385051799172605136">နောက်သို့</translation>
 <translation id="3855472144336161447">German Neo 2</translation>
-<translation id="3856075812838139784">ဖတ်ရန် အတွက်သာ</translation>
 <translation id="3858678421048828670">အီတလီ ကီးဘုတ်</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> ဖြင့်ထုပ်ပိုးပါ</translation>
 <translation id="3866249974567520381">ဖေါ်ပြချက်</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Google မြေပုံ</translation>
 <translation id="7419631653042041064">ကာတာလန် ကီးဘုတ်</translation>
 <translation id="7434823369735508263">UK Dvorak ကီးဘုတ်</translation>
-<translation id="7447678886297481665">ဤဖိုင်တွဲအတွင်းရှိ ဖိုင်များက ဖတ်ရန်သီးသန့် ဖြစ်သည်။ လုပ်ဆောင်ချက်အချို့ကို မပံ့ပိုးပါ။</translation>
 <translation id="7460898608667578234">ယူကရိန်းနီးယန်း</translation>
 <translation id="7474889694310679759">ကနေဒါ အင်္ဂလိပ် ကီးဘုတ်</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> တွေ့ပါသည်
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ne.xtb b/ui/chromeos/translations/ui_chromeos_strings_ne.xtb
index 4749b92..485c671 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ne.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ne.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">गुजराती किबोर्ड (ध्वन्यात्मक)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">अमेरिकी किबोर्ड</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> वस्तुहरू मेटाइए</translation>
 <translation id="2542049655219295786">Google तालिका</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" /> मा थप्नुहोस्</translation>
 <translation id="255937426064304553">यु.एस. अन्तर्राष्ट्रिय</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">सर्वियन</translation>
 <translation id="385051799172605136">पछाडि जानुहोस्</translation>
 <translation id="3855472144336161447">जर्मन नियो 2</translation>
-<translation id="3856075812838139784">पढ्ने मात्र</translation>
 <translation id="3858678421048828670">इटालियन किबोर्ड</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> मार्फत प्याक गर्नुहोस्</translation>
 <translation id="3866249974567520381">विवरण</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Google नक्सा</translation>
 <translation id="7419631653042041064">कातालान किबोर्ड</translation>
 <translation id="7434823369735508263">बेलायत ड्भोराक किबोर्ड</translation>
-<translation id="7447678886297481665">यो फोल्डरभित्र रहेका फाइलहरू रिड गर्न मात्र मिल्छ। केही क्रियाकलापहरू गर्न मिल्दैन।</translation>
 <translation id="7460898608667578234">युक्रेनियन</translation>
 <translation id="7474889694310679759">क्यानाडा अंग्रेजी किबोर्ड</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> फेला पर्‍यो
diff --git a/ui/chromeos/translations/ui_chromeos_strings_nl.xtb b/ui/chromeos/translations/ui_chromeos_strings_nl.xtb
index 9f6ef743..c53c33d 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_nl.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_nl.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Gujarati toetsenbord (fonetisch)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Amerikaans toetsenbord</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> items verwijderd</translation>
 <translation id="2542049655219295786">Google-tabel</translation>
 <translation id="2547921442987553570">Toevoegen aan <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Verenigde Staten (internationaal)</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Servisch</translation>
 <translation id="385051799172605136">Terug</translation>
 <translation id="3855472144336161447">Duits Neo 2</translation>
-<translation id="3856075812838139784">Alleen-lezen</translation>
 <translation id="3858678421048828670">Italiaans toetsenbord</translation>
 <translation id="386548886866354912">Inpakken met <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Beschrijving</translation>
@@ -602,7 +602,6 @@
 <translation id="7417705661718309329">Google-kaart</translation>
 <translation id="7419631653042041064">Catalaans toetsenbord</translation>
 <translation id="7434823369735508263">Brits Dvorak-toetsenbord</translation>
-<translation id="7447678886297481665">Bestanden in deze map zijn alleen-lezen. Sommige activiteiten worden niet ondersteund.</translation>
 <translation id="7460898608667578234">Oekraïens</translation>
 <translation id="7474889694310679759">Canadees-Engels toetsenbord</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> gevonden
diff --git a/ui/chromeos/translations/ui_chromeos_strings_no.xtb b/ui/chromeos/translations/ui_chromeos_strings_no.xtb
index eb0b84a3..b78506e0 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_no.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_no.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Gujarati-tastatur (fonetisk)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Amerikansk tastatur (USA)</translation>
+<translation id="2534155362429831547">Slettet <ph name="NUMBER_OF_ITEMS" /> elementer</translation>
 <translation id="2542049655219295786">Google-tabell</translation>
 <translation id="2547921442987553570">Legg til i <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">USA internasjonalt</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbisk</translation>
 <translation id="385051799172605136">Tilbake</translation>
 <translation id="3855472144336161447">Tysk Neo 2</translation>
-<translation id="3856075812838139784">Skrivebeskyttet</translation>
 <translation id="3858678421048828670">Italiensk tastatur</translation>
 <translation id="386548886866354912">Pakk med <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Beskrivelse</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google Maps</translation>
 <translation id="7419631653042041064">Katalansk tastatur</translation>
 <translation id="7434823369735508263">Britisk tastatur (Dvorak)</translation>
-<translation id="7447678886297481665">Filene i denne mappen er skrivebeskyttede. Noen aktiviteter støttes ikke.</translation>
 <translation id="7460898608667578234">Ukrainsk</translation>
 <translation id="7474889694310679759">Engelsk tastatur (Canada)</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> ble funnet
diff --git a/ui/chromeos/translations/ui_chromeos_strings_or.xtb b/ui/chromeos/translations/ui_chromeos_strings_or.xtb
index e662903..6c1eab5 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_or.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_or.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">ଗୁଜରାତି କୀ'ବୋର୍ଡ (ଫୋନେଟିକ୍)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">US କୀବୋର୍ଡ</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" />ଟି ଆଇଟମ୍‌ ଡିଲିଟ୍‍ ହୋ‍ଇଛି</translation>
 <translation id="2542049655219295786">Google ଟେବଲ୍</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" /> ସହିତ ଯୋଗ କରନ୍ତୁ</translation>
 <translation id="255937426064304553">US ଆନ୍ତର୍ଜାତିକ</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">ସର୍ବିଆନ୍</translation>
 <translation id="385051799172605136">ପଛକୁ</translation>
 <translation id="3855472144336161447">ଜର୍ମନ୍ ନିଓ 2</translation>
-<translation id="3856075812838139784">କେବଳ ପଢ଼ିବା ପାଇଁ</translation>
 <translation id="3858678421048828670">ଇଟାଲିଆନ୍ କୀବୋର୍ଡ</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> ମାଧ୍ୟମରେ ପ୍ୟାକ୍ କରନ୍ତୁ</translation>
 <translation id="3866249974567520381">ବିବରଣୀ</translation>
@@ -595,7 +595,6 @@
 <translation id="7417705661718309329">Google ମ୍ୟାପ୍‌</translation>
 <translation id="7419631653042041064">କାଟାଲାନ୍ କୀବୋର୍ଡ</translation>
 <translation id="7434823369735508263">UK ଡିଭୋରାକ୍ କୀବୋର୍ଡ</translation>
-<translation id="7447678886297481665">ଏହି ଫୋଲ୍ଡରରେ ଥିବା ଫାଇଲଗୁଡ଼ିକ କେବଳ ପଢ଼ିବା ପାଇଁ ଅଟେ। କିଛି କାର୍ଯ୍ୟକଳାପ ସମର୍ଥିତ ନୁହେଁ।</translation>
 <translation id="7460898608667578234">ୟୁକ୍ରାନିଆନ୍</translation>
 <translation id="7474889694310679759">କାନାଡିଆନ୍ ଇଂରାଜୀ କୀବୋର୍ଡ୍</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" />ଟି ମିଳିଛି
diff --git a/ui/chromeos/translations/ui_chromeos_strings_pa.xtb b/ui/chromeos/translations/ui_chromeos_strings_pa.xtb
index 928ba0e..931ff2e1 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_pa.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_pa.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">ਗੁਜਰਾਤੀ ਕੀ-ਬੋਰਡ (ਧੁਨੀਆਤਮਿਕ)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">US ਕੀ-ਬੋਰਡ</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> ਆਈਟਮਾਂ ਮਿਟਾਈਆਂ ਗਈਆਂ</translation>
 <translation id="2542049655219295786">Google ਸਾਰਨੀ</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" /> ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ</translation>
 <translation id="255937426064304553">ਅਮਰੀਕਾ ਅੰਤਰਰਾਸ਼ਟਰੀ</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbian</translation>
 <translation id="385051799172605136">ਪਿੱਛੇ</translation>
 <translation id="3855472144336161447">ਜਰਮਨ Neo 2</translation>
-<translation id="3856075812838139784">ਰੀਡ ਓਨਲੀ</translation>
 <translation id="3858678421048828670">ਇਤਾਲਵੀ ਕੀ-ਬੋਰਡ</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> ਨਾਲ ਪੈਕ ਕਰੋ</translation>
 <translation id="3866249974567520381">ਵਰਣਨ</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Google ਨਕਸ਼ਾ</translation>
 <translation id="7419631653042041064">ਕੈਟਲਨ ਕੀ-ਬੋਰਡ</translation>
 <translation id="7434823369735508263">UK Dvorak ਕੀ-ਬੋਰਡ</translation>
-<translation id="7447678886297481665">ਇਸ ਫੋਲਡਰ ਦੀਆਂ ਫ਼ਾਈਲਾਂ ਸਿਰਫ਼ ਪੜ੍ਹਨ ਲਈ ਹਨ। ਕੁਝ ਸਰਗਰਮੀਆਂ ਸਮਰਥਿਤ ਨਹੀਂ ਹਨ।</translation>
 <translation id="7460898608667578234">Ukrainian</translation>
 <translation id="7474889694310679759">ਕੈਨੇਡੀਅਨ ਅੰਗਰੇਜ਼ੀ ਕੀ-ਬੋਰਡ</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> ਮਿਲੀਆਂ
diff --git a/ui/chromeos/translations/ui_chromeos_strings_pl.xtb b/ui/chromeos/translations/ui_chromeos_strings_pl.xtb
index 7ab681e..362767e 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_pl.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_pl.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Klawiatura gudżarati (fonetyczna)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Klawiatura amerykańska</translation>
+<translation id="2534155362429831547">Usunięte elementy: <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2542049655219295786">Tabela Google</translation>
 <translation id="2547921442987553570">Dodaj do rozszerzenia <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">amerykańska klawiatura międzynarodowa</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbski</translation>
 <translation id="385051799172605136">Wstecz</translation>
 <translation id="3855472144336161447">niemiecka klawiatura Neo 2</translation>
-<translation id="3856075812838139784">Tylko do odczytu</translation>
 <translation id="3858678421048828670">Klawiatura włoska</translation>
 <translation id="386548886866354912">Spakuj, używając rozszerzenia <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Opis</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Mapa Google</translation>
 <translation id="7419631653042041064">Klawiatura katalońska</translation>
 <translation id="7434823369735508263">Klawiatura brytyjska (Dvorak)</translation>
-<translation id="7447678886297481665">Pliki w tym folderze są tylko do odczytu. Niektóre działania nie są obsługiwane.</translation>
 <translation id="7460898608667578234">Ukraiński</translation>
 <translation id="7474889694310679759">Klawiatura kanadyjska (angielski)</translation>
 <translation id="7489215562877293245">Znaleziono <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_pt-BR.xtb b/ui/chromeos/translations/ui_chromeos_strings_pt-BR.xtb
index 166fdb26..eade0092f 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_pt-BR.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_pt-BR.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Teclado gujarati (fonético)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Teclado americano</translation>
+<translation id="2534155362429831547">Itens excluídos: <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2542049655219295786">Tabela do Google</translation>
 <translation id="2547921442987553570">Adicionar à extensão <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Internacional: Estados Unidos</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Sérvio</translation>
 <translation id="385051799172605136">Voltar</translation>
 <translation id="3855472144336161447">Alemão (Neo 2)</translation>
-<translation id="3856075812838139784">Somente leitura</translation>
 <translation id="3858678421048828670">Teclado italiano</translation>
 <translation id="386548886866354912">Compactar com <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Descrição</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Mapa do Google</translation>
 <translation id="7419631653042041064">Teclado catalão</translation>
 <translation id="7434823369735508263">Teclado Dvorak do Reino Unido</translation>
-<translation id="7447678886297481665">Os arquivos dessa pasta são somente leitura. Algumas atividades estão indisponíveis.</translation>
 <translation id="7460898608667578234">Ucraniano</translation>
 <translation id="7474889694310679759">Teclado canadense (inglês)</translation>
 <translation id="7489215562877293245">Total de arquivos encontrados: <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_pt-PT.xtb b/ui/chromeos/translations/ui_chromeos_strings_pt-PT.xtb
index b1597b9..ede41cff 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_pt-PT.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_pt-PT.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Teclado gujarati (fonético)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Teclado americano</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> itens eliminados</translation>
 <translation id="2542049655219295786">Tabela do Google</translation>
 <translation id="2547921442987553570">Adicionar a <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">EUA internacional</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Sérvio</translation>
 <translation id="385051799172605136">Anterior</translation>
 <translation id="3855472144336161447">Alemão Neo 2</translation>
-<translation id="3856075812838139784">Apenas leitura</translation>
 <translation id="3858678421048828670">Teclado italiano</translation>
 <translation id="386548886866354912">Comprimir com <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Descrição</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Mapa Google</translation>
 <translation id="7419631653042041064">Teclado catalão</translation>
 <translation id="7434823369735508263">Teclado inglês (Dvorak)</translation>
-<translation id="7447678886297481665">Os ficheiros nesta pasta são só de leitura. Algumas atividades não são suportadas.</translation>
 <translation id="7460898608667578234">Ucraniano</translation>
 <translation id="7474889694310679759">Teclado canadiano (inglês)</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> encontrada(s)
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ro.xtb b/ui/chromeos/translations/ui_chromeos_strings_ro.xtb
index d0b00de..d2f6540 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ro.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ro.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Tastatură gujarati (Fonetică)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Tastatură S.U.A.</translation>
+<translation id="2534155362429831547">Elemente șterse: <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2542049655219295786">Tabel Google</translation>
 <translation id="2547921442987553570">Adaugă la <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">S.U.A. internațională</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Sârbă</translation>
 <translation id="385051799172605136">Înapoi</translation>
 <translation id="3855472144336161447">Germană Neo 2</translation>
-<translation id="3856075812838139784">Numai în citire</translation>
 <translation id="3858678421048828670">Tastatură italiană</translation>
 <translation id="386548886866354912">Arhivează cu <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Descriere</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Hartă Google</translation>
 <translation id="7419631653042041064">Tastatură catalană</translation>
 <translation id="7434823369735508263">Tastatură UK Dvorak</translation>
-<translation id="7447678886297481665">Fișierele din acest dosar sunt numai în citire. Unele activități nu sunt acceptate.</translation>
 <translation id="7460898608667578234">Ucraineană</translation>
 <translation id="7474889694310679759">Tastatură engleză canadiană</translation>
 <translation id="7489215562877293245">S-au găsit <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ru.xtb b/ui/chromeos/translations/ui_chromeos_strings_ru.xtb
index c6c3b22..726ccca 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ru.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ru.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Раскладка гуджарати (фонетическая)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Американская раскладка</translation>
+<translation id="2534155362429831547">Удалено записей: <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2542049655219295786">Таблица Google</translation>
 <translation id="2547921442987553570">Добавить в расширение "<ph name="EXTENSION_NAME" />"</translation>
 <translation id="255937426064304553">США (международная)</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Сербский</translation>
 <translation id="385051799172605136">Назад</translation>
 <translation id="3855472144336161447">Немецкая (Neo 2)</translation>
-<translation id="3856075812838139784">Только чтение</translation>
 <translation id="3858678421048828670">Итальянская раскладка</translation>
 <translation id="386548886866354912">Создать архив <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Описание</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Карта Google</translation>
 <translation id="7419631653042041064">Каталанская раскладка</translation>
 <translation id="7434823369735508263">Английская раскладка (Дворак)</translation>
-<translation id="7447678886297481665">Файлы в этой папке доступны только для чтения. Некоторые действия не поддерживаются.</translation>
 <translation id="7460898608667578234">Украинский</translation>
 <translation id="7474889694310679759">Канадская раскладка (английский)</translation>
 <translation id="7489215562877293245">Обнаружены файлы (<ph name="FILE_COUNT" />).
diff --git a/ui/chromeos/translations/ui_chromeos_strings_si.xtb b/ui/chromeos/translations/ui_chromeos_strings_si.xtb
index e883a358..07487b94a 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_si.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_si.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">ගුජරාටි යතුරු පුවරුව (ශබ්දිම)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">US යතුරු පුවරුව</translation>
+<translation id="2534155362429831547">අයිතම <ph name="NUMBER_OF_ITEMS" />ක් මකන ලදි</translation>
 <translation id="2542049655219295786">Google වගුව</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" /> වෙත එක් කරන්න</translation>
 <translation id="255937426064304553">US ජාත්‍යන්තර</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">සයිබීරියානු</translation>
 <translation id="385051799172605136">ආපසු</translation>
 <translation id="3855472144336161447">ජර්මානු නියෝ 2</translation>
-<translation id="3856075812838139784">කියවීම පමණයි</translation>
 <translation id="3858678421048828670">ඉතාලි යතුරු පුවරුව</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> සමඟ අසුරන්න</translation>
 <translation id="3866249974567520381">විස්තරය</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Google සිතියම්</translation>
 <translation id="7419631653042041064">කැටලන් යතුරු පුවරුව</translation>
 <translation id="7434823369735508263">එරා-ඩ්වොරක් යතුරු පුවරුව</translation>
-<translation id="7447678886297481665">මෙම ෆෝල්ඩරය තුළ ඇති ගොනු කියවීමට පමණයි. සමහර ක්‍රියාකාරකම්වලට සහය නොදැක්වේ.</translation>
 <translation id="7460898608667578234">යුක්රේන</translation>
 <translation id="7474889694310679759">කනේඩියානු ඉංග්‍රීසි යතුරු පුවරුව</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> හමු විය
diff --git a/ui/chromeos/translations/ui_chromeos_strings_sk.xtb b/ui/chromeos/translations/ui_chromeos_strings_sk.xtb
index 92986d3..a749a78e 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_sk.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_sk.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Gudžarátska klávesnica (fonetický prepis)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">americká klávesnica</translation>
+<translation id="2534155362429831547">Odstránené položky: <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2542049655219295786">Tabuľka Google</translation>
 <translation id="2547921442987553570">Pridať do rozšírenia <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Americká klávesnica s medzinárodným rozložením klávesov</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Srbčina</translation>
 <translation id="385051799172605136">Späť</translation>
 <translation id="3855472144336161447">Nemecká klávesnica Neo 2</translation>
-<translation id="3856075812838139784">Iba na čítanie</translation>
 <translation id="3858678421048828670">talianska klávesnica</translation>
 <translation id="386548886866354912">Komprimovať pomocou rozšírenia <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Popis</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Mapa Google</translation>
 <translation id="7419631653042041064">katalánska klávesnica</translation>
 <translation id="7434823369735508263">americká klávesnica s rozložením klávesov dvorak</translation>
-<translation id="7447678886297481665">Súbory v tomto priečinku sú iba na čítanie. Niektoré aktivity nie sú podporované.</translation>
 <translation id="7460898608667578234">Ukrajinčina</translation>
 <translation id="7474889694310679759">kanadskoanglická klávesnica</translation>
 <translation id="7489215562877293245">Počet nájdených: <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_sl.xtb b/ui/chromeos/translations/ui_chromeos_strings_sl.xtb
index a985c14..d1245e7 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_sl.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_sl.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Tipkovnica za gudžaratščino (fonetična)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Angleška tipkovnica (ZDA)</translation>
+<translation id="2534155362429831547">Št. izbrisanih elementov: <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2542049655219295786">Googlova tabela</translation>
 <translation id="2547921442987553570">Dodajanje za: <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Združene države – mednarodna</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">srbščina</translation>
 <translation id="385051799172605136">Nazaj</translation>
 <translation id="3855472144336161447">nemščina (Neo 2)</translation>
-<translation id="3856075812838139784">Samo za branje</translation>
 <translation id="3858678421048828670">Italijanska tipkovnica</translation>
 <translation id="386548886866354912">Stiskanje z: <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Opis</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Googlov zemljevid</translation>
 <translation id="7419631653042041064">Katalonska tipkovnica</translation>
 <translation id="7434823369735508263">Angleška tipkovnica Dvorak (Velika Britanija)</translation>
-<translation id="7447678886297481665">Datoteke v tej mapi so samo za branje. Nekatere dejavnosti niso podprte.</translation>
 <translation id="7460898608667578234">ukrajinščina</translation>
 <translation id="7474889694310679759">Angleška tipkovnica (Kanada)</translation>
 <translation id="7489215562877293245">Št. najdenih: <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_sq.xtb b/ui/chromeos/translations/ui_chromeos_strings_sq.xtb
index 7968fdb3..42af9d3 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_sq.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_sq.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Tastiera guxharati (fonetike)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Tastiera amerikane</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> artikuj të fshirë</translation>
 <translation id="2542049655219295786">Tabela e Google</translation>
 <translation id="2547921442987553570">Shto te <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Amerikane ndërkombëtare</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serbisht</translation>
 <translation id="385051799172605136">Prapa</translation>
 <translation id="3855472144336161447">Gjermanisht Neo 2</translation>
-<translation id="3856075812838139784">Vetëm për lexim</translation>
 <translation id="3858678421048828670">Tastierë italiane</translation>
 <translation id="386548886866354912">Paketë me <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Përshkrimi</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Hartë e Google</translation>
 <translation id="7419631653042041064">Tastierë në katalanisht</translation>
 <translation id="7434823369735508263">Tastierë britanike Dvorak</translation>
-<translation id="7447678886297481665">Skedarët në këtë dosje janë vetëm për lexim. Disa aktivitete nuk mbështeten.</translation>
 <translation id="7460898608667578234">Ukrainisht</translation>
 <translation id="7474889694310679759">Tastierë në anglishte kanadeze</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> të gjetura
diff --git a/ui/chromeos/translations/ui_chromeos_strings_sr-Latn.xtb b/ui/chromeos/translations/ui_chromeos_strings_sr-Latn.xtb
index 5f09f294..18eafc2a5 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_sr-Latn.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_sr-Latn.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Gudžarati tastatura (fonetska)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Jezik tastature: engleski (SAD)</translation>
+<translation id="2534155362429831547">Izbrisanih stavki: <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2542049655219295786">Google tabela</translation>
 <translation id="2547921442987553570">Dodaj u <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">međunarodna američka</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">srpski</translation>
 <translation id="385051799172605136">Nazad</translation>
 <translation id="3855472144336161447">nemačka Neo 2</translation>
-<translation id="3856075812838139784">Samo za čitanje</translation>
 <translation id="3858678421048828670">Jezik tastature: italijanski</translation>
 <translation id="386548886866354912">Spakuj pomoću dodatka <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Opis</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google mapa</translation>
 <translation id="7419631653042041064">Jezik tastature: katalonski</translation>
 <translation id="7434823369735508263">Jezik tastature: engleski (UK dvorak)</translation>
-<translation id="7447678886297481665">Datoteke u ovom direktorijumu su samo za čitanje. Neke aktivnosti nisu podržane.</translation>
 <translation id="7460898608667578234">ukrajinski</translation>
 <translation id="7474889694310679759">Jezik tastature: engleski (Kanada)</translation>
 <translation id="7489215562877293245">Pronađene su datoteke (<ph name="FILE_COUNT" />)
diff --git a/ui/chromeos/translations/ui_chromeos_strings_sr.xtb b/ui/chromeos/translations/ui_chromeos_strings_sr.xtb
index c799b863..98e7a87 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_sr.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_sr.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Гуџарати тастатура (фонетска)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Језик тастатуре: енглески (САД)</translation>
+<translation id="2534155362429831547">Избрисаних ставки: <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2542049655219295786">Google табела</translation>
 <translation id="2547921442987553570">Додај у <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">међународна америчка</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">српски</translation>
 <translation id="385051799172605136">Назад</translation>
 <translation id="3855472144336161447">немачка Neo 2</translation>
-<translation id="3856075812838139784">Само за читање</translation>
 <translation id="3858678421048828670">Језик тастатуре: италијански</translation>
 <translation id="386548886866354912">Спакуј помоћу додатка <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Опис</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google мапа</translation>
 <translation id="7419631653042041064">Језик тастатуре: каталонски</translation>
 <translation id="7434823369735508263">Језик тастатуре: енглески (УК дворак)</translation>
-<translation id="7447678886297481665">Датотеке у овом директоријуму су само за читање. Неке активности нису подржане.</translation>
 <translation id="7460898608667578234">украјински</translation>
 <translation id="7474889694310679759">Језик тастатуре: енглески (Канада)</translation>
 <translation id="7489215562877293245">Пронађене су датотеке (<ph name="FILE_COUNT" />)
diff --git a/ui/chromeos/translations/ui_chromeos_strings_sv.xtb b/ui/chromeos/translations/ui_chromeos_strings_sv.xtb
index 7c642d9..1f85858 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_sv.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_sv.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Tangentbord för gujarati (fonetiskt)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">USA-tangentbord</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> objekt har tagits bort</translation>
 <translation id="2542049655219295786">Tabell i Google Dokument</translation>
 <translation id="2547921442987553570">Lägg till i <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">USA (internationell)</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">serbiska</translation>
 <translation id="385051799172605136">Föregående</translation>
 <translation id="3855472144336161447">Tyska (neo 2)</translation>
-<translation id="3856075812838139784">Skrivskyddat</translation>
 <translation id="3858678421048828670">Italienskt tangentbord</translation>
 <translation id="386548886866354912">Packa med <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Beskrivning</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google-karta</translation>
 <translation id="7419631653042041064">Katalanskt tangentbord</translation>
 <translation id="7434823369735508263">Dvorak-tangentbord för USA</translation>
-<translation id="7447678886297481665">Filer i den här mappen är skrivskyddade. Vissa aktiviteter stöds inte.</translation>
 <translation id="7460898608667578234">ukrainska</translation>
 <translation id="7474889694310679759">Kanadensiskt-engelskt tangentbord</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> hittades
diff --git a/ui/chromeos/translations/ui_chromeos_strings_sw.xtb b/ui/chromeos/translations/ui_chromeos_strings_sw.xtb
index 600c2ce..fd38524 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_sw.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_sw.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Kibodi ya Gujarati (Fonetiki)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Kibodi ya Kimarekani</translation>
+<translation id="2534155362429831547">Umefuta vipengee <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2542049655219295786">Jedwali la Google</translation>
 <translation id="2547921442987553570">Ongeza kwenye <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Kiingereza cha Marekani cha Kimataifa</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Kiserbia</translation>
 <translation id="385051799172605136">Rudi nyuma</translation>
 <translation id="3855472144336161447">Kijerumani Neo 2</translation>
-<translation id="3856075812838139784">Soma tu</translation>
 <translation id="3858678421048828670">Kibodi ya Kiitaliano</translation>
 <translation id="386548886866354912">Fungasha kwa <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Maelezo</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Ramani ya Google</translation>
 <translation id="7419631653042041064">Kibodi ya Kikatalani</translation>
 <translation id="7434823369735508263">Kibodi ya Dvorak, Uingereza</translation>
-<translation id="7447678886297481665">Faili kwenye folda hizi ni za kusoma tu. Baadhi ya shughuli hazitumiki.</translation>
 <translation id="7460898608667578234">Kiukrania</translation>
 <translation id="7474889694310679759">Kibodi ya Kiingereza cha Kanada</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> imepatikana 
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ta.xtb b/ui/chromeos/translations/ui_chromeos_strings_ta.xtb
index bc5f6ea5..da214073 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ta.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ta.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">குஜராத்தி விசைப்பலகை (ஒலிப்புமுறை)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">யுஎஸ் விசைப்பலகை</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> வரலாற்று உள்ளடக்கங்கள் நீக்கப்பட்டன</translation>
 <translation id="2542049655219295786">Google அட்டவணை</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" /> இல் சேர்</translation>
 <translation id="255937426064304553">யு.எஸ். இன்டர்நேஷனல்</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">செர்பியன்</translation>
 <translation id="385051799172605136">திரும்பு</translation>
 <translation id="3855472144336161447">ஜெர்மன் நியோ 2</translation>
-<translation id="3856075812838139784">படிக்க மட்டும்</translation>
 <translation id="3858678421048828670">இத்தாலியன் விசைப்பலகை</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> மூலம் தொகுப்பாக்கு</translation>
 <translation id="3866249974567520381">விவரம்</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google Maps</translation>
 <translation id="7419631653042041064">கேட்டலன் விசைப்பலகை</translation>
 <translation id="7434823369735508263">யுகே துவோராக் விசைப்பலகை</translation>
-<translation id="7447678886297481665">இந்தக் கோப்புறையில் உள்ள கோப்புகளைப் படிக்க மட்டுமே முடியும். சில செயல்பாடுகள் ஆதரிக்கப்படாது.</translation>
 <translation id="7460898608667578234">உக்ரைனியன்</translation>
 <translation id="7474889694310679759">கனேடியன் ஆங்கில விசைப்பலகை</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> உள்ளது
diff --git a/ui/chromeos/translations/ui_chromeos_strings_te.xtb b/ui/chromeos/translations/ui_chromeos_strings_te.xtb
index 9143e3e..4d4ad6d 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_te.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_te.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">గుజరాతీ కీబోర్డ్ (ఫొనెటిక్)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">US కీబోర్డ్</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> అంశాలు తొలగించబడ్డాయి</translation>
 <translation id="2542049655219295786">Google పట్టిక</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" />కి జోడించండి</translation>
 <translation id="255937426064304553">యుఎస్ అంతర్జాతీయం</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">సెర్బియన్</translation>
 <translation id="385051799172605136">వెనుకకు</translation>
 <translation id="3855472144336161447">జర్మన్ నియో 2</translation>
-<translation id="3856075812838139784">చదవడానికి మాత్రమే</translation>
 <translation id="3858678421048828670">ఇటాలియన్ కీబోర్డ్</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> గల ప్యాక్</translation>
 <translation id="3866249974567520381">వివరణ</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google మ్యాప్</translation>
 <translation id="7419631653042041064">కెటలాన్ కీబోర్డ్</translation>
 <translation id="7434823369735508263">UK డ్వొరక్ కీబోర్డ్</translation>
-<translation id="7447678886297481665">ఈ ఫోల్డర్‌లో ఉన్న ఫైల్‌లు చదవడానికి మాత్రమే. కొన్ని యాక్టివిటీలకు మద్దతు లేదు.</translation>
 <translation id="7460898608667578234">ఉక్రెయినియన్</translation>
 <translation id="7474889694310679759">కెనెడియన్ ఇంగ్లీష్ కీబోర్డ్</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> కనుగొనబడ్డాయి
diff --git a/ui/chromeos/translations/ui_chromeos_strings_th.xtb b/ui/chromeos/translations/ui_chromeos_strings_th.xtb
index 510372f..1e5e5a9 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_th.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_th.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">แป้นพิมพ์ภาษาคุชราต (คำที่ใช้ออกเสียง)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">แป้นพิมพ์ภาษาอังกฤษสหรัฐอเมริกา</translation>
+<translation id="2534155362429831547">ลบแล้ว <ph name="NUMBER_OF_ITEMS" /> รายการ</translation>
 <translation id="2542049655219295786">ตารางของ Google</translation>
 <translation id="2547921442987553570">เพิ่มไปยัง <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">สหรัฐอเมริกาสากล</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">เซอร์เบีย</translation>
 <translation id="385051799172605136">กลับ</translation>
 <translation id="3855472144336161447">Neo 2 แบบเยอรมัน</translation>
-<translation id="3856075812838139784">อ่านอย่างเดียว</translation>
 <translation id="3858678421048828670">แป้นพิมพ์ภาษาอิตาลี</translation>
 <translation id="386548886866354912">แพ็กด้วย <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">คำอธิบาย</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">แผนที่ Google</translation>
 <translation id="7419631653042041064">แป้นพิมพ์ภาษาคาตาลัน</translation>
 <translation id="7434823369735508263">แป้นพิมพ์ดีโวรักสหราชอาณาจักร</translation>
-<translation id="7447678886297481665">ไฟล์ในโฟลเดอร์นี้เป็นแบบอ่านอย่างเดียว โดยระบบจะไม่รองรับบางกิจกรรม</translation>
 <translation id="7460898608667578234">ยูเครน</translation>
 <translation id="7474889694310679759">แป้นพิมพ์ภาษาอังกฤษแคนาดา</translation>
 <translation id="7489215562877293245">พบ <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_tr.xtb b/ui/chromeos/translations/ui_chromeos_strings_tr.xtb
index f54154c3..f4dffb5 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_tr.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_tr.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Guceratça klavye (Fonetik)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">ABD klavye</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> öğe silindi</translation>
 <translation id="2542049655219295786">Google tablosu</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" /> uzantısına ekle</translation>
 <translation id="255937426064304553">ABD uluslararası</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Sırpça</translation>
 <translation id="385051799172605136">Geri</translation>
 <translation id="3855472144336161447">Alman Neo 2</translation>
-<translation id="3856075812838139784">Salt okunur</translation>
 <translation id="3858678421048828670">İtalyanca klavye</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> uzantısıyla paketle</translation>
 <translation id="3866249974567520381">Açıklama</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google harita</translation>
 <translation id="7419631653042041064">Katalanca klavye</translation>
 <translation id="7434823369735508263">İngiltere Dvorak klavye</translation>
-<translation id="7447678886297481665">Bu klasördeki dosyalar salt okunurdur. Bazı işlemler desteklenmez.</translation>
 <translation id="7460898608667578234">Ukraynaca</translation>
 <translation id="7474889694310679759">İngilizce (Kanada) klavye</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> bulundu
diff --git a/ui/chromeos/translations/ui_chromeos_strings_uk.xtb b/ui/chromeos/translations/ui_chromeos_strings_uk.xtb
index 4d571e2..f3b9eb7 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_uk.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_uk.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Клавіатура гуджараті (фонетична)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Американська розкладка</translation>
+<translation id="2534155362429831547">Видалено елементів: <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2542049655219295786">Таблиця Google</translation>
 <translation id="2547921442987553570">Додати в <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Міжнародна (США)</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Сербська</translation>
 <translation id="385051799172605136">Назад</translation>
 <translation id="3855472144336161447">Німецька (Neo 2)</translation>
-<translation id="3856075812838139784">Лише читання</translation>
 <translation id="3858678421048828670">Італійська розкладка</translation>
 <translation id="386548886866354912">Архівувати за допомогою розширення "<ph name="EXTENSION_NAME" />"</translation>
 <translation id="3866249974567520381">Опис</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Карта Google</translation>
 <translation id="7419631653042041064">Каталонська розкладка</translation>
 <translation id="7434823369735508263">Розкладка Дворака (Велика Британія)</translation>
-<translation id="7447678886297481665">Файли в цій папці можна лише переглядати. Деякі дії не підтримуються.</translation>
 <translation id="7460898608667578234">Українська</translation>
 <translation id="7474889694310679759">Англійська розкладка (Канада)</translation>
 <translation id="7489215562877293245">Знайдено: <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ur.xtb b/ui/chromeos/translations/ui_chromeos_strings_ur.xtb
index 6ed32b1..8314021 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ur.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ur.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">گجراتی کی بورڈ (فونیٹک)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">امریکی کی بورڈ</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> آئٹمز حذف ہو گئے</translation>
 <translation id="2542049655219295786">‏Google ٹیبل</translation>
 <translation id="2547921442987553570"><ph name="EXTENSION_NAME" /> میں شامل کریں</translation>
 <translation id="255937426064304553">امریکی بین الاقوامی</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">صربی</translation>
 <translation id="385051799172605136">پیچھے</translation>
 <translation id="3855472144336161447">جرمن نیو 2</translation>
-<translation id="3856075812838139784">صرف پڑھنے کیلئے</translation>
 <translation id="3858678421048828670">اطالوی کی بورڈ</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> کے ساتھ پیک کریں</translation>
 <translation id="3866249974567520381">تفصیل</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">‏Google نقشہ</translation>
 <translation id="7419631653042041064">کیٹلان کی بورڈ</translation>
 <translation id="7434823369735508263">‏UK ڈوراک کی بورڈ</translation>
-<translation id="7447678886297481665">اس فولڈر میں موجود فائلز صرف پڑھنے کے لیے ہیں۔ کچھ سرگرمیاں تعاون یافتہ نہیں ہیں۔</translation>
 <translation id="7460898608667578234">يُوکرينی</translation>
 <translation id="7474889694310679759">کینیڈین انگریزی کی بورڈ</translation>
 <translation id="7489215562877293245">‏<ph name="FILE_COUNT" /> ملیں
diff --git a/ui/chromeos/translations/ui_chromeos_strings_uz.xtb b/ui/chromeos/translations/ui_chromeos_strings_uz.xtb
index abf8b42..2b4370a 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_uz.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_uz.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Gujarot klaviaturasi (fonetik)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">AQSH klaviaturasi</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> ta element oʻchirib tashlandi</translation>
 <translation id="2542049655219295786">Google jadvali</translation>
 <translation id="2547921442987553570">“<ph name="EXTENSION_NAME" />” kengaytmasiga qo‘shish</translation>
 <translation id="255937426064304553">AQSH (xalqaro)</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Serb tili</translation>
 <translation id="385051799172605136">Orqaga</translation>
 <translation id="3855472144336161447">Nemis Neo 2</translation>
-<translation id="3856075812838139784">Faqat o‘qish</translation>
 <translation id="3858678421048828670">Italyancha klaviatura</translation>
 <translation id="386548886866354912"><ph name="EXTENSION_NAME" /> arxiv yaratish</translation>
 <translation id="3866249974567520381">Tavsif</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Google xaritasi</translation>
 <translation id="7419631653042041064">Katalan klaviaturasi</translation>
 <translation id="7434823369735508263">Ingliz Dvorak klaviaturasi</translation>
-<translation id="7447678886297481665">Bu jilddagi fayllarni faqat oʻqish mumkin. Ayrim amallar ishlamaydi.</translation>
 <translation id="7460898608667578234">Ukrayin tili</translation>
 <translation id="7474889694310679759">Kanada (Ingliz) klaviaturasi</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> topildi
diff --git a/ui/chromeos/translations/ui_chromeos_strings_vi.xtb b/ui/chromeos/translations/ui_chromeos_strings_vi.xtb
index 1c01053f..480157d 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_vi.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_vi.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Bàn phím tiếng Gujarat (Ngữ âm)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">Bàn phím Anh-Mỹ</translation>
+<translation id="2534155362429831547">Đã xóa <ph name="NUMBER_OF_ITEMS" /> mục</translation>
 <translation id="2542049655219295786">Bảng Google</translation>
 <translation id="2547921442987553570">Thêm vào <ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">Bàn phím quốc tế Hoa Kỳ</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Tiếng Serbia</translation>
 <translation id="385051799172605136">Quay lại</translation>
 <translation id="3855472144336161447">Neo 2 tiếng Đức</translation>
-<translation id="3856075812838139784">Chỉ đọc</translation>
 <translation id="3858678421048828670">Bàn phím tiếng Ý</translation>
 <translation id="386548886866354912">Gói đi kèm <ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Mô tả</translation>
@@ -310,7 +310,7 @@
 <translation id="4477219268485577442">Ngữ âm tiếng Bungary</translation>
 <translation id="4479812471636796472">Bàn phím Dvorak Hoa Kỳ</translation>
 <translation id="4522570452068850558">Chi tiết</translation>
-<translation id="4527800702232535228">Thư mục này được chia sẻ với ứng dụng Parallels Desktop</translation>
+<translation id="4527800702232535228">Thư mục này được chia sẻ với Parallels Desktop</translation>
 <translation id="4552678318981539154">Mua thêm dung lượng lưu trữ</translation>
 <translation id="4559767610552730302">Hiệu ứng Bokeh</translation>
 <translation id="4572815280350369984">Tệp <ph name="FILE_TYPE" /></translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Bản đồ Google</translation>
 <translation id="7419631653042041064">Bàn phím tiếng Catalan</translation>
 <translation id="7434823369735508263">Bàn phím Dvorak Vương quốc Anh</translation>
-<translation id="7447678886297481665">Các tệp trong thư mục này đang ở chế độ chỉ đọc. Vì thế, bạn sẽ không thực hiện được một số hành động.</translation>
 <translation id="7460898608667578234">Tiếng Ukraina</translation>
 <translation id="7474889694310679759">Bàn phím tiếng Anh ở Canada</translation>
 <translation id="7489215562877293245">Đã tìm thấy <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_zh-CN.xtb b/ui/chromeos/translations/ui_chromeos_strings_zh-CN.xtb
index 6b2211a..df9a80a5 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_zh-CN.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_zh-CN.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">古吉拉特语键盘(注音)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">英语(美国)键盘</translation>
+<translation id="2534155362429831547">删除了 <ph name="NUMBER_OF_ITEMS" /> 项</translation>
 <translation id="2542049655219295786">Google 表格</translation>
 <translation id="2547921442987553570">添加到“<ph name="EXTENSION_NAME" />”</translation>
 <translation id="255937426064304553">美国英语(国际)</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">塞尔维亚语</translation>
 <translation id="385051799172605136">返回</translation>
 <translation id="3855472144336161447">德语Neo 2</translation>
-<translation id="3856075812838139784">只读</translation>
 <translation id="3858678421048828670">意大利语键盘</translation>
 <translation id="386548886866354912">使用“<ph name="EXTENSION_NAME" />”打包</translation>
 <translation id="3866249974567520381">说明</translation>
@@ -596,7 +596,6 @@
 <translation id="7417705661718309329">Google 地图</translation>
 <translation id="7419631653042041064">加泰罗尼亚语键盘</translation>
 <translation id="7434823369735508263">英语(英国)德沃夏克键盘</translation>
-<translation id="7447678886297481665">此文件夹中的文件都是只读文件,所以不支持某些活动。</translation>
 <translation id="7460898608667578234">乌克兰语</translation>
 <translation id="7474889694310679759">英语(加拿大)键盘</translation>
 <translation id="7489215562877293245">找到了 <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_zh-HK.xtb b/ui/chromeos/translations/ui_chromeos_strings_zh-HK.xtb
index f50ec2f..f2d5ce2 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_zh-HK.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_zh-HK.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">古吉拉特文鍵盤 (拼音)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">美式鍵盤</translation>
+<translation id="2534155362429831547">已刪除 <ph name="NUMBER_OF_ITEMS" /> 個項目</translation>
 <translation id="2542049655219295786">Google 表格</translation>
 <translation id="2547921442987553570">新增至「<ph name="EXTENSION_NAME" />」</translation>
 <translation id="255937426064304553">美國國際鍵盤</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">塞爾維亞語</translation>
 <translation id="385051799172605136">返回</translation>
 <translation id="3855472144336161447">德文 Neo 2 鍵盤</translation>
-<translation id="3856075812838139784">唯讀</translation>
 <translation id="3858678421048828670">義大利文鍵盤</translation>
 <translation id="386548886866354912">使用「<ph name="EXTENSION_NAME" />」壓縮</translation>
 <translation id="3866249974567520381">描述</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google 地圖</translation>
 <translation id="7419631653042041064">卡達隆尼亞文鍵盤</translation>
 <translation id="7434823369735508263">英式 Dvorak 鍵盤</translation>
-<translation id="7447678886297481665">此資料夾中的檔案是唯讀檔案,因此不支援部份活動。</translation>
 <translation id="7460898608667578234">烏克蘭文</translation>
 <translation id="7474889694310679759">加拿大英文鍵盤</translation>
 <translation id="7489215562877293245">已找到 <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_zh-TW.xtb b/ui/chromeos/translations/ui_chromeos_strings_zh-TW.xtb
index 4190d50..8a7a83e 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_zh-TW.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_zh-TW.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">古吉拉特文鍵盤 (拼音)</translation>
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2529133382850673012">美式鍵盤</translation>
+<translation id="2534155362429831547">已刪除 <ph name="NUMBER_OF_ITEMS" /> 個項目</translation>
 <translation id="2542049655219295786">Google 表格</translation>
 <translation id="2547921442987553570">加入「<ph name="EXTENSION_NAME" />」中</translation>
 <translation id="255937426064304553">美國國際</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">塞爾維亞文</translation>
 <translation id="385051799172605136">返回</translation>
 <translation id="3855472144336161447">德文 Neo 2</translation>
-<translation id="3856075812838139784">唯讀</translation>
 <translation id="3858678421048828670">義大利文鍵盤</translation>
 <translation id="386548886866354912">使用「<ph name="EXTENSION_NAME" />」封裝</translation>
 <translation id="3866249974567520381">說明</translation>
@@ -601,7 +601,6 @@
 <translation id="7417705661718309329">Google 地圖</translation>
 <translation id="7419631653042041064">卡達隆尼亞文鍵盤</translation>
 <translation id="7434823369735508263">英式 Dvorak 鍵盤</translation>
-<translation id="7447678886297481665">這個資料夾中的檔案是唯讀檔案,因此不支援部分活動。</translation>
 <translation id="7460898608667578234">烏克蘭語</translation>
 <translation id="7474889694310679759">加拿大英文鍵盤</translation>
 <translation id="7489215562877293245">找到 <ph name="FILE_COUNT" />
diff --git a/ui/chromeos/translations/ui_chromeos_strings_zu.xtb b/ui/chromeos/translations/ui_chromeos_strings_zu.xtb
index a7e3e9e..458a94134 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_zu.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_zu.xtb
@@ -142,6 +142,7 @@
 <translation id="2494837236724268445">Ikhibhodi ye-Gujarati (Ifonetiki)</translation>
 <translation id="2515586267016047495">I-Alt</translation>
 <translation id="2529133382850673012">Ikhibhodi ye-US</translation>
+<translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> izinto ezisusiwe</translation>
 <translation id="2542049655219295786">Ithebula le-Google</translation>
 <translation id="2547921442987553570">Engeza ku-<ph name="EXTENSION_NAME" /></translation>
 <translation id="255937426064304553">I-US yamazwe ngamazwe</translation>
@@ -267,7 +268,6 @@
 <translation id="383652340667548381">Isi-Serbian</translation>
 <translation id="385051799172605136">Emuva</translation>
 <translation id="3855472144336161447">Isi-German Neo 2</translation>
-<translation id="3856075812838139784">Funda kuphela</translation>
 <translation id="3858678421048828670">Ikhibhodi ye-Italian</translation>
 <translation id="386548886866354912">Pakisha nge-<ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Incazelo</translation>
@@ -600,7 +600,6 @@
 <translation id="7417705661718309329">Imephu ye-Google</translation>
 <translation id="7419631653042041064">Ikhibhodi ye-Catalan</translation>
 <translation id="7434823369735508263">Ikhibhodi ye-UK Dvorak</translation>
-<translation id="7447678886297481665">Amafayela kuleli folda afundwa kuphela. Eminye imisebenzi ayisekelwa.</translation>
 <translation id="7460898608667578234">Isi-Ukrainian</translation>
 <translation id="7474889694310679759">Ikhbhodi ye-Canadian English</translation>
 <translation id="7489215562877293245"><ph name="FILE_COUNT" /> itholakele
diff --git a/ui/events/event.h b/ui/events/event.h
index 7ab7b05..4224c1b 100644
--- a/ui/events/event.h
+++ b/ui/events/event.h
@@ -567,7 +567,10 @@
   // Raw mouse movement value reported from mouse hardware. The value of this is
   // platform dependent and may change depending upon the hardware connected to
   // the device. This field is only set if the flag EF_UNADJUSTED_MOUSE is
-  // present.
+  // present (which is the case on windows platforms, and CrOS if the
+  // kEnableOrdinalMotion flag is set).
+  //
+  // TODO(b/171249701): always enable on CrOS.
   gfx::Vector2dF movement_;
 
   // The most recent user-generated MouseEvent, used to detect double clicks.
diff --git a/ui/events/ozone/evdev/event_factory_evdev.cc b/ui/events/ozone/evdev/event_factory_evdev.cc
index 68c26983c..bbaa5a7 100644
--- a/ui/events/ozone/evdev/event_factory_evdev.cc
+++ b/ui/events/ozone/evdev/event_factory_evdev.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/feature_list.h"
 #include "base/single_thread_task_runner.h"
 #include "base/task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -23,6 +24,7 @@
 #include "ui/events/ozone/evdev/input_device_factory_evdev_proxy.h"
 #include "ui/events/ozone/evdev/input_injector_evdev.h"
 #include "ui/events/ozone/evdev/touch_evdev_types.h"
+#include "ui/events/ozone/features.h"
 #include "ui/events/ozone/gamepad/gamepad_provider_ozone.h"
 
 namespace ui {
@@ -198,8 +200,7 @@
   DCHECK(device_manager_);
 }
 
-EventFactoryEvdev::~EventFactoryEvdev() {
-}
+EventFactoryEvdev::~EventFactoryEvdev() = default;
 
 void EventFactoryEvdev::Init() {
   DCHECK(!initialized_);
@@ -244,7 +245,8 @@
   event.set_location_f(location);
   event.set_root_location_f(location);
   event.set_source_device_id(params.device_id);
-  if (params.ordinal_delta.has_value()) {
+  if (params.ordinal_delta.has_value() &&
+      base::FeatureList::IsEnabled(kEnableOrdinalMotion)) {
     ui::MouseEvent::DispatcherApi(&event).set_movement(
         params.ordinal_delta.value());
   }
diff --git a/ui/events/ozone/evdev/event_factory_evdev_unittest.cc b/ui/events/ozone/evdev/event_factory_evdev_unittest.cc
index cc78895..ac57d231 100644
--- a/ui/events/ozone/evdev/event_factory_evdev_unittest.cc
+++ b/ui/events/ozone/evdev/event_factory_evdev_unittest.cc
@@ -5,12 +5,14 @@
 #include "ui/events/ozone/evdev/event_factory_evdev.h"
 
 #include "base/optional.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/events/ozone/device/device_manager.h"
 #include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h"
+#include "ui/events/ozone/features.h"
 #include "ui/events/platform/platform_event_observer.h"
 #include "ui/events/platform_event.h"
 #include "ui/gfx/geometry/vector2d_f.h"
@@ -35,11 +37,13 @@
 class EventFactoryEvdevTest : public testing::Test {
  protected:
   EventFactoryEvdevTest() : event_factory_(nullptr, &device_manager_, nullptr) {
+    scoped_feature_list_.InitAndEnableFeature(kEnableOrdinalMotion);
     event_factory_.Init();
     event_factory_.AddPlatformEventObserver(&event_observer_);
   }
 
   base::test::SingleThreadTaskEnvironment task_environment_;
+  base::test::ScopedFeatureList scoped_feature_list_;
   testing::StrictMock<MockDeviceManager> device_manager_;
   testing::NiceMock<MockPlatformEventObserver> event_observer_;
   EventFactoryEvdev event_factory_;
diff --git a/ui/events/ozone/features.cc b/ui/events/ozone/features.cc
index b7ca1671..122674db 100644
--- a/ui/events/ozone/features.cc
+++ b/ui/events/ozone/features.cc
@@ -15,6 +15,10 @@
 const base::Feature kEnableNeuralStylusReportFilter{
     "EnableNeuralStylusReportFilter", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// TODO(b/171249701): Remove this flag when we can support this in all cases.
+const base::Feature kEnableOrdinalMotion{"EnableOrdinalMotion",
+                                         base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kEnablePalmOnMaxTouchMajor{
     "EnablePalmOnMaxTouchMajor", base::FEATURE_ENABLED_BY_DEFAULT};
 
diff --git a/ui/events/ozone/features.h b/ui/events/ozone/features.h
index 8237ff4..ab96e2b 100644
--- a/ui/events/ozone/features.h
+++ b/ui/events/ozone/features.h
@@ -20,6 +20,9 @@
 extern const base::Feature kEnableNeuralStylusReportFilter;
 
 COMPONENT_EXPORT(EVENTS_OZONE)
+extern const base::Feature kEnableOrdinalMotion;
+
+COMPONENT_EXPORT(EVENTS_OZONE)
 extern const base::Feature kEnablePalmOnMaxTouchMajor;
 
 COMPONENT_EXPORT(EVENTS_OZONE)
diff --git a/ui/events/x/events_x_utils.cc b/ui/events/x/events_x_utils.cc
index 3010db5..856dfb22 100644
--- a/ui/events/x/events_x_utils.cc
+++ b/ui/events/x/events_x_utils.cc
@@ -376,7 +376,7 @@
 
 // This is ported from libxi's FP1616toDBL in XExtInt.c
 double Fp1616ToDouble(x11::Input::Fp1616 x) {
-  auto x32 = static_cast<uint32_t>(x);
+  auto x32 = static_cast<int32_t>(x);
   return x32 * 1.0 / (1 << 16);
 }
 
diff --git a/ui/file_manager/externs/volume_info.js b/ui/file_manager/externs/volume_info.js
index a4fd657..851593cc 100644
--- a/ui/file_manager/externs/volume_info.js
+++ b/ui/file_manager/externs/volume_info.js
@@ -128,6 +128,13 @@
      *     on "Downloads" VolumeInfo.
      */
     this.prefixEntry;
+
+    /**
+     * The path on the remote host where this volume is mounted, for crostini
+     * this is the user's homedir (/home/<username>).
+     * @type {(string|undefined)}
+     */
+    this.remoteMountPath;
   }
 
   /**
diff --git a/ui/file_manager/file_manager/background/js/file_operation_manager.js b/ui/file_manager/file_manager/background/js/file_operation_manager.js
index 02ad1e2..1ffb6e7 100644
--- a/ui/file_manager/file_manager/background/js/file_operation_manager.js
+++ b/ui/file_manager/file_manager/background/js/file_operation_manager.js
@@ -522,7 +522,14 @@
    * @param {Array<!fileOperationUtil.TrashItem>} trashItems The trash items.
    */
   restoreDeleted(trashItems) {
-    // TODO(crbug.com/953310): to be implemented in crrev.com/c/2469340.
+    const volumeManager = assert(this.volumeManager_);
+    while (trashItems.length) {
+      this.trash_
+          .restore(
+              volumeManager,
+              /** @type {!TrashItem} */ (trashItems.pop()))
+          .catch(e => console.error('Error restoring deleted file', e));
+    }
   }
 
   /**
diff --git a/ui/file_manager/file_manager/background/js/mock_volume_manager.js b/ui/file_manager/file_manager/background/js/mock_volume_manager.js
index 87da263..71b6a064 100644
--- a/ui/file_manager/file_manager/background/js/mock_volume_manager.js
+++ b/ui/file_manager/file_manager/background/js/mock_volume_manager.js
@@ -80,12 +80,13 @@
    * @param {string} volumeId
    * @param {string} label
    * @param {string=} providerId
+   * @param {string=} remoteMountPath
    *
    * @return {!VolumeInfo}
    */
-  createVolumeInfo(type, volumeId, label, providerId) {
+  createVolumeInfo(type, volumeId, label, providerId, remoteMountPath) {
     const volumeInfo = MockVolumeManager.createMockVolumeInfo(
-        type, volumeId, label, undefined, providerId);
+        type, volumeId, label, undefined, providerId, remoteMountPath);
     this.volumeInfoList.add(volumeInfo);
     return volumeInfo;
   }
@@ -165,9 +166,11 @@
    * @param {string=} label Label.
    * @param {string=} devicePath Device path.
    * @param {string=} providerId Provider id.
+   * @param {string=} remoteMountPath Remote mount path.
    * @return {!VolumeInfo} Created mock VolumeInfo.
    */
-  static createMockVolumeInfo(type, volumeId, label, devicePath, providerId) {
+  static createMockVolumeInfo(
+      type, volumeId, label, devicePath, providerId, remoteMountPath) {
     const fileSystem = new MockFileSystem(volumeId, 'filesystem:' + volumeId);
 
     // If there's no label set it to volumeId to make it shorter to write
@@ -188,7 +191,8 @@
         VolumeManagerCommon.Source.NETWORK,         // source
         VolumeManagerCommon.FileSystemType.UNKNOWN,  // diskFileSystemType
         {},                                          // iconSet
-        '');                                         // driveLabel
+        '',                                          // driveLabel
+        remoteMountPath);                            // remoteMountPath
 
     return volumeInfo;
   }
diff --git a/ui/file_manager/file_manager/background/js/trash.js b/ui/file_manager/file_manager/background/js/trash.js
index 040e5bc..a776f8a 100644
--- a/ui/file_manager/file_manager/background/js/trash.js
+++ b/ui/file_manager/file_manager/background/js/trash.js
@@ -22,37 +22,87 @@
 }
 
 /**
+ * Configuration for where Trash is stored in a volume.
+ */
+class TrashConfig {
+  /**
+   * @param {VolumeManagerCommon.RootType} rootType
+   * @param {string} topDir Top directory of volume. Must end with a slash to
+   *     make comparisons simpler.
+   * @param {string} trashDir Trash directory. Must end with a slash to make
+   *     comparisons simpler.
+   * @param {boolean=} prefixPathWithRemoteMount Optional, if true, 'Path=' in
+   *     *.trashinfo is prefixed with the volume.remoteMountPath. For crostini,
+   *     this is the user's homedir (/home/<username>).
+   */
+  constructor(rootType, topDir, trashDir, prefixPathWithRemoteMount = false) {
+    this.rootType = rootType;
+    this.topDir = topDir;
+    this.trashDir = trashDir;
+    this.prefixPathWithRemoteMount = prefixPathWithRemoteMount;
+    this.pathPrefix = '';
+  }
+}
+
+/**
+ * Result from calling Trash.removeFileOrDirectory().
+ */
+class TrashItem {
+  /**
+   * @param {string} name Name of the file deleted.
+   * @param {!Entry} filesEntry Trash files entry.
+   * @param {!FileEntry} infoEntry Trash info entry.
+   * @param {string=} pathPrefix Optional prefix for 'Path=' in *.trashinfo. For
+   *     crostini, this is the user's homedir (/home/<username>).
+   */
+  constructor(name, filesEntry, infoEntry, pathPrefix = '') {
+    this.name = name;
+    this.filesEntry = filesEntry;
+    this.infoEntry = infoEntry;
+    this.pathPrefix = pathPrefix;
+  }
+}
+
+/**
  * Implementation of trash.
  */
 class Trash {
   constructor() {
     /**
-     * Store /.Trash/files and /.Trash/info to avoid repeated lookup
-     * @private {?TrashDirs}
+     * Store TrashDirs to avoid repeated lookup.
+     * @private {!Object<string, !TrashDirs>}
+     * @const
      */
-    this.trashDirs_;
+    this.trashDirs_ = {};
   }
 
   /**
-   * Only move to trash if feature is on, and entry is in MyFiles, but not
-   * already in /.Trash.
+   * Only move to trash if feature is on, and entry is in one of the supported
+   * volumes, but not already in the trash.
    *
    * @param {!VolumeManager} volumeManager
    * @param {!Entry} entry The entry to remove.
-   * @return {boolean} True if item should be moved to trash, else false if item
-   *     should be permanently deleted.
+   * @return {?TrashConfig} Valid TrashConfig if item should be moved to trash,
+   *     else null if item should be permanently deleted.
    * @private
    */
   shouldMoveToTrash_(volumeManager, entry) {
-    if (loadTimeData.getBoolean('FILES_TRASH_ENABLED')) {
-      const info = volumeManager.getLocationInfo(entry);
-      const entryInTrash =
-          entry.fullPath === '/.Trash' || entry.fullPath.startsWith('/.Trash/');
-      return !!info &&
-          info.rootType === VolumeManagerCommon.RootType.DOWNLOADS &&
-          !entryInTrash;
+    const info = volumeManager.getLocationInfo(entry);
+    if (!loadTimeData.getBoolean('FILES_TRASH_ENABLED') || !info) {
+      return null;
     }
-    return false;
+    const fullPathSlash = entry.fullPath + '/';
+    for (const config of Trash.CONFIG) {
+      const entryInVolume = fullPathSlash.startsWith(config.topDir);
+      if (config.rootType === info.rootType && entryInVolume) {
+        if (config.prefixPathWithRemoteMount) {
+          config.pathPrefix = info.volumeInfo.remoteMountPath;
+        }
+        const entryInTrash = fullPathSlash.startsWith(config.trashDir);
+        return entryInTrash ? null : config;
+      }
+    }
+    return null;
   }
 
   /**
@@ -63,15 +113,17 @@
    * @param {!Entry} entry The entry to remove.
    * @param {boolean} permanentlyDelete If true, entry is deleted, else it is
    *     moved to trash.
-   * @return {!Promise<!Entry|undefined>} Promise which resolves when entry is
-   *     removed, rejects with DOMError.
+   * @return {!Promise<!TrashItem|undefined>} Promise which resolves when entry
+   *     is removed, rejects with DOMError.
    */
   removeFileOrDirectory(volumeManager, entry, permanentlyDelete) {
-    if (!permanentlyDelete && this.shouldMoveToTrash_(volumeManager, entry)) {
-      return this.trashLocalFileOrDirectory_(volumeManager, entry);
-    } else {
-      return this.permanentlyDeleteFileOrDirectory_(entry);
+    if (!permanentlyDelete) {
+      const config = this.shouldMoveToTrash_(volumeManager, entry);
+      if (config) {
+        return this.trashFileOrDirectory_(entry, config);
+      }
     }
+    return this.permanentlyDeleteFileOrDirectory_(entry);
   }
 
   /**
@@ -92,46 +144,56 @@
   }
 
   /**
-   * Get /.Trash/files and /.Trash/info directories.
+   * Get trash files and info directories.
    *
-   * @param {!VolumeManager} volumeManager
+   * @param {!Entry} entry The entry to remove.
+   * @param {!TrashConfig} config
    * @return {!Promise<!TrashDirs>} Promise which resolves with trash dirs.
    * @private
    */
-  getTrashDirs_(volumeManager) {
-    if (this.trashDirs_) {
-      return Promise.resolve(this.trashDirs_);
+  async getTrashDirs_(entry, config) {
+    const key = `${config.rootType}-${config.topDir}`;
+    let trashDirs = this.trashDirs_[key];
+    if (trashDirs) {
+      return trashDirs;
     }
 
-    const downloads = volumeManager.getCurrentProfileVolumeInfo(
-        VolumeManagerCommon.VolumeType.DOWNLOADS);
-    const root = downloads.fileSystem.root;
-    return new Promise((resolve, reject) => {
-      root.getDirectory('.Trash', {create: true}, (trashRoot) => {
-        trashRoot.getDirectory('files', {create: true}, (trashFiles) => {
-          trashRoot.getDirectory('info', {create: true}, trashInfo => {
-            this.trashDirs_ = new TrashDirs(trashFiles, trashInfo);
-            resolve(this.trashDirs_);
-          }, reject);
-        }, reject);
-      }, reject);
-    });
+    let trashRoot = entry.filesystem.root;
+    const parts = config.trashDir.split('/');
+    for (const part of parts) {
+      if (part) {
+        trashRoot = await this.getDirectory_(trashRoot, part);
+      }
+    }
+    const trashFiles = await this.getDirectory_(trashRoot, 'files');
+    const trashInfo = await this.getDirectory_(trashRoot, 'info');
+    trashDirs = new TrashDirs(trashFiles, trashInfo);
+    // Check and remove old items max once per session.
+    this.removeOldItems_(trashDirs, Date.now());
+    this.trashDirs_[key] = trashDirs;
+    return trashDirs;
   }
 
   /**
    * Write /.Trash/info/<name>.trashinfo file.
+   * Creates empty /.Trash/info/<name>.trashinfo.tmp file, writes to file,
+   * then moves to /.Trash/info/<name>.trashinfo. By using mv as the final
+   * operation we guarantee that another process such as removing old items
+   * will not read an incomplete *.trashinfo file.
    *
-   * @param {!Entry} trashInfoDir /.Trash/info directory.
+   * @param {!DirectoryEntry} trashInfoDir /.Trash/info directory.
    * @param {string} name name for <name>.trashinfo file.
    * @param {string} path path to use in .trashinfo file.
-   * @return {!Promise<void>}
+   * @return {!Promise<!FileEntry>}
    * @private
    */
-  writeTrashInfoFile_(trashInfoDir, name, path) {
-    return new Promise((resolve, reject) => {
-      trashInfoDir.getFile(name + '.trashinfo', {create: true}, infoFile => {
+  async writeTrashInfoFile_(trashInfoDir, name, path) {
+    const tmpName = `${name}.trashinfo.tmp`;
+    const finalName = `${name}.trashinfo`;
+    const tmpFile = await new Promise((resolve, reject) => {
+      trashInfoDir.getFile(tmpName, {create: true}, infoFile => {
         infoFile.createWriter(writer => {
-          writer.onwriteend = resolve;
+          writer.onwriteend = resolve.bind(null, infoFile);
           writer.onerror = reject;
           const info = `[Trash Info]\nPath=${path}\nDeletionDate=${
               new Date().toISOString()}`;
@@ -139,15 +201,32 @@
         }, reject);
       }, reject);
     });
+    return this.moveTo_(tmpFile, trashInfoDir, finalName);
+  }
+
+  /**
+   * Promise wrapper for FileSystemDirectoryEntry.getDirectory().
+   *
+   * @param {!DirectoryEntry} dirEntry current directory.
+   * @param {string} path name of directory within dirEntry.
+   * @return {!Promise<!DirectoryEntry>} Promise which resolves with
+   *     <dirEntry>/<path>.
+   * @private
+   */
+  getDirectory_(dirEntry, path) {
+    return new Promise((resolve, reject) => {
+      dirEntry.getDirectory(path, {create: true}, resolve, reject);
+    });
   }
 
   /**
    * Promise wrapper for FileSystemEntry.moveTo().
    *
-   * @param {!Entry} srcEntry source entry to move.
+   * @param {!T} srcEntry source entry to move.
    * @param {!DirectoryEntry} dstDirEntry destination directory.
    * @param {string} name name of entry in destination directory.
-   * @return {!Promise<!Entry>} Promise which resolves with moved entry.
+   * @return {!Promise<!T>} Promise which resolves with moved entry.
+   * @template T
    * @private
    */
   moveTo_(srcEntry, dstDirEntry, name) {
@@ -157,19 +236,187 @@
   }
 
   /**
-   * Move a file or a directory in the local DOWNLOADS volume to
-   * the trash.
+   * Move a file or a directory to the trash.
    *
-   * @param {!VolumeManager} volumeManager
    * @param {!Entry} entry The entry to remove.
-   * @return {!Promise<!Entry>}
+   * @param {!TrashConfig} config trash config for entry.
+   * @return {!Promise<!TrashItem>}
    * @private
    */
-  async trashLocalFileOrDirectory_(volumeManager, entry) {
-    const trashDirs = await this.getTrashDirs_(volumeManager);
+  async trashFileOrDirectory_(entry, config) {
+    const trashDirs = await this.getTrashDirs_(entry, config);
     const name =
         await fileOperationUtil.deduplicatePath(trashDirs.files, entry.name);
-    await this.writeTrashInfoFile_(trashDirs.info, name, entry.fullPath);
-    return this.moveTo_(entry, trashDirs.files, name);
+
+    // Write trashinfo first, then only move file if info write succeeds.
+    // If any step fails, the file will be unchanged, and any partial trashinfo
+    // file created will be cleaned up when we remove old items.
+    const infoEntry = await this.writeTrashInfoFile_(
+        trashDirs.info, name, config.pathPrefix + entry.fullPath);
+    const filesEntry = await this.moveTo_(entry, trashDirs.files, name);
+    return new TrashItem(entry.name, filesEntry, infoEntry, config.pathPrefix);
+  }
+
+  /**
+   * Restores the specified trash item.
+   *
+   * @param {!VolumeManager} volumeManager
+   * @param {!TrashItem} trashItem item in trash.
+   * @return {Promise<void>} Promise which resolves when file is restored.
+   */
+  async restore(volumeManager, trashItem) {
+    // Read Path from info entry.
+    const file = await new Promise(
+        (resolve, reject) => trashItem.infoEntry.file(resolve, reject));
+    const text = await file.text();
+    const found = text.match(/^Path=(.*)/m);
+    if (!found) {
+      throw new DOMException(`No Path found to restore in ${
+          trashItem.infoEntry.fullPath}, text=${text}`);
+    }
+    const path = found[1];
+    if (!path.startsWith(trashItem.pathPrefix)) {
+      throw new DOMException(`Path does not match expected prefix in ${
+          trashItem.infoEntry.fullPath}, prefix=${trashItem.pathPrefix}, text=${
+          text}`);
+    }
+    const pathNoLeadingSlash = path.substring(trashItem.pathPrefix.length + 1);
+    const parts = pathNoLeadingSlash.split('/');
+
+    // Move to last directory in path, making sure dirs are created if needed.
+    let dir = trashItem.filesEntry.filesystem.root;
+    for (let i = 0; i < parts.length - 1; i++) {
+      dir = await this.getDirectory_(dir, parts[i]);
+    }
+
+    // Restore filesEntry first, then remove its trash infoEntry.
+    // If any step fails, then either we still have the file in trash with a
+    // valid trashinfo, or file is restored and trashinfo will be cleaned up
+    // when we remove old items.
+    const name =
+        await fileOperationUtil.deduplicatePath(dir, parts[parts.length - 1]);
+    await this.moveTo_(trashItem.filesEntry, dir, name);
+    await this.permanentlyDeleteFileOrDirectory_(trashItem.infoEntry);
+  }
+
+  /**
+   * Remove any items from trash older than 30d.
+   * @param {!TrashDirs} trashDirs
+   * @param {number} now Current time in milliseconds from epoch.
+   */
+  async removeOldItems_(trashDirs, now) {
+    const ls = (reader) => {
+      return new Promise((resolve, reject) => {
+        reader.readEntries(results => resolve(results), error => reject(error));
+      });
+    };
+    const rm = (entry, log, desc) => {
+      if (entry) {
+        log(`Deleting ${entry.toURL()}: ${desc}`);
+        return this.permanentlyDeleteFileOrDirectory_(entry).catch(
+            e => console.error(`Error deleting ${entry.toURL()}: ${desc}`, e));
+      }
+    };
+
+    // Get all entries in trash/files. Read files first before info in case
+    // trash or restore operations happen during this.
+    const filesEntries = {};
+    const filesReader = trashDirs.files.createReader();
+    try {
+      while (true) {
+        const entries = await ls(filesReader);
+        if (!entries.length) {
+          break;
+        }
+        entries.forEach(entry => filesEntries[entry.name] = entry);
+      }
+    } catch (e) {
+      console.error('Error reading old files entries', e);
+      return;
+    }
+
+    // Check entries in trash/info and delete items older than 30d.
+    const infoReader = trashDirs.info.createReader();
+    try {
+      while (true) {
+        const entries = await ls(infoReader);
+        if (!entries.length) {
+          break;
+        }
+        for (const entry of entries) {
+          if (!entry.isFile) {
+            rm(entry, console.error, 'Unexpected trash info directory');
+            continue;
+          }
+
+          if (!entry.name.endsWith('.trashinfo')) {
+            rm(entry, console.error, 'Unexpected trash info file');
+            continue;
+          }
+
+          const name = entry.name.substring(0, entry.name.length - 10);
+          const filesEntry = filesEntries[name];
+          delete filesEntries[name];
+
+          const file = await new Promise(
+              (resolve, reject) => entry.file(resolve, reject));
+          const text = await file.text();
+          const found = text.match(/^DeletionDate=(.*)/m);
+          if (!found) {
+            rm(entry, console.error, 'Could not find DeletionDate in ' + text);
+            rm(filesEntry, console.error, 'Invalid matching trashinfo');
+            continue;
+          }
+
+          const d = Date.parse(found[1]);
+          if (!d) {
+            rm(entry, console.error, 'Could not parse DeletionDate in ' + text);
+            rm(filesEntry, console.error, 'Invalid matching trashinfo');
+            continue;
+          }
+
+          const ago30d = now - Trash.AUTO_DELETE_INTERVAL_MS;
+          const ago30dStr = new Date(ago30d).toISOString();
+          if (d < ago30d) {
+            const msg = `Older than ${ago30dStr}, DeletionDate=${found[1]}`;
+            rm(entry, console.log, msg);
+            rm(filesEntry, console.log, msg);
+          }
+        }
+      }
+    } catch (e) {
+      console.error('Error reading old info entries', e);
+      return;
+    }
+
+    // Any entries left in filesEntries have no matching *.trashinfo file.
+    for (const entry of Object.values(filesEntries)) {
+      rm(entry, console.error, 'No matching *.trashinfo file');
+    }
   }
 }
+
+/**
+ * Interval (ms) until items in trash are permanently deleted. 30 days.
+ * @const
+ */
+Trash.AUTO_DELETE_INTERVAL_MS = 30 * 24 * 60 * 60 * 1000;
+
+/**
+ * Volumes supported for Trash, and location of Trash dir. Items will be
+ * searched in order.
+ *
+ * @type {!Array<!TrashConfig>}
+ */
+Trash.CONFIG = [
+  // MyFiles/Downloads is a separate volume on a physical device, and doing a
+  // move from MyFiles/Downloads/<path> to MyFiles/.Trash actually does a
+  // copy across volumes, so we have a dedicated MyFiles/Downloads/.Trash.
+  new TrashConfig(
+      VolumeManagerCommon.RootType.DOWNLOADS, '/Downloads/',
+      '/Downloads/.Trash/'),
+  new TrashConfig(VolumeManagerCommon.RootType.DOWNLOADS, '/', '/.Trash/'),
+  new TrashConfig(
+      VolumeManagerCommon.RootType.CROSTINI, '/', '/.local/share/Trash/',
+      /*prefixPathWithRemoteMount=*/ true),
+];
diff --git a/ui/file_manager/file_manager/background/js/trash_unittest.js b/ui/file_manager/file_manager/background/js/trash_unittest.js
index f6b0d37..4910725 100644
--- a/ui/file_manager/file_manager/background/js/trash_unittest.js
+++ b/ui/file_manager/file_manager/background/js/trash_unittest.js
@@ -9,7 +9,9 @@
 function setUp() {
   // Mock LoadTimeData strings.
   window.loadTimeData = {
-    data: {},
+    data: {
+      'FILES_TRASH_ENABLED': true,
+    },
     getBoolean: function(key) {
       return window.loadTimeData.data[key];
     },
@@ -24,7 +26,7 @@
  * we correctly either permanently delete, or move to trash.
  *
  * @suppress {accessControls} Access private functions
- * permanentlyDeleteFileOrDirectory_() and trashLocalFileOrDirectory_().
+ * permanentlyDeleteFileOrDirectory_() and trashFileOrDirectory_().
  */
 function checkRemoveFileOrDirectory(
     filesTrashEnabled, rootType, path, deletePermanently,
@@ -35,21 +37,21 @@
   const f = MockFileEntry.create(volumeInfo.fileSystem, path);
 
   const trash = new Trash();
-  // Detect whether permanentlyDelete..., or trashLocal... is called.
+  // Detect whether permanentlyDelete..., or trash... is called.
   let permanentlyDeleteCalled = false;
-  let trashLocalCalled = false;
+  let trashCalled = false;
   trash.permanentlyDeleteFileOrDirectory_ = () => {
     permanentlyDeleteCalled = true;
     return Promise.resolve();
   };
-  trash.trashLocalFileOrDirectory_ = (volumeManager, entry) => {
-    trashLocalCalled = true;
+  trash.trashFileOrDirectory_ = (volumeManager, entry) => {
+    trashCalled = true;
     return Promise.resolve();
   };
 
   trash.removeFileOrDirectory(volumeManager, f, deletePermanently);
   assertEquals(expectPermanentlyDelete, permanentlyDeleteCalled);
-  assertEquals(!expectPermanentlyDelete, trashLocalCalled);
+  assertEquals(!expectPermanentlyDelete, trashCalled);
 }
 
 /**
@@ -104,12 +106,11 @@
 }
 
 /**
- * Test trashLocalFileOrDirectory_().
- *
- * @suppress {accessControls} Access trashLocalFileOrDirectory_().
+ * Test trash in MyFiles.
  */
-async function testTrashLocalFileOrDirectory(done) {
+async function testMyFilesTrash(done) {
   const trash = new Trash();
+  const deletePermanently = false;
   const downloads = volumeManager.getCurrentProfileVolumeInfo(
       VolumeManagerCommon.VolumeType.DOWNLOADS);
   const fs = downloads.fileSystem;
@@ -123,7 +124,7 @@
   // /.Trash/info.
   assertEquals(5, Object.keys(fs.entries).length);
   assertTrue(!!fs.entries['/dir/file1']);
-  await trash.trashLocalFileOrDirectory_(volumeManager, file1);
+  await trash.removeFileOrDirectory(volumeManager, file1, deletePermanently);
   assertFalse(!!fs.entries['/dir/file1']);
   assertTrue(fs.entries['/.Trash/files'].isDirectory);
   assertTrue(fs.entries['/.Trash/info'].isDirectory);
@@ -137,7 +138,7 @@
 
   // Trashed dir should also move children files into /.Trash/files.
   assertTrue(!!fs.entries['/dir']);
-  await trash.trashLocalFileOrDirectory_(volumeManager, dir);
+  await trash.removeFileOrDirectory(volumeManager, dir, deletePermanently);
   assertFalse(!!fs.entries['/dir']);
   assertFalse(!!fs.entries['/dir/file2']);
   assertFalse(!!fs.entries['/dir/file3']);
@@ -157,3 +158,225 @@
 
   done();
 }
+
+/**
+ * Test that Downloads has its own /Downloads/.Trash since it is a separate
+ * mount on a device and we don't want move to trash to be a copy operation.
+ *
+ * @suppress {accessControls} Access shouldMoveToTrash_().
+ */
+async function testDownloadsHasOwnTrash(done) {
+  const trash = new Trash();
+  const deletePermanently = false;
+  const downloads = volumeManager.getCurrentProfileVolumeInfo(
+      VolumeManagerCommon.VolumeType.DOWNLOADS);
+  const fs = downloads.fileSystem;
+  const file1 = MockFileEntry.create(fs, '/file1', null, new Blob(['f1']));
+  const dir2 = MockDirectoryEntry.create(fs, '/Downloads');
+  const file2 =
+      MockFileEntry.create(fs, '/Downloads/file2', null, new Blob(['f1']));
+  assertEquals(4, Object.keys(fs.entries).length);
+
+  // Move /file1 to trash.
+  await trash.removeFileOrDirectory(volumeManager, file1, deletePermanently);
+  assertTrue(fs.entries['/.Trash'].isDirectory);
+  assertTrue(fs.entries['/.Trash/files'].isDirectory);
+  assertTrue(fs.entries['/.Trash/info'].isDirectory);
+  assertTrue(fs.entries['/.Trash/files/file1'].isFile);
+  assertTrue(fs.entries['/.Trash/info/file1.trashinfo'].isFile);
+  assertEquals(8, Object.keys(fs.entries).length);
+
+  // Move /files2 (in Downloads to trash.
+  await trash.removeFileOrDirectory(volumeManager, file2, deletePermanently);
+  assertTrue(fs.entries['/Downloads/.Trash'].isDirectory);
+  assertTrue(fs.entries['/Downloads/.Trash/files'].isDirectory);
+  assertTrue(fs.entries['/Downloads/.Trash/info'].isDirectory);
+  assertTrue(fs.entries['/Downloads/.Trash/files/file2'].isFile);
+  assertTrue(fs.entries['/Downloads/.Trash/info/file2.trashinfo'].isFile);
+  assertEquals(12, Object.keys(fs.entries).length);
+
+  // Delete /Downloads/.Trash/files/file2.
+  const file2Trashed = fs.entries['/Downloads/.Trash/files/file2'];
+  assertFalse(!!trash.shouldMoveToTrash_(volumeManager, file2Trashed));
+  await trash.removeFileOrDirectory(
+      volumeManager, file2Trashed, deletePermanently);
+  assertEquals(11, Object.keys(fs.entries).length);
+
+  // Delete /Downloads/.Trash.
+  const downloadsTrash = fs.entries['/Downloads/.Trash'];
+  assertFalse(!!trash.shouldMoveToTrash_(volumeManager, downloadsTrash));
+  await trash.removeFileOrDirectory(
+      volumeManager, downloadsTrash, deletePermanently);
+  assertEquals(7, Object.keys(fs.entries).length);
+
+  done();
+}
+
+/**
+ * Test crostini trash in .local/share/Trash.
+ *
+ * @suppress {accessControls} Access shouldMoveToTrash_().
+ */
+async function testCrostiniTrash(done) {
+  const trash = new Trash();
+  const deletePermanently = false;
+  const crostini = volumeManager.createVolumeInfo(
+      VolumeManagerCommon.VolumeType.CROSTINI, 'crostini', 'Linux files', '',
+      '/home/testuser');
+  const fs = crostini.fileSystem;
+  const file1 = MockFileEntry.create(fs, '/file1', null, new Blob(['f1']));
+  const file2 = MockFileEntry.create(fs, '/file2', null, new Blob(['f1']));
+  assertEquals(3, Object.keys(fs.entries).length);
+
+  // Move /file1 to trash.
+  const file1TrashItem = await trash.removeFileOrDirectory(
+      volumeManager, file1, deletePermanently);
+  assertFalse(!!fs.entries['/file1']);
+  assertTrue(fs.entries['/.local/share/Trash'].isDirectory);
+  assertTrue(fs.entries['/.local/share/Trash/files'].isDirectory);
+  assertTrue(fs.entries['/.local/share/Trash/info'].isDirectory);
+  assertTrue(fs.entries['/.local/share/Trash/files/file1'].isFile);
+  assertTrue(fs.entries['/.local/share/Trash/info/file1.trashinfo'].isFile);
+  const text = await fs.entries['/.local/share/Trash/info/file1.trashinfo']
+                   .content.text();
+  assertTrue(
+      text.startsWith('[Trash Info]\nPath=/home/testuser/file1\nDeletionDate='),
+      `${text} must have Path=/home/test/user/file1`);
+  assertEquals(9, Object.keys(fs.entries).length);
+
+  // Restore /file1
+  await trash.restore(volumeManager, assert(file1TrashItem));
+  assertEquals(8, Object.keys(fs.entries).length);
+  assertTrue(!!fs.entries['/file1']);
+
+  // Move /file2 to trash, then delete /.local/share/Trash/files/file2.
+  await trash.removeFileOrDirectory(volumeManager, file2, deletePermanently);
+  const file2Trashed = fs.entries['/.local/share/Trash/files/file2'];
+  assertFalse(!!trash.shouldMoveToTrash_(volumeManager, file2Trashed));
+  await trash.removeFileOrDirectory(
+      volumeManager, file2Trashed, deletePermanently);
+  assertEquals(8, Object.keys(fs.entries).length);
+
+  // Delete /.local/share/Trash.
+  const crostiniTrash = fs.entries['/.local/share/Trash'];
+  assertFalse(!!trash.shouldMoveToTrash_(volumeManager, crostiniTrash));
+  await trash.removeFileOrDirectory(
+      volumeManager, crostiniTrash, deletePermanently);
+  assertEquals(4, Object.keys(fs.entries).length);
+
+  done();
+}
+
+/**
+ * Test restore().
+ */
+async function testRestore(done) {
+  const trash = new Trash();
+  const deletePermanently = false;
+  const downloads = volumeManager.getCurrentProfileVolumeInfo(
+      VolumeManagerCommon.VolumeType.DOWNLOADS);
+  const fs = downloads.fileSystem;
+
+  const dir = MockDirectoryEntry.create(fs, '/dir');
+  const file1 = MockFileEntry.create(fs, '/dir/file1', null, new Blob(['f1']));
+  const file2 = MockFileEntry.create(fs, '/dir/file2', null, new Blob(['f2']));
+  const file3 = MockFileEntry.create(fs, '/dir/file3', null, new Blob(['f3']));
+
+  // Move /dir/file1 to trash.
+  const file1TrashItem = await trash.removeFileOrDirectory(
+      volumeManager, file1, deletePermanently);
+  assertEquals(9, Object.keys(fs.entries).length);
+  assertFalse(!!fs.entries['/dir/file1']);
+  assertEquals('file1', file1TrashItem.name);
+  assertEquals(fs.entries['/.Trash/files/file1'], file1TrashItem.filesEntry);
+  assertEquals(
+      fs.entries['/.Trash/info/file1.trashinfo'], file1TrashItem.infoEntry);
+
+  // Restore it.
+  await trash.restore(volumeManager, assert(file1TrashItem));
+  assertEquals(8, Object.keys(fs.entries).length);
+  assertTrue(!!fs.entries['/dir/file1']);
+
+  // Move /dir/file2 to trash, recreate a new /dir/file2,
+  // original should restore to '/dir/file2 (1)'.
+  const file2TrashItem = await trash.removeFileOrDirectory(
+      volumeManager, file2, deletePermanently);
+  assertFalse(!!fs.entries['/dir/file2']);
+  assertEquals(9, Object.keys(fs.entries).length);
+  MockFileEntry.create(fs, '/dir/file2', null, new Blob(['f2v2']));
+  assertEquals(10, Object.keys(fs.entries).length);
+  await trash.restore(volumeManager, assert(file2TrashItem));
+  assertEquals(9, Object.keys(fs.entries).length);
+  assertTrue(!!fs.entries['/dir/file2 (1)']);
+  let text = await fs.entries['/dir/file2'].content.text();
+  assertEquals('f2v2', text);
+  text = await fs.entries['/dir/file2 (1)'].content.text();
+  assertEquals('f2', text);
+
+  done();
+}
+
+/**
+ * Test removeOldEntries_().
+ *
+ * @suppress {accessControls} Access removeOldItems_().
+ */
+async function testRemoveOldItems_(done) {
+  const trash = new Trash();
+  const deletePermanently = false;
+  const downloads = volumeManager.getCurrentProfileVolumeInfo(
+      VolumeManagerCommon.VolumeType.DOWNLOADS);
+  const fs = downloads.fileSystem;
+
+  const dir = MockDirectoryEntry.create(fs, '/dir');
+  const file1 = MockFileEntry.create(fs, '/dir/file1', null, new Blob(['f1']));
+  const file2 = MockFileEntry.create(fs, '/dir/file2', null, new Blob(['f2']));
+  const file3 = MockFileEntry.create(fs, '/dir/file3', null, new Blob(['f3']));
+  const file4 = MockFileEntry.create(fs, '/dir/file4', null, new Blob(['f4']));
+  const file5 = MockFileEntry.create(fs, '/dir/file5', null, new Blob(['f5']));
+
+  // Move files to trash.
+  for (const f of [file1, file2, file3, file4, file5]) {
+    await trash.removeFileOrDirectory(volumeManager, f, deletePermanently);
+  }
+  assertEquals(15, Object.keys(fs.entries).length);
+  const now = Date.now();
+
+  // Directories inside info should be deleted.
+  MockDirectoryEntry.create(fs, '/.Trash/info/baddir.trashinfo');
+  // Files that do not end with .trashinfo should be deleted.
+  MockFileEntry.create(fs, '/.Trash/info/f', null, new Blob(['f']));
+  // Files without a matching file in .Trash/files are left.
+  delete fs.entries['/.Trash/files/file1'];
+  // Files with no DeletionDate should be deleted.
+  fs.entries['/.Trash/info/file2.trashinfo'].content =
+      new Blob(['no-deletion-date']);
+  // Files with DeletionDate which cannot be parsed should be deleted.
+  fs.entries['/.Trash/info/file3.trashinfo'].content =
+      new Blob(['DeletionDate=abc']);
+  // Files with no matching trashinfo should be deleted.
+  delete fs.entries['/.Trash/info/file4.trashinfo'];
+
+  const trashDirs =
+      new TrashDirs(fs.entries['/.Trash/files'], fs.entries['/.Trash/info']);
+  await trash.removeOldItems_(trashDirs, now);
+  assertTrue(!!fs.entries['/']);
+  assertTrue(!!fs.entries['/.Trash']);
+  assertTrue(!!fs.entries['/.Trash/files']);
+  assertTrue(!!fs.entries['/.Trash/files/file5']);
+  assertTrue(!!fs.entries['/.Trash/info']);
+  assertTrue(!!fs.entries['/.Trash/info/file1.trashinfo']);
+  assertTrue(!!fs.entries['/.Trash/info/file5.trashinfo']);
+  assertTrue(!!fs.entries['/dir']);
+  assertEquals(8, Object.keys(fs.entries).length);
+
+  // Items older than 30d should be deleted.
+  await trash.removeOldItems_(trashDirs, now + (29 * 24 * 60 * 60 * 1000));
+  assertEquals(8, Object.keys(fs.entries).length);
+  await trash.removeOldItems_(trashDirs, now + (31 * 24 * 60 * 60 * 1000));
+  assertFalse(!!fs.entries['/.Trash/info/file5.trashinfo']);
+  assertFalse(!!fs.entries['/.Trash/files/file5']);
+  assertEquals(5, Object.keys(fs.entries).length);
+
+  done();
+}
diff --git a/ui/file_manager/file_manager/background/js/volume_info_impl.js b/ui/file_manager/file_manager/background/js/volume_info_impl.js
index d0eb136..aca1c77 100644
--- a/ui/file_manager/file_manager/background/js/volume_info_impl.js
+++ b/ui/file_manager/file_manager/background/js/volume_info_impl.js
@@ -40,12 +40,15 @@
    * @param {(string|undefined)} driveLabel Drive label of the volume. Removable
    *     partitions belonging to the same device will share the same drive
    *     label.
+   * @param {(string|undefined)} remoteMountPath The path on the remote host
+   *     where this volume is mounted, for crostini this is the user's homedir
+   *     (/home/<username>).
    */
   constructor(
       volumeType, volumeId, fileSystem, error, deviceType, devicePath,
       isReadOnly, isReadOnlyRemovableDevice, profile, label, providerId,
       hasMedia, configurable, watchable, source, diskFileSystemType, iconSet,
-      driveLabel) {
+      driveLabel, remoteMountPath) {
     this.volumeType_ = volumeType;
     this.volumeId_ = volumeId;
     this.fileSystem_ = fileSystem;
@@ -93,6 +96,7 @@
     this.diskFileSystemType_ = diskFileSystemType;
     this.iconSet_ = iconSet;
     this.driveLabel_ = driveLabel;
+    this.remoteMountPath_ = remoteMountPath;
 
     /** @private @const {Promise<!DirectoryEntry>} */
     this.displayRootPromise_ = this.resolveDisplayRootImpl_();
@@ -260,6 +264,15 @@
   }
 
   /**
+   * The path on the remote host where this volume is mounted, for crostini this
+   * is the user's homedir (/home/<username>).
+   * @return {(string|undefined)}
+   */
+  get remoteMountPath() {
+    return this.remoteMountPath_;
+  }
+
+  /**
    * @type {FilesAppEntry} an entry to be used as prefix of this volume on
    *     breadcrumbs, e.g. "My Files > Downloads", "My Files" is a prefixEntry
    *     on "Downloads" VolumeInfo.
diff --git a/ui/file_manager/file_manager/background/js/volume_manager_unittest.js b/ui/file_manager/file_manager/background/js/volume_manager_unittest.js
index b743ab28..71d25b5 100644
--- a/ui/file_manager/file_manager/background/js/volume_manager_unittest.js
+++ b/ui/file_manager/file_manager/background/js/volume_manager_unittest.js
@@ -418,8 +418,9 @@
         /* watchable */ true,
         /* source */ VolumeManagerCommon.Source.FILE,
         /* diskFileSystemType */ VolumeManagerCommon.FileSystemType.UNKNOWN,
-        /* iconSet*/ {},
-        /* driveLabel*/ 'TEST_DRIVE_LABEL');
+        /* iconSet */ {},
+        /* driveLabel */ 'TEST_DRIVE_LABEL',
+        /* remoteMountPath*/ '');
     volumeManager.volumeInfoList.add(volumeInfo);
     const promiseAfterAdd = volumeManager.whenVolumeInfoReady('volumeId');
     reportPromise(
@@ -549,7 +550,7 @@
       (driveVolumeMetadata.source),
       /** @type {VolumeManagerCommon.FileSystemType} */
       (driveVolumeMetadata.diskFileSystemType), driveVolumeMetadata.iconSet,
-      (driveVolumeMetadata.driveLabel));
+      driveVolumeMetadata.driveLabel, driveVolumeMetadata.remoteMountPath);
 
   // Wait for trying to resolve display root, it should fail with
   // |expectedError| if not re-throw to make the test fail.
diff --git a/ui/file_manager/file_manager/background/js/volume_manager_util.js b/ui/file_manager/file_manager/background/js/volume_manager_util.js
index 21092c02..7f64bba 100644
--- a/ui/file_manager/file_manager/background/js/volume_manager_util.js
+++ b/ui/file_manager/file_manager/background/js/volume_manager_util.js
@@ -167,7 +167,7 @@
                 (volumeMetadata.source),
                 /** @type {VolumeManagerCommon.FileSystemType} */
                 (volumeMetadata.diskFileSystemType), volumeMetadata.iconSet,
-                (volumeMetadata.driveLabel));
+                volumeMetadata.driveLabel, volumeMetadata.remoteMountPath);
           })
       .catch(
           /** @param {*} error */
@@ -191,6 +191,6 @@
                 (volumeMetadata.source),
                 /** @type {VolumeManagerCommon.FileSystemType} */
                 (volumeMetadata.diskFileSystemType), volumeMetadata.iconSet,
-                (volumeMetadata.driveLabel));
+                volumeMetadata.driveLabel, volumeMetadata.remoteMountPath);
           });
 };
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn
index 5029f19..1488066 100644
--- a/ui/file_manager/file_manager/foreground/js/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -412,8 +412,11 @@
     "//ui/webui/resources/cr_elements/cr_input:cr_input",
   ]
   externs_list = [
+    "//ui/file_manager/externs/background/file_operation_manager.js",
     "//ui/file_manager/externs/background/progress_center.js",
     "//ui/file_manager/externs/command_handler_deps.js",
+    "//ui/file_manager/externs/file_operation_progress_event.js",
+    "//ui/file_manager/externs/file_operation_util.js",
   ]
 }
 
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager.js b/ui/file_manager/file_manager/foreground/js/file_manager.js
index 41d5324..257f3ff 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager.js
@@ -702,6 +702,7 @@
     this.document_.addEventListener(
         'command',
         this.ui_.listContainer.clearHover.bind(this.ui_.listContainer));
+    CommandHandler.registerUndoDeleteToast(this);
   }
 
   /**
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
index 22d3e47..be307b3 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -1180,6 +1180,35 @@
 };
 
 /**
+ * Register listener on background for delete event, and show undo toast if
+ * files are in trash and can be restored.
+ * @param {!CommandHandlerDeps} fileManager
+ */
+CommandHandler.registerUndoDeleteToast = function(fileManager) {
+  /**
+   * @param {!FileOperationProgressEvent} e
+   */
+  const onDeleted = (e) => {
+    if (e.reason === 'BEGIN' || e.reason === 'PROGRESS' ||
+        !e.trashedItems.length) {
+      return;
+    }
+    const message = e.trashedItems.length === 1 ?
+        strf('UNDO_DELETE_ONE', e.trashedItems[0].name) :
+        strf('UNDO_DELETE_SOME', e.trashedItems.length);
+    fileManager.ui.toast.show(message, {
+      text: str('UNDO_DELETE_ACTION_LABEL'),
+      callback: () => {
+        fileManager.fileOperationManager.restoreDeleted(e.trashedItems);
+      }
+    });
+  };
+
+  util.addEventListenerToBackgroundComponent(
+      assert(fileManager.fileOperationManager), 'delete', onDeleted);
+};
+
+/**
  * Pastes files from clipboard.
  */
 CommandHandler.COMMANDS_['paste'] = new class extends Command {
diff --git a/ui/file_manager/file_manager/foreground/js/providers_model_unittest.js b/ui/file_manager/file_manager/foreground/js/providers_model_unittest.js
index d1fb7f3d..a00d7eb 100644
--- a/ui/file_manager/file_manager/foreground/js/providers_model_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/providers_model_unittest.js
@@ -123,7 +123,8 @@
       VolumeManagerCommon.Source.NETWORK,          // source
       VolumeManagerCommon.FileSystemType.UNKNOWN,  // diskFileSystemType
       {},                                          // iconSet
-      '');                                         // driveLabel
+      '',                                          // driveLabel
+      '');                                         // remoteMountPath
 
   volumeManager.volumeInfoList.add(volumeInfo);
 }
diff --git a/ui/file_manager/file_manager/test/js/strings.js b/ui/file_manager/file_manager/test/js/strings.js
index 782f860e..77c1160 100644
--- a/ui/file_manager/file_manager/test/js/strings.js
+++ b/ui/file_manager/file_manager/test/js/strings.js
@@ -15,7 +15,7 @@
   'FILES_NG_ENABLED': true,
   'FILES_SINGLE_PARTITION_FORMAT_ENABLED': false,
   'FILES_TRANSFER_DETAILS_ENABLED': true,
-  'FILES_TRASH_ENABLED': false,
+  'FILES_TRASH_ENABLED': true,
   'FILTERS_IN_RECENTS_ENABLED': false,
   'GOOGLE_DRIVE_OVERVIEW_URL':
       'https://support.google.com/chromebook/?p=filemanager_drive',
diff --git a/ui/file_manager/integration_tests/file_manager/trash.js b/ui/file_manager/integration_tests/file_manager/trash.js
index 23115e0..86b13584 100644
--- a/ui/file_manager/integration_tests/file_manager/trash.js
+++ b/ui/file_manager/integration_tests/file_manager/trash.js
@@ -33,26 +33,50 @@
 
   // Wait for menu item to appear.
   await remoteCall.waitForElement(
-      appId, '#gear-menu-toggle-hidden-files:not([disabled])');
-
-  // Wait for menu item to appear.
-  await remoteCall.waitForElement(
-      appId, '#gear-menu-toggle-hidden-files:not([checked])');
+      appId, '#gear-menu-toggle-hidden-files:not([disabled]):not([checked])');
 
   // Click the menu item.
   await remoteCall.callRemoteTestUtil(
       'fakeMouseClick', appId, ['#gear-menu-toggle-hidden-files']);
 
-  // Navigate to /My files/.Trash/files.
-  await navigateWithDirectoryTree(appId, '/My files/.Trash/files');
+  // Navigate to /My files/Downloads/.Trash/files.
+  await navigateWithDirectoryTree(appId, '/My files/Downloads/.Trash/files');
 
   // Ensure hello.txt exists.
   await remoteCall.waitForElement(appId, '#file-list [file-name="hello.txt"]');
 
   // Navigate to /My files/.Trash/files.
-  await navigateWithDirectoryTree(appId, '/My files/.Trash/info');
+  await navigateWithDirectoryTree(appId, '/My files/Downloads/.Trash/info');
 
   // Ensure hello.txt.trashinfo exists.
   await remoteCall.waitForElement(
       appId, '#file-list [file-name="hello.txt.trashinfo"]');
 };
+
+/**
+ * Delete files then restore via toast 'Undo'.
+ */
+testcase.trashRestore = async () => {
+  const appId = await setupAndWaitUntilReady(
+      RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET, []);
+
+  // Select hello.txt.
+  await remoteCall.waitAndClickElement(
+      appId, '#file-list [file-name="hello.txt"]');
+
+  // Delete item and confirm delete.
+  await remoteCall.waitAndClickElement(appId, '#delete-button');
+  await remoteCall.waitAndClickElement(
+      appId, '.files-confirm-dialog .cr-dialog-ok');
+
+  // Wait for file to be removed from list.
+  await remoteCall.waitForElementLost(
+      appId, '#file-list [file-name="hello.txt"]');
+
+  // Wait for the undo toast and click undo.
+  await remoteCall.waitAndClickElement(
+      appId, ['#toast', '#action:not([hidden])']);
+
+  // Wait for file to reappear in list.
+  await remoteCall.waitForElement(appId, '#file-list [file-name="hello.txt"]');
+};
diff --git a/ui/gl/direct_composition_child_surface_win.cc b/ui/gl/direct_composition_child_surface_win.cc
index 5ec0bad..c27908e 100644
--- a/ui/gl/direct_composition_child_surface_win.cc
+++ b/ui/gl/direct_composition_child_surface_win.cc
@@ -72,10 +72,12 @@
 DirectCompositionChildSurfaceWin::DirectCompositionChildSurfaceWin(
     VSyncCallback vsync_callback,
     bool use_angle_texture_offset,
-    size_t max_pending_frames)
+    size_t max_pending_frames,
+    bool force_full_damage)
     : vsync_callback_(std::move(vsync_callback)),
       use_angle_texture_offset_(use_angle_texture_offset),
       max_pending_frames_(max_pending_frames),
+      force_full_damage_(force_full_damage),
       vsync_thread_(VSyncThreadWin::GetInstance()),
       task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
 
@@ -150,13 +152,11 @@
           first_swap_ || !vsync_enabled_ || use_swap_chain_tearing ? 0 : 1;
       UINT flags = use_swap_chain_tearing ? DXGI_PRESENT_ALLOW_TEARING : 0;
 
-      bool force_full_damage =
-          ShouldForceDirectCompositionRootSurfaceFullDamage();
       TRACE_EVENT2("gpu", "DirectCompositionChildSurfaceWin::PresentSwapChain",
                    "interval", interval, "dirty_rect",
-                   force_full_damage ? "full_damage" : swap_rect_.ToString());
+                   force_full_damage_ ? "full_damage" : swap_rect_.ToString());
       HRESULT hr;
-      if (force_full_damage) {
+      if (force_full_damage_) {
         hr = swap_chain_->Present(interval, flags);
       } else {
         DXGI_PRESENT_PARAMETERS params = {};
diff --git a/ui/gl/direct_composition_child_surface_win.h b/ui/gl/direct_composition_child_surface_win.h
index 4bf8b7b..b17ea4e 100644
--- a/ui/gl/direct_composition_child_surface_win.h
+++ b/ui/gl/direct_composition_child_surface_win.h
@@ -33,7 +33,8 @@
       base::RepeatingCallback<void(base::TimeTicks, base::TimeDelta)>;
   DirectCompositionChildSurfaceWin(VSyncCallback vsync_callback,
                                    bool use_angle_texture_offset,
-                                   size_t max_pending_frames);
+                                   size_t max_pending_frames,
+                                   bool force_full_damage);
 
   // GLSurfaceEGL implementation.
   bool Initialize(GLSurfaceFormat format) override;
@@ -140,6 +141,7 @@
   const VSyncCallback vsync_callback_;
   const bool use_angle_texture_offset_;
   const size_t max_pending_frames_;
+  const bool force_full_damage_;
 
   VSyncThreadWin* const vsync_thread_;
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
diff --git a/ui/gl/direct_composition_surface_win.cc b/ui/gl/direct_composition_surface_win.cc
index 88bff886..041a672 100644
--- a/ui/gl/direct_composition_surface_win.cc
+++ b/ui/gl/direct_composition_surface_win.cc
@@ -357,7 +357,8 @@
       root_surface_(new DirectCompositionChildSurfaceWin(
           std::move(vsync_callback),
           settings.use_angle_texture_offset,
-          settings.max_pending_frames)),
+          settings.max_pending_frames,
+          settings.force_root_surface_full_damage)),
       layer_tree_(std::make_unique<DCLayerTree>(
           settings.disable_nv12_dynamic_textures,
           settings.disable_larger_than_screen_overlays,
diff --git a/ui/gl/direct_composition_surface_win.h b/ui/gl/direct_composition_surface_win.h
index 0a608315..7b7c162 100644
--- a/ui/gl/direct_composition_surface_win.h
+++ b/ui/gl/direct_composition_surface_win.h
@@ -36,6 +36,7 @@
     size_t max_pending_frames = 2;
     bool use_angle_texture_offset = false;
     bool reset_vp_when_colorspace_changes = false;
+    bool force_root_surface_full_damage = false;
   };
 
   DirectCompositionSurfaceWin(
diff --git a/ui/gtk/gtk_ui.cc b/ui/gtk/gtk_ui.cc
index 9905c4f..63f4dbc 100644
--- a/ui/gtk/gtk_ui.cc
+++ b/ui/gtk/gtk_ui.cc
@@ -520,7 +520,7 @@
 
   // Dividing GTK's cursor blink cycle time (in milliseconds) by this value
   // yields an appropriate value for
-  // blink::mojom::RendererPreferences::caret_blink_interval.
+  // blink::RendererPreferences::caret_blink_interval.
   static const double kGtkCursorBlinkCycleFactor = 2000.0;
 
   gint cursor_blink_time = kGtkDefaultCursorBlinkTime;
diff --git a/ui/message_center/public/cpp/notification.cc b/ui/message_center/public/cpp/notification.cc
index f9c1e4f..a32ee61 100644
--- a/ui/message_center/public/cpp/notification.cc
+++ b/ui/message_center/public/cpp/notification.cc
@@ -145,10 +145,20 @@
   // If |vector_small_image| is not available, fallback to raster based
   // masking and resizing.
   gfx::ImageSkia image = small_image().AsImageSkia();
-  gfx::ImageSkia masked = gfx::ImageSkiaOperations::CreateMaskedImage(
-      CreateSolidColorImage(image.width(), image.height(), color), image);
+
+#if defined(OS_CHROMEOS)
+  bool create_masked_image =
+      !optional_fields_.ignore_accent_color_for_small_image;
+#else
+  bool create_masked_image = false;
+#endif  // defined(OS_CHROMEOS)
+
+  if (create_masked_image) {
+    image = gfx::ImageSkiaOperations::CreateMaskedImage(
+        CreateSolidColorImage(image.width(), image.height(), color), image);
+  }
   gfx::ImageSkia resized = gfx::ImageSkiaOperations::CreateResizedImage(
-      masked, skia::ImageOperations::ResizeMethod::RESIZE_BEST,
+      image, skia::ImageOperations::ResizeMethod::RESIZE_BEST,
       gfx::Size(dip_size, dip_size));
   return gfx::Image(resized);
 }
diff --git a/ui/message_center/public/cpp/notification.h b/ui/message_center/public/cpp/notification.h
index 0381762..94d0c2a9 100644
--- a/ui/message_center/public/cpp/notification.h
+++ b/ui/message_center/public/cpp/notification.h
@@ -106,6 +106,12 @@
   // notification. Optional.
   gfx::Image small_image;
 
+#if defined(OS_CHROMEOS)
+  // If true, we simply use the raw |small_image| icon, ignoring accent color
+  // styling. For example, this is used with raw icons received from Android.
+  bool ignore_accent_color_for_small_image = false;
+#endif  // defined(OS_CHROMEOS)
+
   // Vector version of |small_image|.
   // Used by Notification::GenerateMaskedSmallIcon.
   // If not available, |small_image| will be used by the method. Optional.
diff --git a/ui/native_theme/native_theme_base.cc b/ui/native_theme/native_theme_base.cc
index 3047394c..dc879e3 100644
--- a/ui/native_theme/native_theme_base.cc
+++ b/ui/native_theme/native_theme_base.cc
@@ -891,7 +891,7 @@
 
     // If the button is too small, fallback to drawing a single, solid color.
     if (rect.width() < 5 || rect.height() < 5) {
-      flags.setColor(ControlsFillColorForState(state, color_scheme));
+      flags.setColor(ButtonFillColorForState(state, color_scheme));
       canvas->drawRect(skrect, flags);
       return;
     }
@@ -901,14 +901,14 @@
     // Paint the background (is not visible behind the rounded corners).
     skrect.inset(kBorderWidth / 2, kBorderWidth / 2);
     PaintLightenLayer(canvas, skrect, state, border_radius, color_scheme);
-    flags.setColor(ControlsFillColorForState(state, color_scheme));
+    flags.setColor(ButtonFillColorForState(state, color_scheme));
     canvas->drawRoundRect(skrect, border_radius, border_radius, flags);
 
     // Paint the border: 1px solid.
     if (button.has_border) {
       flags.setStyle(cc::PaintFlags::kStroke_Style);
       flags.setStrokeWidth(kBorderWidth);
-      flags.setColor(ControlsBorderColorForState(state, color_scheme));
+      flags.setColor(ButtonBorderColorForState(state, color_scheme));
       canvas->drawRoundRect(skrect, border_radius, border_radius, flags);
     }
     return;
@@ -1542,6 +1542,22 @@
   return GetControlColor(color_id, color_scheme);
 }
 
+SkColor NativeThemeBase::ButtonBorderColorForState(
+    State state,
+    ColorScheme color_scheme) const {
+  ControlColorId color_id;
+  if (state == kHovered) {
+    color_id = kButtonHoveredBorder;
+  } else if (state == kPressed) {
+    color_id = kButtonPressedBorder;
+  } else if (state == kDisabled) {
+    color_id = kButtonDisabledBorder;
+  } else {
+    color_id = kButtonBorder;
+  }
+  return GetControlColor(color_id, color_scheme);
+}
+
 SkColor NativeThemeBase::ControlsFillColorForState(
     State state,
     ColorScheme color_scheme) const {
@@ -1558,6 +1574,22 @@
   return GetControlColor(color_id, color_scheme);
 }
 
+SkColor NativeThemeBase::ButtonFillColorForState(
+    State state,
+    ColorScheme color_scheme) const {
+  ControlColorId color_id;
+  if (state == kHovered) {
+    color_id = kButtonHoveredFill;
+  } else if (state == kPressed) {
+    color_id = kButtonPressedFill;
+  } else if (state == kDisabled) {
+    color_id = kButtonDisabledFill;
+  } else {
+    color_id = kButtonFill;
+  }
+  return GetControlColor(color_id, color_scheme);
+}
+
 SkColor NativeThemeBase::ControlsBackgroundColorForState(
     State state,
     ColorScheme color_scheme) const {
@@ -1582,12 +1614,16 @@
 
   switch (color_id) {
     case kBorder:
+    case kButtonBorder:
       return SkColorSetRGB(0x76, 0x76, 0x76);
     case kHoveredBorder:
+    case kButtonHoveredBorder:
       return SkColorSetRGB(0x4F, 0x4F, 0x4F);
     case kPressedBorder:
+    case kButtonPressedBorder:
       return SkColorSetRGB(0x8D, 0x8D, 0x8D);
     case kDisabledBorder:
+    case kButtonDisabledBorder:
       return SkColorSetARGB(0x4D, 0x76, 0x76, 0x76);
     case kAccent:
       return SkColorSetRGB(0x00, 0x75, 0xFF);
@@ -1602,12 +1638,16 @@
     case kDisabledBackground:
       return SkColorSetA(SK_ColorWHITE, 0x99);
     case kFill:
+    case kButtonFill:
       return SkColorSetRGB(0xEF, 0xEF, 0xEF);
     case kHoveredFill:
+    case kButtonHoveredFill:
       return SkColorSetRGB(0xE5, 0xE5, 0xE5);
     case kPressedFill:
+    case kButtonPressedFill:
       return SkColorSetRGB(0xF5, 0xF5, 0xF5);
     case kDisabledFill:
+    case kButtonDisabledFill:
       return SkColorSetARGB(0x4D, 0xEF, 0xEF, 0xEF);
     case kLightenLayer:
       return SkColorSetARGB(0x33, 0xA9, 0xA9, 0xA9);
@@ -1661,6 +1701,9 @@
       return SkColorSetRGB(0x63, 0xAD, 0xE5);
     case kFill:
       return SkColorSetRGB(0x3B, 0x3B, 0x3B);
+    case kButtonBorder:
+    case kButtonFill:
+      return SkColorSetRGB(0x6B, 0x6B, 0x6B);
     case kLightenLayer:
     case kAutoCompleteBackground:
     case kBackground:
@@ -1685,9 +1728,17 @@
       return SkColorSetRGB(0x62, 0x62, 0x62);
     case kHoveredFill:
       return SkColorSetRGB(0x3B, 0x3B, 0x3B);
+    case kButtonHoveredBorder:
+    case kButtonHoveredFill:
+      return SkColorSetRGB(0x7B, 0x7B, 0x7B);
     case kPressedFill:
       return SkColorSetRGB(0x3B, 0x3B, 0x3B);
+    case kButtonPressedBorder:
+    case kButtonPressedFill:
+      return SkColorSetRGB(0x61, 0x61, 0x61);
     case kDisabledFill:
+    case kButtonDisabledBorder:
+    case kButtonDisabledFill:
       return SkColorSetRGB(0x36, 0x36, 0x36);
     case kScrollbarArrowBackground:
       return SkColorSetRGB(0x42, 0x42, 0x42);
@@ -1720,10 +1771,14 @@
       case kDisabledBorder:
       case kDisabledAccent:
       case kDisabledSlider:
+      case kButtonDisabledBorder:
         return system_colors_[SystemThemeColor::kGrayText];
       case kBorder:
       case kHoveredBorder:
       case kPressedBorder:
+      case kButtonBorder:
+      case kButtonHoveredBorder:
+      case kButtonPressedBorder:
         return system_colors_[SystemThemeColor::kButtonText];
       case kAccent:
       case kHoveredAccent:
@@ -1743,6 +1798,10 @@
       case kHoveredFill:
       case kPressedFill:
       case kDisabledFill:
+      case kButtonFill:
+      case kButtonHoveredFill:
+      case kButtonPressedFill:
+      case kButtonDisabledFill:
       case kAutoCompleteBackground:
       case kLightenLayer:
       case kScrollbarArrowBackground:
@@ -1762,10 +1821,14 @@
       case kDisabledBorder:
       case kDisabledAccent:
       case kDisabledSlider:
+      case kButtonDisabledBorder:
         return SK_ColorGREEN;
       case kBorder:
       case kHoveredBorder:
       case kPressedBorder:
+      case kButtonBorder:
+      case kButtonHoveredBorder:
+      case kButtonPressedBorder:
       case kScrollbarThumbInactive:
       case kScrollbarArrowBackground:
       case kScrollbarTrack:
@@ -1784,6 +1847,10 @@
       case kHoveredFill:
       case kPressedFill:
       case kDisabledFill:
+      case kButtonFill:
+      case kButtonHoveredFill:
+      case kButtonPressedFill:
+      case kButtonDisabledFill:
       case kAutoCompleteBackground:
       case kLightenLayer:
       case kScrollbarThumb:
diff --git a/ui/native_theme/native_theme_base.h b/ui/native_theme/native_theme_base.h
index ea29899..c4e206b 100644
--- a/ui/native_theme/native_theme_base.h
+++ b/ui/native_theme/native_theme_base.h
@@ -76,7 +76,15 @@
     kScrollbarThumb,
     kScrollbarThumbHovered,
     kScrollbarThumbPressed,
-    kScrollbarThumbInactive
+    kScrollbarThumbInactive,
+    kButtonBorder,
+    kButtonDisabledBorder,
+    kButtonHoveredBorder,
+    kButtonPressedBorder,
+    kButtonFill,
+    kButtonDisabledFill,
+    kButtonHoveredFill,
+    kButtonPressedFill
   };
 
   using NativeTheme::NativeTheme;
@@ -260,6 +268,9 @@
                                   const SkScalar border_radius,
                                   ColorScheme color_scheme) const;
 
+  SkColor ButtonBorderColorForState(State state,
+                                    ColorScheme color_scheme) const;
+  SkColor ButtonFillColorForState(State state, ColorScheme color_scheme) const;
   SkColor ControlsAccentColorForState(State state,
                                       ColorScheme color_scheme) const;
   SkColor ControlsBorderColorForState(State state,
diff --git a/ui/ozone/common/BUILD.gn b/ui/ozone/common/BUILD.gn
index 59c8b174..b5e8da15 100644
--- a/ui/ozone/common/BUILD.gn
+++ b/ui/ozone/common/BUILD.gn
@@ -11,8 +11,6 @@
   sources = [
     "egl_util.cc",
     "egl_util.h",
-    "features.cc",
-    "features.h",
     "gl_ozone_egl.cc",
     "gl_ozone_egl.h",
     "gl_surface_egl_readback.cc",
@@ -21,10 +19,7 @@
     "stub_overlay_manager.h",
   ]
 
-  public_deps = [
-    "//build:chromeos_buildflags",
-    "//ui/ozone:ozone_base",
-  ]
+  public_deps = [ "//ui/ozone:ozone_base" ]
 
   deps = [
     "//ui/gfx/ipc/color",
diff --git a/ui/ozone/common/features.cc b/ui/ozone/common/features.cc
deleted file mode 100644
index e8f68097..0000000
--- a/ui/ozone/common/features.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/ozone/common/features.h"
-#include "build/chromeos_buildflags.h"
-
-namespace ui {
-
-const base::Feature kWaylandOverlayDelegation {
-  "WaylandOverlayDelegation",
-#if BUILDFLAG(IS_LACROS)
-      base::FEATURE_ENABLED_BY_DEFAULT
-#else
-      base::FEATURE_DISABLED_BY_DEFAULT
-#endif
-};
-
-bool IsWaylandOverlayDelegationEnabled() {
-  return base::FeatureList::IsEnabled(kWaylandOverlayDelegation);
-}
-
-}  // namespace ui
diff --git a/ui/ozone/common/features.h b/ui/ozone/common/features.h
deleted file mode 100644
index d4b94d31..0000000
--- a/ui/ozone/common/features.h
+++ /dev/null
@@ -1,17 +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 UI_OZONE_COMMON_FEATURES_H_
-#define UI_OZONE_COMMON_FEATURES_H_
-
-#include "base/feature_list.h"
-
-namespace ui {
-
-extern const base::Feature kWaylandOverlayDelegation;
-bool IsWaylandOverlayDelegationEnabled();
-
-}  // namespace ui
-
-#endif  // UI_OZONE_COMMON_FEATURES_H_
diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn
index 07dadb5c..a551ed0 100644
--- a/ui/ozone/platform/wayland/BUILD.gn
+++ b/ui/ozone/platform/wayland/BUILD.gn
@@ -383,7 +383,6 @@
     "//ui/gfx/linux:test_support",
     "//ui/ozone:platform",
     "//ui/ozone:test_support",
-    "//ui/ozone/common",
     "//ui/platform_window/wm",
   ]
 
diff --git a/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc b/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
index ad0f3bb..1c5062651 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
+++ b/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
@@ -255,7 +255,7 @@
 
     // Prepare overlay plane.
     gl_surface->ScheduleOverlayPlane(
-        INT32_MIN, gfx::OverlayTransform::OVERLAY_TRANSFORM_FLIP_VERTICAL,
+        0, gfx::OverlayTransform::OVERLAY_TRANSFORM_FLIP_VERTICAL,
         gl_image.get(), window_->GetBounds(), {}, false, nullptr);
 
     std::vector<scoped_refptr<FakeGLImageNativePixmap>> gl_images;
@@ -452,10 +452,8 @@
     Sync();
   }
 
-  auto* root_surface = server_.GetObject<wl::MockSurface>(
-      window_->root_surface()->GetSurfaceId());
   auto* mock_primary_surface = server_.GetObject<wl::MockSurface>(
-      window_->primary_subsurface()->wayland_surface()->GetSurfaceId());
+      window_->root_surface()->GetSurfaceId());
 
   CallbacksHelper cbs_helper;
   // Submit a frame with only primary plane
@@ -490,11 +488,9 @@
 
   // Also, we expect only one buffer to be committed.
   EXPECT_CALL(*mock_primary_surface, Attach(_, _, _)).Times(1);
-  EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(0);
+  EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(1);
   EXPECT_CALL(*mock_primary_surface, DamageBuffer(_, _, _, _)).Times(1);
   EXPECT_CALL(*mock_primary_surface, Commit()).Times(1);
-  EXPECT_CALL(*root_surface, Frame(_)).Times(1);
-  EXPECT_CALL(*root_surface, Commit()).Times(1);
 
   Sync();
 
@@ -550,15 +546,13 @@
 
   // Expect one buffer to be committed.
   EXPECT_CALL(*mock_primary_surface, Attach(_, _, _)).Times(1);
-  EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(0);
+  EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(1);
   EXPECT_CALL(*mock_primary_surface, DamageBuffer(_, _, _, _)).Times(1);
   EXPECT_CALL(*mock_primary_surface, Commit()).Times(1);
-  EXPECT_CALL(*root_surface, Frame(_)).Times(1);
-  EXPECT_CALL(*root_surface, Commit()).Times(1);
 
   // Send the frame callback so that pending buffer for swap id=1u is processed
   // and swapped.
-  root_surface->SendFrameCallback();
+  mock_primary_surface->SendFrameCallback();
 
   Sync();
 
@@ -610,19 +604,15 @@
         base::BindOnce(&CallbacksHelper::BufferPresented,
                        base::Unretained(&cbs_helper), swap_id));
   }
-
-  // Do not expect parent surface to be committed.
+  // Expect parent surface to be committed without a buffer.
   EXPECT_CALL(*mock_primary_surface, Attach(_, _, _)).Times(0);
-  EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(0);
+  EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(1);
   EXPECT_CALL(*mock_primary_surface, DamageBuffer(_, _, _, _)).Times(0);
-  EXPECT_CALL(*mock_primary_surface, Commit()).Times(0);
-  // Expect root surface to be committed.
-  EXPECT_CALL(*root_surface, Frame(_)).Times(1);
-  EXPECT_CALL(*root_surface, Commit()).Times(1);
+  EXPECT_CALL(*mock_primary_surface, Commit()).Times(1);
 
   // Send the frame callback so that pending buffer for swap id=2u is processed
   // and swapped.
-  root_surface->SendFrameCallback();
+  mock_primary_surface->SendFrameCallback();
 
   Sync();
 
@@ -701,10 +691,8 @@
     Sync();
   }
 
-  auto* root_surface = server_.GetObject<wl::MockSurface>(
-      window_->root_surface()->GetSurfaceId());
   auto* mock_primary_surface = server_.GetObject<wl::MockSurface>(
-      window_->primary_subsurface()->wayland_surface()->GetSurfaceId());
+      window_->root_surface()->GetSurfaceId());
 
   CallbacksHelper cbs_helper;
   // Submit a frame with 1 primary plane and 1 overlay
@@ -749,13 +737,11 @@
   // Let's sync so that 1) GbmSurfacelessWayland submits the buffer according to
   // internal queue and fake server processes the request.
 
-  // Also, we expect primary buffer to be committed.
+  // Also, we expect only one buffer to be committed.
   EXPECT_CALL(*mock_primary_surface, Attach(_, _, _)).Times(1);
-  EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(0);
+  EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(1);
   EXPECT_CALL(*mock_primary_surface, DamageBuffer(_, _, _, _)).Times(1);
   EXPECT_CALL(*mock_primary_surface, Commit()).Times(1);
-  EXPECT_CALL(*root_surface, Frame(_)).Times(1);
-  EXPECT_CALL(*root_surface, Commit()).Times(1);
 
   Sync();
 
@@ -824,25 +810,21 @@
                        base::Unretained(&cbs_helper), swap_id));
   }
 
-  // Expect primary buffer to be committed.
+  // Expect one buffer to be committed.
   EXPECT_CALL(*mock_primary_surface, Attach(_, _, _)).Times(1);
-  EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(0);
+  EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(1);
   EXPECT_CALL(*mock_primary_surface, DamageBuffer(_, _, _, _)).Times(1);
   EXPECT_CALL(*mock_primary_surface, Commit()).Times(1);
 
-  // Expect overlay buffer to be committed.
+  // Expect one buffer to be committed.
   EXPECT_CALL(*mock_overlay_surface, Attach(_, _, _)).Times(1);
   EXPECT_CALL(*mock_overlay_surface, Frame(_)).Times(0);
   EXPECT_CALL(*mock_overlay_surface, DamageBuffer(_, _, _, _)).Times(1);
   EXPECT_CALL(*mock_overlay_surface, Commit()).Times(1);
 
-  // Expect root surface to be committed without buffer.
-  EXPECT_CALL(*root_surface, Frame(_)).Times(1);
-  EXPECT_CALL(*root_surface, Commit()).Times(1);
-
   // Send the frame callback so that pending buffer for swap id=1u is processed
   // and swapped.
-  root_surface->SendFrameCallback();
+  mock_primary_surface->SendFrameCallback();
 
   Sync();
 
diff --git a/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc b/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
index 76f938c7..5fa747f3 100644
--- a/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
+++ b/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
@@ -234,11 +234,9 @@
 
     // If the same buffer has been submitted again right after the client
     // received OnSubmission for that buffer, just damage the buffer and
-    // commit the surface again. However, if the buffer is released, it's safe
-    // to reattach the buffer.
+    // commit the surface again.
     if (submitted_buffers_.empty() ||
-        submitted_buffers_.back().buffer_id != buffer->buffer_id ||
-        buffer->released) {
+        submitted_buffers_.back().buffer_id != buffer->buffer_id) {
       // Once the BufferRelease is called, the buffer will be released.
       DCHECK(buffer->released);
       buffer->released = false;
@@ -352,27 +350,16 @@
     // Releases may not necessarily come in order, so search the submitted
     // buffers.
     WaylandBuffer* buffer = nullptr;
-    for (const auto& buff : submitted_buffers_) {
-      auto* submitted_buffer = GetBuffer(buff.buffer_id);
+    for (const auto& b : submitted_buffers_) {
+      auto* submitted_buffer = GetBuffer(b.buffer_id);
       if (submitted_buffer && wl_buffer == submitted_buffer->wl_buffer.get()) {
         buffer = submitted_buffer;
         break;
       }
     }
-    if (!buffer)
-      return;
-
-    // Some Wayland compositors (e.g. Gnome) do not send buffer.release for
-    // buffers that are discarded from a wayland subsurface's cached state. In
-    // such case, later buffer.release implies buffers attached to the same
-    // wl_surface previously are also unuesed.
-    for (const auto& buff : submitted_buffers_) {
-      auto* submitted_buffer = GetBuffer(buff.buffer_id);
-      DCHECK(!submitted_buffer->released);
-      submitted_buffer->released = true;
-      if (submitted_buffer == buffer)
-        break;
-    }
+    DCHECK(buffer);
+    DCHECK(!buffer->released);
+    buffer->released = true;
 
     // A release means we may be able to send OnSubmission for previously
     // submitted buffers.
@@ -936,21 +923,11 @@
       if (!surface->HasBuffers() && !surface->HasSurface())
         surfaces_.erase(window->root_surface());
     }
-    if (!destroyed_count) {
-      surface = GetSurface(window->primary_subsurface()->wayland_surface());
-      if (surface) {
-        destroyed_count = surface->DestroyBuffer(buffer_id);
-        if (!surface->HasBuffers() && !surface->HasSurface())
-          surfaces_.erase(window->root_surface());
-      }
-    }
-    if (!destroyed_count) {
-      const auto& subsurfaces = window->wayland_subsurfaces();
-      for (const auto& it : subsurfaces) {
-        Surface* subsurface = GetSurface((*it).wayland_surface());
-        if (subsurface)
-          destroyed_count += subsurface->DestroyBuffer(buffer_id);
-      }
+    const auto& subsurfaces = window->wayland_subsurfaces();
+    for (const auto& it : subsurfaces) {
+      Surface* subsurface = GetSurface((*it).wayland_surface());
+      if (subsurface)
+        destroyed_count += subsurface->DestroyBuffer(buffer_id);
     }
   } else {
     // Case 3)
diff --git a/ui/ozone/platform/wayland/host/wayland_subsurface.cc b/ui/ozone/platform/wayland/host/wayland_subsurface.cc
index b2bee41..9b27f617 100644
--- a/ui/ozone/platform/wayland/host/wayland_subsurface.cc
+++ b/ui/ozone/platform/wayland/host/wayland_subsurface.cc
@@ -19,11 +19,13 @@
                                  int32_t parent_buffer_scale) {
   // TODO(fangzhoug): Verify the correctness of using ui_scale here, and in
   // other ozone wayland files.
-  // Currently, the subsurface tree is at most 1 depth, gpu already sees buffer
-  // bounds in the root_surface-local coordinates. So translation is not
-  // needed for now.
+  const auto parent_bounds_dip =
+      gfx::ScaleToRoundedRect(parent_bounds_px, 1.0 / ui_scale);
   const auto bounds_dip = gfx::ScaleToRoundedRect(bounds_px, 1.0 / ui_scale);
-  return gfx::ScaleToRoundedRect(bounds_dip, ui_scale / parent_buffer_scale);
+  auto new_bounds_dip =
+      wl::TranslateBoundsToParentCoordinates(bounds_dip, parent_bounds_dip);
+  return gfx::ScaleToRoundedRect(new_bounds_dip,
+                                 ui_scale / parent_buffer_scale);
 }
 
 }  // namespace
diff --git a/ui/ozone/platform/wayland/host/wayland_surface.cc b/ui/ozone/platform/wayland/host/wayland_surface.cc
index f3092c43..3cfccaa 100644
--- a/ui/ozone/platform/wayland/host/wayland_surface.cc
+++ b/ui/ozone/platform/wayland/host/wayland_surface.cc
@@ -7,7 +7,6 @@
 #include <viewporter-client-protocol.h>
 
 #include "ui/gfx/geometry/rect_conversions.h"
-#include "ui/gfx/geometry/size.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/ozone/platform/wayland/common/wayland_util.h"
 #include "ui/ozone/platform/wayland/host/wayland_connection.h"
@@ -97,6 +96,8 @@
   if (!display_size_px_.IsEmpty()) {
     viewport_dst =
         gfx::ScaleToCeiledSize(display_size_px_, 1.f / buffer_scale_);
+    wp_viewport_set_destination(viewport(), viewport_dst.width(),
+                                viewport_dst.height());
   }
 
   if (connection_->compositor_version() >=
@@ -158,14 +159,6 @@
 
   buffer_scale_ = new_scale;
   wl_surface_set_buffer_scale(surface_.get(), buffer_scale_);
-
-  if (!display_size_px_.IsEmpty()) {
-    gfx::Size viewport_dst =
-        gfx::ScaleToCeiledSize(display_size_px_, 1.f / buffer_scale_);
-    wp_viewport_set_destination(viewport(), viewport_dst.width(),
-                                viewport_dst.height());
-  }
-
   connection_->ScheduleFlush();
 }
 
@@ -207,10 +200,6 @@
     wp_viewport_set_destination(viewport(), -1, -1);
   }
   display_size_px_ = dest_size_px;
-  gfx::Size viewport_dst =
-      gfx::ScaleToCeiledSize(display_size_px_, 1.f / buffer_scale_);
-  wp_viewport_set_destination(viewport(), viewport_dst.width(),
-                              viewport_dst.height());
 }
 
 wl::Object<wl_subsurface> WaylandSurface::CreateSubsurface(
diff --git a/ui/ozone/platform/wayland/host/wayland_surface.h b/ui/ozone/platform/wayland/host/wayland_surface.h
index c026bc22..7747c6e 100644
--- a/ui/ozone/platform/wayland/host/wayland_surface.h
+++ b/ui/ozone/platform/wayland/host/wayland_surface.h
@@ -74,14 +74,10 @@
   // See:
   // https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/viewporter/viewporter.xml
   // If |src_rect| is empty, the source rectangle is unset.
-  // Note this method does not send corresponding wayland requests until
-  // attaching the next buffer.
   void SetViewportSource(const gfx::RectF& src_rect);
 
   // Set the destination size of the associated wl_surface according to
   // |dest_size_px|, which should be in physical pixels.
-  // Note this method sends corresponding wayland requests immediately because
-  // it does not need a new buffer attach to take effect.
   void SetViewportDestination(const gfx::Size& dest_size_px);
 
   // Creates a wl_subsurface relating this surface and a parent surface,
diff --git a/ui/ozone/platform/wayland/host/wayland_window.cc b/ui/ozone/platform/wayland/host/wayland_window.cc
index 559b2ac..f7e6ae5d 100644
--- a/ui/ozone/platform/wayland/host/wayland_window.cc
+++ b/ui/ozone/platform/wayland/host/wayland_window.cc
@@ -14,7 +14,6 @@
 #include "ui/events/ozone/events_ozone.h"
 #include "ui/events/platform/platform_event_source.h"
 #include "ui/gfx/geometry/point_f.h"
-#include "ui/ozone/common/features.h"
 #include "ui/ozone/platform/wayland/common/wayland_util.h"
 #include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h"
 #include "ui/ozone/platform/wayland/host/wayland_connection.h"
@@ -40,7 +39,6 @@
                              WaylandConnection* connection)
     : delegate_(delegate),
       connection_(connection),
-      wayland_overlay_delegation_enabled_(IsWaylandOverlayDelegationEnabled()),
       accelerated_widget_(
           connection->wayland_window_manager()->AllocateAcceleratedWidget()) {}
 
@@ -49,10 +47,6 @@
 
   PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
 
-  if (wayland_overlay_delegation_enabled_) {
-    connection_->wayland_window_manager()->RemoveSubsurface(
-        GetWidget(), primary_subsurface_.get());
-  }
   for (const auto& widget_subsurface : wayland_subsurfaces()) {
     connection_->wayland_window_manager()->RemoveSubsurface(
         GetWidget(), widget_subsurface.get());
@@ -357,15 +351,6 @@
   if (!OnInitialize(std::move(properties)))
     return false;
 
-  if (wayland_overlay_delegation_enabled_) {
-    primary_subsurface_ =
-        std::make_unique<WaylandSubsurface>(connection_, this);
-    if (!primary_subsurface_->surface())
-      return false;
-    connection_->wayland_window_manager()->AddSubsurface(
-        GetWidget(), primary_subsurface_.get());
-  }
-
   connection_->ScheduleFlush();
 
   PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
@@ -545,10 +530,6 @@
 
   size_t above = (overlays.end() - split) - num_primary_planes;
   size_t below = split - overlays.begin();
-
-  if (overlays.front()->z_order == INT32_MIN)
-    --below;
-
   // Re-arrange the list of subsurfaces to fit the |overlays|. Request extra
   // subsurfaces if needed.
   if (!ArrangeSubsurfaceStack(above, below))
@@ -561,14 +542,12 @@
     auto overlay_iter = split - 1;
     for (auto iter = subsurface_stack_below_.begin();
          iter != subsurface_stack_below_.end(); ++iter, --overlay_iter) {
-      if (overlays.front()->z_order == INT32_MIN
-              ? overlay_iter >= ++overlays.begin()
-              : overlay_iter >= overlays.begin()) {
+      if (overlay_iter >= overlays.begin()) {
         WaylandSurface* reference_above = nullptr;
         if (overlay_iter == split - 1) {
           // It's possible that |overlays| does not contain primary plane, we
           // still want to place relative to the surface with z_order=0.
-          reference_above = primary_subsurface_->wayland_surface();
+          reference_above = root_surface();
         } else {
           reference_above = (*std::next(iter))->wayland_surface();
         }
@@ -597,7 +576,7 @@
         if (overlay_iter == split + num_primary_planes) {
           // It's possible that |overlays| does not contain primary plane, we
           // still want to place relative to the surface with z_order=0.
-          reference_below = primary_subsurface_->wayland_surface();
+          reference_below = root_surface();
         } else {
           reference_below = (*std::prev(iter))->wayland_surface();
         }
@@ -616,30 +595,12 @@
     }
   }
 
-  if (!wayland_overlay_delegation_enabled_) {
+  if (num_primary_planes) {
     connection_->buffer_manager_host()->CommitBufferInternal(
         root_surface(), (*split)->buffer_id, (*split)->damage_region,
         /*wait_for_frame_callback=*/true);
-    return true;
-  }
-
-  if (num_primary_planes) {
-    primary_subsurface_->ConfigureAndShowSurface(
-        (*split)->transform, (*split)->crop_rect, (*split)->bounds_rect,
-        (*split)->enable_blend, nullptr, nullptr);
-    connection_->buffer_manager_host()->CommitBufferInternal(
-        primary_subsurface_->wayland_surface(), (*split)->buffer_id,
-        (*split)->damage_region, /*wait_for_frame_callback=*/false);
-  }
-
-  root_surface_->SetViewportDestination(bounds_px_.size());
-  if (overlays.front()->z_order == INT32_MIN) {
-    connection_->buffer_manager_host()->CommitBufferInternal(
-        root_surface(), overlays.front()->buffer_id,
-        /*damage_region=*/gfx::Rect(0, 0, 1, 1),
-        /*wait_for_frame_callback=*/true);
   } else {
-    // Subsurfaces are set to sync, above surface configs will only take effect
+    // Subsurfaces are set to sync, above operations will only take effects
     // when root_surface is committed.
     connection_->buffer_manager_host()->CommitWithoutBufferInternal(
         root_surface(), /*wait_for_frame_callback=*/true);
diff --git a/ui/ozone/platform/wayland/host/wayland_window.h b/ui/ozone/platform/wayland/host/wayland_window.h
index 7e646f5f..c341ddb 100644
--- a/ui/ozone/platform/wayland/host/wayland_window.h
+++ b/ui/ozone/platform/wayland/host/wayland_window.h
@@ -59,9 +59,6 @@
   void UpdateBufferScale(bool update_bounds);
 
   WaylandSurface* root_surface() const { return root_surface_.get(); }
-  WaylandSubsurface* primary_subsurface() const {
-    return primary_subsurface_.get();
-  }
   const WidgetSubsurfaceSet& wayland_subsurfaces() const {
     return wayland_subsurfaces_;
   }
@@ -232,19 +229,13 @@
   WaylandWindow* parent_window_ = nullptr;
   WaylandWindow* child_window_ = nullptr;
 
-  // |root_surface_| is a surface for the opaque background. Its z-order is
-  // INT32_MIN.
   std::unique_ptr<WaylandSurface> root_surface_;
-  // |primary_subsurface| is the primary that shows the widget content.
-  std::unique_ptr<WaylandSubsurface> primary_subsurface_;
-  // Subsurfaces excluding the primary_subsurface
   WidgetSubsurfaceSet wayland_subsurfaces_;
-  bool wayland_overlay_delegation_enabled_;
 
   // The stack of sub-surfaces to take effect when Commit() is called.
   // |subsurface_stack_above_| refers to subsurfaces that are stacked above the
-  // primary.
-  // Subsurface at the front of the list is the closest to the primary.
+  // parent.
+  // Subsurface at the front of the list is the closest to the parent.
   std::list<WaylandSubsurface*> subsurface_stack_above_;
   std::list<WaylandSubsurface*> subsurface_stack_below_;
 
diff --git a/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
index ab143ca..14ca3fa 100644
--- a/ui/ozone/platform/wayland/ozone_platform_wayland.cc
+++ b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
@@ -22,7 +22,6 @@
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
 #include "ui/gfx/linux/client_native_pixmap_dmabuf.h"
 #include "ui/gfx/native_widget_types.h"
-#include "ui/ozone/common/features.h"
 #include "ui/ozone/platform/wayland/common/wayland_util.h"
 #include "ui/ozone/platform/wayland/gpu/drm_render_node_path_finder.h"
 #include "ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h"
@@ -66,6 +65,11 @@
 
 namespace {
 
+constexpr OzonePlatform::InitializedHostProperties
+    kWaylandInitializedHostProperties = {
+        /*supports_overlays=*/false,
+};
+
 class OzonePlatformWayland : public OzonePlatform {
  public:
   OzonePlatformWayland() { CHECK(features::IsUsingOzonePlatform()); }
@@ -232,13 +236,6 @@
       properties->ignore_screen_bounds_for_menus = true;
       properties->app_modal_dialogs_use_event_blocker = true;
 
-      // Primary planes can be transluscent due to underlay strategy. As a
-      // result Wayland server draws contents occluded by an accelerated widget.
-      // To prevent this, an opaque background image is stacked below the
-      // accelerated widget to occlude contents below.
-      properties->needs_background_image =
-          ui::IsWaylandOverlayDelegationEnabled();
-
       initialised = true;
     }
 
@@ -246,14 +243,7 @@
   }
 
   const InitializedHostProperties& GetInitializedHostProperties() override {
-    static base::NoDestructor<OzonePlatform::InitializedHostProperties>
-        properties;
-    static bool initialized = false;
-    if (!initialized) {
-      properties->supports_overlays = ui::IsWaylandOverlayDelegationEnabled();
-      initialized = true;
-    }
-    return *properties;
+    return kWaylandInitializedHostProperties;
   }
 
   void AddInterfaces(mojo::BinderMap* binders) override {
diff --git a/ui/ozone/platform/wayland/test/wayland_test.cc b/ui/ozone/platform/wayland/test/wayland_test.cc
index 8d01aba..b155af688f 100644
--- a/ui/ozone/platform/wayland/test/wayland_test.cc
+++ b/ui/ozone/platform/wayland/test/wayland_test.cc
@@ -10,7 +10,6 @@
 #include "ui/base/ui_base_features.h"
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
 #include "ui/events/ozone/layout/scoped_keyboard_layout_engine.h"
-#include "ui/ozone/common/features.h"
 #include "ui/ozone/platform/wayland/host/wayland_output_manager.h"
 #include "ui/ozone/platform/wayland/host/wayland_screen.h"
 #include "ui/ozone/platform/wayland/test/mock_surface.h"
@@ -53,8 +52,7 @@
   // that automatically through changes done to "variants", which is also
   // convenient to have locally so that we don't need to worry about that (it's
   // the Wayland DragAndDrop that relies on the feature).
-  feature_list_.InitWithFeatures(
-      {features::kUseOzonePlatform, ui::kWaylandOverlayDelegation}, {});
+  feature_list_.InitAndEnableFeature(features::kUseOzonePlatform);
   ASSERT_TRUE(features::IsUsingOzonePlatform());
 
   ASSERT_TRUE(server_.Start(GetParam()));
diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h
index e27cd90e..7737507 100644
--- a/ui/ozone/public/ozone_platform.h
+++ b/ui/ozone/public/ozone_platform.h
@@ -105,10 +105,6 @@
     // calculating bounds of menu windows.
     bool ignore_screen_bounds_for_menus = false;
 
-    // Wayland only: determines whether BufferQueue needs a background image to
-    // be stacked below an AcceleratedWidget to make a widget opaque.
-    bool needs_background_image = false;
-
     // If true, the platform shows and updates the drag image.
     bool platform_shows_drag_image = true;
 
diff --git a/ui/strings/translations/ui_strings_iw.xtb b/ui/strings/translations/ui_strings_iw.xtb
index 0915cdef..bc796f95 100644
--- a/ui/strings/translations/ui_strings_iw.xtb
+++ b/ui/strings/translations/ui_strings_iw.xtb
@@ -74,7 +74,7 @@
 <translation id="271033894570825754">חדש</translation>
 <translation id="2743387203779672305">העתקה ללוח</translation>
 <translation id="2749082172777216925"><ph name="APP_NAME_INFO" />,‏ <ph name="PRICE" /></translation>
-<translation id="2803313416453193357">פתח את התיקייה</translation>
+<translation id="2803313416453193357">פתיחת התיקייה</translation>
 <translation id="2824719307700604149">{YEARS,plural, =1{לפני שנה אחת}two{לפני שנתיים}many{לפני # שנים}other{לפני # שנים}}</translation>
 <translation id="2878511608894704031">מחיקת הכול</translation>
 <translation id="2907671656515444832">{DAYS,plural, =1{עוד יום אחד}two{עוד 2 ימים}many{עוד # ימים}other{עוד # ימים}}</translation>
@@ -185,10 +185,10 @@
 <translation id="6620110761915583480">שמור קובץ</translation>
 <translation id="6699343763173986273">הרצועה הבאה במדיה</translation>
 <translation id="6710213216561001401">הקודם</translation>
-<translation id="6786750046913594791">סגור את התיקייה</translation>
+<translation id="6786750046913594791">סגירת התיקייה</translation>
 <translation id="6808150112686056157">עצור מדיה</translation>
 <translation id="6845383723252244143">בחר תיקייה</translation>
-<translation id="6845533974506654842">לחץ</translation>
+<translation id="6845533974506654842">לחיצה</translation>
 <translation id="6863590663815976734">{HOURS,plural, =1{נותרה שעה אחת}two{נותרו שעתיים}many{נותרו # שעות}other{נותרו # שעות}}</translation>
 <translation id="688711909580084195">דף אינטרנט ללא כותרת</translation>
 <translation id="6907759265145635167"><ph name="QUANTITY" /> PB/s</translation>
diff --git a/ui/views/controls/button/button_unittest.cc b/ui/views/controls/button/button_unittest.cc
index acb8cf9..c67b614 100644
--- a/ui/views/controls/button/button_unittest.cc
+++ b/ui/views/controls/button/button_unittest.cc
@@ -70,9 +70,11 @@
   DISALLOW_COPY_AND_ASSIGN(TestContextMenuController);
 };
 
-class TestButton : public Button, public ButtonListener {
+class TestButton : public Button {
  public:
-  explicit TestButton(bool has_ink_drop_action_on_click) : Button(this) {
+  explicit TestButton(bool has_ink_drop_action_on_click)
+      : Button(base::BindRepeating([](bool* pressed) { *pressed = true; },
+                                   &pressed_)) {
     SetHasInkDropActionOnClick(has_ink_drop_action_on_click);
   }
 
@@ -84,13 +86,6 @@
     return custom_key_click_action_;
   }
 
-  void ButtonPressed(Button* sender, const ui::Event& event) override {
-    pressed_ = true;
-
-    if (!on_button_pressed_handler_.is_null())
-      on_button_pressed_handler_.Run();
-  }
-
   void OnClickCanceled(const ui::Event& event) override { canceled_ = true; }
 
   // Button:
@@ -103,19 +98,17 @@
     Button::RemoveInkDropLayer(ink_drop_layer);
   }
 
-  bool pressed() { return pressed_; }
-  bool canceled() { return canceled_; }
-  int ink_drop_layer_add_count() { return ink_drop_layer_add_count_; }
-  int ink_drop_layer_remove_count() { return ink_drop_layer_remove_count_; }
+  bool pressed() const { return pressed_; }
+  bool canceled() const { return canceled_; }
+  int ink_drop_layer_add_count() const { return ink_drop_layer_add_count_; }
+  int ink_drop_layer_remove_count() const {
+    return ink_drop_layer_remove_count_;
+  }
 
   void set_custom_key_click_action(KeyClickAction custom_key_click_action) {
     custom_key_click_action_ = custom_key_click_action;
   }
 
-  void set_on_button_pressed_handler(const base::RepeatingClosure& callback) {
-    on_button_pressed_handler_ = callback;
-  }
-
   void Reset() {
     pressed_ = false;
     canceled_ = false;
@@ -133,9 +126,6 @@
 
   KeyClickAction custom_key_click_action_ = KeyClickAction::kNone;
 
-  // If available, will be triggered when the button is pressed.
-  base::RepeatingClosure on_button_pressed_handler_;
-
   DISALLOW_COPY_AND_ASSIGN(TestButton);
 };
 
@@ -171,21 +161,6 @@
   DISALLOW_COPY_AND_ASSIGN(TestButtonObserver);
 };
 
-class TestButtonListener : public ButtonListener {
- public:
-  void ButtonPressed(Button* sender, const ui::Event& event) override {
-    pressed_ = true;
-    sender_ = sender;
-  }
-
-  bool pressed() const { return pressed_; }
-  Button* sender() const { return sender_; }
-
- private:
-  bool pressed_ = false;
-  Button* sender_ = nullptr;
-};
-
 TestInkDrop* AddTestInkDrop(TestButton* button) {
   auto owned_ink_drop = std::make_unique<TestInkDrop>();
   TestInkDrop* ink_drop = owned_ink_drop.get();
@@ -446,7 +421,7 @@
 // events will not revert the disabled state back to normal.
 // https://crbug.com/1084241.
 TEST_F(ButtonTest, GestureEventsRespectDisabledState) {
-  button()->set_on_button_pressed_handler(base::BindRepeating(
+  button()->SetCallback(base::BindRepeating(
       [](TestButton* button) { button->SetEnabled(false); }, button()));
 
   EXPECT_EQ(Button::STATE_NORMAL, button()->GetState());
@@ -754,8 +729,9 @@
 
 // Ensure PressedCallback is dynamically settable.
 TEST_F(ButtonTest, SetCallback) {
-  TestButtonListener listener;
-  button()->SetCallback(Button::PressedCallback(&listener, button()));
+  bool pressed = false;
+  button()->SetCallback(
+      base::BindRepeating([](bool* pressed) { *pressed = true; }, &pressed));
 
   const gfx::Point center(10, 10);
   button()->OnMousePressed(ui::MouseEvent(
@@ -765,8 +741,7 @@
   button()->OnMouseReleased(ui::MouseEvent(
       ui::ET_MOUSE_RELEASED, center, center, ui::EventTimeForNow(),
       ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
-  EXPECT_TRUE(listener.pressed());
-  EXPECT_EQ(button(), listener.sender());
+  EXPECT_TRUE(pressed);
 }
 
 // VisibilityTestButton tests to see if an ink drop or a layer has been added to
diff --git a/ui/views/controls/button/menu_button_controller.cc b/ui/views/controls/button/menu_button_controller.cc
index a61082d..f621f8b 100644
--- a/ui/views/controls/button/menu_button_controller.cc
+++ b/ui/views/controls/button/menu_button_controller.cc
@@ -90,14 +90,6 @@
   set_notify_action(ButtonController::NotifyAction::kOnPress);
 }
 
-MenuButtonController::MenuButtonController(
-    Button* button,
-    ButtonListener* listener,
-    std::unique_ptr<ButtonControllerDelegate> delegate)
-    : MenuButtonController(button,
-                           Button::PressedCallback(listener, button),
-                           std::move(delegate)) {}
-
 MenuButtonController::~MenuButtonController() = default;
 
 bool MenuButtonController::OnMousePressed(const ui::MouseEvent& event) {
@@ -239,7 +231,7 @@
     bool increment_pressed_lock_called = false;
     increment_pressed_lock_called_ = &increment_pressed_lock_called;
 
-    // Allow for ButtonPressed() to delete this.
+    // Allow for the button callback to delete this.
     auto ref = weak_factory_.GetWeakPtr();
 
     // TODO(pbos): Make sure we always propagate an event. This requires changes
diff --git a/ui/views/controls/button/menu_button_controller.h b/ui/views/controls/button/menu_button_controller.h
index ca4b346..a7129e6 100644
--- a/ui/views/controls/button/menu_button_controller.h
+++ b/ui/views/controls/button/menu_button_controller.h
@@ -42,9 +42,6 @@
   MenuButtonController(Button* button,
                        Button::PressedCallback callback,
                        std::unique_ptr<ButtonControllerDelegate> delegate);
-  MenuButtonController(Button* button,
-                       ButtonListener* listener,
-                       std::unique_ptr<ButtonControllerDelegate> delegate);
   ~MenuButtonController() override;
 
   // view::ButtonController
diff --git a/ui/views/controls/button/menu_button_unittest.cc b/ui/views/controls/button/menu_button_unittest.cc
index f06d6fc..2e3eb48 100644
--- a/ui/views/controls/button/menu_button_unittest.cc
+++ b/ui/views/controls/button/menu_button_unittest.cc
@@ -7,7 +7,6 @@
 #include <memory>
 #include <utility>
 
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
@@ -35,28 +34,45 @@
 
 namespace views {
 
-using test::InkDropHostViewTestApi;
-using test::TestInkDrop;
-
-// A MenuButton subclass that provides access to some MenuButton internals.
 class TestMenuButton : public MenuButton {
  public:
-  explicit TestMenuButton(ButtonListener* button_listener)
-      : MenuButton(button_listener, base::string16(ASCIIToUTF16("button"))) {}
-
+  TestMenuButton()
+      : TestMenuButton(base::BindRepeating(&TestMenuButton::ButtonPressed,
+                                           base::Unretained(this))) {}
+  explicit TestMenuButton(PressedCallback callback)
+      : MenuButton(std::move(callback),
+                   base::string16(ASCIIToUTF16("button"))) {}
+  TestMenuButton(const TestMenuButton&) = delete;
+  TestMenuButton& operator=(const TestMenuButton&) = delete;
   ~TestMenuButton() override = default;
 
-  void SetInkDrop(std::unique_ptr<InkDrop> ink_drop) {
-    InkDropHostViewTestApi(this).SetInkDrop(std::move(ink_drop));
+  bool clicked() const { return clicked_; }
+  Button::ButtonState last_state() const { return last_state_; }
+  ui::EventType last_event_type() const { return last_event_type_; }
+
+  void Reset() {
+    clicked_ = false;
+    last_state_ = Button::STATE_NORMAL;
+    last_event_type_ = ui::ET_UNKNOWN;
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(TestMenuButton);
+  void ButtonPressed(const ui::Event& event) {
+    clicked_ = true;
+    last_state_ = GetState();
+    last_event_type_ = event.type();
+  }
+
+  bool clicked_ = false;
+  Button::ButtonState last_state_ = Button::STATE_NORMAL;
+  ui::EventType last_event_type_ = ui::ET_UNKNOWN;
 };
 
 class MenuButtonTest : public ViewsTestBase {
  public:
   MenuButtonTest() = default;
+  MenuButtonTest(const MenuButtonTest&) = delete;
+  MenuButtonTest& operator=(const MenuButtonTest&) = delete;
   ~MenuButtonTest() override = default;
 
   void TearDown() override {
@@ -67,46 +83,16 @@
     ViewsTestBase::TearDown();
   }
 
+ protected:
   Widget* widget() { return widget_; }
   TestMenuButton* button() { return button_; }
   ui::test::EventGenerator* generator() { return generator_.get(); }
-
- protected:
-  TestInkDrop* ink_drop() { return ink_drop_; }
-
-  // Creates a MenuButton with no button listener.
-  void CreateMenuButtonWithNoListener() { CreateMenuButton(nullptr); }
-
-  // Creates a MenuButton with a ButtonListener. In this case, when the
-  // MenuButton is pushed, it notifies the ButtonListener to open a
-  // drop-down menu.
-  void CreateMenuButtonWithButtonListener(ButtonListener* button_listener) {
-    CreateMenuButton(button_listener);
-  }
+  test::TestInkDrop* ink_drop() { return ink_drop_; }
 
   gfx::Point GetOutOfButtonLocation() const {
     return gfx::Point(button_->x() - 1, button_->y() - 1);
   }
 
-  void CreateMenuButton(ButtonListener* button_listener) {
-    CreateWidget();
-    generator_ =
-        std::make_unique<ui::test::EventGenerator>(GetRootWindow(widget_));
-    // Set initial mouse location in a consistent way so that the menu button we
-    // are about to create initializes its hover state in a consistent manner.
-    generator_->set_current_screen_location(gfx::Point(10, 10));
-
-    button_ = widget_->SetContentsView(
-        std::make_unique<TestMenuButton>(button_listener));
-    button_->SetBoundsRect(gfx::Rect(0, 0, 200, 20));
-
-    ink_drop_ = new test::TestInkDrop();
-    test::InkDropHostViewTestApi(button_).SetInkDrop(
-        base::WrapUnique(ink_drop_));
-
-    widget_->Show();
-  }
-
   void CreateWidget() {
     DCHECK(!widget_);
 
@@ -117,75 +103,54 @@
     widget_->Init(std::move(params));
   }
 
-  Widget* widget_ = nullptr;
-  TestMenuButton* button_ = nullptr;
-  std::unique_ptr<ui::test::EventGenerator> generator_;
+  void ConfigureMenuButton(std::unique_ptr<TestMenuButton> button) {
+    CreateWidget();
+    generator_ =
+        std::make_unique<ui::test::EventGenerator>(GetRootWindow(widget_));
+    // Set initial mouse location in a consistent way so that the menu button we
+    // are about to create initializes its hover state in a consistent manner.
+    generator_->set_current_screen_location(gfx::Point(10, 10));
 
-  // Weak ptr, |button_| owns the instance.
-  TestInkDrop* ink_drop_ = nullptr;
+    button_ = widget_->SetContentsView(std::move(button));
+    button_->SetBoundsRect(gfx::Rect(0, 0, 200, 20));
 
-  DISALLOW_COPY_AND_ASSIGN(MenuButtonTest);
-};
+    auto ink_drop = std::make_unique<test::TestInkDrop>();
+    ink_drop_ = ink_drop.get();
+    test::InkDropHostViewTestApi(button_).SetInkDrop(std::move(ink_drop));
 
-class TestButtonListener : public ButtonListener {
- public:
-  TestButtonListener() = default;
-  ~TestButtonListener() override = default;
-
-  void ButtonPressed(Button* sender, const ui::Event& event) override {
-    last_sender_ = sender;
-    Button* button = Button::AsButton(sender);
-    DCHECK(button);
-    last_sender_state_ = button->GetState();
-    last_event_type_ = event.type();
+    widget_->Show();
   }
 
-  void Reset() {
-    last_sender_ = nullptr;
-    last_sender_state_ = Button::STATE_NORMAL;
-    last_event_type_ = ui::ET_UNKNOWN;
-  }
-
-  Button* last_sender() { return last_sender_; }
-  Button::ButtonState last_sender_GetState() { return last_sender_state_; }
-  ui::EventType last_event_type() { return last_event_type_; }
-
  private:
-  Button* last_sender_ = nullptr;
-  Button::ButtonState last_sender_state_ = Button::STATE_NORMAL;
-  ui::EventType last_event_type_ = ui::ET_UNKNOWN;
-
-  DISALLOW_COPY_AND_ASSIGN(TestButtonListener);
+  Widget* widget_ = nullptr;          // Owned by self.
+  TestMenuButton* button_ = nullptr;  // Owned by |widget_|.
+  std::unique_ptr<ui::test::EventGenerator> generator_;
+  test::TestInkDrop* ink_drop_ = nullptr;  // Owned by |button_|.
 };
 
-// A ButtonListener that will acquire a PressedLock in the
-// ButtonPressed() method and optionally release it as well.
-class PressStateButtonListener : public ButtonListener {
+// A Button that will acquire a PressedLock in the pressed callback and
+// optionally release it as well.
+class PressStateButton : public TestMenuButton {
  public:
-  explicit PressStateButtonListener(bool release_lock)
-      : menu_button_(nullptr), release_lock_(release_lock) {}
-
-  ~PressStateButtonListener() override = default;
-
-  void set_menu_button(MenuButton* menu_button) { menu_button_ = menu_button; }
-
-  void ButtonPressed(Button* source, const ui::Event& event) override {
-    pressed_lock_ = menu_button_->button_controller()->TakeLock();
-    if (release_lock_)
-      pressed_lock_.reset();
-  }
+  explicit PressStateButton(bool release_lock)
+      : TestMenuButton(base::BindRepeating(&PressStateButton::ButtonPressed,
+                                           base::Unretained(this))),
+        release_lock_(release_lock) {}
+  PressStateButton(const PressStateButton&) = delete;
+  PressStateButton& operator=(const PressStateButton&) = delete;
+  ~PressStateButton() override = default;
 
   void ReleasePressedLock() { pressed_lock_.reset(); }
 
  private:
-  MenuButton* menu_button_;
+  void ButtonPressed() {
+    pressed_lock_ = button_controller()->TakeLock();
+    if (release_lock_)
+      ReleasePressedLock();
+  }
 
-  std::unique_ptr<MenuButtonController::PressedLock> pressed_lock_;
-
-  // The |pressed_lock_| will be released when true.
   bool release_lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(PressStateButtonListener);
+  std::unique_ptr<MenuButtonController::PressedLock> pressed_lock_;
 };
 
 // Basic implementation of a DragController, to test input behaviour for
@@ -193,6 +158,8 @@
 class TestDragController : public DragController {
  public:
   TestDragController() = default;
+  TestDragController(const TestDragController&) = delete;
+  TestDragController& operator=(const TestDragController&) = delete;
   ~TestDragController() override = default;
 
   void WriteDragDataForView(View* sender,
@@ -208,9 +175,6 @@
                            const gfx::Point& p) override {
     return true;
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestDragController);
 };
 
 #if defined(USE_AURA)
@@ -221,6 +185,8 @@
                            public ui::EventHandler {
  public:
   TestDragDropClient();
+  TestDragDropClient(const TestDragDropClient&) = delete;
+  TestDragDropClient& operator=(const TestDragDropClient&) = delete;
   ~TestDragDropClient() override;
 
   // aura::client::DragDropClient:
@@ -245,8 +211,6 @@
 
   // Target window where drag operations are occurring.
   aura::Window* target_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(TestDragDropClient);
 };
 
 TestDragDropClient::TestDragDropClient() = default;
@@ -292,77 +256,50 @@
 }
 #endif  // defined(USE_AURA)
 
-class TestShowSiblingButtonListener : public ButtonListener {
- public:
-  TestShowSiblingButtonListener() = default;
-  ~TestShowSiblingButtonListener() override = default;
-
-  void ButtonPressed(Button* source, const ui::Event& event) override {
-    // The MenuButton itself doesn't set the PRESSED state during Activate() or
-    // ButtonPressed(). That should be handled by the MenuController or,
-    // if no menu is shown, the listener.
-    EXPECT_EQ(Button::STATE_HOVERED, source->GetState());
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestShowSiblingButtonListener);
-};
-
-// Tests if the listener is notified correctly when a mouse click happens on a
-// MenuButton that has a ButtonListener.
+// Tests if the callback is called correctly when a mouse click happens on a
+// MenuButton.
 TEST_F(MenuButtonTest, ActivateDropDownOnMouseClick) {
-  TestButtonListener button_listener;
-  CreateMenuButtonWithButtonListener(&button_listener);
+  ConfigureMenuButton(std::make_unique<TestMenuButton>());
 
   generator()->ClickLeftButton();
 
-  // Check that MenuButton has notified the listener, while it was in pressed
-  // state.
-  EXPECT_EQ(button(), button_listener.last_sender());
-  EXPECT_EQ(Button::STATE_HOVERED, button_listener.last_sender_GetState());
+  EXPECT_TRUE(button()->clicked());
+  EXPECT_EQ(Button::STATE_HOVERED, button()->last_state());
 }
 
 TEST_F(MenuButtonTest, ActivateOnKeyPress) {
-  TestButtonListener button_listener;
-  CreateMenuButtonWithButtonListener(&button_listener);
+  ConfigureMenuButton(std::make_unique<TestMenuButton>());
 
-  EXPECT_EQ(nullptr, button_listener.last_sender());
+  EXPECT_FALSE(button()->clicked());
   button()->OnKeyPressed(ui::KeyEvent(
       ui::ET_KEY_PRESSED, ui::KeyboardCode::VKEY_SPACE, ui::DomCode::SPACE, 0));
-  EXPECT_EQ(button(), button_listener.last_sender());
+  EXPECT_TRUE(button()->clicked());
 
-  button_listener.Reset();
-  EXPECT_EQ(nullptr, button_listener.last_sender());
+  button()->Reset();
+  EXPECT_FALSE(button()->clicked());
 
   button()->OnKeyPressed(ui::KeyEvent(ui::ET_KEY_PRESSED,
                                       ui::KeyboardCode::VKEY_RETURN,
                                       ui::DomCode::ENTER, 0));
-  if (PlatformStyle::kReturnClicksFocusedControl) {
-    EXPECT_EQ(button(), button_listener.last_sender());
-  } else {
-    EXPECT_EQ(nullptr, button_listener.last_sender());
-  }
+  EXPECT_EQ(PlatformStyle::kReturnClicksFocusedControl, button()->clicked());
 }
 
 // Tests that the ink drop center point is set from the mouse click point.
 TEST_F(MenuButtonTest, InkDropCenterSetFromClick) {
-  TestButtonListener button_listener;
-  CreateMenuButtonWithButtonListener(&button_listener);
+  ConfigureMenuButton(std::make_unique<TestMenuButton>());
 
   gfx::Point click_point(6, 8);
   generator()->MoveMouseTo(click_point);
   generator()->ClickLeftButton();
 
-  EXPECT_EQ(button(), button_listener.last_sender());
-  EXPECT_EQ(
-      click_point,
-      InkDropHostViewTestApi(button()).GetInkDropCenterBasedOnLastEvent());
+  EXPECT_TRUE(button()->clicked());
+  EXPECT_EQ(click_point, test::InkDropHostViewTestApi(button())
+                             .GetInkDropCenterBasedOnLastEvent());
 }
 
 // Tests that the ink drop center point is set from the PressedLock constructor.
 TEST_F(MenuButtonTest, InkDropCenterSetFromClickWithPressedLock) {
-  TestButtonListener button_listener;
-  CreateMenuButtonWithButtonListener(&button_listener);
+  ConfigureMenuButton(std::make_unique<TestMenuButton>());
 
   gfx::Point click_point(11, 7);
   ui::MouseEvent click_event(ui::EventType::ET_MOUSE_PRESSED, click_point,
@@ -371,22 +308,21 @@
                                                  false, &click_event);
 
   EXPECT_EQ(Button::STATE_PRESSED, button()->GetState());
-  EXPECT_EQ(
-      click_point,
-      InkDropHostViewTestApi(button()).GetInkDropCenterBasedOnLastEvent());
+  EXPECT_EQ(click_point, test::InkDropHostViewTestApi(button())
+                             .GetInkDropCenterBasedOnLastEvent());
 }
 
 // Test that the MenuButton stays pressed while there are any PressedLocks.
 TEST_F(MenuButtonTest, ButtonStateForMenuButtonsWithPressedLocks) {
-  CreateMenuButtonWithNoListener();
+  ConfigureMenuButton(std::make_unique<TestMenuButton>());
 
   // Move the mouse over the button; the button should be in a hovered state.
   generator()->MoveMouseTo(gfx::Point(10, 10));
   EXPECT_EQ(Button::STATE_HOVERED, button()->GetState());
 
   // Introduce a PressedLock, which should make the button pressed.
-  std::unique_ptr<MenuButtonController::PressedLock> pressed_lock1(
-      new MenuButtonController::PressedLock(button()->button_controller()));
+  auto pressed_lock1 = std::make_unique<MenuButtonController::PressedLock>(
+      button()->button_controller());
   EXPECT_EQ(Button::STATE_PRESSED, button()->GetState());
 
   // Even if we move the mouse outside of the button, it should remain pressed.
@@ -394,8 +330,8 @@
   EXPECT_EQ(Button::STATE_PRESSED, button()->GetState());
 
   // Creating a new lock should obviously keep the button pressed.
-  std::unique_ptr<MenuButtonController::PressedLock> pressed_lock2(
-      new MenuButtonController::PressedLock(button()->button_controller()));
+  auto pressed_lock2 = std::make_unique<MenuButtonController::PressedLock>(
+      button()->button_controller());
   EXPECT_EQ(Button::STATE_PRESSED, button()->GetState());
 
   // The button should remain pressed while any locks are active.
@@ -436,37 +372,24 @@
   EXPECT_EQ(Button::STATE_NORMAL, button()->GetState());
 }
 
-// Test that if a sibling menu is shown, the original menu button releases its
-// PressedLock.
-TEST_F(MenuButtonTest, PressedStateWithSiblingMenu) {
-  TestShowSiblingButtonListener listener;
-  CreateMenuButtonWithButtonListener(&listener);
-
-  // Move the mouse over the button; the button should be in a hovered state.
-  generator()->MoveMouseTo(gfx::Point(10, 10));
-  EXPECT_EQ(Button::STATE_HOVERED, button()->GetState());
-  generator()->ClickLeftButton();
-  // Test is continued in TestShowSiblingButtonListener::ButtonPressed().
-}
-
 // Test that the MenuButton does not become pressed if it can be dragged, until
 // a release occurs.
 TEST_F(MenuButtonTest, DraggableMenuButtonActivatesOnRelease) {
-  TestButtonListener button_listener;
-  CreateMenuButtonWithButtonListener(&button_listener);
+  ConfigureMenuButton(std::make_unique<TestMenuButton>());
   TestDragController drag_controller;
   button()->set_drag_controller(&drag_controller);
 
   generator()->PressLeftButton();
-  EXPECT_EQ(nullptr, button_listener.last_sender());
+  EXPECT_FALSE(button()->clicked());
 
   generator()->ReleaseLeftButton();
-  EXPECT_EQ(button(), button_listener.last_sender());
-  EXPECT_EQ(Button::STATE_HOVERED, button_listener.last_sender_GetState());
+  EXPECT_TRUE(button()->clicked());
+  EXPECT_EQ(Button::STATE_HOVERED, button()->last_state());
 }
 
-TEST_F(MenuButtonTest, InkDropStateForMenuButtonActivationsWithoutListener) {
-  CreateMenuButtonWithNoListener();
+TEST_F(MenuButtonTest, InkDropStateForMenuButtonActivationsWithoutCallback) {
+  ConfigureMenuButton(
+      std::make_unique<TestMenuButton>(Button::PressedCallback()));
   ink_drop()->AnimateToState(InkDropState::ACTION_PENDING);
   button()->Activate(nullptr);
 
@@ -474,9 +397,8 @@
 }
 
 TEST_F(MenuButtonTest,
-       InkDropStateForMenuButtonActivationsWithListenerThatDoesntAcquireALock) {
-  TestButtonListener button_listener;
-  CreateMenuButtonWithButtonListener(&button_listener);
+       InkDropStateForMenuButtonActivationsWithCallbackThatDoesntAcquireALock) {
+  ConfigureMenuButton(std::make_unique<TestMenuButton>());
   button()->Activate(nullptr);
 
   EXPECT_EQ(InkDropState::ACTION_TRIGGERED,
@@ -485,35 +407,31 @@
 
 TEST_F(
     MenuButtonTest,
-    InkDropStateForMenuButtonActivationsWithListenerThatDontReleaseAllLocks) {
-  PressStateButtonListener button_listener(false);
-  CreateMenuButtonWithButtonListener(&button_listener);
-  button_listener.set_menu_button(button());
+    InkDropStateForMenuButtonActivationsWithCallbackThatDoesntReleaseAllLocks) {
+  ConfigureMenuButton(std::make_unique<PressStateButton>(false));
   button()->Activate(nullptr);
 
   EXPECT_EQ(InkDropState::ACTIVATED, ink_drop()->GetTargetInkDropState());
 }
 
 TEST_F(MenuButtonTest,
-       InkDropStateForMenuButtonActivationsWithListenerThatReleaseAllLocks) {
-  PressStateButtonListener button_listener(true);
-  CreateMenuButtonWithButtonListener(&button_listener);
-  button_listener.set_menu_button(button());
+       InkDropStateForMenuButtonActivationsWithCallbackThatReleasesAllLocks) {
+  ConfigureMenuButton(std::make_unique<PressStateButton>(true));
   button()->Activate(nullptr);
 
   EXPECT_EQ(InkDropState::DEACTIVATED, ink_drop()->GetTargetInkDropState());
 }
 
 TEST_F(MenuButtonTest, InkDropStateForMenuButtonsWithPressedLocks) {
-  CreateMenuButtonWithNoListener();
+  ConfigureMenuButton(std::make_unique<TestMenuButton>());
 
-  std::unique_ptr<MenuButtonController::PressedLock> pressed_lock1(
-      new MenuButtonController::PressedLock(button()->button_controller()));
+  auto pressed_lock1 = std::make_unique<MenuButtonController::PressedLock>(
+      button()->button_controller());
 
   EXPECT_EQ(InkDropState::ACTIVATED, ink_drop()->GetTargetInkDropState());
 
-  std::unique_ptr<MenuButtonController::PressedLock> pressed_lock2(
-      new MenuButtonController::PressedLock(button()->button_controller()));
+  auto pressed_lock2 = std::make_unique<MenuButtonController::PressedLock>(
+      button()->button_controller());
 
   EXPECT_EQ(InkDropState::ACTIVATED, ink_drop()->GetTargetInkDropState());
 
@@ -527,16 +445,16 @@
 // Verifies only one ink drop animation is triggered when multiple PressedLocks
 // are attached to a MenuButton.
 TEST_F(MenuButtonTest, OneInkDropAnimationForReentrantPressedLocks) {
-  CreateMenuButtonWithNoListener();
+  ConfigureMenuButton(std::make_unique<TestMenuButton>());
 
-  std::unique_ptr<MenuButtonController::PressedLock> pressed_lock1(
-      new MenuButtonController::PressedLock(button()->button_controller()));
+  auto pressed_lock1 = std::make_unique<MenuButtonController::PressedLock>(
+      button()->button_controller());
 
   EXPECT_EQ(InkDropState::ACTIVATED, ink_drop()->GetTargetInkDropState());
   ink_drop()->AnimateToState(InkDropState::ACTION_PENDING);
 
-  std::unique_ptr<MenuButtonController::PressedLock> pressed_lock2(
-      new MenuButtonController::PressedLock(button()->button_controller()));
+  auto pressed_lock2 = std::make_unique<MenuButtonController::PressedLock>(
+      button()->button_controller());
 
   EXPECT_EQ(InkDropState::ACTION_PENDING, ink_drop()->GetTargetInkDropState());
 }
@@ -545,8 +463,7 @@
 // before another Activation occurs.
 TEST_F(MenuButtonTest,
        InkDropStateForMenuButtonWithPressedLockBeforeActivation) {
-  TestButtonListener button_listener;
-  CreateMenuButtonWithButtonListener(&button_listener);
+  ConfigureMenuButton(std::make_unique<TestMenuButton>());
   MenuButtonController::PressedLock lock(button()->button_controller());
 
   button()->Activate(nullptr);
@@ -559,8 +476,7 @@
 // Tests that the MenuButton does not become pressed if it can be dragged, and a
 // DragDropClient is processing the events.
 TEST_F(MenuButtonTest, DraggableMenuButtonDoesNotActivateOnDrag) {
-  TestButtonListener button_listener;
-  CreateMenuButtonWithButtonListener(&button_listener);
+  ConfigureMenuButton(std::make_unique<TestMenuButton>());
   TestDragController drag_controller;
   button()->set_drag_controller(&drag_controller);
 
@@ -570,8 +486,8 @@
                                 ui::EventTarget::Priority::kSystem);
 
   generator()->DragMouseBy(10, 0);
-  EXPECT_EQ(nullptr, button_listener.last_sender());
-  EXPECT_EQ(Button::STATE_NORMAL, button_listener.last_sender_GetState());
+  EXPECT_FALSE(button()->clicked());
+  EXPECT_EQ(Button::STATE_NORMAL, button()->last_state());
   button()->RemovePreTargetHandler(&drag_client);
 }
 
@@ -583,8 +499,7 @@
 // Tests if the listener is notified correctly when a gesture tap happens on a
 // MenuButton that has a ButtonListener.
 TEST_F(MenuButtonTest, ActivateDropDownOnGestureTap) {
-  TestButtonListener button_listener;
-  CreateMenuButtonWithButtonListener(&button_listener);
+  ConfigureMenuButton(std::make_unique<TestMenuButton>());
 
   // Move the mouse outside the menu button so that it doesn't impact the
   // button state.
@@ -595,45 +510,41 @@
 
   // Check that MenuButton has notified the listener, while it was in pressed
   // state.
-  EXPECT_EQ(button(), button_listener.last_sender());
-  EXPECT_EQ(Button::STATE_HOVERED, button_listener.last_sender_GetState());
+  EXPECT_TRUE(button()->clicked());
+  EXPECT_EQ(Button::STATE_HOVERED, button()->last_state());
 
-  // The button should go back to it's normal state since the gesture ended.
+  // The button should go back to its normal state since the gesture ended.
   EXPECT_EQ(Button::STATE_NORMAL, button()->GetState());
 }
 
 // Tests that the button enters a hovered state upon a tap down, before becoming
 // pressed at activation.
 TEST_F(MenuButtonTest, TouchFeedbackDuringTap) {
-  TestButtonListener button_listener;
-  CreateMenuButtonWithButtonListener(&button_listener);
+  ConfigureMenuButton(std::make_unique<TestMenuButton>());
   generator()->PressTouch();
   EXPECT_EQ(Button::STATE_HOVERED, button()->GetState());
 
   generator()->ReleaseTouch();
-  EXPECT_EQ(Button::STATE_HOVERED, button_listener.last_sender_GetState());
+  EXPECT_EQ(Button::STATE_HOVERED, button()->last_state());
 }
 
 // Tests that a move event that exits the button returns it to the normal state,
 // and that the button did not activate the listener.
 TEST_F(MenuButtonTest, TouchFeedbackDuringTapCancel) {
-  TestButtonListener button_listener;
-  CreateMenuButtonWithButtonListener(&button_listener);
+  ConfigureMenuButton(std::make_unique<TestMenuButton>());
   generator()->PressTouch();
   EXPECT_EQ(Button::STATE_HOVERED, button()->GetState());
 
   generator()->MoveTouch(gfx::Point(10, 30));
   generator()->ReleaseTouch();
   EXPECT_EQ(Button::STATE_NORMAL, button()->GetState());
-  EXPECT_EQ(nullptr, button_listener.last_sender());
+  EXPECT_FALSE(button()->clicked());
 }
 
 #endif  // !defined(OS_APPLE) || defined(USE_AURA)
 
 TEST_F(MenuButtonTest, InkDropHoverWhenShowingMenu) {
-  PressStateButtonListener button_listener(false);
-  CreateMenuButtonWithButtonListener(&button_listener);
-  button_listener.set_menu_button(button());
+  ConfigureMenuButton(std::make_unique<PressStateButton>(false));
 
   generator()->MoveMouseTo(GetOutOfButtonLocation());
   EXPECT_FALSE(ink_drop()->is_hovered());
@@ -646,62 +557,44 @@
 }
 
 TEST_F(MenuButtonTest, InkDropIsHoveredAfterDismissingMenuWhenMouseOverButton) {
-  PressStateButtonListener button_listener(false);
-  CreateMenuButtonWithButtonListener(&button_listener);
-  button_listener.set_menu_button(button());
+  auto press_state_button = std::make_unique<PressStateButton>(false);
+  auto* test_button = press_state_button.get();
+  ConfigureMenuButton(std::move(press_state_button));
 
   generator()->MoveMouseTo(button()->bounds().CenterPoint());
   generator()->PressLeftButton();
   EXPECT_FALSE(ink_drop()->is_hovered());
-  button_listener.ReleasePressedLock();
+  test_button->ReleasePressedLock();
 
   EXPECT_TRUE(ink_drop()->is_hovered());
 }
 
 TEST_F(MenuButtonTest,
        InkDropIsntHoveredAfterDismissingMenuWhenMouseOutsideButton) {
-  PressStateButtonListener button_listener(false);
-  CreateMenuButtonWithButtonListener(&button_listener);
-  button_listener.set_menu_button(button());
+  auto press_state_button = std::make_unique<PressStateButton>(false);
+  auto* test_button = press_state_button.get();
+  ConfigureMenuButton(std::move(press_state_button));
 
   generator()->MoveMouseTo(button()->bounds().CenterPoint());
   generator()->PressLeftButton();
   generator()->MoveMouseTo(GetOutOfButtonLocation());
-  button_listener.ReleasePressedLock();
+  test_button->ReleasePressedLock();
 
   EXPECT_FALSE(ink_drop()->is_hovered());
 }
 
-class DestroyButtonInGestureListener : public ButtonListener {
- public:
-  DestroyButtonInGestureListener() {
-    menu_button_ = std::make_unique<MenuButton>();
-  }
-
-  ~DestroyButtonInGestureListener() override = default;
-
-  MenuButton* menu_button() { return menu_button_.get(); }
-
- private:
-  // ButtonListener:
-  void ButtonPressed(Button* source, const ui::Event& event) override {
-    menu_button_.reset();
-  }
-
-  std::unique_ptr<MenuButton> menu_button_;
-
-  DISALLOW_COPY_AND_ASSIGN(DestroyButtonInGestureListener);
-};
-
-// This test ensures there isn't a UAF in MenuButton::OnGestureEvent() if
-// the ButtonListener::ButtonPressed() deletes the MenuButton.
+// This test ensures there isn't a UAF in MenuButton::OnGestureEvent() if the
+// button callback deletes the MenuButton.
 TEST_F(MenuButtonTest, DestroyButtonInGesture) {
-  DestroyButtonInGestureListener listener;
+  std::unique_ptr<TestMenuButton> test_menu_button =
+      std::make_unique<TestMenuButton>(base::BindRepeating(
+          [](std::unique_ptr<TestMenuButton>* button) { button->reset(); },
+          &test_menu_button));
+  ConfigureMenuButton(std::move(test_menu_button));
+
   ui::GestureEvent gesture_event(0, 0, 0, base::TimeTicks::Now(),
                                  ui::GestureEventDetails(ui::ET_GESTURE_TAP));
-  CreateWidget();
-  widget_->SetContentsView(listener.menu_button());
-  listener.menu_button()->OnGestureEvent(&gesture_event);
+  button()->OnGestureEvent(&gesture_event);
 }
 
 }  // namespace views
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc
index c2073398..094496e 100644
--- a/ui/views/controls/combobox/combobox.cc
+++ b/ui/views/controls/combobox/combobox.cc
@@ -68,7 +68,8 @@
 // The transparent button which holds a button state but is not rendered.
 class TransparentButton : public Button {
  public:
-  explicit TransparentButton(ButtonListener* listener) : Button(listener) {
+  explicit TransparentButton(PressedCallback callback)
+      : Button(std::move(callback)) {
     SetFocusBehavior(FocusBehavior::NEVER);
     button_controller()->set_notify_action(
         ButtonController::NotifyAction::kOnPress);
@@ -243,7 +244,9 @@
 Combobox::Combobox(ui::ComboboxModel* model, int text_context, int text_style)
     : text_context_(text_context),
       text_style_(text_style),
-      arrow_button_(new TransparentButton(this)) {
+      arrow_button_(new TransparentButton(
+          base::BindRepeating(&Combobox::ArrowButtonPressed,
+                              base::Unretained(this)))) {
   SetModel(model);
 #if defined(OS_APPLE)
   SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
@@ -551,16 +554,6 @@
   return View::HandleAccessibleAction(action_data);
 }
 
-void Combobox::ButtonPressed(Button* sender, const ui::Event& event) {
-  if (!GetEnabled())
-    return;
-
-  // TODO(hajimehoshi): Fix the problem that the arrow button blinks when
-  // cliking this while the dropdown menu is opened.
-  if ((base::TimeTicks::Now() - closed_time_) > kMinimumTimeBetweenButtonClicks)
-    ShowDropDownMenu(ui::GetMenuSourceTypeForEvent(event));
-}
-
 void Combobox::OnComboboxModelChanged(ui::ComboboxModel* model) {
   DCHECK_EQ(model_, model);
 
@@ -577,6 +570,14 @@
   SchedulePaint();
 }
 
+const base::RepeatingClosure& Combobox::GetCallback() const {
+  return callback_;
+}
+
+const std::unique_ptr<ui::ComboboxModel>& Combobox::GetOwnedModel() const {
+  return owned_model_;
+}
+
 void Combobox::UpdateBorder() {
   std::unique_ptr<FocusableBorder> border(new FocusableBorder());
   if (invalid_)
@@ -640,6 +641,16 @@
   PaintComboboxArrow(text_color, arrow_bounds, canvas);
 }
 
+void Combobox::ArrowButtonPressed(const ui::Event& event) {
+  if (!GetEnabled())
+    return;
+
+  // TODO(hajimehoshi): Fix the problem that the arrow button blinks when
+  // cliking this while the dropdown menu is opened.
+  if ((base::TimeTicks::Now() - closed_time_) > kMinimumTimeBetweenButtonClicks)
+    ShowDropDownMenu(ui::GetMenuSourceTypeForEvent(event));
+}
+
 void Combobox::ShowDropDownMenu(ui::MenuSourceType source_type) {
   constexpr int kMenuBorderWidthTop = 1;
   // Menu's requested position's width should be the same as local bounds so the
@@ -717,6 +728,9 @@
 }
 
 BEGIN_METADATA(Combobox, View)
+ADD_PROPERTY_METADATA(base::RepeatingClosure, Callback)
+ADD_PROPERTY_METADATA(std::unique_ptr<ui::ComboboxModel>, OwnedModel)
+ADD_PROPERTY_METADATA(ui::ComboboxModel*, Model)
 ADD_PROPERTY_METADATA(int, SelectedIndex)
 ADD_PROPERTY_METADATA(bool, Invalid)
 ADD_PROPERTY_METADATA(bool, SizeToLargestLabel)
diff --git a/ui/views/controls/combobox/combobox.h b/ui/views/controls/combobox/combobox.h
index aab703d..515f7e9 100644
--- a/ui/views/controls/combobox/combobox.h
+++ b/ui/views/controls/combobox/combobox.h
@@ -40,7 +40,6 @@
 // Combobox has two distinct parts, the drop down arrow and the text.
 class VIEWS_EXPORT Combobox : public View,
                               public PrefixDelegate,
-                              public ButtonListener,
                               public ui::ComboboxModelObserver {
  public:
   METADATA_HEADER(Combobox);
@@ -78,6 +77,7 @@
   bool SelectValue(const base::string16& value);
 
   void SetOwnedModel(std::unique_ptr<ui::ComboboxModel> model);
+
   void SetModel(ui::ComboboxModel* model);
   ui::ComboboxModel* GetModel() const { return model_; }
 
@@ -118,13 +118,14 @@
   void SetSelectedRow(int row) override;
   base::string16 GetTextForRow(int row) override;
 
-  // Overridden from ButtonListener:
-  void ButtonPressed(Button* sender, const ui::Event& event) override;
-
  protected:
   // Overridden from ComboboxModelObserver:
   void OnComboboxModelChanged(ui::ComboboxModel* model) override;
 
+  // Getters to be used by metadata.
+  const base::RepeatingClosure& GetCallback() const;
+  const std::unique_ptr<ui::ComboboxModel>& GetOwnedModel() const;
+
  private:
   friend class test::ComboboxTestApi;
 
@@ -139,6 +140,9 @@
   // Draws the selected value of the drop down list
   void PaintIconAndText(gfx::Canvas* canvas);
 
+  // Opens the dropdown menu in response to |event|.
+  void ArrowButtonPressed(const ui::Event& event);
+
   // Show the drop down list
   void ShowDropDownMenu(ui::MenuSourceType source_type);
 
@@ -226,6 +230,9 @@
 };
 
 BEGIN_VIEW_BUILDER(VIEWS_EXPORT, Combobox, View)
+VIEW_BUILDER_PROPERTY(base::RepeatingClosure, Callback)
+VIEW_BUILDER_PROPERTY(std::unique_ptr<ui::ComboboxModel>, OwnedModel)
+VIEW_BUILDER_PROPERTY(ui::ComboboxModel*, Model)
 VIEW_BUILDER_PROPERTY(int, SelectedIndex)
 VIEW_BUILDER_PROPERTY(bool, Invalid)
 VIEW_BUILDER_PROPERTY(bool, SizeToLargestLabel)
diff --git a/ui/views/controls/editable_combobox/editable_combobox.cc b/ui/views/controls/editable_combobox/editable_combobox.cc
index 0225da4..b9203707 100644
--- a/ui/views/controls/editable_combobox/editable_combobox.cc
+++ b/ui/views/controls/editable_combobox/editable_combobox.cc
@@ -64,7 +64,7 @@
 
 class Arrow : public Button {
  public:
-  explicit Arrow(ButtonListener* listener) : Button(listener) {
+  explicit Arrow(PressedCallback callback) : Button(std::move(callback)) {
     // Similar to Combobox's TransparentButton.
     SetFocusBehavior(FocusBehavior::NEVER);
     button_controller()->set_notify_action(
@@ -333,7 +333,8 @@
     textfield_->SetExtraInsets(gfx::Insets(
         /*top=*/0, /*left=*/0, /*bottom=*/0,
         /*right=*/kComboboxArrowContainerWidth - kComboboxArrowPaddingWidth));
-    arrow_ = AddChildView(std::make_unique<Arrow>(this));
+    arrow_ = AddChildView(std::make_unique<Arrow>(base::BindRepeating(
+        &EditableCombobox::ArrowButtonPressed, base::Unretained(this))));
   }
   SetLayoutManager(std::make_unique<views::FillLayout>());
 }
@@ -446,14 +447,6 @@
   CloseMenu();
 }
 
-void EditableCombobox::ButtonPressed(Button* sender, const ui::Event& event) {
-  textfield_->RequestFocus();
-  if (menu_runner_ && menu_runner_->IsRunning())
-    CloseMenu();
-  else
-    ShowDropDownMenu(ui::GetMenuSourceTypeForEvent(event));
-}
-
 void EditableCombobox::OnLayoutIsAnimatingChanged(
     views::AnimatingLayoutManager* source,
     bool is_animating) {
@@ -496,6 +489,14 @@
   menu_model_->UpdateItemsShown();
 }
 
+void EditableCombobox::ArrowButtonPressed(const ui::Event& event) {
+  textfield_->RequestFocus();
+  if (menu_runner_ && menu_runner_->IsRunning())
+    CloseMenu();
+  else
+    ShowDropDownMenu(ui::GetMenuSourceTypeForEvent(event));
+}
+
 void EditableCombobox::ShowDropDownMenu(ui::MenuSourceType source_type) {
   constexpr int kMenuBorderWidthTop = 1;
 
diff --git a/ui/views/controls/editable_combobox/editable_combobox.h b/ui/views/controls/editable_combobox/editable_combobox.h
index 5b758af..a87863d 100644
--- a/ui/views/controls/editable_combobox/editable_combobox.h
+++ b/ui/views/controls/editable_combobox/editable_combobox.h
@@ -14,7 +14,6 @@
 #include "base/strings/string16.h"
 #include "build/build_config.h"
 #include "ui/base/ui_base_types.h"
-#include "ui/views/controls/button/button.h"
 #include "ui/views/controls/textfield/textfield_controller.h"
 #include "ui/views/layout/animating_layout_manager.h"
 #include "ui/views/style/typography.h"
@@ -33,6 +32,7 @@
 }  // namespace ui
 
 namespace views {
+class Button;
 class EditableComboboxMenuModel;
 class EditableComboboxPreTargetHandler;
 class MenuRunner;
@@ -43,7 +43,6 @@
     : public View,
       public TextfieldController,
       public ViewObserver,
-      public ButtonListener,
       public views::AnimatingLayoutManager::Observer {
  public:
   METADATA_HEADER(EditableCombobox);
@@ -123,6 +122,9 @@
   // Notifies listener of new content and updates the menu items to show.
   void HandleNewContent(const base::string16& new_content);
 
+  // Toggles the dropdown menu in response to |event|.
+  void ArrowButtonPressed(const ui::Event& event);
+
   // Shows the drop-down menu.
   void ShowDropDownMenu(ui::MenuSourceType source_type = ui::MENU_SOURCE_NONE);
 
@@ -142,9 +144,6 @@
   // Overridden from ViewObserver:
   void OnViewBlurred(View* observed_view) override;
 
-  // Overridden from ButtonListener:
-  void ButtonPressed(Button* sender, const ui::Event& event) override;
-
   // Overridden from views::AnimatingLayoutManager::Observer:
   void OnLayoutIsAnimatingChanged(views::AnimatingLayoutManager* source,
                                   bool is_animating) override;
diff --git a/ui/views/controls/scrollbar/base_scroll_bar_button.cc b/ui/views/controls/scrollbar/base_scroll_bar_button.cc
index 1e34ac20..8b81072 100644
--- a/ui/views/controls/scrollbar/base_scroll_bar_button.cc
+++ b/ui/views/controls/scrollbar/base_scroll_bar_button.cc
@@ -4,6 +4,8 @@
 
 #include "ui/views/controls/scrollbar/base_scroll_bar_button.h"
 
+#include <utility>
+
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "ui/display/screen.h"
@@ -12,9 +14,9 @@
 
 namespace views {
 
-BaseScrollBarButton::BaseScrollBarButton(ButtonListener* listener,
+BaseScrollBarButton::BaseScrollBarButton(PressedCallback callback,
                                          const base::TickClock* tick_clock)
-    : Button(listener),
+    : Button(std::move(callback)),
       repeater_(base::BindRepeating(&BaseScrollBarButton::RepeaterNotifyClick,
                                     base::Unretained(this)),
                 tick_clock) {
diff --git a/ui/views/controls/scrollbar/base_scroll_bar_button.h b/ui/views/controls/scrollbar/base_scroll_bar_button.h
index b055ffd8..09635d6 100644
--- a/ui/views/controls/scrollbar/base_scroll_bar_button.h
+++ b/ui/views/controls/scrollbar/base_scroll_bar_button.h
@@ -30,7 +30,7 @@
  public:
   METADATA_HEADER(BaseScrollBarButton);
 
-  explicit BaseScrollBarButton(ButtonListener* listener,
+  explicit BaseScrollBarButton(PressedCallback callback,
                                const base::TickClock* tick_clock = nullptr);
   ~BaseScrollBarButton() override;
 
diff --git a/ui/views/controls/scrollbar/base_scroll_bar_button_unittest.cc b/ui/views/controls/scrollbar/base_scroll_bar_button_unittest.cc
index b49c824f..8672169 100644
--- a/ui/views/controls/scrollbar/base_scroll_bar_button_unittest.cc
+++ b/ui/views/controls/scrollbar/base_scroll_bar_button_unittest.cc
@@ -24,31 +24,28 @@
 using testing::AtLeast;
 using testing::AtMost;
 
-class MockButtonListener : public ButtonListener {
+class MockButtonCallback {
  public:
-  MockButtonListener() = default;
-  MockButtonListener(const MockButtonListener&) = delete;
-  MockButtonListener& operator=(const MockButtonListener&) = delete;
-  ~MockButtonListener() override = default;
+  MockButtonCallback() = default;
+  MockButtonCallback(const MockButtonCallback&) = delete;
+  MockButtonCallback& operator=(const MockButtonCallback&) = delete;
+  ~MockButtonCallback() = default;
 
-  // ButtonListener:
-  MOCK_METHOD(void,
-              ButtonPressed,
-              (Button * sender, const ui::Event& event),
-              (override));
+  MOCK_METHOD(void, ButtonPressed, ());
 };
 
 class BaseScrollBarButtonTest : public testing::Test {
  public:
   BaseScrollBarButtonTest()
       : button_(std::make_unique<BaseScrollBarButton>(
-            &listener_,
+            base::BindRepeating(&MockButtonCallback::ButtonPressed,
+                                base::Unretained(&callback_)),
             task_environment_.GetMockTickClock())) {}
 
   ~BaseScrollBarButtonTest() override = default;
 
  protected:
-  testing::StrictMock<MockButtonListener>& listener() { return listener_; }
+  testing::StrictMock<MockButtonCallback>& callback() { return callback_; }
   Button* button() { return button_.get(); }
 
   void AdvanceTime(base::TimeDelta time_delta) {
@@ -61,7 +58,7 @@
   display::test::TestScreen test_screen_;
   display::test::ScopedScreenOverride screen_override{&test_screen_};
 
-  testing::StrictMock<MockButtonListener> listener_;
+  testing::StrictMock<MockButtonCallback> callback_;
   const std::unique_ptr<Button> button_;
 };
 
@@ -76,18 +73,18 @@
 }
 
 TEST_F(BaseScrollBarButtonTest, CallbackFiresOnMouseDown) {
-  EXPECT_CALL(listener(), ButtonPressed(_, _));
+  EXPECT_CALL(callback(), ButtonPressed());
 
-  // By default the button should notify its listener on mouse release.
+  // By default the button should notify its callback on mouse release.
   button()->OnMousePressed(ui::MouseEvent(
       ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), ui::EventTimeForNow(),
       ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
 }
 
-TEST_F(BaseScrollBarButtonTest, CallbackFilesMultipleTimesMouseHeldDown) {
-  EXPECT_CALL(listener(), ButtonPressed(_, _)).Times(AtLeast(2));
+TEST_F(BaseScrollBarButtonTest, CallbackFiresMultipleTimesMouseHeldDown) {
+  EXPECT_CALL(callback(), ButtonPressed()).Times(AtLeast(2));
 
-  // By default the button should notify its listener on mouse release.
+  // By default the button should notify its callback on mouse release.
   button()->OnMousePressed(ui::MouseEvent(
       ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), ui::EventTimeForNow(),
       ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
@@ -96,16 +93,16 @@
 }
 
 TEST_F(BaseScrollBarButtonTest, CallbackStopsFiringAfterMouseReleased) {
-  EXPECT_CALL(listener(), ButtonPressed(_, _)).Times(AtLeast(2));
+  EXPECT_CALL(callback(), ButtonPressed()).Times(AtLeast(2));
 
-  // By default the button should notify its listener on mouse release.
+  // By default the button should notify its callback on mouse release.
   button()->OnMousePressed(ui::MouseEvent(
       ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), ui::EventTimeForNow(),
       ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
 
   AdvanceTime(RepeatController::GetInitialWaitForTesting() * 10);
 
-  testing::Mock::VerifyAndClearExpectations(&listener());
+  testing::Mock::VerifyAndClearExpectations(&callback());
 
   button()->OnMouseReleased(ui::MouseEvent(
       ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), ui::EventTimeForNow(),
@@ -113,26 +110,26 @@
 
   AdvanceTime(RepeatController::GetInitialWaitForTesting() * 10);
 
-  EXPECT_CALL(listener(), ButtonPressed(_, _)).Times(AtMost(0));
+  EXPECT_CALL(callback(), ButtonPressed()).Times(AtMost(0));
 }
 
 TEST_F(BaseScrollBarButtonTest, CallbackStopsFiringAfterMouseCaptureReleased) {
-  EXPECT_CALL(listener(), ButtonPressed(_, _)).Times(AtLeast(2));
+  EXPECT_CALL(callback(), ButtonPressed()).Times(AtLeast(2));
 
-  // By default the button should notify its listener on mouse release.
+  // By default the button should notify its callback on mouse release.
   button()->OnMousePressed(ui::MouseEvent(
       ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), ui::EventTimeForNow(),
       ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
 
   AdvanceTime(RepeatController::GetInitialWaitForTesting() * 10);
 
-  testing::Mock::VerifyAndClearExpectations(&listener());
+  testing::Mock::VerifyAndClearExpectations(&callback());
 
   button()->OnMouseCaptureLost();
 
   AdvanceTime(RepeatController::GetInitialWaitForTesting() * 10);
 
-  EXPECT_CALL(listener(), ButtonPressed(_, _)).Times(AtMost(0));
+  EXPECT_CALL(callback(), ButtonPressed()).Times(AtMost(0));
 }
 
 }  // namespace views
diff --git a/ui/views/controls/scrollbar/scroll_bar_views.cc b/ui/views/controls/scrollbar/scroll_bar_views.cc
index a56e8729..46301377 100644
--- a/ui/views/controls/scrollbar/scroll_bar_views.cc
+++ b/ui/views/controls/scrollbar/scroll_bar_views.cc
@@ -35,7 +35,7 @@
     kRight,
   };
 
-  ScrollBarButton(ButtonListener* listener, Type type);
+  ScrollBarButton(PressedCallback callback, Type type);
   ~ScrollBarButton() override;
 
   gfx::Size CalculatePreferredSize() const override;
@@ -70,11 +70,8 @@
   ScrollBar* scroll_bar_;
 };
 
-/////////////////////////////////////////////////////////////////////////////
-// ScrollBarButton
-
-ScrollBarButton::ScrollBarButton(ButtonListener* listener, Type type)
-    : BaseScrollBarButton(listener), type_(type) {
+ScrollBarButton::ScrollBarButton(PressedCallback callback, Type type)
+    : BaseScrollBarButton(std::move(callback)), type_(type) {
   EnableCanvasFlippingForRTLUI(true);
   DCHECK_EQ(FocusBehavior::NEVER, GetFocusBehavior());
 }
@@ -142,9 +139,6 @@
   return ui::NativeTheme::kNormal;
 }
 
-/////////////////////////////////////////////////////////////////////////////
-// ScrollBarThumb
-
 ScrollBarThumb::ScrollBarThumb(ScrollBar* scroll_bar)
     : BaseScrollBarThumb(scroll_bar), scroll_bar_(scroll_bar) {}
 
@@ -201,34 +195,24 @@
 
 }  // namespace
 
-////////////////////////////////////////////////////////////////////////////////
-// ScrollBarViews, public:
-
 ScrollBarViews::ScrollBarViews(bool horizontal) : ScrollBar(horizontal) {
   EnableCanvasFlippingForRTLUI(true);
   state_ = ui::NativeTheme::kNormal;
 
   auto* layout = SetLayoutManager(std::make_unique<views::FlexLayout>());
-
-  std::unique_ptr<ScrollBarButton> prev_button, next_button;
-  using Type = ScrollBarButton::Type;
-  if (horizontal) {
-    prev_button = std::make_unique<ScrollBarButton>(this, Type::kLeft);
-    next_button = std::make_unique<ScrollBarButton>(this, Type::kRight);
-
-    part_ = ui::NativeTheme::kScrollbarHorizontalTrack;
-  } else {
+  if (!horizontal)
     layout->SetOrientation(views::LayoutOrientation::kVertical);
 
-    prev_button = std::make_unique<ScrollBarButton>(this, Type::kUp);
-    next_button = std::make_unique<ScrollBarButton>(this, Type::kDown);
+  const auto scroll_func = [](ScrollBarViews* scrollbar, ScrollAmount amount) {
+    scrollbar->ScrollByAmount(amount);
+  };
+  using Type = ScrollBarButton::Type;
+  prev_button_ = AddChildView(std::make_unique<ScrollBarButton>(
+      base::BindRepeating(scroll_func, base::Unretained(this),
+                          ScrollAmount::kPrevLine),
+      horizontal ? Type::kLeft : Type::kUp));
+  prev_button_->set_context_menu_controller(this);
 
-    part_ = ui::NativeTheme::kScrollbarVerticalTrack;
-  }
-  prev_button->set_context_menu_controller(this);
-  next_button->set_context_menu_controller(this);
-
-  prev_button_ = AddChildView(std::move(prev_button));
   SetThumb(new ScrollBarThumb(this));
   // Allow the thumb to take up the whole size of the scrollbar, save for the
   // prev/next buttons.  Layout need only set the thumb cross-axis coordinate;
@@ -237,7 +221,14 @@
       views::kFlexBehaviorKey,
       views::FlexSpecification(views::MinimumFlexSizeRule::kPreferred,
                                views::MaximumFlexSizeRule::kUnbounded));
-  next_button_ = AddChildView(std::move(next_button));
+
+  next_button_ = AddChildView(std::make_unique<ScrollBarButton>(
+      base::BindRepeating(scroll_func, base::Unretained(this),
+                          ScrollBar::ScrollAmount::kNextLine),
+      horizontal ? Type::kRight : Type::kDown));
+  next_button_->set_context_menu_controller(this);
+  part_ = horizontal ? ui::NativeTheme::kScrollbarHorizontalTrack
+                     : ui::NativeTheme::kScrollbarVerticalTrack;
 }
 
 ScrollBarViews::~ScrollBarViews() = default;
@@ -259,9 +250,6 @@
   return std::max(track_size.width(), button_size.width());
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// ScrollBarViews, View overrides:
-
 void ScrollBarViews::OnPaint(gfx::Canvas* canvas) {
   gfx::Rect bounds = GetTrackBounds();
   if (bounds.IsEmpty())
@@ -301,19 +289,6 @@
   return IsHorizontal() ? size.height() : size.width();
 }
 
-//////////////////////////////////////////////////////////////////////////////
-// BaseButton::ButtonListener overrides:
-
-void ScrollBarViews::ButtonPressed(Button* sender, const ui::Event& event) {
-  const bool is_prev = sender == prev_button_;
-  DCHECK(is_prev || sender == next_button_);
-  ScrollByAmount(is_prev ? ScrollBar::ScrollAmount::kPrevLine
-                         : ScrollBar::ScrollAmount::kNextLine);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// ScrollBarViews, private:
-
 gfx::Rect ScrollBarViews::GetTrackBounds() const {
   gfx::Rect bounds = GetLocalBounds();
   gfx::Size size = prev_button_->GetPreferredSize();
diff --git a/ui/views/controls/scrollbar/scroll_bar_views.h b/ui/views/controls/scrollbar/scroll_bar_views.h
index e30f08f8..a08f89b 100644
--- a/ui/views/controls/scrollbar/scroll_bar_views.h
+++ b/ui/views/controls/scrollbar/scroll_bar_views.h
@@ -8,7 +8,6 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "ui/gfx/geometry/point.h"
-#include "ui/native_theme/native_theme.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/scrollbar/scroll_bar.h"
 #include "ui/views/view.h"
@@ -20,7 +19,7 @@
 namespace views {
 
 // Views implementation for the scrollbar.
-class VIEWS_EXPORT ScrollBarViews : public ScrollBar, public ButtonListener {
+class VIEWS_EXPORT ScrollBarViews : public ScrollBar {
  public:
   METADATA_HEADER(ScrollBarViews);
 
@@ -37,9 +36,6 @@
   // ScrollBar overrides:
   int GetThickness() const override;
 
-  // BaseButton::ButtonListener overrides:
-  void ButtonPressed(Button* sender, const ui::Event& event) override;
-
   // Returns the area for the track. This is the area of the scrollbar minus
   // the size of the arrow buttons.
   gfx::Rect GetTrackBounds() const override;
diff --git a/ui/views/examples/combobox_example.cc b/ui/views/examples/combobox_example.cc
index db33ae4b..2ee3231 100644
--- a/ui/views/examples/combobox_example.cc
+++ b/ui/views/examples/combobox_example.cc
@@ -45,30 +45,27 @@
 void ComboboxExample::CreateExampleView(View* container) {
   container->SetLayoutManager(std::make_unique<FillLayout>());
 
-  Combobox* disabled_combobox;
+  auto view =
+      Builder<BoxLayoutView>()
+          .SetOrientation(BoxLayout::Orientation::kVertical)
+          .SetInsideBorderInsets(gfx::Insets(10, 0))
+          .SetBetweenChildSpacing(5)
+          .AddChildren(
+              {Builder<Combobox>()
+                   .CopyAddressTo(&combobox_)
+                   .SetOwnedModel(std::make_unique<ComboboxModelExample>())
+                   .SetSelectedIndex(3)
+                   .SetCallback(base::BindRepeating(
+                       &ComboboxExample::ValueChanged, base::Unretained(this))),
+               Builder<Combobox>()
+                   .SetOwnedModel(std::make_unique<ComboboxModelExample>())
+                   .SetEnabled(false)
+                   .SetSelectedIndex(4)
+                   .SetCallback(
+                       base::BindRepeating(&ComboboxExample::ValueChanged,
+                                           base::Unretained(this)))})
+          .Build();
 
-  auto view = Builder<BoxLayoutView>()
-                  .SetOrientation(BoxLayout::Orientation::kVertical)
-                  .SetInsideBorderInsets(gfx::Insets(10, 0))
-                  .SetBetweenChildSpacing(5)
-                  .AddChildren({Builder<Combobox>().CopyAddressTo(&combobox_),
-                                Builder<Combobox>()
-                                    .CopyAddressTo(&disabled_combobox)
-                                    .SetEnabled(false)})
-                  .Build();
-
-  combobox_->SetOwnedModel(std::make_unique<ComboboxModelExample>());
-  combobox_->SetCallback(base::BindRepeating(&ComboboxExample::ValueChanged,
-                                             base::Unretained(this)));
-  // The index is set outside of the builder because SetOwnedModel will override
-  // set indices.
-  combobox_->SetSelectedIndex(3);
-  disabled_combobox->SetOwnedModel(std::make_unique<ComboboxModelExample>());
-  disabled_combobox->SetCallback(base::BindRepeating(
-      &ComboboxExample::ValueChanged, base::Unretained(this)));
-  // The index is set outside of the builder because SetOwnedModel will override
-  // set indices.
-  disabled_combobox->SetSelectedIndex(4);
   container->AddChildView(std::move(view));
 }
 
diff --git a/ui/views/metadata/property_metadata.h b/ui/views/metadata/property_metadata.h
index c9431211..3dd9043 100644
--- a/ui/views/metadata/property_metadata.h
+++ b/ui/views/metadata/property_metadata.h
@@ -7,6 +7,7 @@
 
 #include <string>
 #include <type_traits>
+#include <utility>
 
 #include "base/macros.h"
 #include "base/strings/string16.h"
@@ -73,7 +74,7 @@
       return;
     if (base::Optional<TValue> result =
             TypeConverter<TValue>::FromString(new_value)) {
-      (static_cast<TClass*>(obj)->*Set)(result.value());
+      (static_cast<TClass*>(obj)->*Set)(std::move(result.value()));
     }
   }
 
diff --git a/ui/views/metadata/type_conversion.h b/ui/views/metadata/type_conversion.h
index 284fd02..9ba57d4 100644
--- a/ui/views/metadata/type_conversion.h
+++ b/ui/views/metadata/type_conversion.h
@@ -7,6 +7,7 @@
 
 #include <stdint.h>
 
+#include <memory>
 #include <utility>
 #include <vector>
 
@@ -159,6 +160,15 @@
   }
 };
 
+template <typename T>
+struct TypeConverter<std::unique_ptr<T>> {
+  static constexpr bool is_serializable = false;
+  static bool IsSerializable() { return is_serializable; }
+  static base::string16 ToString(const std::unique_ptr<T>& source_value);
+  static base::Optional<std::unique_ptr<T>> FromString(
+      const base::string16& source_value);
+};
+
 }  // namespace metadata
 }  // namespace views
 
diff --git a/ui/webui/resources/cr_components/customize_themes/customize_themes.html b/ui/webui/resources/cr_components/customize_themes/customize_themes.html
index 2255ebab..d2fc1a6d 100644
--- a/ui/webui/resources/cr_components/customize_themes/customize_themes.html
+++ b/ui/webui/resources/cr_components/customize_themes/customize_themes.html
@@ -2,7 +2,7 @@
   :host {
     --cr-customize-themes-grid-gap: 20px;
     --cr-customize-themes-icon-size: 72px;
-    display: inline-flex;
+    display: inline-block;
   }
 
   #thirdPartyThemeContainer {
diff --git a/ui/webui/resources/js/cr.gni b/ui/webui/resources/js/cr.gni
new file mode 100644
index 0000000..65808835
--- /dev/null
+++ b/ui/webui/resources/js/cr.gni
@@ -0,0 +1,42 @@
+# 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.
+
+cr_namespace_rewrites = [
+  "cr.getPropertyDescriptor|getPropertyDescriptor",
+  "cr.PropertyKind|PropertyKind",
+  "cr.dispatchPropertyChange|dispatchPropertyChange",
+  "cr.EventTarget|EventTarget",
+  "cr.ui.Command|Command",
+  "cr.ui.contextMenuHandler|contextMenuHandler",
+  "cr.ui.decorate|decorate",
+  "cr.ui.dialogs.BaseDialog|BaseDialog",
+  "cr.ui.dialogs.AlertDialog|AlertDialog",
+  "cr.ui.dialogs.ConfirmDialog|ConfirmDialog",
+  "cr.ui.dialogs.PromptDialog|PromptDialog",
+  "cr.ui.Action|Action",
+  "cr.ui.AnchorType|AnchorType",
+  "cr.ui.ArrayDataModel|ArrayDataModel",
+  "cr.ui.define|crUiDefine",
+  "cr.ui.DeferredAction|DeferredAction",
+  "cr.ui.DragWrapperDelegate|DragWrapperDelegate",
+  "cr.ui.FocusRowDelegate|FocusRowDelegate",
+  "cr.ui.FocusRow|FocusRow",
+  "cr.ui.Grid|Grid",
+  "cr.ui.HideType|HideType",
+  "cr.ui.limitInputWidth|limitInputWidth",
+  "cr.ui.List|List",
+  "cr.ui.ListItem|ListItem",
+  "cr.ui.ListSelectionModel|ListSelectionModel",
+  "cr.ui.ListSelectionController|ListSelectionController",
+  "cr.ui.Menu|Menu",
+  "cr.ui.positionPopupAroundElement|positionPopupAroundElement",
+  "cr.ui.positionPopupAtPoint|positionPopupAtPoint",
+  "cr.ui.swallowDoubleClick|swallowDoubleClick",
+  "cr.ui.Size|Size",
+  "cr.ui.StoreObserver|StoreObserver",
+  "cr.ui.Tab|Tab",
+  "cr.ui.Tree|Tree",
+  "cr.ui.TreeItem|TreeItem",
+  "cr.ui.VirtualFocusRow|VirtualFocusRow",
+]
diff --git a/ui/webui/resources/js/cr/ui/BUILD.gn b/ui/webui/resources/js/cr/ui/BUILD.gn
index 029beb4e..681357d 100644
--- a/ui/webui/resources/js/cr/ui/BUILD.gn
+++ b/ui/webui/resources/js/cr/ui/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//third_party/closure_compiler/compile_js.gni")
 import("../../../tools/js_modulizer.gni")
+import("../../cr.gni")
 
 group("closure_compile") {
   deps = [
@@ -275,43 +276,7 @@
     "tabs.js",
     "tree.js",
   ]
-  namespace_rewrites = [
-    "cr.getPropertyDescriptor|getPropertyDescriptor",
-    "cr.PropertyKind|PropertyKind",
-    "cr.dispatchPropertyChange|dispatchPropertyChange",
-    "cr.EventTarget|EventTarget",
-    "cr.ui.Command|Command",
-    "cr.ui.decorate|decorate",
-    "cr.ui.dialogs.BaseDialog|BaseDialog",
-    "cr.ui.dialogs.AlertDialog|AlertDialog",
-    "cr.ui.dialogs.ConfirmDialog|ConfirmDialog",
-    "cr.ui.dialogs.PromptDialog|PromptDialog",
-    "cr.ui.Action|Action",
-    "cr.ui.AnchorType|AnchorType",
-    "cr.ui.ArrayDataModel|ArrayDataModel",
-    "cr.ui.define|crUiDefine",
-    "cr.ui.DeferredAction|DeferredAction",
-    "cr.ui.DragWrapperDelegate|DragWrapperDelegate",
-    "cr.ui.FocusRowDelegate|FocusRowDelegate",
-    "cr.ui.FocusRow|FocusRow",
-    "cr.ui.Grid|Grid",
-    "cr.ui.HideType|HideType",
-    "cr.ui.limitInputWidth|limitInputWidth",
-    "cr.ui.List|List",
-    "cr.ui.ListItem|ListItem",
-    "cr.ui.ListSelectionModel|ListSelectionModel",
-    "cr.ui.ListSelectionController|ListSelectionController",
-    "cr.ui.Menu|Menu",
-    "cr.ui.positionPopupAroundElement|positionPopupAroundElement",
-    "cr.ui.positionPopupAtPoint|positionPopupAtPoint",
-    "cr.ui.swallowDoubleClick|swallowDoubleClick",
-    "cr.ui.Size|Size",
-    "cr.ui.StoreObserver|StoreObserver",
-    "cr.ui.Tab|Tab",
-    "cr.ui.Tree|Tree",
-    "cr.ui.TreeItem|TreeItem",
-    "cr.ui.VirtualFocusRow|VirtualFocusRow",
-  ]
+  namespace_rewrites = cr_namespace_rewrites
 }
 
 js_type_check("ui_resources_modules") {
diff --git a/weblayer/browser/tab_impl.cc b/weblayer/browser/tab_impl.cc
index a05eb92..7fa1409 100644
--- a/weblayer/browser/tab_impl.cc
+++ b/weblayer/browser/tab_impl.cc
@@ -45,8 +45,8 @@
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/renderer_preferences_util.h"
 #include "content/public/browser/web_contents.h"
+#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
-#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "third_party/blink/public/mojom/window_features/window_features.mojom.h"
 #include "ui/base/window_open_disposition.h"
 #include "weblayer/browser/autofill_client_impl.h"
@@ -1242,8 +1242,7 @@
 }
 
 void TabImpl::UpdateRendererPrefs(bool should_sync_prefs) {
-  blink::mojom::RendererPreferences* prefs =
-      web_contents_->GetMutableRendererPrefs();
+  blink::RendererPreferences* prefs = web_contents_->GetMutableRendererPrefs();
   content::UpdateFontRendererPreferencesFromSystemSettings(prefs);
   prefs->accept_languages = i18n::GetAcceptLangs();
   if (should_sync_prefs)